|
|
@@ -0,0 +1,80 @@
|
|
|
+#pragma once
|
|
|
+
|
|
|
+// GDEH0154Z90, SSD1681 controller, 200x200, black + red (3-colour). Same
|
|
|
+// controller family and command shape as panel_213_z98c.h (SSD1680/1681
|
|
|
+// 3-colour), two 1bpp planes (0x24 black, 0x26 red) sharing one full-frame
|
|
|
+// RAM window.
|
|
|
+//
|
|
|
+// Derived by the descriptor emitter (tools/gxepd2_harness/emit_descriptor.h)
|
|
|
+// observing the real GxEPD2_154_Z90c driver, not hand-transcribed - the first
|
|
|
+// panel brought up that way. The emitter reproduced the 213 Z98c descriptor
|
|
|
+// byte-for-byte as a control, then produced this one; the capture also caught
|
|
|
+// the two real differences from the 213 (verified against the vendor source):
|
|
|
+// - SWRESET (0x12) here waits on the busy pin, where the 213 brackets it
|
|
|
+// with fixed 10ms delays instead;
|
|
|
+// - no 0x21 "display update control" in init (the 213 sets {0x00, 0x80}).
|
|
|
+//
|
|
|
+// plane_invert is NOT emitter-derived (that needs the diag pass); it's set to
|
|
|
+// {false, false} because this driver's writeImage() is byte-identical to the
|
|
|
+// 213's - black via 0x24 as-is, red via 0x26 with _writeData(~data) - and the
|
|
|
+// 213's {false, false} is bench-validated against that exact behaviour. If red
|
|
|
+// and white come out swapped on hardware, flip plane_invert[1] (and see the
|
|
|
+// 213's plane_invert comment for the register/convention coupling).
|
|
|
+//
|
|
|
+// NOT yet bench-tested - no 1.54" panel on hand at import time.
|
|
|
+
|
|
|
+#include "epd_command.h"
|
|
|
+
|
|
|
+namespace esphome::gxepd2 {
|
|
|
+
|
|
|
+inline const uint8_t PANEL_154_Z90C_DRIVER_OUTPUT_CONTROL[] = {0xC7, 0x00, 0x00}; // gate = 0x00C7 = 199 (200 lines)
|
|
|
+inline const uint8_t PANEL_154_Z90C_DATA_ENTRY_MODE[] = {0x03};
|
|
|
+inline const uint8_t PANEL_154_Z90C_BORDER_WAVEFORM[] = {0x05};
|
|
|
+inline const uint8_t PANEL_154_Z90C_TEMP_SENSOR[] = {0x80};
|
|
|
+
|
|
|
+inline const EpdCommand PANEL_154_Z90C_INIT[] = {
|
|
|
+ {0x12, nullptr, 0, /*delay_before_ms=*/0, /*delay_after_ms=*/0, /*wait_busy_after=*/true}, // SWRESET
|
|
|
+ {0x01, PANEL_154_Z90C_DRIVER_OUTPUT_CONTROL, 3},
|
|
|
+ {0x11, PANEL_154_Z90C_DATA_ENTRY_MODE, 1},
|
|
|
+ {0x3C, PANEL_154_Z90C_BORDER_WAVEFORM, 1},
|
|
|
+ {0x18, PANEL_154_Z90C_TEMP_SENSOR, 1},
|
|
|
+};
|
|
|
+
|
|
|
+inline const uint8_t PANEL_154_Z90C_UPDATE_MODE[] = {0xF7};
|
|
|
+
|
|
|
+inline const EpdCommand PANEL_154_Z90C_REFRESH[] = {
|
|
|
+ {0x22, PANEL_154_Z90C_UPDATE_MODE, 1},
|
|
|
+ {0x20, nullptr, 0, /*delay_before_ms=*/0, /*delay_after_ms=*/0, /*wait_busy_after=*/true},
|
|
|
+};
|
|
|
+
|
|
|
+// _setPartialRamArea(0, 0, 200, 200): SSD1681 byte-column X addressing, no
|
|
|
+// Y-reversal (same layout as the 213 Z98c).
|
|
|
+inline const uint8_t PANEL_154_Z90C_WINDOW_X[] = {0x00, 0x18}; // xe/8 = 199/8 = 24
|
|
|
+inline const uint8_t PANEL_154_Z90C_WINDOW_Y[] = {0x00, 0x00, 0xC7, 0x00}; // ye = 199
|
|
|
+inline const uint8_t PANEL_154_Z90C_WINDOW_XC[] = {0x00};
|
|
|
+inline const uint8_t PANEL_154_Z90C_WINDOW_YC[] = {0x00, 0x00};
|
|
|
+
|
|
|
+inline const EpdCommand PANEL_154_Z90C_WINDOW[] = {
|
|
|
+ {0x44, PANEL_154_Z90C_WINDOW_X, 2},
|
|
|
+ {0x45, PANEL_154_Z90C_WINDOW_Y, 4},
|
|
|
+ {0x4E, PANEL_154_Z90C_WINDOW_XC, 1},
|
|
|
+ {0x4F, PANEL_154_Z90C_WINDOW_YC, 2},
|
|
|
+};
|
|
|
+
|
|
|
+inline const EpdPanelDescriptor PANEL_154_Z90C = {
|
|
|
+ .width = 200,
|
|
|
+ .height = 200,
|
|
|
+ .busy_active_level = true, // GxEPD2_EPD(..., /*busy_level=*/HIGH, ...)
|
|
|
+ .busy_timeout_ms = 30000, // vendor full_refresh_time ~14000ms; err long
|
|
|
+ .init_sequence = PANEL_154_Z90C_INIT,
|
|
|
+ .init_sequence_len = sizeof(PANEL_154_Z90C_INIT) / sizeof(PANEL_154_Z90C_INIT[0]),
|
|
|
+ .window_sequence = {PANEL_154_Z90C_WINDOW, nullptr},
|
|
|
+ .window_sequence_len = {sizeof(PANEL_154_Z90C_WINDOW) / sizeof(PANEL_154_Z90C_WINDOW[0]), 0},
|
|
|
+ .plane_count = 2,
|
|
|
+ .plane_write_cmd = {0x24, 0x26},
|
|
|
+ .plane_invert = {false, false}, // see header note (matches 213 Z98c's validated convention)
|
|
|
+ .refresh_sequence = PANEL_154_Z90C_REFRESH,
|
|
|
+ .refresh_sequence_len = sizeof(PANEL_154_Z90C_REFRESH) / sizeof(PANEL_154_Z90C_REFRESH[0]),
|
|
|
+};
|
|
|
+
|
|
|
+} // namespace esphome::gxepd2
|