Tasmota/lib/lib_display/UDisplay/include/uDisplay_EPD_panel.h

134 lines
5.1 KiB
C++

// ======================================================
// uDisplay_epd_panel.h - E-Paper Display Panel Implementation
// ======================================================
#pragma once
#include <functional>
#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<void(uint16_t offset, uint16_t count)> 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);
};