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());
|
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 = {};
|
Si4684FmRdsStatus rds = {};
|
||||||
rds.received = (raw[4] & 0x01U) != 0U;
|
rds.received = (raw[5] & 0x01U) != 0U;
|
||||||
rds.fifoUsed = raw[10];
|
rds.fifoUsed = raw[11];
|
||||||
rds.blockA = readLe16(raw.data() + 12U);
|
rds.blockA = readLe16(raw.data() + 13U);
|
||||||
rds.blockB = readLe16(raw.data() + 14U);
|
rds.blockB = readLe16(raw.data() + 15U);
|
||||||
rds.blockC = readLe16(raw.data() + 16U);
|
rds.blockC = readLe16(raw.data() + 17U);
|
||||||
rds.blockD = readLe16(raw.data() + 18U);
|
rds.blockD = readLe16(raw.data() + 19U);
|
||||||
return rds;
|
return rds;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1063,7 +1066,8 @@ Si4684Driver::readDabDigRadStatus()
|
|||||||
Si4684DabDigRadStatus status = {};
|
Si4684DabDigRadStatus status = {};
|
||||||
status.ficQuality = raw[9];
|
status.ficQuality = raw[9];
|
||||||
status.cnrDb = raw[10];
|
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;
|
status.valid = status.ficQuality > 0U;
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@@ -1085,9 +1089,10 @@ Si4684Driver::readDabEventStatus()
|
|||||||
return std::unexpected(rd.error());
|
return std::unexpected(rd.error());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// raw[5]=RESP4 (see readFmRds()); SVRLISTINT is RESP4 bit0.
|
||||||
Si4684DabEventStatus events = {};
|
Si4684DabEventStatus events = {};
|
||||||
events.serviceListReady = (raw[4] & 0x01U) != 0U;
|
events.serviceListReady = (raw[5] & 0x01U) != 0U;
|
||||||
events.reconfig = (raw[4] & 0x02U) != 0U;
|
events.reconfig = (raw[5] & 0x02U) != 0U;
|
||||||
return events;
|
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
|
top of the music is attributed to antenna quality, not yet independently
|
||||||
confirmed with a proper antenna — flagged as follow-up, not closed.
|
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
|
**Unrelated finding from the same session, logged for completeness**: BT1035
|
||||||
began failing boot deterministically (`no spontaneous UART bytes after
|
began failing boot deterministically (`no spontaneous UART bytes after
|
||||||
hardware reset`, then `AT init failed`) starting from this session, on both
|
hardware reset`, then `AT init failed`) starting from this session, on both
|
||||||
|
|||||||
Reference in New Issue
Block a user