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:
2026-08-16 01:24:54 +02:00
co-authored by Claude Sonnet 5
parent 6974095f35
commit 9b337e7bca
2 changed files with 50 additions and 9 deletions
@@ -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;
}