diff --git a/Software/components/drivers/si4684/src/Si4684Driver.cpp b/Software/components/drivers/si4684/src/Si4684Driver.cpp index acafbe4..c00e2bc 100644 --- a/Software/components/drivers/si4684/src/Si4684Driver.cpp +++ b/Software/components/drivers/si4684/src/Si4684Driver.cpp @@ -931,13 +931,16 @@ std::expected Si4684Driver::readFmRds() return std::unexpected(rd.error()); } + // raw[0]=lead-in, raw[1..4]=STATUS0-3, raw[5]=RESP4 (established + // convention, see getPartInfo()/readDabDigRadStatus() comments) — every + // offset below is RESP-number relative to that, not raw[4]. Si4684FmRdsStatus rds = {}; - rds.received = (raw[4] & 0x01U) != 0U; - rds.fifoUsed = raw[10]; - rds.blockA = readLe16(raw.data() + 12U); - rds.blockB = readLe16(raw.data() + 14U); - rds.blockC = readLe16(raw.data() + 16U); - rds.blockD = readLe16(raw.data() + 18U); + rds.received = (raw[5] & 0x01U) != 0U; + rds.fifoUsed = raw[11]; + rds.blockA = readLe16(raw.data() + 13U); + rds.blockB = readLe16(raw.data() + 15U); + rds.blockC = readLe16(raw.data() + 17U); + rds.blockD = readLe16(raw.data() + 19U); return rds; } @@ -1063,7 +1066,8 @@ Si4684Driver::readDabDigRadStatus() Si4684DabDigRadStatus status = {}; status.ficQuality = raw[9]; status.cnrDb = raw[10]; - status.acquired = (raw[4] & 0x08U) != 0U; + // raw[5]=RESP4 (see readFmRds()); ACQINT is RESP4 bit3. + status.acquired = (raw[5] & 0x08U) != 0U; status.valid = status.ficQuality > 0U; return status; } @@ -1085,9 +1089,10 @@ Si4684Driver::readDabEventStatus() return std::unexpected(rd.error()); } + // raw[5]=RESP4 (see readFmRds()); SVRLISTINT is RESP4 bit0. Si4684DabEventStatus events = {}; - events.serviceListReady = (raw[4] & 0x01U) != 0U; - events.reconfig = (raw[4] & 0x02U) != 0U; + events.serviceListReady = (raw[5] & 0x01U) != 0U; + events.reconfig = (raw[5] & 0x02U) != 0U; return events; } diff --git a/Software/docs/si4684-rf-investigation-report.md b/Software/docs/si4684-rf-investigation-report.md index 8b6743f..6f169bd 100644 --- a/Software/docs/si4684-rf-investigation-report.md +++ b/Software/docs/si4684-rf-investigation-report.md @@ -565,6 +565,42 @@ BT1035 → Bluetooth speaker) in this project's history. Remaining noise on top of the music is attributed to antenna quality, not yet independently confirmed with a proper antenna — flagged as follow-up, not closed. +## 2026-08-16 update: DAB lock confirmed on 3 ensembles + response-offset bug + +With the tune fix in place, a full sweep of freq_index 0-35 found three real +ensemble locks (fic_quality=100 on all three): index 5 (CNR 7 dB), index 22 +(CNR 15 dB), index 23 (CNR 20 dB, strongest). First confirmed DAB lock in +this project's history. + +Chasing why `/api/tuner/services` returned `service_list_empty` even after +30+ seconds on a solid lock found a second bug class, this time in +**response parsing, not command construction**: `readFmRds()`, +`readDabDigRadStatus()`'s `acquired` field, and `readDabEventStatus()` all +read `raw[4]` expecting AN649's "RESP4" field, but this driver's own +established convention elsewhere (`getPartInfo()`, and the already-correct +`ficQuality`/`cnrDb` fields in `readDabDigRadStatus()`) is `raw[5]=RESP4` +(`raw[0]`=SPI lead-in, `raw[1..4]`=STATUS0-3). Fixed all four call sites to +the correct offset; `readFmRds()`'s `fifoUsed`/`blockA-D` fields were +consequently also all off by one and fixed together with it. + +After the fix, `serviceListReady` now correctly gates open and +`/api/tuner/services` returns real data instead of `service_list_empty` — +but the entries themselves are still garbled (implausible `service_id` +values, `component_id` fields that decode as ASCII spaces, e.g. +`538976288 = 0x20202020`, mostly-empty labels). This points to a **third, +separate bug** in `fetchDabServiceList()`'s service-list *body* parsing +(the entry structure walked in the loop over `serviceCount`), not yet +investigated — the DAB service list binary format is documented in AN649 +§7 "Digital Services User's Guide" (starts around page 418), not the +command tables checked so far. Confirmed live: `POST /api/tuner/play` with +one of these garbled IDs accepted (`{"status":"playing"}`) but produced no +audio, consistent with a wrong service/component ID rather than a new +audio-path regression. + +**Follow-up, not done this session**: fix `fetchDabServiceList()` entry +parsing against AN649 §7; then confirm actual DAB audio playback end to +end the same way FM was confirmed. + **Unrelated finding from the same session, logged for completeness**: BT1035 began failing boot deterministically (`no spontaneous UART bytes after hardware reset`, then `AT init failed`) starting from this session, on both