// ====================================================== // uDisplay_epd_panel.h - E-Paper Display Panel Implementation // ====================================================== #pragma once #include #include "uDisplay_panel.h" #include "uDisplay_SPI_controller.h" /** * Configuration for E-Paper displays */ struct EPDPanelConfig { uint16_t width; uint16_t height; uint8_t bpp; // Always 1 for EPD uint8_t ep_mode; // 1=2-LUT, 2=5-LUT, 3=command-based // Timing int16_t lut_full_time; uint16_t lut_partial_time; uint16_t update_time; // Pins int8_t reset_pin; int8_t busy_pin; // EPD-specific flags bool invert_colors; // If true, invert color logic bool invert_framebuffer; // If true, invert when sending to display bool busy_invert; // If true, busy pin is active low // Busy timeout uint16_t busy_timeout = 3000; // UDSP_BUSY_TIMEOUT // Command bytes for ep_mode 2 (4.2" displays) uint8_t saw_1 = 0; // First command for frame update uint8_t saw_2 = 0; // Second command for frame update uint8_t saw_3 = 0; // Third command for frame update // LUT data (for ep_mode 1 - 2-LUT mode) const uint8_t* lut_full = nullptr; uint16_t lut_full_len = 0; const uint8_t* lut_partial = nullptr; uint16_t lut_partial_len = 0; // LUT data (for ep_mode 2 - 5-LUT mode) const uint8_t** lut_array = nullptr; // Array of 5 LUTs const uint8_t* lut_cnt = nullptr; // Size of each LUT uint8_t lut_cmd[5] = {0}; // Commands for each LUT // Additional LUT management (owned by EPD panel) uint8_t* lut_full_data = nullptr; // Owned pointer to full LUT data uint8_t* lut_partial_data = nullptr; // Owned pointer to partial LUT data uint8_t* lut_array_data[5] = {nullptr, nullptr, nullptr, nullptr, nullptr}; // Owned pointers to LUT array data uint16_t lutfsize = 0; // Filled size of lut_full uint16_t lutpsize = 0; // Filled size of lut_partial uint8_t lut_cnt_data[5] = {0}; // Filled sizes of each LUT in array uint8_t lut_siz[5] = {0}; // Allocated sizes of each LUT in array // Command offsets for ep_mode 1 and 3 uint16_t epcoffs_full = 0; // Offset to full update commands uint16_t epcoffs_part = 0; // Offset to partial update commands uint8_t epc_full_cnt = 0; // Count of full update commands uint8_t epc_part_cnt = 0; // Count of partial update commands // Callback to send command sequences from descriptor std::function send_cmds_callback; }; class EPDPanel : public UniversalPanel { public: EPDPanel(const EPDPanelConfig& config, SPIController* spi_ctrl, uint8_t* framebuffer); // REQUIRED for EPD ~EPDPanel(); // UniversalPanel interface bool drawPixel(int16_t x, int16_t y, uint16_t color) override; bool fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) override; bool pushColors(uint16_t *data, uint16_t len, bool first = false) override; bool setAddrWindow(int16_t x0, int16_t y0, int16_t x1, int16_t y1) override; bool drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) override; bool drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) override; bool displayOnff(int8_t on) override; bool invertDisplay(bool invert) override; bool setRotation(uint8_t rotation) override; bool updateFrame() override; // EPD-specific public methods (for uDisplay wrapper compatibility) void resetDisplay(); void setLut(const uint8_t* lut, uint16_t len); void setLuts(); // For ep_mode 2 (5-LUT mode) void setMemoryArea(int x_start, int y_start, int x_end, int y_end); void setMemoryPointer(int x, int y); void clearFrameMemory(uint8_t color); void displayFrame(); void delay_sync(int32_t ms); // ep_mode 2 specific (4.2" displays) void clearFrame_42(); void displayFrame_42(); // Frame memory management void setFrameMemory(const uint8_t* image_buffer); void setFrameMemory(const uint8_t* image_buffer, uint16_t x, uint16_t y, uint16_t w, uint16_t h); void sendEPData(); // Update mode control (for ep_mode 1 and 3) void setUpdateMode(uint8_t mode); // 0=DISPLAY_INIT_MODE, 1=DISPLAY_INIT_PARTIAL, 2=DISPLAY_INIT_FULL EPDPanelConfig cfg; private: SPIController* spi; uint8_t* fb_buffer; // Framebuffer (always used) uint8_t update_mode; // 0=DISPLAY_INIT_MODE, 1=DISPLAY_INIT_PARTIAL, 2=DISPLAY_INIT_FULL uint8_t rotation; // Current rotation (0-3) // Address window for pushColors int16_t window_x1 = 0; int16_t window_y1 = 0; int16_t window_x2 = 0; int16_t window_y2 = 0; // Private helpers void waitBusy(); void drawAbsolutePixel(int x, int y, uint16_t color); void sendYColumnAsXRow(const uint8_t* y_column_buffer, uint16_t buffer_width, uint16_t rows, uint16_t cols_bytes); };