|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +This repository contains MicroPython bindings for LVGL (Light and Versatile Graphics Library). It automatically generates Python bindings from LVGL C headers using the `gen_mpy.py` script, allowing LVGL to be used from MicroPython with native performance. |
| 8 | + |
| 9 | +## Building and Integration |
| 10 | + |
| 11 | +### As a MicroPython User Module |
| 12 | + |
| 13 | +This module is typically used as a git submodule within a MicroPython project. The bindings are built automatically during the MicroPython build process. |
| 14 | + |
| 15 | +**Build Integration:** |
| 16 | +- **Make-based builds**: Uses `micropython.mk` with automatic binding generation |
| 17 | +- **CMake-based builds**: Uses `micropython.cmake` and `mkrules_usermod.cmake` |
| 18 | +- The build system automatically runs `gen/gen_mpy.py` to generate `lv_mpy.c` from LVGL headers |
| 19 | + |
| 20 | +**Key Build Files:** |
| 21 | +- `micropython.mk`: Make-based build rules and LVGL library integration |
| 22 | +- `micropython.cmake`: CMake integration for ESP32/IDF and other platforms |
| 23 | +- `lv_conf.h`: LVGL configuration (affects which bindings are generated) |
| 24 | + |
| 25 | +### Building Standalone (for testing) |
| 26 | + |
| 27 | +From a MicroPython repository with this as a user module: |
| 28 | + |
| 29 | +```bash |
| 30 | +# Unix port (for testing with SDL) |
| 31 | +cd ports/unix |
| 32 | +make USER_C_MODULES=/path/to/lv_binding_micropython/micropython.cmake |
| 33 | +./build-lvgl/micropython |
| 34 | + |
| 35 | +# ESP32 port |
| 36 | +cd ports/esp32 |
| 37 | +make USER_C_MODULES=/path/to/lv_binding_micropython/micropython.cmake BOARD=ESP32_GENERIC |
| 38 | +``` |
| 39 | + |
| 40 | +## Testing |
| 41 | + |
| 42 | +### Automated Tests |
| 43 | + |
| 44 | +**API Tests** (can be automated/CI): |
| 45 | +```bash |
| 46 | +# From micropython/tests directory |
| 47 | +./run-tests.py ../../lib/lv_binding_micropython/tests/api/basic*.py -r . |
| 48 | +``` |
| 49 | + |
| 50 | +**Display Tests** (visual feedback, no interaction): |
| 51 | +```bash |
| 52 | +# From micropython/tests directory |
| 53 | +./run-tests.py ../../lib/lv_binding_micropython/tests/display/basic*.py -r . |
| 54 | +``` |
| 55 | + |
| 56 | +**Interactive Tests** (require user input): |
| 57 | +```bash |
| 58 | +# From micropython/tests directory |
| 59 | +./run-tests.py ../../lib/lv_binding_micropython/tests/indev/basic*.py -r . |
| 60 | +``` |
| 61 | + |
| 62 | +### Example Testing |
| 63 | + |
| 64 | +Run all examples and demos: |
| 65 | +```bash |
| 66 | +cd tests |
| 67 | +./run.sh |
| 68 | +``` |
| 69 | + |
| 70 | +This runs all Python examples in parallel using GNU parallel, with 5-minute timeouts per test. |
| 71 | + |
| 72 | +## Code Architecture |
| 73 | + |
| 74 | +### Binding Generation System |
| 75 | + |
| 76 | +**Core Components:** |
| 77 | +- `gen/gen_mpy.py`: Main binding generator that parses LVGL headers and generates MicroPython C API |
| 78 | +- `pycparser/`: Modified Python C parser for processing LVGL headers |
| 79 | +- `lvgl/`: Git submodule containing the actual LVGL library |
| 80 | + |
| 81 | +**Generation Process:** |
| 82 | +1. C preprocessor processes LVGL headers with `lv_conf.h` settings |
| 83 | +2. `gen_mpy.py` uses pycparser to parse the preprocessed headers |
| 84 | +3. Generates `lv_mpy.c` containing MicroPython module definitions |
| 85 | +4. Build system compiles everything into the MicroPython binary |
| 86 | + |
| 87 | +### Driver Architecture |
| 88 | + |
| 89 | +**Driver Locations:** |
| 90 | +- `driver/esp32/`: ESP32-specific drivers (ILI9XXX, XPT2046, etc.) |
| 91 | +- `driver/generic/`: Platform-independent Python drivers |
| 92 | +- `driver/linux/`: Linux-specific drivers (evdev, etc.) |
| 93 | +- `driver/stm32/`: STM32-specific drivers |
| 94 | + |
| 95 | +**Driver Types:** |
| 96 | +- **Pure Python**: Easiest to implement, runtime configurable |
| 97 | +- **Pure C**: Best performance, requires rebuild for config changes |
| 98 | +- **Hybrid**: Critical parts in C, configuration in Python |
| 99 | + |
| 100 | +### Memory Management |
| 101 | + |
| 102 | +- LVGL is configured to use MicroPython's garbage collector |
| 103 | +- Structs are automatically collected when no longer referenced |
| 104 | +- **Important**: Screen objects (`lv.obj` with no parent) are not auto-collected - call `screen.delete()` explicitly |
| 105 | +- Keep references to display and input drivers to prevent premature collection |
| 106 | + |
| 107 | +### Callback System |
| 108 | + |
| 109 | +**Callback Convention**: LVGL callbacks must follow specific patterns to work with MicroPython: |
| 110 | +- Struct containing `void * user_data` field |
| 111 | +- `user_data` passed as first argument to registration function and callback |
| 112 | +- The binding automatically manages `user_data` for MicroPython callable objects |
| 113 | + |
| 114 | +## Development Patterns |
| 115 | + |
| 116 | +### Configuration Management |
| 117 | + |
| 118 | +**Runtime Configuration**: Unlike typical LVGL C drivers, MicroPython drivers should allow runtime configuration: |
| 119 | + |
| 120 | +```python |
| 121 | +# Good - runtime configurable |
| 122 | +from ili9XXX import ili9341 |
| 123 | +display = ili9341(dc=32, cs=33, mosi=23, clk=18) |
| 124 | + |
| 125 | +# Avoid - requiring rebuild for pin changes |
| 126 | +``` |
| 127 | + |
| 128 | +### Adding New Drivers |
| 129 | + |
| 130 | +1. **Determine driver type** (Pure Python, C, or Hybrid) |
| 131 | +2. **Follow existing patterns** in `driver/` subdirectories |
| 132 | +3. **Make runtime configurable** - avoid hardcoded pins/settings |
| 133 | +4. **Implement standard interface**: |
| 134 | + - Display drivers: `flush_cb` method or automatic setup |
| 135 | + - Input drivers: `read_cb` method or automatic setup |
| 136 | + |
| 137 | +### Testing New Features |
| 138 | + |
| 139 | +1. **Add API tests** in `tests/api/` for automated testing |
| 140 | +2. **Add display tests** in `tests/display/` for visual verification |
| 141 | +3. **Follow existing test patterns** - see `tests/README.md` |
| 142 | +4. **Test on multiple platforms** when possible |
| 143 | + |
| 144 | +## Common Operations |
| 145 | + |
| 146 | +### Regenerating Bindings |
| 147 | + |
| 148 | +If you modify `lv_conf.h` or LVGL headers: |
| 149 | +```bash |
| 150 | +# Clean and rebuild to regenerate bindings |
| 151 | +make clean |
| 152 | +make USER_C_MODULES=/path/to/lv_binding_micropython/micropython.cmake |
| 153 | +``` |
| 154 | + |
| 155 | +### Testing Configuration Changes |
| 156 | + |
| 157 | +Use the examples to verify your changes: |
| 158 | +```bash |
| 159 | +# Run a simple test |
| 160 | +./build-lvgl/micropython examples/example1.py |
| 161 | + |
| 162 | +# Or run comprehensive tests |
| 163 | +cd tests && ./run.sh |
| 164 | +``` |
| 165 | + |
| 166 | +### Debugging Memory Issues |
| 167 | + |
| 168 | +- Use `gc.collect()` to trigger garbage collection |
| 169 | +- Call `screen.delete()` on screens when done |
| 170 | +- Keep driver references in global variables or long-lived objects |
| 171 | + |
| 172 | +## Integration Notes |
| 173 | + |
| 174 | +- This module requires MicroPython's internal scheduler to be enabled |
| 175 | +- LVGL task handler is called via `mp_sched_schedule` for screen refresh |
| 176 | +- Single-threaded design - LVGL and MicroPython run on same thread |
| 177 | +- Display drivers typically handle event loop setup automatically |
0 commit comments