Replace TODO with agent backlog and refresh READMEs.

Adopt the prioritised task list for the coding agent and document
fw 0.7.0 status plus the full HTTP API in Software/README.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-06 23:26:24 +02:00
co-authored by Cursor
parent 82c9f401da
commit 8cd962ee25
3 changed files with 166 additions and 57 deletions
+5 -2
View File
@@ -67,7 +67,7 @@ DigiRadio/
│ ├── pick-and-place/ Component placement (CPL / centroid) │ ├── pick-and-place/ Component placement (CPL / centroid)
│ ├── easyeda/ EasyEDA source project │ ├── easyeda/ EasyEDA source project
│ └── 3d/ 3D renders / STEP │ └── 3d/ 3D renders / STEP
└── Software/ Firmware (in development — see Software/README.md) └── Software/ Firmware (ESP-IDF — see Software/README.md, docs/TODO.md)
``` ```
--- ---
@@ -80,6 +80,9 @@ ADAU1701, FSC-BT1035), the HTTP JSON API, and build instructions. LaTeX
sources live in `Software/docs/manual/`; the repository root `docs/` entry sources live in `Software/docs/manual/`; the repository root `docs/` entry
is a symbolic link to that folder (single source of truth). is a symbolic link to that folder (single source of truth).
Firmware development backlog and agent tasks:
[`Software/docs/TODO.md`](Software/docs/TODO.md).
--- ---
## Design Highlights ## Design Highlights
@@ -101,7 +104,7 @@ is a symbolic link to that folder (single source of truth).
-**PCB layout** — 6-layer, DRC clean, plane continuity verified -**PCB layout** — 6-layer, DRC clean, plane continuity verified
-**BOM** — finalised (manufacturable / sourced) -**BOM** — finalised (manufacturable / sourced)
- 🔜 **Prototype** — in fabrication (PCBWay) - 🔜 **Prototype** — in fabrication (PCBWay)
- 🛠️ **Firmware**in active development (released after bring-up) - 🛠️ **Firmware**fw 0.7.0 on `main` (tuner, DSP, BT pairing, presets); see [`Software/docs/TODO.md`](Software/docs/TODO.md)
--- ---
+31 -8
View File
@@ -2,7 +2,9 @@
Open-source Hi-Fi DAB+/FM receiver firmware for the ESP32-S3. Open-source Hi-Fi DAB+/FM receiver firmware for the ESP32-S3.
**Status:** Slice 3 — Si4684 + ADAU1701 boot at power-up (network from Slice 2). **Status:** fw **0.7.0** — companion-chip boot (Si4684, ADAU1701, BT1035),
Wi-Fi provisioning, tuner/audio REST API, Bluetooth pairing, station presets.
See [`docs/TODO.md`](docs/TODO.md) for the agent task list.
## Quick start ## Quick start
@@ -24,7 +26,7 @@ cmake --build build-host
ctest --test-dir build-host --output-on-failure ctest --test-dir build-host --output-on-failure
``` ```
Documentation (must exit 0): Documentation gates (must exit 0 before merging):
```bash ```bash
doxygen Doxyfile doxygen Doxyfile
@@ -37,26 +39,47 @@ Manual PDF (design + HTTP API + class reference):
cd docs/manual && latexmk -lualatex manual.tex cd docs/manual && latexmk -lualatex manual.tex
``` ```
## HTTP API (fw 0.3.0) ## HTTP API (fw 0.7.0)
| Method | Path | Purpose | | Method | Path | Purpose |
|--------|------|---------| |--------|------|---------|
| GET | `/api/health` | `{"status":"ok","fw":"0.3.0"}` | | GET | `/api/health` | Status, firmware version, companion-chip flags |
| POST | `/api/wifi` | Provision STA credentials; reboot on success | | POST | `/api/wifi` | Provision STA credentials; reboot on success |
| GET | `/api/tuner/status` | Tuner snapshot (DAB/FM) |
| GET | `/api/tuner/services` | DAB service list for current ensemble |
| POST | `/api/tuner/tune` | Tune DAB ensemble or FM frequency |
| POST | `/api/tuner/play` | Start DAB service playback |
| POST | `/api/tuner/seek` | FM seek up |
| GET/PUT | `/api/audio/profile` | Read/apply ADAU1701 mixer + EQ profile |
| POST | `/api/audio/reset` | Factory-flat audio profile |
| POST | `/api/audio/stereo-enhance` | Stereo depth overlay (0100) |
| POST | `/api/audio/bass-enhance` | Bass enhance overlay (0100) |
| GET | `/api/bluetooth/status` | BT1035 boot, pairing, A2DP state |
| POST | `/api/bluetooth/pair` | Enter discoverable mode |
| POST | `/api/bluetooth/pair/stop` | Leave discoverable mode |
| POST | `/api/bluetooth/disconnect` | Release A2DP session |
| GET | `/api/stations` | List saved presets |
| POST | `/api/stations` | Add preset |
| POST | `/api/stations/remove` | Remove preset by index |
| POST | `/api/stations/tune` | Recall preset on tuner |
Full schemas, error tokens, and boot flow: [`docs/manual/ch-api.tex`](docs/manual/ch-api.tex). Full schemas, error tokens, and boot flow: [`docs/manual/ch-api.tex`](docs/manual/ch-api.tex).
C++ signatures: generate with `doxygen Doxyfile``docs/api/html/index.html`. C++ signatures: `doxygen Doxyfile``docs/api/html/index.html`.
## Layout ## Layout
| Path | Role | | Path | Role |
|------|------| |------|------|
| `Firmware/` | Si4684 `.bin` blobs (DAB+FM) + ADAU1701 SigmaStudio export | | `Firmware/` | Si4684 `.bin` blobs (DAB+FM) + ADAU1701 SigmaStudio export |
| `components/drivers/si4684/` | AN649 SPI boot driver | | `components/core/` | Pure domain (host-tested) |
| `components/drivers/adau1701/` | I2C SigmaStudio RAM download | | `components/drivers/` | Si4684, ADAU1701, BT1035 drivers |
| `components/services/` | Tuner, audio, Bluetooth, station services |
| `components/net/` | Wi-Fi, HTTP server, gzipped web UI |
| `docs/manual/` | LaTeX technical manual (canonical) |
| `docs/TODO.md` | Agent task list (prioritised backlog) |
See [`AGENTS.md`](AGENTS.md) §12 and [`instructions.md`](instructions.md) for See [`AGENTS.md`](AGENTS.md) §12 and [`instructions.md`](instructions.md) for
the authoritative repo layout, coding rules, and development roadmap. coding rules and slice roadmap.
## Licence ## Licence
+130 -47
View File
@@ -1,62 +1,145 @@
# DigiRadio — consolidated TODO (audit 2026-07-06) # TODO — DigiRadio firmware
Firmware **0.7.0** after BT1035 pairing + Slice 4 presets. This list Task list for the coding agent. Work top to bottom; each task is a
cross-checks code, manual, API, UI, and `instructions.md`. vertical slice that keeps `main` building and the host tests green.
## Done in this slice **Before writing code, read `AGENTS.md`, `.cursor/rules/`, and
`instructions.md`.** Every task below must satisfy the Definition of Done
in `AGENTS.md §10`: Apache header on new files, doc block on every class
and method, `doxygen Doxyfile` exits 0, host tests pass,
`tools/check-manual-sync.py` passes, no primitive obsession, typed
errors, no plaintext secrets.
| Area | Status | Working directory for all commands is `Software/`.
|------|--------|
| BT1035 pairing AT (`AT+PAIR`, `AT+A2DPSTAT`, `AT+A2DPDISC`) | Done |
| `BluetoothService` + `/api/bluetooth/*` + UI | Done |
| `Station`, `StationList`, NVS persistence | Done |
| `StationService` + `/api/stations/*` + UI | Done |
| Host tests (10/10 green) | Done |
| Manual: `ch-api`, `ch-bt1035`, `ch-classes` | Done |
## High priority (next) **Current firmware:** `0.7.0` — BT1035 pairing (`/api/bluetooth/*`),
station presets (`/api/stations/*`), host tests green (10/10), manual
sync green (38 classes).
1. **Device flash / HIL** — verify Si4684, ADAU1701, BT1035 on hardware; pairing with real headphones; preset recall across reboot. ---
2. **DAB preset save from UI** — “Save current tune target” stores ensemble index only; capture `service_id` / `component_id` from the last played DAB service (needs UI state or tuner cache).
3. **FM band switch UX** — Si4684 boots DAB; FM tune may reload FM image; document/limit band changes in UI (auto-reload or explicit band selector).
4. **NVS encryption** — enable `nvs_keys` partition for production (Wi-Fi, presets, future user creds).
5. **Slice 8 integration** — unify tuner + audio + presets in a single “now playing” model; source selection (DAB / FM / BT Line-In).
## Medium priority ## Completed (fw 0.7.0)
6. **IBtModule interface** — AGENTS mentions it; driver is used directly today. Add when a second BT module or host fake is needed. - **Station / preset list (T3 core)** — `Station`, `StationList`, NVS key
7. **BT1035 extended AT**`AT+NAME`, `AT+PLIST`, `AT+A2DPCONN`, event-driven `+PAIRED` / `+A2DPDEV` (UART listener task). `station_list`, `StationService`, REST + Presets UI. Remaining polish:
8. **Station list reorder API**`StationList::move()` exists in core; no HTTP route yet. reorder API, save DAB `service_id`/`component_id` from UI, HIL on device.
9. **EQ UI completeness** — web UI exposes master/mixer/enhance; per-band EQ editing not in UI (API supports full profile PUT). - **BT1035 pairing** — `AT+PAIR`, `AT+A2DPSTAT`, `AT+A2DPDISC`,
10. **Si4684 RSQ / scan UX** — driver + HTTP largely done; polish seek, service list refresh, signal display on UI. `BluetoothService`, REST + UI (not numbered below; landed with Slice 7).
11. **User credentials**`ISecureStore` extension for login (out of scope until product needs it).
## Documentation / tooling ---
12. **Overleaf sync** — GitHub is source of truth; root `docs/` symlink can break Overleaf push; compile from `Software/docs/manual/manual.tex`. ## P0 — Fix the build gate (do this first)
13. **Firmware version single source**`0.7.0` in `SetupWebServer.cpp`; align `FirmwareVersion` / health test constants if desired.
14. **Doxygen pass** — run `doxygen Doxyfile` on CI host with ESP-IDF toolchain.
## Low priority / ideas ### T1. Clear the 16 Doxygen warnings
**Why:** `doxygen Doxyfile` currently exits non-zero, so the docs gate is
red and CI (once added) will fail.
**What:**
- Replace the invalid `\texttt{...}` with `` `...` `` (backticks) or
`\c word` in: `core/AudioProfileJson.hpp` (l.58, l.80),
`core/AudioEnhancements.hpp` (l.25).
- Fix `\r` interpreted as a command in `core/Bt1035At.hpp` (l.64) —
wrap the AT string in `@code ... @endcode` or escape as `\\r`.
- Add a space after `\ref` in `bt1035/Bt1035Driver.hpp` (l.89) and
`core/AudioEnhancements.hpp` (l.24).
- Document the missing `@param companionChips` in
`net/NetBootstrap.hpp` (`start`) and `net/SetupWebServer.hpp` (`start`).
**Done when:** `doxygen Doxyfile` exits 0 and `docs/api/doxygen-warnings.log`
is empty.
15. Physical preset buttons → map GPIO to `StationService::tuneToIndex` by `PresetSlot`. ### T2. Add the CI workflow
16. OTA updates, mDNS hostname (`digiradio.local`), HTTPS on LAN. **Why:** validate every push automatically.
17. aptX license note (Feasycom) — commercial firmware variant if needed. **What:** add `.github/workflows/ci.yml` with three jobs — host build +
`ctest`, `doxygen` (fail on warnings), and `check-manual-sync.py`. A ready
draft was prepared; place it and confirm all three jobs pass.
**Done when:** the workflow is green on `main` after T1.
## Test gaps ---
| Missing test | Layer | ## P1 — Missing domain features
|--------------|-------|
| `BluetoothService` with fake driver | Host (needs `IBtModule` or inject interface) |
| `StationService` + fake `ISecureStore` | Host |
| `NvsSecureStore` station round-trip | Target / integration |
| BT1035 UART HIL | Hardware-only, marked separate |
## Roadmap alignment (`instructions.md`) ### T3. Station / preset list — polish *(core done in 0.7.0)*
**Status:** CRUD, NVS persistence, tune recall, and basic UI are shipped.
**Remaining:**
- `POST /api/stations/reorder` (core has `StationList::move()`).
- Save DAB presets with `service_id` / `component_id` from last played service.
- Device HIL: preset survives reboot, tune recall on hardware.
**Done when:** the gaps above are closed and covered by tests.
| Slice | Item | State | ### T4. Broadcast metadata (RDS / DLS)
|-------|------|-------| **Why:** `TunerStatus` currently carries only a 17-char `label`. Real
| 4 | Station list + persistence + UI | **Done** (basic CRUD + tune) | radio UX needs the FM RDS station name/radiotext and DAB DLS dynamic
| 5 | Si4684 tuning / RSQ / DAB properties | Mostly done; UI polish open | label so the UI can show "what's playing".
| 7 | BT1035 pairing | **Done** (discover + A2DP stat/disconnect) | **What:**
| 8 | TunerService + AudioService E2E | Partial — health chips OK; unified UX open | - Extend the tuner data model with structured metadata (station name,
radiotext/dynamic label), read from the Si4684 in the driver.
- Surface it through `TunerService::refreshStatus` and the
`/api/tuner/status` JSON.
- Keep the Si4684 register/command details in the driver; the core model
stays hardware-free.
**Done when:** the status JSON exposes the metadata and host tests cover
the parsing of raw label bytes into the model.
### T5. Remove the services stub — integration service
**Why:** `components/services/src/component_stub.cpp` is a Slice-7
placeholder. Tuner and Audio services exist separately but nothing
orchestrates them together.
**What:** implement the integration layer that binds `TunerService`,
`AudioService`, the station list, and the network layer into the
application flow (e.g. "select a preset → tune → apply the stored audio
profile"). Replace the stub file.
**Done when:** `app_main` drives a real end-to-end flow through this
service; the stub is gone; a manual section documents the new class.
---
## P2 — User interface
### T6. Complete the configuration Web UI
**Why:** `components/net/www/index.html` is functional but the
requirement is an *elegant, essential* SPA. It should cover:
Wi-Fi provisioning, station list management, tuner control (FM/DAB,
seek, play), live EQ/volume/enhancement control, Bluetooth pairing, and
now-playing metadata.
**What:** a minimal single-page app served gzipped from flash, design
tokens defined once (spacing, type scale, one accent), thin client over
the existing typed JSON API. No heavy frameworks. No business logic in
the UI.
**Done when:** every API capability has a UI control; the page is served
gzipped; no debug endpoint is exposed in a shipping build.
---
## P3 — Procurement & hardening
### T7. Si4684 firmware blob strategy (legal)
**Why:** the Si4684 images are proprietary (Skyworks). Tools to fetch/
extract exist under `tools/`, but the `.bin` images must **not** be
committed to the public repo.
**What:**
- Confirm `*.bin` (patch, FM, DAB images) are in `.gitignore` and absent
from git history.
- Document in `Software/Firmware/Si4684-Firmware/README.md` how a builder
obtains the images locally (tools + AN649 reference), without
redistributing proprietary binaries.
**Done when:** no proprietary blob is tracked; the procurement path is
documented and reproducible.
### T8. Flash/NVS encryption enablement
**Why:** secure storage holds Wi-Fi and user credentials; encryption at
rest was deferred.
**What:** enable NVS encryption on an encrypted partition (with flash
encryption), per current ESP-IDF security docs. Verify the mechanism
before enabling; keep keys out of the repo.
**Done when:** credentials are encrypted at rest and the boot path still
loads them.
---
## Notes for the agent
- Prefer extending existing patterns over inventing new ones: copy the
shape of `AudioProfile` / `AudioProfileJson` / `IAudioProfileStore` for
new persisted models.
- Never invent Si4684 register/command details — cite AN649.
- One logical change per commit; 50/72 commit messages.
- After each task, run: host `ctest`, `doxygen Doxyfile`,
`tools/check-manual-sync.py` — all must pass before moving on.