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
@@ -241,12 +241,14 @@ namespace adau1701
mixer.si4684Right);
!result)
{
ESP_LOGW(kTag, "applyMixer: si4684 input safeload failed");
return result;
}
if (auto result = setInputVolume(core::MixSource::Esp32, mixer.esp32Left,
mixer.esp32Right);
!result)
{
ESP_LOGW(kTag, "applyMixer: esp32 input safeload failed");
return result;
}
if (auto result =
@@ -254,10 +256,17 @@ namespace adau1701
mixer.mixLeft);
!result)
{
ESP_LOGW(kTag, "applyMixer: st0 safeload failed");
return result;
}
return safeloadGain(static_cast<unsigned>(ADDR_STMIXER1_ST1_VOLUME),
mixer.mixRight);
if (auto result = safeloadGain(
static_cast<unsigned>(ADDR_STMIXER1_ST1_VOLUME), mixer.mixRight);
!result)
{
ESP_LOGW(kTag, "applyMixer: st1 safeload failed");
return result;
}
return {};
}
std::expected<void, Adau1701Error> Adau1701Driver::setEqBand(
@@ -344,6 +353,8 @@ namespace adau1701
if (auto result = setEqBand(*index, band.gain, band.center, band.q);
!result)
{
ESP_LOGW(kTag, "applyEq: band %u safeload failed",
static_cast<unsigned>(i));
return result;
}
}
@@ -16,6 +16,7 @@
#include "driver/i2c_master.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "freertos/task.h"
#include <string.h>
@@ -135,9 +136,22 @@ static int sigma_i2c_write(unsigned int reg, const unsigned char* data,
buf[0] = (unsigned char)((reg >> 8) & 0xFFU);
buf[1] = (unsigned char)(reg & 0xFFU);
memcpy(buf + 2U, data, length);
const esp_err_t err =
i2c_master_transmit(s_dev, buf, (size_t)(2U + length), 1000);
return err == ESP_OK ? 0 : -1;
// Long safeload sequences (e.g. one EQ band = 5 params x 2 writes +
// trigger) chain dozens of back-to-back transactions; a single
// transient NACK anywhere in that chain used to abort the whole
// sequence. Retry a few times before giving up -- cheap and matches
// how every other bus driver in this codebase tolerates bus noise.
static const int kMaxAttempts = 3;
esp_err_t err = ESP_FAIL;
for (int attempt = 0; attempt < kMaxAttempts; ++attempt) {
err = i2c_master_transmit(s_dev, buf, (size_t)(2U + length), 1000);
if (err == ESP_OK) {
return 0;
}
vTaskDelay(pdMS_TO_TICKS(2));
}
return -1;
}
/*