mirror of
https://github.com/meshtastic/firmware.git
synced 2025-06-12 16:12:07 +00:00
E-Ink: change inaccurate terminology (#3269)
Follows a discussion with @markbirss on discord
This commit is contained in:
parent
f95b90364a
commit
3ad34f8759
@ -18,7 +18,7 @@ SPIClass *hspi = NULL;
|
|||||||
#define TECHO_DISPLAY_MODEL GxEPD2_154_D67
|
#define TECHO_DISPLAY_MODEL GxEPD2_154_D67
|
||||||
#elif defined(RAK4630)
|
#elif defined(RAK4630)
|
||||||
|
|
||||||
// GxEPD2_213_BN - RAK14000 2.13 inch b/w 250x122 - changed from GxEPD2_213_B74 - which was not going to give partial update
|
// GxEPD2_213_BN - RAK14000 2.13 inch b/w 250x122 - changed from GxEPD2_213_B74 - which was not going to give fast refresh
|
||||||
// support
|
// support
|
||||||
#define TECHO_DISPLAY_MODEL GxEPD2_213_BN
|
#define TECHO_DISPLAY_MODEL GxEPD2_213_BN
|
||||||
|
|
||||||
@ -131,8 +131,8 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
|
|||||||
// No need to grab this lock because we are on our own SPI bus
|
// No need to grab this lock because we are on our own SPI bus
|
||||||
// concurrency::LockGuard g(spiLock);
|
// concurrency::LockGuard g(spiLock);
|
||||||
|
|
||||||
#if defined(USE_EINK_DYNAMIC_PARTIAL)
|
#if defined(USE_EINK_DYNAMIC_REFRESH)
|
||||||
// Decide if update is partial or full
|
// Decide between full refresh, fast refresh, or skipping the update
|
||||||
bool continueUpdate = determineRefreshMode();
|
bool continueUpdate = determineRefreshMode();
|
||||||
if (!continueUpdate)
|
if (!continueUpdate)
|
||||||
return false;
|
return false;
|
||||||
@ -165,12 +165,12 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
|
|||||||
adafruitDisplay->nextPage();
|
adafruitDisplay->nextPage();
|
||||||
#elif defined(RAK4630) || defined(MAKERPYTHON)
|
#elif defined(RAK4630) || defined(MAKERPYTHON)
|
||||||
|
|
||||||
// RAK14000 2.13 inch b/w 250x122 actually now does support partial updates
|
// RAK14000 2.13 inch b/w 250x122 actually now does support fast refresh
|
||||||
|
|
||||||
// Full update mode (slow)
|
// Full update mode (slow)
|
||||||
// adafruitDisplay->display(false); // FIXME, use partial update mode
|
// adafruitDisplay->display(false); // FIXME, use fast refresh mode
|
||||||
|
|
||||||
// Only enable for e-Paper with support for partial updates and comment out above adafruitDisplay->display(false);
|
// Only enable for e-Paper with support for fast updates and comment out above adafruitDisplay->display(false);
|
||||||
// 1.54 inch 200x200 - GxEPD2_154_M09
|
// 1.54 inch 200x200 - GxEPD2_154_M09
|
||||||
// 2.13 inch 250x122 - GxEPD2_213_BN
|
// 2.13 inch 250x122 - GxEPD2_213_BN
|
||||||
// 2.9 inch 296x128 - GxEPD2_290_T5D
|
// 2.9 inch 296x128 - GxEPD2_290_T5D
|
||||||
@ -203,7 +203,7 @@ void EInkDisplay::display(void)
|
|||||||
// at least one forceDisplay() keyframe. This prevents flashing when we should the critical
|
// at least one forceDisplay() keyframe. This prevents flashing when we should the critical
|
||||||
// bootscreen (that we want to look nice)
|
// bootscreen (that we want to look nice)
|
||||||
|
|
||||||
#ifdef USE_EINK_DYNAMIC_PARTIAL
|
#ifdef USE_EINK_DYNAMIC_REFRESH
|
||||||
lowPriority();
|
lowPriority();
|
||||||
forceDisplay();
|
forceDisplay();
|
||||||
highPriority();
|
highPriority();
|
||||||
@ -257,9 +257,9 @@ bool EInkDisplay::connect()
|
|||||||
auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY);
|
auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY);
|
||||||
adafruitDisplay = new GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT>(*lowLevel);
|
adafruitDisplay = new GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT>(*lowLevel);
|
||||||
adafruitDisplay->init(115200, true, 10, false, SPI1, SPISettings(4000000, MSBFIRST, SPI_MODE0));
|
adafruitDisplay->init(115200, true, 10, false, SPI1, SPISettings(4000000, MSBFIRST, SPI_MODE0));
|
||||||
// RAK14000 2.13 inch b/w 250x122 does actually now support partial updates
|
// RAK14000 2.13 inch b/w 250x122 does actually now support fast refresh
|
||||||
adafruitDisplay->setRotation(3);
|
adafruitDisplay->setRotation(3);
|
||||||
// Partial update support for 1.54, 2.13 RAK14000 b/w , 2.9 and 4.2
|
// Fast refresh support for 1.54, 2.13 RAK14000 b/w , 2.9 and 4.2
|
||||||
// adafruitDisplay->setRotation(1);
|
// adafruitDisplay->setRotation(1);
|
||||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||||
} else {
|
} else {
|
||||||
@ -347,10 +347,10 @@ bool EInkDisplay::connect()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use a mix of full and partial refreshes, to preserve display health
|
// Use a mix of full refresh, fast refresh, and update skipping, to balance urgency and display health
|
||||||
#if defined(USE_EINK_DYNAMIC_PARTIAL)
|
#if defined(USE_EINK_DYNAMIC_REFRESH)
|
||||||
|
|
||||||
// Suggest that subsequent updates should use partial-refresh
|
// Suggest that subsequent updates should use fast-refresh
|
||||||
void EInkDisplay::highPriority()
|
void EInkDisplay::highPriority()
|
||||||
{
|
{
|
||||||
isHighPriority = true;
|
isHighPriority = true;
|
||||||
@ -368,8 +368,8 @@ void EInkDisplay::demandFullRefresh()
|
|||||||
demandingFull = true;
|
demandingFull = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// configure display for partial-refresh
|
// configure display for fast-refresh
|
||||||
void EInkDisplay::configForPartialRefresh()
|
void EInkDisplay::configForFastRefresh()
|
||||||
{
|
{
|
||||||
// Display-specific code can go here
|
// Display-specific code can go here
|
||||||
#if defined(PRIVATE_HW)
|
#if defined(PRIVATE_HW)
|
||||||
@ -390,7 +390,7 @@ void EInkDisplay::configForFullRefresh()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef EINK_PARTIAL_ERASURE_LIMIT
|
#ifdef EINK_FASTREFRESH_ERASURE_LIMIT
|
||||||
// Count black pixels in an image. Used for "erasure tracking"
|
// Count black pixels in an image. Used for "erasure tracking"
|
||||||
int32_t EInkDisplay::countBlackPixels()
|
int32_t EInkDisplay::countBlackPixels()
|
||||||
{
|
{
|
||||||
@ -422,16 +422,16 @@ bool EInkDisplay::tooManyErasures()
|
|||||||
prevBlackCount = blackCount;
|
prevBlackCount = blackCount;
|
||||||
|
|
||||||
// Log the running total - help devs setup new boards
|
// Log the running total - help devs setup new boards
|
||||||
LOG_DEBUG("Dynamic Partial: erasedSinceFull=%hu, EINK_PARTIAL_ERASURE_LIMIT=%hu\n", erasedSinceFull,
|
LOG_DEBUG("Dynamic Refresh: erasedSinceFull=%hu, EINK_FASTREFRESH_ERASURE_LIMIT=%hu\n", erasedSinceFull,
|
||||||
EINK_PARTIAL_ERASURE_LIMIT);
|
EINK_FASTREFRESH_ERASURE_LIMIT);
|
||||||
|
|
||||||
// Check if too many pixels have been erased
|
// Check if too many pixels have been erased
|
||||||
if (erasedSinceFull > EINK_PARTIAL_ERASURE_LIMIT)
|
if (erasedSinceFull > EINK_FASTREFRESH_ERASURE_LIMIT)
|
||||||
return true; // Too many
|
return true; // Too many
|
||||||
else
|
else
|
||||||
return false; // Still okay
|
return false; // Still okay
|
||||||
}
|
}
|
||||||
#endif // ifdef EINK_PARTIAL_BRIGHTEN_LIMIT_PX
|
#endif // ifdef EINK_FASTREFRESH_ERASURE_LIMIT
|
||||||
|
|
||||||
bool EInkDisplay::newImageMatchesOld()
|
bool EInkDisplay::newImageMatchesOld()
|
||||||
{
|
{
|
||||||
@ -452,7 +452,7 @@ bool EInkDisplay::newImageMatchesOld()
|
|||||||
return hashMatches;
|
return hashMatches;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change between partial and full refresh config, or skip update, balancing urgency and display health.
|
// Choose between, full-refresh, fast refresh, and update skipping, to balance urgency and display health.
|
||||||
bool EInkDisplay::determineRefreshMode()
|
bool EInkDisplay::determineRefreshMode()
|
||||||
{
|
{
|
||||||
uint32_t now = millis();
|
uint32_t now = millis();
|
||||||
@ -466,8 +466,8 @@ bool EInkDisplay::determineRefreshMode()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Abort: if too soon for a new frame (unless demanding full)
|
// Abort: if too soon for a new frame (unless demanding full)
|
||||||
if (!demandingFull && isHighPriority && partialRefreshCount > 0 && sinceLast < highPriorityLimitMsec) {
|
if (!demandingFull && isHighPriority && fastRefreshCount > 0 && sinceLast < highPriorityLimitMsec) {
|
||||||
LOG_DEBUG("Dynamic Partial: update skipped. Exceeded EINK_HIGHPRIORITY_LIMIT_SECONDS\n");
|
LOG_DEBUG("Dynamic Refresh: update skipped. Exceeded EINK_HIGHPRIORITY_LIMIT_SECONDS\n");
|
||||||
missedHighPriorityUpdate = true;
|
missedHighPriorityUpdate = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -479,16 +479,16 @@ bool EInkDisplay::determineRefreshMode()
|
|||||||
if (demandingFull)
|
if (demandingFull)
|
||||||
needsFull = true;
|
needsFull = true;
|
||||||
|
|
||||||
// Check if old image (partial) should be redrawn (as full), for image quality
|
// Check if old image (fast-refresh) should be redrawn (as full), for image quality
|
||||||
if (partialRefreshCount > 0 && !isHighPriority)
|
if (fastRefreshCount > 0 && !isHighPriority)
|
||||||
needsFull = true;
|
needsFull = true;
|
||||||
|
|
||||||
// If too many partials, require a full-refresh (display health)
|
// If too many fast updates, require a full-refresh (display health)
|
||||||
if (partialRefreshCount >= partialRefreshLimit)
|
if (fastRefreshCount >= fastRefreshLimit)
|
||||||
needsFull = true;
|
needsFull = true;
|
||||||
|
|
||||||
#ifdef EINK_PARTIAL_ERASURE_LIMIT
|
#ifdef EINK_FASTREFRESH_ERASURE_LIMIT
|
||||||
// Some displays struggle with erasing black pixels to white, during partial refresh
|
// Some displays struggle with erasing black pixels to white, during fast-refresh
|
||||||
if (tooManyErasures())
|
if (tooManyErasures())
|
||||||
needsFull = true;
|
needsFull = true;
|
||||||
#endif
|
#endif
|
||||||
@ -510,29 +510,29 @@ bool EInkDisplay::determineRefreshMode()
|
|||||||
|
|
||||||
// If options require a full refresh
|
// If options require a full refresh
|
||||||
if (!isHighPriority || needsFull) {
|
if (!isHighPriority || needsFull) {
|
||||||
if (partialRefreshCount > 0)
|
if (fastRefreshCount > 0)
|
||||||
configForFullRefresh();
|
configForFullRefresh();
|
||||||
|
|
||||||
LOG_DEBUG("Dynamic Partial: conditions met for full-refresh\n");
|
LOG_DEBUG("Dynamic Refresh: conditions met for full-refresh\n");
|
||||||
partialRefreshCount = 0;
|
fastRefreshCount = 0;
|
||||||
needsFull = false;
|
needsFull = false;
|
||||||
demandingFull = false;
|
demandingFull = false;
|
||||||
erasedSinceFull = 0; // Reset the count for EINK_PARTIAL_ERASURE_LIMIT - tracks ghosting buildup
|
erasedSinceFull = 0; // Reset the count for EINK_FASTREFRESH_ERASURE_LIMIT - tracks ghosting buildup
|
||||||
}
|
}
|
||||||
|
|
||||||
// If options allow a partial refresh
|
// If options allow a fast-refresh
|
||||||
else {
|
else {
|
||||||
if (partialRefreshCount == 0)
|
if (fastRefreshCount == 0)
|
||||||
configForPartialRefresh();
|
configForFastRefresh();
|
||||||
|
|
||||||
LOG_DEBUG("Dynamic Partial: conditions met for partial-refresh\n");
|
LOG_DEBUG("Dynamic Refresh: conditions met for fast-refresh\n");
|
||||||
partialRefreshCount++;
|
fastRefreshCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
lastUpdateMsec = now; // Mark time for rate limiting
|
lastUpdateMsec = now; // Mark time for rate limiting
|
||||||
return true; // Instruct calling method to continue with update
|
return true; // Instruct calling method to continue with update
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // End USE_EINK_DYNAMIC_PARTIAL
|
#endif // End USE_EINK_DYNAMIC_REFRESH
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -55,23 +55,23 @@ class EInkDisplay : public OLEDDisplay
|
|||||||
// Connect to the display
|
// Connect to the display
|
||||||
virtual bool connect() override;
|
virtual bool connect() override;
|
||||||
|
|
||||||
#if defined(USE_EINK_DYNAMIC_PARTIAL)
|
#if defined(USE_EINK_DYNAMIC_REFRESH)
|
||||||
// Full, partial, or skip: balance urgency with display health
|
// Full, fast, or skip: balance urgency with display health
|
||||||
|
|
||||||
// Use partial refresh if EITHER:
|
// Use fast refresh if EITHER:
|
||||||
// * highPriority() was set
|
// * highPriority() was set
|
||||||
// * a highPriority() update was previously skipped, for rate-limiting - (EINK_HIGHPRIORITY_LIMIT_SECONDS)
|
// * a highPriority() update was previously skipped, for rate-limiting - (EINK_HIGHPRIORITY_LIMIT_SECONDS)
|
||||||
|
|
||||||
// Use full refresh if EITHER:
|
// Use full refresh if EITHER:
|
||||||
// * lowPriority() was set
|
// * lowPriority() was set
|
||||||
// * demandFullRefresh() was called - (single shot)
|
// * demandFullRefresh() was called - (single shot)
|
||||||
// * too many partial updates in a row: protect display - (EINK_PARTIAL_REPEAT_LIMIT)
|
// * too many fast updates in a row: protect display - (EINK_FASTREFRESH_REPEAT_LIMIT)
|
||||||
// * no recent updates, and last update was partial: redraw for image quality (EINK_LOWPRIORITY_LIMIT_SECONDS)
|
// * no recent updates, and last update was fast: redraw for image quality (EINK_LOWPRIORITY_LIMIT_SECONDS)
|
||||||
// * (optional) too many "erasures" since full-refresh (black pixels cleared to white)
|
// * (optional) too many "erasures" since full-refresh (black pixels cleared to white)
|
||||||
|
|
||||||
// Rate limit if:
|
// Rate limit if:
|
||||||
// * lowPriority() - (EINK_LOWPRIORITY_LIMIT_SECONDS)
|
// * lowPriority() - (EINK_LOWPRIORITY_LIMIT_SECONDS)
|
||||||
// * highPriority(), if multiple partials have run back-to-back - (EINK_HIGHPRIORITY_LIMIT_SECONDS)
|
// * highPriority(), if multiple fast updates have run back-to-back - (EINK_HIGHPRIORITY_LIMIT_SECONDS)
|
||||||
|
|
||||||
// Skip update entirely if ALL criteria met:
|
// Skip update entirely if ALL criteria met:
|
||||||
// * new image matches old image
|
// * new image matches old image
|
||||||
@ -83,29 +83,29 @@ class EInkDisplay : public OLEDDisplay
|
|||||||
// ------------------------------------
|
// ------------------------------------
|
||||||
|
|
||||||
// To implement for your E-Ink display:
|
// To implement for your E-Ink display:
|
||||||
// * edit configForPartialRefresh()
|
// * edit configForFastRefresh()
|
||||||
// * edit configForFullRefresh()
|
// * edit configForFullRefresh()
|
||||||
// * add macros to variant.h, and adjust to taste:
|
// * add macros to variant.h, and adjust to taste:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#define USE_EINK_DYNAMIC_PARTIAL
|
#define USE_EINK_DYNAMIC_REFRESH
|
||||||
#define EINK_LOWPRIORITY_LIMIT_SECONDS 30
|
#define EINK_LOWPRIORITY_LIMIT_SECONDS 30
|
||||||
#define EINK_HIGHPRIORITY_LIMIT_SECONDS 1
|
#define EINK_HIGHPRIORITY_LIMIT_SECONDS 1
|
||||||
#define EINK_PARTIAL_REPEAT_LIMIT 5
|
#define EINK_FASTREFRESH_REPEAT_LIMIT 5
|
||||||
#define EINK_PARTIAL_ERASURE_LIMIT 300 // optional
|
#define EINK_FASTREFRESH_ERASURE_LIMIT 300 // optional
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void highPriority(); // Suggest partial refresh
|
void highPriority(); // Suggest fast refresh
|
||||||
void lowPriority(); // Suggest full refresh
|
void lowPriority(); // Suggest full refresh
|
||||||
void demandFullRefresh(); // For next update: explicitly request full refresh
|
void demandFullRefresh(); // For next update: explicitly request full refresh
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void configForPartialRefresh(); // Display specific code to select partial refresh mode
|
void configForFastRefresh(); // Display specific code to select fast refresh mode
|
||||||
void configForFullRefresh(); // Display specific code to return to full refresh mode
|
void configForFullRefresh(); // Display specific code to return to full refresh mode
|
||||||
bool newImageMatchesOld(); // Is the new update actually different to the last image?
|
bool newImageMatchesOld(); // Is the new update actually different to the last image?
|
||||||
bool determineRefreshMode(); // Called immediately before data written to display - choose refresh mode, or abort update
|
bool determineRefreshMode(); // Called immediately before data written to display - choose refresh mode, or abort update
|
||||||
#ifdef EINK_PARTIAL_ERASURE_LIMIT
|
#ifdef EINK_FASTREFRESH_ERASURE_LIMIT
|
||||||
int32_t countBlackPixels(); // Calculate the number of black pixels in the new image
|
int32_t countBlackPixels(); // Calculate the number of black pixels in the new image
|
||||||
bool tooManyErasures(); // Has too much "ghosting" (black pixels erased to white) accumulated since last full-refresh?
|
bool tooManyErasures(); // Has too much "ghosting" (black pixels erased to white) accumulated since last full-refresh?
|
||||||
#endif
|
#endif
|
||||||
@ -114,18 +114,18 @@ class EInkDisplay : public OLEDDisplay
|
|||||||
bool needsFull = false; // Is a full refresh forced? (display health)
|
bool needsFull = false; // Is a full refresh forced? (display health)
|
||||||
bool demandingFull = false; // Was full refresh specifically requested? (splash screens, etc)
|
bool demandingFull = false; // Was full refresh specifically requested? (splash screens, etc)
|
||||||
bool missedHighPriorityUpdate = false; // Was a high priority update skipped for rate-limiting?
|
bool missedHighPriorityUpdate = false; // Was a high priority update skipped for rate-limiting?
|
||||||
uint16_t partialRefreshCount = 0; // How many partials have occurred since last full refresh?
|
uint16_t fastRefreshCount = 0; // How many fast updates have occurred since last full refresh?
|
||||||
uint32_t lastUpdateMsec = 0; // When did the last update occur?
|
uint32_t lastUpdateMsec = 0; // When did the last update occur?
|
||||||
uint32_t prevImageHash = 0; // Used to check if update will change screen image (skippable or not)
|
uint32_t prevImageHash = 0; // Used to check if update will change screen image (skippable or not)
|
||||||
int32_t prevBlackCount = 0; // How many black pixels were in the previous image
|
int32_t prevBlackCount = 0; // How many black pixels were in the previous image
|
||||||
uint32_t erasedSinceFull = 0; // How many black pixels have been set back to white since last full-refresh? (roughly)
|
uint32_t erasedSinceFull = 0; // How many black pixels have been set back to white since last full-refresh? (roughly)
|
||||||
|
|
||||||
// Set in variant.h
|
// Set in variant.h
|
||||||
const uint32_t lowPriorityLimitMsec = (uint32_t)1000 * EINK_LOWPRIORITY_LIMIT_SECONDS; // Max rate for partial refreshes
|
const uint32_t lowPriorityLimitMsec = (uint32_t)1000 * EINK_LOWPRIORITY_LIMIT_SECONDS; // Max rate for fast refreshes
|
||||||
const uint32_t highPriorityLimitMsec = (uint32_t)1000 * EINK_HIGHPRIORITY_LIMIT_SECONDS; // Max rate for full refreshes
|
const uint32_t highPriorityLimitMsec = (uint32_t)1000 * EINK_HIGHPRIORITY_LIMIT_SECONDS; // Max rate for full refreshes
|
||||||
const uint32_t partialRefreshLimit = EINK_PARTIAL_REPEAT_LIMIT; // Max consecutive partials, before full is triggered
|
const uint32_t fastRefreshLimit = EINK_FASTREFRESH_REPEAT_LIMIT; // Max consecutive fast updates, before full is triggered
|
||||||
|
|
||||||
#else // !USE_EINK_DYNAMIC_PARTIAL
|
#else // !USE_EINK_DYNAMIC_REFRESH
|
||||||
// Tolerate calls to these methods anywhere, just to be safe
|
// Tolerate calls to these methods anywhere, just to be safe
|
||||||
void highPriority() {}
|
void highPriority() {}
|
||||||
void lowPriority() {}
|
void lowPriority() {}
|
||||||
|
@ -6,12 +6,12 @@
|
|||||||
|
|
||||||
#define USE_EINK
|
#define USE_EINK
|
||||||
|
|
||||||
// Settings for Dynamic Partial mode
|
// Settings for Dynamic Refresh mode
|
||||||
// Change between partial and full refresh config, or skip update, balancing urgency and display health.
|
// Change between full-refresh, fast-refresh, or update-skipping, to balance urgency and display health.
|
||||||
#define USE_EINK_DYNAMIC_PARTIAL
|
#define USE_EINK_DYNAMIC_REFRESH
|
||||||
#define EINK_LOWPRIORITY_LIMIT_SECONDS 30
|
#define EINK_LOWPRIORITY_LIMIT_SECONDS 30
|
||||||
#define EINK_HIGHPRIORITY_LIMIT_SECONDS 1
|
#define EINK_HIGHPRIORITY_LIMIT_SECONDS 1
|
||||||
#define EINK_PARTIAL_REPEAT_LIMIT 5
|
#define EINK_FASTREFRESH_REPEAT_LIMIT 5
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* eink display pins
|
* eink display pins
|
||||||
|
Loading…
Reference in New Issue
Block a user