diff options
| author | jacqueline <me@jacqueline.id.au> | 2024-06-12 17:54:40 +1000 |
|---|---|---|
| committer | jacqueline <me@jacqueline.id.au> | 2024-06-12 17:54:40 +1000 |
| commit | 64bd9053a25297f7a442ca831c7da5b44bd33f84 (patch) | |
| tree | a90c6cad25a12028302ab1a5334510fba0229bae /lib/lvgl/docs/integration/bindings/micropython.rst | |
| parent | 611176ed667c4ed7ee9f609e958f9404f4aee91d (diff) | |
| download | tangara-fw-64bd9053a25297f7a442ca831c7da5b44bd33f84.tar.gz | |
Update LVGL to v9.1.0
Diffstat (limited to 'lib/lvgl/docs/integration/bindings/micropython.rst')
| -rw-r--r-- | lib/lvgl/docs/integration/bindings/micropython.rst | 294 |
1 files changed, 294 insertions, 0 deletions
diff --git a/lib/lvgl/docs/integration/bindings/micropython.rst b/lib/lvgl/docs/integration/bindings/micropython.rst new file mode 100644 index 00000000..a652556c --- /dev/null +++ b/lib/lvgl/docs/integration/bindings/micropython.rst @@ -0,0 +1,294 @@ +.. _micropython: + +=========== +Micropython +=========== + +What is Micropython? +-------------------- + +`Micropython <http://micropython.org/>`__ is Python for +microcontrollers. Using Micropython, you can write Python3 code and run +it even on a bare metal architecture with limited resources. + + +Highlights of Micropython +~~~~~~~~~~~~~~~~~~~~~~~~~ + +- **Compact**: Fits and runs within just 256k of code space and 16k of RAM. No OS is needed, although you + can also run it with an OS, if you want. +- **Compatible**: Strives to be as compatible as possible with normal Python (known as CPython). +- **Versatile**: Supports many architectures (x86, x86-64, ARM, ARM Thumb, Xtensa). +- **Interactive**: No need for the compile-flash-boot cycle. With the REPL (interactive prompt) you can type + commands and execute them immediately, run scripts, etc. +- **Popular**: Many platforms are supported. The user base is growing bigger. Notable forks: + + - `MicroPython <https://github.com/micropython/micropython>`__ + - `CircuitPython <https://github.com/adafruit/circuitpython>`__ + - `MicroPython_ESP32_psRAM_LoBo <https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo>`__ + +- **Embedded Oriented**: Comes with modules specifically for embedded systems, such as the + `machine module <https://docs.micropython.org/en/latest/library/machine.html#classes>`__ + for accessing low-level hardware (I/O pins, ADC, UART, SPI, I2C, RTC, Timers etc.) + +-------------- + + +Why Micropython + LVGL? +----------------------- + +Micropython `does not have a good native high-level GUI library <https://forum.micropython.org/viewtopic.php?f=18&t=5543>`__. +LVGL is an `Object-Oriented Component Based <https://blog.lvgl.io/2018-12-13/extend-lvgl-objects>`__ +high-level GUI library, which seems to be a natural candidate to map into a higher level language, such as Python. +LVGL is implemented in C and its APIs are in C. + + +Here are some advantages of using LVGL in Micropython: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Develop GUI in Python, a very popular high level language. Use paradigms such as Object-Oriented Programming. +- Usually, GUI development requires multiple iterations to get things right. With C, each iteration consists of + **``Change code`` > ``Build`` > ``Flash`` > ``Run``**. In Micropython it's just + **``Change code`` > ``Run``** ! You can even run commands interactively using the + `REPL <https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop>`__ (the interactive prompt) + +Micropython + LVGL could be used for: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Fast prototyping GUI. +- Shortening the cycle of changing and fine-tuning the GUI. +- Modelling the GUI in a more abstract way by defining reusable composite objects, taking advantage of Python's language features + such as Inheritance, Closures, List Comprehension, Generators, Exception Handling, Arbitrary Precision Integers and others. +- Make LVGL accessible to a larger audience. No need to know C to create a nice GUI on an embedded system. This goes well with + `CircuitPython vision <https://learn.adafruit.com/welcome-to-circuitpython/what-is-circuitpython>`__. + CircuitPython was designed with education in mind, to make it easier for new or inexperienced users to get started with + embedded development. +- Creating tools to work with LVGL at a higher level (e.g. drag-and-drop designer). + +-------------- + + +So what does it look like? +-------------------------- + +It's very much like the C API, but Object-Oriented for LVGL components. + +Let's dive right into an example! + + +A simple example +~~~~~~~~~~~~~~~~ + +.. code:: python + + # Initialize + import display_driver + import lvgl as lv + + # Create a button with a label + scr = lv.obj() + btn = lv.button(scr) + btn.align(lv.ALIGN.CENTER, 0, 0) + label = lv.label(btn) + label.set_text('Hello World!') + lv.screen_load(scr) + + +How can I use it? +----------------- + +Online Simulator +~~~~~~~~~~~~~~~~ + +If you want to experiment with LVGL + Micropython without downloading +anything - you can use our online simulator! It's a fully functional +LVGL + Micropython that runs entirely in the browser and allows you to +edit a python script and run it. + +`Click here to experiment on the online simulator <https://sim.lvgl.io/>`__ + +Many `LVGL examples <https://docs.lvgl.io/master/examples.html>`__ are available also for Micropython. Just click the link! + + +PC Simulator +~~~~~~~~~~~~ + +Micropython is ported to many platforms. One notable port is "unix", which allows you to build and run Micropython +(+LVGL) on a Linux machine. (On a Windows machine you might need Virtual Box or WSL or MinGW or Cygwin etc.) + +`Click here to know more information about building and running the unix port <https://github.com/lvgl/lv_micropython>`__ + + +Embedded Platforms +~~~~~~~~~~~~~~~~~~ + +In the end, the goal is to run it all on an embedded platform. Both Micropython and LVGL can be used on many embedded +architectures. `lv_micropython <https://github.com/lvgl/lv_micropython>`__ is a fork of Micropython+LVGL and currently +supports Linux, ESP32, STM32 and RP2. It can be ported to any other platform supported by Micropython. + +- You would also need display and input drivers. You can either use one of the existing drivers provided with lv_micropython, + or you can create your own input/display drivers for your specific hardware. +- Drivers can be implemented either in C as a Micropython module, or in pure Python! + +lv_micropython already contains these drivers: + +- Display drivers: + + - SDL on Linux + - X11 on Linux + - ESP32 specific: + + - ILI9341 + - ILI9488 + - GC9A01 + - ST7789 + - ST7735 + + - Generic (pure Python): + + - ILI9341 + - ST7789 + - ST7735 + +- Input drivers: + + - SDL + - X11 + - XPT2046 + - FT6X36 + - ESP32 ADC with resistive touch + + +Where can I find more information? +---------------------------------- + +- ``lv_micropython`` `README <https://github.com/lvgl/lv_micropython>`__ +- ``lv_binding_micropython`` `README <https://github.com/lvgl/lv_binding_micropython>`__ +- The `LVGL micropython forum <https://forum.lvgl.io/c/micropython>`__ (Feel free to ask anything!) +- At Micropython: `docs <http://docs.micropython.org/en/latest/>`__ and `forum <https://forum.micropython.org/>`__ +- `Blog Post <https://blog.lvgl.io/2019-02-20/micropython-bindings>`__, a little outdated. + + +The Micropython Binding is auto generated! +------------------------------------------ + +- LVGL is a git submodule inside `lv_micropython <https://github.com/lvgl/lv_micropython>`__ + (LVGL is a git submodule of `lv_binding_micropython <https://github.com/lvgl/lv_binding_micropython>`__ + which is itself a submodule of `lv_micropython <https://github.com/lvgl/lv_micropython>`__). +- When building lv_micropython, the public LVGL C API is scanned and Micropython API is auto-generated. That means that + lv_micropython provides LVGL API for **any** LVGL version, and generally does not require code changes as LVGL evolves. + + +LVGL C API Coding Conventions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For a summary of coding conventions to follow see the `CODING STYLE <CODING_STYLE>`__. + +.. _memory_management: + +Memory Management +~~~~~~~~~~~~~~~~~ + +| When LVGL runs in Micropython, all dynamic memory allocations (:cpp:func:`lv_malloc`) are handled by Micropython's memory + manager which is `garbage-collected <https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)>`__ (GC). +| To prevent GC from collecting memory prematurely, all dynamic allocated RAM must be reachable by GC. +| GC is aware of most allocations, except from pointers on the `Data Segment <https://en.wikipedia.org/wiki/Data_segment>`__: + + - Pointers which are global variables + - Pointers which are static global variables + - Pointers which are static local variables + +Such pointers need to be defined in a special way to make them reachable by GC + + +Identify The Problem +^^^^^^^^^^^^^^^^^^^^ + +Problem happens when an allocated memory's pointer (return value of :cpp:func:`lv_malloc`) is stored only in either **global**, +**static global** or **static local** pointer variable and not as part of a previously allocated ``struct`` or other variable. + + +Solve The Problem +^^^^^^^^^^^^^^^^^ + +- Replace the global/static local var with :cpp:expr:`(LV_GLOBAL_DEFAULT()->_var)` +- Include ``lv_global.h`` on files that use ``LV_GLOBAL_DEFAULT`` +- Add ``_var`` to ``lv_global_t`` on ``lv_global.h`` + +Example +^^^^^^^ + + +More Information +^^^^^^^^^^^^^^^^ + +- `In the README <https://github.com/lvgl/lv_binding_micropython#memory-management>`__ +- `In the Blog <https://blog.lvgl.io/2019-02-20/micropython-bindings#i-need-to-allocate-a-littlevgl-struct-such-as-style-color-etc-how-can-i-do-that-how-do-i-allocatedeallocate-memory-for-it>`__ + +.. _callbacks: + +Callbacks +~~~~~~~~~ + +In C a callback is just a function pointer. But in Micropython we need to register a *Micropython callable object* for each +callback. Therefore in the Micropython binding we need to register both a function pointer and a Micropython object for every callback. + +Therefore we defined a **callback convention** for the LVGL C API that expects lvgl headers to be defined in a certain +way. Callbacks that are declared according to the convention would allow the binding to register a Micropython object +next to the function pointer when registering a callback, and access that object when the callback is called. + +- The basic idea is that we have ``void * user_data`` field that is used automatically by the Micropython Binding + to save the *Micropython callable object* for a callback. This field must be provided when registering the function + pointer, and provided to the callback function itself. +- Although called "user_data", the user is not expected to read/write that field. Instead, the Micropython glue code uses + ``user_data`` to automatically keep track of the Micropython callable object. The glue code updates it when the callback + is registered, and uses it when the callback is called in order to invoke a call to the original callable object. + +There are a few options for defining a callback in LVGL C API: + +- Option 1: ``user_data`` in a struct + + - There's a struct that contains a field called ``void * user_data`` + + - A pointer to that struct is provided as the **first** argument of a callback registration function + - A pointer to that struct is provided as the **first** argument of the callback itself + +- Option 2: ``user_data`` as a function argument + + - A parameter called ``void * user_data`` is provided to the registration function as the **last** argument + + - The callback itself receives ``void *`` as the **last** argument + +- Option 3: both callback and ``user_data`` are struct fields + + - The API exposes a struct with both function pointer member and ``user_data`` member + + - The function pointer member receives the same struct as its **first** argument + +In practice it's also possible to mix these options, for example provide a struct pointer when registering a callback +(option 1) and provide ``user_data`` argument when calling the callback (options 2), +**as long as the same ``user_data`` that was registered is passed to the callback when it's called**. + +Examples +^^^^^^^^ + +- :cpp:type:`lv_anim_t` contains ``user_data`` field. :cpp:func:`lv_anim_set_path_cb` + registers `path_cb` callback. Both ``lv_anim_set_path_cb`` and :cpp:type:`lv_anim_path_cb_t` + receive :cpp:type:`lv_anim_t` as their first argument +- ``path_cb`` field can also be assigned directly in the Python code because it's a member + of :cpp:type:`lv_anim_t` which contains ``user_data`` field, and :cpp:type:`lv_anim_path_cb_t` + receive :cpp:type:`lv_anim_t` as its first argument. +- :cpp:func:`lv_imgfont_create` registers ``path_cb`` and receives ``user_data`` as the last + argument. The callback :cpp:type:`lv_imgfont_get_path_cb_t` also receives the ``user_data`` as the last argument. + +.. _more-information-1: + +More Information +^^^^^^^^^^^^^^^^ + +- In the `Blog <https://blog.lvgl.io/2019-08-05/micropython-pure-display-driver#using-callbacks>`__ + and in the `README <https://github.com/lvgl/lv_binding_micropython#callbacks>`__ +- `[v6.0] Callback conventions #1036 <https://github.com/lvgl/lvgl/issues/1036>`__ +- Various discussions: `here <https://github.com/lvgl/lvgl/pull/3294#issuecomment-1184895335>`__ + and `here <https://github.com/lvgl/lvgl/issues/1763#issuecomment-762247629>`__ + and`here <https://github.com/lvgl/lvgl/issues/316#issuecomment-467221587>`__ |
