#ifndef LOW_LEVEL_DISPLAY_ST7796_H #define LOW_LEVEL_DISPLAY_ST7796_H #include "low_level_display.h" #include "st7796.h" #include class LowLevelDisplayST7796 : public LowLevelDisplay { private: const st7796_config* config; int width; int height; bool initialized; uint16_t* rgb_buffer; // Persistent buffer for 1-bit to RGB565 conversion bool invert_color; // If true, swap black/white // Dirty rectangle tracking for partial updates uint8_t* prev_bit_buffer; // Previous frame buffer for change detection bool dirty_rect_enabled; // Enable/disable dirty rectangle optimization struct DirtyRect { int x0, y0; // Top-left corner int x1, y1; // Bottom-right corner (inclusive) bool is_valid; void reset() { x0 = INT_MAX; y0 = INT_MAX; x1 = -1; y1 = -1; is_valid = false; } void expand(int x, int y) { if (x < x0) x0 = x; if (x > x1) x1 = x; if (y < y0) y0 = y; if (y > y1) y1 = y; is_valid = true; } int get_width() const { return is_valid ? (x1 - x0 + 1) : 0; } int get_height() const { return is_valid ? (y1 - y0 + 1) : 0; } int get_area() const { return is_valid ? get_width() * get_height() : 0; } bool overlaps(const DirtyRect& other) const { if (!is_valid || !other.is_valid) return false; return !(x1 < other.x0 || x0 > other.x1 || y1 < other.y0 || y0 > other.y1); } void merge(const DirtyRect& other) { if (!other.is_valid) return; if (!is_valid) { *this = other; return; } x0 = (x0 < other.x0) ? x0 : other.x0; y0 = (y0 < other.y0) ? y0 : other.y0; x1 = (x1 > other.x1) ? x1 : other.x1; y1 = (y1 > other.y1) ? y1 : other.y1; } }; static constexpr int MAX_DIRTY_RECTS = 4; DirtyRect dirty_rects[MAX_DIRTY_RECTS]; // Support up to 4 dirty rectangles (4 quadrants) public: LowLevelDisplayST7796(const st7796_config* cfg, int w, int h, bool invert = false); ~LowLevelDisplayST7796() override; // Core display operations - converts 1-bit to RGB565 internally bool init() override; void clear(bool white = true) override; void draw_pixel(int x, int y, bool white) override; void draw_buffer(const uint8_t* bit_buffer) override; void refresh() override; // Display properties int get_width() const override { return width; } int get_height() const override { return height; } DisplayType get_type() const override { return DISPLAY_TYPE_ST7796; } bool is_color() const override { return true; } // Backlight control void set_backlight(bool on) override; // Brightness control (0-100) void set_brightness(uint8_t brightness) override; uint8_t get_brightness() const override; // Power management void sleep(); // Put display to sleep (low power, touch still active) void wake(); // Wake display from sleep // Orientation control void set_rotation(uint8_t rotation) override; // Color inversion control void set_invert_color(bool inv) { invert_color = inv; } bool get_invert_color() const { return invert_color; } // Power saving hooks void on_idle_2min() override; void on_idle_10min() override; void on_user_interaction() override; // Dirty rectangle optimization control void enable_dirty_rect(bool enabled = true); bool is_dirty_rect_enabled() const { return dirty_rect_enabled; } private: uint8_t saved_brightness = 100; bool is_dimmed = false; bool is_sleeping = false; }; #endif // LOW_LEVEL_DISPLAY_ST7796_H