From 6e7206b821fe4858939b559683a55a50a7f6d10b Mon Sep 17 00:00:00 2001 From: patri Date: Fri, 23 Oct 2026 01:29:25 +0200 Subject: [PATCH] LVGL 9 tuning: CPU 86% -> 53% at full GIF speed (display_gif_embedded) - render in RGB565_SWAPPED (ST77916 byte order), no swap pass in flush; flush swaps only if the display format is plain RGB565 (runtime check, the previous #if compared enum values and was always true) - QSPI clock 50 -> 80 MHz - LV_ATTRIBUTE_FAST_MEM / FLUSH_READY in IRAM (lv_attr_jc3636w518.h) - display_gif_embedded: GIF decoded in the display's color format (no alpha) - tested without gain: LV_GIF_CACHE_DECODE_DATA (unused in 9.6), 120-row buffers Co-Authored-By: Claude Opus 5.5 --- .../display_gif_embedded/src/main.cpp | 3 +++ shared/include/lv_attr_jc3636w518.h | 15 +++++++++++++++ shared/include/lv_conf.h | 6 +++--- shared/lib/JC3636W518/src/jc3636w518.cpp | 10 +++++----- 4 files changed, 26 insertions(+), 8 deletions(-) create mode 100644 shared/include/lv_attr_jc3636w518.h diff --git a/10-OBD-Display-2024/display_gif_embedded/src/main.cpp b/10-OBD-Display-2024/display_gif_embedded/src/main.cpp index 83a7356..a792651 100644 --- a/10-OBD-Display-2024/display_gif_embedded/src/main.cpp +++ b/10-OBD-Display-2024/display_gif_embedded/src/main.cpp @@ -23,6 +23,9 @@ void display_animation() { LV_IMAGE_DECLARE(loligod); img = lv_gif_create(lv_screen_active()); + // shown on a plain black screen: no transparency needed, so decode straight into the display's + // color format (no alpha blending, no conversion) to save CPU + lv_gif_set_color_format(img, lv_display_get_color_format(lv_display_get_default())); Serial.print("Available Heap before: "); Serial.println(esp_get_free_heap_size()); diff --git a/shared/include/lv_attr_jc3636w518.h b/shared/include/lv_attr_jc3636w518.h new file mode 100644 index 0000000..74879a5 --- /dev/null +++ b/shared/include/lv_attr_jc3636w518.h @@ -0,0 +1,15 @@ +/* LVGL attribute overrides for the JC3636W518 (ESP32-S3), included via LV_ATTRIBUTE_CUSTOM_INCLUDE in lv_conf.h */ +#ifndef LV_ATTR_JC3636W518_H +#define LV_ATTR_JC3636W518_H + +#if !defined(__ASSEMBLY__) +#include +#endif + +/* hot drawing/blending functions in internal RAM instead of flash (via cache) */ +#define LV_ATTRIBUTE_FAST_MEM IRAM_ATTR + +/* lv_display_flush_ready() is called from the LCD DMA-done interrupt: keep it in IRAM */ +#define LV_ATTRIBUTE_FLUSH_READY IRAM_ATTR + +#endif diff --git a/shared/include/lv_conf.h b/shared/include/lv_conf.h index a4e131b..ed75c35 100644 --- a/shared/include/lv_conf.h +++ b/shared/include/lv_conf.h @@ -142,7 +142,7 @@ * - LV_COLOR_FORMAT_ARGB8888 * - LV_COLOR_FORMAT_ARGB8888_PREMULTIPLIED */ -#define LV_COLOR_FORMAT_DEFAULT LV_COLOR_FORMAT_RGB565 +#define LV_COLOR_FORMAT_DEFAULT LV_COLOR_FORMAT_RGB565_SWAPPED /* JC3636W518: ST77916 byte order, no swap in flush */ /** 0: no adjustment, get the integer part of the result (round down) * 64: round up from x.75 @@ -2469,7 +2469,7 @@ /** Include the header given by LV_ATTRIBUTE_CUSTOM_INCLUDE to override the * LV_ATTRIBUTE_* macros for your platform. */ -#define LV_ATTRIBUTE_USE_CUSTOM_INCLUDE 0 +#define LV_ATTRIBUTE_USE_CUSTOM_INCLUDE 1 #if LV_ATTRIBUTE_USE_CUSTOM_INCLUDE /** Optional header to override LV_ATTRIBUTE_* macros for your platform. @@ -2527,7 +2527,7 @@ * Leave undefined if not using a binding. * e.g. mp_rom_map_elem_t entry = {MP_ROM_QSTR(MP_QSTR_##int_value), MP_ROM_INT(int_value)} */ -#define LV_ATTRIBUTE_CUSTOM_INCLUDE "" +#define LV_ATTRIBUTE_CUSTOM_INCLUDE "lv_attr_jc3636w518.h" /* JC3636W518: IRAM placement */ #endif /*LV_ATTRIBUTE_USE_CUSTOM_INCLUDE*/ diff --git a/shared/lib/JC3636W518/src/jc3636w518.cpp b/shared/lib/JC3636W518/src/jc3636w518.cpp index 3ecc44a..28f815c 100644 --- a/shared/lib/JC3636W518/src/jc3636w518.cpp +++ b/shared/lib/JC3636W518/src/jc3636w518.cpp @@ -246,7 +246,7 @@ const esp_lcd_panel_vendor_init_cmd_t lcd_init_cmd[] = { }; #endif -#define TFT_SPI_FREQ_HZ (50 * 1000 * 1000) +#define TFT_SPI_FREQ_HZ (80 * 1000 * 1000) // LVGL tick source static uint32_t lv_tick_millis(void) @@ -259,10 +259,10 @@ static void my_disp_flush(lv_display_t *disp, const lv_area_t *area, uint8_t *px ESP_PanelLcd *lcd = (ESP_PanelLcd *)lv_display_get_user_data(disp); const int w = lv_area_get_width(area); const int h = lv_area_get_height(area); -#if LV_COLOR_FORMAT_DEFAULT == LV_COLOR_FORMAT_RGB565 - // LVGL renders little-endian RGB565, the ST77916 expects big-endian - lv_draw_rgb565_swap(px_map, w * h); -#endif + // the ST77916 expects big-endian RGB565; plain RGB565 (little-endian) needs a byte swap, + // RGB565_SWAPPED (LV_COLOR_FORMAT_DEFAULT in lv_conf.h) is rendered in the right order already + if (lv_display_get_color_format(disp) == LV_COLOR_FORMAT_RGB565) + lv_draw_rgb565_swap(px_map, w * h); lcd->drawBitmap(area->x1, area->y1, w, h, (const uint8_t *)px_map); }