pre-agent-version
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
\chapter{Building and Flashing}
|
||||
\label{ch:build}
|
||||
|
||||
The firmware is built with ESP-IDF; the hardware-free domain core also
|
||||
builds and is unit-tested on the host machine.
|
||||
|
||||
\section{Toolchain}
|
||||
|
||||
\begin{table}[htbp]
|
||||
\centering
|
||||
\begin{tabular}{@{}ll@{}}
|
||||
\drhead Item & Choice \\
|
||||
\midrule
|
||||
Framework & ESP-IDF v5.5.x (native) \\
|
||||
Language & C++23 (\texttt{-std=gnu++23}) \\
|
||||
Error model & \texttt{std::expected}; exceptions off \\
|
||||
Documentation & Doxygen (build must pass) \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\caption{Firmware toolchain.}
|
||||
\label{tab:build-toolchain}
|
||||
\end{table}
|
||||
|
||||
\section{Device build}
|
||||
|
||||
\begin{drcode}[Build, flash, monitor]
|
||||
idf.py set-target esp32s3
|
||||
idf.py build
|
||||
idf.py -p <port> flash monitor
|
||||
\end{drcode}
|
||||
|
||||
\section{Host unit tests}
|
||||
|
||||
The pure core is tested on the host, with no board attached. On macOS the
|
||||
tests need a C++23 standard library --- use a Homebrew LLVM (>= 18) or
|
||||
GCC~14 rather than the system Apple Clang.
|
||||
|
||||
\begin{drcode}[Host tests]
|
||||
cmake -S components/core/test -B build-host \
|
||||
-DCMAKE_CXX_COMPILER="$(brew --prefix llvm)/bin/clang++"
|
||||
cmake --build build-host
|
||||
ctest --test-dir build-host --output-on-failure
|
||||
\end{drcode}
|
||||
|
||||
\section{Documentation}
|
||||
|
||||
The API documentation is generated with Doxygen and must build cleanly;
|
||||
an undocumented class, method, or parameter fails the build.
|
||||
|
||||
\begin{drcode}[Docs]
|
||||
doxygen Doxyfile
|
||||
\end{drcode}
|
||||
|
||||
\begin{drcaution}[Keep it green]
|
||||
The Doxygen build and the manual-synchronisation check are part of the
|
||||
definition of done. A change that leaves either failing is not complete.
|
||||
\end{drcaution}
|
||||
@@ -0,0 +1,35 @@
|
||||
\chapter{Class Reference}
|
||||
\label{ch:classes}
|
||||
|
||||
This chapter documents the firmware's public classes at the design level:
|
||||
what each class is responsible for, which collaborators it depends on, its
|
||||
key invariants, and how it fits the system. It complements --- and does
|
||||
not duplicate --- the generated API documentation, which carries the exact
|
||||
method signatures.
|
||||
|
||||
\begin{drnote}[How this chapter grows]
|
||||
Per the development rules, every public, architecturally-significant class
|
||||
(the drivers, the application services, and the public domain-core types)
|
||||
gets a section here, tagged \texttt{\textbackslash label\{cls:ClassName\}},
|
||||
added in the same change that introduces the class. A tooling check keeps
|
||||
this chapter in step with the code, so it is always current.
|
||||
\end{drnote}
|
||||
|
||||
The firmware is under active development. As each public class lands, its
|
||||
section appears below, grouped by layer: domain core, application
|
||||
services, and hardware drivers.
|
||||
|
||||
% ------------------------------------------------------------------
|
||||
% Per-class sections are added here as classes are implemented, e.g.:
|
||||
%
|
||||
% \section{Si4684Driver}\label{cls:Si4684Driver}
|
||||
% Responsibility, collaborators, invariants, usage.
|
||||
%
|
||||
% \section{Adau1701Driver}\label{cls:Adau1701Driver}
|
||||
% \section{Bt1035Driver}\label{cls:Bt1035Driver}
|
||||
% \section{TunerService}\label{cls:TunerService}
|
||||
% ...
|
||||
% ------------------------------------------------------------------
|
||||
|
||||
\section*{(No public classes documented yet)}
|
||||
Sections will appear here as the firmware is implemented.
|
||||
@@ -0,0 +1,202 @@
|
||||
% ============================================================
|
||||
% DigiRadio — Manual section: Firmware Architecture
|
||||
% Drop this into the manual as a \section (or \chapter).
|
||||
%
|
||||
% Required packages (add to the preamble if not present):
|
||||
% \usepackage{tikz}
|
||||
% \usetikzlibrary{positioning, arrows.meta, fit, backgrounds}
|
||||
% \usepackage{booktabs} % for the interface table
|
||||
%
|
||||
% The environments used here are standard. Replace itemize / framed
|
||||
% blocks with your own box taxonomy where you prefer.
|
||||
% ============================================================
|
||||
|
||||
\chapter{Firmware Architecture}
|
||||
\label{sec:firmware-architecture}
|
||||
|
||||
The DigiRadio firmware runs on the ESP32-S3 and orchestrates three
|
||||
companion chips into a single high-fidelity audio path: the Si4684
|
||||
DAB+/FM tuner, the ADAU1701 SigmaDSP, and the FSC-BT1035 Bluetooth
|
||||
transmitter. This section describes how the firmware is organised, how
|
||||
audio flows through the system, and how each chip is controlled. The
|
||||
day-to-day coding conventions (style, documentation, review rules) are
|
||||
intentionally kept out of this manual and live in the repository's
|
||||
\texttt{CONTRIBUTING.md} and \texttt{AGENTS.md}.
|
||||
|
||||
\section{Design principles}
|
||||
\label{sec:fw-principles}
|
||||
|
||||
Two ideas shape the whole codebase:
|
||||
|
||||
\begin{itemize}
|
||||
\item \textbf{Strong typing.} Domain quantities (frequency, gain,
|
||||
station identifier, band) are dedicated types rather than raw
|
||||
integers or floats. Invalid states are made unrepresentable: input
|
||||
from the network, UART, or flash is validated once at the boundary
|
||||
into a domain type, and trusted thereafter.
|
||||
\item \textbf{Functional core, imperative shell.} All hardware-free
|
||||
logic --- coefficient math, boot-image framing, configuration
|
||||
parsing, station-list operations --- lives in a pure \emph{core}
|
||||
that compiles and is unit-tested on the host, with no dependency on
|
||||
ESP-IDF. Every access to the hardware (I\textsuperscript{2}C, SPI,
|
||||
UART, flash) lives in a thin \emph{shell} around that core. This
|
||||
keeps the logic testable without a board attached.
|
||||
\end{itemize}
|
||||
|
||||
\section{Layered structure}
|
||||
\label{sec:fw-layers}
|
||||
|
||||
The firmware is organised in three layers, with dependencies pointing
|
||||
inward only (Figure~\ref{fig:fw-layers}). The outer shell may depend on
|
||||
the services and the core; the pure core depends on nothing outside
|
||||
itself.
|
||||
|
||||
\begin{figure}[htbp]
|
||||
\centering
|
||||
\begin{tikzpicture}[
|
||||
layer/.style={draw, rounded corners, minimum width=10cm,
|
||||
minimum height=1.5cm, align=center, font=\small},
|
||||
node distance=4mm]
|
||||
\node[layer, fill=black!5] (shell) {%
|
||||
\textbf{Imperative shell}\\[2pt]
|
||||
chip drivers \textbullet\ web server \textbullet\ NVS \textbullet\
|
||||
FreeRTOS tasks \textbullet\ ISRs};
|
||||
\node[layer, fill=black!8, below=of shell] (services) {%
|
||||
\textbf{Application services}\\[2pt]
|
||||
TunerService \textbullet\ AudioService \textbullet\
|
||||
ConfigService \textbullet\ NetworkService};
|
||||
\node[layer, fill=black!12, below=of services] (core) {%
|
||||
\textbf{Domain core (pure, host-tested)}\\[2pt]
|
||||
Station \textbullet\ Frequency \textbullet\ EqProfile \textbullet\
|
||||
MixerState \textbullet\ Credential \textbullet\ validation};
|
||||
\draw[-{Latex}] (shell) -- (services);
|
||||
\draw[-{Latex}] (services) -- (core);
|
||||
\end{tikzpicture}
|
||||
\caption{Firmware layering. Dependencies point inward; the pure core
|
||||
has no hardware dependencies.}
|
||||
\label{fig:fw-layers}
|
||||
\end{figure}
|
||||
|
||||
Application services take driver \emph{interfaces}
|
||||
(\texttt{ITuner}, \texttt{IDsp}, \texttt{IBtModule},
|
||||
\texttt{ISecureStore}) injected at construction. Because the services
|
||||
depend on abstractions rather than concrete hardware, the same logic can
|
||||
be exercised against fakes in host tests and against real silicon on the
|
||||
device.
|
||||
|
||||
\section{Audio signal path}
|
||||
\label{sec:fw-audio}
|
||||
|
||||
The audio chain is built around sound quality. The Si4684 produces the
|
||||
DAB+/FM audio stream; the ADAU1701 applies equalisation and mixes it
|
||||
with the ESP32 audio source; the FSC-BT1035 streams the result over
|
||||
Bluetooth with aptX Adaptive (Figure~\ref{fig:fw-audio}).
|
||||
|
||||
\begin{figure}[htbp]
|
||||
\centering
|
||||
\begin{tikzpicture}[
|
||||
block/.style={draw, rounded corners, minimum height=1cm,
|
||||
minimum width=2.4cm, align=center, font=\small},
|
||||
>={Latex}, node distance=8mm]
|
||||
\node[block] (si) {Si4684\\\scriptsize DAB+/FM};
|
||||
\node[block, right=16mm of si] (dsp) {ADAU1701\\\scriptsize EQ + mixer};
|
||||
\node[block, right=16mm of dsp] (bt) {FSC-BT1035\\\scriptsize aptX Adaptive};
|
||||
\node[block, below=12mm of dsp] (esp) {ESP32-S3\\\scriptsize audio src};
|
||||
\draw[->] (si) -- (dsp) node[midway, above, font=\scriptsize]{audio};
|
||||
\draw[->] (dsp) -- (bt) node[midway, above, font=\scriptsize]{out};
|
||||
\draw[->] (esp) -- (dsp) node[midway, right, font=\scriptsize]{mix in};
|
||||
\end{tikzpicture}
|
||||
\caption{Audio signal path. The ADAU1701 input mixer selects/blends
|
||||
the Si4684 and ESP32 sources; equalisation is applied before the
|
||||
Bluetooth output stage.}
|
||||
\label{fig:fw-audio}
|
||||
\end{figure}
|
||||
|
||||
Equalisation and input mixing are exposed to the rest of the firmware as
|
||||
typed operations --- setting an EQ band from a gain, centre frequency,
|
||||
and Q, or setting the mix level of a given source --- never as raw DSP
|
||||
cell addresses. The biquad coefficient math runs in the pure core and is
|
||||
verified against reference values in host tests.
|
||||
|
||||
\section{Chip control and boot}
|
||||
\label{sec:fw-chips}
|
||||
|
||||
\paragraph{Si4684 (tuner).}
|
||||
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.
|
||||
|
||||
\paragraph{ADAU1701 (DSP).}
|
||||
The board carries no self-boot EEPROM. Instead, the ESP32 writes the
|
||||
SigmaStudio-exported program into the DSP's RAM at \emph{every} boot.
|
||||
Runtime changes to equalisation and mixing use the ADAU1701 safeload
|
||||
mechanism, so parameter updates are click-free while audio is playing.
|
||||
|
||||
\begin{drcaution}[Safeload]
|
||||
Writing DSP parameter cells directly while audio is running produces
|
||||
audible clicks. All runtime EQ and mixer changes must go through the
|
||||
safeload registers.
|
||||
\end{drcaution}
|
||||
|
||||
\paragraph{FSC-BT1035 (Bluetooth).}
|
||||
The module is controlled by AT commands over UART. The initialisation
|
||||
sequence includes enabling Line-In mode (\texttt{AT+AUXCFG=1}), which is
|
||||
required for the wired audio path from the DSP; command responses are
|
||||
parsed explicitly, with timeouts treated as errors.
|
||||
|
||||
\section{Configuration, storage, and user interface}
|
||||
\label{sec:fw-config}
|
||||
|
||||
Network provisioning uses a SoftAP/captive-portal for first-time setup,
|
||||
then joins the configured network as a station. Configuration is exposed
|
||||
through an elegant, minimal web interface served from flash, backed by a
|
||||
typed JSON API; the interface holds no business logic.
|
||||
|
||||
Sensitive data --- Wi-Fi credentials, user credentials, and the
|
||||
station/frequency list --- is held in encrypted storage at rest. Secrets
|
||||
are wrapped in a dedicated type that cannot be logged or implicitly
|
||||
converted to a string, and buffers are cleared after use.
|
||||
|
||||
\section{Error-handling model}
|
||||
\label{sec:fw-errors}
|
||||
|
||||
Every operation that can fail returns a typed result
|
||||
(\texttt{std::expected<T, Error>}); nothing fails silently and every
|
||||
timeout is an explicit error value. Errors propagate to the layer that
|
||||
can act on them --- a driver reports, a service decides (retry, degrade,
|
||||
or surface to the UI), and the top level logs. C++ exceptions are
|
||||
disabled.
|
||||
|
||||
\section{Toolchain}
|
||||
\label{sec:fw-toolchain}
|
||||
|
||||
\begin{table}[htbp]
|
||||
\centering
|
||||
\begin{tabular}{@{}ll@{}}
|
||||
\toprule
|
||||
\textbf{Item} & \textbf{Choice} \\
|
||||
\midrule
|
||||
Framework & ESP-IDF v5.5.x (native) \\
|
||||
Language & C++23 (\texttt{-std=gnu++23}) \\
|
||||
Error model & \texttt{std::expected}; exceptions off \\
|
||||
Hardware licence & CERN-OHL-S v2 \\
|
||||
Firmware licence & Apache-2.0 \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\caption{Firmware toolchain and licensing summary.}
|
||||
\label{tab:fw-toolchain}
|
||||
\end{table}
|
||||
|
||||
The firmware source, build instructions, and development conventions are
|
||||
maintained in the \texttt{Software/} directory of the project
|
||||
repository.
|
||||
@@ -0,0 +1,53 @@
|
||||
\chapter{Hardware Overview}
|
||||
\label{ch:hardware}
|
||||
|
||||
This chapter describes the board at a block level. The complete hardware
|
||||
design --- schematics, PCB, Gerbers, and bill of materials --- is
|
||||
published in the repository under the CERN-OHL-S v2 licence.
|
||||
|
||||
\section{System block diagram}
|
||||
|
||||
DigiRadio is built around four devices 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
|
||||
\begin{tabular}{@{}lll@{}}
|
||||
\drhead Device & Role & Interface \\
|
||||
\midrule
|
||||
Si4684 & DAB+/FM tuner & SPI / I\textsuperscript{2}C \\
|
||||
ADAU1701 & Audio DSP (EQ + mixer) & I\textsuperscript{2}C \\
|
||||
ESP32-S3-WROOM-1 & Host controller, Wi-Fi/BLE & --- \\
|
||||
FSC-BT1035 & Bluetooth 5.2 (aptX Adaptive) & UART (AT) \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\caption{Principal integrated circuits and their roles.}
|
||||
\label{tab:hw-ics}
|
||||
\end{table}
|
||||
|
||||
\section{Power}
|
||||
|
||||
The board is powered from USB-C. An AP63203 buck converter generates the
|
||||
main rails 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}
|
||||
|
||||
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.
|
||||
|
||||
\begin{drnote}[Board]
|
||||
The PCB is a six-layer stack-up with controlled impedance on the USB and
|
||||
RF sections. The full fabrication data is in the repository.
|
||||
\end{drnote}
|
||||
|
||||
\section{User interface and connectors}
|
||||
|
||||
Configuration is done over Wi-Fi through a built-in web interface (see
|
||||
Chapter~\ref{ch:firmware}); no display is required on the board itself.
|
||||
Audio reaches the listener wirelessly over Bluetooth.
|
||||
@@ -0,0 +1,41 @@
|
||||
\chapter{Introduction}
|
||||
\label{ch:introduction}
|
||||
|
||||
DigiRadio is an open-source, high-fidelity digital radio receiver. It
|
||||
receives DAB+ and FM broadcasts, processes the audio through a dedicated
|
||||
signal processor, and streams the result over Bluetooth using a
|
||||
high-resolution codec. The whole project --- hardware and firmware --- is
|
||||
released as open source for the maker and audio community to study,
|
||||
build, and improve.
|
||||
|
||||
\section{What DigiRadio is}
|
||||
|
||||
Most DAB+/FM hobby projects stop at basic reception. DigiRadio adds two
|
||||
things that lift it into hi-fi territory: a real audio DSP stage for
|
||||
equalisation and mixing, and a premium-codec Bluetooth output. The result
|
||||
is a genuine wireless audio source rather than a bench demo, and, being
|
||||
fully documented, a practical reference for anyone learning multi-chip
|
||||
audio design or RF-aware PCB layout.
|
||||
|
||||
\begin{drkey}[At a glance]
|
||||
A four-chip design --- Si4684 tuner, ADAU1701 DSP, ESP32-S3 host, and an
|
||||
FSC-BT1035 Bluetooth transmitter --- on a six-layer board, powered from
|
||||
USB-C, configured through an elegant web interface.
|
||||
\end{drkey}
|
||||
|
||||
\section{Who this manual is for}
|
||||
|
||||
This manual documents the system for someone building, flashing, or
|
||||
extending DigiRadio: the hardware at a block level
|
||||
(Chapter~\ref{ch:hardware}), the firmware architecture
|
||||
(Chapter~\ref{ch:firmware}), the per-class reference that grows with the
|
||||
code (Chapter~\ref{ch:classes}), and how to build and flash
|
||||
(Chapter~\ref{ch:build}). The exact register-level programming of each
|
||||
chip lives in the source code and its generated API documentation; this
|
||||
manual explains the design and the reasoning behind it.
|
||||
|
||||
\section{Licensing summary}
|
||||
|
||||
The hardware is licensed under CERN-OHL-S v2 and the firmware under
|
||||
Apache-2.0; full details are in Chapter~\ref{ch:licensing}. The project
|
||||
repository is at \url{https://github.com/manvalan/DigiRadio}.
|
||||
@@ -0,0 +1,40 @@
|
||||
\chapter{Licensing}
|
||||
\label{ch:licensing}
|
||||
|
||||
DigiRadio is dual-licensed, with hardware and firmware under separate but
|
||||
compatible open-source licences.
|
||||
|
||||
\section{Hardware}
|
||||
|
||||
The hardware --- schematics, PCB layout, Gerbers, and bill of materials
|
||||
--- is licensed under the \textbf{CERN Open Hardware Licence Version~2,
|
||||
Strongly Reciprocal (CERN-OHL-S v2)}. Anyone who modifies and distributes
|
||||
the hardware must release their changes under the same terms.
|
||||
|
||||
\section{Firmware}
|
||||
|
||||
The firmware is licensed under the \textbf{Apache License 2.0}. It grants
|
||||
patent rights explicitly and pairs naturally with the ESP-IDF ecosystem,
|
||||
which is Apache-licensed as well. Every source file carries the Apache
|
||||
header with an SPDX identifier.
|
||||
|
||||
\section{Documentation and project pages}
|
||||
|
||||
Where a hosting platform does not offer the CERN-OHL-S licence in its
|
||||
selector, the closest share-alike option is used for that page, with the
|
||||
authoritative licence stated as CERN-OHL-S v2. The definitive licensing
|
||||
is always the one declared in the project repository.
|
||||
|
||||
\section{Third-party components}
|
||||
|
||||
The design integrates third-party silicon (Silicon Labs, Analog Devices,
|
||||
Espressif, Feasycom/Qualcomm) whose datasheets, firmware images, and DSP
|
||||
tools remain subject to their respective vendors' terms. Those terms are
|
||||
unaffected by the DigiRadio licences and must be observed when
|
||||
redistributing vendor-supplied binaries.
|
||||
|
||||
\begin{drnote}[Manufacturing partner]
|
||||
Prototype fabrication and assembly are supported by PCBWay. Their
|
||||
contribution is acknowledged in the project documentation and on the
|
||||
board.
|
||||
\end{drnote}
|
||||
@@ -0,0 +1,169 @@
|
||||
% ============================================================
|
||||
% digiradio-manual.sty — visual style for the DigiRadio manual
|
||||
% Optima-like humanist sans, 12pt, 1.3 leading, restrained colour,
|
||||
% and clear at-a-glance tcolorbox callouts.
|
||||
%
|
||||
% Use with a 12pt KOMA class, e.g.:
|
||||
% \documentclass[12pt,a4paper]{scrartcl}
|
||||
% \usepackage{digiradio-manual}
|
||||
%
|
||||
% FONT: compile with LuaLaTeX or XeLaTeX to get the real Optima
|
||||
% (a system font on macOS). With pdfLaTeX it falls back to Linux
|
||||
% Biolinum, a humanist sans in the same spirit. The package detects
|
||||
% the engine automatically.
|
||||
% ============================================================
|
||||
\NeedsTeXFormat{LaTeX2e}
|
||||
\ProvidesPackage{digiradio-manual}[2026/07/06 DigiRadio manual style]
|
||||
|
||||
\RequirePackage[table,dvipsnames]{xcolor}
|
||||
\RequirePackage{iftex}
|
||||
\RequirePackage{geometry}
|
||||
\RequirePackage{microtype}
|
||||
\RequirePackage{setspace}
|
||||
\RequirePackage{titlesec}
|
||||
\RequirePackage{booktabs}
|
||||
\RequirePackage{array}
|
||||
\RequirePackage{enumitem}
|
||||
\RequirePackage[most]{tcolorbox}
|
||||
\RequirePackage{graphicx}
|
||||
|
||||
% ---------- Fonts (engine-aware) ---------------------------------------
|
||||
\ifPDFTeX
|
||||
\RequirePackage[T1]{fontenc}
|
||||
\RequirePackage[utf8]{inputenc}
|
||||
\RequirePackage{libertine} % Linux Libertine + Biolinum
|
||||
\renewcommand{\familydefault}{\sfdefault} % Biolinum as body (Optima-like)
|
||||
\else
|
||||
\RequirePackage{fontspec}
|
||||
% Real Optima on macOS; change the name if yours differs.
|
||||
\IfFontExistsTF{Optima}{%
|
||||
\setmainfont{Optima}%
|
||||
}{%
|
||||
\setmainfont{Linux Biolinum O}% fallback if Optima not installed
|
||||
}
|
||||
\fi
|
||||
|
||||
% ---------- Colour palette (elegant, restrained) -----------------------
|
||||
% Two signature colours (petrol + amber), a muted red reserved for
|
||||
% cautions, plus ink and neutral. Backgrounds are light tints of these.
|
||||
\definecolor{drPetrol}{HTML}{0F4C5C} % primary — headings, notes
|
||||
\definecolor{drAmber} {HTML}{C46210} % accent — key ideas, emphasis
|
||||
\definecolor{drTeal} {HTML}{1A7F72} % secondary — references
|
||||
\definecolor{drRed} {HTML}{A4303F} % caution only
|
||||
\definecolor{drInk} {HTML}{1B1B1D} % body text
|
||||
\definecolor{drGray} {HTML}{5A5F63} % captions, rules
|
||||
|
||||
\color{drInk}
|
||||
|
||||
% ---------- Page geometry & spacing ------------------------------------
|
||||
\geometry{a4paper, top=2.6cm, bottom=2.6cm, inner=2.6cm, outer=3.2cm,
|
||||
marginparwidth=2.4cm}
|
||||
\setstretch{1.3}
|
||||
\setlength{\parskip}{0.5\baselineskip}
|
||||
\setlength{\parindent}{0pt}
|
||||
|
||||
% ---------- Links -------------------------------------------------------
|
||||
\RequirePackage{hyperref}
|
||||
\hypersetup{colorlinks=true, linkcolor=drPetrol, urlcolor=drAmber,
|
||||
citecolor=drTeal}
|
||||
|
||||
% ---------- Chapter heading (for report-class manuals) -----------------
|
||||
\titleformat{\chapter}[display]
|
||||
{\color{drPetrol}\bfseries}
|
||||
{\filright\color{drAmber}\large\MakeUppercase{\chaptertitlename}\ \thechapter}
|
||||
{6pt}{\Huge}
|
||||
[\vspace{3pt}{\color{drAmber}\titlerule[1.5pt]}]
|
||||
\titlespacing*{\chapter}{0pt}{0pt}{22pt}
|
||||
|
||||
% ---------- Section headings (coloured, sans, distinctive) -------------
|
||||
\titleformat{\section}
|
||||
{\color{drPetrol}\Large\bfseries}
|
||||
{\color{drAmber}\thesection\quad}{0pt}{}
|
||||
[{\color{drAmber}\titlerule[1.2pt]}]
|
||||
\titleformat{\subsection}
|
||||
{\color{drPetrol}\large\bfseries}
|
||||
{\color{drAmber}\thesubsection\quad}{0pt}{}
|
||||
\titleformat{\subsubsection}
|
||||
{\color{drPetrol}\normalsize\bfseries}
|
||||
{\thesubsubsection\quad}{0pt}{}
|
||||
\titleformat{\paragraph}[runin]
|
||||
{\bfseries\color{drPetrol}}{}{0pt}{}[\;]
|
||||
\titlespacing*{\paragraph}{0pt}{0.6\baselineskip}{0.8em}
|
||||
\titlespacing*{\section}{0pt}{1.4\baselineskip}{0.5\baselineskip}
|
||||
|
||||
% ---------- List markers (coloured) ------------------------------------
|
||||
\setlist[itemize,1]{label=\textcolor{drAmber}{\textbullet}, leftmargin=*}
|
||||
\setlist[itemize,2]{label=\textcolor{drTeal}{\textendash}}
|
||||
\setlist[enumerate,1]{label=\textcolor{drAmber}{\bfseries\arabic*.},
|
||||
leftmargin=*}
|
||||
|
||||
% ---------- Callout boxes (clear at a glance) --------------------------
|
||||
\tcbuselibrary{skins,breakable}
|
||||
|
||||
% Shared base: rounded, light tinted body, bold coloured title bar
|
||||
% clipped to the top-left, and an accent rule down the left edge.
|
||||
\tcbset{dr@base/.style={
|
||||
enhanced, breakable, boxrule=0pt, frame hidden, sharp corners=downhill,
|
||||
arc=1.4mm, left=3.5mm, right=3.5mm, top=3mm, bottom=3mm,
|
||||
fonttitle=\bfseries\small, coltitle=white,
|
||||
attach boxed title to top left={xshift=3mm, yshift=-2.4mm},
|
||||
boxed title style={boxrule=0pt, arc=0.8mm,
|
||||
left=2.2mm, right=2.2mm, top=0.6mm, bottom=0.6mm},
|
||||
before skip=8pt, after skip=8pt,
|
||||
}}
|
||||
|
||||
\newtcolorbox{drnote}[1][Note]{dr@base,
|
||||
colback=drPetrol!6, colbacktitle=drPetrol,
|
||||
borderline west={2.6pt}{0pt}{drPetrol}, title={#1}}
|
||||
|
||||
\newtcolorbox{drkey}[1][Key idea]{dr@base,
|
||||
colback=drAmber!9, colbacktitle=drAmber,
|
||||
borderline west={2.6pt}{0pt}{drAmber}, title={#1}}
|
||||
|
||||
\newtcolorbox{drcaution}[1][Caution]{dr@base,
|
||||
colback=drRed!7, colbacktitle=drRed,
|
||||
borderline west={2.6pt}{0pt}{drRed}, title={#1}}
|
||||
|
||||
\newtcolorbox{drref}[1][Datasheet]{dr@base,
|
||||
colback=drTeal!7, colbacktitle=drTeal,
|
||||
borderline west={2.6pt}{0pt}{drTeal}, title={#1}}
|
||||
|
||||
\newtcolorbox{drdecision}[1][Design decision]{dr@base,
|
||||
colback=drPetrol!5, colbacktitle=drGray,
|
||||
borderline west={2.6pt}{0pt}{drGray}, title={#1}}
|
||||
|
||||
% ---------- Table helpers ----------------------------------------------
|
||||
% A coloured header row for booktabs tables. Usage:
|
||||
% \begin{tabular}{...}
|
||||
% \drhead Col A & Col B \\ % coloured header row
|
||||
% \midrule ...
|
||||
\newcommand{\drhead}{\rowcolor{drPetrol}\color{white}\bfseries}
|
||||
% Subtle zebra striping if wanted: \rowcolors{2}{drPetrol!5}{white}
|
||||
% ---------- Code listings (styled to match the callouts) ---------------
|
||||
\tcbuselibrary{listings}
|
||||
\lstdefinestyle{drcpp}{%
|
||||
language=C++,
|
||||
basicstyle=\ttfamily\small,
|
||||
keywordstyle=\color{drPetrol}\bfseries,
|
||||
commentstyle=\color{drGray}\itshape,
|
||||
stringstyle=\color{drTeal},
|
||||
numberstyle=\color{drGray}\scriptsize,
|
||||
numbers=left, numbersep=9pt,
|
||||
showstringspaces=false,
|
||||
tabsize=2, breaklines=true, keepspaces=true,
|
||||
morekeywords={constexpr,noexcept,nullptr,override,final,explicit,
|
||||
enum,class,namespace,using,co_await,std,expected,span,
|
||||
uint32_t,uint8_t},
|
||||
}
|
||||
% drcode: a code block with the same title bar + left accent as the boxes
|
||||
\newtcblisting{drcode}[1][Listing]{%
|
||||
dr@base,
|
||||
colback=drPetrol!4, colbacktitle=drGray,
|
||||
borderline west={2.6pt}{0pt}{drGray},
|
||||
title={#1},
|
||||
listing only, listing style=drcpp,
|
||||
}
|
||||
% inline code: \drcode|std::expected<T,E>|
|
||||
\newcommand{\code}[1]{{\ttfamily\color{drPetrol}#1}}
|
||||
|
||||
\endinput
|
||||
Binary file not shown.
@@ -0,0 +1,52 @@
|
||||
% ============================================================
|
||||
% DigiRadio — Technical Manual (main file)
|
||||
%
|
||||
% Compile with LuaLaTeX or XeLaTeX for the real Optima font
|
||||
% (a system font on macOS):
|
||||
% latexmk -lualatex manual.tex
|
||||
% pdfLaTeX also works and falls back to Linux Biolinum.
|
||||
% ============================================================
|
||||
\documentclass[12pt,a4paper,oneside]{scrreprt}
|
||||
|
||||
\usepackage{digiradio-manual}
|
||||
\usepackage{tikz}
|
||||
\usetikzlibrary{positioning, arrows.meta, fit, backgrounds}
|
||||
|
||||
\begin{document}
|
||||
|
||||
% ---------------- Cover ----------------
|
||||
\begin{titlepage}
|
||||
\thispagestyle{empty}
|
||||
\vspace*{3.5cm}
|
||||
{\color{drPetrol}\fontsize{48}{52}\selectfont\bfseries DigiRadio\par}
|
||||
\vspace{3mm}
|
||||
{\color{drAmber}\rule{\linewidth}{2.5pt}}
|
||||
\vspace{6mm}
|
||||
|
||||
{\color{drInk}\LARGE Open-Source Hi-Fi DAB+/FM Receiver\par}
|
||||
\vspace{3mm}
|
||||
{\color{drGray}\Large Technical Manual\par}
|
||||
|
||||
\vfill
|
||||
{\color{drInk}\large Michele Bigi\par}
|
||||
\vspace{1mm}
|
||||
{\color{drGray} 2026 \quad\textbullet\quad Hardware: CERN-OHL-S v2
|
||||
\quad\textbullet\quad Firmware: Apache-2.0\par}
|
||||
\vspace{2mm}
|
||||
{\color{drGray}\small \url{https://github.com/manvalan/DigiRadio}\par}
|
||||
\end{titlepage}
|
||||
|
||||
% ---------------- Contents ----------------
|
||||
\pagestyle{plain}
|
||||
{\color{drPetrol}\tableofcontents}
|
||||
\clearpage
|
||||
|
||||
% ---------------- Chapters ----------------
|
||||
\include{ch-intro}
|
||||
\include{ch-hardware}
|
||||
\include{ch-firmware}
|
||||
\include{ch-classes}
|
||||
\include{ch-build}
|
||||
\include{ch-licensing}
|
||||
|
||||
\end{document}
|
||||
Reference in New Issue
Block a user