119 lines
3.8 KiB
C++
119 lines
3.8 KiB
C++
// ======================================================
|
|
// panel/uDisplay_rgb_panel.cpp - RGB Panel Implementation
|
|
// ======================================================
|
|
#include "uDisplay_RGB_panel.h"
|
|
|
|
#if SOC_LCD_RGB_SUPPORTED
|
|
|
|
#include <cstdint>
|
|
#include <algorithm>
|
|
#include <rom/cache.h>
|
|
|
|
extern int CACHE_WRITEBACK_ADDR(uint32_t addr, uint32_t size);
|
|
|
|
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
|