Ken Van Hoeylandt 0ebd471cc0
Reduce internal RAM use: embedded assets, fonts in flash, PSRAM stacks, file_ops (#701)
- The `/system` FAT volume is removed. Its files are embedded in the firmware as generated C arrays.
- Default-size fonts are generated at build time and used from flash.
- The LVGL task and the Launcher run on PSRAM-preferred stacks. A new kernel `file_ops` API takes the file work off those threads.
- `MainDispatcher` is reimplemented as an on-demand task.
- More long-lived state is allocated with the PSRAM-preferring helpers.
- Other fixes and improvements
2026-10-18 17:30:43 +02:00

77 lines
3.8 KiB
Markdown

# lvgl-module
This module manages the lifecycle of the [LVGL](https://lvgl.io/) library within the Tactility ecosystem.
## What the library does
The `lvgl-module` provides:
- **Lifecycle Management**: Handles initialization and termination of the LVGL library.
- **Task Management**: Manages the LVGL main loop task.
- **Thread-Safety**: Provides mutex-based locking mechanisms (`lvgl_lock`, `lvgl_unlock`) to ensure safe access to LVGL APIs from multiple tasks.
- **Font Access**: Provides a unified interface to access pre-configured text and icon fonts.
## Different types of fonts
The module supports two main categories of fonts:
### Text Fonts
Text uses the **Adwaita Sans** font in three sizes:
- `FONT_SIZE_SMALL`
- `FONT_SIZE_DEFAULT`
- `FONT_SIZE_LARGE`
Until Tactility registers these fonts with `lvgl_set_text_font()`, the getters return LVGL's built-in default font (Montserrat).
### Icon Fonts
Icons are provided by the **Material Symbols** font, divided into three usage-specific sets:
- **Statusbar Icons**: Optimized for the system status bar.
- **Launcher Icons**: Sized for application launchers.
- **Shared Icons**: General purpose icons used across the system.
## How to update the fonts
All font sizes derive from one default text size: `font.defaultSize` in `device.properties` (`CONFIG_TT_FONT_DEFAULT_SIZE`, 14 on the simulator).
Tactility calculates the other text and icon sizes from it in `Tactility/Source/lvgl/FontSizes.cpp`.
The fonts of the device's default size are generated at build time by `Buildscripts/generate-fonts.py` (using a host built tool, `Buildscripts/BinfontTool`) and embedded in the firmware as `generated_fonts.c`.
They are opened in place and take no RAM. Other sizes and custom fonts use the cache below, which needs at least 2 MB of total memory: without it only the embedded fonts are used and the Appearance app hides the font settings.
When there's no host C++ compiler at build time, no fonts are embedded and the cache is used for all of them.
Text fonts that aren't embedded are rasterized on device at startup from the embedded `Data/system/fonts/AdwaitaSans.ttf` and cached as `.bin` files in the data path.
`Tactility/Fonts/generate.py` creates that TTF subset from `Tactility/Fonts/AdwaitaSans-Regular.ttf` (requires `pip install fonttools`).
Icon fonts are rasterized on device at startup from `Data/system/fonts/MaterialSymbolsRounded.ttf` (a subset with only the used icons) and cached as `.bin` files in the data path, so any icon size works.
The icons per font are listed by name and resolved through `Data/system/fonts/MaterialSymbolsRounded.codepoints`.
To add an icon, add its name to `generate-icons.py` and run it (requires `pip install fonttools`). This regenerates the TTF subset, the codepoints file and the name lists.
## Custom memory allocator
LVGL's malloc/realloc/free can be routed through a custom backend instead of its built-in pool or
plain `malloc`. Three things are required:
**1. Select the backend.** On ESP32, via Kconfig (`sdkconfig`):
```sdkconfig
CONFIG_LV_USE_CUSTOM_MALLOC=y
```
On Simulator/POSIX, ESP-IDF's Kconfig doesn't apply - select it in `lv_conf.h` instead:
```c
#define LV_USE_STDLIB_MALLOC LV_STDLIB_CUSTOM
```
**2. Force the module into the link.** LVGL's own init code calls back into the functions above
a reverse reference a normal single-pass static-archive link can't resolve on its own:
```cmake
tactility_add_module(lvgl-module
...
WHOLE_ARCHIVE
)
```
Without `WHOLE_ARCHIVE`, or without step 1 selecting the custom backend, ESP-IDF's LVGL component
compiles its own allocator using these same symbol names - whichever one the linker happens to
pull in first silently wins, with no error and no guarantee it's the intended one.
## License
This module is licensed under the [Apache v2.0](LICENSE-Apache-2.0.md) license.