|
@@ -1,127 +0,0 @@
|
|
|
-#pragma once
|
|
|
|
|
-
|
|
|
|
|
-// Hand-derived from third_party/GxEPD2/src/epd4c/GxEPD2_579c_GDEY0579F51.{h,cpp}
|
|
|
|
|
-// (GDEY0579F51, HX8717 controller, 792x272, same JD79667-family 2bpp/4-color
|
|
|
|
|
-// packing as GDEY029F51 - see panel_290c_gdey029f51.h). This is the actual
|
|
|
|
|
-// dual-CS-like split panel from the original bench list: NOT two physical
|
|
|
|
|
-// CS pins, but two logical regions ("master"/"slave", left/right halves)
|
|
|
|
|
-// selected over one bus via an 0xA2 command, each with its own window-set
|
|
|
|
|
-// and its own 0x10 plane-write burst.
|
|
|
|
|
-//
|
|
|
|
|
-// Deliberate scope cut (2026-09-19, per user): CycleEngine's state machine
|
|
|
|
|
-// only knows one window-set + one plane-write per update cycle, and
|
|
|
|
|
-// extending it to loop over two regions is real work, not just descriptor
|
|
|
|
|
-// data - so this descriptor addresses the "master" half ONLY, as if it
|
|
|
|
|
-// were a self-contained 396x272 single-region panel, to validate the 2bpp
|
|
|
|
|
-// packing and this controller family's init/refresh shape before building
|
|
|
|
|
-// the master+slave loop.
|
|
|
|
|
-//
|
|
|
|
|
-// First hardware run (2026-09-19) showed real content, correctly decoded,
|
|
|
|
|
-// but compressed/duplicated within roughly half the driven region, plus
|
|
|
|
|
-// noise/black bands on the untouched half - not yet fully explained. One
|
|
|
|
|
-// finding so far: don't assume "master" = the physically-left/near-
|
|
|
|
|
-// connector half. GxEPD2_579_GDEY0579T93.cpp (SSD1683, same 792x272
|
|
|
|
|
-// panel family, comments explicit) maps "near connector" -> SLAVE and
|
|
|
|
|
-// "opposite to connector" -> MASTER - the reverse of what might be
|
|
|
|
|
-// guessed. GDEY0579F51's own driver has no such comment, so which
|
|
|
|
|
-// physical side "master" actually addresses here is unverified, not
|
|
|
|
|
-// assumed-correct. A slave-only variant of this same descriptor (swap
|
|
|
|
|
-// every SELECT_MASTER for SELECT_MASTER->0x02) would empirically test
|
|
|
|
|
-// whether content moves to the other half - not yet done.
|
|
|
|
|
-//
|
|
|
|
|
-// The refresh sequence originally used select=Both (0x00) before the
|
|
|
|
|
-// 0x12 trigger, matching the vendor's own refresh(bool)'s
|
|
|
|
|
-// _setPartialRamAreaBoth() call - but 0x12 appears to fire a real
|
|
|
|
|
-// electrical refresh across the WHOLE physical panel regardless of which
|
|
|
|
|
-// side's RAM was ever written, which explains the noise/black bands as
|
|
|
|
|
-// slave's never-initialized RAM being "developed" onto glass. Changed to
|
|
|
|
|
-// select=Master only, since we only ever want to touch the side we wrote.
|
|
|
|
|
-// Does not yet explain the duplication/compression artifact.
|
|
|
|
|
-//
|
|
|
|
|
-// _InitDisplay()'s reset pulse is gated the same way GDEY029F51's is
|
|
|
|
|
-// (`_hibernating || _initial_write`) - this engine always does a real
|
|
|
|
|
-// hardware reset every cycle regardless, a superset of the vendor
|
|
|
|
|
-// driver's own first-cycle behavior, so no special-casing needed.
|
|
|
|
|
-
|
|
|
|
|
-#include "epd_command.h"
|
|
|
|
|
-
|
|
|
|
|
-namespace esphome::gxepd2 {
|
|
|
|
|
-
|
|
|
|
|
-inline const uint8_t PANEL_579C_GDEY0579F51_MO_SELECT_MASTER[] = {0x01};
|
|
|
|
|
-inline const uint8_t PANEL_579C_GDEY0579F51_MO_SELECT_BOTH[] = {0x00};
|
|
|
|
|
-// 0x03, not 0x07 - see panel_579c_gdey0579f51.h's header comment: this
|
|
|
|
|
-// value's SHL bit was backwards relative to Waveshare's own reference
|
|
|
|
|
-// driver for this panel (2026-09-19).
|
|
|
|
|
-inline const uint8_t PANEL_579C_GDEY0579F51_MO_PSR_MASTER[] = {0x03, 0x29};
|
|
|
|
|
-inline const uint8_t PANEL_579C_GDEY0579F51_MO_BTST[] = {0x32, 0x32, 0x32, 0x32};
|
|
|
|
|
-inline const uint8_t PANEL_579C_GDEY0579F51_MO_TRES[] = {0x01, 0x8C, 0x01, 0x10}; // 396x272
|
|
|
|
|
-inline const uint8_t PANEL_579C_GDEY0579F51_MO_CDI_INIT[] = {0x97};
|
|
|
|
|
-inline const uint8_t PANEL_579C_GDEY0579F51_MO_E9[] = {0x01};
|
|
|
|
|
-inline const uint8_t PANEL_579C_GDEY0579F51_MO_E0[] = {0x01};
|
|
|
|
|
-
|
|
|
|
|
-inline const EpdCommand PANEL_579C_GDEY0579F51_MO_INIT[] = {
|
|
|
|
|
- {0xA2, PANEL_579C_GDEY0579F51_MO_SELECT_MASTER, 1},
|
|
|
|
|
- {0x00, PANEL_579C_GDEY0579F51_MO_PSR_MASTER, 2},
|
|
|
|
|
- {0xA2, PANEL_579C_GDEY0579F51_MO_SELECT_BOTH, 1},
|
|
|
|
|
- {0x06, PANEL_579C_GDEY0579F51_MO_BTST, 4},
|
|
|
|
|
- {0x61, PANEL_579C_GDEY0579F51_MO_TRES, 4},
|
|
|
|
|
- {0x50, PANEL_579C_GDEY0579F51_MO_CDI_INIT, 1},
|
|
|
|
|
- {0xE9, PANEL_579C_GDEY0579F51_MO_E9, 1},
|
|
|
|
|
- {0xE0, PANEL_579C_GDEY0579F51_MO_E0, 1},
|
|
|
|
|
- {0xA2, PANEL_579C_GDEY0579F51_MO_SELECT_MASTER, 1},
|
|
|
|
|
- {0x04, nullptr, 0, /*delay_before_ms=*/0, /*delay_after_ms=*/0, /*wait_busy_after=*/true}, // power on
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-// _setPartialRamAreaMaster(0, 0, 396, 272), default partial_mode=true.
|
|
|
|
|
-inline const uint8_t PANEL_579C_GDEY0579F51_MO_WINDOW[] = {
|
|
|
|
|
- 0x00, 0x00, // x/256, x%256 = 0
|
|
|
|
|
- 0x01, 0x8B, // xe/256, xe%256 = 395
|
|
|
|
|
- 0x00, 0x00, // y/256, y%256 = 0
|
|
|
|
|
- 0x01, 0x0F, // ye/256, ye%256 = 271
|
|
|
|
|
- 0x01,
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-inline const EpdCommand PANEL_579C_GDEY0579F51_MO_WINDOW_SEQ[] = {
|
|
|
|
|
- {0xA2, PANEL_579C_GDEY0579F51_MO_SELECT_MASTER, 1},
|
|
|
|
|
- {0x83, PANEL_579C_GDEY0579F51_MO_WINDOW, 9},
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-// refresh(false): vendor's own refresh(bool) uses _setPartialRamAreaBoth()
|
|
|
|
|
-// here, but see file header - deliberately using select=Master instead so
|
|
|
|
|
-// the 0x12 trigger's real electrical refresh never touches slave's
|
|
|
|
|
-// never-written RAM (that Both selection is what produced the noise/black
|
|
|
|
|
-// bands on the untouched half in the first hardware run).
|
|
|
|
|
-inline const uint8_t PANEL_579C_GDEY0579F51_MO_CDI_REFRESH[] = {0x37};
|
|
|
|
|
-inline const uint8_t PANEL_579C_GDEY0579F51_MO_REFRESH_TRIGGER[] = {0x00};
|
|
|
|
|
-
|
|
|
|
|
-inline const EpdCommand PANEL_579C_GDEY0579F51_MO_REFRESH[] = {
|
|
|
|
|
- {0xA2, PANEL_579C_GDEY0579F51_MO_SELECT_MASTER, 1},
|
|
|
|
|
- {0x83, PANEL_579C_GDEY0579F51_MO_WINDOW, 9},
|
|
|
|
|
- {0x50, PANEL_579C_GDEY0579F51_MO_CDI_REFRESH, 1},
|
|
|
|
|
- {0x12, PANEL_579C_GDEY0579F51_MO_REFRESH_TRIGGER, 1, /*delay_before_ms=*/0, /*delay_after_ms=*/0,
|
|
|
|
|
- /*wait_busy_after=*/true},
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-inline const EpdPanelDescriptor PANEL_579C_GDEY0579F51_MASTER_ONLY = {
|
|
|
|
|
- .width = 396, // WIDTH/2 of the real 792-wide panel - master half only
|
|
|
|
|
- .height = 272,
|
|
|
|
|
- .busy_active_level = false, // GxEPD2_EPD(..., /*busy_level=*/LOW, ...)
|
|
|
|
|
- .busy_timeout_ms = 25000, // full_refresh_time is 21000ms
|
|
|
|
|
- .init_sequence = PANEL_579C_GDEY0579F51_MO_INIT,
|
|
|
|
|
- .init_sequence_len = sizeof(PANEL_579C_GDEY0579F51_MO_INIT) / sizeof(PANEL_579C_GDEY0579F51_MO_INIT[0]),
|
|
|
|
|
- .window_sequence = {PANEL_579C_GDEY0579F51_MO_WINDOW_SEQ, nullptr},
|
|
|
|
|
- .window_sequence_len = {sizeof(PANEL_579C_GDEY0579F51_MO_WINDOW_SEQ) / sizeof(PANEL_579C_GDEY0579F51_MO_WINDOW_SEQ[0]),
|
|
|
|
|
- 0},
|
|
|
|
|
- .plane_count = 1,
|
|
|
|
|
- .plane_write_cmd = {0x10, 0x00},
|
|
|
|
|
- .plane_invert = {false, false},
|
|
|
|
|
- .line_order = LineOrder::PAIRED_EDGES,
|
|
|
|
|
- .bits_per_pixel = 2,
|
|
|
|
|
- .palette = GXEPD2_PALETTE_4C,
|
|
|
|
|
- .palette_len = GXEPD2_PALETTE_4C_LEN,
|
|
|
|
|
- .blank_code = 0x01,
|
|
|
|
|
- .refresh_sequence = PANEL_579C_GDEY0579F51_MO_REFRESH,
|
|
|
|
|
- .refresh_sequence_len = sizeof(PANEL_579C_GDEY0579F51_MO_REFRESH) / sizeof(PANEL_579C_GDEY0579F51_MO_REFRESH[0]),
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-} // namespace esphome::gxepd2
|
|
|