This repo contains a full binding of LVGL to the Berry language. This project is similar to the Micropython+lvgl project in its spirit, and provides easy to use scripting for lvgl on embedded devices. It is used by the Tasmota open-source project for ESP32 based devices.
**Supported version**: LVGL 8.2.0
## Why use LVGL + Berry
LVGL + Berry mapping provides an easy-to-use programming language on top of LVGL powerful APIs. This is ideal for rapid scripting as well as production applications. The Berry mapping comes from the open-source [Tasmota](https://tasmota.github.io/docs/) project for ESP32 based devices, and leverages a vivid ecosystem.
Quickstart with this short tutorial [LVGL in less than 10 minutes with Tasmota](https://tasmota.github.io/docs/LVGL_in_10_minutes/).
[Berry](https://github.com/berry-lang/berry) is an ultra-lightweight dynamically typed embedded scripting language. It is designed for lower-performance embedded devices. The interpreter of Berry includes a one-pass compiler and register-based VM, all the code is written in ANSI C99. Berry offers a syntax very similar to Python, and is inspired from LUA VM.
## Quickstart
Let's start with a simple example:
```
#- start LVGL and init environment (can be called multiple times) -#
lv.start()
hres = lv.get_hor_res() # horizontal resolution of default display
vres = lv.get_ver_res() # vertical resolution of default display
scr = lv.scr_act() # default screen object
#- Background with a gradient from black #000000 (bottom) to dark blue #0000A0 (top) -#
lv_berry provides an object-oriented interface for LVGL, and covers over 99% of LVGL's APIs, noticeably:
- access to almost all LVGL APIs (over 1000+ calls)
- automatic type checking and type conversion based on `C` headers
- access to all `C` ENUMs constants (500+)
- full support for C callbacks in Berry
- full support for LVGL internal memory structures
- ability to create pure Berry custom widgets and custom classes
- supports only 16 bits display (swapped or not)
What is currently not supported (but could be if there is demand):
- multi-screen devices (no support in Tasmota anyways)
- bidirectional text support
- LVGL tasks (Berry has its own task system)
- non-16 bits display
## Type system
### Widgets classes
Although LVGL is C code and is not formally object oriented, LVGL widget follow an inheritance model. Each widget is a virtual subclass of `lv_obj` structure.
Berry builds an actual Object Oriented class system, with a base class `lv_obj` and subclasses.
The class names supported are defined in `convert.py` and are currently standard widgets:
An exception for LVGL colors, they are defined as 32 bits RGB values as follows, and not based on their C representation:
```C
COLOR_WHITE=0xFFFFFF
COLOR_SILVER=0xC0C0C0
COLOR_GRAY=0x808080
COLOR_BLACK=0x000000
COLOR_RED=0xFF0000
COLOR_MAROON=0x800000
COLOR_YELLOW=0xFFFF00
COLOR_OLIVE=0x808000
COLOR_LIME=0x00FF00
COLOR_GREEN=0x008000
COLOR_CYAN=0x00FFFF
COLOR_AQUA=0x00FFFF
COLOR_TEAL=0x008080
COLOR_BLUE=0x0000FF
COLOR_NAVY=0x000080
COLOR_MAGENTA=0xFF00FF
COLOR_PURPLE=0x800080
```
Example: `lv.COLOR_RED`
`lv_color` is a simple class that maps RGB 32 bits colors (as 32 bits int) to the internal representation of colors (usually 16 bits).
Don't be surprised that getting back a value is the 16 bits color converted to 32 bits - rounding errors may occur:
```
[Berry Console]
> c = lv_color(0x808080)
> c
lv_color(0xff838183 - native:0x1084)
```
Note:
- 0xff838183 - is the 32 bits color, with alpha channel (opaque)
- 0x1084 - is the native internal representation as 16 bits color with swapped bytes
## Build system
More details about the mapping are provided in [Tasmota LVGL Internals](https://tasmota.github.io/docs/LVGL_Internals/)
`lv_berry` uses a semi-automated parsing of lvgl's `C` headers to generate the Berry mapping. The process is automated, but may require small parser adjustments with new versions.
This module relies on [berry_mapping](https://github.com/berry-lang/berry_mapping) module to automate the mapping of C functions.
**Phase 1: Parse LVGL source**
This first phase parses most C headers from the LVGL source tree and generates two files:
-`mapping/lv_enum.h` containing all the `enum` values from LVGL (constants)
-`mapping/lv_funcs.h` containing all the functions of the LVGL API normalized to 1 function per line, and with cleaned argument signature.
```
(`cd` in folder tools)
❯ python3 preprocessor.py
(no output)
```
**Phase 2: Generate automatic Berry mapping**
From the two files created in the previous step, all the requires C files are created for the Berry mapping.
The output should look as above, and indicates the C function that have been ignored (if any) if their return type is listed above. It also lists the callback types supported.
**Phase 3: Generate the Berry pre-compiled stubs**
This phase is specific to Berry pre-compiled modules and classes.
**Phase 4: compile Tasmota using platform.io as usual**
## Future projects
There is an on-going project to provide [OpenHASP](https://openhasp.haswitchplate.com/) emulation using LVGL+Berry. This will provide a super-easy to use JSON graphical description of UI interfaces, with no or very low knowledge of LVGL APIs.