Persist Si4684 crystal calibration (ibias/ctun/xtalFreqHz) to EEPROM
Extends the existing FM/DAB ANTCAP EEPROM persistence pattern
(Eeprom24aa::writeFmAntCap/writeDabAntCap) to the crystal trim found by
POST /api/tuner/xtal-calibrate, which previously only applied live and
was lost on every reboot.
- Eeprom24aa gains readXtalCalibration()/writeXtalCalibration() at word
addresses 0x02 (ibias), 0x03 (ctun), 0x04-0x07 (xtalFreqHz,
big-endian), right after the existing FM/DAB ANTCAP bytes.
- HardwareBootstrap::boot() now boots ADAU1701 before Si4684 (needed so
the EEPROM read, which borrows ADAU1701's I2C bus, can happen before
Si4684's boot() call, which takes the crystal trim as an argument),
loads the saved trim if present, and falls back to the compiled-in
defaults (ibias=72, ctun=0, xtalFreqHz=19199750) otherwise.
- POST /api/tuner/xtal-calibrate now persists every successful live
recalibration automatically ("persisted":true/false in the response)
via a new saveXtalCalibration()/net::AntennaCalibration::saveXtal
bridge, mirroring the ANTCAP save pattern.
Verified live: boot log confirms "Xtal not calibrated" before the first
save, "Xtal calibration loaded: ibias=72 ctun=0 xtal_freq_hz=19199750"
after, surviving a reboot; DAB/FM tuning unaffected (DAB CNR 17-19dB,
locked).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
# Note per l'app companion (igiRadio) — sync 2026-08-24
|
||||
|
||||
Riepilogo dei cambi firmware di oggi rilevanti per l'app iOS. Incollare in Cursor come contesto.
|
||||
|
||||
## 1. Nuovo endpoint: codec A2DP Bluetooth
|
||||
|
||||
```
|
||||
GET /api/bluetooth/a2dp-codec
|
||||
POST /api/bluetooth/a2dp-codec body: {"codec_mask": <0-63>}
|
||||
```
|
||||
|
||||
- `GET` risponde `{"codec":"sbc"}` (valori possibili: `sbc`, `aptx`, `aptx-hd`, `aptx-ll`, `aptx-adaptive`; se il modulo BT1035 negozia AAC la risposta può non essere interpretabile — il datasheet Feasycom non documenta un codice di ritorno per AAC, quindi in quel caso l'app deve gestire un valore/errore sconosciuto senza andare in crash).
|
||||
- `POST` con `codec_mask` è una bitmask: `BIT0`=AAC, `BIT1`=aptX, `BIT2`=aptX-LL, `BIT3`=aptX-HD, `BIT4`=aptX-Adaptive, `BIT5`=LDAC. `0` forza solo SBC (baseline obbligatorio). Risposta `{"status":"saved"}` o `{"status":"error","reason":"..."}`.
|
||||
- **Importante**: il cambio vale solo per la prossima negoziazione — se un dispositivo Bluetooth è già connesso, serve chiamare `POST /api/bluetooth/disconnect` e far riconnettere il device (dal lato telefono/speaker) perché il nuovo codec venga effettivamente usato. Se l'app espone questa funzione in UI, considerare di mostrare un messaggio tipo "riconnetti il dispositivo Bluetooth per applicare".
|
||||
|
||||
## 2. Fix: salvataggio profilo audio (EQ/mixer) ora persiste davvero
|
||||
|
||||
Prima di oggi, `PUT /api/audio/profile` applicava le modifiche dal vivo ma **falliva sempre** silenziosamente nel salvataggio permanente (bug: nome chiave NVS troppo lungo). L'app probabilmente vedeva errori intermittenti o impostazioni che sparivano al riavvio della scheda. Ora è risolto e verificato: le modifiche sopravvivono a un riavvio. Nessun cambio di formato richiesto lato app — stesso schema JSON di sempre.
|
||||
|
||||
## 3. Fix: il parser JSON del firmware ora tollera JSON non-compatto
|
||||
|
||||
Prima di oggi il parser lato firmware richiedeva JSON strettamente compatto (`{"key":"value"}`, **nessuno spazio** dopo i due punti) — un `JSONEncoder` Swift in modalità non-compatta (es. con `.prettyPrinted`, o formattazione di default in alcune configurazioni) poteva produrre `"key": "value"` e far fallire il parsing lato server con `invalid_json` o `missing_field`.
|
||||
|
||||
Questo è ora risolto per tutti gli endpoint (tuner, audio profile, stazioni, bluetooth, wifi, streaming, DSP param). **Se nell'app c'era un workaround per forzare JSON compatto** (es. `JSONEncoder().outputFormatting` impostato esplicitamente senza spazi, o costruzione manuale di stringhe JSON), non è più necessario ma può restare — è comunque compatibile.
|
||||
|
||||
## 4. Nomi campi corretti (promemoria, riscontrati oggi durante i test manuali)
|
||||
|
||||
Attenzione a questi nomi campo esatti attesi dal firmware — un nome sbagliato produce `missing_field`, non necessariamente un errore chiaro:
|
||||
|
||||
- `POST /api/tuner/tune` per DAB: `{"band":"dab","freq_index":<0-37>}` — **non** `"frequency"`.
|
||||
- `POST /api/tuner/tune` per FM: `{"band":"fm","frequency_khz":<khz>}`.
|
||||
- `POST /api/stations` per una stazione FM: `{"name":"...","band":"fm","fm_frequency_khz":<khz>}` — **non** `"frequency_khz"` a livello radice.
|
||||
- `POST /api/stations` per una stazione DAB: `{"name":"...","band":"dab","dab_freq_index":<0-37>}` (opzionali `dab_service_id`, `dab_component_id`).
|
||||
- `POST /api/stations/remove`: `{"index":<n>}` — **non** `{"name":"..."}`.
|
||||
|
||||
Se l'app usa nomi diversi da questi in qualche punto, verificare contro `components/core/src/StationListJson.cpp` e `components/core/src/TunerJson.cpp` nel repo firmware (fonte di verità).
|
||||
|
||||
## 5. Nessun cambio di schema per mixer/EQ
|
||||
|
||||
Lo schema di `GET|PUT /api/audio/profile` è invariato:
|
||||
|
||||
```json
|
||||
{
|
||||
"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": 0, "right_db": 0},
|
||||
"eq": [
|
||||
{"gain_db": 0, "center_hz": 20, "q": 1.414},
|
||||
{"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}
|
||||
}
|
||||
```
|
||||
|
||||
Nota: `esp32_left_db`/`esp32_right_db`/`mix_right_db` a `-96` = leg ESP32 (streaming web radio) mutato, `si4684_*`/`mix_left_db` a `0` = leg radio (FM/DAB) aperto — è il default "radio-first" di fabbrica. Se l'app vuole passare a streaming web-radio senza sentire anche la radio in sovrapposizione, deve invertire questi gain (radio a `-96`, esp32 a `0`) — non è automatico solo abilitando `POST /api/streaming`.
|
||||
|
||||
## 6. Bug noto, non ancora risolto
|
||||
|
||||
- `PUT /api/audio/profile` con `enhancements` (stereo/bass) diverso da zero **sovrascrive** eventuali modifiche manuali dell'EQ — bug già tracciato, non toccato oggi.
|
||||
- La banda EQ indice 0 (20 Hz) è in realtà un filtro passa-alto fisso non modificabile dal DSP — il valore `gain_db` mostrato/inviato per quella banda è cosmetico, non ha effetto reale sul suono.
|
||||
Reference in New Issue
Block a user