Files
DigiRadio/Software/docs/manual/ch-hardware.tex
T
micheleandCursor fcda4ef151 Fix manual typographic overflow in tables and API chapter.
Add wrapping table columns, breakable paths, and ragged callout boxes in digiradio-manual.sty, then reflow long endpoint headings, JSON examples, and hardware/driver tables to stay within page margins.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-08 15:02:30 +02:00

502 lines
20 KiB
TeX

\chapter{Hardware Overview}
\label{ch:hardware}
This chapter describes the board in detail: the design choices behind it,
each integrated circuit and how it is controlled, the bus architecture,
and the inter-chip connections. The complete hardware design ---
schematics, PCB, Gerbers, and bill of materials --- is published in the
repository under the CERN-OHL-S v2 licence.
\section{Design philosophy}
\label{sec:hw-philosophy}
Every major choice on the board serves audio quality and
reproducibility.
\begin{drkey}[The four-chip split]
Rather than a single all-in-one radio IC, DigiRadio separates concerns:
a dedicated tuner for reception, a dedicated DSP for audio conditioning,
a dedicated Bluetooth module for the wireless codec, and a general-purpose
host to coordinate them. Each stage can be understood, measured, and
improved on its own.
\end{drkey}
The consequences of that split run through the rest of the board: a
control host that speaks several buses, a clean power tree that keeps the
tuner's analogue supplies away from digital noise, and careful RF layout
so the two 2.4\,GHz radios do not interfere.
\section{System block diagram}
\label{sec:hw-block}
Four devices are coordinated by the ESP32-S3. The tuner produces the
audio stream, the DSP conditions and mixes it, and the Bluetooth module
transmits it; the host manages all three and provides the network
interface.
\begin{table}[htbp]
\centering
\small
\begin{tabular}{@{}L{2.6cm}L{4.2cm}L{2.6cm}L{3.8cm}@{}}
\drhead Device & Role & Control bus & Firmware \\
\midrule
Si4684 & DAB+/FM tuner & SPI & host-loaded image \\
ADAU1701 & Audio DSP (EQ + mixer) & I\textsuperscript{2}C & host-loaded RAM \\
ESP32-S3-WROOM-1 & Host, Wi-Fi/BLE & --- & application FW \\
FSC-BT1035 & Bluetooth 5.2 (aptX Ad.) & UART (AT) & vendor FW + config \\
\bottomrule
\end{tabular}
\caption{Principal integrated circuits, their control bus, and how each
receives its firmware or configuration.}
\label{tab:hw-ics}
\end{table}
\section{The tuner: Si4684}
\label{sec:hw-si4684}
The Si4684 is a single-chip DAB+/FM receiver front-end. It delivers the
decoded audio stream to the DSP and reports signal-quality metrics to the
host.
\subsection{Control interface}
The device is controlled through a command/response protocol over its
host bus. The host issues a command, then polls a clear-to-send (CTS)
status bit before reading the response; the driver validates that status
byte before trusting any returned payload.
\begin{drkey}[SPI for the tuner]
The tuner needs a large firmware image loaded at every power-up
(Section~\ref{sec:hw-si4684-fw}). SPI offers substantially higher
throughput than I\textsuperscript{2}C, so on DigiRadio the tuner uses
\textbf{SPI}, keeping boot time short, while the low-rate DSP control uses
a separate I\textsuperscript{2}C bus.
\end{drkey}
\subsection{Firmware image upload}
\label{sec:hw-si4684-fw}
The Si4684 holds no application firmware of its own at reset. At power-up
the host loads a bootloader/patch and then the firmware image for the
desired mode (FM or DAB). These images are large, so the driver streams
them to the chip in bounded chunks read from the ESP32's flash, rather
than buffering a whole image in RAM.
\begin{drref}[Datasheet]
The exact power-up, patch, image-load, and boot command sequence follows
the Si468x programming guide (AN649). No command byte is issued without a
documented source, and each step in the driver cites its section.
\end{drref}
\section{The audio DSP: ADAU1701}
\label{sec:hw-adau}
The ADAU1701 is a SigmaDSP audio processor. In DigiRadio it performs
equalisation and mixes the tuner audio with the ESP32 audio source before
the signal reaches the Bluetooth stage.
\subsection{Control and program loading}
The DSP is controlled over I\textsuperscript{2}C. Its signal-processing
program is designed in SigmaStudio and exported as a sequence of register
writes (control settings, program RAM, and parameter RAM). The full
SigmaStudio schematic, signal chain, and runtime parameter map are
documented in Chapter~\ref{ch:sigmastudio}. Driver boot, safeload API,
\texttt{AudioService}, and HTTP integration are in
Chapter~\ref{ch:adau1701}.
\begin{drkey}[RAM boot, no EEPROM]
The board deliberately omits the ADAU1701 self-boot EEPROM. Instead, the
ESP32 writes the exported program into the DSP's RAM at \emph{every} boot.
This keeps the audio processing under host control and field-updatable ---
a new EQ or mixer configuration is a firmware update, not a chip
re-programming.
\end{drkey}
\subsection{Click-free parameter updates}
Runtime changes --- adjusting an EQ band, changing a mix level --- are
applied through the ADAU1701 safeload mechanism, which updates parameter
cells atomically between audio samples. Writing parameter cells directly
while audio plays would produce audible clicks and is not done.
\section{The Bluetooth module: FSC-BT1035}
\label{sec:hw-bt1035}
The FSC-BT1035 (Qualcomm QCC3056) is a Bluetooth~5.2 audio transmitter
with aptX, aptX~HD, and aptX~Adaptive support --- the high-resolution
codecs that make the wireless output hi-fi rather than merely convenient.
\subsection{Control interface}
The module is controlled with AT commands over UART, with hardware flow
control (RTS/CTS). The host sends commands and parses the module's
responses explicitly, treating timeouts as errors. Some settings are held
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=1}). See Chapter~\ref{ch:bt1035}, Section~\ref{sec:bt1035-i2s}.
\end{drcaution}
\section{The host: ESP32-S3}
\label{sec:hw-esp32}
The ESP32-S3-WROOM-1 coordinates the whole system. It loads the tuner and
DSP firmware at boot, controls all three companion chips over their
respective buses, serves the configuration web interface, and provides
Wi-Fi connectivity. Its dual-core processor and generous RAM comfortably
handle the firmware images and the network stack alongside the control
tasks.
\section{Bus architecture}
\label{sec:hw-buses}
The host speaks several interfaces, each chosen for its traffic:
\begin{table}[htbp]
\centering
\begin{tabular}{@{}L{2.2cm}L{3.6cm}L{7.2cm}@{}}
\drhead Bus & Devices & Purpose \\
\midrule
SPI & Si4684 & fast firmware-image upload, tuner control \\
I\textsuperscript{2}C & ADAU1701, 24AA025E48 EEPROM & DSP control, device identity \\
UART & FSC-BT1035 & AT command / response (with RTS/CTS) \\
I\textsuperscript{2}S & Si4684, ESP32, ADAU1701, BT1035 & audio (ADAU is master) \\
\bottomrule
\end{tabular}
\caption{Interface assignment and rationale.}
\label{tab:hw-buses}
\end{table}
\section{Power}
\label{sec:hw-power}
The board is powered from USB-C. An AP63203 buck converter generates the
main rail from the USB input, feeding the digital and analogue sections.
The tuner's sensitive supplies are derived and filtered separately to keep
RF performance clean.
\section{RF and antennas}
\label{sec:hw-rf}
Two 2.4\,GHz radios are present --- the ESP32-S3 and the Bluetooth module.
Their antennas are placed on opposite diagonal corners of the board to
maximise separation and minimise mutual desense. Each module keeps its
antenna keep-out clear of copper on all layers. The PCB is a six-layer
stack-up with controlled impedance on the USB and RF sections.
\section{Inter-chip connections (GPIO map)}
\label{sec:hw-gpio}
This section is the authoritative wiring reference between the ESP32-S3
and the companion chips. The firmware pin definitions
(\texttt{board\_pins.hpp}) must match these tables exactly.
\subsection{System and control lines}
\begin{table}[htbp]
\centering
\begin{tabular}{@{}L{2.2cm}L{3.6cm}L{7.2cm}@{}}
\drhead Signal & ESP32-S3 GPIO & Notes \\
\midrule
USB D$-$ & GPIO19 & native USB \\
USB D$+$ & GPIO20 & native USB \\
Reset / boot button & GPIO0 & strapping pin \\
\bottomrule
\end{tabular}
\caption{System and control lines.}
\label{tab:hw-sys}
\end{table}
\subsection{Si4684 tuner (SPI)}
\begin{table}[htbp]
\centering
\small
\begin{tabular}{@{}L{2.4cm}L{2.2cm}L{2.8cm}L{5.8cm}@{}}
\drhead Signal & Si4684 pin & ESP32-S3 GPIO & Notes \\
\midrule
SCLK & pin 30 & GPIO13 & \\
MOSI & pin 31 & GPIO12 & \\
MISO & pin 32 & GPIO9 & \\
SSB (CS) & pin 29 & GPIO8 & chip select, active-low \\
RSTB\# & pin 4 & GPIO38 & active-low, ext.\ pull-down \\
INTB\# & pin 3 & GPIO39 & active-low, ext.\ pull-up \\
\bottomrule
\end{tabular}
\caption{Si4684 control and SPI lines.}
\label{tab:hw-si4684}
\end{table}
\subsection{ADAU1701 DSP (I\textsuperscript{2}C)}
\begin{table}[htbp]
\centering
\begin{tabular}{@{}L{2.2cm}L{3.6cm}L{7.2cm}@{}}
\drhead Signal & ADAU1701 pin & ESP32-S3 GPIO \\
\midrule
SDA & --- & GPIO4 \\
SCL & --- & GPIO5 \\
RESET\# & pin 5 & GPIO47 (active-low, ext.\ pull-up) \\
\bottomrule
\end{tabular}
\caption{ADAU1701 control (I\textsuperscript{2}C) and reset. The 7-bit
I\textsuperscript{2}C address is 0x34 (ADDR0 and ADDR1 tied to GND).}
\label{tab:hw-adau}
\end{table}
\subsection{Device-identity EEPROM (24AA025E48)}
A 24AA025E48 EEPROM shares the DSP's I\textsuperscript{2}C bus. Besides a
small general-purpose memory, it carries a factory-programmed, globally
unique EUI-48 identifier, which the firmware can read to give each unit a
stable identity --- for example a unique Bluetooth name or a device
serial number. Its 7-bit address is 0x52 (A0 to GND, A1 to 3V3).
\begin{table}[htbp]
\centering
\begin{tabular}{@{}L{2.2cm}L{3.6cm}L{7.2cm}@{}}
\drhead Device & 7-bit address & Set by \\
\midrule
ADAU1701 & 0x34 & ADDR0, ADDR1 = GND \\
24AA025E48 EEPROM & 0x52 & A0 = GND, A1 = 3V3 (no A2 pin) \\
\bottomrule
\end{tabular}
\caption{I\textsuperscript{2}C address map (shared bus).}
\label{tab:hw-i2c-addr}
\end{table}
\subsection{FSC-BT1035 Bluetooth}
\begin{table}[htbp]
\centering
\small
\begin{tabular}{@{}L{2.2cm}L{2.2cm}L{2.8cm}L{5.8cm}@{}}
\drhead Signal & BT1035 pin & ESP32-S3 GPIO & Direction \\
\midrule
SYS\_CTL & pin 34 & GPIO15 & ESP32 $\rightarrow$ BT \\
BT\_CTS & pin 15 & GPIO21 & flow control \\
BT\_RTS & pin 16 & GPIO14 & flow control \\
BT\_RX & pin 14 & GPIO40 & ESP32 TX $\rightarrow$ BT RX \\
BT\_TX & pin 13 & GPIO41 & BT TX $\rightarrow$ ESP32 RX \\
RESET & pin 8 & GPIO17 & ESP32 $\rightarrow$ BT \\
\bottomrule
\end{tabular}
\caption{FSC-BT1035 UART, control, and reset lines.}
\label{tab:hw-bt1035}
\end{table}
\subsection{Audio bus (I\textsuperscript{2}S)}
The audio path is a chip-to-chip I\textsuperscript{2}S bus with the
ADAU1701 acting as master. Table~\ref{tab:hw-i2s} lists the chip-to-chip
routing; Table~\ref{tab:hw-i2s-esp} lists the ESP32's own
I\textsuperscript{2}S source lines that feed the mixer.
\begin{table}[htbp]
\centering
\small
\begin{tabular}{@{}L{2.2cm}L{3.6cm}L{7.2cm}@{}}
\drhead Signal & Path & ADAU1701 / BT1035 pins \\
\midrule
SDATA\_IN0 & Si4684 $\rightarrow$ ADAU & MP0 (pin 11) \\
SDATA\_IN1 & ESP32 $\rightarrow$ ADAU & MP1 (pin 10) \\
SDATA\_OUT0 & ADAU $\rightarrow$ BT1035 & MP6 (pin 15) $\rightarrow$ pin 5 \\
LRCLK & ADAU $\rightarrow$ BT1035 & MP4 (pin 8) + MP10 (pin 16) $\rightarrow$ pin 7 \\
BCLK & ADAU $\rightarrow$ BT1035 & MP5 (pin 9) + MP11 (pin 19) $\rightarrow$ pin 4 \\
\bottomrule
\end{tabular}
\caption{I\textsuperscript{2}S audio routing (chip-to-chip). The
MP4/MP10 and MP5/MP11 pairs are electrically connected on the board.}
\label{tab:hw-i2s}
\end{table}
\begin{table}[htbp]
\centering
\begin{tabular}{@{}L{2.2cm}L{3.6cm}L{7.2cm}@{}}
\drhead Signal & ESP32-S3 GPIO & Direction \\
\midrule
BCLK & GPIO6 & in from ADAU (master) \\
LRCLK & GPIO7 & in from ADAU (master) \\
SDATA\_IN1 & GPIO16 & out $\rightarrow$ ADAU MP1 \\
\bottomrule
\end{tabular}
\caption{ESP32 I\textsuperscript{2}S source lines feeding the mixer. The
ESP32 is an I\textsuperscript{2}S slave (clocks in), transmitting
audio data. SDATA\_IN1 lands on ADAU MP1 (pin 10); GPIO16 is the
ESP32 module's physical pin 9.}
\label{tab:hw-i2s-esp}
\end{table}
\subsection{Completeness}
\label{sec:hw-gpio-open}
\begin{drnote}[Map complete]
The GPIO and I\textsuperscript{2}C maps are complete and match
\texttt{board\_pins.hpp}. No values remain open.
\end{drnote}
This section is the authoritative wiring reference for firmware bring-up:
the pin definitions in the source code must match it exactly.
\section{Design validation and critical checks}
\label{sec:hw-validation}
This section records the design-review checks performed against the
component datasheets before fabrication, chip by chip. Items marked
\emph{critical} can cause permanent damage or a non-functional board if
violated, and were verified explicitly.
\subsection{Si4684 tuner}
\label{sec:hw-val-si4684}
\begin{drcaution}[Critical --- RSTB and power sequencing]
The Si4684 datasheet requires that RSTB be held low during any power-supply
transition and remain asserted for 10\,\textmu s after all supplies are
stable; failing to do so \emph{may permanently damage the device}. On
DigiRadio, RSTB (GPIO38) has an external pull-down, so the chip powers up
held in reset until the ESP32 releases it. \textbf{Verified.} The firmware
must not drive RSTB high before the Si4684 supplies are stable.
\end{drcaution}
\begin{drnote}[Firmware bring-up]
RSTB is driven only in \texttt{Si4684Driver::boot()}
(Chapter~\ref{ch:si4684}): GPIO38 is configured as output with
\texttt{GPIO\_PULLDOWN\_ENABLE} so the net cannot glitch high while the pin
mode changes, then held low for 5\,ms and released. The internal pull-down
is \emph{not} redundant with the external resistor: the external pull-down
holds RSTB during board power-on before \texttt{app\_main}; the internal one
closes the brief window between \texttt{gpio\_config} and
\texttt{gpio\_set\_level(0)} where an output register default could otherwise
violate the datasheet sequencing rule. No other code touches GPIO38. Release
occurs only after all Si4684 supplies (VA, VIO, VCORE, VMEM) are stable,
satisfying the +10\,\textmu s requirement in practice.
\end{drnote}
\begin{table}[htbp]
\centering
\small
\begin{tabular}{@{}L{3.2cm}L{8.2cm}L{2.2cm}@{}}
\drhead Check & Requirement (datasheet) & Status \\
\midrule
RSTB low at power-up & held low until supplies stable +10\,\textmu s & verified (pull-down) \\
RSTB release (firmware) & not before supplies stable; boot pulse only & verified (driver) \\
RSTB glitch guard (firmware) &
\texttt{GPIO\_PULLDOWN\_ENABLE} in \texttt{gpio\_config} & verified \\
Core supplies at 1.8\,V & VA = VCORE = VMEM = 1.8\,V & verified \\
VIO level & 1.62--3.6\,V (3.3\,V to talk to ESP32) & verified \\
Bypass caps & 2.2\,nF + 1\,\textmu F per VIO/VMEM/VCORE rail & verified \\
SPI mode & Mode 0 or 3, up to 10\,MHz, SMODE = GND & verified \\
SSB framing (firmware) & SSB held low for the whole transaction & driver rule \\
INTB & interrupt line, external pull-up (GPIO39) & verified \\
\bottomrule
\end{tabular}
\caption{Si4684 design checks (datasheet references below).}
\label{tab:hw-val-si4684}
\end{table}
\begin{drref}[Datasheet]
Power sequencing and SPI framing: \drpath{Hardware/DATASHEET/SI4684-A10.pdf}.
The user must not pulse SSB high between bytes; SSB frames the whole
command/reply. Bypass-capacitor values and placement:
\drpath{Hardware/DATASHEET/AN851.pdf}, \emph{Si468x Schematic and Layout
Guide}. Boot and command protocol: AN649. Local copies:
\drpath{Hardware/DATASHEET/} (see \drpath{README.md}).
\end{drref}
The core, memory, and analogue rails run at 1.8\,V; only VIO is at 3.3\,V
to interface the ESP32. The 2.2\,nF and 1\,\textmu F bypass pairs are
placed close to VIO (pin~34), VMEM (pin~35), and VCORE (pin~37) as AN851
requires. The VHF antenna input follows the AN851 layout guidance (short,
narrow microstrip; ground-fill relief; ferrite beads near the connector).
\subsection{ADAU1701 DSP}
\label{sec:hw-val-adau}
\begin{drkey}[Master-clock loopback is mandatory, not optional]
For an ADAU1701 operating as I\textsuperscript{2}S master while receiving
data on its serial inputs, the datasheet requires OUTPUT\_LRCLK (MP10) and
OUTPUT\_BCLK (MP11) to be set to master mode and \emph{connected externally}
to INPUT\_LRCLK (MP4) and INPUT\_BCLK (MP5). DigiRadio wires exactly this
loopback (MP10$\rightarrow$MP4, MP11$\rightarrow$MP5). Without it the DSP
locks up when input data arrives.
\end{drkey}
\begin{table}[htbp]
\centering
\small
\begin{tabular}{@{}L{2.2cm}L{3.6cm}L{7.2cm}@{}}
\drhead Check & Requirement (datasheet) & Status \\
\midrule
Clock loopback & MP10$\rightarrow$MP4, MP11$\rightarrow$MP5 wired & verified \\
Output master & serial output port in Master Mode & verified \\
MCLK ratio & exactly 256\,$\times$\,f\textsubscript{S} & verified \\
MCLK value & 12.288\,MHz oscillator (256\,$\times$\,48\,kHz) & verified \\
I\textsuperscript{2}C pull-ups & 2\,k\(\Omega\) on SDA/SCL (R16/R1) & verified \\
I\textsuperscript{2}C address & 0x34 (ADDR0 = ADDR1 = GND) & verified \\
Self-boot & disabled (host RAM load) & verified \\
\bottomrule
\end{tabular}
\caption{ADAU1701 design checks. Reference: ADAU1701 data sheet (Rev.~C),
serial-port master/slave section and I\textsuperscript{2}C port.}
\label{tab:hw-val-adau}
\end{table}
\begin{drref}[Datasheet]
Master-clock loopback and serial-port modes:
\texttt{Hardware/DATASHEET/adau1701.pdf}, Rev.~C, Table~63 and the serial-port
section. The master clock must be exactly 256\,$\times$\,f\textsubscript{S}.
I\textsuperscript{2}C lines require pull-up resistors on SDA and SCL.
DigiRadio uses \textbf{2\,k\(\Omega\)} (schematic R1/R16; ADAU1701 datasheet
recommends 2.2\,k\(\Omega\) --- acceptable at 3.3\,V).
\end{drref}
\begin{drnote}[I\textsuperscript{2}C pull-ups confirmed]
Schematic \texttt{DigitalRadio.pdf} and BOM list R1 (SCL) and R16 (SDA) as
2\,k\(\Omega\) to 3V3 on the shared ADAU1701/EEPROM bus.
\end{drnote}
\subsection{FSC-BT1035 (QCC3056)}
\label{sec:hw-val-bt1035}
\begin{table}[htbp]
\centering
\small
\begin{tabular}{@{}L{3.5cm}L{7.5cm}L{2.5cm}@{}}
\drhead Check & Requirement & Status \\
\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 \\
I\textsuperscript{2}S input & receives clocks from ADAU master (slave) & verified \\
Reset line & RESET (GPIO17) driven by ESP32 & verified \\
\bottomrule
\end{tabular}
\caption{FSC-BT1035 design checks (datasheets in \drpath{Hardware/DATASHEET/}).}
\label{tab:hw-val-bt1035}
\end{table}
\begin{drref}[Programming guide defaults]
Module defaults (Feasycom release 1.1.1): BR/EDR name \texttt{FSC-BT1035},
UART 115200/8/N/1, SSP on, auto-reconnect configurable via
\texttt{AT+AUTOCONN=0..15}. DigiRadio overrides the name from EEPROM identity
(\texttt{AT+NAME=<name>,0} disables the module MAC suffix).
\end{drref}
\subsection{System-level summary}
\label{sec:hw-val-summary}
\begin{table}[htbp]
\centering
\small
\begin{tabular}{@{}L{2.2cm}L{4.8cm}L{6.6cm}@{}}
\drhead Area & Item & Status \\
\midrule
Si4684 & RSTB pull-down, 1.8\,V rails, bypass caps, SPI & verified \\
Si4684 & RSTB release only in \texttt{Si4684Driver::boot()} & verified \\
ADAU1701 & clock loopback, master mode, 256$\times$f\textsubscript{S} & verified \\
ADAU1701 & I\textsuperscript{2}C 2\,k\(\Omega\) pull-ups (R1/R16) & verified \\
FSC-BT1035 & UART + flow control, I\textsuperscript{2}S slave & verified \\
Clocking & single 48\,kHz domain, ADAU master & verified \\
\bottomrule
\end{tabular}
\caption{Consolidated pre-fabrication validation status.}
\label{tab:hw-val-summary}
\end{table}
The consolidated pre-fabrication validation is complete for all
damage-class items (Si4684 power sequencing and supply levels) and the
shared I\textsuperscript{2}C bus.