Add internet radio streaming with runtime API, modernize web UI, remove auto-tune/beep at boot
Streaming (main feature this session): - New WebRadioConfig/WebRadioJson core types, ISecureStore-backed persistence - New webradio::WebRadioService (thread-safe live config) + GET/POST /api/streaming - web_radio_stream task now runtime-toggleable (no reboot), no hardcoded URL - Content-Type diagnostic: warns clearly when a URL is a webpage, not an audio stream Boot cleanup: - Removed boot-time auto FM/DAB tune, auto-beep, and the (now-concluded) Si4684 crystal IBIAS/CTUN empirical sweep from main.cpp — tuning/beep are on-demand via the existing REST API only Web UI: - Modernized styling (cards, gradients, toggle switches, light/dark theme) - New Stream tab wired to /api/streaming Fixes found via real idf.py build (not just clangd): - Restored wrongly-removed si4684/Si4684Tuner.hpp include in main.cpp - Fixed MP3Decode() argument types in web_radio_stream.cpp (unsigned char**/int*) Quality-gate fixes: - Host-test stub headers (esp_log.h, freertos/*) so TunerService.cpp's scanForStation logging/pacing compiles for station_service_test / integration_service_test instead of running stale binaries - Added WifiScanner and WebRadioService manual sections; filled in missing Doxygen docs on BluetoothService, i2s_sdata_probe, test_firmware, Bt1035At - Ignore clangd's .cache/ index directory Also includes prior uncommitted work carried in the tree: Wi-Fi/Bluetooth device scan REST API and UI (WifiScanner, BT scan), SigmaStudio TCP bridge, and the current ADAU1701 SigmaStudio DSP program export. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -99,10 +99,14 @@ renamed cells):
|
||||
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.
|
||||
\begin{drnote}[Export-only workflow still recommended]
|
||||
The export-only workflow above remains the simplest path: the ESP32 replays
|
||||
the committed export at every power-up, so \emph{Link Compile Download} is
|
||||
not required for day-to-day firmware builds. Since firmware~0.9.0, however,
|
||||
DigiRadio does expose SigmaStudio's Remote Connection over TCP for live DSP
|
||||
work and bench debugging --- see Section~\ref{sec:adau1701-sigmastudio-tcp}.
|
||||
A completed Download over that path is automatically persisted to flash and
|
||||
becomes the boot program, exactly like re-exporting and rebuilding.
|
||||
\end{drnote}
|
||||
|
||||
\section{Boot sequence (I\textsuperscript{2}C RAM load)}
|
||||
@@ -134,14 +138,97 @@ the DSP program and writes it into RAM after each reset.
|
||||
\label{fig:adau1701-boot}
|
||||
\end{figure}
|
||||
|
||||
\texttt{SIGMA\_WRITE\_REGISTER\_BLOCK} streams each write in 64-byte I\textsuperscript{2}C
|
||||
chunks (payloads may exceed 255 bytes). The active script comes from the
|
||||
\texttt{SIGMA\_WRITE\_REGISTER\_BLOCK} streams each write in $\leq$64-byte
|
||||
I\textsuperscript{2}C chunks, rounded down to a whole number of words for the
|
||||
target region (Parameter RAM = 4~bytes/word, Program RAM = 5, control
|
||||
registers = 2) so chunk boundaries never split a word or desynchronise the
|
||||
running address (payloads may exceed 255 bytes). The active script comes from the
|
||||
\texttt{dsp} data partition when a valid \texttt{DRAD} blob is present; otherwise
|
||||
the embedded SigmaStudio export is used (Section~\ref{sec:api-dsp-program}).
|
||||
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{SigmaStudio Remote Connection (TCP bridge)}
|
||||
\label{sec:adau1701-sigmastudio-tcp}
|
||||
|
||||
\texttt{net::SigmaStudioTcpServer}\label{cls:SigmaStudioTcpServer} exposes the
|
||||
ADAU1701 to SigmaStudio running on a PC over TCP/IP, so SigmaStudio's own
|
||||
\emph{Connect} and \emph{Link Compile Download} work against DigiRadio exactly
|
||||
as they would against a USBi/ICP dongle. It listens on port \textbf{8086} in
|
||||
both SoftAP setup mode and STA mode, started from \texttt{NetBootstrap}
|
||||
alongside \texttt{SetupWebServer}. The socket is unauthenticated, consistent
|
||||
with the existing LAN-exposed \texttt{POST /api/system/ota} and
|
||||
\texttt{POST /api/dsp/program} endpoints.
|
||||
|
||||
\begin{drref}[Protocol source]
|
||||
This implements the subset of SigmaStudio's TCPi wire protocol needed for
|
||||
Connect, Download, register read/write, and runtime safeload, ported from the
|
||||
\href{https://github.com/rarranzb/ADAU1701-TCPi-ESP32}{ADAU1701-TCPi-ESP32}
|
||||
reference project (MIT licence). Analog Devices' TCPi protocol itself is
|
||||
closed/undocumented; this is a single third-party reverse-engineering source,
|
||||
cross-checked against DigiRadio's own generated \texttt{DigiRadio\_IC\_1.h}
|
||||
memory-map constants (Program RAM at word-address \texttt{0x0400}, Parameter
|
||||
RAM at \texttt{0x0000}, core control register at \texttt{0x081C}) which match
|
||||
exactly. Verify with a real SigmaStudio Connect + Download session before
|
||||
relying on it for production DSP work.
|
||||
\end{drref}
|
||||
|
||||
\begin{table}[htbp]
|
||||
\centering
|
||||
\small
|
||||
\begin{tabular}{@{}L{2.2cm}L{9.8cm}@{}}
|
||||
\drhead Frame & Layout \\
|
||||
\midrule
|
||||
\texttt{0x09} WRITE &
|
||||
\texttt{[op][safeload][rsvd][totalLen:2][chipAddr][dataLen:2][addr:2][payload]} \\
|
||||
\texttt{0x0A} READ\_REQ &
|
||||
\texttt{[op][totalLen:2][chipAddr][dataLen:2][addr:2]} \\
|
||||
\texttt{0x0B} READ\_RESP &
|
||||
\texttt{[op][size:2][chipAddr][dataLen:2][addr:2][status][data]} \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\caption{TCPi frame layout (all multi-byte fields big-endian).}
|
||||
\label{tab:adau1701-tcpi-frames}
|
||||
\end{table}
|
||||
|
||||
Direct (non-safeload) writes reuse the region-aware
|
||||
\texttt{SIGMA\_WRITE\_REGISTER\_BLOCK} (Section~\ref{sec:adau1701-boot} boot
|
||||
path). Safeload writes forward SigmaStudio's already-encoded 4-byte words
|
||||
verbatim via \texttt{sigma\_safeload\_raw\_block()} --- unlike
|
||||
\texttt{sigma\_safeload\_block()} (Section~\ref{sec:adau1701-safeload}), which
|
||||
reconstructs the payload from a host \texttt{int}, this path never
|
||||
reinterprets network bytes. A new \texttt{sigma\_studio\_lock()} /
|
||||
\texttt{sigma\_studio\_unlock()} pair in \texttt{SigmaStudioFW.c} serialises
|
||||
whole safeload/write sequences against \texttt{Adau1701Driver}'s own
|
||||
REST-triggered safeload calls, so a live SigmaStudio session and
|
||||
\texttt{/api/audio/*} traffic cannot interleave mid-transaction.
|
||||
|
||||
\subsection{Persisting a Download as the boot program}
|
||||
|
||||
A completed \emph{Link Compile Download} is captured and made the program
|
||||
DigiRadio boots with next time --- the same outcome as re-exporting and
|
||||
rebuilding. \texttt{SigmaStudioTcpServer} coalesces contiguous direct writes
|
||||
into a handful of regions per connection (mirroring the five-block shape
|
||||
of \texttt{EmbeddedDspProgramSource}), completion is detected the same way
|
||||
the reference project detects it: a direct write to \texttt{0x081C} that sets
|
||||
the DSPRUN bit. On completion the coalesced regions are serialised
|
||||
(\texttt{core::serializeDspProgramBlob()}) and written to the \texttt{dsp}
|
||||
flash partition via \texttt{adau1701::FlashDspProgramSource::storeBlob()} ---
|
||||
the same function \texttt{POST /api/dsp/program} already uses
|
||||
(Section~\ref{sec:api-dsp-program}). If a session is too fragmented to fit the
|
||||
blob's own caps (32 regions / 16\,KiB per region / 200\,KiB total), the
|
||||
persist step is skipped for that session only; the DSP still runs from what
|
||||
was written live over I\textsuperscript{2}C.
|
||||
|
||||
\begin{drcaution}[Not ported from the reference project]
|
||||
DigiRadio does not implement the reference project's EEPROM self-boot capture
|
||||
(binary format for an external self-boot EEPROM) or its Wi-Fi/GPIO
|
||||
configuration web UI --- DigiRadio has no self-boot EEPROM on this bus (the
|
||||
24AA025E48 at \texttt{0x52} is an EUI-48 identity chip only), and Wi-Fi
|
||||
provisioning already exists via \texttt{POST /api/wifi}.
|
||||
\end{drcaution}
|
||||
|
||||
\section{Software architecture}
|
||||
\label{sec:adau1701-stack}
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
The Feasycom FSC-BT1035 (Qualcomm QCC3056) is the wireless output stage of
|
||||
DigiRadio: it receives PCM from the ADAU1701 over I\textsuperscript{2}S and
|
||||
streams Bluetooth audio with aptX, aptX~HD, and aptX~Adaptive. This chapter
|
||||
documents how the ESP32-S3 controls the module over UART (AT commands with
|
||||
RTS/CTS), why I\textsuperscript{2}S slave mode is mandatory, and how
|
||||
\texttt{bt1035::Bt1035Driver} implements the bring-up sequence.
|
||||
documents how the ESP32-S3 controls the module over UART (AT commands, no
|
||||
hardware flow control), why I\textsuperscript{2}S slave mode is mandatory,
|
||||
and how \texttt{bt1035::Bt1035Driver} implements the bring-up sequence.
|
||||
|
||||
\begin{drref}[Hardware context]
|
||||
Board wiring (UART pins, I\textsuperscript{2}S to the module, flow control)
|
||||
@@ -30,9 +30,9 @@ accepted and encoded for transmission.
|
||||
|
||||
Without firmware init the module may stay in a default mode that ignores the
|
||||
I\textsuperscript{2}S bus from the ADAU1701. The mandatory
|
||||
\texttt{AT+AUXCFG=3} and \texttt{AT+I2SCFG=67} commands select I\textsuperscript{2}S
|
||||
slave input at 48\,kHz --- omitting them silently breaks the entire wireless
|
||||
output (Section~\ref{sec:bt1035-i2s}).
|
||||
\texttt{AT+AUXCFG=3} and \texttt{AT+I2SCFG=35} commands select I\textsuperscript{2}S
|
||||
slave input at 48\,kHz, 24-bit --- omitting them silently breaks the entire
|
||||
wireless output (Section~\ref{sec:bt1035-i2s}).
|
||||
|
||||
\section{Control interface}
|
||||
\label{sec:bt1035-uart}
|
||||
@@ -48,7 +48,7 @@ output (Section~\ref{sec:bt1035-i2s}).
|
||||
Port & UART2 (not the console UART) \\
|
||||
Baud rate & 115200 \\
|
||||
Data format & 8N1 \\
|
||||
Flow control & Hardware RTS/CTS (required) \\
|
||||
Flow control & Disabled on the ESP32 UART (\texttt{UART\_HW\_FLOWCTRL\_DISABLE}) \\
|
||||
Reset & GPIO active-low pulse at boot \\
|
||||
SYS\_CTL & Held active to enable the module \\
|
||||
\bottomrule
|
||||
@@ -57,6 +57,18 @@ output (Section~\ref{sec:bt1035-i2s}).
|
||||
\label{tab:bt1035-uart}
|
||||
\end{table}
|
||||
|
||||
\begin{drnote}[Flow control disabled, not just unused]
|
||||
Earlier revisions wired \texttt{RTS}/\texttt{CTS} through
|
||||
\texttt{Bt1035Pins} and configured \texttt{UART\_HW\_FLOWCTRL\_CTS\_RTS}.
|
||||
That was reverted: \texttt{Bt1035Driver.cpp} now configures
|
||||
\texttt{UART\_HW\_FLOWCTRL\_DISABLE} and passes
|
||||
\texttt{UART\_PIN\_NO\_CHANGE} for both lines --- GPIO14/21 are not driven by
|
||||
this driver. No AT command in \texttt{core::Bt1035AtCommand} configures flow
|
||||
control on the module side either; this has not caused observed boot
|
||||
failures, but has not been independently verified against the module's own
|
||||
flow-control expectation.
|
||||
\end{drnote}
|
||||
|
||||
\subsection{Response handling}
|
||||
|
||||
Every command expects a module reply containing \texttt{OK} or
|
||||
@@ -69,7 +81,7 @@ Every command expects a module reply containing \texttt{OK} or
|
||||
\end{itemize}
|
||||
|
||||
Host tests in \drpath{components/core/test/bt1035_at_test.cpp} lock the
|
||||
init sequence (\texttt{AT+AUXCFG=3}, \texttt{AT+I2SCFG=67}) and the parser.
|
||||
init sequence (\texttt{AT+AUXCFG=3}, \texttt{AT+I2SCFG=35}) and the parser.
|
||||
|
||||
\section{Mandatory I\textsuperscript{2}S slave mode}
|
||||
\label{sec:bt1035-i2s}
|
||||
@@ -80,7 +92,9 @@ with shared BCLK/LRCLK (see Chapter~\ref{ch:hardware}). The init sequence
|
||||
must use:
|
||||
\begin{itemize}
|
||||
\item \texttt{AT+AUXCFG=3} --- I\textsuperscript{2}S mode (§5.1.25)
|
||||
\item \texttt{AT+I2SCFG=67} --- I\textsuperscript{2}S slave, 48\,kHz, 32-bit (§5.1.4)
|
||||
\item \texttt{AT+I2SCFG=35} --- I\textsuperscript{2}S slave, 48\,kHz, 24-bit (§5.1.4),
|
||||
matching the ADAU1701 serial output word length configured in the
|
||||
SigmaStudio Hardware Configuration
|
||||
\end{itemize}
|
||||
\texttt{AT+AUXCFG=1} (Line-In) does \textbf{not} match the schematic.
|
||||
AGENTS.md treats skipping I\textsuperscript{2}S init as a production bug.
|
||||
@@ -101,16 +115,18 @@ I\textsuperscript{2}S path is ready before Wi-Fi starts.
|
||||
>={Latex}, node distance=3mm]
|
||||
\node[drstep, fill=black!6] (sys) {SYS\_CTL high, RESET\# pulse};
|
||||
\node[drstep, fill=black!6, below=of sys] (uart)
|
||||
{Install UART2 @ 115200, RTS/CTS};
|
||||
\node[drstep, fill=black!8, below=of uart] (at)
|
||||
{Install UART2 @ 115200, flow control disabled};
|
||||
\node[drstep, fill=black!7, below=of uart] (swrst)
|
||||
{Send \texttt{AT+RESET} (best-effort), settle 500\,ms, flush RX};
|
||||
\node[drstep, fill=black!8, below=of swrst] (at)
|
||||
{Send \texttt{AT} --- expect OK};
|
||||
\node[drstep, fill=black!10, below=of at] (aux)
|
||||
{Send \texttt{AT+AUXCFG=3} --- expect OK (I\textsuperscript{2}S)};
|
||||
\node[drstep, fill=black!10, below=of aux] (i2s)
|
||||
{Send \texttt{AT+I2SCFG=67} --- expect OK (slave 48\,kHz)};
|
||||
{Send \texttt{AT+I2SCFG=35} --- expect OK (slave 48\,kHz, 24-bit)};
|
||||
\node[drstep, fill=black!6, below=of i2s] (done)
|
||||
{\texttt{Bt1035Driver::isBooted()} = true};
|
||||
\foreach \a/\b in {sys/uart, uart/at, at/aux, aux/i2s, i2s/done} {
|
||||
\foreach \a/\b in {sys/uart, uart/swrst, swrst/at, at/aux, aux/i2s, i2s/done} {
|
||||
\draw[->] (\a) -- (\b);
|
||||
}
|
||||
\end{tikzpicture}
|
||||
@@ -118,6 +134,17 @@ I\textsuperscript{2}S path is ready before Wi-Fi starts.
|
||||
\label{fig:bt1035-boot}
|
||||
\end{figure}
|
||||
|
||||
\begin{drnote}[AT+RESET is best-effort, not gated]
|
||||
Unlike \texttt{AT+AUXCFG=3}/\texttt{AT+I2SCFG=35} (mandatory,
|
||||
\texttt{core::bootInitSequence()}, boot fails if either is refused),
|
||||
\texttt{AT+RESET} is sent separately and its result is discarded: it is
|
||||
unverified whether this Feasycom firmware acknowledges the command before
|
||||
rebooting, resets silently without a reply, or rejects it outright. Gating
|
||||
boot on an unconfirmed ack would risk breaking an otherwise-working sequence.
|
||||
The 500\,ms settle delay and RX flush after sending it mirror the delay
|
||||
already used after the hardware GPIO reset pulse.
|
||||
\end{drnote}
|
||||
|
||||
Pairing, codec selection, and volume over Bluetooth are handled by the
|
||||
module's own firmware and NVS; DigiRadio firmware currently implements
|
||||
only the I\textsuperscript{2}S bring-up required for the wired audio path.
|
||||
@@ -158,9 +185,10 @@ The firmware enumerates every command it sends. Wire formats follow
|
||||
\begin{tabular}{@{}L{2.4cm}L{3.4cm}L{5.5cm}@{}}
|
||||
\drhead Enum & Line sent & Programming guide \\
|
||||
\midrule
|
||||
\texttt{Reset} & \texttt{AT+RESET} & software reset, best-effort \\
|
||||
\texttt{Ping} & \texttt{AT} & link check \\
|
||||
\texttt{I2sMode} & \texttt{AT+AUXCFG=3} & §5.1.25 Param=3 I2S \\
|
||||
\texttt{I2sSlave48k32} & \texttt{AT+I2SCFG=67} & §5.1.4 slave 48\,kHz 32-bit \\
|
||||
\texttt{I2sSlave48k24} & \texttt{AT+I2SCFG=35} & §5.1.4 slave 48\,kHz 24-bit \\
|
||||
\texttt{PairDiscoverable} & \texttt{AT+PAIR=1} & §5.1.20 enter discoverable \\
|
||||
\texttt{PairHidden} & \texttt{AT+PAIR=0} & §5.1.20 leave discoverable \\
|
||||
\texttt{A2dpStat} & \texttt{AT+A2DPSTAT} & §5.3.1; states 1--5 \\
|
||||
@@ -171,7 +199,9 @@ The firmware enumerates every command it sends. Wire formats follow
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\caption{Enumerated AT commands (\texttt{core::Bt1035AtCommand}). Boot
|
||||
uses Ping + I2sMode + I2sSlave48k32; pairing commands are runtime.}
|
||||
sends Reset (best-effort) then the mandatory Ping + I2sMode +
|
||||
I2sSlave48k24 (\texttt{core::bootInitSequence()}); pairing commands are
|
||||
runtime.}
|
||||
\label{tab:bt1035-at}
|
||||
\end{table}
|
||||
|
||||
@@ -258,7 +288,7 @@ bt1035::Bt1035Driver& bt = ...;
|
||||
if (auto r = bt.sendCommand(core::Bt1035AtCommand::I2sMode); !r) {
|
||||
// handle Bt1035Error
|
||||
}
|
||||
if (auto r = bt.sendCommand(core::Bt1035AtCommand::I2sSlave48k32); !r) {
|
||||
if (auto r = bt.sendCommand(core::Bt1035AtCommand::I2sSlave48k24); !r) {
|
||||
// handle Bt1035Error
|
||||
}
|
||||
\end{verbatim}
|
||||
|
||||
@@ -79,11 +79,20 @@ Minimal HTTP server: gzipped setup UI and typed JSON REST handlers:
|
||||
\item Audio: \texttt{/api/audio/*}
|
||||
\item Bluetooth: \texttt{/api/bluetooth/*}
|
||||
\item Presets: \texttt{/api/stations/*}
|
||||
\item Streaming: \texttt{/api/streaming}
|
||||
\end{itemize}
|
||||
JSON parsing and serialisation delegate to the pure core; credentials persist via \texttt{ISecureStore};
|
||||
tuner via \texttt{tuner::TunerService}; audio via
|
||||
\texttt{audio::AudioService}; Bluetooth via \texttt{bluetooth::BluetoothService};
|
||||
presets via \texttt{station::StationService}.
|
||||
presets via \texttt{station::StationService}; streaming via
|
||||
\texttt{webradio::WebRadioService}.
|
||||
|
||||
\section{WifiScanner}\label{cls:WifiScanner}
|
||||
Stateless shell helper wrapping \texttt{esp\_wifi} scan for the setup UI's
|
||||
Wi-Fi tab. \texttt{scanNearby()} temporarily switches an AP-only radio to
|
||||
APSTA mode when needed, runs a blocking scan, dedupes access points by
|
||||
SSID (keeping the strongest RSSI), and maps results to
|
||||
\texttt{core::WifiScannedNetwork}. Called from \texttt{POST /api/wifi/scan}.
|
||||
|
||||
\section{NetBootstrap}\label{cls:NetBootstrap}
|
||||
Owns network resources for setup or STA mode. Initialises encrypted NVS via
|
||||
@@ -168,7 +177,7 @@ index (1--8), 12-digit MAC, and optional friendly name. Parsed by
|
||||
UART driver for the FSC-BT1035 (Chapter~\ref{ch:bt1035}). \texttt{boot()}
|
||||
pulses RESET\#, opens UART2 with RTS/CTS, and runs
|
||||
\texttt{core::bootInitSequence()} (Ping + \texttt{AT+AUXCFG=3} +
|
||||
\texttt{AT+I2SCFG=67}). Returns
|
||||
\texttt{AT+I2SCFG=35}). Returns
|
||||
\texttt{Bt1035Error} on timeout, ERROR response, or UART failure.
|
||||
|
||||
\section{Adau1701Driver}\label{cls:Adau1701Driver}
|
||||
@@ -341,4 +350,12 @@ the inactive OTA slot, validates the app descriptor via
|
||||
\texttt{core::validateOtaAppDescriptor()}, and exposes
|
||||
\texttt{confirmBoot()} for rollback cancellation after a healthy network boot.
|
||||
|
||||
\section{WebRadioService}\label{cls:WebRadioService}
|
||||
Thread-safe holder for the internet radio streaming config (enabled flag +
|
||||
HTTP MP3 URL), backed by \texttt{core::ISecureStore}. A FreeRTOS mutex
|
||||
guards an in-RAM copy so \texttt{setConfig()} from an HTTP handler and
|
||||
\texttt{config()} polled by the streaming task in
|
||||
\texttt{main/web\_radio\_stream.cpp} never race. Exposed on
|
||||
\texttt{/api/streaming}.
|
||||
|
||||
% ------------------------------------------------------------------
|
||||
|
||||
@@ -151,7 +151,7 @@ safeload registers.
|
||||
\paragraph{FSC-BT1035 (Bluetooth).}
|
||||
The module is controlled by AT commands over UART with hardware flow control.
|
||||
The initialisation sequence includes enabling I\textsuperscript{2}S slave mode
|
||||
(\texttt{AT+AUXCFG=3} and \texttt{AT+I2SCFG=67}), which is required for the
|
||||
(\texttt{AT+AUXCFG=3} and \texttt{AT+I2SCFG=35}), which is required for the
|
||||
wired digital audio path from the ADAU1701 to the module.
|
||||
Command responses are parsed explicitly, with timeouts treated as errors.
|
||||
Full driver API, boot flow, and error codes are in Chapter~\ref{ch:bt1035}.
|
||||
@@ -218,7 +218,7 @@ bring-up:
|
||||
defaults) via ADAU1701 safeload before network bring-up.
|
||||
\item \textbf{FSC-BT1035} (UART): \texttt{bt1035::Bt1035Driver::boot()}
|
||||
enables I\textsuperscript{2}S slave mode (\texttt{AT+AUXCFG=3},
|
||||
\texttt{AT+I2SCFG=67}) after the DSP path is configured
|
||||
\texttt{AT+I2SCFG=35}) after the DSP path is configured
|
||||
(Chapter~\ref{ch:bt1035}).
|
||||
\end{enumerate}
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ in the module's own non-volatile memory.
|
||||
\begin{drcaution}[I\textsuperscript{2}S slave mode]
|
||||
The PCB routes ADAU1701 \texttt{SDATA\_OUT0} to the module over
|
||||
I\textsuperscript{2}S (BCLK, LRCLK, PCM data). Firmware must initialise
|
||||
\texttt{AT+AUXCFG=3} and \texttt{AT+I2SCFG=67}, not Line-In
|
||||
\texttt{AT+AUXCFG=3} and \texttt{AT+I2SCFG=35}, not Line-In
|
||||
(\texttt{AT+AUXCFG=1}). See Chapter~\ref{ch:bt1035}, Section~\ref{sec:bt1035-i2s}.
|
||||
\end{drcaution}
|
||||
|
||||
@@ -525,7 +525,7 @@ ever used.}
|
||||
\midrule
|
||||
UART with flow control & TX/RX + RTS/CTS wired & verified \\
|
||||
I\textsuperscript{2}S init (firmware) &
|
||||
\texttt{AT+AUXCFG=3}, \texttt{AT+I2SCFG=67} & driver rule \\
|
||||
\texttt{AT+AUXCFG=3}, \texttt{AT+I2SCFG=35} & driver rule \\
|
||||
I\textsuperscript{2}S input & receives clocks from ADAU master (slave) & verified \\
|
||||
Reset line & RESET (GPIO17) driven by ESP32 & verified \\
|
||||
\bottomrule
|
||||
|
||||
@@ -21,9 +21,18 @@ the program, not to drive the chip in operation.
|
||||
The whole program can be built and exported offline, without a physical
|
||||
ADAU1701 or a USBi programmer connected. A USBi block is placed in the
|
||||
Hardware Configuration only because SigmaStudio requires a communication
|
||||
channel to compile; it is never used for a real download in this project.
|
||||
channel to compile.
|
||||
\end{drkey}
|
||||
|
||||
\begin{drref}[Live connection is also possible]
|
||||
Since firmware~0.9.0, DigiRadio's \texttt{net::SigmaStudioTcpServer}
|
||||
(Chapter~\ref{ch:adau1701}, Section~\ref{sec:adau1701-sigmastudio-tcp})
|
||||
exposes a TCP:8086 bridge so SigmaStudio can \emph{Connect} and
|
||||
\emph{Link Compile Download} directly against a running board, for live DSP
|
||||
tuning and bench debugging. The export-only workflow below remains the
|
||||
simplest path for ordinary firmware builds.
|
||||
\end{drref}
|
||||
|
||||
\section{Hardware Configuration}
|
||||
\label{sec:ss-hwcfg}
|
||||
|
||||
@@ -270,9 +279,11 @@ The firmware's ADAU1701 driver replays the program data over
|
||||
I\textsuperscript{2}C at boot, and uses the parameter addresses for
|
||||
safeload updates.
|
||||
|
||||
\begin{drnote}[No download needed]
|
||||
Since there is no ADAU1701 attached during development, do \emph{not} use
|
||||
\emph{Link Compile Download} (it would fail trying to reach the chip).
|
||||
\emph{Export System Files} compiles the schematic and writes the files
|
||||
directly.
|
||||
\begin{drnote}[Export System Files vs. Link Compile Download]
|
||||
Without a physical ADAU1701/USBi attached, \emph{Export System Files} is what
|
||||
you want: it compiles the schematic and writes the files directly, with no
|
||||
chip connection required. \emph{Link Compile Download} instead needs a live
|
||||
communication channel to a chip --- either the classic USBi/ICP dongle, or
|
||||
DigiRadio's own TCP:8086 SigmaStudio bridge (Section~\ref{sec:adau1701-sigmastudio-tcp})
|
||||
when connecting live to a running board.
|
||||
\end{drnote}
|
||||
|
||||
Reference in New Issue
Block a user