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:
@@ -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
@@ -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 (0–100) |
|
||||||
|
| POST | `/api/audio/bass-enhance` | Bass enhance overlay (0–100) |
|
||||||
|
| 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
@@ -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.
|
||||||
|
|||||||
Reference in New Issue
Block a user