Release fw 0.8.4: doc sync, System UI, BT/FM polish.

Align README, manual, and backlog to 0.8.4; add Web UI System tab for OTA/DSP uploads, serial in health header, FM seek down, and BT1035 paired list plus auto-reconnect API.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-07 09:56:44 +02:00
co-authored by Cursor
parent b9ed8a2dcd
commit 176cdd9319
28 changed files with 988 additions and 66 deletions
@@ -341,6 +341,24 @@ public:
std::uint32_t componentId,
Si4684DigitalServiceType type = Si4684DigitalServiceType::Audio);
/**
* @brief stopDabService — stop active DAB audio (STOP_DIGITAL_SERVICE).
*
* @dname stopDabService
* @param serviceId Selected service identifier.
* @param componentId Audio component within the service.
* @param type Digital service type (audio by default).
* @return Ok on success, or Si4684Error.
* @pubstate sends STOP_DIGITAL_SERVICE (AN649 opcode 0x82).
*
* @author Michele Bigi
* @date 2026-07-07
*/
[[nodiscard]] std::expected<void, Si4684Error> stopDabService(
std::uint32_t serviceId,
std::uint32_t componentId,
Si4684DigitalServiceType type = Si4684DigitalServiceType::Audio);
private:
enum class Command : std::uint8_t {
PowerUp = 0x01,
@@ -357,6 +375,7 @@ private:
FmRdsStatus = 0x34,
GetDigitalServiceList = 0x80,
StartDigitalService = 0x81,
StopDigitalService = 0x82,
GetDigitalServiceData = 0x84,
DabTuneFreq = 0xB0,
DabDigRadStatus = 0xB2,
@@ -829,4 +829,33 @@ std::expected<void, Si4684Error> Si4684Driver::startDabService(
return {};
}
std::expected<void, Si4684Error> Si4684Driver::stopDabService(
std::uint32_t serviceId,
std::uint32_t componentId,
Si4684DigitalServiceType type)
{
if (auto band = ensureBand(Si4684Band::Dab); !band) {
return band;
}
const std::uint8_t args[] = {
static_cast<std::uint8_t>(type),
0x00U,
0x00U,
static_cast<std::uint8_t>(serviceId & 0xFFU),
static_cast<std::uint8_t>((serviceId >> 8) & 0xFFU),
static_cast<std::uint8_t>((serviceId >> 16) & 0xFFU),
static_cast<std::uint8_t>(serviceId >> 24),
static_cast<std::uint8_t>(componentId & 0xFFU),
static_cast<std::uint8_t>((componentId >> 8) & 0xFFU),
static_cast<std::uint8_t>((componentId >> 16) & 0xFFU),
static_cast<std::uint8_t>(componentId >> 24),
};
if (auto cmd =
writeCommand(Command::StopDigitalService, args, sizeof(args));
!cmd) {
return std::unexpected(Si4684Error::CommandFailed);
}
return {};
}
} // namespace si4684
@@ -153,6 +153,14 @@ std::expected<void, core::TunerError> Si4684Tuner::tuneDab(
std::expected<void, core::TunerError> Si4684Tuner::tuneFm(
core::FrequencyKHz frequency)
{
if (driver_.loadedBand() == Si4684Band::Dab && lastDabServiceId_
&& lastDabComponentId_) {
(void)driver_.stopDabService(*lastDabServiceId_, *lastDabComponentId_);
lastDabServiceId_.reset();
lastDabComponentId_.reset();
dabDynamicLabel_.reset();
}
if (auto result = driver_.tuneFm(frequency); !result) {
return std::unexpected(mapError(result.error()));
}