#include "low_level_display_st7796.h" #include #include // RGB565 color definitions #define COLOR_BLACK 0x0000 #define COLOR_WHITE 0xFFFF LowLevelDisplayST7796::LowLevelDisplayST7796(const st7796_config* cfg, int w, int h, bool invert) : config(cfg), width(w), height(h), initialized(false), rgb_buffer(nullptr), invert_color(invert) { } LowLevelDisplayST7796::~LowLevelDisplayST7796() { if (rgb_buffer) { free(rgb_buffer); rgb_buffer = nullptr; } } bool LowLevelDisplayST7796::init() { if (initialized) { return true; } st7796_init(config, width, height); // Allocate RGB565 buffer once (reused for all draw operations) size_t buffer_size = width * height * sizeof(uint16_t); rgb_buffer = (uint16_t *)malloc(buffer_size); if (!rgb_buffer) { printf("Error: Failed to allocate %zu bytes for RGB buffer\n", buffer_size); return false; } printf("ST7796 display initialized: %dx%d (RGB buffer: %zu bytes)\n", width, height, buffer_size); initialized = true; return true; } void LowLevelDisplayST7796::clear(bool white) { bool out_white = invert_color ? !white : white; st7796_fill(out_white ? COLOR_WHITE : COLOR_BLACK); } void LowLevelDisplayST7796::draw_pixel(int x, int y, bool white) { bool out_white = invert_color ? !white : white; st7796_draw_pixel(x, y, out_white ? COLOR_WHITE : COLOR_BLACK); } void LowLevelDisplayST7796::draw_buffer(const uint8_t* bit_buffer) { if (!bit_buffer || !rgb_buffer) return; // Convert 1-bit buffer to RGB565 using persistent buffer for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int byte_index = (y * width + x) / 8; int bit_index = 7 - (x % 8); bool pixel_white = (bit_buffer[byte_index] >> bit_index) & 0x01; bool out_white = invert_color ? !pixel_white : pixel_white; rgb_buffer[y * width + x] = out_white ? COLOR_WHITE : COLOR_BLACK; } } // Draw entire buffer at once st7796_set_cursor(0, 0); st7796_write(rgb_buffer, width * height); } void LowLevelDisplayST7796::refresh() { // ST7796 updates immediately, no refresh needed } void LowLevelDisplayST7796::set_backlight(bool on) { // Use brightness control: on = 100%, off = 0% st7796_set_brightness(on ? 100 : 0); } void LowLevelDisplayST7796::set_brightness(uint8_t brightness) { st7796_set_brightness(brightness); } uint8_t LowLevelDisplayST7796::get_brightness() const { return st7796_get_brightness(); } void LowLevelDisplayST7796::sleep() { st7796_sleep(); } void LowLevelDisplayST7796::wake() { st7796_wake(); } void LowLevelDisplayST7796::set_rotation(uint8_t rotation) { // ST7796 driver doesn't have rotation control yet // TODO: Add MADCTL register manipulation for rotation (void)rotation; } void LowLevelDisplayST7796::on_idle_2min() { if (!is_dimmed && !is_sleeping) { saved_brightness = get_brightness(); set_brightness(5); // Dim to 5% is_dimmed = true; printf("TFT: Dimmed to 5%%\n"); } } void LowLevelDisplayST7796::on_idle_10min() { if (!is_sleeping) { sleep(); is_sleeping = true; is_dimmed = true; // Sleep implies dimmed printf("TFT: Entered sleep mode\n"); } } void LowLevelDisplayST7796::on_user_interaction() { if (is_sleeping) { wake(); // Restore brightness if we have a saved value, or default to 100 set_brightness(saved_brightness > 0 ? saved_brightness : 100); is_sleeping = false; is_dimmed = false; printf("TFT: Woke from sleep\n"); } else if (is_dimmed) { set_brightness(saved_brightness > 0 ? saved_brightness : 100); is_dimmed = false; printf("TFT: Restored brightness\n"); } }