Files
DigiRadio/Software/components/core/src/RdsMetadataAccumulator.cpp
T
micheleandCursor 0fc714e431 Add preset polish and broadcast metadata (fw 0.8.0).
Ship station reorder, DAB playing ids in presets, RDS PS/RT and DAB DLS in tuner status, Si4684 data-service read, host tests, and UI now-playing lines.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-07 00:01:49 +02:00

101 lines
2.8 KiB
C++

/**
* @file RdsMetadataAccumulator.cpp
* @brief RdsMetadataAccumulator implementation.
*
* DigiRadio firmware — https://github.com/manvalan/DigiRadio
*
* Copyright 2026 Michele Bigi
* SPDX-License-Identifier: Apache-2.0
*
* @author Michele Bigi
* @date 2026-07-06
*/
#include "core/RdsMetadataAccumulator.hpp"
namespace core {
void RdsMetadataAccumulator::reset() noexcept
{
psBuffer_.fill('\0');
psSegmentValid_.fill(false);
rtBuffer_.fill('\0');
rtSegmentValid_.fill(false);
rtAbFlag_ = false;
rtAbInitialized_ = false;
}
void RdsMetadataAccumulator::applyGroup(std::uint16_t blockA,
std::uint16_t blockB,
std::uint16_t blockC,
std::uint16_t blockD) noexcept
{
(void)blockA;
const std::uint8_t groupType =
static_cast<std::uint8_t>((blockB >> 12U) & 0x0FU);
if (groupType == 0U) {
const std::size_t index =
static_cast<std::size_t>((blockB >> 1U) & 0x03U);
if (index < kPsSegments) {
psBuffer_[index * 2U] =
static_cast<char>((blockC >> 8U) & 0xFFU);
psBuffer_[index * 2U + 1U] = static_cast<char>(blockC & 0xFFU);
psSegmentValid_[index] = true;
}
return;
}
if (groupType == 2U) {
const bool abFlag = (blockB & 0x10U) != 0U;
if (!rtAbInitialized_ || abFlag != rtAbFlag_) {
rtBuffer_.fill('\0');
rtSegmentValid_.fill(false);
rtAbFlag_ = abFlag;
rtAbInitialized_ = true;
}
const std::size_t index =
static_cast<std::size_t>(blockB & 0x0FU);
if (index < kRtSegments) {
rtBuffer_[index * 4U] =
static_cast<char>((blockC >> 8U) & 0xFFU);
rtBuffer_[index * 4U + 1U] =
static_cast<char>(blockC & 0xFFU);
rtBuffer_[index * 4U + 2U] =
static_cast<char>((blockD >> 8U) & 0xFFU);
rtBuffer_[index * 4U + 3U] =
static_cast<char>(blockD & 0xFFU);
rtSegmentValid_[index] = true;
}
}
}
std::optional<BroadcastLabel> RdsMetadataAccumulator::programName() const
{
for (bool valid : psSegmentValid_) {
if (!valid) {
return std::nullopt;
}
}
return BroadcastLabel::tryFromChipBytes(
std::string_view(psBuffer_.data(), psBuffer_.size()));
}
std::optional<BroadcastLabel> RdsMetadataAccumulator::radiotext() const
{
bool any = false;
for (bool valid : rtSegmentValid_) {
if (valid) {
any = true;
break;
}
}
if (!any) {
return std::nullopt;
}
return BroadcastLabel::tryFromChipBytes(
std::string_view(rtBuffer_.data(), rtBuffer_.size()));
}
} // namespace core