Add M0 milestone plan

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
This commit is contained in:
2026-10-01 18:29:07 +02:00
co-authored by Claude Opus 5.5
parent 87b6b845fb
commit fe3be01eec
+69
View File
@@ -0,0 +1,69 @@
# M0 — Skeleton: Launcher, Status Bar, Settings, battery
**Goal:** a firmware you can flash and hold. It boots to a Launcher, shows a live Status Bar, navigates with the keyboard and saves Settings. It proves the App/Service architecture that every later milestone plugs into.
## Done when
- Building, testing and flashing each work with one command, run inside a local Docker container (no toolchain on the host).
- First boot runs the setup wizard (names, Region, timezone), and later boots skip it.
- The Launcher lists Apps. Enter starts one, `` ` `` goes back, and Fn+`` ` `` returns home from anywhere.
- The Status Bar shows battery %, a charging indicator and the clock (relative until set), with placeholders for GNSS, mesh, Wi-Fi and unread count.
- The Settings App edits and persists: long and short name, Region, timezone, brightness, dim and off timeouts, sound on/off, and probe-request MAC handling (raw by default).
- An About screen shows the version, free heap, battery voltage, SD status and usage, and uptime.
- The screen dims at 30 s and turns off at 60 s. Any key wakes it without the key also acting on the App.
- A long press of G0 powers off (deep sleep). G0 or a key wakes the device.
- The Compose Key types accented characters in the line editor (`opt` `'` `e` → é).
- Toast Notifications work. A demo App can raise one, with a beep and LED flash.
- SD usage is watched: a Storage Warning appears once per boot above 80%. The Log-write cutoff flag is set at 90%, with no Log writers yet.
## Out of scope for M0
Storage Clean-up screen (M1, once IRC Logs exist), any radio, GNSS, Wi-Fi.
## Work breakdown
1. **Project scaffold**
- PlatformIO project with the pioarduino platform (Arduino-ESP32 3.x on ESP-IDF 5.x). Board `m5stack-stamps3`, 8 MB partitions, USB-CDC on boot.
- Dependencies: `M5Cardputer` (pulls in M5Unified and M5GFX).
- `LICENSE` (GPL-3.0), `README.md` with build and flash steps, a version string injected from git at build time (semver tags).
- A `native` environment for host-side unit tests (Unity).
- **Local CI** in a Docker image with PlatformIO. One script builds the firmware and runs the native tests, and the same container flashes over USB. The repo is hosted on self-hosted Gitea, and a Gitea Actions workflow can reuse this image later.
2. **Hardware bring-up checks** (manual, on the device)
- Display, keyboard (TCA8418) and speaker through M5Cardputer.
- Confirm there's no PSRAM, and record the heap at boot.
- Investigate the G38 backlight/LED power-rail coupling, then decide how dimming works without killing the LED.
- Battery ADC on G10 (×2 divider): calibrate the voltage-to-% curve.
- SD card mount on the shared SPI bus (CS=12), behind a bus lock ready for the LoRa radio in M3.
3. **Core runtime**
- **Event bus:** Services publish events (battery changed, notification, storage threshold), and the UI consumes them on the UI task.
- **Service interface:** start, stop, periodic tick, state snapshot for the Status Bar.
- **App interface:** enter, exit, key event, draw. Plus a registry, so adding an App means one file and one registration line.
- **App lifecycle:** one foreground App; Home and Back handling.
4. **Services for M0**
- **Settings store:** typed keys in NVS (internal flash), with defaults and change events.
- **Battery Service:** sampled voltage, smoothed %, charging detection if the hardware allows it.
- **Clock Service:** no time source yet. API for "set from source X", plus relative-time formatting and Europe/Brussels conversion.
- **Storage Service:** SD present/absent, usage %, 80% and 90% thresholds raising events, Log-write permission flag.
- **Power Service:** dim and off timers, wake-key swallowing, G0 long-press → deep sleep.
5. **Widget kit** (ADR 0002): an off-screen buffer pushed to the display.
- Status Bar, list, text view, line editor (with the Compose Key), dialog and Toast.
- A Latin-1 font set.
6. **Input layer**
- Map key events to logical keys: arrows (Fn + `;` `.` `,` `/`), Back, Home, Select.
- Compose Key dead-key state machine. This is pure logic, unit-tested on the host.
7. **Apps:** Launcher, Settings (including About), first-boot wizard, and a hidden Demo App for exercising Toasts and widgets.
8. **Docs:** a short walkthrough for a first-time setup: install PlatformIO, USB permissions on Linux, flash, recover via download mode.
## Host-tested logic (TDD candidates)
- Compose Key state machine
- Battery voltage → % curve and smoothing
- Storage threshold and once-per-boot warning logic
- Relative-time formatting and timezone conversion
- Settings defaults and validation (e.g. Region must be confirmed before any transmit flag)
## Risks to resolve early
- **G38 shared rail:** if the backlight and LED really share power, "screen off" may also need to turn the LED off.
- **RAM headroom:** the off-screen buffer is 240×135×2 ≈ 64 KB at 16-bit, or about 32 KB at 8-bit. Measure the free heap now, because Wi-Fi + TLS (M1) is the tightest point.
- **Keyboard library maturity** for the ADV's TCA8418 in `M5Cardputer`. Fall back to Adafruit_TCA8418 directly if needed.