diff --git a/.github/workflows/micropython_lvgl_ci.yml b/.github/workflows/micropython_lvgl_ci.yml new file mode 100644 index 0000000000..5f7039345d --- /dev/null +++ b/.github/workflows/micropython_lvgl_ci.yml @@ -0,0 +1,124 @@ +name: MicroPython-LVGL CI + +on: + push: + pull_request: + + +concurrency: + group: ${{ github.ref }}-${{ github.workflow }} + cancel-in-progress: true + +jobs: + build-lvgl-micropython: + + runs-on: ubuntu-24.04 + continue-on-error: true + strategy: + matrix: + port: ['unix', 'stm32', 'rp2', 'esp32'] + steps: + - uses: ammaraskar/gcc-problem-matcher@master + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + + - name: Install Dependencies + run: | + sudo add-apt-repository -y "deb http://archive.ubuntu.com/ubuntu `lsb_release -sc` main universe restricted multiverse" + sudo apt-get update -y -qq + sudo apt-get install libsdl2-dev parallel libfreetype-dev librlottie-dev libavformat-dev libavcodec-dev libswscale-dev libavutil-dev build-essential libc-bin + python3 -m pip install pillow + + - name: Clone lv_micropython + run: | + git clone https://github.com/lvgl/lv_micropython.git . + git checkout master + + - name: Initialize lv_bindings submodule + run: git submodule update --init --recursive user_modules/lv_binding_micropython + + - name: Update ${{ matrix.port }} port submodules + run: make -C ports/${{ matrix.port}} DEBUG=1 submodules + + # - name: Debug GitHub Event + # run: -${{ tojson(github.event) }} + # shell: cat {0} + + - name: Checkout lv_bindings (push) + working-directory: ./user_modules/lv_binding_micropython + if: ${{github.event_name == 'push'}} + run: | + + git fetch --force ${{ github.event.repository.html_url }} "+${{github.event.ref}}:refs/remotes/origin/${{github.event.head_commit.author.username}}-${{github.event.head_commit.id}}" + git checkout ${{ github.event.head_commit.id }} + git submodule update --init --recursive + + - name: Checkout lv_bindings (pull_request) + working-directory: ./user_modules/lv_binding_micropython + if: ${{github.event_name == 'pull_request'}} + run: | + + git fetch --force ${{ github.event.repository.html_url }} "+refs/pull/${{github.event.pull_request.number}}/head:refs/remotes/origin/${{github.event.pull_request.head.ref}}" + git checkout ${{ github.event.pull_request.head.sha }} + git submodule update --init --recursive + + + - name: Build mpy-cross + run: make -j $(nproc) -C mpy-cross + + # STM32 port + - name: Build stm32 port + if: matrix.port == 'stm32' + run: | + source tools/ci.sh && ci_stm32_setup + make -C ports/stm32 BOARD=PYBV11 submodules + make -j $(nproc) -C ports/stm32 BOARD=PYBV11 USER_C_MODULES=../../user_modules LV_CONF_PATH=../../user_modules/lv_binding_micropython/ports/stm32/lv_conf_stm32.h + # Raspberry Pi Pico port + - name: Build rp2 port + if: matrix.port == 'rp2' + run: | + source tools/ci.sh && ci_rp2_setup + make -C ports/rp2 BOARD=RPI_PICO submodules + make -j $(nproc) -C ports/rp2 BOARD=RPI_PICO USER_C_MODULES=../../user_modules/lv_binding_micropython/micropython.cmake + + # ESP32 port + - name: Build esp32 port + if: matrix.port == 'esp32' + run: | + source tools/ci.sh && ci_esp32_idf_setup + source tools/ci.sh && ci_esp32_build_common + make -C ports/esp32 BOARD=ESP32_GENERIC_S3 USER_C_MODULES=../../user_modules/lv_binding_micropython/micropython.cmake + + # Unix port + - name: Build unix port + if: matrix.port == 'unix' + run: make -j $(nproc) -C ports/unix DEBUG=1 VARIANT=lvgl + + - name: Run MicroPython Tests + if: matrix.port == 'unix' + run: MICROPY_MICROPYTHON=ports/unix/build-lvgl/micropython ./tests/run-tests.py -d tests/basics + + - name: Run MicroPython-LVGL API Tests + if: matrix.port == 'unix' + run: MICROPY_MICROPYTHON=ports/unix/build-lvgl/micropython ./tests/run-tests.py -d user_modules/lv_binding_micropython/tests/api + + - name: Process Tests Artifacts + + if: matrix.port == 'unix' + working-directory: ./user_modules/lv_binding_micropython/tests + run: ./imageconvert.py api/*.bin + + - name: Upload Test Artifacts + if: matrix.port == 'unix' + uses: actions/upload-artifact@v4 + with: + name: API Tests Screenshots + path: ./user_modules/lv_binding_micropython/tests/api/*.png + + # TODO: Fix run.sh catchsegv not found command + - name: Run tests + if: matrix.port == 'unix' + run: | + export XDG_RUNTIME_DIR=/tmp + user_modules/lv_binding_micropython/tests/run.sh diff --git a/.github/workflows/unix_port.yml b/.github/workflows/unix_port.yml deleted file mode 100644 index 013bbe8a8f..0000000000 --- a/.github/workflows/unix_port.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Build lv_micropython unix port - -on: - push: - pull_request: - -jobs: - build: - - runs-on: ubuntu-24.04 - - steps: - - name: Install Dependencies - run: | - sudo add-apt-repository -y "deb http://archive.ubuntu.com/ubuntu `lsb_release -sc` main universe restricted multiverse" - sudo apt-get update -y -qq - sudo apt-get install libsdl2-dev parallel libfreetype-dev librlottie-dev libavformat-dev libavcodec-dev libswscale-dev libavutil-dev - - name: Clone lv_micropython - run: | - git clone https://github.com/lvgl/lv_micropython.git . - git checkout master - - name: Initialize lv_bindings submodule - run: git submodule update --init --recursive user_modules/lv_binding_micropython - - name: Update Unix port submodules - run: make -C ports/unix DEBUG=1 submodules - - name: Checkout lv_bindings - working-directory: ./user_modules/lv_binding_micropython - run: | - git fetch --force ${{ github.event.repository.html_url }} "+refs/heads/*:refs/remotes/origin/*" - git fetch --force ${{ github.event.repository.html_url }} "+refs/pull/*:refs/remotes/origin/pr/*" - git checkout ${{ github.sha }} || git checkout ${{ github.event.pull_request.head.sha }} - git submodule update --init --recursive - - name: Build mpy-cross - run: make -j $(nproc) -C mpy-cross - - name: Build the unix port - run: make -j $(nproc) -C ports/unix DEBUG=1 VARIANT=lvgl - - name: Run tests - run: | - export XDG_RUNTIME_DIR=/tmp - user_modules/lv_binding_micropython/tests/run.sh diff --git a/README.md b/README.md index 96f6deaf30..9fe2c2b603 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![Build lv_micropython unix port](https://github.com/lvgl/lv_binding_micropython/workflows/Build%20lv_micropython%20unix%20port/badge.svg) +[![MicroPython-LVGL CI](https://github.com/lvgl/lv_binding_micropython/actions/workflows/micropython_lvgl_ci.yml/badge.svg)](https://github.com/lvgl/lv_binding_micropython/actions/workflows/micropython_lvgl_ci.yml) # Bindings for LVGL diff --git a/examples/advanced_demo.py b/examples/advanced_demo.py index b40155fce4..2c177806f6 100644 --- a/examples/advanced_demo.py +++ b/examples/advanced_demo.py @@ -1,16 +1,19 @@ import usys as sys -sys.path.append('') # See: https://github.com/micropython/micropython/issues/6419 + +sys.path.append("") # See: https://github.com/micropython/micropython/issues/6419 # See: https://pymotw.com/2/sys/tracing.html + def mp_trace(frame, event, arg): co = frame.f_code func_name = co.co_name func_line_no = frame.f_lineno func_filename = co.co_filename - print('[%s] [%s] %s:%s' % (event, func_name, func_filename, func_line_no)) + print("[%s] [%s] %s:%s" % (event, func_name, func_filename, func_line_no)) return mp_trace + # sys.settrace(mp_trace) import lvgl as lv @@ -24,6 +27,7 @@ def mp_trace(frame, event, arg): # Styles ############################################################################## + class ColorStyle(lv.style_t): def __init__(self, color): super().__init__() @@ -34,6 +38,7 @@ def __init__(self, color): self.set_bg_main_stop(0) self.set_bg_grad_stop(128) + class ShadowStyle(lv.style_t): def __init__(self): super().__init__() @@ -44,6 +49,7 @@ def __init__(self): self.set_shadow_offset_y(3) self.set_shadow_spread(0) + # A square button with a shadow when not pressed class ButtonStyle(lv.style_t): def __init__(self): @@ -56,6 +62,7 @@ def __init__(self): self.set_shadow_offset_y(lv.dpx(10)) self.set_shadow_spread(0) + class ButtonPressedStyle(lv.style_t): def __init__(self): super().__init__() @@ -67,8 +74,8 @@ def __init__(self): # Themes ############################################################################## -class AdvancedDemoTheme(lv.theme_t): +class AdvancedDemoTheme(lv.theme_t): def __init__(self): super().__init__() self.button_style = ButtonStyle() @@ -85,16 +92,18 @@ def __init__(self): # Activate this theme on default display lv.display_get_default().set_theme(self) - + def apply(self, theme, obj): if obj.get_class() == lv.button_class: obj.add_style(self.button_style, lv.PART.MAIN) obj.add_style(self.button_pressed_style, lv.PART.MAIN | lv.STATE.PRESSED) + ############################################################################## member_name_cache = {} + def get_member_name(obj, value): try: return member_name_cache[id(obj)][id(value)] @@ -118,17 +127,21 @@ def __init__(self, parent, symbol, text): self.label = lv.label(self) self.label.set_text(text) self.set_flex_flow(lv.FLEX_FLOW.COLUMN) - self.set_flex_align(lv.FLEX_ALIGN.SPACE_EVENLY, lv.FLEX_ALIGN.CENTER, lv.FLEX_ALIGN.CENTER) + self.set_flex_align( + lv.FLEX_ALIGN.SPACE_EVENLY, lv.FLEX_ALIGN.CENTER, lv.FLEX_ALIGN.CENTER + ) class Page_Buttons: def __init__(self, app, page): self.app = app self.page = page - self.button_event_count = {'Play': 0, 'Pause': 0} + self.button_event_count = {"Play": 0, "Pause": 0} self.page.set_flex_flow(lv.FLEX_FLOW.ROW) - self.page.set_flex_align(lv.FLEX_ALIGN.SPACE_EVENLY, lv.FLEX_ALIGN.CENTER, lv.FLEX_ALIGN.START) + self.page.set_flex_align( + lv.FLEX_ALIGN.SPACE_EVENLY, lv.FLEX_ALIGN.CENTER, lv.FLEX_ALIGN.START + ) self.button1 = SymbolButton(page, lv.SYMBOL.PLAY, "Play") self.button1.set_size(80, 80) @@ -143,11 +156,19 @@ def __init__(self, app, page): def button_cb(event, name): self.button_event_count[name] += 1 event_name = get_member_name(lv.EVENT, event.code) - if all((not event_name.startswith(s)) for s in ['DRAW', 'GET', 'STYLE', 'REFR']): - self.label.set_text('[%d] %s %s' % (self.button_event_count[name], name, event_name)) + if all( + (not event_name.startswith(s)) for s in ["DRAW", "GET", "STYLE", "REFR"] + ): + self.label.set_text( + "[%d] %s %s" % (self.button_event_count[name], name, event_name) + ) - for button, name in [(self.button1, 'Play'), (self.button2, 'Pause')]: - button.add_event_cb(lambda event, button_name=name: button_cb(event, button_name), lv.EVENT.ALL, None) + for button, name in [(self.button1, "Play"), (self.button2, "Pause")]: + button.add_event_cb( + lambda event, button_name=name: button_cb(event, button_name), + lv.EVENT.ALL, + None, + ) class Page_Simple: @@ -157,7 +178,9 @@ def __init__(self, app, page): self.test_events = [] self.page.set_flex_flow(lv.FLEX_FLOW.COLUMN) - self.page.set_flex_align(lv.FLEX_ALIGN.SPACE_EVENLY, lv.FLEX_ALIGN.CENTER, lv.FLEX_ALIGN.CENTER) + self.page.set_flex_align( + lv.FLEX_ALIGN.SPACE_EVENLY, lv.FLEX_ALIGN.CENTER, lv.FLEX_ALIGN.CENTER + ) # slider self.slider = lv.slider(page) @@ -167,20 +190,24 @@ def __init__(self, app, page): self.on_slider_changed(None) # style selector - self.styles = [('Gray', ColorStyle(0xCCC)), - ('Red', ColorStyle(0xF00)), - ('Green',ColorStyle(0x0F0)), - ('Blue', ColorStyle(0x00F))] - + self.styles = [ + ("Gray", ColorStyle(0xCCC)), + ("Red", ColorStyle(0xF00)), + ("Green", ColorStyle(0x0F0)), + ("Blue", ColorStyle(0x00F)), + ] + self.style_selector = lv.dropdown(page) self.style_selector.add_style(ShadowStyle(), lv.PART.MAIN) self.style_selector.align(lv.ALIGN.OUT_BOTTOM_LEFT, 0, 40) - self.style_selector.set_options('\n'.join(x[0] for x in self.styles)) - self.style_selector.add_event_cb(self.on_style_selector_changed, lv.EVENT.VALUE_CHANGED, None) + self.style_selector.set_options("\n".join(x[0] for x in self.styles)) + self.style_selector.add_event_cb( + self.on_style_selector_changed, lv.EVENT.VALUE_CHANGED, None + ) # counter button self.counter_button = lv.button(page) - self.counter_button.set_size(80,80) + self.counter_button.set_size(80, 80) self.counter_label = lv.label(self.counter_button) self.counter_label.set_text("Count") self.counter_label.align(lv.ALIGN.CENTER, 0, 0) @@ -193,7 +220,8 @@ def on_slider_changed(self, event): def on_style_selector_changed(self, event): selected = self.style_selector.get_selected() tabview = self.app.screen_main.tabview - if hasattr(self, 'selected_style'): tabview.remove_style(self.selected_style, lv.PART.MAIN) + if hasattr(self, "selected_style"): + tabview.remove_style(self.selected_style, lv.PART.MAIN) self.selected_style = self.styles[selected][1] tabview.add_style(self.selected_style, lv.PART.MAIN) @@ -201,11 +229,22 @@ def on_counter_button(self, event): self.counter += 1 self.counter_label.set_text(str(self.counter)) + class Anim(lv.anim_t): - def __init__(self, obj, val, size, exec_cb, path_cb, time=500, playback=False, completed_cb=None): + def __init__( + self, + obj, + val, + size, + exec_cb, + path_cb, + time=500, + playback=False, + completed_cb=None, + ): super().__init__() self.init() - self.set_time(time) + self.set_duration(time) self.set_values(val, val + size) if callable(exec_cb): self.set_custom_exec_cb(exec_cb) @@ -217,7 +256,7 @@ def __init__(self, obj, val, size, exec_cb, path_cb, time=500, playback=False, c if completed_cb: self.set_completed_cb(completed_cb) self.start() - + class AnimatedChart(lv.chart): def __init__(self, parent, val, size): @@ -234,9 +273,9 @@ def anim_phase1(self): self, self.val, self.size, - lambda a, val: self.set_range(self.AXIS.PRIMARY_Y, 0, val), + lambda a, val: self.set_axis_range(self.AXIS.PRIMARY_Y, 0, val), lv.anim_t.path_ease_in, - completed_cb=lambda a:self.anim_phase2(), + completed_cb=lambda a: self.anim_phase2(), time=(self.max * self.factor) // 100, ) @@ -245,39 +284,50 @@ def anim_phase2(self): self, self.val + self.size, -self.size, - lambda a, val: self.set_range(self.AXIS.PRIMARY_Y, 0, val), + lambda a, val: self.set_axis_range(self.AXIS.PRIMARY_Y, 0, val), lv.anim_t.path_ease_out, - completed_cb=lambda a:self.anim_phase1(), + completed_cb=lambda a: self.anim_phase1(), time=(self.min * self.factor) // 100, ) + + class Page_Text: def __init__(self, app, page): self.app = app self.page = page self.page.set_flex_flow(lv.FLEX_FLOW.ROW) - self.page.set_flex_align(lv.FLEX_ALIGN.SPACE_EVENLY, lv.FLEX_ALIGN.CENTER, lv.FLEX_ALIGN.CENTER) + self.page.set_flex_align( + lv.FLEX_ALIGN.SPACE_EVENLY, lv.FLEX_ALIGN.CENTER, lv.FLEX_ALIGN.CENTER + ) self.ta = lv.textarea(self.page) self.ta.set_height(lv.pct(100)) self.ta.set_width(lv.pct(100)) + class Page_Chart: def __init__(self, app, page): self.app = app self.page = page self.page.set_flex_flow(lv.FLEX_FLOW.ROW) - self.page.set_flex_align(lv.FLEX_ALIGN.SPACE_EVENLY, lv.FLEX_ALIGN.CENTER, lv.FLEX_ALIGN.CENTER) + self.page.set_flex_align( + lv.FLEX_ALIGN.SPACE_EVENLY, lv.FLEX_ALIGN.CENTER, lv.FLEX_ALIGN.CENTER + ) self.page.set_style_pad_all(10, lv.PART.MAIN) self.page.set_style_pad_gap(10, lv.PART.MAIN) self.chart = AnimatedChart(page, 100, 1000) self.chart.set_flex_grow(1) self.chart.set_height(lv.pct(100)) - self.series1 = self.chart.add_series(lv.color_hex(0xFF0000), self.chart.AXIS.PRIMARY_Y) + self.series1 = self.chart.add_series( + lv.color_hex(0xFF0000), self.chart.AXIS.PRIMARY_Y + ) self.chart.set_type(self.chart.TYPE.LINE) self.chart.set_style_line_width(3, lv.PART.ITEMS) self.chart.add_style(ColorStyle(0x055), lv.PART.ITEMS) - self.chart.set_range(self.chart.AXIS.PRIMARY_Y, 0, 100) + self.chart.set_axis_range(self.chart.AXIS.PRIMARY_Y, 0, 100) self.chart.set_point_count(10) - self.chart.set_ext_y_array(self.series1, [10, 20, 30, 20, 10, 40, 50, 90, 95, 90]) + self.chart.set_series_ext_y_array( + self.series1, [10, 20, 30, 20, 10, 40, 50, 90, 95, 90] + ) # self.chart.set_x_tick_texts("a\nb\nc\nd\ne", 2, lv.chart.AXIS.DRAW_LAST_TICK) # self.chart.set_x_tick_length(10, 5) # self.chart.set_y_tick_texts("1\n2\n3\n4\n5", 2, lv.chart.AXIS.DRAW_LAST_TICK) @@ -295,6 +345,7 @@ def on_slider_changed(event): self.slider.set_value(self.chart.factor, 0) self.slider.add_event_cb(on_slider_changed, lv.EVENT.VALUE_CHANGED, None) + class Screen_Main(lv.obj): def __init__(self, app, *args, **kwds): self.app = app @@ -319,16 +370,16 @@ def init_gui_SDL(self): self.mouse = lv.sdl_mouse_create() self.keyboard = lv.sdl_keyboard_create() self.keyboard.set_group(self.group) - - def init_gui_esp32(self): + def init_gui_esp32(self): # Initialize ILI9341 display from ili9XXX import ili9341 # self.disp = ili9341(dc=32, cs=33, power=-1, backlight=-1) - self.disp = ili9341(mhz=20, dc=32, cs=33, power=-1, backlight=-1, hybrid=False, factor=8) - + self.disp = ili9341( + mhz=20, dc=32, cs=33, power=-1, backlight=-1, hybrid=False, factor=8 + ) # Register raw resistive touch driver @@ -357,7 +408,7 @@ 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) @@ -375,36 +426,46 @@ def init_gui_stm32(self): def init_gui_rp2(self): import xpt2046 import st77xx - if sys.platform!='rp2': raise ImportError('Only works on the rp2 platform.') - print('Using RP2 GUI') - spi=machine.SPI( + + if sys.platform != "rp2": + raise ImportError("Only works on the rp2 platform.") + print("Using RP2 GUI") + spi = machine.SPI( 1, baudrate=24_000_000, polarity=0, phase=0, - sck=machine.Pin(10,machine.Pin.OUT), - mosi=machine.Pin(11,machine.Pin.OUT), - miso=machine.Pin(12,machine.Pin.IN) + sck=machine.Pin(10, machine.Pin.OUT), + mosi=machine.Pin(11, machine.Pin.OUT), + miso=machine.Pin(12, machine.Pin.IN), + ) + self.disp = st77xx.St7789( + rot=st77xx.ST77XX_INV_LANDSCAPE, + res=(240, 320), + spi=spi, + cs=9, + dc=8, + bl=13, + rst=15, + rp2_dma=None, ) - self.disp=st77xx.St7789(rot=st77xx.ST77XX_INV_LANDSCAPE,res=(240,320),spi=spi,cs=9,dc=8,bl=13,rst=15,rp2_dma=None) self.disp.set_backlight(100) - self.touch=xpt2046.Xpt2046(spi=spi,cs=16,rot=xpt2046.XPT2046_INV_LANDSCAPE) + self.touch = xpt2046.Xpt2046(spi=spi, cs=16, rot=xpt2046.XPT2046_INV_LANDSCAPE) def init_gui(self): - self.group = lv.group_create() self.group.set_default() # Identify platform and initialize it if not event_loop.is_running(): - if sys.platform == 'rp2': + if sys.platform == "rp2": self.init_gui_rp2() - elif sys.platform == 'esp32': + elif sys.platform == "esp32": self.init_gui_esp32() - elif sys.platform == 'linux': + elif sys.platform == "linux": self.init_gui_SDL() - elif sys.platform == 'stm32': + elif sys.platform == "stm32": self.init_gui_stm32() # Create the main screen and load it. @@ -419,4 +480,3 @@ def init_gui(self): # if __name__ == '__main__': # while True: # pass - diff --git a/ports/stm32/lv_conf_stm32.h b/ports/stm32/lv_conf_stm32.h new file mode 100644 index 0000000000..673d4cce9e --- /dev/null +++ b/ports/stm32/lv_conf_stm32.h @@ -0,0 +1,1140 @@ +/** + * @file lv_conf.h + * Configuration file for v9.1.0 + */ + +/* + * Copy this file as `lv_conf.h` + * 1. simply next to the `lvgl` folder + * 2. or any other places and + * - define `LV_CONF_INCLUDE_SIMPLE` + * - add the path as include path + */ + +/* clang-format off */ +#if 1 /*Set it to "1" to enable content*/ + +#ifndef LV_CONF_H +#define LV_CONF_H + +/*If you need to include anything here, do it inside the `__ASSEMBLY__` guard */ +#if 0 && defined(__ASSEMBLY__) +#include "my_include.h" +#endif + +/*==================== + COLOR SETTINGS + *====================*/ + +/*Color depth: 8 (A8), 16 (RGB565), 24 (RGB888), 32 (XRGB8888)*/ +#define LV_COLOR_DEPTH 16 + +/*========================= + STDLIB WRAPPER SETTINGS + *=========================*/ + +/* Possible values + * - LV_STDLIB_BUILTIN: LVGL's built in implementation + * - LV_STDLIB_CLIB: Standard C functions, like malloc, strlen, etc + * - LV_STDLIB_MICROPYTHON: MicroPython implementation + * - LV_STDLIB_RTTHREAD: RT-Thread implementation + * - LV_STDLIB_CUSTOM: Implement the functions externally + */ +#define LV_USE_STDLIB_MALLOC LV_STDLIB_MICROPYTHON +#define LV_USE_STDLIB_STRING LV_STDLIB_BUILTIN +#define LV_USE_STDLIB_SPRINTF LV_STDLIB_BUILTIN + +#define LV_STDINT_INCLUDE +#define LV_STDDEF_INCLUDE +#define LV_STDBOOL_INCLUDE +#define LV_INTTYPES_INCLUDE +#define LV_LIMITS_INCLUDE +#define LV_STDARG_INCLUDE + +#if LV_USE_STDLIB_MALLOC == LV_STDLIB_BUILTIN + /*Size of the memory available for `lv_malloc()` in bytes (>= 2kB)*/ + #define LV_MEM_SIZE (64 * 1024U) /*[bytes]*/ + + /*Size of the memory expand for `lv_malloc()` in bytes*/ + #define LV_MEM_POOL_EXPAND_SIZE 0 + + /*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/ + #define LV_MEM_ADR 0 /*0: unused*/ + /*Instead of an address give a memory allocator that will be called to get a memory pool for LVGL. E.g. my_malloc*/ + #if LV_MEM_ADR == 0 + #undef LV_MEM_POOL_INCLUDE + #undef LV_MEM_POOL_ALLOC + #endif +#endif /*LV_USE_STDLIB_MALLOC == LV_STDLIB_BUILTIN*/ + +/*==================== + HAL SETTINGS + *====================*/ + +/*Default display refresh, input device read and animation step period.*/ +#define LV_DEF_REFR_PERIOD 33 /*[ms]*/ + +/*Default Dot Per Inch. Used to initialize default sizes such as widgets sized, style paddings. + *(Not so important, you can adjust it to modify default sizes and spaces)*/ +#define LV_DPI_DEF 130 /*[px/inch]*/ + +/*================= + * OPERATING SYSTEM + *=================*/ +/*Select an operating system to use. Possible options: + * - LV_OS_NONE + * - LV_OS_PTHREAD + * - LV_OS_FREERTOS + * - LV_OS_CMSIS_RTOS2 + * - LV_OS_RTTHREAD + * - LV_OS_WINDOWS + * - LV_OS_CUSTOM */ +#define LV_USE_OS LV_OS_NONE + +#if LV_USE_OS == LV_OS_CUSTOM + #define LV_OS_CUSTOM_INCLUDE +#endif + +/*======================== + * RENDERING CONFIGURATION + *========================*/ + +/*Align the stride of all layers and images to this bytes*/ +#define LV_DRAW_BUF_STRIDE_ALIGN 1 + +/*Align the start address of draw_buf addresses to this bytes*/ +#define LV_DRAW_BUF_ALIGN 4 + +/* If a widget has `style_opa < 255` (not `bg_opa`, `text_opa` etc) or not NORMAL blend mode + * it is buffered into a "simple" layer before rendering. The widget can be buffered in smaller chunks. + * "Transformed layers" (if `transform_angle/zoom` are set) use larger buffers + * and can't be drawn in chunks. */ + +/*The target buffer size for simple layer chunks.*/ +#define LV_DRAW_LAYER_SIMPLE_BUF_SIZE (24 * 1024) /*[bytes]*/ + +#define LV_USE_DRAW_SW 1 +#if LV_USE_DRAW_SW == 1 + + /* + * Selectively disable color format support in order to reduce code size. + * NOTE: some features use certain color formats internally, e.g. + * - gradients use RGB888 + * - bitmaps with transparency may use ARGB8888 + */ + #define LV_DRAW_SW_SUPPORT_RGB565 1 + #define LV_DRAW_SW_SUPPORT_RGB565A8 0 + #define LV_DRAW_SW_SUPPORT_RGB888 1 + #define LV_DRAW_SW_SUPPORT_XRGB8888 0 + #define LV_DRAW_SW_SUPPORT_ARGB8888 1 + #define LV_DRAW_SW_SUPPORT_ARGB8888_PREMULTIPLIED 0 + #define LV_DRAW_SW_SUPPORT_L8 0 + #define LV_DRAW_SW_SUPPORT_AL88 0 + #define LV_DRAW_SW_SUPPORT_A8 0 + #define LV_DRAW_SW_SUPPORT_I1 1 + + /* The threshold of the luminance to consider a pixel as + * active in indexed color format */ + #define LV_DRAW_SW_I1_LUM_THRESHOLD 127 + /* Set the number of draw unit. + * > 1 requires an operating system enabled in `LV_USE_OS` + * > 1 means multiply threads will render the screen in parallel */ + #define LV_DRAW_SW_DRAW_UNIT_CNT 1 + + /* Use Arm-2D to accelerate the sw render */ + #define LV_USE_DRAW_ARM2D_SYNC 0 + + /* Enable native helium assembly to be compiled */ + #define LV_USE_NATIVE_HELIUM_ASM 0 + + /* 0: use a simple renderer capable of drawing only simple rectangles with gradient, images, texts, and straight lines only + * 1: use a complex renderer capable of drawing rounded corners, shadow, skew lines, and arcs too */ + #define LV_DRAW_SW_COMPLEX 1 + + #if LV_DRAW_SW_COMPLEX == 1 + /*Allow buffering some shadow calculation. + *LV_DRAW_SW_SHADOW_CACHE_SIZE is the max. shadow size to buffer, where shadow size is `shadow_width + radius` + *Caching has LV_DRAW_SW_SHADOW_CACHE_SIZE^2 RAM cost*/ + #define LV_DRAW_SW_SHADOW_CACHE_SIZE 0 + + /* Set number of maximally cached circle data. + * The circumference of 1/4 circle are saved for anti-aliasing + * radius * 4 bytes are used per circle (the most often used radiuses are saved) + * 0: to disable caching */ + #define LV_DRAW_SW_CIRCLE_CACHE_SIZE 4 + #endif + + #define LV_USE_DRAW_SW_ASM LV_DRAW_SW_ASM_NONE + + #if LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_CUSTOM + #define LV_DRAW_SW_ASM_CUSTOM_INCLUDE "" + #endif +#endif + +/* Use NXP's VG-Lite GPU on iMX RTxxx platforms. */ +#define LV_USE_DRAW_VGLITE 0 + +#if LV_USE_DRAW_VGLITE + /* Enable blit quality degradation workaround recommended for screen's dimension > 352 pixels. */ + #define LV_USE_VGLITE_BLIT_SPLIT 0 + + #if LV_USE_OS + /* Enable VGLite draw async. Queue multiple tasks and flash them once to the GPU. */ + #define LV_USE_VGLITE_DRAW_ASYNC 1 + #endif + + /* Enable VGLite asserts. */ + #define LV_USE_VGLITE_ASSERT 0 +#endif + +/* Use NXP's PXP on iMX RTxxx platforms. */ +#define LV_USE_DRAW_PXP 0 + +#if LV_USE_DRAW_PXP + /* Enable PXP asserts. */ + #define LV_USE_PXP_ASSERT 0 +#endif + +/* Use Renesas Dave2D on RA platforms. */ +#define LV_USE_DRAW_DAVE2D 0 + +/* Draw using cached SDL textures*/ +#define LV_USE_DRAW_SDL 0 + +/* Use VG-Lite GPU. */ +#define LV_USE_DRAW_VG_LITE 0 + +#if LV_USE_DRAW_VG_LITE +/* Enable VG-Lite custom external 'gpu_init()' function */ +#define LV_VG_LITE_USE_GPU_INIT 0 + +/* Enable VG-Lite assert. */ +#define LV_VG_LITE_USE_ASSERT 0 + +/* VG-Lite flush commit trigger threshold. GPU will try to batch these many draw tasks. */ +#define LV_VG_LITE_FLUSH_MAX_COUNT 8 + +/* Enable border to simulate shadow + * NOTE: which usually improves performance, + * but does not guarantee the same rendering quality as the software. */ +#define LV_VG_LITE_USE_BOX_SHADOW 0 + +/* VG-Lite linear gradient image maximum cache number. + * NOTE: The memory usage of a single gradient image is 4K bytes. + */ +#define LV_VG_LITE_LINEAER_GRAD_CACHE_CNT 32 + +/* VG-Lite radial gradient image maximum cache size. + * NOTE: The memory usage of a single gradient image is radial grad radius * 4 bytes. + */ +#define LV_VG_LITE_RADIAL_GRAD_CACHE_CNT 32 + +#endif + +/*======================= + * FEATURE CONFIGURATION + *=======================*/ + +/*------------- + * Logging + *-----------*/ + +/*Enable the log module*/ +#ifdef MICROPY_LV_USE_LOG + #define LV_USE_LOG MICROPY_LV_USE_LOG +#else + #define LV_USE_LOG 0 +#endif + +#if LV_USE_LOG + + /*How important log should be added: + *LV_LOG_LEVEL_TRACE A lot of logs to give detailed information + *LV_LOG_LEVEL_INFO Log important events + *LV_LOG_LEVEL_WARN Log if something unwanted happened but didn't cause a problem + *LV_LOG_LEVEL_ERROR Only critical issue, when the system may fail + *LV_LOG_LEVEL_USER Only logs added by the user + *LV_LOG_LEVEL_NONE Do not log anything*/ + #define LV_LOG_LEVEL LV_LOG_LEVEL_WARN + + /*1: Print the log with 'printf'; + *0: User need to register a callback with `lv_log_register_print_cb()`*/ + #define LV_LOG_PRINTF 0 + + /*1: Enable print timestamp; + *0: Disable print timestamp*/ + #define LV_LOG_USE_TIMESTAMP 1 + + /*1: Print file and line number of the log; + *0: Do not print file and line number of the log*/ + #define LV_LOG_USE_FILE_LINE 1 + + /*Enable/disable LV_LOG_TRACE in modules that produces a huge number of logs*/ + #define LV_LOG_TRACE_MEM 1 + #define LV_LOG_TRACE_TIMER 1 + #define LV_LOG_TRACE_INDEV 1 + #define LV_LOG_TRACE_DISP_REFR 1 + #define LV_LOG_TRACE_EVENT 1 + #define LV_LOG_TRACE_OBJ_CREATE 1 + #define LV_LOG_TRACE_LAYOUT 1 + #define LV_LOG_TRACE_ANIM 1 + #define LV_LOG_TRACE_CACHE 1 + +#endif /*LV_USE_LOG*/ + +/*------------- + * Asserts + *-----------*/ + +/*Enable asserts if an operation is failed or an invalid data is found. + *If LV_USE_LOG is enabled an error message will be printed on failure*/ +#define LV_USE_ASSERT_NULL 1 /*Check if the parameter is NULL. (Very fast, recommended)*/ +#define LV_USE_ASSERT_MALLOC 1 /*Checks is the memory is successfully allocated or no. (Very fast, recommended)*/ +#define LV_USE_ASSERT_STYLE 0 /*Check if the styles are properly initialized. (Very fast, recommended)*/ +#define LV_USE_ASSERT_MEM_INTEGRITY 0 /*Check the integrity of `lv_mem` after critical operations. (Slow)*/ +#define LV_USE_ASSERT_OBJ 0 /*Check the object's type and existence (e.g. not deleted). (Slow)*/ + +/*Add a custom handler when assert happens e.g. to restart the MCU*/ +#define LV_ASSERT_HANDLER_INCLUDE +#define LV_ASSERT_HANDLER while(1); /*Halt by default*/ + +/*------------- + * Debug + *-----------*/ + +/*1: Draw random colored rectangles over the redrawn areas*/ +#define LV_USE_REFR_DEBUG 0 + +/*1: Draw a red overlay for ARGB layers and a green overlay for RGB layers*/ +#define LV_USE_LAYER_DEBUG 0 + +/*1: Draw overlays with different colors for each draw_unit's tasks. + *Also add the index number of the draw unit on white background. + *For layers add the index number of the draw unit on black background.*/ +#define LV_USE_PARALLEL_DRAW_DEBUG 0 + +/*------------- + * Others + *-----------*/ +/* PRIVATE API */ + +#define LV_USE_PRIVATE_API 1 + +/*Garbage Collector settings + *Used if LVGL is bound to higher level language and the memory is managed by that language*/ +extern void mp_lv_init_gc(); +extern void mp_lv_deinit_gc(); +#define LV_GC_INIT() mp_lv_init_gc() +#define LV_GC_DEINIT() mp_lv_deinit_gc() + +extern void lv_deinit(); +#define MICROPY_PORT_DEINIT_FUNC lv_deinit() + +#define LV_ENABLE_GLOBAL_CUSTOM 1 +#if LV_ENABLE_GLOBAL_CUSTOM + extern void *mp_lv_roots; + #define LV_GLOBAL_CUSTOM() ((lv_global_t*)mp_lv_roots) +#endif + +/*Default cache size in bytes. + *Used by image decoders such as `lv_lodepng` to keep the decoded image in the memory. + *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 +#else + #define LV_CACHE_DEF_SIZE 0 +#endif + +/*Default number of image header cache entries. The cache is used to store the headers of images + *The main logic is like `LV_CACHE_DEF_SIZE` but for image headers.*/ +#ifdef MICROPY_IMAGE_HEADER_CACHE_COUNT + #define LV_IMAGE_HEADER_CACHE_DEF_CNT MICROPY_IMAGE_HEADER_CACHE_COUNT +#else + #define LV_IMAGE_HEADER_CACHE_DEF_CNT 32 +#endif + +/*Number of stops allowed per gradient. Increase this to allow more stops. + *This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/ +#define LV_GRADIENT_MAX_STOPS 2 + +/* Adjust color mix functions rounding. GPUs might calculate color mix (blending) differently. + * 0: round down, 64: round up from x.75, 128: round up from half, 192: round up from x.25, 254: round up */ +#define LV_COLOR_MIX_ROUND_OFS 0 + +/* Add 2 x 32 bit variables to each lv_obj_t to speed up getting style properties */ +#define LV_OBJ_STYLE_CACHE 1 + +/* Add `id` field to `lv_obj_t` */ +#define LV_USE_OBJ_ID 0 + +/* Use lvgl builtin method for obj ID */ +#define LV_USE_OBJ_ID_BUILTIN 0 + +/*Use obj property set/get API*/ +#define LV_USE_OBJ_PROPERTY 0 + +/* VG-Lite Simulator */ +/*Requires: LV_USE_THORVG_INTERNAL or LV_USE_THORVG_EXTERNAL */ +#define LV_USE_VG_LITE_THORVG 0 + +#if LV_USE_VG_LITE_THORVG + + /*Enable LVGL's blend mode support*/ + #define LV_VG_LITE_THORVG_LVGL_BLEND_SUPPORT 0 + + /*Enable YUV color format support*/ + #define LV_VG_LITE_THORVG_YUV_SUPPORT 0 + + /*Enable 16 pixels alignment*/ + #define LV_VG_LITE_THORVG_16PIXELS_ALIGN 1 + + /*Buffer address alignment*/ + #define LV_VG_LITE_THORVG_BUF_ADDR_ALIGN 64 + + /*Enable multi-thread render*/ + #define LV_VG_LITE_THORVG_THREAD_RENDER 0 + +#endif + +/* Enable the multi-touch gesture recognition feature */ +/* Gesture recognition requires the use of floats */ +#define LV_USE_GESTURE_RECOGNITION 0 +/*===================== + * COMPILER SETTINGS + *====================*/ + +/*For big endian systems set to 1*/ +#define LV_BIG_ENDIAN_SYSTEM 0 + +/*Define a custom attribute to `lv_tick_inc` function*/ +#define LV_ATTRIBUTE_TICK_INC + +/*Define a custom attribute to `lv_timer_handler` function*/ +#define LV_ATTRIBUTE_TIMER_HANDLER + +/*Define a custom attribute to `lv_display_flush_ready` function*/ +#define LV_ATTRIBUTE_FLUSH_READY + +/*Required alignment size for buffers*/ +#define LV_ATTRIBUTE_MEM_ALIGN_SIZE 1 + +/*Will be added where memories needs to be aligned (with -Os data might not be aligned to boundary by default). + * E.g. __attribute__((aligned(4)))*/ +#define LV_ATTRIBUTE_MEM_ALIGN + +/*Attribute to mark large constant arrays for example font's bitmaps*/ +#define LV_ATTRIBUTE_LARGE_CONST + +/*Compiler prefix for a big array declaration in RAM*/ +#define LV_ATTRIBUTE_LARGE_RAM_ARRAY + +/*Place performance critical functions into a faster memory (e.g RAM)*/ +#define LV_ATTRIBUTE_FAST_MEM + +/*Export integer constant to binding. This macro is used with constants in the form of LV_ that + *should also appear on LVGL binding API such as Micropython.*/ +#define LV_EXPORT_CONST_INT(int_value) enum {ENUM_##int_value = int_value} + +/*Prefix all global extern data with this*/ +#define LV_ATTRIBUTE_EXTERN_DATA + +/* Use `float` as `lv_value_precise_t` */ +#define LV_USE_FLOAT 0 + +/** Enable matrix support + * - Requires `LV_USE_FLOAT = 1` */ +#define LV_USE_MATRIX 0 + +/*================== + * FONT USAGE + *===================*/ + +/*Montserrat fonts with ASCII range and some symbols using bpp = 4 + *https://fonts.google.com/specimen/Montserrat*/ +#define LV_FONT_MONTSERRAT_8 0 +#define LV_FONT_MONTSERRAT_10 0 +#define LV_FONT_MONTSERRAT_12 0 +#define LV_FONT_MONTSERRAT_14 1 +#define LV_FONT_MONTSERRAT_16 1 +#define LV_FONT_MONTSERRAT_18 0 +#define LV_FONT_MONTSERRAT_20 0 +#define LV_FONT_MONTSERRAT_22 0 +#define LV_FONT_MONTSERRAT_24 1 +#define LV_FONT_MONTSERRAT_26 0 +#define LV_FONT_MONTSERRAT_28 0 +#define LV_FONT_MONTSERRAT_30 0 +#define LV_FONT_MONTSERRAT_32 0 +#define LV_FONT_MONTSERRAT_34 0 +#define LV_FONT_MONTSERRAT_36 0 +#define LV_FONT_MONTSERRAT_38 0 +#define LV_FONT_MONTSERRAT_40 0 +#define LV_FONT_MONTSERRAT_42 0 +#define LV_FONT_MONTSERRAT_44 0 +#define LV_FONT_MONTSERRAT_46 0 +#define LV_FONT_MONTSERRAT_48 0 + +/*Demonstrate special features*/ +#define LV_FONT_MONTSERRAT_28_COMPRESSED 0 /*bpp = 3*/ +#define LV_FONT_DEJAVU_16_PERSIAN_HEBREW 0 /*Hebrew, Arabic, Persian letters and all their forms*/ + +#define LV_FONT_SIMSUN_14_CJK 0 /**< 1000 most common CJK radicals */ +#define LV_FONT_SIMSUN_16_CJK 0 /**< 1000 most common CJK radicals */ +#define LV_FONT_SOURCE_HAN_SANS_SC_14_CJK 0 /**< 1338 most common CJK radicals */ +#define LV_FONT_SOURCE_HAN_SANS_SC_16_CJK 0 /**< 1338 most common CJK radicals */ +/*Pixel perfect monospace fonts*/ +#define LV_FONT_UNSCII_8 0 +#define LV_FONT_UNSCII_16 0 + +/*Optionally declare custom fonts here. + *You can use these fonts as default font too and they will be available globally. + *E.g. #define LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(my_font_1) LV_FONT_DECLARE(my_font_2)*/ +#define LV_FONT_CUSTOM_DECLARE + +/*Always set a default font*/ +#define LV_FONT_DEFAULT &lv_font_montserrat_14 + +/*Enable handling large font and/or fonts with a lot of characters. + *The limit depends on the font size, font face and bpp. + *Compiler error will be triggered if a font needs it.*/ +#define LV_FONT_FMT_TXT_LARGE 0 + +/*Enables/disables support for compressed fonts.*/ +#define LV_USE_FONT_COMPRESSED 0 + +/*Enable drawing placeholders when glyph dsc is not found*/ +#define LV_USE_FONT_PLACEHOLDER 1 + +/*================= + * TEXT SETTINGS + *=================*/ + +/** + * Select a character encoding for strings. + * Your IDE or editor should have the same character encoding + * - LV_TXT_ENC_UTF8 + * - LV_TXT_ENC_ASCII + */ +#define LV_TXT_ENC LV_TXT_ENC_UTF8 + +/*Can break (wrap) texts on these chars*/ +#define LV_TXT_BREAK_CHARS " ,.;:-_)]}" + +/*If a word is at least this long, will break wherever "prettiest" + *To disable, set to a value <= 0*/ +#define LV_TXT_LINE_BREAK_LONG_LEN 0 + +/*Minimum number of characters in a long word to put on a line before a break. + *Depends on LV_TXT_LINE_BREAK_LONG_LEN.*/ +#define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3 + +/*Minimum number of characters in a long word to put on a line after a break. + *Depends on LV_TXT_LINE_BREAK_LONG_LEN.*/ +#define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3 + +/*Support bidirectional texts. Allows mixing Left-to-Right and Right-to-Left texts. + *The direction will be processed according to the Unicode Bidirectional Algorithm: + *https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/ +#define LV_USE_BIDI 0 +#if LV_USE_BIDI + /*Set the default direction. Supported values: + *`LV_BASE_DIR_LTR` Left-to-Right + *`LV_BASE_DIR_RTL` Right-to-Left + *`LV_BASE_DIR_AUTO` detect texts base direction*/ + #define LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_AUTO +#endif + +/*Enable Arabic/Persian processing + *In these languages characters should be replaced with an other form based on their position in the text*/ +#define LV_USE_ARABIC_PERSIAN_CHARS 0 + +/*================== + * WIDGETS + *================*/ + +/*Documentation of the widgets: https://docs.lvgl.io/latest/en/html/widgets/index.html*/ + +#define LV_WIDGETS_HAS_DEFAULT_VALUE 0 + +#define LV_USE_ANIMIMG 0 + +#define LV_USE_ARC 1 + +#define LV_USE_BAR 1 + +#define LV_USE_BUTTON 1 + +#define LV_USE_BUTTONMATRIX 1 + +#define LV_USE_CALENDAR 0 +#if LV_USE_CALENDAR + #define LV_CALENDAR_WEEK_STARTS_MONDAY 0 + #if LV_CALENDAR_WEEK_STARTS_MONDAY + #define LV_CALENDAR_DEFAULT_DAY_NAMES {"Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"} + #else + #define LV_CALENDAR_DEFAULT_DAY_NAMES {"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"} + #endif + + #define LV_CALENDAR_DEFAULT_MONTH_NAMES {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"} + #define LV_USE_CALENDAR_HEADER_ARROW 1 + #define LV_USE_CALENDAR_HEADER_DROPDOWN 1 +#endif /*LV_USE_CALENDAR*/ + +#define LV_USE_CANVAS 0 + +#define LV_USE_CHART 1 + +#define LV_USE_CHECKBOX 1 + +#define LV_USE_DROPDOWN 1 /*Requires: lv_label*/ + +#define LV_USE_IMAGE 1 /*Requires: lv_label*/ + +#define LV_USE_IMAGEBUTTON 1 + +#define LV_USE_KEYBOARD 0 + +#define LV_USE_LABEL 1 +#if LV_USE_LABEL + #define LV_LABEL_TEXT_SELECTION 1 /*Enable selecting text of the label*/ + #define LV_LABEL_LONG_TXT_HINT 1 /*Store some extra info in labels to speed up drawing of very long texts*/ + #define LV_LABEL_WAIT_CHAR_COUNT 3 /*The count of wait chart*/ +#endif + +#define LV_USE_LED 1 + +#define LV_USE_LINE 1 + +#define LV_USE_LIST 1 + +#define LV_USE_LOTTIE 0 /**< Requires: lv_canvas, thorvg */ + +#define LV_USE_MENU 1 + +#define LV_USE_MSGBOX 1 + +#define LV_USE_ROLLER 1 /*Requires: lv_label*/ + +#define LV_USE_SCALE 1 + +#define LV_USE_SLIDER 1 /*Requires: lv_bar*/ + +#define LV_USE_SPAN 1 +#if LV_USE_SPAN + /*A line text can contain maximum num of span descriptor */ + #define LV_SPAN_SNIPPET_STACK_SIZE 64 +#endif + +#define LV_USE_SPINBOX 1 + +#define LV_USE_SPINNER 1 + +#define LV_USE_SWITCH 1 + +#define LV_USE_TEXTAREA 1 /*Requires: lv_label*/ +#if LV_USE_TEXTAREA != 0 + #define LV_TEXTAREA_DEF_PWD_SHOW_TIME 1500 /*ms*/ +#endif + +#define LV_USE_TABLE 1 + +#define LV_USE_TABVIEW 0 + +#define LV_USE_TILEVIEW 1 + +#define LV_USE_WIN 0 + +#define LV_USE_3DTEXTURE 0 + +/*================== + * THEMES + *==================*/ + +/*A simple, impressive and very complete theme*/ +#define LV_USE_THEME_DEFAULT 1 +#if LV_USE_THEME_DEFAULT + + /*0: Light mode; 1: Dark mode*/ + #define LV_THEME_DEFAULT_DARK 0 + + /*1: Enable grow on press*/ + #define LV_THEME_DEFAULT_GROW 1 + + /*Default transition time in [ms]*/ + #define LV_THEME_DEFAULT_TRANSITION_TIME 80 +#endif /*LV_USE_THEME_DEFAULT*/ + +/*A very simple theme that is a good starting point for a custom theme*/ +#define LV_USE_THEME_SIMPLE 0 + +/*A theme designed for monochrome displays*/ +#define LV_USE_THEME_MONO 0 + +/*================== + * LAYOUTS + *==================*/ + +/*A layout similar to Flexbox in CSS.*/ +#define LV_USE_FLEX 1 + +/*A layout similar to Grid in CSS.*/ +#define LV_USE_GRID 1 + +/*==================== + * 3RD PARTS LIBRARIES + *====================*/ + +/*File system interfaces for common APIs */ + +/*API for fopen, fread, etc*/ +#define LV_USE_FS_STDIO 0 +#if LV_USE_FS_STDIO + #define LV_FS_STDIO_LETTER 'A' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ + #define LV_FS_STDIO_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/ + #define LV_FS_STDIO_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ +#endif + +/*API for open, read, etc*/ +#define LV_USE_FS_POSIX 0 +#if LV_USE_FS_POSIX + #define LV_FS_POSIX_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ + #define LV_FS_POSIX_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/ + #define LV_FS_POSIX_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ +#endif + +/*API for CreateFile, ReadFile, etc*/ +#define LV_USE_FS_WIN32 0 +#if LV_USE_FS_WIN32 + #define LV_FS_WIN32_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ + #define LV_FS_WIN32_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/ + #define LV_FS_WIN32_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ +#endif + +/*API for FATFS (needs to be added separately). Uses f_open, f_read, etc*/ +#define LV_USE_FS_FATFS 0 +#if LV_USE_FS_FATFS + #define LV_FS_FATFS_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ + #define LV_FS_FATFS_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ +#endif + +/*API for memory-mapped file access. */ +#define LV_USE_FS_MEMFS 0 +#if LV_USE_FS_MEMFS + #define LV_FS_MEMFS_LETTER 'M' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ +#endif + +/*API for LittleFs. */ +#define LV_USE_FS_LITTLEFS 0 +#if LV_USE_FS_LITTLEFS + #define LV_FS_LITTLEFS_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ +#endif + +/*API for Arduino LittleFs. */ +#define LV_USE_FS_ARDUINO_ESP_LITTLEFS 0 +#if LV_USE_FS_ARDUINO_ESP_LITTLEFS + #define LV_FS_ARDUINO_ESP_LITTLEFS_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ +#endif + +/*LODEPNG decoder library*/ +#define LV_USE_LODEPNG 0 + +/*PNG decoder(libpng) library*/ +#define LV_USE_LIBPNG 0 + +/*BMP decoder library*/ +#define LV_USE_BMP 0 + +/* JPG + split JPG decoder library. + * Split JPG is a custom format optimized for embedded systems. */ +#define LV_USE_TJPGD 0 + +/* libjpeg-turbo decoder library. + * Supports complete JPEG specifications and high-performance JPEG decoding. */ +#define LV_USE_LIBJPEG_TURBO 0 + +/*GIF decoder library*/ +#define LV_USE_GIF 0 +#if LV_USE_GIF +/*GIF decoder accelerate*/ +#define LV_GIF_CACHE_DECODE_DATA 0 +#endif + +/*Decode bin images to RAM*/ +#define LV_BIN_DECODER_RAM_LOAD 0 + +/*RLE decompress library*/ +#define LV_USE_RLE 0 + +/*QR code library*/ +#define LV_USE_QRCODE 0 + +/*Barcode code library*/ +#define LV_USE_BARCODE 0 + +/*FreeType library*/ +#ifdef MICROPY_FREETYPE + #define LV_USE_FREETYPE MICROPY_FREETYPE +#else + #define LV_USE_FREETYPE 0 +#endif +#if LV_USE_FREETYPE + /*Let FreeType to use LVGL memory and file porting*/ + #define LV_FREETYPE_USE_LVGL_PORT 0 + + /*Cache count of the glyphs in FreeType. It means the number of glyphs that can be cached. + *The higher the value, the more memory will be used.*/ + #define LV_FREETYPE_CACHE_FT_GLYPH_CNT 256 +#endif + +/* Built-in TTF decoder */ +#ifndef LV_USE_TINY_TTF + #define LV_USE_TINY_TTF 0 +#endif +#if LV_USE_TINY_TTF + /* Enable loading TTF data from files */ + #define LV_TINY_TTF_FILE_SUPPORT 0 +#endif + +/*Rlottie library*/ +#ifdef MICROPY_RLOTTIE + #define LV_USE_RLOTTIE MICROPY_RLOTTIE +#else + #define LV_USE_RLOTTIE 0 +#endif + +/*Enable Vector Graphic APIs*/ +#define LV_USE_VECTOR_GRAPHIC 0 + +/* Enable ThorVG (vector graphics library) from the src/libs folder */ +#define LV_USE_THORVG_INTERNAL 0 + +/* Enable ThorVG by assuming that its installed and linked to the project */ +#define LV_USE_THORVG_EXTERNAL 0 + +/*Use lvgl built-in LZ4 lib*/ +#define LV_USE_LZ4_INTERNAL 0 + +/*Use external LZ4 library*/ +#define LV_USE_LZ4_EXTERNAL 0 + +/*FFmpeg library for image decoding and playing videos + *Supports all major image formats so do not enable other image decoder with it*/ +#ifdef MICROPY_FFMPEG + #define LV_USE_FFMPEG MICROPY_FFMPEG +#else + #define LV_USE_FFMPEG 0 +#endif +#if LV_USE_FFMPEG + /*Dump input information to stderr*/ + #define LV_FFMPEG_DUMP_FORMAT 0 +#endif + +/*================== + * OTHERS + *==================*/ + +/*1: Enable API to take snapshot for object*/ +#define LV_USE_SNAPSHOT 0 + +/*1: Enable system monitor component*/ +#define LV_USE_SYSMON 0 +#if LV_USE_SYSMON + /*Get the idle percentage. E.g. uint32_t my_get_idle(void);*/ + #define LV_SYSMON_GET_IDLE lv_timer_get_idle + + /*1: Show CPU usage and FPS count + * Requires `LV_USE_SYSMON = 1`*/ + #define LV_USE_PERF_MONITOR 0 + #if LV_USE_PERF_MONITOR + #define LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT + + /*0: Displays performance data on the screen, 1: Prints performance data using log.*/ + #define LV_USE_PERF_MONITOR_LOG_MODE 0 + #endif + + /*1: Show the used memory and the memory fragmentation + * Requires `LV_USE_STDLIB_MALLOC = LV_STDLIB_BUILTIN` + * Requires `LV_USE_SYSMON = 1`*/ + #define LV_USE_MEM_MONITOR 0 + #if LV_USE_MEM_MONITOR + #define LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_LEFT + #endif + +#endif /*LV_USE_SYSMON*/ + +/*1: Enable the runtime performance profiler*/ +#define LV_USE_PROFILER 0 +#if LV_USE_PROFILER + /*1: Enable the built-in profiler*/ + #define LV_USE_PROFILER_BUILTIN 1 + #if LV_USE_PROFILER_BUILTIN + /*Default profiler trace buffer size*/ + #define LV_PROFILER_BUILTIN_BUF_SIZE (16 * 1024) /*[bytes]*/ + #endif + + /*Header to include for the profiler*/ + #define LV_PROFILER_INCLUDE "lvgl/src/misc/lv_profiler_builtin.h" + + /*Profiler start point function*/ + #define LV_PROFILER_BEGIN LV_PROFILER_BUILTIN_BEGIN + + /*Profiler end point function*/ + #define LV_PROFILER_END LV_PROFILER_BUILTIN_END + + /*Profiler start point function with custom tag*/ + #define LV_PROFILER_BEGIN_TAG LV_PROFILER_BUILTIN_BEGIN_TAG + + /*Profiler end point function with custom tag*/ + #define LV_PROFILER_END_TAG LV_PROFILER_BUILTIN_END_TAG +#endif + +/*1: Enable Monkey test*/ +#define LV_USE_MONKEY 0 + +/*1: Enable grid navigation*/ +#ifndef LV_USE_GRIDNAV + #define LV_USE_GRIDNAV 0 +#endif + +/*1: Enable lv_obj fragment*/ +#define LV_USE_FRAGMENT 0 + +/*1: Support using images as font in label or span widgets */ +#define LV_USE_IMGFONT 1 + +/*1: Enable an observer pattern implementation*/ +#define LV_USE_OBSERVER 1 + +/*1: Enable Pinyin input method*/ +/*Requires: lv_keyboard*/ +#ifndef LV_USE_IME_PINYIN + #define LV_USE_IME_PINYIN 0 +#endif +#if LV_USE_IME_PINYIN + /*1: Use default thesaurus*/ + /*If you do not use the default thesaurus, be sure to use `lv_ime_pinyin` after setting the thesauruss*/ + #define LV_IME_PINYIN_USE_DEFAULT_DICT 1 + /*Set the maximum number of candidate panels that can be displayed*/ + /*This needs to be adjusted according to the size of the screen*/ + #define LV_IME_PINYIN_CAND_TEXT_NUM 6 + + /*Use 9 key input(k9)*/ + #define LV_IME_PINYIN_USE_K9_MODE 1 + #if LV_IME_PINYIN_USE_K9_MODE == 1 + #define LV_IME_PINYIN_K9_CAND_TEXT_NUM 3 + #endif /*LV_IME_PINYIN_USE_K9_MODE*/ +#endif + +/*1: Enable file explorer*/ +/*Requires: lv_table*/ +#ifndef LV_USE_FILE_EXPLORER + #define LV_USE_FILE_EXPLORER 0 +#endif +#if LV_USE_FILE_EXPLORER + /*Maximum length of path*/ + #define LV_FILE_EXPLORER_PATH_MAX_LEN (128) + /*Quick access bar, 1:use, 0:not use*/ + /*Requires: lv_list*/ + #define LV_FILE_EXPLORER_QUICK_ACCESS 1 +#endif +/** Enable emulated input devices, time emulation, and screenshot compares. */ +#define LV_USE_TEST 0 +#if LV_USE_TEST + +/** Enable `lv_test_screenshot_compare`. + * Requires libpng and a few MB of extra RAM. */ +#define LV_USE_TEST_SCREENSHOT_COMPARE 0 +#endif /*LV_USE_TEST*/ + +/** Enable loading XML UIs runtime */ +#define LV_USE_XML 0 + + +/*================== + * DEVICES + *==================*/ + +/*Use SDL to open window on PC and handle mouse and keyboard*/ +#ifdef MICROPY_SDL + #define LV_USE_SDL MICROPY_SDL +#else + #define LV_USE_SDL 0 +#endif +#if LV_USE_SDL + #define LV_SDL_INCLUDE_PATH + #define LV_SDL_RENDER_MODE LV_DISPLAY_RENDER_MODE_DIRECT /*LV_DISPLAY_RENDER_MODE_DIRECT is recommended for best performance*/ + #define LV_SDL_BUF_COUNT 1 /*1 or 2*/ + #define LV_SDL_FULLSCREEN 0 /*1: Make the window full screen by default*/ + #define LV_SDL_DIRECT_EXIT 1 /*1: Exit the application when all SDL windows are closed*/ + #define LV_SDL_MOUSEWHEEL_MODE LV_SDL_MOUSEWHEEL_MODE_ENCODER /*LV_SDL_MOUSEWHEEL_MODE_ENCODER/CROWN*/ +#endif + +/*Use X11 to open window on Linux desktop and handle mouse and keyboard*/ +#define LV_USE_X11 0 +#if LV_USE_X11 + #define LV_X11_DIRECT_EXIT 1 /*Exit the application when all X11 windows have been closed*/ + #define LV_X11_DOUBLE_BUFFER 1 /*Use double buffers for endering*/ + /*select only 1 of the following render modes (LV_X11_RENDER_MODE_PARTIAL preferred!)*/ + #define LV_X11_RENDER_MODE_PARTIAL 1 /*Partial render mode (preferred)*/ + #define LV_X11_RENDER_MODE_DIRECT 0 /*direct render mode*/ + #define LV_X11_RENDER_MODE_FULL 0 /*Full render mode*/ +#endif + +/*Driver for /dev/fb*/ +#ifdef MICROPY_FB + #define LV_USE_LINUX_FBDEV MICROPY_FB +#else + #define LV_USE_LINUX_FBDEV 0 +#endif +#if LV_USE_LINUX_FBDEV + #define LV_LINUX_FBDEV_BSD 0 + #define LV_LINUX_FBDEV_RENDER_MODE LV_DISPLAY_RENDER_MODE_PARTIAL + #define LV_LINUX_FBDEV_BUFFER_COUNT 0 + #define LV_LINUX_FBDEV_BUFFER_SIZE 60 +#endif + +/*Use Nuttx to open window and handle touchscreen*/ +#define LV_USE_NUTTX 0 +#if LV_USE_NUTTX + #define LV_USE_NUTTX_LIBUV 0 + + /*Use Nuttx custom init API to open window and handle touchscreen*/ + #define LV_USE_NUTTX_CUSTOM_INIT 0 + + /*Driver for /dev/lcd*/ + #define LV_USE_NUTTX_LCD 0 + #if LV_USE_NUTTX_LCD + #define LV_NUTTX_LCD_BUFFER_COUNT 0 + #define LV_NUTTX_LCD_BUFFER_SIZE 60 + #endif + + /*Driver for /dev/input*/ + #define LV_USE_NUTTX_TOUCHSCREEN 0 + +#endif + +/*Driver for /dev/dri/card*/ +#define LV_USE_LINUX_DRM 0 + +/*Interface for TFT_eSPI*/ +#define LV_USE_TFT_ESPI 0 + +/*Driver for evdev input devices*/ +#define LV_USE_EVDEV 0 + +/*Driver for libinput input devices*/ +#define LV_USE_LIBINPUT 0 +#if LV_USE_LIBINPUT + #define LV_LIBINPUT_BSD 0 + + /*Full keyboard support*/ + #define LV_LIBINPUT_XKB 0 + #if LV_LIBINPUT_XKB + /*"setxkbmap -query" can help find the right values for your keyboard*/ + #define LV_LIBINPUT_XKB_KEY_MAP { .rules = NULL, .model = "pc101", .layout = "us", .variant = NULL, .options = NULL } + #endif +#endif + +/*Drivers for LCD devices connected via SPI/parallel port*/ +#define LV_USE_ST7735 0 +#define LV_USE_ST7789 0 +#define LV_USE_ST7796 0 +#define LV_USE_ILI9341 0 + +#define LV_USE_GENERIC_MIPI (LV_USE_ST7735 | LV_USE_ST7789 | LV_USE_ST7796 | LV_USE_ILI9341) + +/* LVGL Windows backend */ +#define LV_USE_WINDOWS 0 + +/** LVGL UEFI backend */ +#define LV_USE_UEFI 0 +#if LV_USE_UEFI + #define LV_USE_UEFI_INCLUDE "myefi.h" /**< Header that hides the actual framework (EDK2, gnu-efi, ...) */ + #define LV_UEFI_USE_MEMORY_SERVICES 0 /**< Use the memory functions from the boot services table */ +#endif + +/** Use OpenGL to open window on PC and handle mouse and keyboard */ +#define LV_USE_OPENGLES 0 +#if LV_USE_OPENGLES + #define LV_USE_OPENGLES_DEBUG 1 /**< Enable or disable debug for opengles */ +#endif + +/** QNX Screen display and input drivers */ +#define LV_USE_QNX 0 +#if LV_USE_QNX + #define LV_QNX_BUF_COUNT 1 /**< 1 or 2 */ +#endif +/*================== +* EXAMPLES +*==================*/ + +/*Enable the examples to be built with the library*/ +#ifndef LV_BUILD_EXAMPLES + #define LV_BUILD_EXAMPLES 0 +#endif + +/*=================== + * DEMO USAGE + ====================*/ + +/*Show some widget. It might be required to increase `LV_MEM_SIZE` */ +#define LV_USE_DEMO_WIDGETS 0 + +/*Demonstrate the usage of encoder and keyboard*/ +#define LV_USE_DEMO_KEYPAD_AND_ENCODER 0 + +/*Benchmark your system*/ +#define LV_USE_DEMO_BENCHMARK 0 + +/*Render test for each primitives. Requires at least 480x272 display*/ +#define LV_USE_DEMO_RENDER 0 + +/*Stress test for LVGL*/ +#define LV_USE_DEMO_STRESS 0 + +/*Music player demo*/ +#define LV_USE_DEMO_MUSIC 0 +#if LV_USE_DEMO_MUSIC + #define LV_DEMO_MUSIC_SQUARE 0 + #define LV_DEMO_MUSIC_LANDSCAPE 0 + #define LV_DEMO_MUSIC_ROUND 0 + #define LV_DEMO_MUSIC_LARGE 0 + #define LV_DEMO_MUSIC_AUTO_PLAY 0 +#endif + +/*Vector graphic demo*/ +#define LV_USE_DEMO_VECTOR_GRAPHIC 0 + +/*--------------------------- + * Demos from lvgl/lv_demos + ---------------------------*/ + +/** Flex layout demo */ +#define LV_USE_DEMO_FLEX_LAYOUT 0 + +/** Smart-phone like multi-language demo */ +#define LV_USE_DEMO_MULTILANG 0 + +/** Widget transformation demo */ +#define LV_USE_DEMO_TRANSFORM 0 + +/** Demonstrate scroll settings */ +#define LV_USE_DEMO_SCROLL 0 + +/*E-bike demo with Lottie animations (if LV_USE_LOTTIE is enabled)*/ +#define LV_USE_DEMO_EBIKE 0 +#if LV_USE_DEMO_EBIKE + #define LV_DEMO_EBIKE_PORTRAIT 0 /*0: for 480x270..480x320, 1: for 480x800..720x1280*/ +#endif + +/** High-resolution demo */ +#define LV_USE_DEMO_HIGH_RES 0 + +/* Smart watch demo */ +#define LV_USE_DEMO_SMARTWATCH 0 + +/*--END OF LV_CONF_H--*/ + +#endif /*LV_CONF_H*/ + +#endif /*End of "Content enable"*/ diff --git a/tests/api/basic.py b/tests/api/basic.py index fb29d1f524..9c2d1596ca 100644 --- a/tests/api/basic.py +++ b/tests/api/basic.py @@ -11,7 +11,9 @@ # RGB colors, layout aligment and events. -async def demo(scr, display=None): +async def buttons(scr, display=None): + display.debug_display(True) + def get_button(scr, text, align, color): _btn = lv.button(scr) _btn.set_size(lv.pct(25), lv.pct(10)) @@ -41,6 +43,7 @@ def button_cb(event, name): ) await asyncio.sleep_ms(500) # await so the frame can be rendered + await display.screenshot() print("EVENT TEST:") for _btn, name in _all_btns: _btn.send_event(lv.EVENT.CLICKED, None) @@ -56,8 +59,11 @@ def button_cb(event, name): display_config.MODE = "sim" display_config.POINTER = "sim" + display_config.COLOR_FORMAT = lv.COLOR_FORMAT.RGB888 + display_config.WIDTH = 240 + display_config.HEIGHT = 320 except Exception: display_config = testrunner.display_config -testrunner.run(demo, __file__, disp_config=display_config) +testrunner.run(buttons, __file__, disp_config=display_config) testrunner.devicereset() diff --git a/tests/api/basic.py.exp b/tests/api/basic.py.exp index 7335e2ca0e..9a0da5f438 100644 --- a/tests/api/basic.py.exp +++ b/tests/api/basic.py.exp @@ -1,5 +1,7 @@ DISPLAY_MODE: SIM INDEV_MODE: SIM +COLOR_FORMAT: RGB888 +DISPLAY_SIZE: 240 x 320 FRAME: 0 (0, 0, 240, 32, 23040) d5c5d09cff879bb12cb926dc44bf10161cded58d2057806e7cbde536540b1421 @@ -30,6 +32,7 @@ FRAME: 8 (0, 256, 240, 32, 23040) FRAME: 9 (0, 288, 240, 32, 23040) f546d8ae7340f5fb71e30358ef0d6f33a4f2d72946d9b312444b07fa9d659396 +SCREENSHOT @ buttons@screenshot EVENT TEST: RED PRESSED GREEN PRESSED diff --git a/tests/api/basic_indev.py b/tests/api/basic_indev.py index 36f7944061..6f7d8b21db 100644 --- a/tests/api/basic_indev.py +++ b/tests/api/basic_indev.py @@ -11,7 +11,9 @@ # RGB colors, layout aligment and events. -async def demo(scr, display=None): +async def buttons_indev(scr, display=None): + display.debug_display(True) + def get_button(scr, text, align, color): _btn = lv.button(scr) _btn.set_size(lv.pct(25), lv.pct(10)) @@ -41,6 +43,7 @@ def button_cb(event, name): ) await asyncio.sleep_ms(500) # await so the frame can be rendered + await display.screenshot() print("EVENT TEST:") for _btn, name in _all_btns: _btn.send_event(lv.EVENT.CLICKED, None) @@ -54,8 +57,8 @@ def button_cb(event, name): await asyncio.sleep_ms(500) print("INDEV + BUTTONS TEST:") - # display.debug_indev(press=False, release=False) - display.debug_display(False) + display.debug_indev(press=False, release=False) + # display.debug_display(False) for _btn, name in _all_btns: pos = _btn.get_x(), _btn.get_y() await display.touch(*pos) @@ -73,8 +76,11 @@ def button_cb(event, name): display_config.MODE = "sim" display_config.POINTER = "sim" + display_config.COLOR_FORMAT = lv.COLOR_FORMAT.RGB888 + display_config.WIDTH = 240 + display_config.HEIGHT = 320 except Exception: display_config = testrunner.display_config -testrunner.run(demo, __file__, disp_config=display_config) +testrunner.run(buttons_indev, __file__, disp_config=display_config) testrunner.devicereset() diff --git a/tests/api/basic_indev.py.exp b/tests/api/basic_indev.py.exp index eaeb722443..d7c73339d4 100644 --- a/tests/api/basic_indev.py.exp +++ b/tests/api/basic_indev.py.exp @@ -1,5 +1,7 @@ DISPLAY_MODE: SIM INDEV_MODE: SIM +COLOR_FORMAT: RGB888 +DISPLAY_SIZE: 240 x 320 FRAME: 0 (0, 0, 240, 32, 23040) d5c5d09cff879bb12cb926dc44bf10161cded58d2057806e7cbde536540b1421 @@ -30,6 +32,7 @@ FRAME: 8 (0, 256, 240, 32, 23040) FRAME: 9 (0, 288, 240, 32, 23040) f546d8ae7340f5fb71e30358ef0d6f33a4f2d72946d9b312444b07fa9d659396 +SCREENSHOT @ buttons_indev@screenshot EVENT TEST: RED PRESSED GREEN PRESSED @@ -38,12 +41,69 @@ INDEV TEST: [PRESSED]: (100,100) [RELEASED]: (100,100) INDEV + BUTTONS TEST: -[PRESSED]: (90,0) + +FRAME: 10 (84, 0, 72, 38, 8208) +157dfb805ab2ba43fbbc789a8f04acddafbc43f86c68c870b70b249e5eec3efa RED PRESSED -[RELEASED]: (90,0) -[PRESSED]: (90,288) + +FRAME: 11 (86, 0, 68, 36, 7344) +ebdc55471b3d85d64146db2f7965878921ca8dc2d41c4317fe51211414fa8fd7 + +FRAME: 12 (86, 0, 68, 36, 7344) +d10793db22c7ae992adcc36f58c16ae31b0e92a3a162ced1953960568fc9e742 + +FRAME: 13 (84, 0, 72, 38, 8208) +d98bc48d22da3f3b32fce603ff3aa21aee69d701ff160e77650a6955bc281635 + +FRAME: 14 (84, 0, 72, 38, 8208) +b4cd49a5447516e99d043bfe2ca3867a731ebe8dd281d13a69320133b07f4762 + +FRAME: 15 (85, 0, 70, 37, 7770) +246790d253029c6c79615a2847a728841871abd40d5b596fb8014c9027e5ec16 + +FRAME: 16 (86, 0, 68, 36, 7344) +ebdc55471b3d85d64146db2f7965878921ca8dc2d41c4317fe51211414fa8fd7 + +FRAME: 17 (84, 282, 72, 38, 8208) +f624854eef5536d3bafd81f0f7b90f00dd302b6f7ff07737df6dd775cd378181 GREEN PRESSED -[RELEASED]: (90,288) -[PRESSED]: (90,144) + +FRAME: 18 (86, 284, 68, 36, 7344) +131fbb5efd5e845ba9670c8a370abc04b80cb2dcb60b38285dbd585bcd1b21ce + +FRAME: 19 (86, 284, 68, 36, 7344) +6d7d0faf3b7f1def1c254ba9df57d6b1e5dda47ed6d157c7fd5066d81d07bab5 + +FRAME: 20 (84, 282, 72, 38, 8208) +1dd8b92e3bc0f2478e4ef81305f432e49a88f11e6f54c4217fcfd735fcfc81e5 + +FRAME: 21 (84, 282, 72, 38, 8208) +c1d776b5dc5dd414dc1aaca04d2f831a6ea95027970518ae5f547fc3cb19966d + +FRAME: 22 (85, 283, 70, 37, 7770) +2fed0a49fc70e2f22833d4c0c81e9cc82fff47cd19b3535173ad83d8531b33f1 + +FRAME: 23 (86, 284, 68, 36, 7344) +131fbb5efd5e845ba9670c8a370abc04b80cb2dcb60b38285dbd585bcd1b21ce + +FRAME: 24 (84, 138, 72, 44, 9504) +06e453a6320b8ca53935bc2d69917fdf214550bf841bffe737cc4609bad47a7c BLUE PRESSED -[RELEASED]: (90,144) + +FRAME: 25 (86, 140, 68, 40, 8160) +aeed69ee9d3f90d53bd6077b50cdeac36c3cb126e479a0ffaaf2e50eda9aaa50 + +FRAME: 26 (86, 140, 68, 40, 8160) +6e8687de59be1d073e84bef14fe3bc096341c46534461f5dcf086f1aa7325641 + +FRAME: 27 (84, 138, 72, 44, 9504) +bfc53618af37ea3b5649ee28f0cd66322e5deb6a30962b9cb6356be59a326d0c + +FRAME: 28 (84, 138, 72, 44, 9504) +2792a7c5c8dc152ee41a1908353e9ec3f6d6def057185d94758da9e37cf21de7 + +FRAME: 29 (85, 139, 70, 42, 8820) +635e77e10be5307dc805d341b5e39eb7b69c58b7a9f65e6a43950a9fd86ca237 + +FRAME: 30 (86, 140, 68, 40, 8160) +aeed69ee9d3f90d53bd6077b50cdeac36c3cb126e479a0ffaaf2e50eda9aaa50 diff --git a/tests/api/basic_slider.py b/tests/api/basic_slider.py index f378e0233b..2971f7bf5a 100644 --- a/tests/api/basic_slider.py +++ b/tests/api/basic_slider.py @@ -11,37 +11,39 @@ # RGB colors, layout aligment and events. -async def demo(scr, display=None): - def get_button(scr, text, align, color): +async def sliders(scr, display=None): + display.debug_display(True) + + def get_slider(scr, text, align, color): scr.set_style_pad_all(10, 0) - _btn = lv.slider(scr) - _btn.set_width(lv.pct(75)) - _btn.set_height(lv.pct(10)) - _lab = lv.label(_btn) + slider = lv.slider(scr) + slider.set_width(lv.pct(75)) + slider.set_height(lv.pct(10)) + _lab = lv.label(slider) _lab.set_text(text) _lab.set_style_text_color(lv.color_white(), 0) _lab.center() - _btn.set_style_align(align, 0) - _btn.set_style_bg_color(lv.color_make(*color), lv.PART.INDICATOR) - _btn.set_style_bg_color(lv.color_make(*color), lv.PART.MAIN) - _btn.set_style_bg_color(lv.color_make(*color), lv.PART.KNOB) - return _btn, text + slider.set_style_align(align, 0) + slider.set_style_bg_color(lv.color_make(*color), lv.PART.INDICATOR) + slider.set_style_bg_color(lv.color_make(*color), lv.PART.MAIN) + slider.set_style_bg_color(lv.color_make(*color), lv.PART.KNOB) + return slider, text - buttons = [ + sliders = [ ("RED", lv.ALIGN.TOP_MID, (255, 0, 0)), ("GREEN", lv.ALIGN.BOTTOM_MID, (0, 255, 0)), ("BLUE", lv.ALIGN.CENTER, (0, 0, 255)), ] - def button_cb(event, name, slider): + def slider_cb(event, name, slider): if slider.get_value() == 100: print(f"{name} VALUE: {slider.get_value()}") - _all_btns = [get_button(scr, *btn) for btn in buttons] + _all_objs = [get_slider(scr, *slider) for slider in sliders] - for btn, name in _all_btns: - btn.add_event_cb( - lambda event, button_name=name, slider=btn: button_cb( + for sld, name in _all_objs: + sld.add_event_cb( + lambda event, button_name=name, slider=sld: slider_cb( event, button_name, slider ), lv.EVENT.VALUE_CHANGED, @@ -49,12 +51,14 @@ def button_cb(event, name, slider): ) await asyncio.sleep_ms(500) # await so the frame can be rendered + await display.screenshot(name="start") + # simulate touch events if display: print("INDEV + SLIDER TEST:") display.debug_indev(press=False) display.debug_display(False) - for _btn, name in _all_btns: + for _btn, name in _all_objs: pos = _btn.get_x(), _btn.get_y() pos2 = _btn.get_x2(), _btn.get_y2() x1, y1 = pos @@ -63,7 +67,8 @@ def button_cb(event, name, slider): await display.swipe(x1 + 5, y_mid, x2 + (y2 - y1), y_mid, ms=500) await asyncio.sleep_ms(100) - return _all_btns + await display.screenshot(name="end") + return _all_objs __file__ = globals().get("__file__", "test") @@ -73,8 +78,11 @@ def button_cb(event, name, slider): display_config.MODE = "sim" display_config.POINTER = "sim" + display_config.COLOR_FORMAT = lv.COLOR_FORMAT.RGB888 + display_config.WIDTH = 240 + display_config.HEIGHT = 320 except Exception: display_config = testrunner.display_config -testrunner.run(demo, __file__, disp_config=display_config) +testrunner.run(sliders, __file__, disp_config=display_config) testrunner.devicereset() diff --git a/tests/api/basic_slider.py.exp b/tests/api/basic_slider.py.exp index 78222cf95b..8dd0958ca1 100644 --- a/tests/api/basic_slider.py.exp +++ b/tests/api/basic_slider.py.exp @@ -1,5 +1,7 @@ DISPLAY_MODE: SIM INDEV_MODE: SIM +COLOR_FORMAT: RGB888 +DISPLAY_SIZE: 240 x 320 FRAME: 0 (0, 0, 240, 32, 23040) 6e5737038637abc5ea724930a5113dd9193a3e708b13c3be75d2e5164ccfc57a @@ -30,6 +32,7 @@ a6b9cdacc2013dbb3ce95198217d24ce42333d0178da7fddd15ff353ab012891 FRAME: 9 (0, 288, 240, 32, 23040) 08943f10a0eeb2c8a3b8ec437fd2d0725b5a764d29375282553eaafd51ff704a +SCREENSHOT @ sliders@start INDEV + SLIDER TEST: RED VALUE: 100 [RELEASED]: (218,15) @@ -37,3 +40,4 @@ GREEN VALUE: 100 [RELEASED]: (218,285) BLUE VALUE: 100 [RELEASED]: (218,150) +SCREENSHOT @ sliders@end diff --git a/tests/display/basic.py b/tests/display/basic.py index 3ae06fc08d..9869716c76 100644 --- a/tests/display/basic.py +++ b/tests/display/basic.py @@ -56,6 +56,7 @@ def button_cb(event, name): display_config.MODE = "interactive" display_config.POINTER = "sim" + display_config.SHOW_INFO = False except Exception: display_config = testrunner.display_config diff --git a/tests/display/basic_indev.py b/tests/display/basic_indev.py index bdf9e2de03..739c204631 100644 --- a/tests/display/basic_indev.py +++ b/tests/display/basic_indev.py @@ -54,7 +54,7 @@ def button_cb(event, name): await asyncio.sleep_ms(500) print("INDEV + BUTTONS TEST:") - # display.debug_indev(press=True, release=True) + display.debug_indev(press=False, release=False) display.debug_display(False) for _btn, name in _all_btns: pos = _btn.get_x(), _btn.get_y() @@ -73,6 +73,7 @@ def button_cb(event, name): display_config.MODE = "interactive" display_config.POINTER = "sim" + display_config.SHOW_INFO = False except Exception: display_config = testrunner.display_config diff --git a/tests/display/basic_indev.py.exp b/tests/display/basic_indev.py.exp index 647113bf4a..c471e5ff15 100644 --- a/tests/display/basic_indev.py.exp +++ b/tests/display/basic_indev.py.exp @@ -8,12 +8,6 @@ INDEV TEST: [PRESSED]: (100,100) [RELEASED]: (100,100) INDEV + BUTTONS TEST: -[PRESSED]: (90,0) RED PRESSED -[RELEASED]: (90,0) -[PRESSED]: (90,288) GREEN PRESSED -[RELEASED]: (90,288) -[PRESSED]: (90,144) BLUE PRESSED -[RELEASED]: (90,144) diff --git a/tests/display/basic_slider.py b/tests/display/basic_slider.py index f61d1249fa..90114de039 100644 --- a/tests/display/basic_slider.py +++ b/tests/display/basic_slider.py @@ -52,7 +52,7 @@ def button_cb(event, name, slider): # simulate touch events if display: print("INDEV + SLIDER TEST:") - display.debug_indev(press=False) + display.debug_indev(press=False, release=False) display.debug_display(False) for _btn, name in _all_btns: pos = _btn.get_x(), _btn.get_y() @@ -73,6 +73,7 @@ def button_cb(event, name, slider): display_config.MODE = "interactive" display_config.POINTER = "sim" + display_config.SHOW_INFO = False except Exception: display_config = testrunner.display_config diff --git a/tests/display/basic_slider.py.exp b/tests/display/basic_slider.py.exp index e008e851e0..7ce4576336 100644 --- a/tests/display/basic_slider.py.exp +++ b/tests/display/basic_slider.py.exp @@ -2,8 +2,5 @@ DISPLAY_MODE: INTERACTIVE INDEV_MODE: SIM INDEV + SLIDER TEST: RED VALUE: 100 -[RELEASED]: (218,15) GREEN VALUE: 100 -[RELEASED]: (218,285) BLUE VALUE: 100 -[RELEASED]: (218,150) diff --git a/tests/indev/basic.py b/tests/indev/basic.py index 66ed84ade7..13cf52a85f 100644 --- a/tests/indev/basic.py +++ b/tests/indev/basic.py @@ -26,12 +26,20 @@ def get_button(scr, text, align, color): _lab.center() _btn.set_style_align(align, 0) _btn.set_style_bg_color(lv.color_make(*color), 0) + + _btn.set_style_bg_color( + lv.color_make(255, 255, 255), lv.PART.MAIN | lv.STATE.FOCUSED + ) + _btn.set_style_outline_width(1, lv.PART.MAIN | lv.STATE.FOCUSED) + _btn.set_style_outline_color( + lv.color_make(255, 255, 255), lv.PART.MAIN | lv.STATE.FOCUSED + ) return _btn, text buttons = [ ("RED", lv.ALIGN.TOP_MID, (255, 0, 0)), - ("GREEN", lv.ALIGN.BOTTOM_MID, (0, 255, 0)), ("BLUE", lv.ALIGN.CENTER, (0, 0, 255)), + ("GREEN", lv.ALIGN.BOTTOM_MID, (0, 255, 0)), ] def button_cb(event, name, button): @@ -40,6 +48,7 @@ def button_cb(event, name, button): _all_btns = [get_button(scr, *btn) for btn in buttons] + wgroup = lv.group_create() for btn, name in _all_btns: btn.add_event_cb( lambda event, button_name=name, button=btn: button_cb( @@ -49,6 +58,10 @@ def button_cb(event, name, button): None, ) + wgroup.add_obj(btn) + + if hasattr(display, "indev"): + display.indev.set_group(wgroup) await asyncio.sleep_ms(500) # await so the frame can be rendered print("PRESS EVENT TEST:") for _btn, name in _all_btns: @@ -63,6 +76,7 @@ def button_cb(event, name, button): display_config.MODE = "interactive" display_config.POINTER = "interactive" + display_config.SHOW_INFO = False except Exception: display_config = testrunner.display_config diff --git a/tests/run.sh b/tests/run.sh index e8bfec8dee..5b845d092d 100755 --- a/tests/run.sh +++ b/tests/run.sh @@ -22,5 +22,5 @@ EXCLUDE_PATH=" \ EXCLUDE_FINDEXP=$(echo $EXCLUDE_PATH | sed "s/^\|[[:space:]]/ -and -not -path /g") find $TEST_PATH -name "*.py" $EXCLUDE_FINDEXP |\ - parallel --halt-on-error now,fail=1 --max-args=1 --max-procs $NUMCPUS -I {} timeout 5m catchsegv $SCRIPT_PATH/../../../ports/unix/build-lvgl/micropython $SCRIPT_PATH/run_test.py {} + parallel --halt-on-error now,fail=1 --max-args=1 --max-procs $NUMCPUS -I {} timeout 5m $SCRIPT_PATH/../../../ports/unix/build-lvgl/micropython $SCRIPT_PATH/run_test.py {} diff --git a/tests/testdisplay.py b/tests/testdisplay.py index a40821942c..046e3ec4e0 100644 --- a/tests/testdisplay.py +++ b/tests/testdisplay.py @@ -15,6 +15,7 @@ class TestDisplayConfig: MODE = "sim" POINTER = "sim" COLOR_FORMAT = lv.COLOR_FORMAT.RGB888 + SHOW_INFO = True class TestDisplayDriver: @@ -68,16 +69,25 @@ def __init__( len(self._frame_buffer1), render_mode, ) - self.indev_test = lv.indev_create() - self.indev_test.set_display(lv.display_get_default()) - self.indev_test.set_group(lv.group_get_default()) + if hasattr(display_drv, "set_frame_buffer"): + display_drv.set_frame_buffer(self._frame_buffer1) + self.indev = lv.indev_create() + self.indev.set_display(lv.display_get_default()) + self.indev.set_group(lv.group_get_default()) # TODO: test other types of indev - self.indev_test.set_type(lv.INDEV_TYPE.POINTER) + if pointer in ("sim", "interactive"): + _indev_type = lv.INDEV_TYPE.POINTER + if pointer == "interactive" and hasattr(display_drv, "indev_type"): + _indev_type = display_drv.indev_type + else: + _indev_type = getattr(lv.INDEV_TYPE, pointer.upper()) + + self.indev.set_type(_indev_type) if hasattr(display_drv, "read_cb") and pointer != "sim": - self.indev_test.set_read_cb(display_drv.read_cb) + self.indev.set_read_cb(display_drv.read_cb) else: - self.indev_test.set_read_cb(self._read_cb) + self.indev.set_read_cb(self._read_cb) else: # interactive + DummyDisplay -> SDL self.group = lv.group_create() @@ -89,7 +99,7 @@ def __init__( self.mouse = lv.sdl_mouse_create() self.keyboard = lv.sdl_keyboard_create() self.keyboard.set_group(self.group) - if pointer == "sim": + if pointer in ("sim", "encoder"): self.indev = lv.indev_create() self.indev.set_display(self.lv_display_int) self.indev.set_group(self.group) @@ -171,6 +181,10 @@ def _read_cb(self, indev, data): print(f"[RELEASED]: ({self._x},{self._y})") data.state = self._dstate + def screenshot(self, **kwargs): + if hasattr(self.display_drv, "screenshot"): + return self.display_drv.screenshot(**kwargs) + class DummyDisplay: def __init__(self, width=240, height=320, color_format=lv.COLOR_FORMAT.RGB565): @@ -180,9 +194,13 @@ def __init__(self, width=240, height=320, color_format=lv.COLOR_FORMAT.RGB565): self.color_size = lv.color_format_get_size(color_format) self.n = 0 self.test_name = "testframe" - self._header_set = False + self._header_set = True self._save_frame = sys.platform in ["darwin", "linux"] - self._debug = True + # TODO: use framebuf for snapshot + self._debug = False + if self._save_frame: + self._pbuff = bytearray(self.color_size) + self._save_frame = False @property def debug(self): @@ -191,16 +209,60 @@ def debug(self): @debug.setter def debug(self, x): self._debug = x - self._save_frame = x + # self._save_frame = x + + def reverse_pixel(self, a): + for i in range(len(a) - 1, -1, -1): + self._pbuff[len(a) - 1 - i] = a[i] + return self._pbuff - def save_frame(self, data): + def save_frame(self, data, w, h): if not self._header_set: self._header_set = True + # print(self.test_name, f"{self.width}:{self.height}:{self.color_size}") with open(f"{self.test_name}.bin", "wb") as fr: fr.write(f"{self.width}:{self.height}:{self.color_size}\n".encode()) + # print(bytes(data)) + assert len(bytes(data[:])) == w * h * self.color_size with open(f"{self.test_name}.bin", "ab") as fr: - fr.write(data) + pi = 0 + for py in range(0, h): + for px in range(0, w): + try: + pixel = data[pi : pi + self.color_size] + + fr.write(self.reverse_pixel(pixel)) + # fr.write(bytes(pixel)) + pi += self.color_size + except Exception: + print(pi) + + async def screenshot(self, name="screenshot", debug=False): + _debug = self._debug + self._debug = False + self._save_frame = False + + # Reset + self._rst_scr = lv.obj() + c_scr = lv.screen_active() + lv.screen_load(self._rst_scr) + await asyncio.sleep_ms(500) + + # Load test screen + self._save_frame = sys.platform in ["darwin", "linux"] + self._header_set = False + self._debug = debug + _test_name = self.test_name + self.test_name = f"{self.test_name}@{name}" + print(f"SCREENSHOT @ {self.test_name.rsplit('/')[-1].split('.')[-1]}") + lv.screen_load(c_scr) + await asyncio.sleep_ms(500) + + self._debug = _debug + self._save_frame = False + self._header_set = True + self.test_name = _test_name def _shasum_frame(self, data): _hash = hashlib.sha256() @@ -210,12 +272,12 @@ def _shasum_frame(self, data): return result def blit(self, x1, y1, w, h, buff): - if self.debug: - print(f"\nFRAME: {self.n} {(x1, y1, w, h, len(buff[:]))}") - print(self._shasum_frame(bytes(buff[:]))) if self._save_frame: - self.save_frame(buff[:]) - self.n += 1 + self.save_frame(buff, w, h) + if self.debug: + print(f"\nFRAME: {self.n} {(x1, y1, w, h, len(buff))}") + print(self._shasum_frame(bytes(buff))) + self.n += 1 tdisp = DummyDisplay(color_format=lv.COLOR_FORMAT.RGB888) @@ -239,14 +301,16 @@ def get_display( color_format=lv.COLOR_FORMAT.RGB888, mode="sim", pointer="sim", + show_display_info=False, ): print(f"DISPLAY_MODE: {mode.upper()}") print(f"INDEV_MODE: {pointer.upper()}") - _cf = {v: k for k, v in lv.COLOR_FORMAT.__dict__.items() if k != "NATIVE"} - # print(f"COLOR_FORMAT: {_cf.get(color_format, 'UNKNOWN')}") if mode == "sim": + show_display_info = True disp = tdisp + disp.width = width + disp.height = height elif mode == "interactive": disp.width = width disp.height = height @@ -260,18 +324,23 @@ def get_display( if sys.platform not in ["darwin", "linux"]: sys.print_exception(e) assert hasattr(disp, "width") is True, "expected width attribute in display driver" - assert ( - hasattr(disp, "height") is True - ), "expected height attribute in display driver" + assert hasattr(disp, "height") is True, ( + "expected height attribute in display driver" + ) + + assert hasattr(disp, "color_depth") is True, ( + "expected color_depth attribute in display driver" + ) - assert ( - hasattr(disp, "color_depth") is True - ), "expected color_depth attribute in display driver" + if show_display_info: + _cf = {v: k for k, v in lv.COLOR_FORMAT.__dict__.items() if k != "NATIVE"} + print(f"COLOR_FORMAT: {_cf.get(color_format, 'UNKNOWN')}") + print(f"DISPLAY_SIZE: {width} x {height}") alloc_buffer = lambda buffersize: memoryview(bytearray(buffer_size)) factor = 10 ### Must be 1 if using an RGBBus - double_buf = True ### Must be False if using an RGBBus + double_buf = False ### Must be False if using an RGBBus buffer_size = disp.width * disp.height * (disp.color_depth // 8) // factor diff --git a/tests/testrunner.py b/tests/testrunner.py index 488f254b94..c9c89151cd 100644 --- a/tests/testrunner.py +++ b/tests/testrunner.py @@ -4,7 +4,13 @@ sys.path.append("..") sys.path.append(os.getcwd()) -from testdisplay import get_display, display_config # noqa +try: + # testrunner, testdisplay from package + from .testdisplay import get_display, display_config # noqa +except ImportError: + # testrunner, testdisplay from root dir + from testdisplay import get_display, display_config # noqa + _int = sys.argv.pop() if sys.platform in ["darwin", "linux"] else "" _mode = "sim" @@ -12,7 +18,7 @@ _mode = "interactive" -async def run_test(func, display=None): +async def run_test(func, display=None, **kwargs): import lvgl as lv # noqa lv.init() @@ -21,7 +27,7 @@ async def run_test(func, display=None): scr.set_style_bg_color(lv.color_black(), 0) lv.screen_load(scr) - resp = await func(scr, display) + resp = await func(scr, display, **kwargs) return scr, resp @@ -33,14 +39,20 @@ def run(func, filename, disp_config=display_config, **kwargs): # micropython.mem_info() async def _run(func, disp_config=disp_config, **kwargs): + # OVERRIDE if display_config.py hasattr, else use default + # display_config if hasattr(disp_config, "COLOR_FORMAT"): display_config.COLOR_FORMAT = disp_config.COLOR_FORMAT + + if hasattr(disp_config, "SHOW_INFO"): + display_config.SHOW_INFO = disp_config.SHOW_INFO display = get_display( disp_config.WIDTH, disp_config.HEIGHT, mode=disp_config.MODE if disp_config.MODE is not None else _mode, pointer=disp_config.POINTER, color_format=display_config.COLOR_FORMAT, + show_display_info=display_config.SHOW_INFO, ) if display.mode == "sim": @@ -48,7 +60,7 @@ async def _run(func, disp_config=disp_config, **kwargs): await run_test(func, display) await asyncio.sleep_ms(100) elif display.mode == "interactive": - await run_test(func, display) + await run_test(func, display, **kwargs) if _int == "-id": while True: try: