From 145a651e2a39d5fdfe1dd1a395e327acafe6a7a6 Mon Sep 17 00:00:00 2001 From: Michele Bigi Date: Sat, 1 Aug 2026 23:34:38 +0200 Subject: [PATCH] Refactor HubAudio architecture domains and add documentation tooling --- .../ADR-001-ADAU1467-Audio-Domain-Master.md | 20 +- docs/adr/ADR-002-SPI-Control-Architecture.md | 38 +- .../ADR-003-I2S-Audio-Routing-Architecture.md | 28 +- docs/adr/ADR-004-Power-Domain-Architecture.md | 2 +- .../ADAU1467-Hardware-Architecture.md | 385 +++++++++++++ .../HubAudio-Clock-Architecture.md | 38 +- .../architecture/HubAudio-I2S-Architecture.md | 62 +- .../architecture/HubAudio-SPI-Architecture.md | 66 +-- .../HubAudio-System-Architecture.md | 141 +++-- docs/architecture/Power_Architecture.md | 2 +- docs/architecture/Power_Domains.md | 4 +- docs/knowledge/architecture-review.md | 203 +++++++ tools/docs/architecture_linter.py | 529 ++++++++++++++++++ tools/docs/role_refactor.py | 169 ++++++ tools/docs/roles.yml | 51 ++ 15 files changed, 1537 insertions(+), 201 deletions(-) create mode 100644 docs/architecture/ADAU1467-Hardware-Architecture.md create mode 100644 docs/knowledge/architecture-review.md create mode 100644 tools/docs/architecture_linter.py create mode 100644 tools/docs/role_refactor.py create mode 100644 tools/docs/roles.yml diff --git a/docs/adr/ADR-001-ADAU1467-Audio-Domain-Master.md b/docs/adr/ADR-001-ADAU1467-Audio-Domain-Master.md index 7a9fb88..752bf22 100644 --- a/docs/adr/ADR-001-ADAU1467-Audio-Domain-Master.md +++ b/docs/adr/ADR-001-ADAU1467-Audio-Domain-Master.md @@ -1,4 +1,4 @@ -# ADR-001: ADAU1467 as Audio Domain Master +# ADR-001: Audio Processor as Audio Domain Master - Status: Accepted - Date: 2026-08-01 @@ -9,8 +9,8 @@ HubAudio is designed as a modular digital audio platform integrating several audio sources and destinations: -- ESP32-S3 streaming subsystem -- Si4684 radio receiver +- System Controller streaming subsystem +- Radio Receiver radio receiver - Bluetooth RX/TX modules - Digital audio converters - Analog CODEC/DAC stages @@ -22,13 +22,13 @@ The system requires a central component responsible for: - timing synchronization - audio stream management -The ADAU1467 has been selected as the central audio processor. +The Audio Processor has been selected as the central audio processor. ## Decision -The ADAU1467 is the master component of the HubAudio Audio Domain. +The Audio Processor is the master component of the HubAudio Audio Domain. -The ADAU1467 is responsible for: +The Audio Processor is responsible for: - DSP processing - audio routing @@ -37,10 +37,10 @@ The ADAU1467 is responsible for: - audio clock generation - synchronization of external audio peripherals -The ADAU1467 is considered the audio domain master. +The Audio Processor is considered the audio domain master. -The ESP32-S3 participates in the Audio Domain as a digital audio source. It does not act as the audio timing master or routing controller. Its role inside the audio domain is equivalent to other digital audio sources. -The ESP32-S3 has a dual role: +The System Controller participates in the Audio Domain as a digital audio source. It does not act as the audio timing master or routing controller. Its role inside the audio domain is equivalent to other digital audio sources. +The System Controller has a dual role: - audio source inside the Audio Domain system supervisor inside the Control Domain @@ -71,7 +71,7 @@ It operates as system supervisor and is responsible for: ## Rationale -The ADAU1467 is selected not only as a DSP processor but as the central +The Audio Processor is selected not only as a DSP processor but as the central controller of the digital audio domain. This decision defines the HubAudio architecture. diff --git a/docs/adr/ADR-002-SPI-Control-Architecture.md b/docs/adr/ADR-002-SPI-Control-Architecture.md index be64848..b5ff511 100644 --- a/docs/adr/ADR-002-SPI-Control-Architecture.md +++ b/docs/adr/ADR-002-SPI-Control-Architecture.md @@ -11,9 +11,9 @@ control and firmware management. The main devices involved are: -- ESP32-S3 system controller -- ADAU1467 audio processor -- Si4684 radio receiver +- System Controller system controller +- Audio Processor audio processor +- Radio Receiver radio receiver A clear separation between system control and internal device management is required. @@ -25,9 +25,9 @@ audio transport interface. The SPI architecture is divided into independent functional domains. -The ESP32-S3 operates as the master of the system control SPI bus. +The System Controller operates as the master of the system control SPI bus. -The ADAU1467 and Si4684 expose SPI slave interfaces for external +The Audio Processor and Radio Receiver expose SPI slave interfaces for external configuration and control. The internal management of each device remains under the responsibility of @@ -37,48 +37,48 @@ the device itself. System control SPI domain: - ESP32-S3 + System Controller SPI MASTER | +---------+---------+ | | - ADAU1467 Si4684 + Audio Processor Radio Receiver SPI SLAVE SPI SLAVE -## ADAU1467 Configuration Domain +## Audio Processor Configuration Domain -The ADAU1467 manages its own external configuration memory through its +The Audio Processor manages its own external configuration memory through its internal SPI master interface. - ADAU1467 + Audio Processor SPI MASTER | - 25AA1024 + Audio EEPROM DSP Program / Configuration Memory -The ESP32-S3 controls the ADAU1467 through the external SPI interface but +The System Controller controls the Audio Processor through the external SPI interface but does not directly access the DSP configuration memory during normal operation. -## Si4684 Firmware Domain +## Radio Receiver Firmware Domain -The Si4684 firmware loading and configuration process is managed through +The Radio Receiver firmware loading and configuration process is managed through commands exchanged on the external SPI control interface. - ESP32-S3 + System Controller SPI MASTER | - Si4684 + Radio Receiver | @@ -88,8 +88,8 @@ commands exchanged on the external SPI control interface. Internal RAM -The ESP32-S3 controls the initialization process but does not directly access -the internal operational memory of the Si4684. +The System Controller controls the initialization process but does not directly access +the internal operational memory of the Radio Receiver. ## Consequences @@ -108,7 +108,7 @@ the internal operational memory of the Si4684. ## Rationale -The ESP32-S3 supervises the complete HubAudio system but does not replace the +The System Controller supervises the complete HubAudio system but does not replace the internal controllers of specialized devices. Each component remains responsible for its own functional domain. diff --git a/docs/adr/ADR-003-I2S-Audio-Routing-Architecture.md b/docs/adr/ADR-003-I2S-Audio-Routing-Architecture.md index 5bc39f2..9a939cc 100644 --- a/docs/adr/ADR-003-I2S-Audio-Routing-Architecture.md +++ b/docs/adr/ADR-003-I2S-Audio-Routing-Architecture.md @@ -10,8 +10,8 @@ HubAudio integrates multiple digital audio sources and destinations: Sources: -- ESP32-S3 streaming subsystem -- Si4684 radio receiver +- System Controller streaming subsystem +- Radio Receiver radio receiver - Bluetooth receiver - Optical digital input @@ -25,7 +25,7 @@ A deterministic and scalable digital audio routing architecture is required. ## Decision -The ADAU1467 is the central routing element of the Audio Domain. +The Audio Processor is the central routing element of the Audio Domain. Each major audio device is assigned to a dedicated serial audio interface. @@ -35,36 +35,36 @@ The preferred architecture is: One audio device = One dedicated I2S interface -The ADAU1467 operates as the audio timing reference. +The Audio Processor operates as the audio timing reference. External audio devices operate as I2S slaves whenever supported. ## Audio Input Allocation -| ADAU1467 Port | Device | Function | +| Audio Processor Port | Device | Function | |---|---|---| -| SDATA_IN0 | ESP32-S3 | Network audio stream | -| SDATA_IN1 | Si4684 | Radio audio | +| SDATA_IN0 | System Controller | Network audio stream | +| SDATA_IN1 | Radio Receiver | Radio audio | | SDATA_IN2 | DECODEC | Optical digital input | | SDATA_IN3 | Bluetooth RX | Wireless audio input | -ESP32-S3 -------- -Si4684 --------- -DECODEC ----------+---- ADAU1467 +System Controller -------- +Radio Receiver --------- +DECODEC ----------+---- Audio Processor BT RX ---------/ ## Audio Output Allocation -| ADAU1467 Port | Device | Function | +| Audio Processor Port | Device | Function | |---|---|---| | SDATA_OUT0 | CODEC/DAC | Analog audio output | | SDATA_OUT1 | Bluetooth TX | Wireless audio output | | SDATA_OUT2 | ENCODEC | Optical digital output | | SDATA_OUT3 | Reserved | Future expansion | - ADAU1467 + Audio Processor | +------------+------------+ @@ -73,7 +73,7 @@ BT RX ---------/ ## Clocking -The ADAU1467 provides the master audio timing reference. +The Audio Processor provides the master audio timing reference. The audio clock domain consists of: @@ -105,4 +105,4 @@ domain. HubAudio prioritizes signal integrity, maintainability and deterministic audio behavior over maximum bus utilization. -The ADAU1467 acts as the central audio router of the system. \ No newline at end of file +The Audio Processor acts as the central audio router of the system. \ No newline at end of file diff --git a/docs/adr/ADR-004-Power-Domain-Architecture.md b/docs/adr/ADR-004-Power-Domain-Architecture.md index d8b681b..76aa65a 100644 --- a/docs/adr/ADR-004-Power-Domain-Architecture.md +++ b/docs/adr/ADR-004-Power-Domain-Architecture.md @@ -7,7 +7,7 @@ HubAudio integra sottosistemi con caratteristiche elettriche molto differenti: -- elaborazione digitale (ESP32-S3) +- elaborazione digitale (System Controller) - DSP audio - ricevitore radio - Bluetooth diff --git a/docs/architecture/ADAU1467-Hardware-Architecture.md b/docs/architecture/ADAU1467-Hardware-Architecture.md new file mode 100644 index 0000000..d7c6941 --- /dev/null +++ b/docs/architecture/ADAU1467-Hardware-Architecture.md @@ -0,0 +1,385 @@ +# ADAU1467 Hardware Architecture + +- Status: Draft +- Date: 2026-08-01 +- Document Type: Component Architecture + + +# 1. Overview + +The ADAU1467 is the central audio processor of HubAudio. + +It represents the boundary between: + +- Control Domain +- Audio Domain +- Time Domain + +The device provides: + +- SigmaDSP processing +- digital audio routing +- serial audio interfaces +- clock generation +- self boot capability + + +The ADAU1467 is not considered a simple peripheral but the master component +of the Audio Domain. + + +--- + +# 2. Functional Role + +The ADAU1467 performs: + +- DSP execution +- audio mixing +- signal routing +- sample rate management +- digital audio synchronization + + +The ESP32-S3 configures the ADAU1467 but does not process real-time audio. + + +Architecture: + + +ESP32-S3 + +| +| + +SPI + +| + +ADAU1467 + +| +| + +I2S + +Audio Peripherals + + + +--- + +# 3. Power Architecture + +The ADAU1467 requires separated power domains. + +Main domains: + + +Digital Supply + +DVDD + +| + +Digital core + +Analog Supply + +AVDD + +| + +PLL and analog sections + +Interface Supply + +IOVDD + +| + +Digital interfaces + + + +Power design rules: + +- local decoupling on every supply pin +- clean analog supply +- short return paths +- separation between noisy digital regulators and audio rails + + +The ADAU1467 power domains must be integrated with the HubAudio power +architecture. + + +--- + +# 4. Master Clock Architecture + + +The ADAU1467 uses an external reference clock. + +Target audio clock family: + + +12.288 MHz + +48 kHz × 256 + + + +Clock chain: + + +12.288 MHz Reference + + | + + ADAU1467 + + | + +Internal PLL + + | + +Audio Clock Domain + + | + +MCLK / BCLK / LRCLK + + + +The ADAU1467 defines the timing reference of the Audio Domain. + + +--- + +# 5. Clock Distribution + + +The ADAU1467 clock output can be distributed using a dedicated clock buffer. + + + ADAU1467 + + Clock Master + + | + + MCLK + + | + + PCS2P2309NZ + + Clock Buffer + + +-----------+-----------+ + + | | | + + CODEC BT Radio + + +The PCS2P2309NZ provides fan-out and signal integrity improvement. + +It does not generate the audio clock. + + +--- + +# 6. SPI Control Interface + + +The ADAU1467 provides an SPI control interface. + + +Connection: + + +ESP32-S3 + +SPI MASTER + + | + + | + +ADAU1467 + +SPI SLAVE + + + +Used for: + +- configuration +- parameter update +- status monitoring + + +--- + +# 7. Self Boot EEPROM + + +The ADAU1467 supports self boot from external EEPROM. + + +HubAudio implementation: + + + +ADAU1467 + +SPI MASTER + + | + +25AA1024 EEPROM + + | + +DSP Program + + + +During normal operation: + +- ESP32 configures the ADAU1467 +- ADAU1467 manages its DSP memory + + +The EEPROM remains part of the Audio Processor domain. + + +--- + +# 8. Serial Audio Interfaces + + +The ADAU1467 provides multiple serial audio ports. + + +HubAudio allocation: + + +Inputs: + + +SDATA_IN0 + +ESP32-S3 + +SDATA_IN1 + +Si4684 + +SDATA_IN2 + +Optical DECODEC + +SDATA_IN3 + +Bluetooth RX + + + +Outputs: + + +SDATA_OUT0 + +CODEC + +SDATA_OUT1 + +Bluetooth TX + +SDATA_OUT2 + +Optical ENCODEC + + + +The ADAU1467 operates as audio timing master. + + +--- + +# 9. Boot Sequence + + + +Power ON + +| + +ESP32-S3 startup + +| + +Configure ADAU1467 + +| + +ADAU1467 loads DSP program + +| + +Audio clocks enabled + +| + +Audio peripherals synchronized + +| + +System ready + + + +--- + +# 10. PCB Design Requirements + + +Critical signals: + +- MCLK +- BCLK +- LRCLK +- SPI +- I2S DATA + + +Layout rules: + +- continuous ground reference +- short clock traces +- avoid RF proximity +- local decoupling +- controlled return currents + + +The ADAU1467 section should be treated as a high-performance mixed-signal +audio subsystem. + + +--- + +# 11. Design Philosophy + + +The ADAU1467 is the conductor of the HubAudio orchestra. + +The ESP32-S3 provides instructions. + +The peripherals provide instruments. + +The ADAU1467 defines timing, routing and processing. + diff --git a/docs/architecture/HubAudio-Clock-Architecture.md b/docs/architecture/HubAudio-Clock-Architecture.md index 6f707e8..99afb02 100644 --- a/docs/architecture/HubAudio-Clock-Architecture.md +++ b/docs/architecture/HubAudio-Clock-Architecture.md @@ -9,7 +9,7 @@ The HubAudio architecture defines a centralized audio timing domain. -The ADAU1467 is the master of the audio clock system. +The Audio Processor is the master of the audio clock system. The purpose of this architecture is to provide a single timing reference for all digital audio devices, avoiding independent clock domains and minimizing @@ -18,7 +18,7 @@ sample synchronization problems. The audio clock domain is composed of: - Master oscillator -- ADAU1467 PLL and clock generation +- Audio Processor PLL and clock generation - Clock distribution stage - Audio peripheral clock inputs @@ -27,9 +27,9 @@ The audio clock domain is composed of: # 2. Audio Clock Master -The ADAU1467 is responsible for generating the audio timing reference. +The Audio Processor is responsible for generating the audio timing reference. -The ADAU1467 provides: +The Audio Processor provides: - DSP processing clock - Serial audio clock generation @@ -43,7 +43,7 @@ Conceptually: | | - ADAU1467 + Audio Processor DSP + Audio Clock Master @@ -51,7 +51,7 @@ Conceptually: MCLK / BCLK / LRCLK -The ADAU1467 is the timing authority of the Audio Domain. +The Audio Processor is the timing authority of the Audio Domain. --- @@ -91,9 +91,9 @@ Future support for 44.1 kHz family may require: # 4. Clock Distribution -The ADAU1467 clock output is distributed through a dedicated clock buffer. +The Audio Processor clock output is distributed through a dedicated clock buffer. -The PCS2P2309NZ is used as clock distribution element. +The Clock Buffer is used as clock distribution element. Its role is: @@ -107,7 +107,7 @@ It does not generate the audio clock. Architecture: - ADAU1467 + Audio Processor Audio Clock Master @@ -117,7 +117,7 @@ Architecture: | - PCS2P2309NZ + Clock Buffer Clock Distribution @@ -125,7 +125,7 @@ Architecture: | | | | | | - Si4684 BT Modules CODEC + Radio Receiver BT Modules CODEC --- @@ -135,7 +135,7 @@ All digital audio peripherals belong to the same clock domain. Expected clock relationships: - ADAU1467 + Audio Processor | @@ -147,7 +147,7 @@ Expected clock relationships: +------+------+------+------+ | | | | -ESP32 Si4684 BT RX CODEC +ESP32 Radio Receiver BT RX CODEC @@ -167,7 +167,7 @@ The audio data flow is independent from control communication. Control: -ESP32-S3 +System Controller | | @@ -176,7 +176,7 @@ SPI | -ADAU1467 / Si4684 +Audio Processor / Radio Receiver @@ -192,13 +192,13 @@ Source Device | | -ADAU1467 +Audio Processor Timing: -ADAU1467 +Audio Processor | | @@ -266,8 +266,8 @@ Clock signals must always reference a continuous ground plane. The HubAudio clock architecture follows the same principle as a musical orchestra: -The ADAU1467 is the conductor. +The Audio Processor is the conductor. -The PCS2P2309NZ distributes the beat. +The Clock Buffer distributes the beat. All audio devices perform synchronized to the same timing reference. \ No newline at end of file diff --git a/docs/architecture/HubAudio-I2S-Architecture.md b/docs/architecture/HubAudio-I2S-Architecture.md index fc926d2..2609637 100644 --- a/docs/architecture/HubAudio-I2S-Architecture.md +++ b/docs/architecture/HubAudio-I2S-Architecture.md @@ -10,7 +10,7 @@ The HubAudio audio architecture is based on a centralized digital audio processing model. -The ADAU1467 is the core audio processor and manages: +The Audio Processor is the core audio processor and manages: - digital audio routing - DSP processing @@ -18,7 +18,7 @@ The ADAU1467 is the core audio processor and manages: - synchronization - audio stream conversion -All digital audio streams are connected to the ADAU1467 through serial audio +All digital audio streams are connected to the Audio Processor through serial audio interfaces. The audio domain is independent from the system control domain. @@ -26,7 +26,7 @@ The audio domain is independent from the system control domain. CONTROL DOMAIN -ESP32-S3 +System Controller | | SPI @@ -35,8 +35,8 @@ Configuration AUDIO DOMAIN -ESP32-S3 -Si4684 +System Controller +Radio Receiver BT RX Optical Input @@ -44,7 +44,7 @@ Optical Input | v -ADAU1467 +Audio Processor | | @@ -58,7 +58,7 @@ Optical Output # 2. Audio Clock Master -The ADAU1467 is the master of the audio timing domain. +The Audio Processor is the master of the audio timing domain. The generated audio clock consists of: @@ -70,7 +70,7 @@ The generated audio clock consists of: All external audio devices should operate as synchronized slaves whenever supported. - ADAU1467 + Audio Processor AUDIO CLOCK MASTER @@ -82,64 +82,64 @@ supported. | +------------+------------+ | | | - Si4684 BT RX CODEC + Radio Receiver BT RX CODEC --- # 3. Input Audio Interfaces -The ADAU1467 provides multiple serial input ports. +The Audio Processor provides multiple serial input ports. The HubAudio input allocation is: | ADAU Port | Source | Description | |-----------|--------|-------------| -| SDATA_IN0 | ESP32-S3 | Network audio stream | -| SDATA_IN1 | Si4684 | Radio receiver audio | +| SDATA_IN0 | System Controller | Network audio stream | +| SDATA_IN1 | Radio Receiver | Radio receiver audio | | SDATA_IN2 | DECODEC | Optical digital input | | SDATA_IN3 | Bluetooth RX | Wireless audio input | -## ESP32-S3 Audio Input +## System Controller Audio Input -The ESP32-S3 acts as a digital audio source. +The System Controller acts as a digital audio source. Its role inside the Audio Domain is equivalent to any other audio source. -ESP32-S3 +System Controller I2S DATA OUT | | v -ADAU1467 SDATA_IN0 +Audio Processor SDATA_IN0 -The ESP32-S3 does not control the audio timing. +The System Controller does not control the audio timing. -The timing is provided by the ADAU1467 clock domain. +The timing is provided by the Audio Processor clock domain. --- -## Si4684 Audio Input +## Radio Receiver Audio Input -The Si4684 provides decoded radio audio. +The Radio Receiver provides decoded radio audio. -Si4684 +Radio Receiver I2S DATA OUT | | v -ADAU1467 SDATA_IN1 +Audio Processor SDATA_IN1 -The Si4684 is a peripheral of the audio domain. +The Radio Receiver is a peripheral of the audio domain. It does not define the system audio clock. @@ -166,7 +166,7 @@ I2S | | -ADAU1467 SDATA_IN2 +Audio Processor SDATA_IN2 The decoder must support operation synchronized with the HubAudio clock @@ -190,7 +190,7 @@ I2S | | -ADAU1467 SDATA_IN3 +Audio Processor SDATA_IN3 The selected Bluetooth module must support external audio clock operation. @@ -200,7 +200,7 @@ The selected Bluetooth module must support external audio clock operation. # 4. Output Audio Interfaces -The ADAU1467 output allocation is: +The Audio Processor output allocation is: | ADAU Port | Destination | Description | |-----------|-------------|-------------| @@ -213,7 +213,7 @@ The ADAU1467 output allocation is: ## Analog Audio Output -ADAU1467 +Audio Processor SDATA_OUT0 @@ -232,7 +232,7 @@ Analog Output ## Bluetooth Transmission Output -ADAU1467 +Audio Processor SDATA_OUT1 @@ -251,7 +251,7 @@ Wireless Audio ## Optical Digital Output -ADAU1467 +Audio Processor SDATA_OUT2 @@ -269,7 +269,7 @@ SPDIF Optical Output # 5. I2S Versus TDM Strategy -The ADAU1467 supports multiple serial audio formats including: +The Audio Processor supports multiple serial audio formats including: - I2S - Left Justified @@ -325,5 +325,5 @@ The architecture reserves: - TDM expansion possibilities -The ADAU1467 remains the central audio routing element for future HubAudio +The Audio Processor remains the central audio routing element for future HubAudio versions. \ No newline at end of file diff --git a/docs/architecture/HubAudio-SPI-Architecture.md b/docs/architecture/HubAudio-SPI-Architecture.md index e1fe767..45e108c 100644 --- a/docs/architecture/HubAudio-SPI-Architecture.md +++ b/docs/architecture/HubAudio-SPI-Architecture.md @@ -26,7 +26,7 @@ The control architecture is based on independent SPI domains. CONTROL PLANE - ESP32-S3 + System Controller System Controller @@ -37,7 +37,7 @@ CONTROL PLANE +-----------+-----------+ | | -ADAU1467 Si4684 +Audio Processor Radio Receiver Audio Processor Radio Receiver @@ -45,9 +45,9 @@ Audio Processor Radio Receiver --- -# 2. ESP32-S3 Control Domain +# 2. System Controller Control Domain -The ESP32-S3 is the system supervisor. +The System Controller is the system supervisor. Its responsibilities are: @@ -58,9 +58,9 @@ Its responsibilities are: - firmware update coordination -The ESP32-S3 owns the main control SPI interface. +The System Controller owns the main control SPI interface. - ESP32-S3 + System Controller SPI MASTER @@ -68,7 +68,7 @@ The ESP32-S3 owns the main control SPI interface. +---------+---------+ | | - ADAU1467 Si4684 + Audio Processor Radio Receiver SPI SLAVE SPI SLAVE @@ -78,11 +78,11 @@ The control bus is independent from all audio data paths. --- -# 3. ADAU1467 SPI Domain +# 3. Audio Processor SPI Domain -The ADAU1467 contains its own SPI interface for external control. +The Audio Processor contains its own SPI interface for external control. -The ESP32-S3 uses this interface for: +The System Controller uses this interface for: - DSP configuration - parameter updates @@ -90,9 +90,9 @@ The ESP32-S3 uses this interface for: - status reading -The ADAU1467 also manages its external program memory. +The Audio Processor also manages its external program memory. - ADAU1467 + Audio Processor +----------------------+ | @@ -100,23 +100,23 @@ The ADAU1467 also manages its external program memory. | v - 25AA1024 + Audio EEPROM DSP Program Memory -The ESP32-S3 does not directly access the EEPROM during normal operation. +The System Controller does not directly access the EEPROM during normal operation. -The ADAU1467 is responsible for loading its DSP configuration. +The Audio Processor is responsible for loading its DSP configuration. --- -# 4. Si4684 SPI Domain +# 4. Radio Receiver SPI Domain -The Si4684 is controlled by the ESP32-S3 through its SPI slave interface. +The Radio Receiver is controlled by the System Controller through its SPI slave interface. -The ESP32-S3 manages: +The System Controller manages: - initialization sequence - command exchange @@ -124,13 +124,13 @@ The ESP32-S3 manages: - firmware loading procedure - ESP32-S3 + System Controller SPI MASTER | - Si4684 + Radio Receiver | @@ -141,7 +141,7 @@ The ESP32-S3 manages: Internal RAM -The Si4684 remains responsible for its internal operational memory. +The Radio Receiver remains responsible for its internal operational memory. --- @@ -152,7 +152,7 @@ The HubAudio architecture intentionally avoids a single shared SPI bus. The design uses: - ESP32-S3 + System Controller +-------------+ @@ -162,7 +162,7 @@ The design uses: | | - ADAU1467 Si4684 + Audio Processor Radio Receiver Advantages: @@ -186,7 +186,7 @@ Power ON | -ESP32-S3 boot +System Controller boot | @@ -194,14 +194,14 @@ Initialize SPI buses | -Configure ADAU1467 +Configure Audio Processor | -+--> ADAU loads DSP program from 25AA1024 ++--> ADAU loads DSP program from Audio EEPROM | -Configure Si4684 +Configure Radio Receiver | +--> Firmware initialization @@ -212,7 +212,7 @@ Enable Audio Domain | -ADAU1467 starts audio processing +Audio Processor starts audio processing @@ -224,7 +224,7 @@ ADAU1467 starts audio processing ## Control Domain -ESP32-S3 +System Controller | | @@ -249,7 +249,7 @@ I2S | -ADAU1467 +Audio Processor | @@ -284,11 +284,11 @@ Critical signals: # 9. Design Philosophy -The ESP32-S3 is the system coordinator. +The System Controller is the system coordinator. -The ADAU1467 is the audio processor. +The Audio Processor is the audio processor. -The Si4684 is a specialized audio peripheral. +The Radio Receiver is a specialized audio peripheral. Each component controls its own functional domain while remaining part of the complete HubAudio system. \ No newline at end of file diff --git a/docs/architecture/HubAudio-System-Architecture.md b/docs/architecture/HubAudio-System-Architecture.md index e6a4b9b..c61e250 100644 --- a/docs/architecture/HubAudio-System-Architecture.md +++ b/docs/architecture/HubAudio-System-Architecture.md @@ -8,99 +8,98 @@ # 1. Overview HubAudio is a modular digital audio platform designed around a centralized -audio processing architecture. +Audio Domain architecture. -The system separates three main functional domains: +The system separates three main functional areas: - Control Domain - Audio Domain -- Time Domain +- Clock Distribution Layer -Each domain has a clearly defined responsibility. +Each area has a clearly defined responsibility. The architecture is based on the principle: -ESP32-S3 manages the system. +System Controller System Controller manages the Control Domain. -ADAU1467 manages the audio. +Audio Processor Audio Processor manages the Audio Domain. -The clock domain synchronizes the orchestra. +The Clock Distribution Layer provides the synchronization reference +for all digital audio peripherals. - ---- +The Audio Processor acts as the timing and routing authority of the digital +audio infrastructure, while the System Controller provides supervision, +connectivity and configuration management. # 2. High Level Architecture - - HUBAUDIO CONTROL DOMAIN - ESP32-S3 + System Controller System Controller - WiFi / Network / UI + Network / UI / Configuration - | + | - | + | - SPI + SPI - | + | - +---------------+---------------+ + +--------------+--------------+ - | | + | | - ADAU1467 Si4684 + Audio Processor Audio Processor Radio Receiver Radio Receiver - Audio Processor Radio Receiver + | + | + | + AUDIO DOMAIN - | - | - | - AUDIO DOMAIN + Audio Sources: + + System Controller System Controller + Radio Receiver Radio Receiver + Bluetooth Receiver + Optical Input - | - +-------+-------+-------+-------+ - | | | | | + | -ESP32 Si4684 BT RX Optical Other + | - | + Audio Processing - ADAU1467 - - DSP / Routing / Mixing + DSP / Routing / Mixing - | + | - +-------+-------+-------+ + | - | | | + Audio Destinations: -CODEC BT TX Optical Out - - | - - TIME DOMAIN - - | - - Audio Clock Tree - - | - - MCLK / BCLK / LRCLK + CODEC/DAC + Bluetooth Transmitter + Optical Output ---- + | + + | + + CLOCK DISTRIBUTION LAYER + + | + + MCLK / BCLK / LRCLK # 3. Functional Domains @@ -112,7 +111,7 @@ The Control Domain is responsible for system management. Main component: -ESP32-S3 +System Controller Responsibilities: @@ -128,7 +127,7 @@ Responsibilities: Communication: -ESP32-S3 +System Controller | @@ -147,9 +146,9 @@ The Control Domain does not transport real-time audio. # 3.2 Audio Domain -The Audio Domain is centered around the ADAU1467. +The Audio Domain is centered around the Audio Processor. -The ADAU1467 is responsible for: +The Audio Processor is responsible for: - DSP processing - audio routing @@ -162,8 +161,8 @@ The ADAU1467 is responsible for: Audio sources: -ESP32-S3 -Si4684 +System Controller +Radio Receiver Bluetooth RX Optical Input @@ -191,7 +190,7 @@ I2S The Time Domain provides the synchronization reference. -The ADAU1467 is the audio clock master. +The Audio Processor is the audio clock master. The clock distribution provides: @@ -202,7 +201,7 @@ The clock distribution provides: Clock distribution: - ADAU1467 + Audio Processor Audio Clock Master @@ -218,7 +217,7 @@ Clock distribution: | | | - CODEC Si4684 BT + CODEC Radio Receiver BT --- @@ -226,7 +225,7 @@ Clock distribution: # 4. Component Roles -## ESP32-S3 +## System Controller Role: @@ -249,7 +248,7 @@ I2S Source --- -## ADAU1467 +## Audio Processor Role: @@ -275,7 +274,7 @@ Clock -> Synchronization --- -## Si4684 +## Radio Receiver Role: @@ -318,14 +317,14 @@ I2S | -ADAU1467 +Audio Processor Bluetooth TX: -ADAU1467 +Audio Processor | @@ -359,14 +358,14 @@ I2S | -ADAU1467 +Audio Processor Output: -ADAU1467 +Audio Processor | @@ -389,9 +388,9 @@ SPDIF HubAudio follows a distributed intelligence model. -The ESP32-S3 provides connectivity and supervision. +The System Controller provides connectivity and supervision. -The ADAU1467 provides audio intelligence. +The Audio Processor provides audio intelligence. Dedicated peripherals provide specialized functions. @@ -448,19 +447,19 @@ HubAudio is structured around three independent but coordinated planes: CONTROL PLANE -ESP32-S3 +System Controller | SPI AUDIO PLANE -ADAU1467 +Audio Processor | I2S TIME PLANE -ADAU1467 +Audio Processor | Clock Distribution diff --git a/docs/architecture/Power_Architecture.md b/docs/architecture/Power_Architecture.md index fa13f68..5cf069e 100644 --- a/docs/architecture/Power_Architecture.md +++ b/docs/architecture/Power_Architecture.md @@ -40,7 +40,7 @@ Il dominio digitale alimenta esclusivamente i componenti di controllo. Comprende: -- ESP32-S3 +- System Controller - EEPROM - GPIO Expander - Display diff --git a/docs/architecture/Power_Domains.md b/docs/architecture/Power_Domains.md index e617e4a..b32a2a5 100644 --- a/docs/architecture/Power_Domains.md +++ b/docs/architecture/Power_Domains.md @@ -31,7 +31,7 @@ Questa architettura permette: --- -# ADAU1467 Domain +# Audio Processor Domain ``` 3V3_AUDIO @@ -63,7 +63,7 @@ Le tensioni locali vengono generate mediante LDO dedicati. --- -# Si4684 Domain +# Radio Receiver Domain ``` 3V3_AUDIO diff --git a/docs/knowledge/architecture-review.md b/docs/knowledge/architecture-review.md new file mode 100644 index 0000000..b0dc689 --- /dev/null +++ b/docs/knowledge/architecture-review.md @@ -0,0 +1,203 @@ +# HubAudio Architecture Report + +## adr/ADR-001-ADAU1467-Audio-Domain-Master.md + +- Line 1: `ADAU1467` → `Audio Processor` +- Line 12: `ESP32-S3` → `System Controller` +- Line 13: `Si4684` → `Radio Receiver` +- Line 25: `ADAU1467` → `Audio Processor` +- Line 29: `ADAU1467` → `Audio Processor` +- Line 31: `ADAU1467` → `Audio Processor` +- Line 40: `ADAU1467` → `Audio Processor` +- Line 42: `ESP32-S3` → `System Controller` +- Line 43: `ESP32-S3` → `System Controller` +- Line 74: `ADAU1467` → `Audio Processor` + +## adr/ADR-002-SPI-Control-Architecture.md + +- Line 14: `ESP32-S3` → `System Controller` +- Line 15: `ADAU1467` → `Audio Processor` +- Line 16: `Si4684` → `Radio Receiver` +- Line 28: `ESP32-S3` → `System Controller` +- Line 30: `ADAU1467` → `Audio Processor` +- Line 30: `Si4684` → `Radio Receiver` +- Line 40: `ESP32-S3` → `System Controller` +- Line 47: `ADAU1467` → `Audio Processor` +- Line 47: `Si4684` → `Radio Receiver` +- Line 51: `ADAU1467` → `Audio Processor` +- Line 53: `ADAU1467` → `Audio Processor` +- Line 56: `ADAU1467` → `Audio Processor` +- Line 62: `25AA1024` → `Audio EEPROM` +- Line 66: `ADAU1467` → `Audio Processor` +- Line 66: `ESP32-S3` → `System Controller` +- Line 70: `Si4684` → `Radio Receiver` +- Line 72: `Si4684` → `Radio Receiver` +- Line 75: `ESP32-S3` → `System Controller` +- Line 81: `Si4684` → `Radio Receiver` +- Line 91: `ESP32-S3` → `System Controller` +- Line 92: `Si4684` → `Radio Receiver` +- Line 111: `ESP32-S3` → `System Controller` + +## adr/ADR-003-I2S-Audio-Routing-Architecture.md + +- Line 13: `ESP32-S3` → `System Controller` +- Line 14: `Si4684` → `Radio Receiver` +- Line 28: `ADAU1467` → `Audio Processor` +- Line 38: `ADAU1467` → `Audio Processor` +- Line 44: `ADAU1467` → `Audio Processor` +- Line 46: `ESP32-S3` → `System Controller` +- Line 47: `Si4684` → `Radio Receiver` +- Line 52: `ESP32-S3` → `System Controller` +- Line 53: `Si4684` → `Radio Receiver` +- Line 54: `ADAU1467` → `Audio Processor` +- Line 60: `ADAU1467` → `Audio Processor` +- Line 67: `ADAU1467` → `Audio Processor` +- Line 76: `ADAU1467` → `Audio Processor` +- Line 108: `ADAU1467` → `Audio Processor` + +## adr/ADR-004-Power-Domain-Architecture.md + +- Line 10: `ESP32-S3` → `System Controller` + +## architecture/HubAudio-Clock-Architecture.md + +- Line 12: `ADAU1467` → `Audio Processor` +- Line 21: `ADAU1467` → `Audio Processor` +- Line 30: `ADAU1467` → `Audio Processor` +- Line 32: `ADAU1467` → `Audio Processor` +- Line 46: `ADAU1467` → `Audio Processor` +- Line 54: `ADAU1467` → `Audio Processor` +- Line 94: `ADAU1467` → `Audio Processor` +- Line 96: `PCS2P2309NZ` → `Clock Buffer` +- Line 110: `ADAU1467` → `Audio Processor` +- Line 120: `PCS2P2309NZ` → `Clock Buffer` +- Line 128: `Si4684` → `Radio Receiver` +- Line 138: `ADAU1467` → `Audio Processor` +- Line 150: `Si4684` → `Radio Receiver` +- Line 170: `ESP32-S3` → `System Controller` +- Line 179: `ADAU1467` → `Audio Processor` +- Line 179: `Si4684` → `Radio Receiver` +- Line 195: `ADAU1467` → `Audio Processor` +- Line 201: `ADAU1467` → `Audio Processor` +- Line 269: `ADAU1467` → `Audio Processor` +- Line 271: `PCS2P2309NZ` → `Clock Buffer` + +## architecture/HubAudio-I2S-Architecture.md + +- Line 13: `ADAU1467` → `Audio Processor` +- Line 21: `ADAU1467` → `Audio Processor` +- Line 29: `ESP32-S3` → `System Controller` +- Line 38: `ESP32-S3` → `System Controller` +- Line 39: `Si4684` → `Radio Receiver` +- Line 47: `ADAU1467` → `Audio Processor` +- Line 61: `ADAU1467` → `Audio Processor` +- Line 73: `ADAU1467` → `Audio Processor` +- Line 85: `Si4684` → `Radio Receiver` +- Line 91: `ADAU1467` → `Audio Processor` +- Line 97: `ESP32-S3` → `System Controller` +- Line 98: `Si4684` → `Radio Receiver` +- Line 103: `ESP32-S3` → `System Controller` +- Line 105: `ESP32-S3` → `System Controller` +- Line 110: `ESP32-S3` → `System Controller` +- Line 117: `ADAU1467` → `Audio Processor` +- Line 120: `ESP32-S3` → `System Controller` +- Line 122: `ADAU1467` → `Audio Processor` +- Line 127: `Si4684` → `Radio Receiver` +- Line 129: `Si4684` → `Radio Receiver` +- Line 132: `Si4684` → `Radio Receiver` +- Line 139: `ADAU1467` → `Audio Processor` +- Line 142: `Si4684` → `Radio Receiver` +- Line 169: `ADAU1467` → `Audio Processor` +- Line 193: `ADAU1467` → `Audio Processor` +- Line 203: `ADAU1467` → `Audio Processor` +- Line 216: `ADAU1467` → `Audio Processor` +- Line 235: `ADAU1467` → `Audio Processor` +- Line 254: `ADAU1467` → `Audio Processor` +- Line 272: `ADAU1467` → `Audio Processor` +- Line 328: `ADAU1467` → `Audio Processor` + +## architecture/HubAudio-SPI-Architecture.md + +- Line 29: `ESP32-S3` → `System Controller` +- Line 40: `ADAU1467` → `Audio Processor` +- Line 40: `Si4684` → `Radio Receiver` +- Line 48: `ESP32-S3` → `System Controller` +- Line 50: `ESP32-S3` → `System Controller` +- Line 61: `ESP32-S3` → `System Controller` +- Line 63: `ESP32-S3` → `System Controller` +- Line 71: `ADAU1467` → `Audio Processor` +- Line 71: `Si4684` → `Radio Receiver` +- Line 81: `ADAU1467` → `Audio Processor` +- Line 83: `ADAU1467` → `Audio Processor` +- Line 85: `ESP32-S3` → `System Controller` +- Line 93: `ADAU1467` → `Audio Processor` +- Line 95: `ADAU1467` → `Audio Processor` +- Line 103: `25AA1024` → `Audio EEPROM` +- Line 108: `ESP32-S3` → `System Controller` +- Line 110: `ADAU1467` → `Audio Processor` +- Line 115: `Si4684` → `Radio Receiver` +- Line 117: `ESP32-S3` → `System Controller` +- Line 117: `Si4684` → `Radio Receiver` +- Line 119: `ESP32-S3` → `System Controller` +- Line 127: `ESP32-S3` → `System Controller` +- Line 133: `Si4684` → `Radio Receiver` +- Line 144: `Si4684` → `Radio Receiver` +- Line 155: `ESP32-S3` → `System Controller` +- Line 165: `ADAU1467` → `Audio Processor` +- Line 165: `Si4684` → `Radio Receiver` +- Line 189: `ESP32-S3` → `System Controller` +- Line 197: `ADAU1467` → `Audio Processor` +- Line 200: `25AA1024` → `Audio EEPROM` +- Line 204: `Si4684` → `Radio Receiver` +- Line 215: `ADAU1467` → `Audio Processor` +- Line 227: `ESP32-S3` → `System Controller` +- Line 252: `ADAU1467` → `Audio Processor` +- Line 287: `ESP32-S3` → `System Controller` +- Line 289: `ADAU1467` → `Audio Processor` +- Line 291: `Si4684` → `Radio Receiver` + +## architecture/HubAudio-System-Architecture.md + +- Line 24: `ESP32-S3` → `System Controller` +- Line 26: `ADAU1467` → `Audio Processor` +- Line 42: `ESP32-S3` → `System Controller` +- Line 58: `ADAU1467` → `Audio Processor` +- Line 58: `Si4684` → `Radio Receiver` +- Line 73: `Si4684` → `Radio Receiver` +- Line 77: `ADAU1467` → `Audio Processor` +- Line 115: `ESP32-S3` → `System Controller` +- Line 131: `ESP32-S3` → `System Controller` +- Line 150: `ADAU1467` → `Audio Processor` +- Line 152: `ADAU1467` → `Audio Processor` +- Line 165: `ESP32-S3` → `System Controller` +- Line 166: `Si4684` → `Radio Receiver` +- Line 194: `ADAU1467` → `Audio Processor` +- Line 205: `ADAU1467` → `Audio Processor` +- Line 221: `Si4684` → `Radio Receiver` +- Line 229: `ESP32-S3` → `System Controller` +- Line 252: `ADAU1467` → `Audio Processor` +- Line 278: `Si4684` → `Radio Receiver` +- Line 321: `ADAU1467` → `Audio Processor` +- Line 328: `ADAU1467` → `Audio Processor` +- Line 362: `ADAU1467` → `Audio Processor` +- Line 369: `ADAU1467` → `Audio Processor` +- Line 392: `ESP32-S3` → `System Controller` +- Line 394: `ADAU1467` → `Audio Processor` +- Line 451: `ESP32-S3` → `System Controller` +- Line 457: `ADAU1467` → `Audio Processor` +- Line 463: `ADAU1467` → `Audio Processor` + +## architecture/Power_Architecture.md + +- Line 29: `ESP32-S3` → `System Controller` + +## architecture/Power_Domains.md + +- Line 22: `ADAU1467` → `Audio Processor` +- Line 34: `Si4684` → `Radio Receiver` + +--- + +Files checked: 16 + +Issues found: 166 diff --git a/tools/docs/architecture_linter.py b/tools/docs/architecture_linter.py new file mode 100644 index 0000000..dfb262d --- /dev/null +++ b/tools/docs/architecture_linter.py @@ -0,0 +1,529 @@ +#!/usr/bin/env python3 +""" +HubAudio Architecture Linter + +Checks that architecture documentation uses architectural roles +instead of hardware implementation names. + +Usage + + python architecture_linter.py docs --check + + python architecture_linter.py docs --fix + + python architecture_linter.py docs --report report.md +""" + +from __future__ import annotations + +import argparse +import re +import sys + +from pathlib import Path +from dataclasses import dataclass +from typing import Dict, List + +import yaml + + +# ========================================================== +# Configuration +# ========================================================== + +TARGET_DIRS = { + "adr", + "architecture", + "engineering", +} + +SKIP_FILE_PATTERNS = ( + "-Hardware-Architecture.md", + "-Hardware.md", + "-Datasheet.md", +) + +CODE_BLOCK = re.compile( + r"```.*?```", + flags=re.DOTALL +) + +INLINE_CODE = re.compile( + r"`[^`]+`" +) + +ASCII_DIAGRAM = re.compile( + r"^[\s\|\+\-\>\<]+$" +) + + +# ========================================================== +# Data model +# ========================================================== + +@dataclass +class Role: + + role: str + + implementation: str + + aliases: List[str] + + +@dataclass +class Finding: + + line: int + + implementation: str + + role: str + + +# ========================================================== +# Role database +# ========================================================== + +class RoleDatabase: + + def __init__(self, filename: Path): + + self.roles: List[Role] = [] + + self.load(filename) + + def load(self, filename: Path): + + if not filename.exists(): + raise FileNotFoundError(filename) + + data = yaml.safe_load( + filename.read_text(encoding="utf8") + ) + + for role_name, cfg in data["roles"].items(): + + self.roles.append( + Role( + role=role_name, + implementation=cfg["implementation"], + # aliases=cfg.get("aliases", []) + aliases=list( + set(cfg.get("aliases", [])) + - + {cfg["implementation"]} + ) + ) + ) + + +# ========================================================== +# Markdown parser +# ========================================================== + +class MarkdownCleaner: + + """ + Temporarily removes code blocks before scanning. + """ + + def __init__(self): + + self.blocks = [] + + def protect(self, text: str): + + def repl(match): + + token = f"@@BLOCK{len(self.blocks)}@@" + + self.blocks.append(match.group(0)) + + return token + + text = CODE_BLOCK.sub(repl, text) + + text = INLINE_CODE.sub(repl, text) + + return text + + def restore(self, text: str): + + for i, block in enumerate(self.blocks): + + text = text.replace( + f"@@BLOCK{i}@@", + block + ) + + return text + + +# ========================================================== +# Linter +# ========================================================== + +class ArchitectureLinter: + + def __init__( + self, + docs_root: Path, + roles: RoleDatabase + ): + + self.root = docs_root + + self.roles = roles + + self.findings: Dict[Path, List[Finding]] = {} + + self.checked = 0 + + self.modified = 0 + + # ------------------------------------------------------ + + def iter_files(self): + + for md in self.root.rglob("*.md"): + + rel = md.relative_to(self.root) + + if len(rel.parts) == 0: + continue + + first = rel.parts[0] + + if first not in TARGET_DIRS: + continue + + skip = False + + for pattern in SKIP_FILE_PATTERNS: + + if md.name.endswith(pattern): + skip = True + break + + if skip: + continue + + yield md + + # ------------------------------------------------------ + + def analyse_file( + self, + filename: Path + ): + + cleaner = MarkdownCleaner() + + original = filename.read_text( + encoding="utf8" + ) + + text = cleaner.protect(original) + + findings = [] + + lines = text.splitlines() + + for lineno, line in enumerate(lines, start=1): + + # + # Ignore implementation section + # + if ASCII_DIAGRAM.match(line): + continue + + if "Current implementation" in line: + continue + if line.lstrip().startswith("#"): + continue + # + # Ignore titles like + # + # ADAU1467 Hardware Architecture + # + + if line.startswith("#") and "Hardware" in line: + continue + + for role in self.roles.roles: + + names = [ + role.implementation, + *role.aliases + ] + + for implementation in names: + + pattern = ( + r"\b" + + re.escape(implementation) + + r"\b" + ) + + if re.search(pattern, line): + + findings.append( + Finding( + line=lineno, + implementation=implementation, + role=role.role + ) + ) + + self.findings[filename] = findings + + self.checked += 1 + # ------------------------------------------------------ + + def check(self): + + for file in self.iter_files(): + + self.analyse_file(file) + + # ------------------------------------------------------ + + def fix(self): + + for filename in self.iter_files(): + + cleaner = MarkdownCleaner() + + original = filename.read_text( + encoding="utf8" + ) + + protected = cleaner.protect(original) + + text = protected + + changed = False + + # + # sostituzioni + # + + for role in self.roles.roles: + + names = [ + role.implementation, + *role.aliases + ] + + for implementation in names: + + pattern = ( + r"\b" + + re.escape(implementation) + + r"\b" + ) + + new_text = re.sub( + pattern, + role.role, + text + ) + + if new_text != text: + + changed = True + text = new_text + + text = cleaner.restore(text) + + if changed: + + filename.write_text( + text, + encoding="utf8" + ) + + self.modified += 1 + + # ------------------------------------------------------ + + def print_report(self): + + issues = 0 + + print() + + print("=" * 70) + print("HubAudio Architecture Linter") + print("=" * 70) + + for filename in sorted(self.findings): + + findings = self.findings[filename] + + if not findings: + continue + + issues += len(findings) + + rel = filename.relative_to(self.root) + + print() + print(rel) + print("-" * len(str(rel))) + + for f in findings: + + print( + f"line {f.line:4d} : " + f"{f.implementation}" + f" -> " + f"{f.role}" + ) + + print() + print("=" * 70) + print(f"Files checked : {self.checked}") + print(f"Issues found : {issues}") + print(f"Files changed : {self.modified}") + print("=" * 70) + + # ------------------------------------------------------ + + def save_report( + self, + filename: Path + ): + + issues = 0 + + with filename.open( + "w", + encoding="utf8" + ) as fp: + + fp.write("# HubAudio Architecture Report\n\n") + + for md in sorted(self.findings): + + findings = self.findings[md] + + if not findings: + continue + + rel = md.relative_to(self.root) + + fp.write(f"## {rel}\n\n") + + for f in findings: + + issues += 1 + + fp.write( + f"- Line {f.line}: " + f"`{f.implementation}` " + f"→ " + f"`{f.role}`\n" + ) + + fp.write("\n") + + fp.write("---\n\n") + fp.write(f"Files checked: {self.checked}\n\n") + fp.write(f"Issues found: {issues}\n") + + +# ========================================================== +# CLI +# ========================================================== + +def main(): + + parser = argparse.ArgumentParser( + description="HubAudio Architecture Linter" + ) + + parser.add_argument( + "docs", + help="Documentation root" + ) + + parser.add_argument( + "--roles", + default="tools/docs/roles.yml", + help="roles.yml" + ) + + group = parser.add_mutually_exclusive_group() + + group.add_argument( + "--check", + action="store_true" + ) + + parser.add_argument( + "--report", + help="Write markdown report" + ) + + parser.add_argument( + "--fix", + action="store_true", + help="Apply architecture naming fixes" + ) + + args = parser.parse_args() + + docs = Path(args.docs) + + if not docs.exists(): + + print("Documentation directory not found.") + sys.exit(1) + + role_db = RoleDatabase( + Path(args.roles) + ) + + linter = ArchitectureLinter( + docs, + role_db + ) + + linter.check() + + if args.fix: + + print() + print("=" * 70) + print("Applying architecture fixes") + print("=" * 70) + + linter.fix() + + # + # Ricontrolla dopo la correzione + # + + linter.findings.clear() + linter.checked = 0 + + linter.check() + + linter.print_report() + + if args.report: + + linter.save_report( + Path(args.report) + ) + + print() + print("Report written to") + print(args.report) + + +if __name__ == "__main__": + + main() \ No newline at end of file diff --git a/tools/docs/role_refactor.py b/tools/docs/role_refactor.py new file mode 100644 index 0000000..bb6fbec --- /dev/null +++ b/tools/docs/role_refactor.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python3 +""" +HubAudio Documentation Role Refactor + +Replaces hardware implementation names with architectural role names. + +Example: + + python role_refactor.py docs --dry-run + python role_refactor.py docs --write +""" + +from pathlib import Path +import argparse +import re +import sys + + +# ---------------------------------------------------------------------- +# Mapping +# ---------------------------------------------------------------------- + +ROLE_MAP = { + "ADAU1467": "Audio Processor", + "ESP32-S3": "System Controller", + "Si4684": "Radio Receiver", + "BT1026": "Bluetooth Receiver", + "BT1035": "Bluetooth Transmitter", + "PCS2P2309NZ": "Clock Buffer", + "BQ24074": "Battery Charger", + "BQ27441": "Fuel Gauge", + "TPS65217": "Power Manager", + "25AA1024": "Audio EEPROM", +} + + +# ---------------------------------------------------------------------- +# Ignore folders +# ---------------------------------------------------------------------- + +IGNORE = { + "datasheets", + "hardware", + "firmware", + ".git", + "__pycache__", +} + + +# ---------------------------------------------------------------------- +# Replace inside one file +# ---------------------------------------------------------------------- + +def process_file(path: Path, write: bool): + + text = path.read_text(encoding="utf-8") + + original = text + + replacements = [] + + for implementation, role in ROLE_MAP.items(): + + pattern = r"\b" + re.escape(implementation) + r"\b" + + matches = len(re.findall(pattern, text)) + + if matches: + + text = re.sub(pattern, role, text) + + replacements.append((implementation, role, matches)) + + if not replacements: + return False, [] + + print(f"\n{path}") + + total = 0 + + for old, new, count in replacements: + + total += count + + print(f" {old:18} -> {new:24} ({count})") + + print(f" Total replacements: {total}") + + if write: + path.write_text(text, encoding="utf-8") + + return True, replacements + + +# ---------------------------------------------------------------------- +# Scan tree +# ---------------------------------------------------------------------- + +def scan(root: Path, write: bool): + + modified = 0 + + files = 0 + + for file in root.rglob("*.md"): + + if any(part in IGNORE for part in file.parts): + continue + + changed, _ = process_file(file, write) + + if changed: + modified += 1 + + files += 1 + + print("\n----------------------------------------") + + print(f"Markdown scanned : {files}") + print(f"Files modified : {modified}") + + if write: + print("\nChanges written to disk.") + else: + print("\nDry run completed.") + + +# ---------------------------------------------------------------------- +# Main +# ---------------------------------------------------------------------- + +def main(): + + parser = argparse.ArgumentParser() + + parser.add_argument( + "path", + help="Root documentation directory" + ) + + parser.add_argument( + "--write", + action="store_true", + help="Write modifications" + ) + + parser.add_argument( + "--dry-run", + action="store_true", + help="Only show modifications" + ) + + args = parser.parse_args() + + if args.write and args.dry_run: + print("Choose either --write or --dry-run") + sys.exit(1) + + root = Path(args.path) + + if not root.exists(): + print("Directory not found.") + sys.exit(1) + + scan(root, write=args.write) + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/tools/docs/roles.yml b/tools/docs/roles.yml new file mode 100644 index 0000000..0aa1c21 --- /dev/null +++ b/tools/docs/roles.yml @@ -0,0 +1,51 @@ +roles: + + Audio Processor: + implementation: ADAU1467 + category: functional + aliases: [] + + System Controller: + implementation: ESP32-S3 + category: functional + aliases: [] + + Radio Receiver: + implementation: Si4684 + category: functional + aliases: [] + + Bluetooth Receiver: + implementation: BT1026 + category: functional + aliases: [] + + Bluetooth Transmitter: + implementation: BT1035 + category: functional + aliases: [] + + Clock Buffer: + implementation: PCS2P2309NZ + category: infrastructure + aliases: [] + + Audio EEPROM: + implementation: 25AA1024 + category: memory + aliases: [] + + Battery Charger: + implementation: BQ24074 + category: power + aliases: [] + + Fuel Gauge: + implementation: BQ27441 + category: power + aliases: [] + + Power Manager: + implementation: TPS65217 + category: power + aliases: [] \ No newline at end of file