mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-28 13:16:32 +00:00
Utilize ESP-IDF's LCD driver for pushing pixels to RGB displays with ESP32-S3 (#22970)
This commit is an optimization of code and possibly performance for pushing pixel data to an RGB display with an ESP32-S3. It uses ESP-IDF's LCD driver for doing so and replaces multiple code paths in the previous implementation. No code for other ESP32 variants has been changed. Also see the discussion arendst/Tasmota#22553
This commit is contained in:
parent
7a97a8fa98
commit
b07bd68046
@ -1225,12 +1225,19 @@ Renderer *uDisplay::Init(void) {
|
||||
_panel_config->de_gpio_num = de;
|
||||
_panel_config->pclk_gpio_num = pclk;
|
||||
|
||||
// assume that byte swapping of 16-bit color is done only upon request
|
||||
// via display.ini and not by callers of pushColor()
|
||||
// -> swap bytes by swapping GPIO numbers
|
||||
int8_t *par_db8 = lvgl_param.swap_color ? par_dbl : par_dbh;
|
||||
for (uint32_t cnt = 0; cnt < 8; cnt ++) {
|
||||
_panel_config->data_gpio_nums[cnt] = par_dbh[cnt];
|
||||
_panel_config->data_gpio_nums[cnt] = par_db8[cnt];
|
||||
}
|
||||
par_db8 = lvgl_param.swap_color ? par_dbh : par_dbl;
|
||||
for (uint32_t cnt = 0; cnt < 8; cnt ++) {
|
||||
_panel_config->data_gpio_nums[cnt + 8] = par_dbl[cnt];
|
||||
_panel_config->data_gpio_nums[cnt + 8] = par_db8[cnt];
|
||||
}
|
||||
lvgl_param.swap_color = 0;
|
||||
|
||||
_panel_config->disp_gpio_num = GPIO_NUM_NC;
|
||||
|
||||
_panel_config->flags.disp_active_low = 0;
|
||||
@ -1781,9 +1788,6 @@ void uDisplay::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) {
|
||||
|
||||
if (interface == _UDSP_RGB) {
|
||||
#ifdef USE_ESP32_S3
|
||||
if (lvgl_param.swap_color) {
|
||||
color = color << 8 | color >> 8;
|
||||
}
|
||||
if (cur_rot > 0) {
|
||||
while (h--) {
|
||||
drawPixel_RGB(x , y , color);
|
||||
@ -1854,9 +1858,6 @@ void uDisplay::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) {
|
||||
|
||||
if (interface == _UDSP_RGB) {
|
||||
#ifdef USE_ESP32_S3
|
||||
if (lvgl_param.swap_color) {
|
||||
color = color << 8 | color >> 8;
|
||||
}
|
||||
if (cur_rot > 0) {
|
||||
while (w--) {
|
||||
drawPixel_RGB(x , y , color);
|
||||
@ -2228,7 +2229,6 @@ void uDisplay::pushColorsMono(uint16_t *data, uint16_t len, bool rgb16_swap) {
|
||||
static inline void lvgl_color_swap(uint16_t *data, uint16_t len) { for (uint32_t i = 0; i < len; i++) (data[i] = data[i] << 8 | data[i] >> 8); }
|
||||
|
||||
void uDisplay::pushColors(uint16_t *data, uint16_t len, boolean not_swapped) {
|
||||
uint16_t color;
|
||||
|
||||
if (lvgl_param.swap_color) {
|
||||
not_swapped = !not_swapped;
|
||||
@ -2238,63 +2238,21 @@ void uDisplay::pushColors(uint16_t *data, uint16_t len, boolean not_swapped) {
|
||||
|
||||
// Isolating _UDSP_RGB to increase code sharing
|
||||
//
|
||||
// LVGL documentation suggest to call the following:
|
||||
// lv_draw_sw_rgb565_swap() to invert bytes
|
||||
// esp_lcd_panel_draw_bitmap() to paste bytes
|
||||
// but it appears to be faster to include the color swap in the copy loop
|
||||
// because the CPU is much faster than PSRAM (SPI bus), therefore
|
||||
// swapping bytes on the fly costs zero performance
|
||||
//
|
||||
// not_swapped == false : called from LVGL bytes are swapped
|
||||
// not_swapped == true : called from displaytext, no byte swap, currently no dma here
|
||||
// Use ESP-IDF LCD driver to push colors and rely on the following assumptions:
|
||||
// * bytes swapping is already handled in the driver configuration (see uDisplay::Init()),
|
||||
// * pushColors() is only called with not_swapped equals true,
|
||||
// * cache flushing is done by the LCD driver.
|
||||
if (interface == _UDSP_RGB) {
|
||||
#ifdef USE_ESP32_S3
|
||||
if (!not_swapped) {
|
||||
// internal error -> write error message but continue (with possibly wrong colors)
|
||||
AddLog(LOG_LEVEL_ERROR, PSTR("DSP: Unexpected byte-swapping requested in pushColors()"));
|
||||
}
|
||||
|
||||
// check that bytes count matches the size of area, and remove from inner loop
|
||||
if ((seta_yp2 - seta_yp1) * (seta_xp2 - seta_xp2) > len) { return; }
|
||||
|
||||
uint16_t lenc = len;
|
||||
|
||||
if (cur_rot > 0) {
|
||||
for (uint32_t y = seta_yp1; y < seta_yp2; y++) {
|
||||
seta_yp1++;
|
||||
for (uint32_t x = seta_xp1; x < seta_xp2; x++) {
|
||||
uint16_t color = *data++;
|
||||
if (!not_swapped) { color = color << 8 | color >> 8; }
|
||||
drawPixel_RGB(x, y, color);
|
||||
lenc--;
|
||||
if (!lenc) return; // failsafe - exist if len (pixel number) is exhausted
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uint16_t *fb_y = rgb_fb + (int32_t)seta_yp1 * _width;
|
||||
for (uint32_t y = seta_yp1; y < seta_yp2; y++) {
|
||||
uint16_t * fb_xy = fb_y + seta_xp1;
|
||||
// we get the 'not_swapped' test outside of the inner loop
|
||||
if (not_swapped) {
|
||||
for (uint32_t x = seta_xp1; x < seta_xp2; x++) {
|
||||
uint16_t color = *data++;
|
||||
*fb_xy = color;
|
||||
fb_xy++;
|
||||
lenc--;
|
||||
if (!lenc) break; // failsafe - exist if len (pixel number) is exhausted
|
||||
}
|
||||
} else {
|
||||
for (uint32_t x = seta_xp1; x < seta_xp2; x++) {
|
||||
uint16_t color = *data++;
|
||||
color = color << 8 | color >> 8;
|
||||
*fb_xy = color;
|
||||
fb_xy++;
|
||||
lenc--;
|
||||
if (!lenc) break; // failsafe - exist if len (pixel number) is exhausted
|
||||
}
|
||||
}
|
||||
uint16_t * flush_ptr = rgb_fb + (int32_t)seta_yp1 * _width + seta_xp1;
|
||||
Cache_WriteBack_Addr((uint32_t)flush_ptr, (seta_xp2 - seta_xp1) * 2);
|
||||
fb_y += _width;
|
||||
seta_yp1++;
|
||||
if (!lenc) break;
|
||||
}
|
||||
}
|
||||
esp_lcd_panel_draw_bitmap(_panel_handle, seta_xp1, seta_yp1, seta_xp2, seta_yp2, (void *)data);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
@ -2329,6 +2287,7 @@ void uDisplay::pushColors(uint16_t *data, uint16_t len, boolean not_swapped) {
|
||||
uint8_t *line = (uint8_t*)malloc(len * 3);
|
||||
uint8_t *lp = line;
|
||||
if (line) {
|
||||
uint16_t color;
|
||||
for (uint32_t cnt = 0; cnt < len; cnt++) {
|
||||
color = *data++;
|
||||
color = (color << 8) | (color >> 8);
|
||||
@ -2463,9 +2422,6 @@ void uDisplay::drawPixel(int16_t x, int16_t y, uint16_t color) {
|
||||
|
||||
#ifdef USE_ESP32_S3
|
||||
if (interface == _UDSP_RGB) {
|
||||
if (lvgl_param.swap_color) {
|
||||
color = color << 8 | color >> 8;
|
||||
}
|
||||
drawPixel_RGB(x, y, color);
|
||||
return;
|
||||
}
|
||||
@ -2548,6 +2504,15 @@ void uDisplay::setRotation(uint8_t rotation) {
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef USE_ESP32_S3
|
||||
if (interface == _UDSP_RGB) {
|
||||
// utilize the ESP-IDF LCD driver's support for display rotation:
|
||||
// mirror x axis for rotation 1 and 2, mirror y axis for rotation 2 and 3
|
||||
esp_lcd_panel_mirror(_panel_handle, rotation == 1 || rotation == 2, rotation & 2);
|
||||
// swap x/y for rotation 1 and 3
|
||||
esp_lcd_panel_swap_xy(_panel_handle, rotation & 1);
|
||||
}
|
||||
#endif // USE_ESP32_S3
|
||||
}
|
||||
|
||||
void udisp_bpwr(uint8_t on);
|
||||
|
Loading…
x
Reference in New Issue
Block a user