| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- #pragma once
- // Hand-derived from third_party/GxEPD2/src/gdeq/GxEPD2_426_GDEQ0426T82.{h,cpp}
- // (GDEQ0426T82, SSD1677 controller, 800x480, monochrome). First panel with
- // a genuine current/previous differential RAM (0x24/0x26) - the vendor
- // driver's writeImageAgain()/writeImageForFullRefresh() keep both buffers
- // in sync purely so a *future* fast-partial update diffs correctly; this
- // engine never does partial refresh (see gxepd2_extraction_next_steps in
- // project memory for that scope decision), so only the current-buffer
- // command (0x24) is ever written here - 0x26 is dropped entirely, same as
- // GxEPD2's own _initial_write priming pass (a dummy full-buffer clear
- // before the real content write) is dropped, since this engine always
- // writes real content directly and re-initializes fully every cycle. The
- // 0x26 write is still recorded below, in plane_write_cmd_for_full_refresh,
- // so a future partial-refresh engine has it without a second capture pass.
- //
- // Also the first panel whose RAM-window-set (_setPartialRamArea) layout
- // differs from GxEPD2_213_Z98c's: SSD1677 addresses 0x44/0x45 in raw
- // pixels (not byte columns), reverses Y, and re-issues the entry-mode
- // command (0x11) on every window set - see window_sequence below.
- #include "epd_command.h"
- namespace esphome::gxepd2 {
- inline const uint8_t PANEL_426_GDEQ0426T82_TEMP_SENSOR[] = {0x80};
- inline const uint8_t PANEL_426_GDEQ0426T82_ANALOG_BLOCK[] = {0xAE, 0xC7, 0xC3, 0xC0, 0x80};
- // Driver output control: (HEIGHT-1) low/high byte, then SM=0x02 (interlaced).
- inline const uint8_t PANEL_426_GDEQ0426T82_DRIVER_OUTPUT_CONTROL[] = {0xDF, 0x01, 0x02};
- inline const uint8_t PANEL_426_GDEQ0426T82_BORDER_WAVEFORM[] = {0x01};
- inline const EpdCommand PANEL_426_GDEQ0426T82_INIT[] = {
- {0x12, nullptr, 0, /*delay_before_ms=*/10, /*delay_after_ms=*/10, /*wait_busy_after=*/false}, // SWRESET
- {0x18, PANEL_426_GDEQ0426T82_TEMP_SENSOR, 1},
- {0x0C, PANEL_426_GDEQ0426T82_ANALOG_BLOCK, 5},
- {0x01, PANEL_426_GDEQ0426T82_DRIVER_OUTPUT_CONTROL, 3},
- {0x3C, PANEL_426_GDEQ0426T82_BORDER_WAVEFORM, 1},
- };
- // _setPartialRamArea(0, 0, 800, 480). y is stored as HEIGHT-y-h, which is
- // 0 for a full-height window regardless of the reversal - only matters for
- // a real partial window, which this engine never does.
- inline const uint8_t PANEL_426_GDEQ0426T82_ENTRY_MODE[] = {0x01};
- inline const uint8_t PANEL_426_GDEQ0426T82_WINDOW_X[] = {0x00, 0x00, 0x1F, 0x03}; // xs=0, xe=799
- inline const uint8_t PANEL_426_GDEQ0426T82_WINDOW_Y[] = {0xDF, 0x01, 0x00, 0x00}; // ye=479, ys=0
- inline const uint8_t PANEL_426_GDEQ0426T82_WINDOW_XC[] = {0x00, 0x00};
- inline const uint8_t PANEL_426_GDEQ0426T82_WINDOW_YC[] = {0xDF, 0x01};
- inline const EpdCommand PANEL_426_GDEQ0426T82_WINDOW[] = {
- {0x11, PANEL_426_GDEQ0426T82_ENTRY_MODE, 1},
- {0x44, PANEL_426_GDEQ0426T82_WINDOW_X, 4},
- {0x45, PANEL_426_GDEQ0426T82_WINDOW_Y, 4},
- {0x4E, PANEL_426_GDEQ0426T82_WINDOW_XC, 2},
- {0x4F, PANEL_426_GDEQ0426T82_WINDOW_YC, 2},
- };
- // _Update_Full(), useFastFullUpdate=true path (this panel's vendor default).
- inline const uint8_t PANEL_426_GDEQ0426T82_DISPLAY_UPDATE_CONTROL[] = {0x40, 0x00}; // bypass RED as 0, single chip
- inline const uint8_t PANEL_426_GDEQ0426T82_TEMP_REGISTER[] = {0x5A};
- inline const uint8_t PANEL_426_GDEQ0426T82_UPDATE_MODE[] = {0xD7};
- inline const EpdCommand PANEL_426_GDEQ0426T82_REFRESH[] = {
- {0x21, PANEL_426_GDEQ0426T82_DISPLAY_UPDATE_CONTROL, 2},
- {0x1A, PANEL_426_GDEQ0426T82_TEMP_REGISTER, 1},
- {0x22, PANEL_426_GDEQ0426T82_UPDATE_MODE, 1},
- {0x20, nullptr, 0, /*delay_before_ms=*/0, /*delay_after_ms=*/0, /*wait_busy_after=*/true},
- };
- inline const uint8_t PANEL_426_GDEQ0426T82_HIBERNATE_0_10[] = {0x01};
- inline const EpdCommand PANEL_426_GDEQ0426T82_HIBERNATE[] = {
- {0x10, PANEL_426_GDEQ0426T82_HIBERNATE_0_10, 1},
- };
- inline const EpdPanelDescriptor PANEL_426_GDEQ0426T82 = {
- .width = 800,
- .height = 480,
- .busy_active_level = true, // GxEPD2_EPD(..., /*busy_level=*/HIGH, ...)
- .busy_timeout_ms = 20000, // full_refresh_time is 1600ms; generous ceiling, matches PANEL_213_Z98C's style
- .init_sequence = PANEL_426_GDEQ0426T82_INIT,
- .init_sequence_len = sizeof(PANEL_426_GDEQ0426T82_INIT) / sizeof(PANEL_426_GDEQ0426T82_INIT[0]),
- .window_sequence = {PANEL_426_GDEQ0426T82_WINDOW, nullptr},
- .window_sequence_len = {sizeof(PANEL_426_GDEQ0426T82_WINDOW) / sizeof(PANEL_426_GDEQ0426T82_WINDOW[0]), 0},
- .plane_count = 1,
- .plane_write_cmd = {0x24, 0x00},
- .plane_write_cmd_for_full_refresh = {0x26, 0x00}, // see file header
- .plane_invert = {false, false},
- .refresh_sequence = PANEL_426_GDEQ0426T82_REFRESH,
- .refresh_sequence_len = sizeof(PANEL_426_GDEQ0426T82_REFRESH) / sizeof(PANEL_426_GDEQ0426T82_REFRESH[0]),
- .hibernate_sequence = PANEL_426_GDEQ0426T82_HIBERNATE,
- .hibernate_sequence_len = sizeof(PANEL_426_GDEQ0426T82_HIBERNATE) / sizeof(PANEL_426_GDEQ0426T82_HIBERNATE[0]),
- };
- } // namespace esphome::gxepd2
|