Si4684 RF investigation report; fix ADAU1701 I2C reliability under long safeload bursts

- Add docs/si4684-rf-investigation-report.md: full record of the FM/DAB no-lock
  investigation (crystal, front-end matching, ANTCAP sweep, continuity, leading
  EP solder-defect hypothesis, PCBWay report sent) plus the separate audio
  profile NVS bug found and partially fixed this session.
- Fix sigma_i2c_write() (SigmaStudioFW.c): no retry on I2C failure meant a single
  transient NACK anywhere in a long safeload burst (EQ apply = ~55 sequential
  transactions) aborted the whole sequence. Added a 3-attempt retry.
- Add granular failure logging (AudioService::applyProfileToDsp/persistProfile,
  Adau1701Driver::applyMixer/applyEq, NvsAudioProfileStore::saveProfile error
  codes) to isolate the remaining NVS-side audio profile save failure.
- Si4684Driver::tuneFm gains an optional ANTCAP argument (default 0 = unchanged
  auto-tune behavior) used during this session's front-end matching sweep.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-13 22:21:04 +02:00
co-authored by Claude Sonnet 5
parent 6f7b6dd12c
commit bee8cfa86f
7 changed files with 193 additions and 13 deletions
@@ -15,6 +15,7 @@
#include "core/AudioProfileJson.hpp"
#include "esp_log.h"
#include "nvs.h"
#include <string>
@@ -23,6 +24,7 @@
namespace secure_store {
namespace {
constexpr char kTag[] = "NvsAudioProfileStore";
constexpr char kNamespace[] = "digiradio";
constexpr char kProfileKey[] = "audio_profile_json";
} // namespace
@@ -46,13 +48,23 @@ std::expected<void, core::StoreError> NvsAudioProfileStore::saveProfile(
const std::string json = core::serializeAudioProfileJson(profile);
nvs_handle_t handle = 0;
if (nvs_open(kNamespace, NVS_READWRITE, &handle) != ESP_OK) {
esp_err_t openErr = nvs_open(kNamespace, NVS_READWRITE, &handle);
if (openErr != ESP_OK) {
ESP_LOGW(kTag, "nvs_open failed (0x%x)", static_cast<unsigned>(openErr));
return std::unexpected(core::StoreError::IoFailed);
}
esp_err_t err = nvs_set_str(handle, kProfileKey, json.c_str());
if (err == ESP_OK) {
if (err != ESP_OK) {
ESP_LOGW(kTag, "nvs_set_str failed (0x%x) json_len=%u",
static_cast<unsigned>(err),
static_cast<unsigned>(json.size()));
} else {
err = nvs_commit(handle);
if (err != ESP_OK) {
ESP_LOGW(kTag, "nvs_commit failed (0x%x)",
static_cast<unsigned>(err));
}
}
nvs_close(handle);