diff --git a/docs/v0.1-mvp-technical.md b/docs/v0.1-mvp-technical.md index 50884a4..74ce9b0 100644 --- a/docs/v0.1-mvp-technical.md +++ b/docs/v0.1-mvp-technical.md @@ -45,7 +45,7 @@ blocked by I/O. | Task | Core | Stack | Responsibility | | ------------- | ---- | ----- | -------------------------------------------------------- | | `usb_task` | 0 | 8 KB | TinyUSB host loop, decode HID reports, post `KeyEvent`s | -| `wifi_task` | 0 | 8 KB | Station mode only (no provisioning AP); expose status | +| `wifi_task` | 0 | 8 KB | On-demand station: off by default, brought up by `Ctrl-G` | | `ui_task` | 1 | 16 KB | Consume `KeyEvent`s, mutate editor state, enqueue render | | `render_task` | 1 | 12 KB | Drain render queue, do partial/full refresh on EPD | | `git_task` | 1 | 32 KB | Triggered by `Ctrl-G`; runs gitoxide commit + push | @@ -67,7 +67,7 @@ read snapshot (render diff). └─ present → continue 5. Init SPI bus (shared: EPD + SD on different CS) 6. Init EPD, full refresh: splash + boot log -7. Start tasks: usb, wifi (station), ui, render +7. Start tasks: usb, wifi (spawned in `Off` state — no radio bring-up), ui, render 8. ui_task opens /sd/repo/notes.md, places cursor, enqueues full render 9. STEADY STATE ``` @@ -156,15 +156,32 @@ Storage split rationale: - The file is read fully into the rope at boot. v0.1 caps file size at 256 KB; larger files refuse to open with a clear message. -### `wifi` — provisioning + station +### `wifi` — on-demand station -- Provisioning: SoftAP `typewriter-setup`, captive-portal DNS, tiny HTTP - server (`esp-idf-svc::http`). Form submits config; on success, restart in - station mode. -- Station: reconnect with exponential backoff (1, 2, 5, 10, 30, 60 s, hold - at 60). Status exposed via a `WifiState` atomic enum. -- Time sync via SNTP — needed for commit timestamps. Failure is logged but - non-fatal; commits use device uptime if SNTP fails. +- **Off by default.** The radio is powered down (`esp_wifi_stop`) except + during a Publish and a short grace window after. This is the load-bearing + battery decision: always-on station mode burns ~410 mAh/day just for the + radio; on-demand is closer to ~25 mAh/day at 10 Publishes/day. See + [qfd.md H13](qfd.md#6-critical-performance-budget). +- **Bring-up on `Ctrl-G`.** `wifi_task` transitions `Off → Associating → + Connected`. Association timeout: 10 s. If association fails, the local + commit is preserved and the status line shows `⌁ ✗`; no background retry. +- **Grace window** of ~90 s after a Publish completes. A `Ctrl-G` inside + the window reuses the connection (no second association cost). If no + Publish fires before the window expires, the radio tears down. +- **No reconnect-backoff state machine.** There is nothing to reconnect to + when the user isn't trying to Publish. Single-shot try-on-demand replaces + the exponential-backoff approach. +- **SNTP** runs on the first successful bring-up of a power session. The + result is cached for up to 24 h; subsequent Publishes use the cached time + for the commit message. Falls back to device uptime if SNTP has never + succeeded — logged but non-fatal. +- **Status exposed via a `WifiState` atomic enum** (`Off`, `Associating`, + `Connected`, `Failed`). + +On-device provisioning (SSID, PAT rotation, etc.) is deliberately deferred +to v0.9. v0.1 reads all config from the binary at build time — see +"Provisioning — build-time only" below. ### `git` — commit + push