panel_213_z98c.h 3.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. #pragma once
  2. // GDEY0213Z98, SSD1680 controller, 128x250 RAM window (122 columns visible),
  3. // black + red. Derived from third_party/GxEPD2/src/epd3c/GxEPD2_213_Z98c.{h,cpp}.
  4. #include "epd_command.h"
  5. namespace esphome::gxepd2 {
  6. // _InitDisplay(): SWRESET (0x12) bracketed by fixed 10ms delays (not a
  7. // busy-pin wait), driver output control, data entry mode, border waveform,
  8. // temp sensor, and display update control (0x21). The trailing
  9. // _setPartialRamArea() is dropped - CycleEngine's SET_WINDOW covers it.
  10. inline const uint8_t PANEL_213_Z98C_DRIVER_OUTPUT_CONTROL[] = {0xF9, 0x00, 0x00};
  11. inline const uint8_t PANEL_213_Z98C_DATA_ENTRY_MODE[] = {0x03};
  12. inline const uint8_t PANEL_213_Z98C_BORDER_WAVEFORM[] = {0x05};
  13. inline const uint8_t PANEL_213_Z98C_TEMP_SENSOR[] = {0x80};
  14. inline const uint8_t PANEL_213_Z98C_DISPLAY_UPDATE_CONTROL[] = {0x00, 0x80};
  15. inline const EpdCommand PANEL_213_Z98C_INIT[] = {
  16. {0x12, nullptr, 0, /*delay_before_ms=*/10, /*delay_after_ms=*/10, /*wait_busy_after=*/false}, // SWRESET
  17. {0x01, PANEL_213_Z98C_DRIVER_OUTPUT_CONTROL, 3},
  18. {0x11, PANEL_213_Z98C_DATA_ENTRY_MODE, 1},
  19. {0x3C, PANEL_213_Z98C_BORDER_WAVEFORM, 1},
  20. {0x18, PANEL_213_Z98C_TEMP_SENSOR, 1},
  21. {0x21, PANEL_213_Z98C_DISPLAY_UPDATE_CONTROL, 2},
  22. };
  23. // _Update_Full(): a single combined trigger (0x22 update control + 0x20) that
  24. // handles power internally.
  25. inline const uint8_t PANEL_213_Z98C_UPDATE_MODE[] = {0xF7};
  26. inline const EpdCommand PANEL_213_Z98C_REFRESH[] = {
  27. {0x22, PANEL_213_Z98C_UPDATE_MODE, 1},
  28. {0x20, nullptr, 0, /*delay_before_ms=*/0, /*delay_after_ms=*/0, /*wait_busy_after=*/true},
  29. };
  30. // _setPartialRamArea(0, 0, WIDTH, HEIGHT): SSD1680 byte-column X addressing
  31. // (0x44's operands are RAM byte columns, not raw pixels), no Y-reversal.
  32. inline const uint8_t PANEL_213_Z98C_WINDOW_X[] = {0x00, 0x0F}; // xe/8 = 127/8
  33. inline const uint8_t PANEL_213_Z98C_WINDOW_Y[] = {0x00, 0x00, 0xF9, 0x00}; // ye = 249
  34. inline const uint8_t PANEL_213_Z98C_WINDOW_XC[] = {0x00};
  35. inline const uint8_t PANEL_213_Z98C_WINDOW_YC[] = {0x00, 0x00};
  36. inline const EpdCommand PANEL_213_Z98C_WINDOW[] = {
  37. {0x44, PANEL_213_Z98C_WINDOW_X, 2},
  38. {0x45, PANEL_213_Z98C_WINDOW_Y, 4},
  39. {0x4E, PANEL_213_Z98C_WINDOW_XC, 1},
  40. {0x4F, PANEL_213_Z98C_WINDOW_YC, 2},
  41. };
  42. inline const uint8_t PANEL_213_Z98C_HIBERNATE_0_10[] = {0x01};
  43. inline const EpdCommand PANEL_213_Z98C_HIBERNATE[] = {
  44. {0x10, PANEL_213_Z98C_HIBERNATE_0_10, 1},
  45. };
  46. // Vendor full_refresh_time is 15000ms; used as the ceiling for every busy
  47. // wait (erring long only delays reporting a genuine timeout).
  48. inline const EpdPanelDescriptor PANEL_213_Z98C = {
  49. .width = 128, // RAM window width (addressing works in this, not WIDTH_VISIBLE=122)
  50. .height = 250,
  51. .busy_active_level = true, // GxEPD2_EPD(..., /*busy_level=*/HIGH, ...)
  52. .busy_timeout_ms = 30000,
  53. .init_sequence = PANEL_213_Z98C_INIT,
  54. .init_sequence_len = sizeof(PANEL_213_Z98C_INIT) / sizeof(PANEL_213_Z98C_INIT[0]),
  55. .window_sequence = {PANEL_213_Z98C_WINDOW, nullptr},
  56. .window_sequence_len = {sizeof(PANEL_213_Z98C_WINDOW) / sizeof(PANEL_213_Z98C_WINDOW[0]), 0},
  57. .plane_count = 2,
  58. .plane_write_cmd = {0x24, 0x26},
  59. // Color-plane wire convention: vendor writeImage() does _writeData(~data)
  60. // with a 0xFF "blank" default, so wire 0x00 = not-red; our buffer's 1=red
  61. // bit matches that, so no inversion. (DISPLAY_UPDATE_CONTROL={0x00,0x80}
  62. // above sets the matching plane polarity.) Bench-confirmed.
  63. .plane_invert = {false, false},
  64. .refresh_sequence = PANEL_213_Z98C_REFRESH,
  65. .refresh_sequence_len = sizeof(PANEL_213_Z98C_REFRESH) / sizeof(PANEL_213_Z98C_REFRESH[0]),
  66. .hibernate_sequence = PANEL_213_Z98C_HIBERNATE,
  67. .hibernate_sequence_len = sizeof(PANEL_213_Z98C_HIBERNATE) / sizeof(PANEL_213_Z98C_HIBERNATE[0]),
  68. };
  69. } // namespace esphome::gxepd2