rlvgl 0.2.4

A modular, idiomatic Rust reimplementation of the LVGL graphics library for embedded and simulator use.
Documentation
<!--
src/bin/creator/README.md - Guide to the rlvgl-creator binary workflows.
-->
<p align="center">
  <img src="../../../rlvgl-logo.png" alt="rlvgl" />
</p>

# rlvgl-creator

A combined UI and command-line tool for normalizing assets and generating dual-mode assets crates for rlvgl projects. Running without arguments launches the desktop UI; providing arguments executes the CLI. This guide covers the end-to-end workflow from initialization to consumption.

## Workflow

1. **Initialize folders and manifest**
   ```sh
   cargo run --bin rlgvl-creator --features creator,creator_ui -- init
   ```
   Creates `icons/`, `fonts/`, `media/`, and a `manifest.yml` in the working directory.

2. **Scan for new or changed assets**
   ```sh
   cargo run --bin rlgvl-creator --features creator,creator_ui -- scan .
   ```
   Updates hashes in the manifest for assets under the allowed roots.

3. **Convert assets into raw sequences and font packs**
   ```sh
   cargo run --bin rlgvl-creator --features creator,creator_ui -- convert
   ```
   Raster images become raw RGBA sequences, and fonts are packed into bitmap binaries and metrics. Conversions run in parallel
   with stable ordering. Use `--force` to rebuild all assets regardless of cache.

   To render vector assets, the `svg` command converts an SVG into one or more raw images at chosen DPI values:
   ```sh
   cargo run --bin rlgvl-creator --features creator,creator_ui -- svg logo.svg out/ --dpi 96 --dpi 192
   ```
   Supply `--threshold <VAL>` to apply a monochrome cutoff suitable for e-ink displays.

4. **Synchronize feature flags, constants, and index**
   ```sh
   cargo run --bin rlgvl-creator --features creator,creator_ui -- sync
   ```
   Regenerates manifest-driven code without touching asset bytes.

5. **Scaffold a consumer assets crate**
   ```sh
   cargo run --bin rlgvl-creator --features creator,creator_ui -- scaffold assets-crate
   ```
   Generates a crate with `embed` and `vendor` features that exposes your processed assets.

6. **Vendor assets for build output**
   ```sh
   cargo run --bin rlgvl-creator --features creator,creator_ui -- vendor
   ```
   Copies processed assets to `$OUT_DIR` and emits an `rlvgl_assets.rs` module for inclusion.

The resulting crate can be built with `--features embed` to include raw bytes or `--features vendor` to copy files at build time while importing the generated module.

## BSP Generation

`rlvgl-creator` can generate board support crates from two different vendor
inputs:

### STM32 (.ioc input)

```sh
cargo run --bin rlgvl-creator --features creator -- bsp from-ioc \
    path/to/board.ioc --out gen/ --emit-hal --emit-pac
```

Runs the STM32 CubeMX `.ioc` → generic IR → MiniJinja → Rust pipeline
using the embedded `rlvgl-chips-stm` alternate-function database. Supports
HAL, PAC, and custom MiniJinja templates, single-file and per-peripheral
layouts, label-based identifier generation, and STM32H7 dual-core splits.

### Espressif (YAML chipdb input)

```sh
cargo run --bin rlgvl-creator --features creator -- bsp from-yaml \
    --vendor esp \
    --board esp32c3_devkitm_1 \
    --out gen/ \
    --emit-pac
```

Consumes the YAML chip and board specs embedded in `rlvgl-chips-esp` and
emits a PAC-style BSP targeting the `esp32c3` PAC crate. Each board spec
identifies its chip by name; `--chip` / `--chip-yaml` / `--board-yaml` are
available to override the chipdb lookups for out-of-tree data.

The generated BSP consists of six files under `gen/<board_stem>/`:

- `mod.rs``pub mod board; pub mod clocks; pub mod io_mux; pub mod pac;
  pub mod peripherals; pub use pac::init;`
- `pac.rs``pub fn init()` entry sequencing clocks → IO MUX → peripherals
- `clocks.rs``SYSTEM` peripheral clock enables and resets
- `io_mux.rs` — per-pin IO MUX / GPIO matrix routing
- `peripherals.rs` — per-instance init (UART0 real when it is the console,
  others stubbed with TODOs pointing at the PAC register path)
- `board.rs` — board constants and labeled pin consts (`LED`, `BOOT_BTN`, …)

Overrides:

| Flag            | Effect                                              |
|-----------------|-----------------------------------------------------|
| `--vendor`      | Vendor backend: `esp`, `nrf`, `nxp`, `rp`, `renesas` (aliases: `espressif`, `nordic`, `imxrt`, `rp2040`, `ra`) |
| `--cpu-hz`      | Override the resolved CPU frequency in hertz        |
| `--baud`        | Override the console baud rate                      |
| `--chip`        | Use a different chip spec file stem (default: esp32c3) |
| `--chip-yaml`   | Load chip spec from a file (bypasses chipdb)        |
| `--board-yaml`  | Load board spec from a file (bypasses chipdb)       |

Add or edit chips and boards by dropping new YAML files into
`chipdb/rlvgl-chips-esp/db/chips/` and `chipdb/rlvgl-chips-esp/db/boards/`
and rebuilding.

### Nordic nRF (YAML chipdb input)

```sh
cargo run --bin rlgvl-creator --features creator -- bsp from-yaml \
    --vendor nrf \
    --board nrf52840_dk \
    --out gen/ \
    --emit-pac
```

Consumes the YAML chip and board specs embedded in `rlvgl-chips-nrf` and
emits a PAC-style BSP targeting the `nrf52840_pac` PAC crate. Uses
PSEL-based pin routing for peripheral-to-pin assignment.

The generated BSP consists of six files under `gen/<board_stem>/`:

- `mod.rs` — module index
- `pac.rs``pub fn init()` entry sequencing clocks, GPIO, peripherals
- `clocks.rs` — clock configuration
- `gpio.rs` — PSEL-based pin routing for each peripheral
- `peripherals.rs` — per-instance peripheral init
- `board.rs` — board constants and labeled pin consts

### NXP i.MX RT (YAML chipdb input)

```sh
cargo run --bin rlgvl-creator --features creator -- bsp from-yaml \
    --vendor nxp \
    --board mimxrt1060_evkb \
    --out gen/ \
    --emit-pac
```

Consumes the YAML chip and board specs embedded in `rlvgl-chips-nxp` and
emits a BSP targeting the `imxrt_ral` register access layer. Uses IOMUX
ALT0-7 pad routing with daisy chain SELECT_INPUT muxing and CCM CCGR
clock gating.

The generated BSP consists of six files under `gen/<board_stem>/`:

- `mod.rs` — module index
- `pac.rs``pub fn init()` entry sequencing clocks, IOMUX, peripherals
- `clocks.rs` — CCM CCGR clock-gate enables
- `iomux.rs` — per-pad ALT mux + daisy chain SELECT_INPUT routing
- `peripherals.rs` — per-instance peripheral init
- `board.rs` — board constants and labeled pin consts

### RP2040 (YAML chipdb input)

```sh
cargo run --bin rlgvl-creator --features creator -- bsp from-yaml \
    --vendor rp \
    --board pico \
    --out gen/ \
    --emit-pac
```

Consumes the YAML chip and board specs embedded in `rlvgl-chips-rp2040`
and emits a BSP targeting the `rp2040_pac` PAC crate. Uses FUNCSEL
per-GPIO pin routing and RESETS register for peripheral reset release (no
clock gating).

The generated BSP consists of six files under `gen/<board_stem>/`:

- `mod.rs` — module index
- `pac.rs``pub fn init()` entry sequencing clocks, GPIO, peripherals
- `clocks.rs` — clock and RESETS configuration
- `gpio.rs` — per-GPIO FUNCSEL routing
- `peripherals.rs` — per-instance peripheral init
- `board.rs` — board constants and labeled pin consts

### Renesas RA (YAML chipdb input)

```sh
cargo run --bin rlgvl-creator --features creator -- bsp from-yaml \
    --vendor renesas \
    --board ek_ra6m5 \
    --out gen/ \
    --emit-pac
```

Consumes the YAML chip and board specs embedded in `rlvgl-chips-renesas`
and emits a BSP using raw register addresses (no PAC crate). Uses PFS
PSEL + PMR pin routing and MSTP clock gating.

The generated BSP consists of six files under `gen/<board_stem>/`:

- `mod.rs` — module index
- `pac.rs``pub fn init()` entry sequencing clocks, PFS, peripherals
- `clocks.rs` — MSTP clock-gate enables
- `pfs.rs` — PFS PSEL + PMR pin function select and routing
- `peripherals.rs` — per-instance peripheral init
- `board.rs` — board constants and labeled pin consts

## Application Schema (`app from-yaml`)

Consume an [`app.yaml`](../../../docs/app-schema/01-manifest-schema.md)
manifest (`schema: rlvgl-app/v0`) and emit a buildable Cargo crate
scaffold per [chapter 02](../../../docs/app-schema/02-generator-pipeline.md).
The orchestrator drives the BSP generator, asset pipeline, vendored
SM-crate consumption, i18n + theme translators, and per-prong main
glue from one declarative manifest.

```sh
cargo run --bin rlvgl-creator --features creator -- app from-yaml \
    examples/beetle-esp32c3/app-bsp-pac.yaml \
    --out /tmp/rlvgl-beetle-bsp-pac
```

Validate-only (no emission):

```sh
cargo run --bin rlvgl-creator --features creator -- app from-yaml \
    --validate-only examples/beaglebone-black/app.yaml
```

CI determinism gate — emit to a temp dir and diff against `--out`
byte-for-byte (chapter 02 §5.2 `--check`):

```sh
cargo run --bin rlvgl-creator --features creator -- app from-yaml \
    --check examples/beetle-esp32c3/app-bsp-pac.yaml \
    --out /tmp/rlvgl-beetle-bsp-pac
```

`--force` overwrites files in `<out>` that aren't recorded in the
previous inventory at `<out>/.rlvgl-app-manifest.json`.

`--jobs N` (default 1) parallelises the independent stage-3
sub-generators (BSP-gen, asset-pipeline, SM-gen, i18n, theme) via
`std::thread::scope`. Output is byte-deterministic regardless of N
per chapter 02 §9.1.

Five committed manifests exercise the full grammar:

- `examples/beetle-esp32c3/app.yaml` — esp_hal SSD1306 demo
  (`generator: hosted`)
- `examples/beetle-esp32c3/app-bsp-pac.yaml` — raw-PAC LED blink
  (`generator: creator-bsp-pac`, exercises BSP-gen)
- `examples/beaglebone-black/app.yaml` — BBB Linux prong with
  cross-tree splash asset
- `examples/stm32h747i-disco/app.yaml` — H747 FreeRTOS prong
  (`generator: hand_written`)
- `examples/stm32h747i-disco/app-zephyr.yaml` — H747 Zephyr prong
  with nested west project

State machines vendor a pre-generated SM crate under
`state_machine.vendored_crate` per
[chapter 04 §5.3](../../../docs/app-schema/04-state-machine-boundary.md#53-vendored-crate-offline-model--frozen);
the orchestrator never invokes the external `mcp-statechart` tool
during emission.

### Authoring lifecycle

Three sibling subcommands round out the manifest workflow:

```sh
# Scaffold a starter manifest + minimal layout (cargo-new style).
# Refuses to overwrite an existing path.
cargo run --bin rlvgl-creator --features creator -- app new my-app

# Human-readable summary: target, controller, state machine,
# asset histogram, screens, theme, i18n, eligible stage-3 stages.
# Validates the manifest first.
cargo run --bin rlvgl-creator --features creator -- app inspect my-app/app.yaml

# Emit a JSON Schema for the rlvgl-app/v0 manifest grammar.
# Useful for editor validation (VS Code YAML extension, etc.) and
# CI lint hooks. Captures chapter 01 §5 grammar; runtime cross-
# reference rules (chipdb lookup, path safety) still need the
# full validator.
cargo run --bin rlvgl-creator --features creator -- app schema --out app.schema.json
```

Together these form the authoring loop:

```
app new <NAME>                           # scaffold
app inspect <NAME>/app.yaml              # check the summary
app from-yaml --validate-only ...        # rule check
app from-yaml ... --out <DIR>            # emit
app from-yaml --check ... --out <DIR>    # CI determinism gate
```

## Desktop UI and Emulator

Launch the desktop UI explicitly:

```sh
cargo run --bin rlgvl-creator --features creator,creator_ui -- ui
```

Run the simulator from the same binary:

```sh
cargo run --bin rlgvl-creator --features creator,creator_ui -- sim --screen=800x480 --png --qrcode
```

## Developer Notes

For details on customizing scaffold templates and extending the conversion pipeline, see
[`docs/creator/TEMPLATES.md`](../../../docs/creator/TEMPLATES.md).