Skip to content

Commit

Permalink
Merge pull request #6 from todd-herbert/async
Browse files Browse the repository at this point in the history
Async Full Refresh
  • Loading branch information
thebentern authored Mar 11, 2024
2 parents 378318c + 8aa46f2 commit 55f6189
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 13 deletions.
19 changes: 19 additions & 0 deletions src/GxEPD2_BW.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
#ifndef _GxEPD2_BW_H_
#define _GxEPD2_BW_H_

// This version of meshtastic/GxEPD2 has been modified (defiled) to allow nextPage() to run full refreshes asynchronously
// This macro ensures that the relevant modifications to meshtastic/firmware will only run with a correctly modified version of GxEPD2
// Note: this async behavior is unrelated to the callback system implemented in newer versions of ZinggJM/GxEPD2
#define HAS_EINK_ASYNCFULL

// uncomment next line to use class GFX of library GFX_Root instead of Adafruit_GFX
//#include <GFX.h>

Expand Down Expand Up @@ -239,6 +244,16 @@ class GxEPD2_BW : public GxEPD2_GFX_BASE_CLASS
_second_phase = false;
}

// Transplanted from nextPage(), non-paged, full refresh
// This is the code which runs after the refresh() call
// Method is called by meshtastic/firmware, once polling GxEPD2_BW::isBusy() reports that the physical refresh is complete
void endAsyncFull() {
if (epd2.hasFastPartialUpdate) {
epd2.writeImageAgain(_buffer, 0, 0, WIDTH, HEIGHT);
}
epd2.powerOff();
}

bool nextPage()
{
if (1 == _pages)
Expand All @@ -258,12 +273,16 @@ class GxEPD2_BW : public GxEPD2_GFX_BASE_CLASS
{
epd2.writeImageForFullRefresh(_buffer, 0, 0, WIDTH, HEIGHT);
epd2.refresh(false);
#if defined(USE_EINK_DYNAMICDISPLAY) // This macro defined in meshtastic/firmware
// -- meshtastic: moved to endAsyncFull() --
#else
if (epd2.hasFastPartialUpdate)
{
epd2.writeImageAgain(_buffer, 0, 0, WIDTH, HEIGHT);
//epd2.refresh(true); // not needed
}
epd2.powerOff();
#endif
}
return false;
}
Expand Down
17 changes: 17 additions & 0 deletions src/GxEPD2_EPD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,12 @@ void GxEPD2_EPD::_reset()

void GxEPD2_EPD::_waitWhileBusy(const char* comment, uint16_t busy_time)
{
// For full refreshes, meshtastic/firmare will poll GxEPD2_EPD::isBusy() instead of waiting here (for EInkDynamicDisplay only)
#if defined(USE_EINK_DYNAMICDISPLAY)
if (_isUpdatingFull(comment))
return;
#endif

if (_busy >= 0)
{
delay(1); // add some margin to become active
Expand Down Expand Up @@ -241,3 +247,14 @@ void GxEPD2_EPD::_endTransfer()
if (_cs >= 0) digitalWrite(_cs, HIGH);
_spi.endTransaction();
}

// Polled by meshtastic/firmware, during async full-refresh
bool GxEPD2_EPD::isBusy() {
return (digitalRead(_busy) == _busy_level);
}

// Used to skip _waitWhileBusy(), for meshtastic async
bool GxEPD2_EPD::_isUpdatingFull(const char* comment) {
// True if comment matches
return ( strcmp(comment, "_Update_Full") == 0 );
}
2 changes: 2 additions & 0 deletions src/GxEPD2_EPD.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ class GxEPD2_EPD
{
return (a > b ? a : b);
};
bool isBusy(); // Used in meshtastic/firmware, to poll after nextPage(), for async full refresh
protected:
void _reset();
void _waitWhileBusy(const char* comment = 0, uint16_t busy_time = 5000);
Expand All @@ -104,6 +105,7 @@ class GxEPD2_EPD
void _startTransfer();
void _transfer(uint8_t value);
void _endTransfer();
bool _isUpdatingFull(const char* comment); // Meshtastic: Determine if _waitWhileBusy() should be skipped (for async), by comparing the comment string..
protected:
int8_t _cs, _dc, _rst, _busy, _busy_level;
uint32_t _busy_timeout;
Expand Down
14 changes: 2 additions & 12 deletions src/epd/GxEPD2_213_FC1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ void GxEPD2_213_FC1::clearScreen(uint8_t value)
_writeScreenBuffer(0x13, value); // Clear "NEW" (red) mem
_writeScreenBuffer(0x10, value); // Clear "OLD" (black) mem
refresh(false); // Full refresh
_PowerOff();
_initial_write = false;
_initial_refresh = false;
}
Expand Down Expand Up @@ -158,19 +159,10 @@ void GxEPD2_213_FC1::powerOff()
_PowerOff();
}

// Put the display into an extra-low power state. Hard reset required to wake.
// Caution: will wipe display memory - problematic for fast-refresh, so not used by meshtastic
// No hibernate for this display, only power off. Preserves image memory for fast refresh.
void GxEPD2_213_FC1::hibernate()
{
_PowerOff();
if (_rst >= 0)
{
_writeCommand(0x07); // deep sleep mode
_writeData(0xA5); // enter deep sleep
_hibernating = true;
_configured_for_full = false;
_configured_for_fast = false;
}
}

void GxEPD2_213_FC1::_PowerOn()
Expand Down Expand Up @@ -280,7 +272,6 @@ void GxEPD2_213_FC1::_Update_Full()
_PowerOn();
_writeCommand(0x12);
_waitWhileBusy("_Update_Full", full_refresh_time);
_PowerOff();
}

void GxEPD2_213_FC1::_Update_Part()
Expand All @@ -289,7 +280,6 @@ void GxEPD2_213_FC1::_Update_Part()
_PowerOn();
_writeCommand(0x12);
_waitWhileBusy("_Update_Part", partial_refresh_time);
_PowerOff();
}

// Fast refresh waveform is unofficial (experimental?)
Expand Down
2 changes: 1 addition & 1 deletion src/epd/GxEPD2_213_FC1.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class GxEPD2_213_FC1 : public GxEPD2_EPD
void refresh(bool partial_update_mode = false); // screen refresh from controller memory to full screen
void refresh(int16_t x, int16_t y, int16_t w, int16_t h); // screen refresh from controller memory, fast-refresh
void powerOff(); // turns off generation of panel driving voltages, avoids screen fading over time
void hibernate(); // turns powerOff() and sets controller to deep sleep for minimum power use, ONLY if wakeable by RST (rst >= 0)
void hibernate(); // For this display, no deep sleep, only power off. Preserves image memory for fast refresh

// Unimplemented for meshtastic
public:
Expand Down

0 comments on commit 55f6189

Please sign in to comment.