display_gif_embedded: port to LVGL 9.6.0 (20.6 -> 23.4 fps)

- lvgl/lvgl@9.6.0 via lib_deps, lv_conf.h from the 9.6 template
- scr_st77916.h: lv_display/lv_indev API, RGB565 byte swap in flush,
  lv_tick_set_cb
- FPS counter via display refresh events
- loligod.c: lv_image_dsc_t descriptor

GIF now plays at its own frame rate; decode time halved by LVGL 9.6's
AnimatedGIF decoder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
patriandClaude Opus 5.5 committed 2026-10-23 01:00:18 +02:00
1 parent 70114f73aa
commit 9684ab39f2
7 files changed
+170574 -168624

No files matched your search

File diff suppressed because it is too large. Load diff
@@ -9,10 +9,9 @@
#define SCREEN_RES_HOR 360
#define SCREEN_RES_VER 360
static lv_color_t *disp_draw_buf;
static lv_color_t *disp_draw_buf2; // second buffer: LVGL renders into one while the other is sent to the LCD
static lv_disp_draw_buf_t draw_buf;
static lv_disp_drv_t disp_drv;
static uint8_t *disp_draw_buf;
static uint8_t *disp_draw_buf2; // second buffer: LVGL renders into one while the other is sent to the LCD
static lv_display_t *disp = NULL;
static lv_indev_t *indev_touchpad;
static ESP_PanelBacklight *backlight = NULL;
static ESP_PanelLcd *lcd = NULL;
@@ -251,20 +250,25 @@ const esp_lcd_panel_vendor_init_cmd_t lcd_init_cmd[] = {
#define TFT_SPI_FREQ_HZ (50 * 1000 * 1000)
static void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
// LVGL tick source (replaces LV_TICK_CUSTOM of LVGL 8)
static uint32_t lv_tick_millis(void)
{
ESP_PanelLcd *lcd = (ESP_PanelLcd *)disp->user_data;
const int offsetx1 = area->x1;
const int offsetx2 = area->x2;
const int offsety1 = area->y1;
const int offsety2 = area->y2;
lcd->drawBitmap(offsetx1, offsety1, offsetx2 - offsetx1 + 1, offsety2 - offsety1 + 1, (const uint8_t *)color_p);
return millis();
}
static void my_disp_flush(lv_display_t *disp, const lv_area_t *area, uint8_t *px_map)
{
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);
// LVGL 9 renders little-endian RGB565, the ST77916 expects big-endian (LVGL 8 used LV_COLOR_16_SWAP)
lv_draw_rgb565_swap(px_map, w * h);
lcd->drawBitmap(area->x1, area->y1, w, h, (const uint8_t *)px_map);
}
IRAM_ATTR bool onRefreshFinishCallback(void *user_data)
{
lv_disp_drv_t *drv = (lv_disp_drv_t *)user_data;
lv_disp_flush_ready(drv);
lv_display_flush_ready((lv_display_t *)user_data);
return false;
}
@@ -330,9 +334,9 @@ void set_brightness(uint8_t bri)
backlight->setBrightness(bri);
}
static void touchpad_read(lv_indev_drv_t *indev_drv, lv_indev_data_t *data)
static void touchpad_read(lv_indev_t *indev, lv_indev_data_t *data)
{
ESP_PanelTouch *tp = (ESP_PanelTouch *)indev_drv->user_data;
ESP_PanelTouch *tp = (ESP_PanelTouch *)lv_indev_get_user_data(indev);
ESP_PanelTouchPoint point;
int read_touch_result = tp->readPoints(&point, 1);
@@ -352,12 +356,11 @@ static lv_indev_t *indev_init(ESP_PanelTouch *tp)
{
ESP_PANEL_CHECK_FALSE_RET(tp != nullptr, nullptr, "Invalid touch device");
ESP_PANEL_CHECK_FALSE_RET(tp->getHandle() != nullptr, nullptr, "Touch device is not initialized");
static lv_indev_drv_t indev_drv_tp;
lv_indev_drv_init(&indev_drv_tp);
indev_drv_tp.type = LV_INDEV_TYPE_POINTER;
indev_drv_tp.read_cb = touchpad_read;
indev_drv_tp.user_data = (void *)tp;
return lv_indev_drv_register(&indev_drv_tp);
lv_indev_t *indev = lv_indev_create();
lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
lv_indev_set_read_cb(indev, touchpad_read);
lv_indev_set_user_data(indev, (void *)tp);
return indev;
}
void scr_lvgl_init()
@@ -418,22 +421,20 @@ void scr_lvgl_init()
size_t lv_cache_rows = 72;
disp_draw_buf = (lv_color_t *)heap_caps_malloc(lv_cache_rows * SCREEN_RES_HOR * 2, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
disp_draw_buf2 = (lv_color_t *)heap_caps_malloc(lv_cache_rows * SCREEN_RES_HOR * 2, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
size_t buf_bytes = lv_cache_rows * SCREEN_RES_HOR * 2; // RGB565
disp_draw_buf = (uint8_t *)heap_caps_malloc(buf_bytes, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
disp_draw_buf2 = (uint8_t *)heap_caps_malloc(buf_bytes, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
lv_init();
lv_disp_draw_buf_init(&draw_buf, disp_draw_buf, disp_draw_buf2, SCREEN_RES_HOR * lv_cache_rows);
lv_tick_set_cb(lv_tick_millis);
lv_disp_drv_init(&disp_drv);
disp_drv.hor_res = SCREEN_RES_HOR;
disp_drv.ver_res = SCREEN_RES_VER;
disp_drv.flush_cb = my_disp_flush;
disp_drv.draw_buf = &draw_buf;
disp_drv.user_data = (void *)lcd;
lv_disp_t *disp = lv_disp_drv_register(&disp_drv);
disp = lv_display_create(SCREEN_RES_HOR, SCREEN_RES_VER);
lv_display_set_flush_cb(disp, my_disp_flush);
lv_display_set_buffers(disp, disp_draw_buf, disp_draw_buf2, buf_bytes, LV_DISPLAY_RENDER_MODE_PARTIAL);
lv_display_set_user_data(disp, (void *)lcd);
if (lcd->getBus()->getType() != ESP_PANEL_BUS_TYPE_RGB)
{
lcd->attachRefreshFinishCallback(onRefreshFinishCallback, (void *)disp->driver);
lcd->attachRefreshFinishCallback(onRefreshFinishCallback, (void *)disp);
}
indev_touchpad = indev_init(touch);
}