From 0e25c4cc1a3dcedabb04961a0d2ba9e77ec8c376 Mon Sep 17 00:00:00 2001 From: Michele Bigi Date: Mon, 6 Jul 2026 16:10:52 +0200 Subject: [PATCH] Document Si4684 driver, TunerService, and tuner HTTP API (0.4.0). Adds ch-si4684 and updates API/class reference chapters for slice 4. Co-authored-by: Cursor --- Software/docs/manual/ch-api.tex | 85 ++++++++- Software/docs/manual/ch-classes.tex | 76 ++++++-- Software/docs/manual/ch-firmware.tex | 35 ++-- Software/docs/manual/ch-si4684.tex | 258 +++++++++++++++++++++++++++ Software/docs/manual/manual.tex | 1 + 5 files changed, 431 insertions(+), 24 deletions(-) create mode 100644 Software/docs/manual/ch-si4684.tex diff --git a/Software/docs/manual/ch-api.tex b/Software/docs/manual/ch-api.tex index 1f2eecd..ced397a 100644 --- a/Software/docs/manual/ch-api.tex +++ b/Software/docs/manual/ch-api.tex @@ -6,7 +6,7 @@ implemented in \texttt{SetupWebServer}. Request bodies are parsed into domain types in the pure core (\texttt{components/core}) before any persistence or driver call. Exact C++ signatures live in the generated Doxygen output under \texttt{docs/api/}; this chapter documents the -wire protocol and behaviour as shipped in firmware~0.2.0 (Slices~1--2). +wire protocol and behaviour as shipped in firmware~0.4.0 (Slices~1--4). \section{Transport and reachability} @@ -36,7 +36,7 @@ Returns a health-check DTO serialised by \begin{drnote}[Response schema] \begin{drcode}[JSON] -{"status":"ok","fw":"0.2.0"} +{"status":"ok","fw":"0.4.0"} \end{drcode} \begin{itemize} \item \texttt{status} --- coarse indicator; \texttt{ok} when the @@ -93,10 +93,89 @@ HTTP status: \textbf{200 OK} on save success; \textbf{400 Bad Request} for parse/validation failures; \textbf{500 Internal Server Error} when NVS persistence fails. +\subsection{\texttt{GET /api/tuner/status}} +\label{sec:api-tuner-status} + +Returns a tuner snapshot serialised by +\texttt{core::serializeTunerStatusJson()} from \texttt{core::TunerStatus}. +The handler calls \texttt{tuner::TunerService::refreshStatus()}. + +\begin{drnote}[Response schema (DAB example)] +\begin{drcode}[JSON] +{"booted":true,"band":"dab","locked":true,"volume":63, + "dab":{"freq_index":12,"fic_quality":80,"cnr_db":25},"fm":null} +\end{drcode} +For FM, \texttt{fm} carries \texttt{frequency\_khz}, \texttt{rssi\_dbuv}, +\texttt{snr\_db}, and \texttt{stereo}; \texttt{dab} is \texttt{null}. +\end{drnote} + +HTTP status: \textbf{200 OK}; \textbf{500} with +\texttt{\{"status":"error","reason":...\}} on driver failure; +\textbf{503} when the tuner service is unavailable. + +\subsection{\texttt{GET /api/tuner/services}} +\label{sec:api-tuner-services} + +Lists DAB programmes for the current ensemble via +\texttt{TunerService::listDabServices()}. + +\begin{drnote}[Response schema] +\begin{drcode}[JSON] +{"services":[{"service_id":12345,"component_id":1,"label":"BBC R1"}]} +\end{drcode} +\end{drnote} + +HTTP status: \textbf{200 OK}; \textbf{409 Conflict} when the list cannot be +fetched (wrong band, empty ensemble, hardware error). + +\subsection{\texttt{POST /api/tuner/tune}} +\label{sec:api-tuner-tune} + +Tunes to a DAB ensemble or FM frequency. Body parsed by +\texttt{core::parseTunerTuneJson()}. + +\begin{drnote}[Request schema] +\begin{drcode}[JSON] +{"band":"dab","freq_index":12} +\end{drcode} +or +\begin{drcode}[JSON] +{"band":"fm","frequency_khz":101500} +\end{drcode} +DAB \texttt{freq\_index} is 0--37; FM \texttt{frequency\_khz} is +64\,000--108\,000. +\end{drnote} + +On success returns the updated status JSON (same shape as +\texttt{GET /api/tuner/status}). HTTP status: \textbf{200 OK}; +\textbf{400} for invalid JSON; \textbf{409} for tune failures. + +\subsection{\texttt{POST /api/tuner/play}} +\label{sec:api-tuner-play} + +Starts a DAB audio service. Body parsed by +\texttt{core::parseTunerPlayJson()}. + +\begin{drnote}[Request schema] +\begin{drcode}[JSON] +{"service_id":12345,"component_id":1} +\end{drcode} +\end{drnote} + +Success response: \texttt{\{"status":"playing"\}}. HTTP status: +\textbf{200 OK}; \textbf{409} when playback cannot start. + +\subsection{\texttt{POST /api/tuner/seek}} +\label{sec:api-tuner-seek} + +Seeks FM upward (no request body). Returns +\texttt{\{"frequency\_khz":...\}} on success. HTTP status: \textbf{200 OK}; +\textbf{409} on seek failure. + \section{Boot and network state machine} \label{sec:api-boot-flow} -At boot, \texttt{net::NetBootstrap::start()} consults +At boot, \texttt{net::NetBootstrap::start(store, tuner)} consults \texttt{ISecureStore::hasWifiCredentials()}: \begin{enumerate} diff --git a/Software/docs/manual/ch-classes.tex b/Software/docs/manual/ch-classes.tex index 37ab567..1a259cf 100644 --- a/Software/docs/manual/ch-classes.tex +++ b/Software/docs/manual/ch-classes.tex @@ -50,15 +50,17 @@ RAII wrapper around the ESP-IDF Wi-Fi stack that starts and stops the configured SoftAP. Imperative shell; no business logic. \section{SetupWebServer}\label{cls:SetupWebServer} -Minimal HTTP server: gzipped setup UI, \texttt{GET /api/health}, and -\texttt{POST /api/wifi} for provisioning. JSON parsing and serialisation -delegate to the pure core; credentials persist via \texttt{ISecureStore}. +Minimal HTTP server: gzipped setup UI, \texttt{GET /api/health}, +\texttt{POST /api/wifi}, and tuner routes (\texttt{/api/tuner/*}). +JSON parsing and serialisation delegate to the pure core; credentials +persist via \texttt{ISecureStore}; tuner operations via +\texttt{tuner::TunerService}. \section{NetBootstrap}\label{cls:NetBootstrap} -Owns network resources for setup or STA mode. \texttt{start(store)} -initialises the platform, joins stored Wi-Fi when credentials exist, or -falls back to the \texttt{DigiRadio-setup} SoftAP. Must outlive -\texttt{app\_main} for the process lifetime. +Owns network resources for setup or STA mode. +\texttt{start(store, tuner)} initialises the platform, joins stored Wi-Fi +when credentials exist, or falls back to the \texttt{DigiRadio-setup} +SoftAP. Must outlive \texttt{app\_main} for the process lifetime. % ------------------------------------------------------------------ % Domain core + secure store (Slice 2) @@ -92,8 +94,60 @@ are stored as NVS strings and never logged. Production should enable NVS encryption using the reserved \texttt{nvs\_keys} partition. % ------------------------------------------------------------------ -% Future slices (drivers, services) +% Hardware drivers (Slice 3) % ------------------------------------------------------------------ -% \section{Si4684Driver}\label{cls:Si4684Driver} -% \section{TunerService}\label{cls:TunerService} -% ... + +\section{IFirmwareBlobReader}\label{cls:IFirmwareBlobReader} +Abstract streaming reader for firmware blobs embedded in flash. The Si4684 +driver uses it to HOST\_LOAD patch and application images in bounded SPI +chunks without allocating the full image on the heap. Host tests use the +same interface over in-memory buffers. + +\section{EmbeddedBlobReader}\label{cls:EmbeddedBlobReader} +Non-owning \texttt{IFirmwareBlobReader} over a contiguous byte range (linker +symbols from \texttt{EMBED\_FILES} or test data). Implements offset-based +\texttt{read()} with truncation at end-of-blob. + +\section{Si4684EmbeddedImages}\label{cls:Si4684EmbeddedImages} +Owns \texttt{EmbeddedBlobReader} views over \texttt{rom\_patch\_016.bin}, +\texttt{dab\_firmware.bin}, and \texttt{fm\_firmware.bin}. Constructed once; +passed to \texttt{Si4684Driver}. \texttt{applicationImage(Si4684Band)} selects +DAB or FM. + +\section{Si4684Driver}\label{cls:Si4684Driver} +Full SPI driver for the Si4684 DAB+/FM tuner (Chapter~\ref{ch:si4684}). + +\texttt{boot(Si4684Band)} runs AN649 HOST\_LOAD, configures I\textsuperscript{2}S +and band-specific properties, and records \texttt{loadedBand()}. After boot the +driver exposes FM tuning/seek/RSQ/RDS, DAB ensemble tuning, digital service list +fetch, and \texttt{startDabService}. Property access (\texttt{setProperty}, +\texttt{setVolume}) and diagnostics (\texttt{getPartInfo}, \texttt{getSysState}) +are included. Wrong-band calls return \texttt{Si4684Error::WrongBand}. +Register-level opcodes remain private; see \texttt{Si4684Types.hpp} for status +DTOs. + +\section{Adau1701Driver}\label{cls:Adau1701Driver} +RAII I2C driver for the ADAU1701 SigmaDSP. \texttt{boot()} asserts RESET\#, +initialises the shared I2C bus, and replays the SigmaStudio export from +\texttt{Firmware/ADAU1701-Firmware/} on every power-up (no EEPROM self-boot +on DigiRadio). + +% ------------------------------------------------------------------ +% Application services (Slice 4) +% ------------------------------------------------------------------ + +\section{ITuner}\label{cls:ITuner} +Abstract tuner boundary in the pure core. Defines boot, band selection, +status readout, FM/DAB tuning, service list, playback, and volume without +ESP-IDF types. \texttt{si4684::Si4684Tuner} implements it on device; host +tests can use fakes. + +\section{TunerService}\label{cls:TunerService} +Application service exposing intent-level tuner operations to HTTP and +future UI. Holds a reference to \texttt{core::ITuner}, tracks last tune +target and volume, and maps driver failures to \texttt{core::TunerError}. + +\section{Si4684Tuner}\label{cls:Si4684Tuner} +\texttt{ITuner} adapter over \texttt{Si4684Driver}. Translates domain calls +into SPI commands and maps \texttt{Si4684Error} to \texttt{TunerError}. +Constructed once in \texttt{HardwareBootstrap} alongside the driver. diff --git a/Software/docs/manual/ch-firmware.tex b/Software/docs/manual/ch-firmware.tex index df0c4f7..b27277e 100644 --- a/Software/docs/manual/ch-firmware.tex +++ b/Software/docs/manual/ch-firmware.tex @@ -125,16 +125,9 @@ verified against reference values in host tests. At power-up the driver follows the documented boot sequence: power on, load the patch/bootloader, load the firmware image (FM or DAB), then boot. Firmware images are large and are streamed to the chip in bounded -chunks from flash rather than buffered whole in RAM. - -\begin{drref}[Datasheet] -The exact power-up, patch, image-load, and boot command sequence follows -the Si468x programming guide (AN649). Each step in the driver cites the -relevant section; no command byte is issued without a documented source. -\end{drref} The public -interface is intent-level (\texttt{powerUp}, \texttt{loadImage}, -\texttt{tuneTo}, \texttt{readRsq}); register-level detail is private to -the driver. +chunks from flash rather than buffered whole in RAM. See +Chapter~\ref{ch:si4684} for blob sources, uGreen extraction, and the full +\texttt{Si4684Driver} API (tuning, RSQ, DAB service list). \paragraph{ADAU1701 (DSP).} The board carries no self-boot EEPROM. Instead, the ESP32 writes the @@ -184,6 +177,28 @@ values cannot be logged or implicitly converted to a string; buffers are cleared on destruction. Production builds should enable NVS encryption at rest (see Chapter~\ref{sec:api-storage}). +\section{Companion-chip boot at power-up} +\label{sec:fw-chip-boot} + +The ESP32-S3 loads both audio companion chips from assets under +\texttt{Software/Firmware/} during \texttt{app\_main}, before network +bring-up: + +\begin{enumerate} + \item \textbf{Si4684} (SPI): ROM patch \texttt{rom\_patch\_016.bin}, then either + DAB image \texttt{dab\_firmware.bin} or FM image \texttt{fm\_firmware.bin}, + following AN649 (Chapter~\ref{ch:si4684}). DAB blob default from PE5PVB; FM + from eval pack or uGreen \texttt{radio\_cli}. Blobs are local-only + (\texttt{.gitignore}); embedded via ESP-IDF \texttt{EMBED\_FILES}. + \item \textbf{ADAU1701} (I\textsuperscript{2}C): SigmaStudio export + (\texttt{DigiRadio\_IC\_1.h}) replayed through + \texttt{SIGMA\_WRITE\_REGISTER\_BLOCK} after hardware reset. The DSP + program lives in RAM only; download runs on every boot. +\end{enumerate} + +If either driver returns an error, the firmware logs the failure and stops +before starting Wi-Fi (fail-closed bring-up). + \section{Error-handling model} \label{sec:fw-errors} diff --git a/Software/docs/manual/ch-si4684.tex b/Software/docs/manual/ch-si4684.tex new file mode 100644 index 0000000..fc10b4d --- /dev/null +++ b/Software/docs/manual/ch-si4684.tex @@ -0,0 +1,258 @@ +% ============================================================ +% DigiRadio — Manual chapter: Si4684 tuner +% ============================================================ + +\chapter{Si4684 DAB+/FM Tuner} +\label{ch:si4684} + +The Skyworks Si4684 is the primary RF front-end of DigiRadio: it demodulates +DAB/DAB+ and FM, decodes RDS, and delivers PCM over I\textsuperscript{2}S to +the ADAU1701. This chapter documents how firmware images are obtained and kept +local, how the chip is booted on the ESP32-S3, and how \texttt{Si4684Driver} +exposes every day-to-day operation without leaking register-level details to +application code. + +\section{Role in the audio chain} +\label{sec:si4684-role} + +After boot the Si4684 runs as an I\textsuperscript{2}S master at +44.1\,kHz stereo. The ESP32 loads proprietary application firmware into chip +RAM at every cold start (there is no self-boot EEPROM on DigiRadio). Tuning, +service selection, and signal-quality reads all go through +\texttt{si4684::Si4684Driver}; higher layers (\texttt{TunerService}, web UI) +will depend on that class rather than issuing SPI transactions directly. + +\begin{drref}[Programming guide] +Command opcodes, property IDs, and reply layouts follow Skyworks application +note \textbf{AN649} (Si468x programming guide). The DigiRadio driver aligns +with the PE5PVB/SI4684-DAB-Receiver reference for DAB and with community FM +images for the FM application blob. +\end{drref} + +\section{Firmware images} +\label{sec:si4684-firmware} + +Three binary blobs live under \texttt{Firmware/Si4684-Firmware/}. They are +\textbf{not} committed to the public Git repository (proprietary Skyworks / +uGreen licence); \texttt{.gitignore} keeps them on the developer machine only. + +\begin{table}[htbp] + \centering + \begin{tabular}{@{}llp{6.2cm}@{}} + \toprule + \textbf{Local file} & \textbf{Typ.\ size} & \textbf{Source} \\ + \midrule + \texttt{rom\_patch\_016.bin} & 5796 B & + ROM patch (\texttt{rom00\_patch.016.bin}); refreshed from + PE5PVB or uGreen \texttt{radio\_cli}. \\ + \texttt{dab\_firmware.bin} & $\sim$517--497 KB & + DAB application image; default from PE5PVB header extract; optional + uGreen \texttt{dab\_radio\_6\_0\_6.bin}. \\ + \texttt{fm\_firmware.bin} & $\sim$530 KB & + FM/HD application; eval CD, dabpi \texttt{si46xx\_firmware/}, or uGreen + \texttt{fmhd\_radio\_5\_1\_3.bin}. \\ + \bottomrule + \end{tabular} + \caption{Si4684 firmware blobs (local only).} + \label{tab:si4684-blobs} +\end{table} + +\subsection{Where images come from} +\label{sec:si4684-sources} + +Community projects name the same Skyworks files differently; none of them +redistribute the binaries in git: + +\begin{itemize} + \item \textbf{PE5PVB/SI4684-DAB-Receiver} --- DAB image and ROM patch as + C arrays (\texttt{firmware.h}, \texttt{Si468xROM.h}). Safe to automate. + \item \textbf{uGreen DABBoard} (\url{https://ugreen.eu/downloads/}) --- + \texttt{Files\_v16.zip} embeds FM, DAB, and patch inside + \texttt{radio\_cli}; use \texttt{tools/extract\_ugreen\_radio\_cli.py}. + \item \textbf{hitech95/si468x\_dab\_receiver} --- Linux driver only; device + tree references \texttt{si468x/fmhd\_radio\_5\_1\_0.bin} but does not + ship the files (closed source). + \item \textbf{PhilBladen/Radio} --- STM32 reference using \emph{external} + SPI flash (\texttt{FLASH\_LOAD}); different hardware path from DigiRadio's + \texttt{HOST\_LOAD} flow. +\end{itemize} + +\begin{drcaution}[Licence] +Do not push \texttt{*.bin} firmware to GitHub. Obtain images from your own +eval board, uGreen customer download, or dabpi folder; keep them in +\texttt{Firmware/Si4684-Firmware/} locally. +\end{drcaution} + +\subsection{Refreshing blobs} +\label{sec:si4684-refresh} + +\begin{verbatim} +# DAB + patch from PE5PVB (always safe to re-run): +python3 tools/fetch_si4684_firmware.py --dab-only + +# FM from uGreen radio_cli (Files_v16.zip): +python3 tools/fetch_si4684_firmware.py \ + --from-ugreen-radio-cli ~/Downloads/Files_v16.zip + +# All three blobs from uGreen (overrides PE5PVB DAB): +python3 tools/fetch_si4684_firmware.py \ + --from-ugreen-radio-cli ~/Downloads/Files_v16.zip --ugreen-all + +# FM from dabpi / Skyworks eval folder: +python3 tools/fetch_si4684_firmware.py --si46xx-dir /path/to/si46xx_firmware +\end{verbatim} + +Low-level helpers: \texttt{tools/extract\_si4684\_blob.py} (C header or copy), +\texttt{tools/extract\_ugreen\_radio\_cli.py} (ELF symbol scrape). + +\section{Boot sequence (HOST\_LOAD)} +\label{sec:si4684-boot} + +DigiRadio follows AN649 ``cold start with HOST\_LOAD'' (same as PE5PVB), not +the \texttt{FLASH\_LOAD} path used by boards with a pre-programmed SST25V. + +\begin{figure}[htbp] + \centering + \begin{tikzpicture}[ + step/.style={draw, rounded corners, minimum width=9cm, + minimum height=0.9cm, align=center, font=\small}, + >={Latex}, node distance=3mm] + \node[step, fill=black!6] (rst) {Hardware reset (RST\#)}; + \node[step, fill=black!6, below=of rst] (pu) + {POWER\_UP (crystal / clock args)}; + \node[step, fill=black!6, below=of pu] (li1) {LOAD\_INIT}; + \node[step, fill=black!8, below=of li1] (patch) + {HOST\_LOAD \texttt{rom\_patch\_016.bin} (124 B chunks)}; + \node[step, fill=black!6, below=of patch] (li2) {LOAD\_INIT}; + \node[step, fill=black!8, below=of li2] (img) + {HOST\_LOAD \texttt{dab\_} or \texttt{fm\_firmware.bin} + (2044 B chunks)}; + \node[step, fill=black!6, below=of img] (boot) {BOOT}; + \node[step, fill=black!10, below=of boot] (cfg) + {Properties: I\textsuperscript{2}S 44.1 kHz, RDS/DAB FE, volume}; + \foreach \a/\b in {rst/pu, pu/li1, li1/patch, patch/li2, li2/img, + img/boot, boot/cfg} { + \draw[->] (\a) -- (\b); + } + \end{tikzpicture} + \caption{Si4684 boot flow on DigiRadio (AN649 / PE5PVB).} + \label{fig:si4684-boot} +\end{figure} + +Images are embedded in the ESP32 flash partition via ESP-IDF +\texttt{EMBED\_FILES} and streamed through \texttt{IFirmwareBlobReader} so the +full $\sim$1\,MB of patch + DAB + FM never has to fit in RAM at once. Switching +band (\texttt{Si4684Band::Fm} $\leftrightarrow$ \texttt{Dab}) performs reset and +a complete reload of patch + the other application image. + +\section{Si4684Driver API} +\label{sec:si4684-driver} + +\texttt{Si4684Driver} owns SPI, implements boot, and exposes intent-level +methods grouped below. All return \texttt{std::expected}; FM +calls fail with \texttt{WrongBand} if the FM image is not loaded, and vice +versa for DAB. + +\subsection{Bring-up and diagnostics} + +\begin{table}[htbp] + \centering + \begin{tabular}{@{}ll@{}} + \toprule + \textbf{Method} & \textbf{Purpose} \\ + \midrule + \texttt{boot(Si4684Band)} & Cold start + default properties \\ + \texttt{isBooted()}, \texttt{loadedBand()} & State query \\ + \texttt{getPartInfo()} & Chip ID + firmware version \\ + \texttt{getSysState()} & Running application type \\ + \texttt{setProperty(id, value)} & Generic SET\_PROPERTY \\ + \texttt{setVolume(0--63)} & Audio attenuator \\ + \bottomrule + \end{tabular} + \caption{Si4684 bring-up and property access.} +\end{table} + +\subsection{FM operations} + +Requires \texttt{boot(Si4684Band::Fm)}. + +\begin{itemize} + \item \texttt{tuneFm(frequencyKhz)} --- FM\_TUNE\_FREQ, waits for STC. + \item \texttt{seekFm(up, wrap)} --- FM\_SEEK\_START; returns tuned kHz. + \item \texttt{readFmRsq()} --- RSSI, SNR, stereo flag, validity. + \item \texttt{readFmRds()} --- last RDS group blocks A--D. +\end{itemize} + +\subsection{DAB operations} + +Requires \texttt{boot(Si4684Band::Dab)}. The default Band~III frequency plan +(38 channels, Table~\ref{tab:si4684-dab-plan}) is installed automatically +after boot. + +\begin{itemize} + \item \texttt{installDefaultDabFrequencyPlan()} --- DAB\_SET\_FREQ\_LIST + (also called from boot). + \item \texttt{tuneDab(freqIndex)} --- tune ensemble by index 0--37. + \item \texttt{readDabDigRadStatus()} --- FIC quality, CNR, lock. + \item \texttt{readDabEventStatus()} --- service-list-ready flag. + \item \texttt{fetchDabServiceList()} --- parsed services + labels. + \item \texttt{startDabService(serviceId, componentId)} --- begin audio + decode (START\_DIGITAL\_SERVICE). +\end{itemize} + +\begin{table}[htbp] + \centering + \small + \begin{tabular}{@{}cl@{}} + \toprule + \textbf{Index} & \textbf{Centre frequency (kHz)} \\ + \midrule + 0--3 & 174928 -- 180064 (5A--5D) \\ + 4--7 & 181936 -- 187072 (6A--6D) \\ + 8--11 & 188928 -- 194064 (7A--7D) \\ + 12--15 & 195936 -- 201072 (8A--8D) \\ + 16--19 & 202928 -- 208064 (9A--9D) \\ + 20--23 & 209936 -- 215072 (10A--10D) \\ + 24--27 & 216928 -- 222064 (11A--11D) \\ + 28--31 & 223936 -- 229072 (12A--12D) \\ + 32--35 & 230784 -- 235776 (13A--13D) \\ + 36--37 & 237488 -- 239200 (13E--13F) \\ + \bottomrule + \end{tabular} + \caption{DAB Band III plan (\texttt{kDefaultDabFrequencyKhz}).} + \label{tab:si4684-dab-plan} +\end{table} + +\subsection{Typical DAB session} + +\begin{enumerate} + \item \texttt{boot(Dab)} at power-up (already done in + \texttt{HardwareBootstrap}). + \item \texttt{tuneDab(index)} for the desired ensemble. + \item Poll \texttt{readDabDigRadStatus()} until FIC quality $> 0$. + \item \texttt{fetchDabServiceList()} when + \texttt{readDabEventStatus().serviceListReady}. + \item \texttt{startDabService(serviceId, componentId)} for the chosen + programme; audio appears on I\textsuperscript{2}S. +\end{enumerate} + +\section{Integration at power-up} +\label{sec:si4684-integration} + +\texttt{main/hardware\_bootstrap.cpp} constructs a static +\texttt{Si4684EmbeddedImages}, \texttt{Si4684Driver}, and +\texttt{Si4684Tuner}, calls \texttt{boot(Si4684Band::Dab)} before Wi-Fi, +then boots the ADAU1701. Failure is fail-closed (logged, no network start). +\texttt{main/main.cpp} wraps the tuner adapter in +\texttt{tuner::TunerService} and passes it to \texttt{NetBootstrap::start()} +so HTTP routes under \texttt{/api/tuner/*} can tune and play at runtime. + +\section{Further reading} +\label{sec:si4684-reading} + +\begin{itemize} + \item Skyworks AN649 --- command and property reference. + \item \texttt{Firmware/Si4684-Firmware/README.md} --- blob refresh cheatsheet. + \item PE5PVB \texttt{si4684.cpp} --- DAB service list and MOT (not yet ported). + \item uGreen \texttt{radio\_cli\_RELEASE\_NOTES.md} --- embedded firmware versions. +\end{itemize} diff --git a/Software/docs/manual/manual.tex b/Software/docs/manual/manual.tex index 460080a..832ae09 100644 --- a/Software/docs/manual/manual.tex +++ b/Software/docs/manual/manual.tex @@ -45,6 +45,7 @@ \include{ch-intro} \include{ch-hardware} \include{ch-firmware} +\include{ch-si4684} \include{ch-api} \include{ch-classes} \include{ch-build}