// ====================================================== // panel/uDisplay_rgb_panel.cpp - RGB Panel Implementation // ====================================================== #include "uDisplay_RGB_panel.h" #if SOC_LCD_RGB_SUPPORTED #include #include #include RGBPanel::RGBPanel(const esp_lcd_rgb_panel_config_t *config) { ESP_ERROR_CHECK(esp_lcd_new_rgb_panel(config, &panel_handle)); ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle)); ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle)); width = config->timings.h_res; height = config->timings.v_res; framebuffer_size = width * height * 2; // 16 bpp void* buf = NULL; esp_lcd_rgb_panel_get_frame_buffer(panel_handle, 1, &buf); framebuffer = (uint16_t*)buf; uint16_t color = random(0xffff); ESP_ERROR_CHECK(esp_lcd_panel_draw_bitmap(panel_handle, 0, 0, 1, 1, &color)); } RGBPanel::~RGBPanel() { // TODO: Cleanup panel_handle if needed } bool RGBPanel::drawPixel(int16_t x, int16_t y, uint16_t color) { int16_t w = width, h = height; // Apply rotation switch (rotation) { case 1: std::swap(w, h); std::swap(x, y); x = w - x - 1; break; case 2: x = w - x - 1; y = h - y - 1; break; case 3: std::swap(w, h); std::swap(x, y); y = h - y - 1; break; } if ((x < 0) || (x >= w) || (y < 0) || (y >= h)) return true; // Handled (out of bounds) framebuffer[y * w + x] = color; framebuffer_dirty = true; return true; // Handled by RGB panel } bool RGBPanel::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) { for (int16_t yp = y; yp < y + h; yp++) { uint16_t* line_start = &framebuffer[yp * width + x]; for (int16_t i = 0; i < w; i++) { line_start[i] = color; } } framebuffer_dirty = true; return true; // Handled by RGB panel } bool RGBPanel::setAddrWindow(int16_t x0, int16_t y0, int16_t x1, int16_t y1) { window_x1 = x0; window_y1 = y0; window_x2 = x1; window_y2 = y1; return true; // Handled by RGB panel } bool RGBPanel::pushColors(uint16_t *data, uint16_t len, bool first) { esp_lcd_panel_draw_bitmap(panel_handle, window_x1, window_y1, window_x2, window_y2, data); return true; // Handled by RGB panel } bool RGBPanel::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) { uint16_t* line_start = &framebuffer[y * width + x]; for (int16_t i = 0; i < w; i++) { line_start[i] = color; } CACHE_WRITEBACK_ADDR((uint32_t)line_start, w * 2); return true; // Handled by RGB panel } bool RGBPanel::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) { for (int16_t j = 0; j < h; j++) { framebuffer[(y + j) * width + x] = color; } CACHE_WRITEBACK_ADDR((uint32_t)&framebuffer[y * width + x], h * 2); return true; // Handled by RGB panel } bool RGBPanel::displayOnff(int8_t on) { esp_lcd_panel_disp_on_off(panel_handle, on != 0); return false; // bpanel is controlled from display class } bool RGBPanel::invertDisplay(bool invert) { // TODO: Not supported by RGB panels in ESP-IDF API return false; // Not handled - let uDisplay handle if possible } bool RGBPanel::setRotation(uint8_t rotation) { this->rotation = rotation & 3; esp_lcd_panel_mirror(panel_handle, rotation == 1 || rotation == 2, rotation & 2); esp_lcd_panel_swap_xy(panel_handle, rotation & 1); return true; // Handled by RGB panel } bool RGBPanel::updateFrame() { if (!framebuffer_dirty) { return true; } CACHE_WRITEBACK_ADDR((uint32_t)framebuffer, framebuffer_size); //KISS and fast enough! framebuffer_dirty = false; return true; // Handled (no-op is still handled) } #endif // #if SOC_LCD_RGB_SUPPORTED