Fix FM RDS: station name/RadioText never decoded, three stacked bugs
GET /api/tuner/status and the full FM band scan always returned an
empty station_name, on every frequency, regardless of signal quality
-- confirmed live on multiple >35 dB SNR channels before this fix.
Three independent problems, found by reading the Si4684 datasheet
(AN649 Rev.2.0) instead of guessing further:
1. FM_RDS_CONFIG (property 0x3C02) was enabled (RDSEN=1) but with both
block-error thresholds at 0 ("no block errors"), so almost any
real-world RDS group -- routine with ordinary multipath/noise, even
on a strong signal -- got rejected from the FIFO outright. Raised
to the datasheet's most tolerant recommended setting (2, "3-5 bit
errors detected and corrected").
2. FM_RDS_INTERRUPT_FIFO_COUNT (property 0x3C01) was never set at all,
defaulting to 0 -- which the datasheet states disables RDSFIFOINT
permanently. Si4684Driver::readFmRds()'s "received" flag reads
exactly that bit (FM_RDS_STATUS RESP4 bit 0), so it could never be
true, and Si4684Tuner::refreshStatus()'s RDS poll loop broke out on
its first iteration every single time, before ever touching the
accumulator. Set to 1 (fire as soon as one group is queued).
3. The real bug, once groups actually started arriving:
RdsMetadataAccumulator::applyGroup() read the two Program Service
name characters from Block C and computed the segment index as
(blockB >> 1) & 0x3. Per ETSI EN 62106 §3.1.5, PS characters for
group type 0 (both 0A and 0B) are always in Block D -- Block C
holds alternate-frequency codes (0A) or a repeated PI code (0B),
never text -- and the segment address is blockB bits[1:0] with no
shift. This function had no dedicated test before now, which is
how a wrong block/bit pair could ship unnoticed: the old test
fixture encoded the same bug in its "expected" input.
Confirmed live after all three fixes: station_name and radiotext both
populate with stable, plausible content across repeated reads (not
noise) on a real broadcast signal.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -35,12 +35,15 @@ void RdsMetadataAccumulator::applyGroup(std::uint16_t blockA,
|
||||
static_cast<std::uint8_t>((blockB >> 12U) & 0x0FU);
|
||||
|
||||
if (groupType == 0U) {
|
||||
const std::size_t index =
|
||||
static_cast<std::size_t>((blockB >> 1U) & 0x03U);
|
||||
// Group type 0 (both 0A and 0B): the two Program Service name
|
||||
// characters are always in Block D. Block C differs by version --
|
||||
// 0A carries alternate-frequency codes, 0B repeats the PI code --
|
||||
// but never PS text either way (ETSI EN 62106 §3.1.5).
|
||||
const std::size_t index = static_cast<std::size_t>(blockB & 0x03U);
|
||||
if (index < kPsSegments) {
|
||||
psBuffer_[index * 2U] =
|
||||
static_cast<char>((blockC >> 8U) & 0xFFU);
|
||||
psBuffer_[index * 2U + 1U] = static_cast<char>(blockC & 0xFFU);
|
||||
static_cast<char>((blockD >> 8U) & 0xFFU);
|
||||
psBuffer_[index * 2U + 1U] = static_cast<char>(blockD & 0xFFU);
|
||||
psSegmentValid_[index] = true;
|
||||
}
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user