Skip to content

[Issue] Excessive E-Ink display refresh time and BUSY pin timeouts #21

Description

@RomanAlexandroff

The Good Display GDEY075Z08 7.5" tri-color E-Ink display requires significantly longer to refresh than expected. While the displayed image is always rendered correctly, the refresh process consistently takes approximately one minute and appears to be dominated by repeated BUSY timeouts inside the GxEPD2 library.

Current behaviour

A typical display update produces the following serial log:

[THE DISPLAY] Drawing the cluster number with...
Busy Timeout!
_PowerOn : 20001049
Busy Timeout!
_Update_Full : 20000025
Busy Timeout!
_PowerOff : 20000025
[THE DISPLAY] ...the default cluster icons
Busy Timeout!
_PowerOn : 20001049
Busy Timeout!
_Update_Part : 20000024
[THE DISPLAY] The drawing process is complete

Each timeout lasts approximately 25 seconds, resulting in a total display update time of over one minute.


Expected behaviour

A full refresh of the 7.5" tri-color display should typically complete in approximately 15–25 seconds (depending on temperature and controller revision), while partial updates should also be considerably faster than the current implementation.


Observations

  • The final image is always rendered correctly.
  • Black and red colours are displayed correctly.
  • No graphical corruption has ever been observed.
  • SPI communication appears to function correctly.
  • Hardware SPI is being used.
  • The display performs the expected refresh animation, although it lasts considerably longer than expected.
  • The GxEPD2 library repeatedly reports BUSY timeouts before continuing with the refresh sequence.

Current hypothesis

The display itself appears to complete its operations successfully; however, the GxEPD2 library never observes the BUSY pin changing to the expected state and therefore waits until the internal timeout expires before continuing.

Possible causes include:

  • BUSY signal not reaching the ESP32 correctly.
  • Incorrect BUSY signal polarity.
  • Incorrect handling of the BUSY pin inside GxEPD2.
  • Hardware issue on the DESPI-C02 SPI adapter.
  • Wiring issue.
  • Controller-specific timing incompatibility.

Hardware

  • MCU: Seeed Studio XIAO ESP32-C3
  • Display: Good Display GDEY075Z08 (800×480, tri-color)
  • SPI adapter: Good Display DESPI-C02
  • BUSY connected to: GPIO6 (XIAO pin D4)

Future investigation

  • Instrument the BUSY pin:

    • Print its logic level before and after refresh.
    • Log its state whenever a timeout occurs.
    • Count BUSY transitions during refresh.
  • Measure the duration of each GxEPD2 operation separately.

  • Verify BUSY polarity using the library implementation.

  • Compare behaviour with the official GxEPD2 examples.

  • Investigate whether GxEPD2 supports operation without the BUSY pin (BUSY = -1) as a diagnostic experiment.

  • Review the implementation of _waitWhileBusy() inside the selected panel driver.

  • Verify the DESPI-C02 BUSY signal electrically once physical access to the hardware is available.


Why this matters

Resolving this issue would improve both user experience and power efficiency. The device currently spends approximately 40 additional seconds waiting for BUSY timeouts during each refresh, increasing the total update time and unnecessarily extending the period during which the ESP32 and display remain active. This also affects future power-saving optimizations, such as entering Light Sleep while the display controller is busy.


Investigation and progress

GxEPD2 timing measurements

The numbers printed by GxEPD2 after operations such as _Update_Full are elapsed times measured in microseconds by the library's _waitWhileBusy() function.

For example:

_Update_Full : 20000025

means that GxEPD2 waited for approximately 20,000,025 us (20.000025 seconds) for the BUSY pin to leave the expected busy state.

This confirmed that the original approximately 20-second delays were caused by the configured BUSY timeout rather than by the display genuinely requiring 20 seconds for every individual operation.

BUSY polarity experiment

The BUSY polarity expected by the original GxEPD2_750c_Z08 driver was temporarily changed from LOW to HIGH.

The resulting measurements were:

_Update_Full : 7 us
_PowerOff : 7 us
_PowerOn : 7 us
_Update_Part : 7 us

The device then performed almost no BUSY waiting. According to the person observing the device, _Update_Full managed to draw some part of the image, while _Update_Part did not manage to draw anything.

This experiment therefore did not solve the problem and strongly suggested that simply reversing the BUSY polarity was not the correct solution. The original LOW polarity was restored.

Incorrect display-controller driver discovered

A major discovery was made while checking the GxEPD2 driver source.

The actual display is: GDEY075Z08 with a UC8179 controller.

The project had been using: GxEPD2_750c_Z08 which is intended for a different panel (GDEW075Z08) and controller (GD7965) combination.

The installed GxEPD2 library was also almost three years old, while the dedicated driver for the actual GDEY075Z08 / UC8179 combination had been added only approximately six months ago.

The current GxEPD2 library contains the dedicated driver: GxEPD2_750c_GDEY075Z08 for the exact GDEY075Z08 / UC8179 display.

Migration to the correct driver

The project was moved to the newer GxEPD2 library and the display driver was changed from: GxEPD2_750c_Z08 to GxEPD2_750c_GDEY075Z08. The existing SPI pin configuration was kept unchanged.

During the first attempt with the new driver, using the full GxEPD2_750c_GDEY075Z08::HEIGHT as the display-buffer height caused the ESP32-C3 to crash with:

Guru Meditation Error: Core 0 panic'ed (Load access fault).

Display-buffer height investigation

The following experiments were performed:

  1. MAX_DISPLAY_BUFFER_SIZE = 96124, full display HEIGHT:

    • Device crashed.
  2. MAX_DISPLAY_BUFFER_SIZE = 65536, full display HEIGHT:

    • Device still crashed.
  3. MAX_DISPLAY_BUFFER_SIZE = 65536, HEIGHT / 4:

    • Device stopped crashing and started working normally.
  4. MAX_DISPLAY_BUFFER_SIZE = 96124, HEIGHT / 4:

    • Device continued working normally.

This demonstrated that the critical factor was the display-buffer height specified as the second template parameter, rather than the value of MAX_DISPLAY_BUFFER_SIZE.

The working configuration is therefore:

GxEPD2_3C<
    GxEPD2_750c_GDEY075Z08,
    GxEPD2_750c_GDEY075Z08::HEIGHT / 4
>

The project's existing:

#define MAX_DISPLAY_BUFFER_SIZE 96124ul

was restored and works correctly with the new / 4 buffer height.

The current GxEPD2 examples also use HEIGHT / 4 for the GDEY075Z08 driver.

Results with the correct driver

After switching to the correct GDEY075Z08 / UC8179 driver and the working / 4 buffer configuration, the measured BUSY timings became:

_Update_Full : 16765001 us
_PowerOff : 40919 us
_PowerOn : 126918 us
_Update_Part : 16769001 us
_PowerOff : 40001 us

Equivalent times:

_Update_Full : 16.765001 s
_PowerOff    : 0.040919 s
_PowerOn     : 0.126918 s
_Update_Part : 16.769001 s
_PowerOff    : 0.040001 s

This is a major improvement over the previous behaviour, where the operations repeatedly hit approximately 20-second BUSY timeouts.

The previous measured sequence was approximately:

20.001064 s
20.001063 s
20.001063 s
20.001064 s
20.001066 s

for a total of approximately 100.005 seconds.

The new sequence is approximately:

16.765001 s
0.040919 s
0.126918 s
16.769001 s
0.040001 s

for a total of approximately 33.742 seconds.

This represents an improvement of approximately 66.26 seconds per complete display-operation sequence, reducing the elapsed time by approximately 66.3% and making the sequence approximately 2.96 times faster.

The new measurements are also fundamentally different from the old ones: they represent real BUSY durations from the correct display/controller driver rather than repeated 20-second timeout values.

Current status

The migration to the correct:

GDEY075Z08 + UC8179

driver appears to have resolved the original BUSY-timeout behaviour.

The display now performs full and partial updates in approximately 16.8 seconds, while power-on and power-off operations take approximately 127 ms and 40 ms respectively.

The remaining question is whether the approximately 16.8-second full and partial update times are the expected behaviour for the GDEY075Z08 / UC8179 combination, or whether further optimization is possible.

In particular, it remains to be investigated whether using a larger display buffer than HEIGHT / 4 could reduce update time further, and whether the current driver performs a single controller refresh or multiple refresh operations when using the paged HEIGHT / 4 buffer.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

advancedOnly for those who is highly familiar with the code basebugSomething isn't working

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions