Skip to content

Commit

Permalink
Update LVGL, fix display drivers and examples (#298)
Browse files Browse the repository at this point in the history
* Update LVGL and fix pixel size detection

* Update lv_conf.h

* Fix ili9xxx and st7xx color format NATIVE_REVERSED

* Fix display drivers

* Enable font Dejavu 16 persian hebrew

* Enable TinyTTF

* Enable IME Pinyin

* Enable File Explorer

* Fix GC9A01 display driver, and update LVGL config file

* Update LVGL
  • Loading branch information
PGNetHun authored Jan 8, 2024
1 parent 56bf132 commit c17bcf3
Show file tree
Hide file tree
Showing 10 changed files with 224 additions and 133 deletions.
64 changes: 32 additions & 32 deletions README.md

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions driver/esp32/espidf.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "freertos/task.h"
#include "esp_system.h"
#include "soc/cpu.h"
#include "lvgl/src/draw/sw/lv_draw_sw.h"


// ESP IDF has some functions that are declared but not implemented.
Expand Down Expand Up @@ -232,6 +233,11 @@ void ili9xxx_flush(void *_disp_drv, const void *_area, void *_color_p)
size_t size = (area->x2 - area->x1 + 1) * (area->y2 - area->y1 + 1);
uint8_t color_size = 2;

bool swap_rgb565_bytes = mp_obj_get_int(mp_obj_dict_get(driver_data, MP_OBJ_NEW_QSTR(MP_QSTR_swap_rgb565_bytes)));
if ( swap_rgb565_bytes == true ) {
lv_draw_sw_rgb565_swap(color_p, size);
}

if ( dt == DISPLAY_TYPE_ILI9488 ) {
color_size = 3;
/*Convert ARGB to RGB is required (cut off A-byte)*/
Expand Down
56 changes: 34 additions & 22 deletions driver/esp32/ili9XXX.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
##############################################################################
# Pure/Hybrid micropython lvgl display driver for ili9341 and ili9488 on ESP32
# Pure/Hybrid micropython lvgl display driver for
# ili9341, ili9488, ili9488g, gc9a01, st7789 on ESP32
#
# For ili9341 display:
#
Expand Down Expand Up @@ -64,6 +65,8 @@
import micropython
import gc

from micropython import const

micropython.alloc_emergency_exception_buf(256)
# gc.threshold(0x10000) # leave enough room for SPI master TX DMA buffers

Expand Down Expand Up @@ -94,9 +97,10 @@
DISPLAY_TYPE_ST7789 = const(4)
DISPLAY_TYPE_ST7735 = const(5)

_TRANS_BUFFER_LEN = const(16)

class ili9XXX:

TRANS_BUFFER_LEN = const(16)
display_name = 'ili9XXX'
init_cmds = [ ]

Expand All @@ -107,7 +111,7 @@ def __init__(self,
miso=5, mosi=18, clk=19, cs=13, dc=12, rst=4, power=14, backlight=15, backlight_on=0, power_on=0,
spihost=esp.HSPI_HOST, spimode=0, mhz=40, factor=4, hybrid=True, width=240, height=320, start_x=0, start_y=0,
invert=False, double_buffer=True, half_duplex=True, display_type=0, asynchronous=False, initialize=True,
color_format=None
color_format=None, swap_rgb565_bytes=False
):

# Initializations
Expand Down Expand Up @@ -140,6 +144,7 @@ def __init__(self,
self.hybrid = hybrid
self.half_duplex = half_duplex
self.display_type = display_type
self.swap_rgb565_bytes = swap_rgb565_bytes

self.buf_size = (self.width * self.height * lv.COLOR_DEPTH // 8) // factor

Expand Down Expand Up @@ -167,6 +172,7 @@ def __init__(self,
'dc': self.dc,
'spi': self.spi,
'dt': self.display_type,
'swap_rgb565_bytes': self.swap_rgb565_bytes,
'start_x': self.start_x,
'start_y': self.start_y})

Expand Down Expand Up @@ -238,7 +244,7 @@ def disp_spi_init(self):
ret = esp.spi_bus_initialize(self.spihost, buscfg, 1)
if ret != 0: raise RuntimeError("Failed initializing SPI bus")

self.trans_buffer = esp.heap_caps_malloc(TRANS_BUFFER_LEN, esp.MALLOC_CAP.DMA)
self.trans_buffer = esp.heap_caps_malloc(_TRANS_BUFFER_LEN, esp.MALLOC_CAP.DMA)
self.cmd_trans_data = self.trans_buffer.__dereference__(1)
self.word_trans_data = self.trans_buffer.__dereference__(4)

Expand Down Expand Up @@ -353,7 +359,7 @@ def send_cmd(self, cmd):

def send_data(self, data):
esp.gpio_set_level(self.dc, 1) # Data mode
if len(data) > TRANS_BUFFER_LEN: raise RuntimeError('Data too long, please use DMA!')
if len(data) > _TRANS_BUFFER_LEN: raise RuntimeError('Data too long, please use DMA!')
trans_data = self.trans_buffer.__dereference__(len(data))
trans_data[:] = data[:]
self.spi_send(trans_data)
Expand Down Expand Up @@ -442,6 +448,7 @@ def power_down(self):
end_time_ptr = esp.C_Pointer()
flush_acc_setup_cycles = 0
flush_acc_dma_cycles = 0
_rgb565_swap = lv.draw_sw_rgb565_swap

def flush(self, disp_drv, area, color_p):

Expand Down Expand Up @@ -482,7 +489,10 @@ def flush(self, disp_drv, area, color_p):
self.send_cmd(0x2C)

size = (x2 - x1 + 1) * (y2 - y1 + 1)
data_view = color_p.__dereference__(size * lv.color_t.__SIZE__)
data_view = color_p.__dereference__(size * lv.COLOR_DEPTH // 8)

if self.swap_rgb565_bytes:
self._rgb565_swap(data_view, size)

esp.get_ccount(self.end_time_ptr)
if self.end_time_ptr.int_val > self.start_time_ptr.int_val:
Expand Down Expand Up @@ -542,12 +552,12 @@ def __init__(self,
miso=5, mosi=18, clk=19, cs=13, dc=12, rst=4, power=14, backlight=15, backlight_on=0, power_on=0,
spihost=esp.HSPI_HOST, spimode=0, mhz=40, factor=4, hybrid=True, width=240, height=320, start_x=0, start_y=0,
colormode=COLOR_MODE_BGR, rot=PORTRAIT, invert=False, double_buffer=True, half_duplex=True,
asynchronous=False, initialize=True, color_format=lv.COLOR_FORMAT.NATIVE_REVERSED
asynchronous=False, initialize=True, color_format=lv.COLOR_FORMAT.NATIVE, swap_rgb565_bytes=True
):

# Make sure Micropython was built such that color won't require processing before DMA

if lv.color_t.__SIZE__ != 2:
if lv.COLOR_DEPTH != 16:
raise RuntimeError('ili9341 micropython driver requires defining LV_COLOR_DEPTH=16')

self.display_name = 'ILI9341'
Expand Down Expand Up @@ -586,7 +596,7 @@ def __init__(self,
backlight_on=backlight_on, power_on=power_on, spihost=spihost, spimode=spimode, mhz=mhz, factor=factor, hybrid=hybrid,
width=width, height=height, start_x=start_x, start_y=start_y, invert=invert, double_buffer=double_buffer,
half_duplex=half_duplex, display_type=DISPLAY_TYPE_ILI9341, asynchronous=asynchronous, initialize=initialize,
color_format=color_format)
color_format=color_format, swap_rgb565_bytes=swap_rgb565_bytes)

class ili9488(ili9XXX):

Expand All @@ -597,7 +607,7 @@ def __init__(self,
color_format=None, display_type=DISPLAY_TYPE_ILI9488, p16=False
):

if (lv.color_t.__SIZE__ != 4) and not p16:
if (lv.COLOR_DEPTH != 32) and not p16:
raise RuntimeError('ili9488 micropython driver requires defining LV_COLOR_DEPTH=32')
if not hybrid:
raise RuntimeError('ili9488 micropython driver do not support non-hybrid driver')
Expand Down Expand Up @@ -638,7 +648,8 @@ def __init__(self,
super().__init__(miso=miso, mosi=mosi, clk=clk, cs=cs, dc=dc, rst=rst, power=power, backlight=backlight,
backlight_on=backlight_on, power_on=power_on, spihost=spihost, spimode=spimode, mhz=mhz, factor=factor, hybrid=hybrid,
width=width, height=height, invert=invert, double_buffer=double_buffer, half_duplex=half_duplex,
display_type=display_type, asynchronous=asynchronous, initialize=initialize, color_format=color_format)
display_type=display_type, asynchronous=asynchronous, initialize=initialize,
color_format=color_format)

class ili9488g(ili9488):

Expand All @@ -648,13 +659,13 @@ def __init__(self,
rot=PORTRAIT, invert=False, double_buffer=True, half_duplex=True, asynchronous=False, initialize=True
):

if lv.color_t.__SIZE__ == 4:
if lv.COLOR_DEPTH == 32:
colormode=COLOR_MODE_RGB
color_format=None
display_type=DISPLAY_TYPE_ILI9488 # 24-bit pixel handling
p16=False

if lv.color_t.__SIZE__ == 2:
if lv.COLOR_DEPTH == 16:
colormode=COLOR_MODE_BGR
color_format=lv.COLOR_FORMAT.NATIVE_REVERSE
display_type=DISPLAY_TYPE_ILI9341 # Force use of 16-bit pixel handling
Expand All @@ -674,10 +685,10 @@ def __init__(self,
miso=5, mosi=18, clk=19, cs=13, dc=12, rst=4, power=14, backlight=15, backlight_on=0, power_on=0,
spihost=esp.HSPI_HOST, spimode=0, mhz=60, factor=4, hybrid=True, width=240, height=240, colormode=COLOR_MODE_RGB,
rot=PORTRAIT, invert=False, double_buffer=True, half_duplex=True, asynchronous=False, initialize=True,
color_format=None
color_format=None, swap_rgb565_bytes=True
):

if lv.color_t.__SIZE__ != 2:
if lv.COLOR_DEPTH != 16:
raise RuntimeError('gc9a01 micropython driver requires defining LV_COLOR_DEPTH=16')

# This is included as the color mode appears to be reversed from the
Expand Down Expand Up @@ -749,7 +760,8 @@ def __init__(self,
super().__init__(miso=miso, mosi=mosi, clk=clk, cs=cs, dc=dc, rst=rst, power=power, backlight=backlight,
backlight_on=backlight_on, power_on=power_on, spihost=spihost, spimode=spimode, mhz=mhz, factor=factor, hybrid=hybrid,
width=width, height=height, invert=invert, double_buffer=double_buffer, half_duplex=half_duplex,
display_type=DISPLAY_TYPE_GC9A01, asynchronous=asynchronous, initialize=initialize, color_format=color_format)
display_type=DISPLAY_TYPE_GC9A01, asynchronous=asynchronous, initialize=initialize, color_format=color_format,
swap_rgb565_bytes=swap_rgb565_bytes)

class st7789(ili9XXX):

Expand All @@ -762,11 +774,11 @@ def __init__(self,
miso=-1, mosi=19, clk=18, cs=5, dc=16, rst=23, power=-1, backlight=4, backlight_on=1, power_on=0,
spihost=esp.HSPI_HOST, spimode=0, mhz=40, factor=4, hybrid=True, width=320, height=240, start_x=0, start_y=0,
colormode=COLOR_MODE_BGR, rot=PORTRAIT, invert=True, double_buffer=True, half_duplex=True,
asynchronous=False, initialize=True, color_format=lv.COLOR_FORMAT.NATIVE_REVERSED):
asynchronous=False, initialize=True, color_format=lv.COLOR_FORMAT.NATIVE, swap_rgb565_bytes=True):

# Make sure Micropython was built such that color won't require processing before DMA

if lv.color_t.__SIZE__ != 2:
if lv.COLOR_DEPTH != 16:
raise RuntimeError('st7789 micropython driver requires defining LV_COLOR_DEPTH=16')

self.display_name = 'ST7789'
Expand Down Expand Up @@ -801,7 +813,7 @@ def __init__(self,
backlight_on=backlight_on, power_on=power_on, spihost=spihost, spimode=spimode, mhz=mhz, factor=factor, hybrid=hybrid,
width=width, height=height, start_x=start_x, start_y=start_y, invert=invert, double_buffer=double_buffer,
half_duplex=half_duplex, display_type=DISPLAY_TYPE_ST7789, asynchronous=asynchronous,
initialize=initialize, color_format=color_format)
initialize=initialize, color_format=color_format, swap_rgb565_bytes=swap_rgb565_bytes)

class st7735(ili9XXX):

Expand All @@ -814,11 +826,11 @@ def __init__(self,
miso=-1, mosi=19, clk=18, cs=13, dc=12, rst=4, power=-1, backlight=15, backlight_on=1, power_on=0,
spihost=esp.HSPI_HOST, spimode=0, mhz=40, factor=4, hybrid=True, width=128, height=160, start_x=0, start_y=0,
colormode=COLOR_MODE_RGB, rot=PORTRAIT, invert=False, double_buffer=True, half_duplex=True,
asynchronous=False, initialize=True, color_format=lv.COLOR_FORMAT.NATIVE_REVERSED):
asynchronous=False, initialize=True, color_format=lv.COLOR_FORMAT.NATIVE, swap_rgb565_bytes=True):

# Make sure Micropython was built such that color won't require processing before DMA

if lv.color_t.__SIZE__ != 2:
if lv.COLOR_DEPTH != 16:
raise RuntimeError('st7735 micropython driver requires defining LV_COLOR_DEPTH=16')

self.display_name = 'ST7735'
Expand Down Expand Up @@ -857,4 +869,4 @@ def __init__(self,
backlight_on=backlight_on, power_on=power_on, spihost=spihost, spimode=spimode, mhz=mhz, factor=factor, hybrid=hybrid,
width=width, height=height, start_x=start_x, start_y=start_y, invert=invert, double_buffer=double_buffer,
half_duplex=half_duplex, display_type=DISPLAY_TYPE_ST7735, asynchronous=asynchronous,
initialize=initialize, color_format=color_format)
initialize=initialize, color_format=color_format, swap_rgb565_bytes=swap_rgb565_bytes)
5 changes: 3 additions & 2 deletions driver/generic/st77xx.py
Original file line number Diff line number Diff line change
Expand Up @@ -441,13 +441,14 @@ def disp_drv_flush_cb(self,disp_drv,area,color):
# blit in background
self.blit(area.x1,area.y1,w:=(area.x2-area.x1+1),h:=(area.y2-area.y1+1),color.__dereference__(2*w*h),is_blocking=False)
self.disp_drv.flush_ready()

def __init__(self,doublebuffer=True,factor=4):
import lvgl as lv
import lv_utils

if lv.COLOR_DEPTH!=16: raise RuntimeError(f'LVGL *must* be compiled with LV_COLOR_DEPTH=16 (currently LV_COLOR_DEPTH={lv.COLOR_DEPTH}.')

bufSize=(self.width*self.height*lv.color_t.__SIZE__)//factor
bufSize=(self.width * self.height * lv.COLOR_DEPTH // 8) // factor

if not lv.is_initialized(): lv.init()
# create event loop if not yet present
Expand All @@ -457,7 +458,7 @@ def __init__(self,doublebuffer=True,factor=4):
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_color_format(lv.COLOR_FORMAT.NATIVE if self.bgr else lv.COLOR_FORMAT.NATIVE_REVERSED)
self.disp_drv.set_color_format(lv.COLOR_FORMAT.NATIVE)

class St7735(St7735_hw,St77xx_lvgl):
def __init__(self,res,doublebuffer=True,factor=4,**kw):
Expand Down
4 changes: 2 additions & 2 deletions examples/advanced_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,8 +358,8 @@ def init_gui_stm32(self):
lcd.init(w=hres, h=vres)
self.disp_drv = lv.display_create(hres, vres)
self.disp_drv.set_flush_cb(lcd.flush)
buf1_1 = bytearray(hres * 50 * lv.color_t.__SIZE__)
buf1_2 = bytearray(hres * 50 * lv.color_t.__SIZE__)
buf1_1 = bytearray(hres * 50 * lv.COLOR_DEPTH // 8)
buf1_2 = bytearray(hres * 50 * lv.COLOR_DEPTH // 8)
self.disp_drv.set_draw_buffers(buf1_1, buf1_2, len(buf1_1), lv.DISPLAY_RENDER_MODE.PARTIAL)

# Register touch sensor
Expand Down
2 changes: 1 addition & 1 deletion examples/example1.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class driver:
def init_gui_SDL(self):
self.event_loop = lv_utils.event_loop()
self.disp_drv = lv.sdl_window_create(480, 320)
self.indev_drv = lv.sdl_mouse_create();
self.indev_drv = lv.sdl_mouse_create()

def init_gui_esp32(self):

Expand Down
4 changes: 2 additions & 2 deletions examples/example3.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
lcd.init(w=hres, h=vres)
disp_drv = lv.disp_create(hres, vres)
disp_drv.set_flush_cb(lcd.flush)
buf1_1 = bytearray(hres * 10 * lv.color_t.__SIZE__)
buf1_2 = bytearray(hres * 10 * lv.color_t.__SIZE__)
buf1_1 = bytearray(hres * 10 * lv.COLOR_DEPTH // 8)
buf1_2 = bytearray(hres * 10 * lv.COLOR_DEPTH // 8)
disp_drv.set_draw_buffers(buf1_1, buf1_2, len(buf1_1), lv.DISP_RENDER_MODE.PARTIAL)

# disp_drv.gpu_blend_cb = lcd.gpu_blend
Expand Down
2 changes: 1 addition & 1 deletion gen/gen_mpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -2113,7 +2113,7 @@ def get_arg_name(arg):
if isinstance(arg, c_ast.PtrDecl) or isinstance(arg, c_ast.FuncDecl):
return get_arg_name(arg.type)
if hasattr(arg, 'declname'): return arg.declname
if hasattr(arg, 'name'): return name
if hasattr(arg, 'name'): return arg.name
return 'unnamed_arg'

# print("// Typedefs: " + ", ".join(get_arg_name(t) for t in typedefs))
Expand Down
Loading

0 comments on commit c17bcf3

Please sign in to comment.