Add a cross-platform SDL emulator for developing the goggle UI without hardware#617
Add a cross-platform SDL emulator for developing the goggle UI without hardware#617christhomas wants to merge 1 commit into
Conversation
42f50bc to
a50ee05
Compare
Adds a desktop build of the goggle UI (Linux/macOS/Windows) that runs the real
application code -- the same main(), menu system, OSD and page logic that ships
on the goggle -- rendered through SDL2 instead of the framebuffer, with the
hardware peripherals replaced by compiled-in mocks. This lets the LVGL interface
be developed, previewed and regression-tested without hardware.
Build and run:
.devcontainer/build.sh {images,linux,windows,mac} build (in a container)
./run-native.sh run natively on the host
Every target compiles inside a devcontainer image, so builds are reproducible and
need no host toolchain; the resulting binary runs natively on its OS. macOS is
cross-compiled to Mach-O in the container too (LLVM/clang); its SDK is staged once
from your Xcode since Apple's is not redistributable. CI is the one place macOS
builds natively -- on a macos-latest runner -- because CI can't stage that SDK.
Zero cost to the firmware: all emulator code lives behind EMULATOR_BUILD or in
src/emulator/*, which CMake compiles only for the emulator, so the goggle binary
contains none of it. Hardware drivers that genuinely differ (UART, I2C, RTC, the
framebuffer) are split into per-target files selected by CMake, keeping the goggle
drivers free of emulator #ifdefs.
Peripherals are mocked at their hardware seam, so the app itself is unchanged:
- display engine -> SDL2 window + software compositor
- DM5680 video -> decodes a looping MPEG-1 clip (vendored pl_mpeg; no ffmpeg
is linked) behind the OSD, and only in the video view
- DM5680 serial -> socketpair-backed UART + a mock answering version/RSSI
- I2C bus, RTC -> no-op bus, in-memory clock
- system_exec -> logged and skipped, so device shell commands (display pokes,
register writes, wifi/passwd scripts) never touch the host
Also included: configurable filesystem roots (path_app/path_extsd from config+env,
compiled away on the goggle), POSIX compat shims for macOS/Windows hosts, a fix for
ATOMIC_VAR_INIT removed on newer toolchains (which the emulator build requires; also
offered standalone), and CI that builds all three targets on every push with a
headless screenshot, publishing binaries on a semver tag.
a50ee05 to
1c980e3
Compare
|
AI Generated comment Problem: Proposed solution: Have |
|
AI Generated comment Not authoritative — flagging for consideration, deferring to the author's judgment on implementation. Problem: Some floor has to be fixed regardless of implementation — whether via an older base image, a fully static build, or explicit glibc-ABI targeting in the toolchain, all three amount to picking a minimum glibc version the output supports. Tracking whatever LTS is newest leaves that floor undefined and drifting upward every two years. Proposed solution: Pin the build environment to a deliberately conservative glibc floor. Simplest: change |
Adds a desktop build of the goggle UI (Linux, macOS, Windows) that runs the real
application code — the same
main(), menu system, OSD and page logic that ships on thegoggle — rendered through SDL2 instead of the framebuffer, with the hardware peripherals
replaced by compiled-in mocks.
The aim is to make the LVGL interface developable and previewable without hardware, and
to give CI a way to catch UI/driver regressions on every push.
Build and run
Every target compiles inside a devcontainer image, so builds are reproducible and need
no host toolchain; the resulting binary runs natively on its OS. macOS is the one exception
and builds on a mac, since a cross image would need Apple's non-redistributable SDK.
Zero cost to the firmware
All emulator code sits behind
EMULATOR_BUILDor insrc/emulator/*, which CMake compilesonly for the emulator — the goggle firmware binary contains none of it. Hardware drivers
that genuinely differ (UART, I2C, RTC, the framebuffer) are split into per-target files
selected by CMake, so the goggle drivers carry no emulator
#ifdefs.Verified by building the firmware from this branch: it compiles unchanged, with zero
emulator objects linked in.
What's mocked (at the hardware seam, so the app itself is untouched)
pl_mpeg; no ffmpeg is linked) behind the OSD, and only in the video viewsystem_exec)Also included: configurable filesystem roots (
path_app()/path_extsd()from a config file/mnt/appand/mnt/extsddefaults areunchanged), and POSIX compat shims for macOS/Windows hosts.
CI
.github/workflows/build_emulator.ymlbuilds all three targets on every push/PR with aheadless screenshot as a regression check, and publishes per-platform binaries on a semver
tag. The existing firmware workflows are untouched (and pass on this branch).
Notes
ATOMIC_VAR_INITfix), which the emulator build requires and whichthis branch therefore includes. Once Fix build on newer toolchains where ATOMIC_VAR_INIT was removed #616 merges, this rebases down to a single commit.
docs/emulator.md.