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>
This commit is contained in:
@@ -0,0 +1,371 @@
|
||||
# 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
|
||||
|
||||
```bash
|
||||
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):**
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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](8719ea5e-ee61-48fe-ba57-7298b5638cf9): 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
|
||||
Reference in New Issue
Block a user