Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions libs/display/EInkDisplay/include/EInkDisplay.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,17 @@ class EInkDisplay {
// Power management
void deepSleep();

// Optional hooks fired around long BUSY waits. A refresh takes ~0.3-2 s during
// which the CPU only polls the BUSY pin; these let host firmware save power in
// that window (e.g. reduce the CPU clock) without the SDK knowing the policy.
// The begin hook fires once a wait exceeds BUSY_WAIT_HOOK_THRESHOLD_MS (so
// short command waits never pay for it); the matching end hook fires when the
// wait completes. Plain function pointers; both default to disabled.
void setBusyWaitHooks(void (*beginHook)(), void (*endHook)()) {
_busyWaitBeginHook = beginHook;
_busyWaitEndHook = endHook;
}

// Access to frame buffer
uint8_t* getFrameBuffer() const {
return frameBuffer;
Expand All @@ -133,6 +144,11 @@ class EInkDisplay {
// Internal geometry setter used by setDisplayX3().
void setDisplayDimensions(uint16_t width, uint16_t height);

// Busy-wait hooks (see setBusyWaitHooks)
static constexpr unsigned long BUSY_WAIT_HOOK_THRESHOLD_MS = 20;
void (*_busyWaitBeginHook)() = nullptr;
void (*_busyWaitEndHook)() = nullptr;

// Pin configuration
int8_t _sclk, _mosi, _cs, _dc, _rst, _busy;

Expand Down
23 changes: 19 additions & 4 deletions libs/display/EInkDisplay/src/EInkDisplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -579,10 +579,19 @@ void EInkDisplay::waitForRefresh(const char *comment) {

void EInkDisplay::pollBusy(const char *comment, const char *completeWord) {
unsigned long start = millis();
// The begin hook fires lazily, only once the wait has proven long (see
// setBusyWaitHooks); hookFired guarantees the end hook is balanced with it.
bool hookFired = false;
bool x3SawLow = false;
if (!_x3Mode) {
// X4: BUSY held HIGH while busy, drops LOW when done.
while (digitalRead(_busy) == HIGH) {
delay(1);
if (!hookFired && _busyWaitBeginHook != nullptr &&
millis() - start > BUSY_WAIT_HOOK_THRESHOLD_MS) {
hookFired = true;
_busyWaitBeginHook();
}
if (millis() - start > 30000)
break;
}
Expand All @@ -595,23 +604,29 @@ void EInkDisplay::pollBusy(const char *comment, const char *completeWord) {
// LOW -> HIGH edge. If we never observe the LOW phase the operation
// either completed faster than we could see or was a no-op, and we
// skip the completion log line.
bool sawLow = false;
while (digitalRead(_busy) == HIGH) {
delay(1);
if (millis() - start > 1000)
break;
}
if (digitalRead(_busy) == LOW) {
sawLow = true;
x3SawLow = true;
while (digitalRead(_busy) == LOW) {
delay(1);
if (!hookFired && _busyWaitBeginHook != nullptr &&
millis() - start > BUSY_WAIT_HOOK_THRESHOLD_MS) {
hookFired = true;
_busyWaitBeginHook();
}
if (millis() - start > 30000)
break;
}
}
if (!sawLow)
return;
}
if (hookFired && _busyWaitEndHook != nullptr)
_busyWaitEndHook();
if (_x3Mode && !x3SawLow)
return;
if (comment && Serial)
Serial.printf("[%lu] %s: %s (%lu ms)\n", millis(), completeWord, comment,
millis() - start);
Expand Down