The 2026-08-16 IBP=1 override (commit 6974095) was applied alongside a
separate, simultaneous fix to Si4684's PIN_CONFIG_ENABLE and credited
with turning static into audible music. SerialInputRegister (0x081F) is
a single register shared by every SDATA_INx pin on the ADAU1701, so the
override also applied to the ESP32 streaming input, not just Si4684's.
Live A/B testing today (DAB, FM, and ESP32 web-radio, all isolated via
mixer gain, with and without ADAU1701 DSP bypass, with and without BT
A2DP codec changes) narrowed the hiss to this one shared register.
Removing the override and leaving IBP at its compiled default (0x00)
resolved the hiss on both the Si4684 and ESP32 paths, confirmed by ear.
Also:
- Add a runtime HTTP API (GET/POST /api/bluetooth/a2dp-codec) to change
the BT1035 A2DP codec bitmask without reflashing, used to rule out
AAC/SBC codec choice as a contributing cause.
- Extend the ADAU1701 boot-time EQ diagnostic to read back all 6 bands
(previously band 0 only) using the correct 5.23 fixed-point format.
- Note EEPROM persistence for ANTCAP/crystal calibration as TODO.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
DigiRadio Firmware
Open-source Hi-Fi DAB+/FM receiver firmware for the ESP32-S3.
Status: fw 0.8.5 on main — BT1035 I2S slave boot init, dual OTA + DSP blob updates, EEPROM identity,
NVS + flash encryption (development mode), tabbed Web UI with System uploads,
15 host tests, 4 CI jobs. Agent tasks T1–T12 complete; device HIL pending
first PCB.
| Area | Shipped in 0.8.5 |
|---|---|
| Boot | Si4684 HOST_LOAD, ADAU1701 RAM program, BT1035 I2S slave init (AUXCFG=3, I2SCFG=67) |
| Tuner | FM/DAB tune, seek up/down, RSQ, RDS, DAB services + DLS |
| Audio | 6-band EQ, mixer, stereo/bass enhance, NVS profile |
| Updates | ESP32 dual-OTA, ADAU1701 dsp partition blob replay |
| Identity | 24AA025E48 EUI-48 → serial, SoftAP/BT name suffix |
| 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 |
| 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 · backlog: docs/TODO.md
Prerequisites
Si4684 blobs (proprietary, local only — not in git):
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.
ESP-IDF v5.5.x, target esp32s3.
Quick start
Open this directory (Software/) as the Cursor project so AGENTS.md and
.cursor/rules/ load automatically.
idf.py set-target esp32s3
idf.py build
idf.py erase-flash flash # once when first enabling encryption (0.8.3+)
idf.py -p <port> monitor
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):
cmake -S components/core/test -B build-host \
-DCMAKE_CXX_COMPILER="$(brew --prefix llvm)/bin/clang++"
cmake --build build-host
ctest --test-dir build-host --output-on-failure
Quality gates (CI on every push to main)
Run from Software/:
doxygen Doxyfile
python3 tools/check-manual-sync.py
python3 tools/check_si4684_blobs.py
tools/gzip-www.sh # after editing components/net/www/index.html
CI jobs: host-tests, doxygen, manual-sync, si4684-blobs
(.github/workflows/ci.yml).
Web UI
Gzipped single-page app at / — tabs: Now (RDS/DLS), Radio, Presets,
Audio (6-band EQ), BT, Wi‑Fi, System (firmware OTA + DSP upload).
Header shows EEPROM serial from /api/health. Source:
components/net/www/index.html · regenerate embed:
tools/gzip-www.sh.
HTTP API (fw 0.8.5)
| Method | Path | Purpose |
|---|---|---|
| GET | /api/health |
Status, firmware version, serial, companion-chip flags |
| POST | /api/wifi |
Provision STA credentials; reboot on success |
| GET | /api/tuner/status |
Tuner snapshot (DAB/FM, RDS/DLS metadata) |
| 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 or down ({"direction":"up|down"}) |
| 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) |
| POST | /api/dsp/program |
Upload ADAU1701 DRAD blob (raw bytes, reboot) |
| POST | /api/system/ota |
Upload ESP32 firmware image (raw bytes, reboot) |
| GET | /api/bluetooth/status |
BT1035 boot, pairing, A2DP, name, auto-reconnect |
| GET | /api/bluetooth/paired |
Paired-device list from module |
| POST | /api/bluetooth/pair |
Enter discoverable mode |
| POST | /api/bluetooth/pair/stop |
Leave discoverable mode |
| POST | /api/bluetooth/disconnect |
Release A2DP session |
| POST | /api/bluetooth/auto-reconnect |
Set auto-reconnect count (0–15) |
| GET | /api/stations |
List saved presets |
| POST | /api/stations |
Add preset |
| POST | /api/stations/remove |
Remove preset by index |
| POST | /api/stations/reorder |
Move preset (from/to indices) |
| POST | /api/stations/tune |
Recall preset (tuner + audio profile + NVS) |
Wire schemas: docs/manual/ch-api.tex · C++ API:
doxygen Doxyfile → docs/api/html/index.html.
Layout
| Path | Role |
|---|---|
Firmware/ |
Si4684 .bin (local) + ADAU1701 SigmaStudio export |
components/core/ |
Pure domain (host-tested) |
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 |
sdkconfig.defaults |
C++23, NVS + flash encryption (dev mode) |
partitions.csv |
nvs, otadata, dual OTA (ota_0/ota_1), dsp blob, nvs_keys |
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 |
Manual PDF: cd docs/manual && latexmk -lualatex manual.tex
Licence
Apache-2.0 — see LICENSE.