Repository navigation
Decouple screen lifecycle, fix input drops, PNG screenshot reference - #5
Conversation
Add a root west.yml so the repository works as a west manifest repository: clone + west init -l + west update is all that is needed to get a buildable LVGL application, without the project creator. - Pin Zephyr v4.4.0 and allowlist only the modules needed by the supported boards (LVGL + vendor HALs + MCUboot/mbedTLS for ESP32) - Modernize main.c for the current LVGL module API (lvgl_zephyr.h, lvgl_lock/lvgl_unlock, optional workqueue-driven rendering) - Build demo sources conditionally and add the new widgets demo files - Add native_sim configs so the app runs on the desktop via SDL Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Rewrite README around clone + west init -l + west update - Fix FRDM-MCXN947 shield (lcd_par_s035_8080; the spi variant no longer applies to this board) and rename its conf fragment to the fully qualified board name so it is picked up again - Fix M5Stack Core2 manifest description (was copy-pasted from the MIMXRT1170-EVK entry) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The manifest repository is now itself the application: CMakeLists.txt,
prj.conf, boards/ and src/ live at the root, and the deps/ path prefix
is gone so the workspace is {lv_zephyr, zephyr, modules, bootloader}.
This lets users run plain 'west build -b <board>' from inside the
repository without passing an application path.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Restore the deps path-prefix so the workspace separates editable code (lv_zephyr/) from what west downloads (deps/zephyr, deps/modules, deps/bootloader). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Move west.yml to manifest/ so 'west init -l manifest' run from the repository root makes the repo itself the workspace topdir. Zephyr and all modules then land in the git-ignored deps/ folder inside the clone, keeping a clean separation between code users edit (tracked) and code west downloads (ignored), without polluting the clone's parent directory. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Define the lvgl project explicitly instead of allowlisting the one imported from Zephyr's manifest, pointing at the upstream LVGL repository. Users can now pick any LVGL tag, branch or commit by changing one revision line. The default (v9.5.0) is the exact commit Zephyr v4.4.0 bundles, so out of the box nothing changes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Pin the standalone lvgl project to the exact commit Zephyr v4.4.0 bundles (== v9.5.0) and document, both in the manifest and the README, how to point it at any lvgl/lvgl tag, branch or commit instead. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
GitHub Actions workflow building the simulator and all five boards in the Zephyr CI container, plus a screenshot test: the app built with tests/screenshot.conf renders the demo on native_sim headless (dummy SDL driver), captures the settled UI via lv_snapshot into a BMP, and CI compares it against a committed reference image with a stdlib-only script (1% pixel tolerance, diff visualization uploaded as artifact). The capture mode lives in src/screenshot.c behind CONFIG_APP_SCREENSHOT (native_sim only) and exits the process after writing the file, so the same binary serves interactive use and CI. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR converts the repository into a self-contained Zephyr workspace application (local west manifest + updated docs/CI), adds a native_sim screenshot CI test harness (capture + pixel-diff script), and refreshes board/project-creator metadata and per-board config overrides.
Changes:
- Add west-manifest-based workspace layout (
manifest/west.yml), new CI workflow, and expanded README with setup/testing instructions. - Add screenshot capture path (LVGL snapshot → BMP) and a stdlib-only BMP comparison script + native_sim screenshot test config.
- Add/update per-board Kconfig/overlay defaults and update project-creator JSON manifests.
Reviewed changes
Copilot reviewed 20 out of 28 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
tests/screenshot.conf |
Extra Kconfig for native_sim screenshot CI run (enables snapshot, enlarges LVGL pool, disables flaky overlays). |
tests/compare_screenshots.py |
New stdlib BMP reader/comparator and optional diff visualization writer. |
src/screenshot.h |
Declares screenshot polling API for capture-on-idle behavior. |
src/screenshot.c |
Implements LVGL snapshot capture and BMP writing, exiting after saving. |
src/main.c |
New app entrypoint with LVGL locking, demo UI creation, and optional screenshot polling. |
README.md |
Major rewrite: workspace layout, build/run instructions, and screenshot test docs. |
prj.conf |
New baseline Kconfig for LVGL + demo widgets + shell/logging. |
manifests/stm32u5g9j-dk2.json |
Updates “get started” instructions formatting and content. |
manifests/m5stack_core2.json |
Updates description/instructions and normalizes typography. |
manifests/imxrt1170-evk.json |
Updates “get started” instructions and normalizes typography. |
manifests/frdm-mcxn947.json |
Updates “get started” instructions formatting and content. |
manifests/ek-ra8d1.json |
Updates “get started” instructions formatting and content. |
manifest/west.yml |
New west manifest to fetch Zephyr + allowlisted modules under deps/. |
Kconfig |
Adds APP_SCREENSHOT option (ARCH_POSIX) for CI screenshot mode. |
CMakeLists.txt |
Renames project, adds LVGL demo sources, and conditional widget demo sources. |
boards/stm32u5g9j_dk2.conf |
Board-specific LVGL memory/alignment overrides. |
boards/native_sim.overlay |
Sets SDL display controller resolution. |
boards/native_sim.conf |
native_sim LVGL color depth config. |
boards/native_sim_native_64.overlay |
Sets SDL display controller resolution (native/64). |
boards/native_sim_native_64.conf |
native_sim/native/64 LVGL color depth + pool size. |
boards/mimxrt1170_evk_mimxrt1176_cm7.conf |
Enables DMA/PXP settings for this target. |
boards/m5stack_core2_procpu.conf |
Adjusts main stack size for ESP32 target. |
boards/frdm_mcxn947_mcxn947_cpu0.conf |
Board-specific LVGL pool/DMA/stack overrides. |
boards/ek_ra8d1.conf |
Board-specific LVGL memory/alignment overrides. |
application/src/main.c |
Removes the previous application main (migrated to src/main.c). |
.gitignore |
Ignores west/deps/build outputs and screenshot artifacts. |
.github/workflows/ci.yml |
New CI: matrix builds + native_sim screenshot compare + artifact upload. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| FILE *f = fopen(path, "wb"); | ||
|
|
||
| if (f == NULL) { | ||
| return -1; | ||
| } | ||
| fwrite(header, 1, sizeof(header), f); | ||
| for (int32_t y = (int32_t)h - 1; y >= 0; y--) { | ||
| fwrite(img->data + (uint32_t)y * stride, 1, w * 3u, f); | ||
| fwrite(pad, 1, row_size - w * 3u, f); | ||
| } | ||
| fclose(f); | ||
| return 0; |
| CI ([.github/workflows/ci.yml](.github/workflows/ci.yml)) builds the | ||
| application for the simulator and every supported board on each pull | ||
| request, and runs a screenshot test: the app is built for native_sim with | ||
| [tests/screenshot.conf](tests/screenshot.conf), run headless, and the | ||
| rendered UI is captured with LVGL's snapshot feature and compared against | ||
| [tests/screenshot-reference.bmp](tests/screenshot-reference.bmp) (small | ||
| tolerance for anti-aliasing differences). To run it locally: | ||
|
|
||
| ```sh | ||
| west build -p -b native_sim/native/64 -- -DEXTRA_CONF_FILE=tests/screenshot.conf | ||
| SDL_VIDEODRIVER=dummy SDL_RENDER_DRIVER=software ./build/zephyr/zephyr.exe | ||
| python3 tests/compare_screenshots.py tests/screenshot-reference.bmp screenshot.bmp diff.bmp | ||
| ``` | ||
|
|
||
| After an intentional UI change, regenerate the reference by replacing | ||
| `tests/screenshot-reference.bmp` with the new `screenshot.bmp` (CI also | ||
| uploads the captured screenshot and a diff visualization as artifacts on | ||
| every run). |
There was a problem hiding this comment.
1 issue found across 28 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| @@ -0,0 +1,95 @@ | |||
| /* | |||
There was a problem hiding this comment.
Should we use LVGL's screenshot utility instead of using bmp files?
https://lvgl.io/docs/open/debugging/test#screenshot-comparison
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
681fc7a to
031c231
Compare
There was a problem hiding this comment.
1 issue found across 1 file (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="README.md">
<violation number="1" location="README.md:26">
P1: The prerequisite instructions point readers to Zephyr's 'Get Zephyr and install Python dependencies' section, which includes `west zephyr-export` and `west packages pip --install`. The note then says to skip the source checkout because this repo's `west init`/`west update` happens later in Quick start. But in the official guide those commands come *after* the source checkout and need the checked-out `zephyr/` tree (`west packages pip --install` reads requirements from the workspace). A literal follower will either be unable to finish the prerequisites before Quick start, or will try to install dependencies in the wrong order. Please update the note to explicitly defer the source checkout, `west zephyr-export`, and `west packages pip --install` until after Quick start's `west update`, and then add those two commands to the Quick start sequence.</violation>
</file>
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
| 3. **Install the Zephyr SDK** — the | ||
| [compiler toolchains](https://docs.zephyrproject.org/latest/develop/toolchains/zephyr_sdk.html). | ||
|
|
||
| In section 2 you can skip sub-step 4 ("Get the Zephyr source code"): this |
There was a problem hiding this comment.
P1: The prerequisite instructions point readers to Zephyr's 'Get Zephyr and install Python dependencies' section, which includes west zephyr-export and west packages pip --install. The note then says to skip the source checkout because this repo's west init/west update happens later in Quick start. But in the official guide those commands come after the source checkout and need the checked-out zephyr/ tree (west packages pip --install reads requirements from the workspace). A literal follower will either be unable to finish the prerequisites before Quick start, or will try to install dependencies in the wrong order. Please update the note to explicitly defer the source checkout, west zephyr-export, and west packages pip --install until after Quick start's west update, and then add those two commands to the Quick start sequence.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At README.md, line 26:
<comment>The prerequisite instructions point readers to Zephyr's 'Get Zephyr and install Python dependencies' section, which includes `west zephyr-export` and `west packages pip --install`. The note then says to skip the source checkout because this repo's `west init`/`west update` happens later in Quick start. But in the official guide those commands come *after* the source checkout and need the checked-out `zephyr/` tree (`west packages pip --install` reads requirements from the workspace). A literal follower will either be unable to finish the prerequisites before Quick start, or will try to install dependencies in the wrong order. Please update the note to explicitly defer the source checkout, `west zephyr-export`, and `west packages pip --install` until after Quick start's `west update`, and then add those two commands to the Quick start sequence.</comment>
<file context>
@@ -12,15 +12,22 @@ so you do **not** need a pre-existing Zephyr installation or any extra tooling.
+ [compiler toolchains](https://docs.zephyrproject.org/latest/develop/toolchains/zephyr_sdk.html).
-To run the simulator on your PC you also need SDL2
+In section 2 you can skip sub-step 4 ("Get the Zephyr source code"): this
+repository is already its own west workspace, so `west init`/`west update` are
+covered by the [Quick start](#quick-start) below. Running it anyway is harmless.
</file context>
Zephyr compiles LVGL from a source list bundled with Zephyr, so a custom
LVGL revision that adds/removes files (or needs a config value forced) can
break the build. Add a documented way to adjust the LVGL module build
without patching Zephyr or LVGL, via CMake's built-in CMAKE_PROJECT_INCLUDE:
west build -b <board> -- -DCMAKE_PROJECT_INCLUDE=$PWD/zephyr-with-custom-lvgl.cmake
- zephyr-with-custom-lvgl.cmake: ready-to-edit hook with patterns to add or
remove LVGL sources and override config values (targets modules__lvgl, app).
- README: "Customizing the LVGL build" section documenting the workflow.
- tests/screenshot.c: allow overriding the reference base path at run time via
the LV_Z_SCREENSHOT_REFERENCE env var (test-only, so no Kconfig option).
- CI: extend the screenshot job to inject tests/screenshot-dark.cmake (forces
the dark theme) and compare against a dedicated dark reference. Matching a
dedicated reference - not merely differing from the default - catches a hook
that silently stops applying; the reference is chosen at run time, keeping it
independent of the hook under test.
There was a problem hiding this comment.
1 issue found across 5 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name=".github/workflows/ci.yml">
<violation number="1" location=".github/workflows/ci.yml:47">
P2: The conditional esptool install inside the `if` block is redundant: esptool was already installed unconditionally on the line above. The `if` block never has a unique effect. Plus, esptool is now installed unnecessarily for the `hal_renesas` blob type (ek_ra6m3). Move the install inside the conditional and remove the unconditional line so esptool is only installed when it's actually needed.</violation>
</file>
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
| if: matrix.blobs | ||
| run: | | ||
| PIP_BREAK_SYSTEM_PACKAGES=1 pip3 install "esptool>=5.0.2" | ||
| if [ "${{ matrix.blobs }}" = "hal_espressif" ]; then |
There was a problem hiding this comment.
P2: The conditional esptool install inside the if block is redundant: esptool was already installed unconditionally on the line above. The if block never has a unique effect. Plus, esptool is now installed unnecessarily for the hal_renesas blob type (ek_ra6m3). Move the install inside the conditional and remove the unconditional line so esptool is only installed when it's actually needed.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/ci.yml, line 47:
<comment>The conditional esptool install inside the `if` block is redundant: esptool was already installed unconditionally on the line above. The `if` block never has a unique effect. Plus, esptool is now installed unnecessarily for the `hal_renesas` blob type (ek_ra6m3). Move the install inside the conditional and remove the unconditional line so esptool is only installed when it's actually needed.</comment>
<file context>
@@ -37,11 +38,15 @@ jobs:
if: matrix.blobs
run: |
PIP_BREAK_SYSTEM_PACKAGES=1 pip3 install "esptool>=5.0.2"
+ if [ "${{ matrix.blobs }}" = "hal_espressif" ]; then
+ PIP_BREAK_SYSTEM_PACKAGES=1 pip3 install "esptool>=5.0.2"
+ fi
</file context>
Summary
Full update and refactor of the example project.