From 90541264d19e927d77341a29dc070ce0faf1846c Mon Sep 17 00:00:00 2001 From: Gabor Peresztegi Date: Thu, 11 Jan 2024 01:10:25 +0100 Subject: [PATCH] Update LVGL and display drivers --- driver/esp32/ili9XXX.py | 84 ++++++++++++++++++--------------------- driver/generic/st77xx.py | 9 ++++- examples/advanced_demo.py | 10 +++-- examples/example1.py | 17 ++++++-- examples/example3.py | 19 ++++++--- lv_conf.h | 8 ++-- lvgl | 2 +- 7 files changed, 85 insertions(+), 64 deletions(-) diff --git a/driver/esp32/ili9XXX.py b/driver/esp32/ili9XXX.py index d05d80952..2d31e8e4d 100644 --- a/driver/esp32/ili9XXX.py +++ b/driver/esp32/ili9XXX.py @@ -14,29 +14,6 @@ # color convert). Pure MicroPython is only supported for ili9341 and # gc9a01 displays! # -# -# Display configurations: -# -# ili9341: -# - -# -# ili9488: -# - SPI frequency: 40 MHz -# This means cca 9fps of full screen -# redraw. to increase FPS, you can use 80MHz SPI - easily add parameter -# mhz=80 in initialization of driver. -# -# ili9488g (gCore): -# - SPI frequency: 80 MHz -# -# gc9a01: -# - SPI frequency: 60 MHz, as that is the maximum the tested display -# would support despite the datasheet suggesting that higher freqs would be -# supported -# -# st7789: -# - -# ############################################################################## import espidf as esp @@ -89,7 +66,7 @@ def __init__(self, invert=False, double_buffer=True, half_duplex=True, display_type=0, asynchronous=False, initialize=True, color_format=lv.COLOR_FORMAT.RGB565, swap_rgb565_bytes=False ): - + # Initializations if not lv.is_initialized(): @@ -126,6 +103,9 @@ def __init__(self, self.swap_rgb565_bytes = swap_rgb565_bytes self.rgb565_swap_func = lv.draw_sw_rgb565_swap if swap_rgb565_bytes else None + if not color_format: + raise RuntimeError("No color format is defined") + # SPI self.start_time_ptr = esp.C_Pointer() self.end_time_ptr = esp.C_Pointer() @@ -143,28 +123,38 @@ def __init__(self, self.monitor_count = 0 self.cycles_in_ms = esp.esp_clk_cpu_freq() // 1000 - self.buf_size = (self.width * self.height * self.pixel_size) // factor - if invert: self.init_cmds.append({'cmd': 0x21}) - # Register display driver - - self.buf1 = esp.heap_caps_malloc(self.buf_size, esp.MALLOC_CAP.DMA) - self.buf2 = esp.heap_caps_malloc(self.buf_size, esp.MALLOC_CAP.DMA) if double_buffer else None + # Allocate display buffer(s) - if self.buf1 and self.buf2: - print("Double buffer") - elif self.buf1: - print("Single buffer") - else: + buf_size = (self.width * self.height * self.pixel_size) // factor + self.buf_size = buf_size + self.draw_buf1 = lv.draw_buf_t() + self.draw_buf2 = None + + buf1 = esp.heap_caps_malloc(buf_size, esp.MALLOC_CAP.DMA) + if not buf1: raise RuntimeError("Not enough DMA-able memory to allocate display buffer") + if self.draw_buf1.init(width, height // factor, color_format, 0, buf1, buf_size) != lv.RESULT.OK: + raise RuntimeError("Draw buffer 1 initialization failed") + + if double_buffer: + buf2 = esp.heap_caps_malloc(buf_size, esp.MALLOC_CAP.DMA) + if buf2: + self.draw_buf2 = lv.draw_buf_t() + if self.draw_buf2.init(width, height // factor, color_format, 0, buf2, buf_size) != lv.RESULT.OK: + raise RuntimeError("Draw buffer 2 initialization failed") + + # Register display driver + self.disp_spi_init() self.disp_drv = lv.display_create(self.width, self.height) self.disp_drv.set_flush_cb(esp.ili9xxx_flush if hybrid and hasattr(esp, 'ili9xxx_flush') else self.flush) - self.disp_drv.set_draw_buffers(self.buf1, self.buf2, self.buf_size, lv.DISPLAY_RENDER_MODE.PARTIAL) - + self.disp_drv.set_draw_buffers(self.draw_buf1, self.draw_buf2) + self.disp_drv.set_render_mode(lv.DISPLAY_RENDER_MODE.PARTIAL) + self.disp_drv.set_color_format(color_format) self.disp_drv.set_driver_data({ 'dc': self.dc, 'spi': self.spi, @@ -174,9 +164,6 @@ def __init__(self, 'start_y': self.start_y }) - if color_format: - self.disp_drv.set_color_format(color_format) - if self.initialize: self.init() @@ -312,13 +299,18 @@ def deinit(self): # Free RAM - if self.buf1: - esp.heap_caps_free(self.buf1) - self.buf1 = None + if self.draw_buf1: + + esp.heap_caps_free(self.draw_buf1.unaligned_data) + self.draw_buf1.unaligned_data = None + lv.draw_buf_destroy(self.draw_buf1) + self.draw_buf1 = None - if self.buf2: - esp.heap_caps_free(self.buf2) - self.buf2 = None + if self.draw_buf2: + esp.heap_caps_free(self.draw_buf2.unaligned_data) + self.draw_buf2.unaligned_data = None + lv.draw_buf_destroy(self.draw_buf2) + self.draw_buf2 = None if self.trans_buffer: esp.heap_caps_free(self.trans_buffer) diff --git a/driver/generic/st77xx.py b/driver/generic/st77xx.py index 6a7a6d279..286d67e8c 100644 --- a/driver/generic/st77xx.py +++ b/driver/generic/st77xx.py @@ -447,16 +447,21 @@ def __init__(self,doublebuffer=True,factor=4): import lv_utils color_format = lv.COLOR_FORMAT.RGB565 - bufSize=(self.width * self.height * lv.color_format_get_size(color_format)) // factor if not lv.is_initialized(): lv.init() + # create event loop if not yet present if not lv_utils.event_loop.is_running(): self.event_loop=lv_utils.event_loop() + # create display buffer(s) + draw_buf1 = lv.draw_buf_create(self.width, self.height // factor, color_format, 0) + draw_buf2 = lv.draw_buf_create(self.width, self.height // factor, color_format, 0) if doublebuffer else None + # attach all to self to avoid objects' refcount dropping to zero when the scope is exited self.disp_drv = lv.disp_create(self.width, self.height) self.disp_drv.set_flush_cb(self.disp_drv_flush_cb) - self.disp_drv.set_draw_buffers(bytearray(bufSize), bytearray(bufSize) if doublebuffer else None, bufSize, lv.DISP_RENDER_MODE.PARTIAL) + self.disp_drv.set_draw_buffers(draw_buf1, draw_buf2) + self.disp_drv.set_render_mode(lv.DISPLAY_RENDER_MODE.PARTIAL) self.disp_drv.set_color_format(color_format) class St7735(St7735_hw,St77xx_lvgl): diff --git a/examples/advanced_demo.py b/examples/advanced_demo.py index 6e6c22fea..58761db05 100644 --- a/examples/advanced_demo.py +++ b/examples/advanced_demo.py @@ -357,13 +357,15 @@ def init_gui_stm32(self): # Register display driver self.event_loop = event_loop() lcd.init(w=hres, h=vres) + + draw_buf1 = lv.draw_buf_create(hres, 50, color_format, 0) + draw_buf2 = lv.draw_buf_create(hres, 50, color_format, 0) + self.disp_drv = lv.display_create(hres, vres) self.disp_drv.set_flush_cb(lcd.flush) self.disp_drv.set_color_format(color_format) - buf_size = hres * 50 * lv.color_format_get_size(color_format) - buf1_1 = bytearray(buf_size) - buf1_2 = bytearray(buf_size) - self.disp_drv.set_draw_buffers(buf1_1, buf1_2, len(buf1_1), lv.DISPLAY_RENDER_MODE.PARTIAL) + self.disp_drv.set_draw_buffers(draw_buf1, draw_buf2) + self.disp_drv.set_render_mode(lv.DISPLAY_RENDER_MODE.PARTIAL) # Register touch sensor self.indev_drv = lv.indev_create() diff --git a/examples/example1.py b/examples/example1.py index 768266814..3f1abd4a6 100644 --- a/examples/example1.py +++ b/examples/example1.py @@ -39,15 +39,26 @@ def init_gui_stm32(self): hres = 480 vres = 272 + color_format = lv.COLOR_FORMAT.XRGB8888 # Register display driver event_loop = lv_utils.event_loop() lcd.init(w=hres, h=vres) + + buf1 = lcd.framebuffer(1) + buf2 = lcd.framebuffer(2) + draw_buf1 = lv.draw_buf_t() + draw_buf2 = lv.draw_buf_t() + if draw_buf1.init(hres, vres, color_format, 0, buf1, len(buf1)) != lv.RESULT.OK: + raise RuntimeError("Draw buffer 1 initialization failed") + if draw_buf2.init(hres, vres, color_format, 0, buf2, len(buf2)) != lv.RESULT.OK: + raise RuntimeError("Draw buffer 2 initialization failed") + self.disp_drv = lv.disp_create(hres, vres) self.disp_drv.set_flush_cb(lcd.flush) - buf1_1 = lcd.framebuffer(1) - buf1_2 = lcd.framebuffer(2) - self.disp_drv.set_draw_buffers(buf1_1, buf1_2, len(buf1_1), lv.DISP_RENDER_MODE.PARTIAL) + self.disp_drv.set_color_format(color_format) + self.disp_drv.set_draw_buffers(draw_buf1, draw_buf2) + self.disp_drv.set_render_mode(lv.DISPLAY_RENDER_MODE.PARTIAL) # disp_drv.gpu_blend_cb = lcd.gpu_blend # disp_drv.gpu_fill_cb = lcd.gpu_fill diff --git a/examples/example3.py b/examples/example3.py index a6b3f8931..1bfd65820 100644 --- a/examples/example3.py +++ b/examples/example3.py @@ -10,17 +10,26 @@ hres = 480 vres = 272 - color_format = lv.COLOR_FORMAT.ARGB8888 + color_format = lv.COLOR_FORMAT.XRGB8888 lv.init() event_loop = lv_utils.event_loop() lcd.init(w=hres, h=vres) + + buf1 = lcd.framebuffer(1) + buf2 = lcd.framebuffer(2) + draw_buf1 = lv.draw_buf_t() + draw_buf2 = lv.draw_buf_t() + if draw_buf1.init(hres, vres, color_format, 0, buf1, len(buf1)) != lv.RESULT.OK: + raise RuntimeError("Draw buffer 1 initialization failed") + if draw_buf2.init(hres, vres, color_format, 0, buf2, len(buf2)) != lv.RESULT.OK: + raise RuntimeError("Draw buffer 2 initialization failed") + disp_drv = lv.disp_create(hres, vres) disp_drv.set_flush_cb(lcd.flush) - buf_size = hres * 10 * lv.color_format_get_size(color_format) - buf1_1 = bytearray(buf_size) - buf1_2 = bytearray(buf_size) - disp_drv.set_draw_buffers(buf1_1, buf1_2, len(buf1_1), lv.DISP_RENDER_MODE.PARTIAL) + disp_drv.set_color_format(color_format) + disp_drv.set_draw_buffers(draw_buf1, draw_buf2) + disp_drv.set_render_mode(lv.DISPLAY_RENDER_MODE.PARTIAL) # disp_drv.gpu_blend_cb = lcd.gpu_blend # disp_drv.gpu_fill_cb = lcd.gpu_fill diff --git a/lv_conf.h b/lv_conf.h index 25da64608..d79f05720 100644 --- a/lv_conf.h +++ b/lv_conf.h @@ -145,6 +145,10 @@ /* Enable VG-Lite assert. */ #define LV_VG_LITE_USE_ASSERT 0 + +/* Simulate VG-Lite hardware using ThorVG */ +#define LV_USE_VG_LITE_THORVG 0 + #endif /*================= @@ -287,7 +291,7 @@ extern void mp_lv_init_gc(); *If size is not set to 0, the decoder will fail to decode when the cache is full. *If size is 0, the cache function is not enabled and the decoded mem will be released immediately after use.*/ #ifdef MICROPY_CACHE_SIZE - #define LV_CACHE_DEF_SIZE MICROPY_CACHE_SIZE + #define LV_CACHE_DEF_SIZE MICROPY_CACHE_SIZE #else #define LV_CACHE_DEF_SIZE 0 #endif @@ -514,8 +518,6 @@ extern void mp_lv_init_gc(); #define LV_USE_MENU 1 -#define LV_USE_METER 1 - #define LV_USE_MSGBOX 1 #define LV_USE_ROLLER 1 /*Requires: lv_label*/ diff --git a/lvgl b/lvgl index a9960c621..9a088565c 160000 --- a/lvgl +++ b/lvgl @@ -1 +1 @@ -Subproject commit a9960c6216ac001c3c2384bed26c41c3c86c626e +Subproject commit 9a088565ccc45222c1b7ffc0b50bafc9783988e6