فهرست منبع

Bracket the refresh trigger with explicit power-on/off, matching the proven driver

Fourth hardware run (after fixing the red-plane bit convention): busy
cleared normally, but the panel came out solid black - meaning the black
plane is also ending up fully inked, not just masked by the earlier red
bug. Busy engaging and clearing normally across every run points at an
incomplete/malformed waveform, not a hang or purely a data bug.

GxEPD2's vendor source fires a single combined trigger (0x22/0xF7 + 0x20)
and assumes it handles power internally. The known-working epaper_spi
driver for this exact panel instead runs POWER_ON (0x22/0xF8 + 0x20),
resets the RAM counters again, THEN the refresh trigger (0x22/0xF7 + 0x20),
THEN POWER_OFF (0x22/0x83 + 0x20) - each with its own busy-wait. Mirroring
that sequence, since GxEPD2's shortcut is what's unproven here.
ZiB 1 ماه پیش
والد
کامیت
cb280b6b8d
1فایلهای تغییر یافته به همراه24 افزوده شده و 3 حذف شده
  1. 24 3
      components/gxepd2/panel_213_z98c.h

+ 24 - 3
components/gxepd2/panel_213_z98c.h

@@ -40,14 +40,35 @@ inline const EpdCommand PANEL_213_Z98C_INIT[] = {
     {0x21, PANEL_213_Z98C_DISPLAY_UPDATE_CONTROL, 2},
 };
 
-// GxEPD2_213_Z98c::_Update_Full()/_Update_Part() are identical - both just
-// write 0xF7 to the display-update-control register (0x22) and trigger
-// (0x20). This panel has no separate fast-partial mode.
+// GxEPD2_213_Z98c::_Update_Full()/_Update_Part() fire a single combined
+// trigger (0x22/0xF7 + 0x20) and assume it handles power internally. That
+// matched neither hardware symptom we saw (solid black, then solid red) -
+// busy genuinely engaged and cleared each time, consistent with a waveform
+// that ran without properly stabilized power, not a hang. The known-working
+// epaper_spi driver for this exact panel instead brackets the refresh with
+// explicit power-on/off triggers, each with its own busy-wait, and resets
+// the RAM counters again immediately before the refresh trigger itself:
+//   POWER_ON (0x22/0xF8 + 0x20, wait busy)
+//   reset RAM counters (0x4E/0x4F back to 0,0)
+//   REFRESH  (0x22/0xF7 + 0x20, wait busy)
+//   POWER_OFF (0x22/0x83 + 0x20, wait busy)
+// Mirroring that sequence here since GxEPD2's shortcut is what's unproven
+// on this specific panel/FPC revision.
+inline const uint8_t PANEL_213_Z98C_POWER_ON_MODE[] = {0xF8};
 inline const uint8_t PANEL_213_Z98C_UPDATE_MODE[] = {0xF7};
+inline const uint8_t PANEL_213_Z98C_POWER_OFF_MODE[] = {0x83};
+inline const uint8_t PANEL_213_Z98C_RESET_X_COUNTER[] = {0x00};
+inline const uint8_t PANEL_213_Z98C_RESET_Y_COUNTER[] = {0x00, 0x00};
 
 inline const EpdCommand PANEL_213_Z98C_REFRESH[] = {
+    {0x22, PANEL_213_Z98C_POWER_ON_MODE, 1},
+    {0x20, nullptr, 0, /*delay_before_ms=*/0, /*delay_after_ms=*/0, /*wait_busy_after=*/true},
+    {0x4E, PANEL_213_Z98C_RESET_X_COUNTER, 1},
+    {0x4F, PANEL_213_Z98C_RESET_Y_COUNTER, 2},
     {0x22, PANEL_213_Z98C_UPDATE_MODE, 1},
     {0x20, nullptr, 0, /*delay_before_ms=*/0, /*delay_after_ms=*/0, /*wait_busy_after=*/true},
+    {0x22, PANEL_213_Z98C_POWER_OFF_MODE, 1},
+    {0x20, nullptr, 0, /*delay_before_ms=*/0, /*delay_after_ms=*/0, /*wait_busy_after=*/true},
 };
 
 // full_refresh_time/partial_refresh_time from the vendor header are both