From fcda4ef15145c2c55fee456b3886ee40b74246d6 Mon Sep 17 00:00:00 2001 From: Michele Bigi Date: Wed, 8 Jul 2026 15:02:30 +0200 Subject: [PATCH] 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 --- Software/docs/manual/ch-adau1701.tex | 20 +++--- Software/docs/manual/ch-api.tex | 79 ++++++++++++----------- Software/docs/manual/ch-bt1035.tex | 28 ++++---- Software/docs/manual/ch-build.tex | 2 +- Software/docs/manual/ch-classes.tex | 14 ++-- Software/docs/manual/ch-firmware.tex | 2 +- Software/docs/manual/ch-hardware.tex | 56 ++++++++-------- Software/docs/manual/ch-si4684.tex | 20 +++--- Software/docs/manual/ch-sigmastudio.tex | 15 +++-- Software/docs/manual/digiradio-manual.sty | 15 +++++ 10 files changed, 141 insertions(+), 110 deletions(-) diff --git a/Software/docs/manual/ch-adau1701.tex b/Software/docs/manual/ch-adau1701.tex index e6cc629..11ac5dc 100644 --- a/Software/docs/manual/ch-adau1701.tex +++ b/Software/docs/manual/ch-adau1701.tex @@ -46,7 +46,7 @@ authoritative DSP program for firmware builds. \begin{table}[htbp] \centering - \begin{tabular}{@{}llp{6.5cm}@{}} + \begin{tabular}{@{}L{3.8cm}L{3.5cm}L{6.2cm}@{}} \toprule \textbf{File} & \textbf{Role} & \textbf{Used by firmware} \\ \midrule @@ -151,7 +151,7 @@ separates concerns as follows: \begin{table}[htbp] \centering \small - \begin{tabular}{@{}llp{5.8cm}@{}} + \begin{tabular}{@{}L{2.5cm}L{3.8cm}L{6.2cm}@{}} \drhead Layer & Type & Responsibility \\ \midrule HTTP / UI & \texttt{SetupWebServer}, web UI & @@ -189,7 +189,7 @@ successful \texttt{boot()}. \begin{table}[htbp] \centering - \begin{tabular}{@{}ll@{}} + \begin{tabular}{@{}L{4.2cm}L{9.2cm}@{}} \toprule \textbf{Method} & \textbf{Purpose} \\ \midrule @@ -205,7 +205,7 @@ successful \texttt{boot()}. \begin{table}[htbp] \centering - \begin{tabular}{@{}ll@{}} + \begin{tabular}{@{}L{4.2cm}L{9.2cm}@{}} \toprule \textbf{Method} & \textbf{Purpose} \\ \midrule @@ -237,7 +237,7 @@ runtime-adjustable, matching Table~\ref{tab:ss-runtime}. \subsection{Gain and EQ coefficient path} Volume cells (faders, master) store linear gain as ADAU \textbf{8.23 fixpoint}. -\texttt{core::gainDbToLinearFixpoint()} converts \texttt{GainDb} before +\texttt{core::gainDbTo\-LinearFixpoint()} converts \texttt{GainDb} before \texttt{sigma\_safeload\_param()}. PEQ bands use \texttt{core::designPeakingEq()} at 48\,kHz sample rate to @@ -259,13 +259,13 @@ header \texttt{DigiRadio\_IC\_1\_PARAM.h} defines \texttt{ADDR\_*} symbols; \begin{table}[htbp] \centering \small - \begin{tabular}{@{}lll@{}} + \begin{tabular}{@{}L{2.4cm}L{3.6cm}L{7.2cm}@{}} \drhead Domain & \texttt{ADDR\_*} & SigmaStudio block \\ \midrule Si4684 L/R & \texttt{SI4674}, \texttt{SI4674\_1} & Si4674 fader \\ ESP32 L/R & \texttt{ESP32}, \texttt{ESP32\_1} & ESP32 fader \\ - Mix L/R & \texttt{STMIXER1\_ST0/1\_VOLUME} & St Mixer1 \\ - EQ band $n$ & \texttt{PARAMEQ1\_ST$n$\_B0} + 0..4 & Param EQ1 coeffs \\ + Mix L/R & {\footnotesize\texttt{STMIXER1\_ST0/1\_VOLUME}} & St Mixer1 \\ + EQ band $n$ & {\footnotesize\texttt{PARAMEQ1\_ST$n$\_B0} + 0..4} & Param EQ1 coeffs \\ Master L/R & \texttt{MULTIPLE1}, \texttt{MULTIPLE1\_1} & Multiple 1 \\ \bottomrule \end{tabular} @@ -335,7 +335,7 @@ use for audio path control: \begin{table}[htbp] \centering \small - \begin{tabular}{@{}ll@{}} + \begin{tabular}{@{}L{4.2cm}L{9.2cm}@{}} \toprule \textbf{Method} & \textbf{Effect} \\ \midrule @@ -423,7 +423,7 @@ only if band indices and centre frequencies still match; otherwise reset via \begin{table}[htbp] \centering \small - \begin{tabular}{@{}ll@{}} + \begin{tabular}{@{}L{4.2cm}L{9.2cm}@{}} \drhead Error & Typical cause \\ \midrule \texttt{ResetFailed} & GPIO reset line configuration \\ diff --git a/Software/docs/manual/ch-api.tex b/Software/docs/manual/ch-api.tex index d13caa1..71e835b 100644 --- a/Software/docs/manual/ch-api.tex +++ b/Software/docs/manual/ch-api.tex @@ -27,7 +27,7 @@ All responses use \texttt{Content-Type: application/json} except \section{Endpoints} -\subsection{\texttt{GET /api/health}} +\apiendpoint{GET}{/api/health} \label{sec:api-health} Returns a health-check DTO serialised by @@ -53,7 +53,7 @@ Returns a health-check DTO serialised by HTTP status: \textbf{200 OK} on success. -\subsection{\texttt{POST /api/wifi}} +\apiendpoint{POST}{/api/wifi} \label{sec:api-wifi} Accepts Wi-Fi credentials for station (STA) join. The body is parsed by @@ -88,17 +88,16 @@ reboots after the indicated delay. \begin{drcode}[JSON] {"status":"error","reason":"invalid_ssid"} \end{drcode} -Serialised by \texttt{core::serializeWifiProvisionErrorJson()}. Reason -tokens (never include secrets): \texttt{invalid\_json}, -\texttt{missing\_field}, \texttt{invalid\_ssid}, \texttt{invalid\_password}, -\texttt{store\_failed}. +Serialised by \texttt{core::serializeWifiProvisionErrorJson()}. Reason tokens (never include secrets): +\texttt{invalid\_json}, \texttt{missing\_field}, \texttt{invalid\_ssid}, +\texttt{invalid\_password}, \texttt{store\_failed}. \end{drnote} 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}} +\apiendpoint{GET}{/api/tuner/status} \label{sec:api-tuner-status} Returns a tuner snapshot serialised by @@ -111,8 +110,9 @@ and~\ref{sec:si4684-fm-session}. \begin{drcode}[JSON] {"booted":true,"band":"dab","locked":true,"volume":63, "dab":{"freq_index":12,"fic_quality":80,"cnr_db":25, - "playing_service_id":42,"playing_component_id":7, - "dynamic_label":"Live show"},"fm":null} + "playing_service_id":42,"playing_component_id":7, + "dynamic_label":"Live show"}, + "fm":null} \end{drcode} For FM, \texttt{fm} carries \texttt{frequency\_khz}, \texttt{rssi\_dbuv}, \texttt{snr\_db}, \texttt{stereo}, optional \texttt{station\_name} (RDS PS), @@ -125,7 +125,7 @@ HTTP status: \textbf{200 OK}; \textbf{500} with \texttt{station\_name} and \texttt{radiotext}; DAB responses may include \texttt{dynamic\_label} when a programme is playing. -\subsection{\texttt{GET /api/tuner/services}} +\apiendpoint{GET}{/api/tuner/services} \label{sec:api-tuner-services} Lists DAB programmes for the current ensemble via @@ -140,7 +140,7 @@ Lists DAB programmes for the current ensemble via 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}} +\apiendpoint{POST}{/api/tuner/tune} \label{sec:api-tuner-tune} Tunes to a DAB ensemble or FM frequency. Body parsed by @@ -162,7 +162,7 @@ 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}} +\apiendpoint{POST}{/api/tuner/play} \label{sec:api-tuner-play} Starts a DAB audio service. Body parsed by @@ -177,7 +177,7 @@ Starts a DAB audio service. Body parsed by Success response: \texttt{\{"status":"playing"\}}. HTTP status: \textbf{200 OK}; \textbf{409} when playback cannot start. -\subsection{\texttt{POST /api/tuner/seek}} +\apiendpoint{POST}{/api/tuner/seek} \label{sec:api-tuner-seek} Seeks FM in the requested direction. Optional JSON body parsed by @@ -194,7 +194,7 @@ Use \texttt{"down"} for downward seek. Omit the body or send an empty JSON object (\texttt{\{\}}) for upward seek (backward compatible). \end{drnote} -\subsection{\texttt{GET /api/audio/profile}} +\apiendpoint{GET}{/api/audio/profile} \label{sec:api-audio-profile-get} Returns the current ADAU1701 audio snapshot serialised by @@ -205,8 +205,9 @@ Chapter~\ref{ch:adau1701}. \begin{drnote}[Response schema (excerpt)] \begin{drcode}[JSON] -{"mixer":{"si4684_left_db":0,"si4684_right_db":0,"esp32_left_db":0, - "esp32_right_db":0,"mix_left_db":0,"mix_right_db":0}, +{"mixer":{"si4684_left_db":0,"si4684_right_db":0, + "esp32_left_db":0,"esp32_right_db":0, + "mix_left_db":0,"mix_right_db":0}, "master":{"left_db":0,"right_db":0}, "eq":[{"gain_db":0,"center_hz":40,"q":1.414}, ...], "enhancements":{"stereo_level":0,"bass_level":0}} @@ -218,7 +219,7 @@ Enhancement levels are 0--100; at 0 the base EQ band settings apply. HTTP status: \textbf{200 OK}; \textbf{503} when the audio service is unavailable. -\subsection{\texttt{PUT /api/audio/profile}} +\apiendpoint{PUT}{/api/audio/profile} \label{sec:api-audio-profile-put} Applies a full audio profile. Body parsed by @@ -235,7 +236,7 @@ the ADAU1701 and writes NVS key \texttt{audio\_profile\_json}. HTTP status: \textbf{200 OK}; \textbf{400} for parse/validation failures; \textbf{500} when safeload or NVS persistence fails. -\subsection{\texttt{POST /api/dsp/program}} +\apiendpoint{POST}{/api/dsp/program} \label{sec:api-dsp-program} Uploads a framed ADAU1701 RAM download blob (\texttt{DRAD} v1, see @@ -255,7 +256,7 @@ for invalid/truncated/CRC failures; \textbf{413} when the body exceeds 200\,KiB; \textbf{500} on flash write failure. Pack blobs with \texttt{tools/pack\_dsp\_program.py} or \texttt{core::serializeDspProgramBlob()}. -\subsection{\texttt{POST /api/system/ota}} +\apiendpoint{POST}{/api/system/ota} \label{sec:api-system-ota} Streams a raw ESP-IDF application \texttt{.bin} into the inactive OTA slot @@ -278,7 +279,7 @@ for invalid project/magic or flash write failures; \textbf{500} on \texttt{esp\_ota\_end}/set-boot failures. Push with \texttt{curl --data-binary @build/digiradio.bin}. -\subsection{\texttt{POST /api/audio/reset}} +\apiendpoint{POST}{/api/audio/reset} \label{sec:api-audio-reset} Restores \texttt{AudioProfile::factoryDefault()} (flat EQ, 0\,dB gains), @@ -286,7 +287,7 @@ applies it to the DSP, and persists to NVS. Success response: \texttt{\{"status":"saved"\}}. HTTP status: \textbf{200 OK}; \textbf{500} on apply/persist failure. -\subsection{\texttt{POST /api/audio/stereo-enhance}} +\apiendpoint{POST}{/api/audio/stereo-enhance} \label{sec:api-audio-stereo-enhance} Adjusts stereo depth via a psychoacoustic PEQ overlay on bands 3--5 @@ -305,7 +306,7 @@ Success response: \texttt{\{"status":"saved"\}}. HTTP status: \textbf{200 OK}; \textbf{400} for invalid JSON or level; \textbf{500} when safeload or NVS persistence fails. -\subsection{\texttt{POST /api/audio/bass-enhance}} +\apiendpoint{POST}{/api/audio/bass-enhance} \label{sec:api-audio-bass-enhance} Adjusts bass emphasis via a PEQ overlay on bands 1--2 (100\,Hz / @@ -316,7 +317,7 @@ Adjusts bass emphasis via a PEQ overlay on bands 1--2 (100\,Hz / % Bluetooth (Slice 7) % ------------------------------------------------------------------ -\subsection{\texttt{GET /api/bluetooth/status}} +\apiendpoint{GET}{/api/bluetooth/status} \label{sec:api-bluetooth-status} Returns BT1035 boot flag, whether discoverable mode was requested, the @@ -330,24 +331,24 @@ Serialised by \texttt{core::serializeBluetoothStatusJson()}. \end{drcode} \end{drnote} -\subsection{\texttt{POST /api/bluetooth/pair}} +\apiendpoint{POST}{/api/bluetooth/pair} \label{sec:api-bluetooth-pair} Enters discoverable mode (\texttt{AT+PAIR=1}). Success: \texttt{\{"status":"pairing"\}}. -\subsection{\texttt{POST /api/bluetooth/pair/stop}} +\apiendpoint{POST}{/api/bluetooth/pair/stop} \label{sec:api-bluetooth-pair-stop} Leaves discoverable mode (\texttt{AT+PAIR=0}). Success: \texttt{\{"status":"idle"\}}. -\subsection{\texttt{POST /api/bluetooth/disconnect}} +\apiendpoint{POST}{/api/bluetooth/disconnect} \label{sec:api-bluetooth-disconnect} Releases the current A2DP session (\texttt{AT+A2DPDISC}). -\subsection{\texttt{GET /api/bluetooth/paired}} +\apiendpoint{GET}{/api/bluetooth/paired} \label{sec:api-bluetooth-paired} Returns paired remotes from \texttt{AT+PLIST}, serialised by @@ -359,7 +360,7 @@ Returns paired remotes from \texttt{AT+PLIST}, serialised by \end{drcode} \end{drnote} -\subsection{\texttt{POST /api/bluetooth/auto-reconnect}} +\apiendpoint{POST}{/api/bluetooth/auto-reconnect} \label{sec:api-bluetooth-auto-reconnect} Sets the module auto-reconnect retry count (\texttt{AT+AUTOCONN=0..15}). @@ -376,29 +377,29 @@ Success: \texttt{\{"status":"saved"\}}. % Station presets (Slice 4) % ------------------------------------------------------------------ -\subsection{\texttt{GET /api/stations}} +\apiendpoint{GET}{/api/stations} \label{sec:api-stations-get} Returns presets serialised by \texttt{core::serializeStationListJson()}. -\subsection{\texttt{POST /api/stations}} +\apiendpoint{POST}{/api/stations} \label{sec:api-stations-post} Adds one preset (\texttt{core::parseStationJson()}); persists via \texttt{ISecureStore::saveStationListJson()}. -\subsection{\texttt{POST /api/stations/remove}} +\apiendpoint{POST}{/api/stations/remove} \label{sec:api-stations-remove} Removes a preset by list index (\texttt{\{"index":0\}}). -\subsection{\texttt{POST /api/stations/reorder}} +\apiendpoint{POST}{/api/stations/reorder} \label{sec:api-stations-reorder} Reorders presets using \texttt{StationList::move()}. Body: \texttt{\{"from":1,"to":0\}}. Success: \texttt{\{"status":"reordered"\}}. -\subsection{\texttt{POST /api/stations/tune}} +\apiendpoint{POST}{/api/stations/tune} \label{sec:api-stations-tune} Recalls a preset via \texttt{integration::IntegrationService::recallPreset()} @@ -435,10 +436,10 @@ as \texttt{last\_preset} (u8). Passwords are wrapped in \texttt{core::Secret} in RAM and are never logged or returned by the API. \begin{drcaution}[Encryption at rest] -Firmware~0.8.3+ enables NVS encryption (\texttt{CONFIG\_NVS\_ENCRYPTION}) and -flash encryption in development mode (\texttt{sdkconfig.defaults}). Keys live in -the \texttt{nvs\_keys} partition; Wi-Fi passwords remain wrapped in -\texttt{core::Secret} in RAM and are never logged. First upgrade from plain NVS -requires \texttt{idf.py erase-flash}. HIL checklist: -\texttt{Software/docs/security-flash-nvs.md}. +Firmware~0.8.3+ enables NVS encryption +(\texttt{CONFIG\_NVS\_ENCRYPTION}) and flash encryption in development mode +(\texttt{sdkconfig.defaults}). Keys live in the \texttt{nvs\_keys} partition; +Wi-Fi passwords remain wrapped in \texttt{core::Secret} in RAM and are never +logged. First upgrade from plain NVS requires \texttt{idf.py erase-flash}. +HIL checklist: \drpath{Software/docs/security-flash-nvs.md}. \end{drcaution} diff --git a/Software/docs/manual/ch-bt1035.tex b/Software/docs/manual/ch-bt1035.tex index 591fe1a..49a2659 100644 --- a/Software/docs/manual/ch-bt1035.tex +++ b/Software/docs/manual/ch-bt1035.tex @@ -41,7 +41,8 @@ output (Section~\ref{sec:bt1035-i2s}). \begin{table}[htbp] \centering - \begin{tabular}{@{}ll@{}} + \small + \begin{tabular}{@{}L{4.2cm}L{9.2cm}@{}} \drhead Setting & Value \\ \midrule Port & UART2 (not the console UART) \\ @@ -67,7 +68,7 @@ Every command expects a module reply containing \texttt{OK} or \item treats timeouts and unexpected payloads as errors (never ignored). \end{itemize} -Host tests in \texttt{components/core/test/bt1035\_at\_test.cpp} lock the +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. \section{Mandatory I\textsuperscript{2}S slave mode} @@ -76,11 +77,13 @@ init sequence (\texttt{AT+AUXCFG=3}, \texttt{AT+I2SCFG=67}) and the parser. \begin{drcaution}[I\textsuperscript{2}S init is not optional] The board routes ADAU1701 \texttt{SDATA\_OUT0} (MP6) to the module PCM input with shared BCLK/LRCLK (see Chapter~\ref{ch:hardware}). The init sequence -must therefore use \texttt{AT+AUXCFG=3} (I\textsuperscript{2}S mode per -programming guide §5.1.25) followed by \texttt{AT+I2SCFG=67} (I\textsuperscript{2}S -slave, 48\,kHz, 32-bit per §5.1.4). \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. +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) +\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. \end{drcaution} \section{Boot sequence} @@ -125,7 +128,7 @@ only the I\textsuperscript{2}S bring-up required for the wired audio path. \begin{table}[htbp] \centering \small - \begin{tabular}{@{}llp{5.8cm}@{}} + \begin{tabular}{@{}L{2.5cm}L{3.8cm}L{6.2cm}@{}} \drhead Layer & Type & Responsibility \\ \midrule Bootstrap & \texttt{HardwareBootstrap} & @@ -145,14 +148,14 @@ only the I\textsuperscript{2}S bring-up required for the wired audio path. \label{sec:bt1035-at} The firmware enumerates every command it sends. Wire formats follow -\texttt{Hardware/DATASHEET/FSC-BT1035\_programming\_user\_guide\_1.1.1.pdf} +\drpath{Hardware/DATASHEET/FSC-BT1035_programming_user_guide_1.1.1.pdf} (§5 commands, §6 events). Extending the subset requires updating \texttt{core::Bt1035AtCommand}, the manual, and a host test. \begin{table}[htbp] \centering \small - \begin{tabular}{@{}llp{5.2cm}@{}} + \begin{tabular}{@{}L{2.4cm}L{3.4cm}L{5.5cm}@{}} \drhead Enum & Line sent & Programming guide \\ \midrule \texttt{Ping} & \texttt{AT} & link check \\ @@ -184,7 +187,8 @@ reconnect count). \begin{table}[htbp] \centering - \begin{tabular}{@{}ll@{}} + \small + \begin{tabular}{@{}L{4.2cm}L{9.2cm}@{}} \toprule \textbf{Method} & \textbf{Purpose} \\ \midrule @@ -210,7 +214,7 @@ reconnect count). \begin{table}[htbp] \centering \small - \begin{tabular}{@{}ll@{}} + \begin{tabular}{@{}L{4.2cm}L{9.2cm}@{}} \drhead \texttt{Bt1035Error} & Typical cause \\ \midrule \texttt{ResetFailed} & GPIO configuration failure \\ diff --git a/Software/docs/manual/ch-build.tex b/Software/docs/manual/ch-build.tex index 88f20f5..5ba876f 100644 --- a/Software/docs/manual/ch-build.tex +++ b/Software/docs/manual/ch-build.tex @@ -8,7 +8,7 @@ builds and is unit-tested on the host machine. \begin{table}[htbp] \centering - \begin{tabular}{@{}ll@{}} + \begin{tabular}{@{}L{4.2cm}L{9.2cm}@{}} \drhead Item & Choice \\ \midrule Framework & ESP-IDF v5.5.x (native) \\ diff --git a/Software/docs/manual/ch-classes.tex b/Software/docs/manual/ch-classes.tex index 8b34c2e..adc02e7 100644 --- a/Software/docs/manual/ch-classes.tex +++ b/Software/docs/manual/ch-classes.tex @@ -72,11 +72,15 @@ 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}, -\texttt{POST /api/wifi}, tuner routes (\texttt{/api/tuner/*}), audio -routes (\texttt{/api/audio/*}), Bluetooth (\texttt{/api/bluetooth/*}), and -station presets (\texttt{/api/stations/*}). JSON parsing and serialisation -delegate to the pure core; credentials persist via \texttt{ISecureStore}; +Minimal HTTP server: gzipped setup UI and typed JSON REST handlers: +\begin{itemize} + \item \texttt{GET /api/health}, \texttt{POST /api/wifi} + \item Tuner: \texttt{/api/tuner/*} + \item Audio: \texttt{/api/audio/*} + \item Bluetooth: \texttt{/api/bluetooth/*} + \item Presets: \texttt{/api/stations/*} +\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}. diff --git a/Software/docs/manual/ch-firmware.tex b/Software/docs/manual/ch-firmware.tex index 55e782a..08b7ca2 100644 --- a/Software/docs/manual/ch-firmware.tex +++ b/Software/docs/manual/ch-firmware.tex @@ -240,7 +240,7 @@ disabled. \begin{table}[htbp] \centering - \begin{tabular}{@{}ll@{}} + \begin{tabular}{@{}L{4.2cm}L{9.2cm}@{}} \toprule \textbf{Item} & \textbf{Choice} \\ \midrule diff --git a/Software/docs/manual/ch-hardware.tex b/Software/docs/manual/ch-hardware.tex index 0fb0bba..b3078bf 100644 --- a/Software/docs/manual/ch-hardware.tex +++ b/Software/docs/manual/ch-hardware.tex @@ -36,7 +36,8 @@ interface. \begin{table}[htbp] \centering - \begin{tabular}{@{}llll@{}} + \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 \\ @@ -152,7 +153,7 @@ The host speaks several interfaces, each chosen for its traffic: \begin{table}[htbp] \centering - \begin{tabular}{@{}lll@{}} + \begin{tabular}{@{}L{2.2cm}L{3.6cm}L{7.2cm}@{}} \drhead Bus & Devices & Purpose \\ \midrule SPI & Si4684 & fast firmware-image upload, tuner control \\ @@ -192,7 +193,7 @@ and the companion chips. The firmware pin definitions \subsection{System and control lines} \begin{table}[htbp] \centering - \begin{tabular}{@{}lll@{}} + \begin{tabular}{@{}L{2.2cm}L{3.6cm}L{7.2cm}@{}} \drhead Signal & ESP32-S3 GPIO & Notes \\ \midrule USB D$-$ & GPIO19 & native USB \\ @@ -207,7 +208,8 @@ and the companion chips. The firmware pin definitions \subsection{Si4684 tuner (SPI)} \begin{table}[htbp] \centering - \begin{tabular}{@{}llll@{}} + \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 & \\ @@ -225,7 +227,7 @@ and the companion chips. The firmware pin definitions \subsection{ADAU1701 DSP (I\textsuperscript{2}C)} \begin{table}[htbp] \centering - \begin{tabular}{@{}lll@{}} + \begin{tabular}{@{}L{2.2cm}L{3.6cm}L{7.2cm}@{}} \drhead Signal & ADAU1701 pin & ESP32-S3 GPIO \\ \midrule SDA & --- & GPIO4 \\ @@ -247,7 +249,7 @@ serial number. Its 7-bit address is 0x52 (A0 to GND, A1 to 3V3). \begin{table}[htbp] \centering - \begin{tabular}{@{}lll@{}} + \begin{tabular}{@{}L{2.2cm}L{3.6cm}L{7.2cm}@{}} \drhead Device & 7-bit address & Set by \\ \midrule ADAU1701 & 0x34 & ADDR0, ADDR1 = GND \\ @@ -261,7 +263,8 @@ serial number. Its 7-bit address is 0x52 (A0 to GND, A1 to 3V3). \subsection{FSC-BT1035 Bluetooth} \begin{table}[htbp] \centering - \begin{tabular}{@{}llll@{}} + \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 \\ @@ -285,7 +288,7 @@ I\textsuperscript{2}S source lines that feed the mixer. \begin{table}[htbp] \centering \small - \begin{tabular}{@{}lll@{}} + \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) \\ @@ -302,7 +305,7 @@ I\textsuperscript{2}S source lines that feed the mixer. \begin{table}[htbp] \centering - \begin{tabular}{@{}lll@{}} + \begin{tabular}{@{}L{2.2cm}L{3.6cm}L{7.2cm}@{}} \drhead Signal & ESP32-S3 GPIO & Direction \\ \midrule BCLK & GPIO6 & in from ADAU (master) \\ @@ -365,12 +368,13 @@ satisfying the +10\,\textmu s requirement in practice. \begin{table}[htbp] \centering \small - \begin{tabular}{@{}lll@{}} + \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 (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 \\ @@ -379,19 +383,17 @@ satisfying the +10\,\textmu s requirement in practice. INTB & interrupt line, external pull-up (GPIO39) & verified \\ \bottomrule \end{tabular} - \caption{Si4684 design checks. References: - \texttt{Hardware/DATASHEET/SI4684-A10.pdf} (power sequencing, SPI, - supply levels) and \texttt{Hardware/DATASHEET/AN851.pdf} (bypass and layout).} + \caption{Si4684 design checks (datasheet references below).} \label{tab:hw-val-si4684} \end{table} \begin{drref}[Datasheet] -Power sequencing and SPI framing: -\texttt{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: \texttt{Hardware/DATASHEET/AN851.pdf}, -\emph{Si468x Schematic and Layout Guide}. Boot and command protocol: AN649. -Local copies: \texttt{Hardware/DATASHEET/} (see \texttt{README.md}). +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 @@ -415,7 +417,7 @@ locks up when input data arrives. \begin{table}[htbp] \centering \small - \begin{tabular}{@{}lll@{}} + \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 \\ @@ -452,18 +454,17 @@ Schematic \texttt{DigitalRadio.pdf} and BOM list R1 (SCL) and R16 (SDA) as \begin{table}[htbp] \centering \small - \begin{tabular}{@{}lll@{}} + \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 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. Datasheet: - \texttt{Hardware/DATASHEET/FSC-BT1035\_Datasheet\_EN.pdf}; AT commands: - \texttt{FSC-BT1035\_programming\_user\_guide\_1.1.1.pdf} §5.} + \caption{FSC-BT1035 design checks (datasheets in \drpath{Hardware/DATASHEET/}).} \label{tab:hw-val-bt1035} \end{table} @@ -479,7 +480,8 @@ UART 115200/8/N/1, SSP on, auto-reconnect configurable via \begin{table}[htbp] \centering - \begin{tabular}{@{}lll@{}} + \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 \\ diff --git a/Software/docs/manual/ch-si4684.tex b/Software/docs/manual/ch-si4684.tex index b600aea..a51c7ed 100644 --- a/Software/docs/manual/ch-si4684.tex +++ b/Software/docs/manual/ch-si4684.tex @@ -38,7 +38,8 @@ uGreen licence); \texttt{.gitignore} keeps them on the developer machine only. \begin{table}[htbp] \centering - \begin{tabular}{@{}llp{6.2cm}@{}} + \footnotesize + \begin{tabular}{@{}L{3.2cm}L{2.2cm}L{8.2cm}@{}} \toprule \textbf{Local file} & \textbf{Typ.\ size} & \textbf{Source} \\ \midrule @@ -99,7 +100,8 @@ 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 +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), @@ -167,7 +169,7 @@ versa for DAB. \begin{table}[htbp] \centering - \begin{tabular}{@{}ll@{}} + \begin{tabular}{@{}L{4.2cm}L{9.2cm}@{}} \toprule \textbf{Method} & \textbf{Purpose} \\ \midrule @@ -284,7 +286,7 @@ selects the blob: \begin{table}[htbp] \centering - \begin{tabular}{@{}lll@{}} + \begin{tabular}{@{}L{2.4cm}L{3.6cm}L{7.2cm}@{}} \drhead Band & Image loaded & Primary API \\ \midrule \texttt{Si4684Band::Dab} & \texttt{dab\_firmware.bin} & @@ -309,14 +311,16 @@ The setup UI and REST clients use \texttt{tuner::TunerService}, which wraps \begin{table}[htbp] \centering - \small - \begin{tabular}{@{}llp{5.5cm}@{}} + \footnotesize + \begin{tabular}{@{}L{2.8cm}L{1.6cm}L{8.2cm}@{}} \drhead Endpoint & Band & Action \\ \midrule \texttt{POST /api/tuner/tune} & - DAB & \texttt{\{"band":"dab","freq\_index":0..37\}} \\ + DAB & \texttt{\{"band":"dab",}\\ + & & \texttt{"freq\_index":0..37\}} \\ \texttt{POST /api/tuner/tune} & - FM & \texttt{\{"band":"fm","frequency\_khz":64000..108000\}} \\ + FM & \texttt{\{"band":"fm",}\\ + & & \texttt{"frequency\_khz":64000..108000\}} \\ \texttt{GET /api/tuner/services} & DAB only & Programme list for ensemble \\ \texttt{POST /api/tuner/play} & DAB only & Start \texttt{service\_id}/\texttt{component\_id} \\ \texttt{POST /api/tuner/seek} & FM only & Seek up/down, return new kHz \\ diff --git a/Software/docs/manual/ch-sigmastudio.tex b/Software/docs/manual/ch-sigmastudio.tex index fa99354..e26bc73 100644 --- a/Software/docs/manual/ch-sigmastudio.tex +++ b/Software/docs/manual/ch-sigmastudio.tex @@ -32,7 +32,7 @@ settings are collected in Table~\ref{tab:ss-hwcfg}. \begin{table}[htbp] \centering - \begin{tabular}{@{}ll@{}} + \begin{tabular}{@{}L{4.2cm}L{9.2cm}@{}} \drhead Setting & Value \\ \midrule Control port (I\textsuperscript{2}C address) & 0x34 (ADDR0/ADDR1 = GND) \\ @@ -57,7 +57,7 @@ matches the board GPIO map (Section~\ref{sec:hw-gpio}). \begin{table}[htbp] \centering - \begin{tabular}{@{}lll@{}} + \begin{tabular}{@{}L{2.4cm}L{3.6cm}L{7.2cm}@{}} \drhead MP pin & Direction / function & Signal \\ \midrule MP0 & Input Sdata\_in0 & audio from Si4684 (radio) \\ @@ -107,7 +107,7 @@ digital outputs that feed the Bluetooth module. \begin{table}[htbp] \centering \small - \begin{tabular}{@{}lll@{}} + \begin{tabular}{@{}L{2.4cm}L{3.6cm}L{7.2cm}@{}} \drhead Stage & Block & Role \\ \midrule Input & Input (ch. 2--5) & radio L/R, ESP32 L/R \\ @@ -144,10 +144,11 @@ firmware. \begin{table}[htbp] \centering - \begin{tabular}{@{}lllll@{}} + \footnotesize + \begin{tabular}{@{}L{1.4cm}L{2.4cm}L{2.2cm}L{1.6cm}L{1.2cm}@{}} \drhead Band & Type & Frequency & Gain & Q \\ \midrule - 1 & Butterworth High (high-pass) & 20\,Hz & --- & 1.41 \\ + 1 & HP Butterworth & 20\,Hz & --- & 1.41 \\ 2 & Peaking & 100\,Hz & 0\,dB & 1.0 \\ 3 & Peaking & 400\,Hz & 0\,dB & 1.0 \\ 4 & Peaking & 1\,kHz & 0\,dB & 1.0 \\ @@ -177,7 +178,7 @@ Table~\ref{tab:ss-lim}. \begin{table}[htbp] \centering - \begin{tabular}{@{}ll@{}} + \begin{tabular}{@{}L{4.2cm}L{9.2cm}@{}} \drhead Parameter & Value \\ \midrule RMS TC & 50\,dB/s \\ @@ -199,7 +200,7 @@ SigmaStudio export (Section~\ref{sec:ss-export}). \begin{table}[htbp] \centering - \begin{tabular}{@{}lll@{}} + \begin{tabular}{@{}L{2.4cm}L{3.6cm}L{7.2cm}@{}} \drhead Control & Block & Runtime-adjustable \\ \midrule Source levels (2) & Si4674 / ESP32 faders & yes \\ diff --git a/Software/docs/manual/digiradio-manual.sty b/Software/docs/manual/digiradio-manual.sty index 1e4bd14..a7f0ccb 100644 --- a/Software/docs/manual/digiradio-manual.sty +++ b/Software/docs/manual/digiradio-manual.sty @@ -23,10 +23,16 @@ \RequirePackage{titlesec} \RequirePackage{booktabs} \RequirePackage{array} +\RequirePackage{ragged2e} +\RequirePackage{tabularx} \RequirePackage{enumitem} \RequirePackage[most]{tcolorbox} \RequirePackage{graphicx} +% Wrapping column type for tables (use L{width} instead of l). +\newcolumntype{L}[1]{>{\RaggedRight\arraybackslash}p{#1}} +\setlength{\emergencystretch}{5em} + % ---------- Fonts (engine-aware) --------------------------------------- \ifPDFTeX \RequirePackage[T1]{fontenc} @@ -72,6 +78,7 @@ \setlength{\parindent}{0pt} % ---------- Links ------------------------------------------------------- +\RequirePackage{xurl} \RequirePackage{hyperref} \hypersetup{colorlinks=true, linkcolor=drPetrol, urlcolor=drAmber, citecolor=drTeal} @@ -119,6 +126,7 @@ 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, + before upper={\RaggedRight}, }} \newtcolorbox{drnote}[1][Note]{dr@base, @@ -174,5 +182,12 @@ } % inline code: \drcode|std::expected| \newcommand{\code}[1]{{\ttfamily\color{drPetrol}#1}} +% Breakable repo/file paths (use instead of long \texttt{...}). +\newcommand{\drpath}[1]{\nolinkurl{#1}} +% HTTP API subsection headings that wrap at slashes. +\newcommand{\apiendpoint}[2]{% + \subsection{\texorpdfstring{% + {\raggedright\texttt{#1} \texttt{#2}\par}}{#1 #2}}% +} \endinput