Fix Si4684 response-parsing offset bug: RDS, DAB acquired/event status
readFmRds(), readDabDigRadStatus()'s acquired field, and readDabEventStatus() all read raw[4] expecting AN649's RESP4 field, but this driver's own established convention (getPartInfo(), and the already-correct ficQuality/cnrDb fields in readDabDigRadStatus() itself) is raw[5]=RESP4 (raw[0]=SPI lead-in, raw[1..4]=STATUS0-3). This is why DAB_GET_EVENT_STATUS's serviceListReady never set — it was reading STATUS3's ERRNR bit instead of RESP4's SVRLISTINT bit, so /api/tuner/services returned service_list_empty forever regardless of lock quality. Fixed all four sites; readFmRds()'s fifoUsed/blockA-D were consequently also off by one and fixed together with it. Confirmed live: first DAB ensemble locks in this project's history (3 found sweeping freq_index 0-35, fic_quality=100, best CNR 20 dB on index 23), and /api/tuner/services now returns real entries instead of service_list_empty. The service-list entry contents themselves are still garbled (a third, separate bug in fetchDabServiceList()'s body parsing, documented but not fixed this session — see docs/si4684-rf-investigation-report.md). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0178rASQ6ZETPMUamvpoR2KR
This commit is contained in:
@@ -931,13 +931,16 @@ std::expected<Si4684FmRdsStatus, Si4684Error> 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user