Add now-playing view with metadata polling, six-band EQ controls, full REST coverage, companion-chip badges, and gzip-www helper for the embedded setup page. Co-authored-by: Cursor <cursoragent@cursor.com>
466 lines
18 KiB
TeX
466 lines
18 KiB
TeX
% ============================================================
|
|
% DigiRadio — Manual chapter: ADAU1701 DSP
|
|
% ============================================================
|
|
|
|
\chapter{ADAU1701 Audio DSP}
|
|
\label{ch:adau1701}
|
|
|
|
The Analog Devices ADAU1701 is the central audio processor of DigiRadio: it
|
|
mixes the Si4684 radio stream with the ESP32 I\textsuperscript{2}S source,
|
|
applies parametric equalisation and master volume, and feeds the
|
|
FSC-BT1035 over I\textsuperscript{2}S. This chapter documents how the
|
|
SigmaStudio program is stored and replayed at boot, how
|
|
\texttt{adau1701::Adau1701Driver} controls the chip over I\textsuperscript{2}C,
|
|
and how application code (\texttt{audio::AudioService}, HTTP, web UI) uses the
|
|
driver without touching parameter RAM addresses directly.
|
|
|
|
\begin{drref}[Companion chapter]
|
|
The SigmaStudio \emph{design} --- hardware settings, signal chain, EQ bands,
|
|
and export procedure --- is documented in Chapter~\ref{ch:sigmastudio}. This
|
|
chapter covers the \emph{firmware side}: boot, safeload, driver API, domain
|
|
types, persistence, and HTTP integration.
|
|
\end{drref}
|
|
|
|
\section{Role in the audio chain}
|
|
\label{sec:adau1701-role}
|
|
|
|
After boot the ADAU1701 runs as the I\textsuperscript{2}S \textbf{master}
|
|
at 48\,kHz, 24-bit stereo. It receives PCM from the Si4684 on serial input~0
|
|
and from the ESP32 on serial input~1, mixes and equalises the result, and
|
|
outputs to the Bluetooth module on \texttt{SDATA\_OUT0}. The ESP32 never
|
|
processes audio samples in software; all tone shaping and mixing happen inside
|
|
the DSP program exported from SigmaStudio.
|
|
|
|
Every runtime adjustment --- input level, EQ band, master volume, stereo/bass
|
|
enhancement --- flows through typed domain objects in \texttt{components/core}
|
|
and reaches the hardware only via \texttt{Adau1701Driver} safeload writes.
|
|
Board wiring and I\textsuperscript{2}C address are in
|
|
Section~\ref{sec:hw-adau} (Chapter~\ref{ch:hardware}).
|
|
|
|
\section{Program image (SigmaStudio export)}
|
|
\label{sec:adau1701-firmware}
|
|
|
|
Unlike the Si4684 blobs (local-only, not in git), the ADAU1701 export is
|
|
\textbf{committed} under \texttt{Firmware/ADAU1701-Firmware/}. It is the
|
|
authoritative DSP program for firmware builds.
|
|
|
|
\begin{table}[htbp]
|
|
\centering
|
|
\begin{tabular}{@{}llp{6.5cm}@{}}
|
|
\toprule
|
|
\textbf{File} & \textbf{Role} & \textbf{Used by firmware} \\
|
|
\midrule
|
|
\texttt{DigiRadio\_IC\_1.h} &
|
|
Program + parameter RAM init data &
|
|
\texttt{default\_download\_IC\_1()} replayed at boot \\
|
|
\texttt{DigiRadio\_IC\_1\_PARAM.h} &
|
|
Parameter cell indices &
|
|
\texttt{ADDR\_*} macros; safeload targets \\
|
|
\texttt{DigiRadio\_IC\_1\_REG.h} &
|
|
Control register map &
|
|
Safeload trigger registers \\
|
|
\texttt{DigiRadio\_NetList.xml} &
|
|
Schematic netlist &
|
|
Reference when re-exporting \\
|
|
\texttt{DigiRadio.params} &
|
|
Parameter metadata &
|
|
SigmaStudio round-trip \\
|
|
\texttt{SigmaStudioFW.h} &
|
|
Safeload / I2C glue header &
|
|
\texttt{sigma\_safeload\_*} API \\
|
|
\bottomrule
|
|
\end{tabular}
|
|
\caption{ADAU1701 SigmaStudio export files (in git).}
|
|
\label{tab:adau1701-files}
|
|
\end{table}
|
|
|
|
The driver component wraps the generated C in three layers:
|
|
\texttt{adau1701\_program.c} calls \texttt{default\_download\_IC\_1()};
|
|
\texttt{SigmaStudioFW.c} implements \texttt{SIGMA\_WRITE\_REGISTER\_BLOCK}
|
|
and safeload on ESP-IDF I\textsuperscript{2}C; \texttt{Adau1701Driver.cpp}
|
|
adds reset, boot state, and typed runtime control.
|
|
|
|
\subsection{Refreshing after a SigmaStudio change}
|
|
\label{sec:adau1701-refresh}
|
|
|
|
When the schematic changes in SigmaStudio (new block, different EQ layout,
|
|
renamed cells):
|
|
|
|
\begin{enumerate}
|
|
\item Edit the project offline (Chapter~\ref{ch:sigmastudio},
|
|
Section~\ref{sec:ss-export}).
|
|
\item \emph{Action $\rightarrow$ Export System Files} into
|
|
\texttt{Firmware/ADAU1701-Firmware/}, overwriting the generated headers.
|
|
\item Copy or reconcile any new \texttt{ADDR\_*} symbols into
|
|
\texttt{Adau1701ParamMap.hpp} if block names moved (fader/EQ addresses
|
|
must match \texttt{DigiRadio\_IC\_1\_PARAM.h}).
|
|
\item Rebuild firmware; the ESP32 will replay the new download on next boot.
|
|
\item Update Chapter~\ref{ch:sigmastudio} tables if band frequencies or the
|
|
signal chain changed.
|
|
\end{enumerate}
|
|
|
|
\begin{drnote}[No USBi download on DigiRadio]
|
|
Do \emph{not} rely on SigmaStudio \emph{Link Compile Download} on this
|
|
hardware path. Export-only workflow is sufficient: the ESP32 is the programmer
|
|
at every power-up.
|
|
\end{drnote}
|
|
|
|
\section{Boot sequence (I\textsuperscript{2}C RAM load)}
|
|
\label{sec:adau1701-boot}
|
|
|
|
DigiRadio has no ADAU1701 self-boot EEPROM. The ESP32 holds the only copy of
|
|
the DSP program and writes it into RAM after each reset.
|
|
|
|
\begin{figure}[htbp]
|
|
\centering
|
|
\begin{tikzpicture}[
|
|
step/.style={draw, rounded corners, minimum width=9.5cm,
|
|
minimum height=0.9cm, align=center, font=\small},
|
|
>={Latex}, node distance=3mm]
|
|
\node[step, fill=black!6] (rst) {Assert RESET\# (10\,ms), release};
|
|
\node[step, fill=black!6, below=of rst] (i2c)
|
|
{Create I\textsuperscript{2}C master @ 100\,kHz, address 0x34};
|
|
\node[step, fill=black!8, below=of i2c] (dl)
|
|
{\texttt{default\_download\_IC\_1()} --- control, program, param RAM};
|
|
\node[step, fill=black!6, below=of dl] (ready)
|
|
{\texttt{Adau1701Driver::isBooted()} = true};
|
|
\node[step, fill=black!10, below=of ready] (prof)
|
|
{\texttt{AudioService::loadAndApply()} --- safeload user profile};
|
|
\foreach \a/\b in {rst/i2c, i2c/dl, dl/ready, ready/prof} {
|
|
\draw[->] (\a) -- (\b);
|
|
}
|
|
\end{tikzpicture}
|
|
\caption{ADAU1701 boot flow on DigiRadio (host RAM load).}
|
|
\label{fig:adau1701-boot}
|
|
\end{figure}
|
|
|
|
\texttt{SIGMA\_WRITE\_REGISTER\_BLOCK} streams each write in 64-byte I\textsuperscript{2}C
|
|
chunks. After download, \texttt{loadAndApply()} restores the saved
|
|
\texttt{core::AudioProfile} from NVS (or factory defaults) so user settings
|
|
survive power cycles without re-writing the whole program.
|
|
|
|
\section{Software architecture}
|
|
\label{sec:adau1701-stack}
|
|
|
|
Application code never includes \texttt{DigiRadio\_IC\_1\_PARAM.h}. The stack
|
|
separates concerns as follows:
|
|
|
|
\begin{table}[htbp]
|
|
\centering
|
|
\small
|
|
\begin{tabular}{@{}llp{5.8cm}@{}}
|
|
\drhead Layer & Type & Responsibility \\
|
|
\midrule
|
|
HTTP / UI & \texttt{SetupWebServer}, web UI &
|
|
JSON $\rightarrow$ \texttt{AudioService} \\
|
|
Service & \texttt{audio::AudioService} &
|
|
Profile in RAM, NVS, enhancement overlay \\
|
|
Domain & \texttt{core::AudioProfile}, \texttt{IDsp} &
|
|
Host-testable types, no ESP-IDF \\
|
|
Adapter & \texttt{adau1701::Adau1701Dsp} &
|
|
Maps \texttt{DspError} $\leftrightarrow$ \texttt{Adau1701Error} \\
|
|
Driver & \texttt{adau1701::Adau1701Driver} &
|
|
I\textsuperscript{2}C, boot, safeload \\
|
|
Generated + glue & \texttt{DigiRadio\_IC\_1.h}, \texttt{SigmaStudioFW.c} &
|
|
SigmaStudio export, register writes \\
|
|
\bottomrule
|
|
\end{tabular}
|
|
\caption{ADAU1701 control stack (Slice~5).}
|
|
\label{tab:adau1701-stack}
|
|
\end{table}
|
|
|
|
\texttt{AudioService} merges \texttt{AudioProfile::enhancements} into the
|
|
effective EQ via \texttt{core::applyEnhancementsToEq()} before calling
|
|
\texttt{IDsp::applyEq()} or \texttt{applyProfile()}. Base EQ settings in NVS
|
|
stay unchanged; enhancement bands are overlays (Section~\ref{sec:ss-enhancements}).
|
|
|
|
\section{Adau1701Driver API}
|
|
\label{sec:adau1701-driver}
|
|
|
|
\texttt{Adau1701Driver} owns the I\textsuperscript{2}C bus (RAII), drives
|
|
RESET\#, and exposes intent-level methods. All return
|
|
\texttt{std::expected<T, Adau1701Error>}. Runtime methods require a prior
|
|
successful \texttt{boot()}.
|
|
|
|
\subsection{Bring-up and state}
|
|
|
|
\begin{table}[htbp]
|
|
\centering
|
|
\begin{tabular}{@{}ll@{}}
|
|
\toprule
|
|
\textbf{Method} & \textbf{Purpose} \\
|
|
\midrule
|
|
\texttt{boot()} & Reset chip, init I\textsuperscript{2}C, run
|
|
\texttt{default\_download\_IC\_1()} \\
|
|
\texttt{isBooted()} & \texttt{true} after successful download \\
|
|
\bottomrule
|
|
\end{tabular}
|
|
\caption{ADAU1701 bring-up.}
|
|
\end{table}
|
|
|
|
\subsection{Full profile and partial updates}
|
|
|
|
\begin{table}[htbp]
|
|
\centering
|
|
\begin{tabular}{@{}ll@{}}
|
|
\toprule
|
|
\textbf{Method} & \textbf{Purpose} \\
|
|
\midrule
|
|
\texttt{applyProfile(profile)} &
|
|
Safeload mixer + EQ + master in one call \\
|
|
\texttt{applyMixer(mixer)} &
|
|
Si4684/ESP32 faders + St Mixer1 L/R \\
|
|
\texttt{applyEq(eq)} &
|
|
All six PEQ bands (band~0 skipped, see below) \\
|
|
\texttt{setInputVolume(source, L, R)} &
|
|
One source path (\texttt{MixSource::Si4684} or \texttt{Esp32}) \\
|
|
\texttt{setMasterVolume(L, R)} &
|
|
Multiple~1 master output \\
|
|
\texttt{setEqBand(band, gain, center, q)} &
|
|
Design biquad in core, safeload five coefficients \\
|
|
\bottomrule
|
|
\end{tabular}
|
|
\caption{Runtime safeload entry points.}
|
|
\label{tab:adau1701-api}
|
|
\end{table}
|
|
|
|
\begin{drnote}[High-pass band fixed]
|
|
\texttt{setEqBand} and \texttt{applyEq} \emph{skip} band index~0 (SigmaStudio
|
|
band~1, 20\,Hz Butterworth high-pass). Calls with index~0 return
|
|
\texttt{Adau1701Error::InvalidParameter}. Only peaking bands 1--5 are
|
|
runtime-adjustable, matching Table~\ref{tab:ss-runtime}.
|
|
\end{drnote}
|
|
|
|
\subsection{Gain and EQ coefficient path}
|
|
|
|
Volume cells (faders, master) store linear gain as ADAU \textbf{8.23 fixpoint}.
|
|
\texttt{core::gainDbToLinearFixpoint()} converts \texttt{GainDb} before
|
|
\texttt{sigma\_safeload\_param()}.
|
|
|
|
PEQ bands use \texttt{core::designPeakingEq()} at 48\,kHz sample rate to
|
|
produce five biquad coefficients (\texttt{B0..B2, A0..A1}), converted to
|
|
fixpoint and written atomically with \texttt{sigma\_safeload\_block()} (up to
|
|
five parameters per transfer --- one band per call).
|
|
|
|
Host tests in \texttt{components/core/test/biquad\_design\_test.cpp} lock the
|
|
coefficient math; \texttt{enhancements\_design\_test.cpp} locks enhancement
|
|
curves.
|
|
|
|
\section{Parameter address map}
|
|
\label{sec:adau1701-parammap}
|
|
|
|
SigmaStudio assigns small integer indices to parameter RAM cells. The export
|
|
header \texttt{DigiRadio\_IC\_1\_PARAM.h} defines \texttt{ADDR\_*} symbols;
|
|
\texttt{Adau1701ParamMap.hpp} maps domain concepts to those addresses:
|
|
|
|
\begin{table}[htbp]
|
|
\centering
|
|
\small
|
|
\begin{tabular}{@{}lll@{}}
|
|
\drhead Domain & \texttt{ADDR\_*} & SigmaStudio block \\
|
|
\midrule
|
|
Si4684 L/R & \texttt{SI4674}, \texttt{SI4674\_1} & Si4674 fader \\
|
|
ESP32 L/R & \texttt{ESP32}, \texttt{ESP32\_1} & ESP32 fader \\
|
|
Mix L/R & \texttt{STMIXER1\_ST0/1\_VOLUME} & St Mixer1 \\
|
|
EQ band $n$ & \texttt{PARAMEQ1\_ST$n$\_B0} + 0..4 & Param EQ1 coeffs \\
|
|
Master L/R & \texttt{MULTIPLE1}, \texttt{MULTIPLE1\_1} & Multiple 1 \\
|
|
\bottomrule
|
|
\end{tabular}
|
|
\caption{Runtime parameter map (current export). Re-verify after
|
|
SigmaStudio re-export.}
|
|
\label{tab:adau1701-addr}
|
|
\end{table}
|
|
|
|
If a schematic rename changes cell names, update \texttt{Adau1701ParamMap.hpp}
|
|
and this table together with \texttt{DigiRadio\_IC\_1\_PARAM.h}.
|
|
|
|
\section{Safeload mechanism}
|
|
\label{sec:adau1701-safeload}
|
|
|
|
Direct parameter RAM writes during playback cause audible clicks. The ADAU1701
|
|
provides \emph{safeload} registers: the host stages up to five
|
|
(address, value) pairs, then triggers a single atomic update between
|
|
samples.
|
|
|
|
DigiRadio implements this in \texttt{SigmaStudioFW.c}:
|
|
|
|
\begin{enumerate}
|
|
\item Write each fixpoint value to \texttt{SAFELOAD\_DATA\_0..4}.
|
|
\item Write each target parameter index to \texttt{SAFELOAD\_ADDR\_0..4}.
|
|
\item Pulse \texttt{CORE\_CONTROL} with \texttt{IST\_TRIGGER}.
|
|
\end{enumerate}
|
|
|
|
\texttt{sigma\_safeload\_param()} handles one cell (volume fader).
|
|
\texttt{sigma\_safeload\_block()} handles up to five (full PEQ band).
|
|
\texttt{Adau1701Driver} never writes parameter data registers directly for
|
|
runtime control.
|
|
|
|
\begin{drcaution}[Safeload only for live changes]
|
|
Boot-time programming uses \texttt{SIGMA\_WRITE\_REGISTER\_BLOCK} to fill
|
|
program and parameter RAM from the export. After audio is running, mixer and
|
|
EQ updates must use safeload only.
|
|
\end{drcaution}
|
|
|
|
\section{Domain model and persistence}
|
|
\label{sec:adau1701-domain}
|
|
|
|
\texttt{core::AudioProfile} is the unit of persistence and HTTP serialisation:
|
|
|
|
\begin{itemize}
|
|
\item \texttt{MixerState} --- six \texttt{GainDb} fields (Si4684 L/R,
|
|
ESP32 L/R, St Mixer1 L/R).
|
|
\item \texttt{EqProfile} --- six bands; index~0 fixed high-pass, 1--5
|
|
peaking (100\,Hz--8\,kHz defaults per Chapter~\ref{sec:ss-eq}).
|
|
\item \texttt{masterLeft}, \texttt{masterRight} --- Multiple~1.
|
|
\item \texttt{AudioEnhancements} --- \texttt{stereo\_level} and
|
|
\texttt{bass\_level} (0--100), mapped to PEQ overlays at apply time.
|
|
\end{itemize}
|
|
|
|
JSON parse/serialise lives in \texttt{core::AudioProfileJson} (pure core, host
|
|
tested). NVS key \texttt{audio\_profile\_json} in namespace \texttt{digiradio}
|
|
via \texttt{secure\_store::NvsAudioProfileStore}.
|
|
|
|
\texttt{AudioProfile::factoryDefault()} is flat EQ, 0\,dB gains, enhancements
|
|
off. \texttt{POST /api/audio/reset} restores and persists this snapshot.
|
|
|
|
\section{audio::AudioService}
|
|
\label{sec:adau1701-service}
|
|
|
|
\texttt{AudioService} is the only entry point HTTP and future UI code should
|
|
use for audio path control:
|
|
|
|
\begin{table}[htbp]
|
|
\centering
|
|
\small
|
|
\begin{tabular}{@{}ll@{}}
|
|
\toprule
|
|
\textbf{Method} & \textbf{Effect} \\
|
|
\midrule
|
|
\texttt{loadAndApply()} & Load NVS (or default), safeload full profile \\
|
|
\texttt{applyProfile(p, persist)} & Replace profile, safeload, optional NVS \\
|
|
\texttt{setInputVolume(source, L, R, persist)} & One input path \\
|
|
\texttt{setMasterVolume(L, R, persist)} & Master fader \\
|
|
\texttt{setEqBand(band, ...)} & Update base EQ + effective overlay \\
|
|
\texttt{setStereoEnhance(level, persist)} & PEQ overlay bands 3--5 \\
|
|
\texttt{setBassEnhance(level, persist)} & PEQ overlay bands 1--2 \\
|
|
\texttt{currentProfile()} & Snapshot for \texttt{GET /api/audio/profile} \\
|
|
\bottomrule
|
|
\end{tabular}
|
|
\caption{\texttt{AudioService} intent-level API.}
|
|
\label{tab:adau1701-service}
|
|
\end{table}
|
|
|
|
On boot, \texttt{HardwareBootstrap::boot()} runs Si4684 boot, then
|
|
\texttt{Adau1701Driver::boot()}, then \texttt{loadAndApply()}. ADAU boot
|
|
failure is fail-closed (no network start); profile apply failure is logged as
|
|
warning but boot continues.
|
|
|
|
\section{HTTP and web UI}
|
|
\label{sec:adau1701-http}
|
|
|
|
REST routes (Chapter~\ref{ch:api}, Section~\ref{sec:api-audio-profile-get})
|
|
delegate to \texttt{AudioService}:
|
|
|
|
\begin{itemize}
|
|
\item \texttt{GET/PUT /api/audio/profile} --- full JSON profile.
|
|
\item \texttt{POST /api/audio/reset} --- factory flat profile.
|
|
\item \texttt{POST /api/audio/stereo-enhance} --- body
|
|
\texttt{\{"level":0..100\}}.
|
|
\item \texttt{POST /api/audio/bass-enhance} --- same schema.
|
|
\end{itemize}
|
|
|
|
The gzipped setup page (\texttt{components/net/www/index.html}) is a tabbed
|
|
SPA: a \emph{Now playing} view (RDS/DLS metadata), tuner and preset panels,
|
|
master/path levels, six PEQ band gain sliders, enhancement overlays, Bluetooth
|
|
controls, and Wi-Fi provisioning. Saving sends \texttt{PUT /api/audio/profile};
|
|
enhancement sliders call the dedicated POST routes for immediate safeload +
|
|
persist. Regenerate \texttt{index.html.gz} with \texttt{tools/gzip-www.sh}
|
|
after editing the HTML source.
|
|
|
|
\section{Typical usage patterns}
|
|
\label{sec:adau1701-patterns}
|
|
|
|
\subsection{C++ firmware (direct service access)}
|
|
|
|
\begin{enumerate}
|
|
\item After \texttt{HardwareBootstrap::boot()}, obtain
|
|
\texttt{HardwareBootstrap::audioService()}.
|
|
\item Adjust levels:
|
|
\texttt{setMasterVolume(GainDb::tryFromDb(-3), ..., true)}.
|
|
\item Tune one EQ band (index 2 = 400\,Hz peaking in default map):
|
|
\texttt{setEqBand(band, gain, center, q, true)}.
|
|
\item Read back: \texttt{currentProfile()} for logging or display.
|
|
\end{enumerate}
|
|
|
|
\subsection{HTTP client}
|
|
|
|
\begin{verbatim}
|
|
# Read current snapshot:
|
|
curl http://digiradio.local/api/audio/profile
|
|
|
|
# Boost bass enhance to 60%:
|
|
curl -X POST http://digiradio.local/api/audio/bass-enhance \
|
|
-H "Content-Type: application/json" -d '{"level":60}'
|
|
|
|
# Restore factory flat:
|
|
curl -X POST http://digiradio.local/api/audio/reset
|
|
\end{verbatim}
|
|
|
|
\subsection{After SigmaStudio EQ layout change}
|
|
|
|
Re-export, rebuild firmware, flash ESP32. Existing NVS profiles remain valid
|
|
only if band indices and centre frequencies still match; otherwise reset via
|
|
\texttt{POST /api/audio/reset} or migrate JSON manually.
|
|
|
|
\section{Error handling}
|
|
\label{sec:adau1701-errors}
|
|
|
|
\texttt{Adau1701Error} values and typical causes:
|
|
|
|
\begin{table}[htbp]
|
|
\centering
|
|
\small
|
|
\begin{tabular}{@{}ll@{}}
|
|
\drhead Error & Typical cause \\
|
|
\midrule
|
|
\texttt{ResetFailed} & GPIO reset line configuration \\
|
|
\texttt{I2cInitFailed} & Bus or device add on ESP32 \\
|
|
\texttt{DownloadFailed} & I\textsuperscript{2}C failure during boot download \\
|
|
\texttt{NotBooted} & Runtime call before \texttt{boot()} \\
|
|
\texttt{SafeloadFailed} & I\textsuperscript{2}C or safeload trigger failure \\
|
|
\texttt{InvalidParameter} & EQ band~0 or out-of-range domain input \\
|
|
\bottomrule
|
|
\end{tabular}
|
|
\caption{ADAU1701 driver errors.}
|
|
\label{tab:adau1701-errors}
|
|
\end{table}
|
|
|
|
\texttt{Adau1701Dsp} maps these to \texttt{core::DspError} for
|
|
\texttt{AudioService}. HTTP handlers map store/DSP failures to
|
|
\texttt{\{"status":"error","reason":"store\_failed"\}} with HTTP~500.
|
|
|
|
\section{Integration at power-up}
|
|
\label{sec:adau1701-integration}
|
|
|
|
Static instances in \texttt{main/hardware\_bootstrap.cpp}:
|
|
|
|
\begin{verbatim}
|
|
Adau1701Driver -> Adau1701Dsp -> AudioService(NvsAudioProfileStore)
|
|
\end{verbatim}
|
|
|
|
Boot order: Si4684 \texttt{boot(Dab)} $\rightarrow$ ADAU1701 \texttt{boot()}
|
|
$\rightarrow$ \texttt{loadAndApply()} $\rightarrow$ network stack.
|
|
\texttt{main/main.cpp} passes \texttt{audioService()} to
|
|
\texttt{NetBootstrap::start()} for HTTP registration.
|
|
|
|
\section{Further reading}
|
|
\label{sec:adau1701-reading}
|
|
|
|
\begin{itemize}
|
|
\item Chapter~\ref{ch:sigmastudio} --- schematic, EQ bands, export workflow.
|
|
\item Chapter~\ref{ch:api} --- JSON schemas for \texttt{/api/audio/*}.
|
|
\item \texttt{Firmware/ADAU1701-Firmware/README.md} --- export file cheatsheet.
|
|
\item Analog Devices ADAU1701 datasheet --- safeload and I\textsuperscript{2}C protocol.
|
|
\item \texttt{components/core/test/} --- biquad and profile JSON host tests.
|
|
\end{itemize}
|