Document DigiRadioFinale DSP revision, archive SigmaStudio source
Adds the new SigmaStudio project export (Sigmastudio.zip, source screenshot) alongside the existing project archives in Sigmastudio/, rewrites docs/adau1701-sigmastudio-analysis.md for the 224-parameter program (exclusive source mux replacing the old mixer, Bass Boost1/ SPhat1 dedicated blocks, unimplemented VU-meter readback), adds the DigiRadioFinale figure/table to the manual, and adds a brief for the iOS app side (active_source API shape, enhancement semantics change) to hand to Cursor. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 192 KiB |
@@ -6,188 +6,186 @@ con il driver firmware (`components/drivers/adau1701/`) e le API HTTP
|
||||
(`components/net/src/SetupWebServer.cpp`). Ogni valore di indirizzo/registro citato è
|
||||
letto direttamente dai file di export SigmaStudio, non inventato.
|
||||
|
||||
**Root cause del bug "volume/mixer/EQ non si salvano mai" trovato e risolto in questa
|
||||
sessione (2026-08-24): vedi §7.** Tutto il resto del documento descrive l'architettura
|
||||
del programma DSP com'è oggi, dopo il fix.
|
||||
**Questo documento descrive la revisione "DigiRadioFinale" (2026-08-25)**, che
|
||||
sostituisce il programma DSP precedente (74 parametri, mixer additivo) con uno
|
||||
molto più ricco (224 parametri) basato su un **selettore di sorgente esclusivo**
|
||||
invece di un mixer. §5 raccoglie anche i bug storici della revisione precedente,
|
||||
per riferimento.
|
||||
|
||||
---
|
||||
|
||||
## 1. Catena del segnale (da `DigiRadio_NetList.xml`)
|
||||
|
||||
```
|
||||
┌─────────────┐
|
||||
Si4684 (I2S) ──L──▶ │ Gain Si4674 │──▶┐
|
||||
──R──▶ │ (addr 3,4) │──▶┤
|
||||
└─────────────┘ │
|
||||
│ ┌──────────────┐ ┌──────────────┐
|
||||
ESP32 (I2S) ──L──▶ ┌─────────────┐ ├──▶│ St Mixer1 │──▶│ Param EQ1 │──┐
|
||||
──R──▶ │ Gain ESP32 │──▶┤ │ ST0/ST1/ST2 │ │ 6 bande │ │
|
||||
│ (addr 5,6) │──▶┘ │ (addr 9-11) │ │ (addr 12-41) │ │
|
||||
└─────────────┘ └──────────────┘ └──────────────┘ │
|
||||
│
|
||||
Beep1 (interno) ──▶ Single1 ──▶ SSplitter1 ──▶ (ST2, ingresso mixer) │
|
||||
(addr 0-2) (addr 7) (addr 8) │
|
||||
Input1 (Si4684 L/R, ESP32 L/R) ──┬─▶ DCB1 (L radio) ─┐
|
||||
├─▶ DCB2 (R radio) ─┼─▶ Compressor1 ─▶ 1×RTA1 (L) ─┐
|
||||
├─▶ DCB4 (L esp32) ─┤ (stereo RMS) 1×RTA2 (R) ─┤
|
||||
└─▶ DCB3 (R esp32) ─┘ 1×RTA3 (L) ─┤ (readback,
|
||||
1×RTA4 (R) ─┤ ingresso)
|
||||
Beep1 ─▶ S Splitter1 (mono→stereo) ─────────────────────────────────────────────────┤
|
||||
▼
|
||||
┌──────────────────┐
|
||||
│ Multiple1 (L/R) │
|
||||
│ = MASTER VOLUME │
|
||||
│ (addr 42, 43) │
|
||||
│ MX1 (mux) │
|
||||
│ select = DC1 │
|
||||
│ 0=Radio 1=BT │
|
||||
│ 2=Beep (raw int!) │
|
||||
└──────────────────┘
|
||||
│
|
||||
┌────────────┴────────────┐
|
||||
▼
|
||||
Param EQ1 (6 bande, addr 59-88)
|
||||
│
|
||||
▼
|
||||
SPhat1 (Spatializer, addr 89-140)
|
||||
│
|
||||
▼
|
||||
Gen Filter1 (Voice Clarifier,
|
||||
addr 141-145 — non tarato)
|
||||
│
|
||||
▼
|
||||
Multiple1 (Master Volume,
|
||||
addr 146-147)
|
||||
│
|
||||
▼
|
||||
Bass Boost1 (Dynamic Bass Boost,
|
||||
addr 148-187)
|
||||
│
|
||||
┌──────────┴──────────┐
|
||||
▼ ▼
|
||||
┌───────────────┐ ┌───────────────┐
|
||||
│ Limiter1 (L) │ │ Limiter2 (R) │
|
||||
│ (addr 44-58) │ │ (addr 59-73) │
|
||||
└───────────────┘ └───────────────┘
|
||||
1×RTA1_2 (readback) 1×RTA2_2 (readback)
|
||||
│ │
|
||||
▼ ▼
|
||||
Limiter1 (L) Limiter2 (R)
|
||||
addr 209-223 addr 194-208
|
||||
│ │
|
||||
▼ ▼
|
||||
Output1 Output2
|
||||
(→ BT1035 I2S, L) (→ BT1035 I2S, R)
|
||||
```
|
||||
|
||||
Punto architetturale importante, spesso fonte di confusione: **ogni sorgente ha DUE
|
||||
livelli di gain in cascata**, non uno solo:
|
||||
**Cambio architetturale rispetto alla revisione precedente**: non esiste più un
|
||||
mixer che combina Si4684 + ESP32 + Beep simultaneamente. `MX1` è un **selettore
|
||||
esclusivo**: passa UNA SOLA delle tre coppie stereo alla volta, scelta scrivendo
|
||||
`DC1` (indirizzo 3). Non esistono più gain pre-mixer per sorgente (`SI4674`/`ESP32`
|
||||
sono spariti) — il livello si controlla solo con Master Volume ed EQ, a valle
|
||||
della selezione.
|
||||
|
||||
1. **Gain pre-mixer** (`SI4674`/`SI4674_1` addr 3/4, `ESP32`/`ESP32_1` addr 5/6) — un
|
||||
gain indipendente per canale L e R, applicato PRIMA che il segnale entri nel mixer.
|
||||
2. **Gain del mixer** (`STMIXER1_ST0_VOLUME`/`ST1_VOLUME` addr 9/10) — un SOLO gain per
|
||||
l'intera coppia stereo di quella sorgente, applicato AL mixer.
|
||||
|
||||
Se uno dei due è a -96dB (muto) e l'altro è aperto, il risultato finale è comunque
|
||||
muto — impostare solo uno dei due senza sapere dell'altro è la causa più comune di
|
||||
"ho cambiato il volume ma non sento niente".
|
||||
**Scoperta empirica cruciale (2026-08-25)**: `DC1` è dichiarato
|
||||
`SIGMASTUDIOTYPE_FIXPOINT` nell'export compilato (che farebbe pensare al formato
|
||||
5.23 usato da tutte le altre celle), ma **MX1 legge invece un intero a 32 bit
|
||||
grezzo**. Scrivere `0x00800000` (= 1.0 in 5.23) non cambia la sorgente; scrivere
|
||||
`0x00000001` sì. Confermato dal vivo: 0=Radio, 1=Bluetooth(ESP32), 2=Beep. Vedi
|
||||
`adau1701::paramSourceIndex()` e `Adau1701Driver::selectSource()`.
|
||||
|
||||
---
|
||||
|
||||
## 2. Mappa completa dei registri Parameter RAM (74 indirizzi, 0-73)
|
||||
## 2. Mappa completa dei registri Parameter RAM (224 indirizzi, 0-223)
|
||||
|
||||
| Indirizzo | Nome SigmaStudio | Funzione | Gruppo |
|
||||
| Indirizzi | Blocco | Funzione | Controllo runtime |
|
||||
|---|---|---|---|
|
||||
| 0 | `BEEP1_ENABLE` | Abilita generatore toni interno | Diagnostica |
|
||||
| 1 | `BEEP1_KICK` | Trigger del generatore toni | Diagnostica |
|
||||
| 2 | `BEEP1_BEEP_FREQ` | Frequenza del tono (fissa, mai cambiata a runtime) | Diagnostica |
|
||||
| 3 | `SI4674` | Gain pre-mixer Si4684, canale L | Mixer |
|
||||
| 4 | `SI4674_1` | Gain pre-mixer Si4684, canale R | Mixer |
|
||||
| 5 | `ESP32` | Gain pre-mixer streaming ESP32, canale L | Mixer |
|
||||
| 6 | `ESP32_1` | Gain pre-mixer streaming ESP32, canale R | Mixer |
|
||||
| 7 | `SINGLE1` | Gain del tono Beep prima dello splitter | Diagnostica |
|
||||
| 8 | `SSPLITTER1` | Splitter mono→stereo per il tono Beep | Diagnostica |
|
||||
| 9 | `STMIXER1_ST0_VOLUME` | Gain mixer, leg Si4684 (stereo, un solo controllo) | Mixer |
|
||||
| 10 | `STMIXER1_ST1_VOLUME` | Gain mixer, leg ESP32 (stereo, un solo controllo) | Mixer |
|
||||
| 11 | `STMIXER1_ST2_VOLUME` | Gain mixer, leg Beep — **mai esposto da nessuna API curata**, fisso a 1.0 (unity) di fabbrica | Mixer (non controllato) |
|
||||
| 12-16 | `PARAMEQ1_ST0_*` (B0,B1,B2,A0,A1) | Banda EQ 0 — **filtro passa-alto fisso, mai scritto da `applyEq()`** | EQ (banda bloccata) |
|
||||
| 17-21 | `PARAMEQ1_ST1_*` | Banda EQ 1 (default 100 Hz) | EQ |
|
||||
| 22-26 | `PARAMEQ1_ST2_*` | Banda EQ 2 (default 400 Hz) | EQ |
|
||||
| 27-31 | `PARAMEQ1_ST3_*` | Banda EQ 3 (default 1000 Hz) | EQ |
|
||||
| 32-36 | `PARAMEQ1_ST4_*` | Banda EQ 4 (default 3000 Hz) | EQ |
|
||||
| 37-41 | `PARAMEQ1_ST5_*` | Banda EQ 5 (default 8000 Hz) | EQ |
|
||||
| 42 | `MULTIPLE1` | **Volume master**, canale L | Master |
|
||||
| 43 | `MULTIPLE1_1` | **Volume master**, canale R | Master |
|
||||
| 44-58 | `LIMITER1_*` | Limiter canale L (soglia a indirizzo 55) | Limiter |
|
||||
| 59-73 | `LIMITER2_*` | Limiter canale R (soglia a indirizzo 70) | Limiter |
|
||||
| 0-2 | `BEEP1_*` | Tono di test interno | `setBeepEnabled()` (live-only) |
|
||||
| 3 | `DC1` | Selettore sorgente per MX1 — **intero grezzo**, non 5.23 | `selectSource()` |
|
||||
| 4-7 | `DCB1-4_POLE` | DC blocker, uno per canale (radio L/R, esp32 L/R) | Fisso (compilato) |
|
||||
| 8 | `SSPLITTER1` | Fan-out mono→stereo per Beep | Fisso |
|
||||
| 9-46 | `COMPRESSOR1_*` | Compressore RMS stereo (curva a 34 punti) su radio L/R | Fisso |
|
||||
| 47-58 | `1XRTA3,4,1,2` | 4 VU-meter in ingresso (radio L/R, esp32 L/R) | Lettura via indirizzo speciale 2074 — **meccanismo non ancora implementato in firmware** |
|
||||
| 59-88 | `PARAMEQ1_ST0..5_*` | EQ parametrico, 6 bande × 5 coefficienti (B0,B1,B2,A0,A1) | `setEqBand()`/`applyEq()` |
|
||||
| 89-140 | `SPHAT1_*` | Spatializer (SuperPhat) — solo `SPREAD1`/`SPREAD2` (139,140) sono la manopola di intensità; il resto (filtro crossover, tabella compander) è tarato in SigmaStudio | `setStereoSpreadLevel()` — scala SPREAD1/2 proporzionalmente (0=nessuno spread aggiunto, 100=pieno) |
|
||||
| 141-145 | `GENFILTER1_ST0_*` | Voice Clarifier — **ancora piatto/identità** in questo export (b0=1, resto 0), non tarato | Non ancora implementato |
|
||||
| 146-147 | `MULTIPLE1`, `MULTIPLE1_1` | Master Volume L/R | `setMasterVolume()` |
|
||||
| 148-187 | `BASSBOOST1_*` | Dynamic Bass Boost — `BASSFREQUENCY`/`TIMECONSTANT` fissi; filtro crossover (B0,B1,B2,A1,A2) e tabella compander a 33 punti (`TABLE0-32`) sono la parte "intensità" | `setBassBoostLevel()` — scala filtro+tabella verso l'identità/unità (0=bypass piatto, 100=pieno compilato) |
|
||||
| 188-193 | `1XRTA2_2,1_2` | 2 VU-meter in uscita (post Bass Boost, pre limiter) | Stesso meccanismo di lettura non ancora implementato |
|
||||
| 194-208 | `LIMITER2_*` | Limiter canale R (soglia indirizzo 205) | Fisso |
|
||||
| 209-223 | `LIMITER1_*` | Limiter canale L (soglia indirizzo 220) | Fisso |
|
||||
|
||||
Le 6 bande EQ condividono gli **stessi coefficienti per L e R** (il cell "Parametric
|
||||
EQ - Double Precision" è stereo ma con un solo set di coefficienti per banda) — non
|
||||
esiste un controllo EQ separato per canale.
|
||||
|
||||
Formato dati: fixed-point **5.23** (28 bit significativi, non 32 — un errore di
|
||||
decodifica di questo formato durante l'indagine del 23/08 aveva fatto sembrare
|
||||
instabile un filtro che in realtà era corretto; vedi `core::floatToFixpoint823()` /
|
||||
sign-extend da bit 27 in `Adau1701Driver.cpp`).
|
||||
Formato dati: fixed-point **5.23** per quasi tutte le celle (28 bit significativi,
|
||||
sign-extend da bit 27 — vedi `core::floatToFixpoint823()`), **eccetto `DC1`** che è
|
||||
un intero grezzo a 32 bit (vedi sopra).
|
||||
|
||||
---
|
||||
|
||||
## 3. Registri di controllo (Core Control block, 0x800-0x827)
|
||||
## 3. API HTTP e corrispondenza con i registri
|
||||
|
||||
| Indirizzo | Nome | Uso nel nostro firmware |
|
||||
|---|---|---|
|
||||
| 0x81C | Core Control Register | Scritto una sola volta al boot dal replay del programma compilato |
|
||||
| 0x81E | Serial Output Control | Compilato, mai modificato a runtime |
|
||||
| 0x81F | Serial Input Control (bit IBP/ILP) | **Storia**: un override IBP=1 qui era stato introdotto il 16/08 insieme a un fix non correlato di Si4684, mai validato da solo, e causa del fruscio multi-giorno risolto oggi (24/08). Rimosso — ora resta al default compilato (0x00) |
|
||||
| 0x820/0x821 | MP Config 0/1 | Compilato, mai toccato |
|
||||
| 0x822 | Analog Power-Down | Compilato, mai toccato |
|
||||
| 0x826 | Analog Interface Register 2 | Contiene i bit IBIAS_ADJ/VREF_TRIM di trim analogico interno, mai toccati; è un registro diverso da quello dove viveva l'override IBP (0x81F) |
|
||||
|
||||
---
|
||||
|
||||
## 4. API HTTP e corrispondenza con i registri — tutte testate dal vivo il 24/08
|
||||
|
||||
| Endpoint | Metodo | Corpo | Registri toccati | Persistenza NVS | Testato |
|
||||
| Endpoint | Metodo | Corpo | Cosa tocca | Persistenza | Testato dal vivo |
|
||||
|---|---|---|---|---|---|
|
||||
| `/api/audio/profile` | GET | — | legge tutto | — | ✅ |
|
||||
| `/api/audio/profile` | PUT | mixer + master + eq[6] + enhancements | 3,4,5,6,9,10,12-41,42,43 | ✅ | ✅ (round-trip completo dopo riavvio) |
|
||||
| `/api/audio/reset` | POST | — | ripristina `AudioProfile::factoryDefault()` (mixer: **entrambe** le sorgenti aperte a 0dB, non radio-first) | ✅ | ✅ |
|
||||
| `/api/audio/stereo-enhance` | POST | `{"level":0-100}` | bande EQ 3,4,5 (sovrascrive) | ✅ | ✅ |
|
||||
| `/api/audio/bass-enhance` | POST | `{"level":0-100}` | bande EQ 1,2 (sovrascrive) | ✅ | ✅ |
|
||||
| `/api/audio/beep` | POST | `{"enabled":true/false}` | 0 (`BEEP1_ENABLE`), 1 (`BEEP1_KICK`) | ❌ (live-only, come da design) | ✅ |
|
||||
| `/api/dsp/params` | GET | — | elenco statico nome→indirizzo (74 celle) | — | ✅ |
|
||||
| `/api/dsp/param` | PUT | `{"name":"...","value":<float>}` | qualunque cella per nome, incluse quelle **non** raggiungibili dalle API curate (es. `STMIXER1_ST2_VOLUME`) | ❌ (live-only, "escape hatch" come SigmaStudio Remote Connection) | ✅ (scritto e ripristinato `STMIXER1_ST2_VOLUME`) |
|
||||
| `/api/tuner/xtal-calibrate` | POST | `{"ibias","ctun","xtal_freq_hz"}` | Si4684 POWER_UP (non ADAU1701) | ✅ (dal fix di stasera) | ✅ |
|
||||
| `/api/audio/profile` | GET/PUT | `active_source`, `master`, `eq[6]`, `enhancements` | `DC1`, EQ 59-88, Master 146-147, Bass Boost/Spatializer via enhancements | ✅ | ✅ |
|
||||
| `/api/audio/reset` | POST | — | `AudioProfile::factoryDefault()` (Radio, EQ piatto, enhancements 0) | ✅ | — |
|
||||
| `/api/audio/stereo-enhance` | POST | `{"level":0-100}` | `SPHAT1_SPREAD1/2` (scala proporzionale) | ✅ | ✅ (effetto soggettivo/sottile) |
|
||||
| `/api/audio/bass-enhance` | POST | `{"level":0-100}` | `BASSBOOST1_*` filtro+tabella (scala verso identità) | ✅ | ✅ (confermato su radio, non su tono fisso — l'algoritmo è dinamico, reagisce a contenuto con dinamica reale) |
|
||||
| `/api/audio/beep` | POST | `{"enabled":true/false}` | `BEEP1_ENABLE/KICK` | ❌ (live-only, per design) | ✅ |
|
||||
| `/api/dsp/params` | GET | — | elenco statico nome→indirizzo (230 celle, incluse le 6 speciali readback) | — | ✅ |
|
||||
| `/api/dsp/param` | PUT | `{"name":"...","value":<float>}` | qualunque cella per nome — **eccetto `DC1`, che qui va scritto già come intero puro, non tramite `selectSource()`** | ❌ (live-only) | ✅ (sweep completo di 223/224 celle scrivibili, 0 errori) |
|
||||
|
||||
### Campo `"locked"` per banda EQ (aggiunto oggi)
|
||||
`active_source` accetta `"radio"`, `"bluetooth"`, `"beep"`. Il vecchio campo
|
||||
`"mixer"` (con `si4684_left_db`/`esp32_left_db`/`mix_left_db` ecc.) **non esiste
|
||||
più** — non ha più senso dato che non c'è più un mixer da bilanciare.
|
||||
|
||||
`GET/PUT /api/audio/profile` ora include `"locked":true/false` per ciascuna delle 6
|
||||
bande in `eq[]`:
|
||||
- banda 0: **sempre `true`** — è il passa-alto fisso, qualsiasi valore scritto è
|
||||
cosmetico, non ha mai effetto udibile (`Adau1701Driver::applyEq()` la salta
|
||||
esplicitamente).
|
||||
- bande 1,2: `true` quando `bass_level > 0` — l'enhancement le sovrascrive con valori
|
||||
calcolati da formula, un edit manuale in quel momento non è udibile.
|
||||
- bande 3,4,5: `true` quando `stereo_level > 0`, stesso motivo.
|
||||
|
||||
Prima di questo fix il comportamento era identico (le bande erano già sovrascritte),
|
||||
ma l'API non lo segnalava — sembrava che "il salvataggio non facesse nulla" quando in
|
||||
realtà stava facendo esattamente quello che il DSP prevede, solo senza dirlo.
|
||||
Il campo `"locked"` per banda EQ (introdotto il 24/08 quando bass/stereo enhance
|
||||
sovrascrivevano le bande EQ) **ora è sempre `false` tranne la banda 0** (passa-alto
|
||||
fisso): bass/stereo enhance non toccano più l'EQ, guidano direttamente Bass
|
||||
Boost1/SPhat1.
|
||||
|
||||
---
|
||||
|
||||
## 5. Bug trovati e stato
|
||||
## 4. VU-meter (readback) — non ancora implementato
|
||||
|
||||
Le 6 celle `1×RTA*` sono veri VU-meter (level detector) posizionati in 4 punti
|
||||
d'ingresso e 2 punti d'uscita. Il loro valore letto NON sta al normale indirizzo
|
||||
Parameter RAM di ciascuna — condividono tutte l'indirizzo speciale **2074**, con
|
||||
un codice di selezione diverso per ciascuna (`VALUES_1XRTA1` = 0x0376, ecc., tipo
|
||||
`SIGMASTUDIOTYPE_SPECIAL`/`SIGMASTUDIOTYPE_10_14`). Questo è il meccanismo di
|
||||
"Data Capture" dell'ADAU1701 (registro indiretto), diverso dal semplice
|
||||
read/safeload usato ovunque altrove in questo firmware. **Va ancora reverse-
|
||||
engineerato e implementato** — non è stato inventato né testato in questa sessione.
|
||||
|
||||
---
|
||||
|
||||
## 5. Bug trovati e stato (cronologia)
|
||||
|
||||
| # | Sintomo | Causa reale | Stato |
|
||||
|---|---|---|---|
|
||||
| 1 | Mixer/volume/EQ salvati non sopravvivono MAI a un riavvio | **NVS inizializzato DOPO** `AudioService::loadAndApply()` in `app_main()` — ogni lettura falliva con `ESP_ERR_NVS_NOT_INITIALIZED` (0x1101), silenziosamente, da sempre | ✅ risolto oggi — riordinato boot in `main.cpp`, verificato dal vivo |
|
||||
| 2 | Anche dopo il fix #1, mixer e master tornavano comunque al preset "radio" a ogni riavvio | `HardwareBootstrap::boot()` chiamava `applyRadioFirstMix()` **incondizionatamente** dopo il caricamento, sovrascrivendo qualunque valore appena ripristinato da NVS | ✅ risolto oggi — ora condizionale, si applica solo se non c'è un profilo salvato |
|
||||
| 3 | Modificare la banda EQ 0 (20 Hz) via web UI/app non ha mai effetto udibile | È il filtro passa-alto fisso del programma compilato, `applyEq()` la salta di proposito | ✅ ora segnalato via `"locked":true`, non più silenzioso |
|
||||
| 4 | Attivare bass/stereo enhancement sembra "cancellare" le modifiche manuali dell'EQ sulle bande coinvolte | `core::applyEnhancementsToEq()` sovrascrive bande 1-2 (bass) e 3-5 (stereo) con valori a formula quando il livello è > 0 | ✅ ora segnalato via `"locked":true` sulle bande coinvolte; il comportamento DSP resta invariato (per design) |
|
||||
| 5 | Il leg Beep del mixer (`STMIXER1_ST2_VOLUME`, indirizzo 11) non è mai regolabile dalle API curate | Nessun bug — è un ingresso diagnostico interno, mai stato nei piani esporlo. Raggiungibile comunque via `/api/dsp/param` se serve per debug | Non è un bug, solo documentato |
|
||||
| 6 | Fruscio persistente su radio e streaming (multi-giorno) | Override IBP=1 su `SerialInputRegister` (0x81F), introdotto l'8/16 agosto insieme a un fix non correlato, mai validato da solo — condiviso da tutti gli ingressi seriali del chip | ✅ risolto ieri (24/08, prima parte della sessione) — vedi `docs/si4684-rf-investigation-report.md` |
|
||||
| 1 | Mixer/volume/EQ salvati non sopravvivono MAI a un riavvio (revisione precedente) | NVS inizializzato dopo `AudioService::loadAndApply()` in `app_main()` | ✅ risolto 2026-08-24 |
|
||||
| 2 | Mixer e master tornavano al preset "radio" a ogni riavvio anche dopo il fix #1 | `HardwareBootstrap::boot()` chiamava `applyRadioFirstMix()` incondizionatamente | ✅ risolto 2026-08-24 |
|
||||
| 3 | Qualsiasi modifica EQ/enhancement diversa da zero → silenzio totale (anche sul tono di test) | Segno mancante in `core::designPeakingEq()`: i coefficienti di retroazione RBJ (sottrattivi) venivano scritti tali e quali nei registri A0/A1 dell'ADAU1701 (additivi) — retroazione positiva invece che negativa, il filtro divergeva su un valore costante (DC, inaudibile) | ✅ risolto 2026-08-25 — vedi `components/core/src/BiquadDesign.cpp`, test di stabilità in `biquad_design_test.cpp` |
|
||||
| 4 | Bridge TCP SigmaStudio (porta 8086): `accept()` in loop infinito su EBADF da ogni boot | `SigmaStudioTcpServer::stop()` cancellava incondizionatamente il singleton del socket attivo, anche quando chiamato sull'oggetto move-from (ogni boot ne crea uno) | ✅ risolto 2026-08-25 |
|
||||
| 5 | Nuovo netlist DigiRadioFinale: nessun mixer, solo `MX1` a selezione esclusiva | Non è un bug — cambio di design intenzionale, confermato dall'utente | Documentato, non un bug |
|
||||
| 6 | Scrivere `DC1` in formato 5.23 (es. 1.0 = 0x00800000) non cambia la sorgente selezionata | `MX1` legge `DC1` come intero grezzo, non fixpoint, nonostante `TYPE_DC1` compilato dica `SIGMASTUDIOTYPE_FIXPOINT` | ✅ risolto 2026-08-25 — confermato dal vivo (0/1/2 → Radio/BT/Beep) |
|
||||
| 7 | Fruscio persistente su radio e streaming (multi-giorno, revisione precedente) | Override IBP=1 su `SerialInputRegister` (0x81F), mai validato in isolamento | ✅ risolto 2026-08-24 |
|
||||
|
||||
---
|
||||
|
||||
## 6. Come testare manualmente (comandi usati stasera)
|
||||
## 6. Come testare manualmente
|
||||
|
||||
```bash
|
||||
# Stato attuale
|
||||
curl http://192.168.1.62/api/audio/profile
|
||||
|
||||
# Scrivi un pattern distintivo (mixer + master + 5 bande EQ)
|
||||
# Cambia sorgente
|
||||
curl -X PUT http://192.168.1.62/api/audio/profile -d '{
|
||||
"mixer": {"si4684_left_db": 0, "si4684_right_db": 0,
|
||||
"esp32_left_db": -96, "esp32_right_db": -96,
|
||||
"mix_left_db": 0, "mix_right_db": -96},
|
||||
"master": {"left_db": -4, "right_db": -4},
|
||||
"active_source": "bluetooth",
|
||||
"master": {"left_db": 0, "right_db": 0},
|
||||
"eq": [
|
||||
{"gain_db": 0, "center_hz": 20, "q": 1.414},
|
||||
{"gain_db": 5, "center_hz": 100, "q": 1},
|
||||
{"gain_db": -3, "center_hz": 400, "q": 1.2},
|
||||
{"gain_db": 2, "center_hz": 1000, "q": 1},
|
||||
{"gain_db": -1, "center_hz": 3000, "q": 1},
|
||||
{"gain_db": 4, "center_hz": 8000, "q": 1}
|
||||
{"gain_db": 0, "center_hz": 100, "q": 1},
|
||||
{"gain_db": 0, "center_hz": 400, "q": 1},
|
||||
{"gain_db": 0, "center_hz": 1000, "q": 1},
|
||||
{"gain_db": 0, "center_hz": 3000, "q": 1},
|
||||
{"gain_db": 0, "center_hz": 8000, "q": 1}
|
||||
],
|
||||
"enhancements": {"stereo_level": 0, "bass_level": 0}
|
||||
}'
|
||||
|
||||
# Riavvia la scheda (fisicamente, o via reset seriale) e rileggi:
|
||||
curl http://192.168.1.62/api/audio/profile
|
||||
# → deve mostrare ESATTAMENTE gli stessi valori scritti sopra
|
||||
# Bass Boost / Spatializer
|
||||
curl -X POST http://192.168.1.62/api/audio/bass-enhance -d '{"level":100}'
|
||||
curl -X POST http://192.168.1.62/api/audio/stereo-enhance -d '{"level":100}'
|
||||
```
|
||||
|
||||
Per leggere/scrivere una singola cella arbitraria (debug avanzato, non persistente):
|
||||
Per leggere/scrivere una singola cella arbitraria (debug avanzato, non
|
||||
persistente — **non usare per `DC1`**, che ha una semantica intero-grezzo
|
||||
diversa da tutte le altre celle):
|
||||
|
||||
```bash
|
||||
curl http://192.168.1.62/api/dsp/params # elenco nome→indirizzo
|
||||
curl -X PUT http://192.168.1.62/api/dsp/param -d '{"name":"STMIXER1_ST2_VOLUME","value":1.0}'
|
||||
curl http://192.168.1.62/api/dsp/params # elenco nome→indirizzo (230 celle)
|
||||
curl -X PUT http://192.168.1.62/api/dsp/param -d '{"name":"SPHAT1_SPREAD1","value":0.0629}'
|
||||
```
|
||||
|
||||
---
|
||||
@@ -196,12 +194,12 @@ curl -X PUT http://192.168.1.62/api/dsp/param -d '{"name":"STMIXER1_ST2_VOLUME",
|
||||
|
||||
| File | Contenuto |
|
||||
|---|---|
|
||||
| `Firmware/ADAU1701-Firmware/DigiRadio_IC_1_PARAM.h` | Sorgente di verità per tutti gli indirizzi Parameter RAM |
|
||||
| `Firmware/ADAU1701-Firmware/DigiRadio_IC_1_PARAM.h` | Sorgente di verità per tutti gli indirizzi Parameter RAM (export DigiRadioFinale) |
|
||||
| `Firmware/ADAU1701-Firmware/DigiRadio_NetList.xml` | Topologia del segnale (chi è collegato a chi) |
|
||||
| `components/drivers/adau1701/include/adau1701/Adau1701ParamTable.hpp` | Tabella nome→indirizzo generata da PARAM.h, usata da `/api/dsp/param` |
|
||||
| `components/drivers/adau1701/include/adau1701/Adau1701ParamMap.hpp` | Funzioni helper indirizzo-per-banda-EQ e indirizzo-per-sorgente-mixer |
|
||||
| `components/drivers/adau1701/src/Adau1701Driver.cpp` | Implementazione `applyMixer`/`applyEq`/`setMasterVolume`/`setBeepEnabled` |
|
||||
| `components/services/audio/src/AudioService.cpp` | `loadAndApply()`, `applyRadioFirstMix()`, enhancement plumbing |
|
||||
| `components/core/src/EnhancementsDesign.cpp` | Formula di sovrascrittura EQ per bass/stereo enhancement |
|
||||
| `main/main.cpp` | Ordine di boot (`app_main()`) — sede del fix root-cause di oggi |
|
||||
| `main/hardware_bootstrap.cpp` | `HardwareBootstrap::boot()` — sede del secondo fix (radio-first condizionale) |
|
||||
| `components/core/include/core/ActiveSource.hpp` | Enum Radio/Bluetooth/Beep + nota sulla semantica intero-grezzo di DC1 |
|
||||
| `components/drivers/adau1701/include/adau1701/Adau1701ParamTable.hpp` | Tabella nome→indirizzo generata da PARAM.h (230 celle) |
|
||||
| `components/drivers/adau1701/include/adau1701/Adau1701ParamMap.hpp` | `paramAddrEqBandBase()`, `paramSourceIndex()` |
|
||||
| `components/drivers/adau1701/src/Adau1701Driver.cpp` | `selectSource()`, `applyEq()`, `setMasterVolume()`, `setBassBoostLevel()`, `setStereoSpreadLevel()`, `setBeepEnabled()` |
|
||||
| `components/core/src/BiquadDesign.cpp` | `designPeakingEq()` — fix del segno A0/A1 (2026-08-25) |
|
||||
| `components/services/audio/src/AudioService.cpp` | `loadAndApply()`, `applyRadioFirstMix()`, `selectSource()`, enhancement plumbing |
|
||||
| `docs/manual/ch-sigmastudio.tex` §"Next revision: DigiRadioFinale" | Diagramma e tabella indirizzi per il manuale PDF |
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
# Brief per Cursor — allineamento app iOS al nuovo firmware DSP (DigiRadioFinale)
|
||||
|
||||
Il firmware ADAU1701 è stato sostituito con un programma DSP molto più ricco
|
||||
(224 parametri contro 74 prima). Questo documento descrive **cosa è cambiato
|
||||
lato API HTTP** e **quali controlli nuovi puoi costruire in app**, più qualche
|
||||
indicazione di UX. I dettagli implementativi Swift (struttura file, ViewModels
|
||||
esistenti, tab bar) restano una tua scelta — qui do solo il contratto dati e
|
||||
gli obiettivi funzionali.
|
||||
|
||||
Dispositivo di test: `http://192.168.1.62` (mDNS `digiradio-CC4DB4.local`).
|
||||
|
||||
---
|
||||
|
||||
## 1. Breaking change: `mixer` → `active_source`
|
||||
|
||||
**Prima**: `GET/PUT /api/audio/profile` aveva un oggetto `"mixer"` con guadagni
|
||||
indipendenti per Si4684, ESP32 e i due leg del mixer — permetteva di
|
||||
"mescolare" radio e Bluetooth insieme.
|
||||
|
||||
**Ora**: il firmware non ha più un mixer. C'è un **selettore di sorgente
|
||||
esclusivo** — si ascolta una sorgente alla volta, come su un vero stereo.
|
||||
|
||||
```json
|
||||
{
|
||||
"active_source": "radio",
|
||||
"master": {"left_db": 0, "right_db": 0},
|
||||
"eq": [ ... 6 bande, invariato ... ],
|
||||
"enhancements": {"stereo_level": 0, "bass_level": 0}
|
||||
}
|
||||
```
|
||||
|
||||
`active_source` accetta esattamente `"radio"`, `"bluetooth"`, `"beep"`.
|
||||
`"beep"` è il tono di test interno (usato per diagnostica firmware, probabilmente
|
||||
da nascondere in UI di produzione o mettere in una sezione "Diagnostica").
|
||||
|
||||
**Azione richiesta**: sostituire ogni UI che oggi mostra due slider indipendenti
|
||||
(volume radio / volume BT) con un **selettore a scelta singola** (segmented
|
||||
control o lista) tra Radio e Bluetooth. Non esiste più un modo per sentirli
|
||||
mescolati.
|
||||
|
||||
---
|
||||
|
||||
## 2. `enhancements` ora pilota algoritmi DSP reali, non più un trucco EQ
|
||||
|
||||
**Prima**: `bass_level`/`stereo_level` sovrascrivevano silenziosamente alcune
|
||||
bande dell'equalizzatore manuale (da cui il campo `"locked"` per banda, per
|
||||
segnalarlo).
|
||||
|
||||
**Ora**: pilotano due blocchi DSP dedicati e indipendenti dall'EQ:
|
||||
- `bass_level` (0-100) → **Bass Boost1**, un vero algoritmo ADI di "Dynamic
|
||||
Bass Boost" (filtro crossover + compander dinamico). Effetto udibile solo su
|
||||
contenuto reale con dinamica (radio, streaming) — su un tono fisso costante
|
||||
non si sente quasi nulla, è normale (l'algoritmo reagisce a variazioni di
|
||||
livello nel tempo).
|
||||
- `stereo_level` (0-100) → **SPhat1** ("SuperPhat" Spatializer/stereo widener),
|
||||
un secondo algoritmo ADI dedicato.
|
||||
|
||||
Il campo `"locked"` per banda EQ **ora è sempre `false`** tranne la banda 0
|
||||
(passa-alto fisso, sempre `true`, invariato da prima). Puoi quindi rimuovere
|
||||
qualunque logica "banda grigia perché l'enhancement l'ha sovrascritta" —
|
||||
l'EQ manuale ora è sempre indipendente dagli enhancement.
|
||||
|
||||
**Azione richiesta**: nessun cambio di forma dati per `enhancements` (stessi
|
||||
due slider 0-100 di prima), ma puoi rimuovere la UI "banda bloccata" per le
|
||||
bande 1-5 (resta solo per la banda 0, che era già così).
|
||||
|
||||
---
|
||||
|
||||
## 3. Non ancora disponibile lato firmware (in arrivo)
|
||||
|
||||
- **VU-meter / readback dei livelli** (in ingresso e in uscita) — il firmware
|
||||
ha 6 sensori di livello nel DSP ma il meccanismo di lettura (un registro
|
||||
indiretto dell'ADAU1701) non è ancora implementato. Non costruire ancora una
|
||||
UI che dipende da dati di livello in tempo reale dal firmware — se vuoi una
|
||||
sezione "grafica" ora, usa un placeholder o un'animazione generica non
|
||||
agganciata a dati reali, finché non arriva l'endpoint.
|
||||
- **Voice Clarifier** — la cella DSP dedicata (`Gen Filter1`) esiste nella
|
||||
catena del segnale ma non è ancora tarata (passa tutto invariato). Nessuna
|
||||
API la pilota ancora. Non esporre ancora questo controllo in UI, o mettilo
|
||||
disabilitato/"prossimamente".
|
||||
- **Mute in uscita** (pre-Output1/Output2) — non presente in questo export del
|
||||
firmware. Se serve, va aggiunto lato SigmaStudio prima di poter esporlo via API.
|
||||
|
||||
Ti avviso appena questi sono pronti lato firmware con l'endpoint esatto.
|
||||
|
||||
---
|
||||
|
||||
## 4. Riepilogo controlli disponibili ORA (tutti testati dal vivo sul dispositivo)
|
||||
|
||||
| Controllo | Endpoint | Corpo |
|
||||
|---|---|---|
|
||||
| Sorgente attiva | `PUT /api/audio/profile` (campo `active_source`) | `"radio"` \| `"bluetooth"` \| `"beep"` |
|
||||
| Master volume | `PUT /api/audio/profile` (campo `master`) | `{"left_db":..,"right_db":..}`, range tipico -96..+12 dB |
|
||||
| Equalizzatore (6 bande) | `PUT /api/audio/profile` (campo `eq`) | invariato: `gain_db`, `center_hz`, `q` per banda; banda 0 sempre inerte |
|
||||
| Bass Boost | `POST /api/audio/bass-enhance` | `{"level":0-100}` |
|
||||
| Stereo Spread | `POST /api/audio/stereo-enhance` | `{"level":0-100}` |
|
||||
| Tono di test (diagnostica) | `POST /api/audio/beep` | `{"enabled":true/false}` — richiede anche `active_source:"beep"` per essere udibile |
|
||||
| Lettura stato completo | `GET /api/audio/profile` | risposta con tutti i campi sopra |
|
||||
|
||||
---
|
||||
|
||||
## 5. Indicazioni di stile (dalla richiesta dell'utente)
|
||||
|
||||
- Stile Apple/HIG nativo: niente slider/bottoni "grezzi" o accozzaglia in
|
||||
un'unica schermata. Raggruppa per tab/sezione logica (es. "Ascolto" per
|
||||
sorgente+volume, "Suono" per EQ+Bass Boost+Stereo Spread, "Bluetooth" per
|
||||
pairing, "Diagnostica" per tono di test/dettagli tecnici).
|
||||
- Preferisci componenti nativi SwiftUI (`Picker` segmented per la sorgente,
|
||||
`Slider` con `.tint()` per i livelli, liste con `Form`/`List` in stile
|
||||
Impostazioni) piuttosto che controlli custom pesanti.
|
||||
- La sezione "grafica" (visualizzazione carina) può oggi mostrare solo dati
|
||||
già disponibili (EQ come curva, o un'animazione leggera legata allo stato
|
||||
sorgente/tono) — non agganciarla a VU-meter reali finché non sono pronti
|
||||
(punto 3).
|
||||
- Dato che non esiste più il mix simultaneo radio+BT, il cambio sorgente è
|
||||
un'azione "netta" (come cambiare stazione) — vale la pena un feedback visivo
|
||||
chiaro (es. breve transizione/fade nell'interfaccia, non nell'audio: il
|
||||
cambio DSP è istantaneo) quando l'utente lo seleziona.
|
||||
@@ -287,3 +287,61 @@ communication channel to a chip --- either the classic USBi/ICP dongle, or
|
||||
DigiRadio's own TCP:8086 SigmaStudio bridge (Section~\ref{sec:adau1701-sigmastudio-tcp})
|
||||
when connecting live to a running board.
|
||||
\end{drnote}
|
||||
|
||||
\section{Next revision: DigiRadioFinale}
|
||||
\label{sec:ss-digiradiofinale}
|
||||
|
||||
\begin{drcaution}[Not yet integrated into firmware]
|
||||
This section documents a SigmaStudio export (\texttt{DigiRadioFinale}) captured
|
||||
2026-08-25 that is not yet the program the firmware replays at boot. It expands
|
||||
the parameter RAM from 74 to 224 words with several new dedicated blocks,
|
||||
replacing two of the EQ-overlay workarounds in
|
||||
Section~\ref{sec:ss-enhancements} with real ADI algorithm modules. Driver,
|
||||
safeload API, and this manual's runtime tables will be updated once the
|
||||
program is finalised.
|
||||
\end{drcaution}
|
||||
|
||||
\begin{figure}[htbp]
|
||||
\centering
|
||||
\includegraphics[width=\linewidth]{sigmastudiofinale.png}
|
||||
\caption{DigiRadioFinale signal chain: per-channel DC blockers and RMS
|
||||
compressor, four input-side level meters, the 6-leg Param EQ, the
|
||||
SuperPhat spatializer, an unconfigured general filter, master volume,
|
||||
the Dynamic Bass Boost algorithm, two output-side level meters, and the
|
||||
L/R limiters.}
|
||||
\label{fig:ss-digiradiofinale}
|
||||
\end{figure}
|
||||
|
||||
\begin{table}[htbp]
|
||||
\centering
|
||||
\small
|
||||
\begin{tabular}{@{}L{2.6cm}L{2.2cm}L{7.6cm}@{}}
|
||||
\drhead Addresses & Block & Role \\
|
||||
\midrule
|
||||
0--2 & Beep1 & test tone (unchanged) \\
|
||||
3 & DC1 & input trim \\
|
||||
4--7 & DCB1--4 & DC blocker, one per channel \\
|
||||
8 & S Splitter1 & control fan-out (unchanged) \\
|
||||
9--46 & Compressor1 & RMS compander, 34-point curve \\
|
||||
47--58 & 1×RTA3,4,1,2 & 4 input-side level meters (readback) \\
|
||||
59--88 & Param EQ1 & 6 stereo legs (ST0--ST5) $\times$ 5 coefficients \\
|
||||
89--140 & SPhat1 & SuperPhat spatializer (dedicated algorithm,
|
||||
replaces the stereo-enhance EQ overlay) \\
|
||||
141--145& Gen Filter1 & general 2nd-order filter, currently flat/bypassed
|
||||
--- reserved, not yet configured (candidate slot
|
||||
for Voice Clarifier) \\
|
||||
146--147& Multiple1 & master volume L/R (unchanged) \\
|
||||
148--187& Bass Boost1 & Dynamic Bass Boost algorithm (dedicated,
|
||||
replaces the bass-enhance EQ overlay) \\
|
||||
188--193& 1×RTA2\_2,1\_2 & 2 output-side level meters (readback) \\
|
||||
194--223& Limiter2, Limiter1 & unchanged \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\caption{DigiRadioFinale parameter RAM map, by address.}
|
||||
\label{tab:ss-digiradiofinale-map}
|
||||
\end{table}
|
||||
|
||||
No dedicated mute cell exists yet in this export, and Gen Filter1 (the
|
||||
Voice Clarifier candidate) is still an identity filter (b0=1, all other
|
||||
coefficients zero). Both are pending further SigmaStudio work before this
|
||||
program replaces the one described earlier in this chapter.
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 192 KiB |
Reference in New Issue
Block a user