display_gif_embedded: 15.4 -> 20.6 fps
- FPS/refresh/decode counter via LVGL monitor_cb (printed once per second) - LVGL logging off, per-loop memory prints removed, loop delay 5 -> 1 ms - double draw buffer (render while previous chunk is flushed) - compile with -O2 instead of -Os Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4e63fb65c6
commit
70114f73aa
5 files changed
+70
-39
No files matched your search
@@ -201,7 +201,7 @@
|
||||
*-----------*/
|
||||
|
||||
/*Enable the log module*/
|
||||
#define LV_USE_LOG 1
|
||||
#define LV_USE_LOG 0
|
||||
#if LV_USE_LOG
|
||||
|
||||
/*How important log should be added:
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#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 lv_indev_t *indev_touchpad;
|
||||
@@ -418,8 +419,9 @@ 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);
|
||||
lv_init();
|
||||
lv_disp_draw_buf_init(&draw_buf, disp_draw_buf, NULL, SCREEN_RES_HOR * lv_cache_rows);
|
||||
lv_disp_draw_buf_init(&draw_buf, disp_draw_buf, disp_draw_buf2, SCREEN_RES_HOR * lv_cache_rows);
|
||||
|
||||
lv_disp_drv_init(&disp_drv);
|
||||
disp_drv.hor_res = SCREEN_RES_HOR;
|
||||
|
||||
@@ -1,29 +1,32 @@
|
||||
; JC3636W518 — ESP32-S3R8, 16 MB QIO flash, 8 MB OPI PSRAM, 360x360 ST77916 QSPI + CST816S
|
||||
; Settings mirror the vendor Arduino IDE setup (2-Program Example/Demo_Arduino/docs/Arduino set up.png)
|
||||
|
||||
[env:jc3636w518]
|
||||
; pioarduino = Arduino core 3.0.5 (ESP32_Display_Panel 0.1.4 needs core 3.x)
|
||||
platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.05/platform-espressif32.zip
|
||||
board = esp32-s3-devkitc-1
|
||||
framework = arduino
|
||||
|
||||
board_build.arduino.memory_type = qio_opi
|
||||
board_build.flash_mode = qio
|
||||
board_upload.flash_size = 16MB
|
||||
; GIF compiled into firmware -> 3.4 MB, too big for huge_app (3 MB); 6.25 MB app slots
|
||||
board_build.partitions = default_16MB.csv
|
||||
|
||||
build_flags =
|
||||
-DBOARD_HAS_PSRAM
|
||||
-DARDUINO_USB_CDC_ON_BOOT=1
|
||||
; LVGL (also when compiled as a library) picks up include/lv_conf.h of this project
|
||||
-DLV_CONF_INCLUDE_SIMPLE
|
||||
-Iinclude
|
||||
|
||||
; vendor-bundled libraries: ESP32_Display_Panel 0.1.4, ESP32_IO_Expander 0.0.2, lvgl 8.3.11
|
||||
lib_extra_dirs = ../../2-Program Example/Demo_Arduino/library
|
||||
|
||||
upload_port = COM21
|
||||
monitor_port = COM21
|
||||
monitor_speed = 115200
|
||||
monitor_filters = esp32_exception_decoder
|
||||
; JC3636W518 — ESP32-S3R8, 16 MB QIO flash, 8 MB OPI PSRAM, 360x360 ST77916 QSPI + CST816S
|
||||
; Settings mirror the vendor Arduino IDE setup (2-Program Example/Demo_Arduino/docs/Arduino set up.png)
|
||||
|
||||
[env:jc3636w518]
|
||||
; pioarduino = Arduino core 3.0.5 (ESP32_Display_Panel 0.1.4 needs core 3.x)
|
||||
platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.05/platform-espressif32.zip
|
||||
board = esp32-s3-devkitc-1
|
||||
framework = arduino
|
||||
|
||||
board_build.arduino.memory_type = qio_opi
|
||||
board_build.flash_mode = qio
|
||||
board_upload.flash_size = 16MB
|
||||
; GIF compiled into firmware -> 3.4 MB, too big for huge_app (3 MB); 6.25 MB app slots
|
||||
board_build.partitions = default_16MB.csv
|
||||
|
||||
; optimise for speed instead of size (faster GIF decoding)
|
||||
build_unflags = -Os
|
||||
build_flags =
|
||||
-O2
|
||||
-DBOARD_HAS_PSRAM
|
||||
-DARDUINO_USB_CDC_ON_BOOT=1
|
||||
; LVGL (also when compiled as a library) picks up include/lv_conf.h of this project
|
||||
-DLV_CONF_INCLUDE_SIMPLE
|
||||
-Iinclude
|
||||
|
||||
; vendor-bundled libraries: ESP32_Display_Panel 0.1.4, ESP32_IO_Expander 0.0.2, lvgl 8.3.11
|
||||
lib_extra_dirs = ../../2-Program Example/Demo_Arduino/library
|
||||
|
||||
upload_port = COM21
|
||||
monitor_port = COM21
|
||||
monitor_speed = 115200
|
||||
monitor_filters = esp32_exception_decoder
|
||||
@@ -12,6 +12,30 @@ const char* password = "123456789";
|
||||
|
||||
String httpGETRequest(const char* serverName);
|
||||
|
||||
// FPS measurement: LVGL calls this after every screen refresh (= one GIF frame here)
|
||||
static volatile uint32_t refr_count = 0;
|
||||
static volatile uint32_t refr_time_ms = 0;
|
||||
static uint32_t busy_us = 0; // time spent inside lv_timer_handler()
|
||||
|
||||
static void refr_monitor_cb(lv_disp_drv_t* drv, uint32_t time, uint32_t px) {
|
||||
refr_count++;
|
||||
refr_time_ms += time;
|
||||
}
|
||||
|
||||
void print_fps() {
|
||||
static uint32_t last_ms = 0;
|
||||
uint32_t now = millis();
|
||||
if (now - last_ms < 1000) return;
|
||||
// decode = busy time not spent refreshing the screen (mostly GIF decoding)
|
||||
Serial.printf("FPS: %.1f avg refresh: %lu ms avg decode: %lu ms\n", refr_count * 1000.0f / (now - last_ms),
|
||||
refr_count ? refr_time_ms / refr_count : 0,
|
||||
refr_count ? (busy_us / 1000 - refr_time_ms) / refr_count : 0);
|
||||
refr_count = 0;
|
||||
refr_time_ms = 0;
|
||||
busy_us = 0;
|
||||
last_ms = now;
|
||||
}
|
||||
|
||||
|
||||
void my_print(const char* buf) {
|
||||
Serial.println(buf); // Print logs to the serial monitor
|
||||
@@ -106,6 +130,7 @@ void setup() {
|
||||
delay(200);
|
||||
Serial.begin(115200);
|
||||
scr_lvgl_init();
|
||||
lv_disp_get_default()->driver->monitor_cb = refr_monitor_cb;
|
||||
|
||||
lv_init();
|
||||
|
||||
@@ -143,15 +168,11 @@ void setup() {
|
||||
}
|
||||
|
||||
void loop() {
|
||||
uint32_t t0 = micros();
|
||||
lv_timer_handler();
|
||||
vTaskDelay(5);
|
||||
|
||||
lv_mem_monitor_t mem_mon;
|
||||
lv_mem_monitor(&mem_mon);
|
||||
printf("Free memory: %d bytes\n", mem_mon.free_size);
|
||||
|
||||
Serial.print("Available Heap: ");
|
||||
Serial.println(esp_get_free_heap_size());
|
||||
busy_us += micros() - t0;
|
||||
vTaskDelay(1);
|
||||
print_fps();
|
||||
|
||||
|
||||
// if (WiFi.status() == WL_CONNECTED) {
|
||||
|
||||
@@ -96,6 +96,11 @@ Cheap dual-mode clones typically expose BLE service `FFF0` (notify `FFF1`, write
|
||||
## Gotchas / observations
|
||||
- **LVGL GIF bug (patched locally):** LVGL 8.3.11 `gifdec.c` (`gd_open_gif`) filled the canvas *opaque* with the GIF's background color. GIFs with a transparent background (e.g. `loligod.gif`, bg = RGB 28,29,49) showed that dark gray except where "restore to background" frames had cleared to transparent (→ screen black). **Patched** in the vendor copy `2-Program Example/Demo_Arduino/library/lvgl/src/extra/libs/gif/gifdec.c`: initial canvas alpha 0x00 (marked `LOCAL PATCH`). Re-apply if LVGL is ever replaced/upgraded.
|
||||
- Most GIFs in `assets/gifs` are optimized (transparent unchanged pixels, disposal 1/2); `loligod.gif` has a fully transparent background (~84 % of each frame).
|
||||
- **GIF performance** (360×360 loligod, embedded, measured with a `monitor_cb` FPS counter in `display_gif_embedded`):
|
||||
baseline 15.4 fps (decode 27 ms + refresh 31 ms) → no LVGL log / no per-loop prints: no change → `vTaskDelay(1)`: 16.5 → **double draw buffer** (2×72 rows internal RAM): 19.5 (refresh 21 ms) → **`-O2`** instead of `-Os`: **20.6 fps** (refresh 19 ms, decode ~24 ms). GIF's own rate is 23.7 fps. From SD card it was only ~1.4 fps.
|
||||
Remaining limit is LVGL's single-threaded GIF decode; going further would need decoding on the other core or a lighter format (e.g. pre-converted frames/MJPEG).
|
||||
- **SD card (user's 487 MB SDSC)** intermittently fails to init (`sdmmc_init_ocr ... 0x107`) after resets; once stuck only a power cycle helps (card VDD is hard-wired to 3V3). Recommend a newer SDHC card.
|
||||
- Reading boot logs: USB-CDC — reset via DTR=0/RTS pulse, then reopen the port (it re-enumerates).
|
||||
- LVGL version: all JC3636W518 projects use the vendor-bundled **LVGL 8.3.11**. LVGL 9 would require porting `scr_st77916.h` (display/touch driver glue).
|
||||
- Display is round: corners of the 360×360 framebuffer are not visible — design UI within a 360 px circle.
|
||||
- Compiling a 13.9 MB GIF into the firmware will not fit "Huge APP" (3 MB); large media should live on SD (or in a custom partition).
|
||||
|
||||
Reference in new issue
Block a user