Files
DigiRadio/Software/docs/claude-code-audio-bringup.md
micheleandClaude Sonnet 5 6f7b6dd12c Add internet radio streaming with runtime API, modernize web UI, remove auto-tune/beep at boot
Streaming (main feature this session):
- New WebRadioConfig/WebRadioJson core types, ISecureStore-backed persistence
- New webradio::WebRadioService (thread-safe live config) + GET/POST /api/streaming
- web_radio_stream task now runtime-toggleable (no reboot), no hardcoded URL
- Content-Type diagnostic: warns clearly when a URL is a webpage, not an audio stream

Boot cleanup:
- Removed boot-time auto FM/DAB tune, auto-beep, and the (now-concluded) Si4684
  crystal IBIAS/CTUN empirical sweep from main.cpp — tuning/beep are on-demand
  via the existing REST API only

Web UI:
- Modernized styling (cards, gradients, toggle switches, light/dark theme)
- New Stream tab wired to /api/streaming

Fixes found via real idf.py build (not just clangd):
- Restored wrongly-removed si4684/Si4684Tuner.hpp include in main.cpp
- Fixed MP3Decode() argument types in web_radio_stream.cpp (unsigned char**/int*)

Quality-gate fixes:
- Host-test stub headers (esp_log.h, freertos/*) so TunerService.cpp's
  scanForStation logging/pacing compiles for station_service_test /
  integration_service_test instead of running stale binaries
- Added WifiScanner and WebRadioService manual sections; filled in missing
  Doxygen docs on BluetoothService, i2s_sdata_probe, test_firmware, Bt1035At
- Ignore clangd's .cache/ index directory

Also includes prior uncommitted work carried in the tree: Wi-Fi/Bluetooth
device scan REST API and UI (WifiScanner, BT scan), SigmaStudio TCP bridge,
and the current ADAU1701 SigmaStudio DSP program export.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-08 21:15:22 +02:00

15 KiB
Raw Permalink Blame History

Claude Code — brief completo: audio bring-up DigiRadio

RISOLTO (2026-08-07): audio confermato funzionante end-to-end su Bose. Causa finale: la cella DSP "Beep - variable gain" richiede sia ENABLE sia KICK per avviare la generazione — vedi Adau1701Driver::setBeepEnabled(). Il tono di test ora è generato dall'oscillatore interno del DSP ADAU1701, non più dall'ESP32; il codice esp32_i2s_tone e CONFIG_ESP32_I2S_TONE_TEST descritti in questo documento sono stati rimossi dal firmware. Resto del documento come riferimento storico del bring-up.

Data: 2026-08-05
Repo: /Users/michelebigi/Documents/Develop/DigiRadio
Working dir firmware: Software/
Priorità: far sentire audio sul Bose Solo II (test tono 440 Hz, poi FM)


Prompt iniziale (copia-incolla in Claude Code)

Stai lavorando su DigiRadio (ESP32-S3 firmware in Software/).

CONTESTO
- Bring-up audio su scheda reale: Si4684 → ADAU1701 → FSC-BT1035 → Bose Solo II.
- Serial: /dev/cu.usbmodem1101
- Speaker BT salvato: Bose Solo II MAC BC87FAE69D6E
- WiFi: MikiLab, mDNS digiradio-CC4DB4.local

PROBLEMA
L'utente non sente NULLA sul Bose. I log seriali mostrano però:
- A2DPSTAT=4 (streaming OK) dopo AT+A2DPAUDIO=1
- esp32_i2s: I2S slave TX started
- esp32_i2s: i2s streaming 2048 bytes/frame to ADAU MP1

Quindi il firmware BT + I2S sembra OK; il silenzio potrebbe essere:
1) routing/mute ADAU (NVS profile sovrascrive mix),
2) formato I2S ESP32↔ADAU (24 vs 32 bit),
3) cablaggio I2S ADAU MP6 → BT1035,
4) Bose (sorgente BT errata, telefono in competizione).

LEGGI PRIMA
- Software/AGENTS.md
- Software/docs/claude-code-audio-bringup.md (questo file)
- Software/docs/audio-bringup-handoff.md

OBIETTIVO
1. Far sentire un tono 440 Hz sul Bose (CONFIG_ESP32_I2S_TONE_TEST=y).
2. Poi FM su 100.9 MHz (Massa) con applyRadioFirstMix.

VINCOLI
- NON committare senza richiesta esplicita.
- Modifiche minime, seguire convenzioni esistenti.
- Build: idf.py build da Software/
- Flash: idf.py -p /dev/cu.usbmodem1101 flash monitor

TASK SUGGERITI (in ordine)
A) Verificare log post-boot (~30s): cercare mix re-applied, i2s streaming, errori write.
B) Se software OK ma muto: aggiungere test alternativo — safeload beep interno ADAU o DC test su master volume (se possibile via parametri esistenti).
C) Avviare tone task SOLO da BluetoothService dopo "boot reconnect OK" (elimina race UART).
D) Provare entrambi i formati I2S (24-bit Philips vs 32-bit MSB<<8) con Kconfig o retry.
E) Verificare che IntegrationService::startup() non muti il mixer durante tone test (skip applyProfile se tone test attivo).
F) Documentare pinout I2S ADAU↔BT1035 da docs/manual/ e Hardware/ per debug utente.

Quando finisci: riassumi cosa hai cambiato, comando flash, log attesi.

Setup laboratorio

Parametro Valore
MCU ESP32-S3 (USB-JTAG /dev/cu.usbmodem1101)
Serial monitor 115200 baud
WiFi STA MikiLab
IP / mDNS ~192.168.1.56, digiradio-CC4DB4.local
Unit serial D8478FCC4DB4
Speaker BT Bose Solo II, nome AT BOSE SOLO 2, MAC BC87FAE69D6E
Area FM (Massa MS) RTL 100900 kHz, RAI1 95500, Club FM 97300
Build ESP-IDF 5.5, C++23, target esp32s3

Catena audio

Si4684 I2S (slave)  → ADAU1701 MP0 / Si4674 fader ─┐
ESP32 I2S (slave)   → ADAU1701 MP1 / ESP32 fader  ─┤→ St Mixer1 (ST0=Si4684, ST1=ESP32)
                                                     │   → Param EQ → master → MP6 SDATA_OUT0
                                                     └→ BT1035 I2S slave (AUXCFG=3, I2SCFG=67)
                                                         → A2DP encode → Bose Solo II
Ruolo Chip Note
I2S master 48 kHz ADAU1701 BCLK/LRCLK su MP10/MP11
I2S slave TX test ESP32 BCLK=GPIO6, WS=GPIO7, DOUT=GPIO16 → ADAU MP1
I2S slave RX BT1035 Riceve da ADAU MP6
FM tuner Si4684 I2S out verso ADAU MP0; richiede I2SOUTEN

Documentazione SigmaStudio: Software/docs/manual/ch-adau1701.tex, export in Software/Firmware/ADAU1701-Firmware/.


Stato attuale (2026-08-05 sera)

Layer Stato Evidenza log
ADAU boot + program load OK hw_boot: companion chips ready
BT1035 I2S slave OK AT+AUXCFG=3, AT+I2SCFG=67
Reconnect Bose OK reconnect saved speaker BC87FAE69D6E
A2DP Connected (3) OK A2DPSTAT=3
A2DP Streaming (4) OK fix AT+A2DPAUDIO=1
Mix esp32-first OK (con re-apply) ADAU esp32-first mix re-applied before tone
ESP32 I2S tone 440 Hz Firmware OK I2S slave TX started, i2s streaming 2048 bytes/frame
Audio al Bose FALLITO Utente: «no nulla»
FM 100.9 MHz Segnale assente rssi=0 (antenna wire)

Conclusione: il collo di bottiglia non è più A2DP Connected-vs-Streaming. Prossimo focus: path ADAU MP6 → BT1035 oppure formato/mix, o Bose lato utente.


Modifiche firmware (non committate)

A. Bluetooth — A2DP streaming (FIX PRINCIPALE, verificato)

Root cause: BT1035 restava su A2DPSTAT=3 (Connected). Serve AT+A2DPAUDIO=1 (Feasycom §5.3.6) per A2DPSTAT=4 (Streaming).

File Modifica
components/core/include/core/Bt1035At.hpp buildBt1035A2dpAudioLine(bool establish)
components/core/src/Bt1035At.cpp AT+A2DPAUDIO=1\r\n / =0
components/core/test/bt1035_at_test.cpp Unit test linee AT
components/drivers/bt1035/include/bt1035/Bt1035Driver.hpp startA2dpAudio(), waitForA2dpStreaming(int timeoutMs)
components/drivers/bt1035/src/Bt1035Driver.cpp Poll A2DPSTAT; retry A2DPAUDIO=1 ogni 3 s su Connected; no early return se query fallisce
components/services/bluetooth/src/BluetoothService.cpp ensureA2dpStreaming() dopo ogni connect/reconnect

B. ADAU1701 — mixer routing

File Modifica
components/core/include/core/MixerState.hpp radioFirst(), esp32First()
components/core/src/MixerState.cpp ST0=Si4684, ST1=ESP32; mute path non usato a 96 dB
components/services/audio/include/audio/AudioService.hpp applyRadioFirstMix(), applyEsp32FirstMix()
components/services/audio/src/AudioService.cpp Safeload mixer + master unity
main/hardware_bootstrap.cpp Dopo loadAndApply(): mix per Kconfig

Mapping SigmaStudio (St Mixer1):

  • mixLeft → ST0 (Si4684)
  • mixRight → ST1 (ESP32)

Bug scoperto: IntegrationService::startup()recallPreset()applyStoredAudioProfile() può sovrascrivere il mix dopo hw_boot. Fix attuale: re-apply applyEsp32FirstMix() in esp32I2sToneTask prima di I2S. Fix migliore: skip apply profile durante tone test, o avviare tone da BluetoothService post-reconnect.

C. Si4684 FM

File Modifica
components/drivers/si4684/src/Si4684Driver.cpp AUDIO_OUTPUT_CONFIG I2SOUTEN (0x0302=0x0002); unmute; vol 63; RSQ offsets AN649; tune STC fallback 150 ms
components/drivers/si4684/src/Si4684Tuner.cpp Volume 63; READFREQ stale guard
components/services/tuner/src/TunerService.cpp FM scan step +100 kHz; SNR≥10; chip freq check
components/core/include/core/TunerStatus.hpp fmChipReadFrequency

D. Test tono ESP32 (bring-up dev)

File Modifica
main/Kconfig.projbuild CONFIG_ESP32_I2S_TONE_TEST (default y)
main/esp32_i2s_tone.cpp 440 Hz sine, I2S slave, 24-bit Philips, mclk_multiple=384, amp 0.85
main/esp32_i2s_tone.hpp bool start()
main/main.cpp Task esp32_tone: delay 15 s → wait A2DP → re-apply mix → startA2dpAudio() → I2S
main/CMakeLists.txt Condizionale su Kconfig
main/board_pins.hpp BCLK=6, WS=7, DOUT=16
sdkconfig.defaults CONFIG_ESP32_I2S_TONE_TEST=y
sdkconfig CONFIG_ESP32_I2S_TONE_TEST=y (critico — se # is not set il tone non compila)

E. FM probe (alternativa, tone test OFF)

File Modifica
main/main.cpp fm_probe stack 16384; tune 100900 kHz; applyRadioFirstMix

F. Altri file dirty (sessioni precedenti, non audio-core)

Net/UI, secure store, BluetoothJson, SetupWebServer, station/tuner tests — vedi git diff --name-only.


Boot sequence (ordine temporale)

app_main
  → HardwareBootstrap::boot()
       → ADAU program load
       → loadAndApply()          ← profilo NVS
       → applyEsp32FirstMix()    ← se tone test
       → BT1035 boot (AUXCFG=3)
       → Si4684 boot
  → integration.startup()       ← può recall preset + applyProfile (SOVRASCRIVE MIX)
  → NetBootstrap
  → bluetoothService.startupReconnect()  ← task async, A2DPSTAT→4
  → esp32I2sToneTask              ← delay 15s, wait stream, re-apply mix, I2S start

Build, flash, verifica

cd /Users/michelebigi/Documents/Develop/DigiRadio/Software

# Verifica tone test compilato
rg CONFIG_ESP32_I2S_TONE_TEST build/config/sdkconfig.h
# Atteso: #define CONFIG_ESP32_I2S_TONE_TEST 1

idf.py build
idf.py -p /dev/cu.usbmodem1101 flash monitor

Disabilitare tone test (FM probe):

# In sdkconfig: # CONFIG_ESP32_I2S_TONE_TEST is not set
idf.py fullclean reconfigure build flash

Log attesi (tone test OK, ~30 s dopo reset)

I (hw_boot) ADAU1701 ESP32 I2S input routed (esp32-first mix)
I (Bt1035) I2S slave mode enabled (AT+AUXCFG=3, AT+I2SCFG=67)
I (BluetoothSvc) boot reconnect task started
I (BluetoothSvc) reconnect saved speaker BC87FAE69D6E (BOSE SOLO 2)
I (Bt1035) A2DP audio start (AT+A2DPAUDIO=1)
I (Bt1035) stream wait: A2DPSTAT=4
I (BluetoothSvc) A2DP streaming OK
I (digiradio) ==== ESP32 I2S tone test (440 Hz) — waiting A2DP streaming ====
I (digiradio) A2DP streaming — starting I2S tone
I (digiradio) ADAU esp32-first mix re-applied before tone
I (esp32_i2s) I2S slave TX started (BCLK=6 WS=7 DOUT=16)
I (esp32_i2s) tone task: 440 Hz sine, 48000 Hz, ADAU I2S slave TX
I (esp32_i2s) i2s streaming 2048 bytes/frame to ADAU MP1

Errori già risolti (non devono riapparire):

E (i2s_std) i2s_std_calculate_clock(68): sample rate is too large   ← I2S_CLK_SRC_EXTERNAL errato
W (digiradio) A2DP not streaming after 90000 ms  (a t=10s)           ← race waitForA2dpStreaming

Ipotesi da investigare (Claude Code)

H1 — Hardware I2S ADAU → BT1035

Firmware invia PCM a BT1035 solo se ADAU MP6 ha clock+dati. Verificare:

  • MP6 configurato come SDATA_OUT0 (SigmaStudio MFSELECT6=0x4 in export)
  • REG_SERIALOUTREGISTER1 = 0x800 (output enabled)
  • Cavo dati MP6 → pin I2S DIN del BT1035

H2 — Formato I2S ESP32 → ADAU MP1

ADAU accetta 24-bit I2S. Firmware usa 24-bit Philips; provare anche 32-bit con sample << 8 se tono ancora muto.

H3 — NVS profile muta mixer/enhancements

IntegrationService richiama applyProfile(currentProfile()) che riapplica mixer da NVS. Durante tone test:

  • Disabilitare recall preset audio, oppure
  • #if CONFIG_ESP32_I2S_TONE_TEST skip in IntegrationService::applyStoredAudioProfile

H4 — Bose non in playout

  • Telefono connesso al Bose in parallelo
  • Bose su input AUX invece di BT
  • Volume Bose al minimo

H5 — BT1035 I2S non sincronizzato

Con A2DPSTAT=4 e I2S da ADAU: verificare se BT1035 richiede comandi aggiuntivi oltre A2DPAUDIO=1 (leggere docs/manual/ch-bt1035.tex, manuale Feasycom).

H6 — Master volume / enhancements

applyProfile applica EQ con enhancements overlay. Verificare che master gain non sia 96 dB in profilo NVS salvato.


Task concreti per Claude Code (checklist)

  • T1 Leggere log fresh dopo flash; confermare sequenza sopra.
  • T2 Spostare avvio tone in callback BluetoothService post boot reconnect OK (elimina delay 15s + race UART).
  • T3 Guard tone test: skip IntegrationService::applyStoredAudioProfile quando CONFIG_ESP32_I2S_TONE_TEST.
  • T4 Aggiungere Kconfig ESP32_I2S_TONE_FORMAT_32BIT per A/B test formato senza rebuild manuale.
  • T5 Log queryA2dpState + A2DPENC / volume BT1035 se esiste comando AT.
  • T6 Test senza ESP32: applyRadioFirstMix + Si4684 tone/noise (se RSSI>0 con antenna) per isolare BT path.
  • T7 Aggiornare docs/audio-bringup-handoff.md con esito.

File chiave (aprire per primi)

Software/main/main.cpp
Software/main/esp32_i2s_tone.cpp
Software/main/hardware_bootstrap.cpp
Software/main/board_pins.hpp
Software/main/Kconfig.projbuild

Software/components/services/bluetooth/src/BluetoothService.cpp
Software/components/drivers/bt1035/src/Bt1035Driver.cpp
Software/components/core/src/Bt1035At.cpp

Software/components/services/audio/src/AudioService.cpp
Software/components/core/src/MixerState.cpp
Software/components/drivers/adau1701/src/Adau1701Driver.cpp

Software/components/services/integration/src/IntegrationService.cpp
Software/components/drivers/si4684/src/Si4684Driver.cpp

Software/Firmware/ADAU1701-Firmware/DigiRadio_IC_1_PARAM.h
Software/sdkconfig
Software/sdkconfig.defaults

Regole progetto

  • Leggere Software/AGENTS.md e Software/.cursor/rules/ prima di ogni modifica.
  • Non committare senza richiesta utente.
  • Tone test = solo dev; produzione usa sdkconfig.defaults.production senza tone test.
  • Host tests: cmake --build build-host && ctest (se tocchi core/bt1035).

Comandi debug rapidi

# Monitor filtrato
idf.py -p /dev/cu.usbmodem1101 monitor 2>&1 | rg -i 'A2DP|esp32_i2s|hw_boot|tone|streaming|error|mix'

# Reset + 90s capture
python3 <<'PY'
import serial, time
s = serial.Serial("/dev/cu.usbmodem1101", 115200, timeout=0.2)
s.dtr = False; s.rts = True; time.sleep(0.1); s.rts = False
t = time.time()
while time.time() - t < 90:
    line = s.readline()
    if line: print(line.decode(errors="replace"), end="")
PY

# Host unit test BT1035 AT
cd Software && cmake -B build-host -DBUILD_HOST_TESTS=ON && cmake --build build-host && ctest --test-dir build-host -R bt1035

Documenti correlati

File Contenuto
Software/docs/claude-code-audio-bringup.md Questo file — brief operativo Claude Code
Software/docs/audio-bringup-handoff.md Handoff tecnico sessione Cursor
Software/docs/manual/ch-adau1701.tex ADAU boot, safeload, signal chain
Software/docs/manual/ch-bt1035.tex BT1035 I2S, AUXCFG, pairing
Software/AGENTS.md Regole agenti, build, DoD

Storia sessione Cursor

  • Thread: audio/FM bring-up, ID d10654e5-d27a-4999-812e-f371dc48567a
  • Subagent Fix no audio path: fix AT+A2DPAUDIO=1 + tone test scaffold
  • Follow-up Cursor: sdkconfig tone test, fix I2S slave clock, mix re-apply, flash multipli
  • Utente conferma silenzio persistente nonostante log software OK → sospetto hardware o mix/NVS