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

116 lines
4.0 KiB
C++

// WIP
// ======================================================
// uDisplay_spi_panel.h - SPI LCD Panel Implementation
// ======================================================
#pragma once
#include "uDisplay_panel.h"
#include "uDisplay_SPI_controller.h"
typedef struct LVGL_PARAMS_t {
uint16_t flushlines;
union {
uint8_t data;
struct {
uint8_t use_dma : 1;
uint8_t swap_color : 1;
uint8_t async_dma : 1; // force DMA completion before returning, avoid conflict with other devices on same bus. If set you should make sure the display is the only device on the bus
uint8_t busy_invert : 1;
uint8_t invert_bw : 1;
uint8_t resvd_3 : 1;
uint8_t resvd_4 : 1;
uint8_t resvd_5 : 1;
};
};
}LVGL_PARAMS_t;
/**
* Configuration for SPI-based displays
*/
struct SPIPanelConfig {
// ===== Display Dimensions =====
uint16_t width;
uint16_t height;
uint8_t bpp; // bits per pixel (1, 8, 16, etc.)
uint8_t col_mode; // color mode (16, 18, etc.)
// ===== Address Window Protocol =====
uint8_t cmd_set_addr_x; // Command to set X address range
uint8_t cmd_set_addr_y; // Command to set Y address range
uint8_t cmd_write_ram; // Command to write pixel data
// ===== Display Control Commands =====
uint8_t cmd_display_on;
uint8_t cmd_display_off;
uint8_t cmd_invert_on;
uint8_t cmd_invert_off;
uint8_t cmd_memory_access; // For rotation settings
uint8_t cmd_startline; // For vertical scroll offset
// ===== Per-Rotation Configuration =====
uint8_t rot_cmd[4]; // Memory access command variant for each rotation
uint16_t x_addr_offset[4]; // Address offset per rotation
uint16_t y_addr_offset[4];
uint8_t address_mode; // Addressing scheme (8, 16, 32-bit)
// ===== Flags =====
bool all_commands_mode; // If true: send data bytes as commands
// ===== Reset & Power Control =====
int8_t reset_pin; // GPIO for display reset (-1 if none)
// int8_t busy_pin; // REMOVED - busy_pin is EPD-only, moved to EPDPanelConfig
int8_t bpanel; // Backlight GPIO (-1 if none)
};
class SPIPanel : public UniversalPanel {
public:
/**
* Constructor - receives framebuffer from uDisplay if needed
*/
SPIPanel(const SPIPanelConfig& config,
SPIController* spi_ctrl,
uint8_t* framebuffer);
~SPIPanel();
// ===== 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 not_swapped = 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;
private:
// ===== Hardware & Configuration =====
SPIController* spi; // Not owned by panel
SPIPanelConfig cfg; // Copy of config
// ===== Framebuffer =====
uint8_t* fb_buffer; // Framebuffer (if provided by uDisplay)
// ===== Display State =====
uint8_t rotation; // Current rotation (0-3)
int16_t window_x0, window_y0, window_x1, window_y1;
bool display_on;
bool inverted;
bool use_hw_spi = false;
// ===== Internal Helpers =====
void setAddrWindow_internal(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
void sendAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
void sendCommand(uint8_t cmd);
void sendData8(uint8_t data);
void sendData16(uint16_t data);
void writeColor(uint16_t color);
void resetDisplay();
void waitBusy();
};