| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- #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={false, false} is capture-derived, by the plane-invert probe
- // (tools/gxepd2_harness/probe_plane_invert.h): writeScreenBuffer() white/black/
- // red fills put plane0 wire=0xFF for white and plane1 wire=0xFF for red, which
- // agrees with the engine's buffer convention (plane0 bit=white, plane1 bit=red)
- // => no inversion. The same probe reproduces the bench-validated 213 Z98c's
- // {false, false}, so this is at the same confidence as the rest of the
- // descriptor, not an analogy guess.
- //
- // Bench-confirmed 2026-10-18: 3 colors, clean lines, correct color map, ~22s
- // full refresh. First emitter-derived descriptor validated on real hardware -
- // the probe-derived plane_invert={false,false} rendered red/white correctly.
- #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 uint8_t PANEL_154_Z90C_HIBERNATE_0_10[] = {0x01};
- inline const EpdCommand PANEL_154_Z90C_HIBERNATE[] = {
- {0x10, PANEL_154_Z90C_HIBERNATE_0_10, 1},
- };
- 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]),
- .hibernate_sequence = PANEL_154_Z90C_HIBERNATE,
- .hibernate_sequence_len = sizeof(PANEL_154_Z90C_HIBERNATE) / sizeof(PANEL_154_Z90C_HIBERNATE[0]),
- };
- } // namespace esphome::gxepd2
|