diff --git a/README.md b/README.md index 85e9a14..cd6e886 100644 --- a/README.md +++ b/README.md @@ -64,12 +64,12 @@ no analogue conversions are introduced between the tuner and the wireless link. | **Boot & chips** | Si4684 DAB+FM firmware load (HOST_LOAD blobs), ADAU1701 RAM program at every boot, BT1035 UART init | | **Tuner** | FM tune/seek, DAB ensemble tune, service scan & play, RSQ/RDS, DAB event status | | **Now playing** | FM RDS (PS, RadioText, PI, PTY) and DAB Dynamic Label (DLS) in status JSON and web UI | -| **Audio** | 5-band EQ, input mixer, stereo/bass enhancement overlays, profile persist in NVS | +| **Audio** | 6-band EQ, input mixer, stereo/bass enhancement overlays, profile persist in encrypted NVS | | **Presets** | Station list CRUD, reorder, recall with audio profile re-apply, last-preset restore at boot | | **Bluetooth** | Discoverable pairing, A2DP status, disconnect | | **Network** | SoftAP setup mode, STA provisioning, tabbed gzipped SPA (`/`), typed JSON REST API | | **Security** | NVS + flash encryption at rest (dev mode); keys never in repo | -| **Quality** | **13** host unit tests, Doxygen gate, LaTeX manual sync check, GitHub Actions CI on `main` | +| **Quality** | **13** host unit tests, 4 CI jobs (tests, Doxygen, manual sync, blob policy) | Architecture follows a **functional core + imperative shell**: pure domain logic (compilation, JSON, EQ design, RDS/DLS parsing) runs on the host under `ctest`; @@ -84,7 +84,7 @@ Vertical slices landed on `main` (newest first): | Version | Highlights | |---------|------------| | **0.8.3** | NVS + flash encryption (development mode), `initEncryptedStorage`, security docs | -| **0.8.2** | Tabbed Web UI + Si4684 blob CI policy | +| **0.8.2** | Tabbed Web UI (now-playing, 6-band EQ, all REST); Si4684 blob CI policy | | **0.8.1** | `IntegrationService` — boot preset recall, tune orchestration (tuner + audio + NVS `last_preset`); services stub removed | | **0.8.0** | Preset reorder API/UI; broadcast metadata (RDS + DAB DLS); `readDabServiceData` driver path | | **0.7.1** | CI workflow (host tests, Doxygen, manual sync); Doxygen warnings cleared | @@ -92,8 +92,9 @@ Vertical slices landed on `main` (newest first): | **0.5–0.6** | ADAU1701 runtime EQ/mixer, Si4684 tuning & DAB service list, BT1035 driver | | **0.3–0.4** | Secure store, Wi-Fi provisioning, companion-chip boot, walking skeleton | -**Next up:** device HIL for encrypted NVS (when PCB arrives). Agent backlog: -[`Software/docs/TODO.md`](Software/docs/TODO.md). +**Next:** device HIL when the PCB arrives ([`Software/docs/security-flash-nvs.md`](Software/docs/security-flash-nvs.md), +[`Software/docs/TODO.md`](Software/docs/TODO.md)). Contributing: +[`CONTRIBUTING.md`](CONTRIBUTING.md). --- @@ -125,8 +126,8 @@ DigiRadio/ │ │ └── TODO.md Agent backlog and completed tasks │ ├── Firmware/ Si4684 blobs + ADAU1701 SigmaStudio export │ ├── main/ app_main, hardware bootstrap -│ └── tools/ Manual sync checker, Si4684 blob helpers -├── CONTRIBUTING.md +│ └── tools/ fetch_si4684_firmware, check_*, gzip-www +├── CONTRIBUTING.md human-facing dev guide ├── LICENSE CERN-OHL-S v2 (hardware) └── README.md ← you are here ``` @@ -172,7 +173,8 @@ python3 tools/check-manual-sync.py python3 tools/check_si4684_blobs.py ``` -Full build notes, API table, and component map: [`Software/README.md`](Software/README.md). +Full build notes: [`Software/README.md`](Software/README.md) · security: +[`Software/docs/security-flash-nvs.md`](Software/docs/security-flash-nvs.md). ### First boot (device) diff --git a/Software/Firmware/ADAU1701-Firmware/README.md b/Software/Firmware/ADAU1701-Firmware/README.md index 3929dbe..1ba50cd 100644 --- a/Software/Firmware/ADAU1701-Firmware/README.md +++ b/Software/Firmware/ADAU1701-Firmware/README.md @@ -1,6 +1,7 @@ # ADAU1701 SigmaStudio export -SigmaStudio project **DigiRadio**, IC1 = ADAU1701. +SigmaStudio project **DigiRadio**, IC1 = ADAU1701. Shipped with DigiRadio firmware +**0.8.3**. ## Key files @@ -12,29 +13,32 @@ SigmaStudio project **DigiRadio**, IC1 = ADAU1701. | `DigiRadio_NetList.xml` | Schematic netlist (reference) | | `SigmaStudioFW.h` | Safeload / I2C glue API | -The ESP32 replays `default_download_IC_1()` over I2C on every boot via -`adau1701::Adau1701Driver`. Runtime mixer/EQ/master changes use the -ADAU1701 safeload mechanism (`sigma_safeload_param` / -`sigma_safeload_block` in `components/drivers/adau1701/src/SigmaStudioFW.c`). +## Runtime (fw 0.8.3) -I2C address: 7-bit `0x34` (ADDR0=ADDR1=GND), matching `board_pins.hpp`. +- **Boot:** ESP32 replays `default_download_IC_1()` over I2C via + `adau1701::Adau1701Driver` on every power-up. +- **Live control:** six-band PEQ, input mixer, master volume, stereo/bass + enhancement overlays — safeload via `audio::AudioService` and REST + `/api/audio/*`; profile persisted in encrypted NVS. +- **Web UI:** **Audio** tab — 6 EQ sliders + mixer/enhance controls. -Sample rate: **48 kHz** (see `DigiRadio_NetList.xml`). +I2C address: 7-bit `0x34` (ADDR0=ADDR1=GND). Sample rate: **48 kHz**. + +Safeload implementation: `components/drivers/adau1701/src/SigmaStudioFW.c`. +Parameter map: `components/drivers/adau1701/include/adau1701/Adau1701ParamMap.hpp`. ## After re-exporting from SigmaStudio 1. **Action → Export System Files** into this folder (overwrite headers). -2. Reconcile new `ADDR_*` symbols in `components/drivers/adau1701/include/adau1701/Adau1701ParamMap.hpp` if block names moved. -3. Rebuild and flash firmware. -4. Update the manual: `docs/manual/ch-sigmastudio.tex` (design) and - `docs/manual/ch-adau1701.tex` (driver/API) if the signal chain changed. +2. Reconcile new `ADDR_*` symbols in `Adau1701ParamMap.hpp` if block names moved. +3. Rebuild and flash firmware (`idf.py build`). +4. Update manual: `docs/manual/ch-sigmastudio.tex`, `docs/manual/ch-adau1701.tex`. + +Do **not** use SigmaStudio *Link Compile Download* on DigiRadio — export only; +the ESP32 programs the DSP at every power-up. ## Documentation -- **Manual — SigmaStudio design:** `docs/manual/ch-sigmastudio.tex` -- **Manual — driver & usage:** `docs/manual/ch-adau1701.tex` (boot, safeload, - `Adau1701Driver`, `AudioService`, HTTP `/api/audio/*`) -- **HTTP schemas:** `docs/manual/ch-api.tex` - -Do **not** use SigmaStudio *Link Compile Download* on DigiRadio — export -only; the ESP32 programs the DSP at every power-up. +- Design: `docs/manual/ch-sigmastudio.tex` +- Driver & API: `docs/manual/ch-adau1701.tex` +- HTTP: `docs/manual/ch-api.tex` (`/api/audio/*`) diff --git a/Software/Firmware/README.md b/Software/Firmware/README.md index aeee61a..7da5ca5 100644 --- a/Software/Firmware/README.md +++ b/Software/Firmware/README.md @@ -1,26 +1,49 @@ # DigiRadio — companion-chip firmware assets -Binary and SigmaStudio exports loaded by the ESP32 at every boot. +Binary and SigmaStudio exports loaded by the ESP32 at every boot (fw **0.8.3**). -| Directory | Chip | Contents | -|-----------|------|----------| -| `ADAU1701-Firmware/` | ADAU1701 SigmaDSP | SigmaStudio export (`DigiRadio_IC_1.h`, …) — RAM program | -| `Si4684-Firmware/` | Si4684 DAB+/FM tuner | ROM patch + DAB + FM application images (`.bin`) | +| Directory | Chip | In git? | Loaded by | +|-----------|------|---------|-----------| +| `ADAU1701-Firmware/` | ADAU1701 SigmaDSP | Yes (headers) | `Adau1701Driver` — RAM program every boot | +| `Si4684-Firmware/` | Si4684 DAB+/FM | README only | `Si4684Driver` — HOST_LOAD embedded blobs | -## Si4684 blobs +## Before first device build -Proprietary Skyworks images — **local only**, gitignored (`*.bin`). See -[`Si4684-Firmware/README.md`](Si4684-Firmware/README.md) for procurement and -legal notes. Populate with: +Si4684 application images are **proprietary** and **gitignored**. Populate locally: ```bash cd Software python3 tools/fetch_si4684_firmware.py --dab-only python3 tools/fetch_si4684_firmware.py --si46xx-dir /path/to/si46xx_firmware python3 tools/check_si4684_blobs.py +ls Firmware/Si4684-Firmware/*.bin # expect 3 files ``` +Without blobs, `idf.py build` fails at embed/link time. + +Full procurement and legal notes: [`Si4684-Firmware/README.md`](Si4684-Firmware/README.md). + +## Si4684 blobs + +| File | Role | +|------|------| +| `rom_patch_016.bin` | ROM patch (HOST_LOAD before main image) | +| `dab_firmware.bin` | DAB+ application (PE5PVB / Skyworks) | +| `fm_firmware.bin` | FM application (Skyworks eval or community source) | + +Boot sequence: AN649 — POWER_UP → LOAD_INIT → HOST_LOAD(patch) → LOAD_INIT → +HOST_LOAD(image) → BOOT. + ## ADAU1701 export -Generated by Analog Devices SigmaStudio for the DigiRadio DSP schematic. -Loaded on every boot (no self-boot EEPROM on this board). +SigmaStudio project **DigiRadio** — exported headers replayed over I2C on every +boot (no self-boot EEPROM). Runtime EQ/mixer/enhancements via safeload and the +Web UI **Audio** tab (`/api/audio/*`). + +Details: [`ADAU1701-Firmware/README.md`](ADAU1701-Firmware/README.md) · manual: +`docs/manual/ch-adau1701.tex`, `docs/manual/ch-sigmastudio.tex`. + +## Security note + +User settings (Wi-Fi, presets, audio profiles) live in **encrypted NVS**, not in +this folder. See `docs/security-flash-nvs.md`. diff --git a/Software/Firmware/Si4684-Firmware/README.md b/Software/Firmware/Si4684-Firmware/README.md index 6c04158..fd2231d 100644 --- a/Software/Firmware/Si4684-Firmware/README.md +++ b/Software/Firmware/Si4684-Firmware/README.md @@ -1,8 +1,8 @@ # Si4684 firmware images (local only — not in git) -Skyworks Si4684 application firmware is **proprietary**. This directory holds -the three binary blobs your build embeds via `HOST_LOAD`; they must **never** -be committed to the public repository. +Skyworks Si4684 application firmware is **proprietary**. DigiRadio fw **0.8.3** +embeds these blobs via ESP-IDF `EMBED_FILES`; they must **never** be committed. +CI runs `tools/check_si4684_blobs.py` on every push to `main`. | File | Size (typ.) | Role | |------|-------------|------| diff --git a/Software/README.md b/Software/README.md index 373d558..f5fd905 100644 --- a/Software/README.md +++ b/Software/README.md @@ -2,9 +2,37 @@ Open-source Hi-Fi DAB+/FM receiver firmware for the ESP32-S3. -**Status:** fw **0.8.3** — NVS + flash encryption (dev mode); tabbed Web UI; -`IntegrationService`; **13** host tests; CI on `main`. -See [`docs/TODO.md`](docs/TODO.md) for the agent task list. +**Status:** fw **0.8.3** on `main` — NVS + flash encryption (development mode), +tabbed Web UI, `IntegrationService`, RDS/DLS metadata, **13** host tests, **4** CI +jobs. Agent tasks T1–T8 complete; device HIL pending first PCB. + +| Area | Shipped in 0.8.3 | +|------|------------------| +| Boot | Si4684 HOST_LOAD, ADAU1701 RAM program, BT1035 Line-In init | +| Tuner | FM/DAB tune, seek, RSQ, RDS, DAB services + DLS | +| Audio | 6-band EQ, mixer, stereo/bass enhance, NVS profile | +| Presets | CRUD, reorder, integrated recall + last-preset at boot | +| Network | SoftAP/STA, tabbed gzipped SPA, typed JSON REST API | +| Security | `initEncryptedStorage()` — see [`docs/security-flash-nvs.md`](docs/security-flash-nvs.md) | +| Quality | Doxygen, manual sync, Si4684 blob policy check | + +Architecture: **functional core** (`components/core`, host-tested, no ESP-IDF) + +**imperative shell** (drivers, services, net, secure_store). Rules: +[`AGENTS.md`](AGENTS.md) · backlog: [`docs/TODO.md`](docs/TODO.md) + +## Prerequisites + +**Si4684 blobs** (proprietary, local only — not in git): + +```bash +python3 tools/fetch_si4684_firmware.py --dab-only +python3 tools/fetch_si4684_firmware.py --si46xx-dir /path/to/si46xx_firmware +python3 tools/check_si4684_blobs.py +``` + +See [`Firmware/Si4684-Firmware/README.md`](Firmware/Si4684-Firmware/README.md). + +**ESP-IDF** v5.5.x, target `esp32s3`. ## Quick start @@ -14,11 +42,16 @@ Open this directory (`Software/`) as the Cursor project so `AGENTS.md` and ```bash idf.py set-target esp32s3 idf.py build -idf.py erase-flash flash # once when upgrading to encrypted NVS (0.8.3+) -idf.py -p flash monitor +idf.py erase-flash flash # once when first enabling encryption (0.8.3+) +idf.py -p monitor ``` -Host unit tests (pure core, no hardware): +Production flash-encryption release mode: overlay `sdkconfig.defaults.production` +(see security doc — irreversible on chip). + +## Host tests + +Pure core, no hardware (needs C++23 compiler on macOS — Homebrew `llvm` or GCC 14): ```bash cmake -S components/core/test -B build-host \ @@ -27,7 +60,9 @@ cmake --build build-host ctest --test-dir build-host --output-on-failure ``` -Documentation gates (must exit 0 before merging; also enforced in CI): +## Quality gates (CI on every push to `main`) + +Run from `Software/`: ```bash doxygen Doxyfile @@ -36,11 +71,15 @@ python3 tools/check_si4684_blobs.py python3 tools/gzip-www.sh # after editing components/net/www/index.html ``` -Manual PDF (design + HTTP API + class reference): +CI jobs: `host-tests`, `doxygen`, `manual-sync`, `si4684-blobs` +(`.github/workflows/ci.yml`). -```bash -cd docs/manual && latexmk -lualatex manual.tex -``` +## Web UI + +Gzipped single-page app at `/` — tabs: **Now** (RDS/DLS), **Radio**, **Presets**, +**Audio** (6-band EQ), **BT**, **Wi‑Fi**. Source: +`components/net/www/index.html` · regenerate embed: +`tools/gzip-www.sh`. ## HTTP API (fw 0.8.3) @@ -53,7 +92,7 @@ cd docs/manual && latexmk -lualatex manual.tex | 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 | +| GET/PUT | `/api/audio/profile` | Read/apply ADAU1701 mixer + 6-band EQ | | 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) | @@ -67,25 +106,27 @@ cd docs/manual && latexmk -lualatex manual.tex | POST | `/api/stations/reorder` | Move preset (`from`/`to` indices) | | POST | `/api/stations/tune` | Recall preset (tuner + audio profile + NVS) | -Full schemas, error tokens, and boot flow: [`docs/manual/ch-api.tex`](docs/manual/ch-api.tex). -C++ signatures: `doxygen Doxyfile` → `docs/api/html/index.html`. +Wire schemas: [`docs/manual/ch-api.tex`](docs/manual/ch-api.tex) · C++ API: +`doxygen Doxyfile` → `docs/api/html/index.html`. ## Layout | Path | Role | |------|------| -| `Firmware/` | Si4684 `.bin` blobs (DAB+FM) + ADAU1701 SigmaStudio export | +| `Firmware/` | Si4684 `.bin` (local) + ADAU1701 SigmaStudio export | | `components/core/` | Pure domain (host-tested) | -| `components/drivers/` | Si4684, ADAU1701, BT1035 drivers | -| `components/services/` | Tuner, audio, Bluetooth, station, integration services | +| `components/drivers/` | Si4684, ADAU1701, BT1035 | +| `components/services/` | Tuner, audio, Bluetooth, station, integration | +| `components/secure_store/` | Encrypted NVS: credentials, profiles, presets | | `components/net/` | Wi-Fi, HTTP server, gzipped web UI | -| `docs/manual/` | LaTeX technical manual (canonical) | -| `docs/security-flash-nvs.md` | NVS + flash encryption and HIL checklist | -| `docs/TODO.md` | Agent task list (prioritised backlog) | +| `sdkconfig.defaults` | C++23, NVS + flash encryption (dev mode) | +| `partitions.csv` | `nvs` + `nvs_keys` partitions | +| `docs/manual/` | LaTeX technical manual | +| `docs/security-flash-nvs.md` | Encryption + device HIL checklist | +| `docs/TODO.md` | Completed tasks + HIL backlog | +| `tools/` | Blob fetch, CI policy checks, UI gzip | -See [`AGENTS.md`](AGENTS.md), [`instructions.md`](instructions.md), -[`docs/security-flash-nvs.md`](docs/security-flash-nvs.md), and -[`docs/TODO.md`](docs/TODO.md) for coding rules, security, and backlog. +Manual PDF: `cd docs/manual && latexmk -lualatex manual.tex` ## Licence