# Dante / AES67 Audio-over-IP for ESP32-P4 **Status: AES67 base vendored in, untested on hardware.** The `aes67-esp32p4` engine and a board-configurable app entry point are in place; not yet build-verified or run against real gear. Native Dante support is still at the notes stage. ## Goal A low-cost, network audio endpoint on the ESP32-P4 that can interoperate with Dante-based AV systems. In practice "Dante-interoperable" is being pursued in two phases: 1. **AES67 interop (primary target)** — most Dante hardware from the last several years can send/receive AES67, so a solid AES67 endpoint already gets us into the same audio network as Dante gear. 2. **Native Dante protocol support (stretch goal)** — Dante's proprietary discovery (mDNS records), control protocol (routing/subscription), and PTPv1 clocking, for talking to older or AES67-disabled Dante devices. ## Why ESP32-P4 The original ESP32 (WiFi, Xtensa) can't hold AES67's ~1ms RTP packet timing tightly enough over WiFi to be spec-compliant. The P4 drops WiFi in favour of a real Ethernet MAC with hardware PTP timestamping, which is what makes sub-millisecond, spec-accurate AoIP achievable on this class of chip at all. ## Two source projects this builds on ### 1. [DatanoiseTV/aes67-esp32p4](https://github.com/DatanoiseTV/aes67-esp32p4) — foundation (Apache-2.0) This is what we fork from. It already solves the hard, P4-specific problems: hardware PTP timestamping via the EMAC, an I2S driver with APLL clock recovery, an RTP engine with an L2 hook that bypasses lwIP for latency, SAP/SDP, and mDNS/DNS-SD advertisement. Apache-2.0 means we can build on it freely, including for commercial client work. ### 2. [teodly/inferno](https://github.com/teodly/inferno) — protocol reference only (GPL-3.0-or-later / AGPL-3.0-or-later) A full software Dante device implementation for Linux. **We do not vendor or copy code from this repo.** It's copyleft-licensed, and incorporating its code would obligate this whole firmware image to the same license — which rules out using it in closed commercial deliverables. Instead it's used as documentation: reading `inferno_aoip` to understand Dante's wire behaviour (mDNS service records, control-protocol framing, flow subscriptions) well enough to write an independent, clean-room implementation against the P4 component. > **This licensing boundary is the most important constraint on this > project.** See `CLAUDE.md` for the hard rule any dev session (human or > agent) needs to follow. ## Hardware target Target board: **Waveshare ESP32-P4-ETH** ([product](https://www.waveshare.com/esp32-p4-eth.htm) · [wiki](https://www.waveshare.com/wiki/ESP32-P4-ETH)). Ethernet via IP101 GRI PHY (RMII); onboard ES8311 codec + NS4150B amplifier + microphone + 8Ω speaker connector; 32 MB PSRAM, 32 MB NOR flash. Pins below are verified against the board schematic (`docs/esp32-p4_schematic_en.pdf`) and are mirrored in `main/board_config.h`. | Function | GPIO | Notes | |---|---|---| | Ethernet MDC | 31 | IP101 GRI, PHY addr 1 | | Ethernet MDIO | 52 | | | Ethernet REF_CLK | 50 | 50 MHz reference | | Ethernet PHY_RST | 51 | | | I2S MCLK | 13 | 18.432 MHz via APLL | | I2S BCLK | 12 | bit clock | | I2S LRCLK | 10 | word/frame clock | | I2S DOUT | 9 | data out → ES8311 DAC | | I2S DIN | 11 | data in ← ES8311 ADC / mic | | PA Enable | 53 | active high (speaker amp) | | I2C SCL / SDA | 8 / 7 | ES8311 control (addr 0x18) | Fixed EMAC RMII data pins (not software-configurable, listed for reference): TXD0/1 = 34/35, RXD0/1 = 30/29, TX_EN = 49, CRS_DV = 28. ## Repo layout ``` components/aes67/ Forked from aes67-esp32p4 — AES67 engine (PTP, RTP, I2S, SAP/SDP, mDNS) components/dante/ Clean-room Dante support (discovery now; ARC/CMC/flows/PTPv1 later) main/ Application entry point, board config docs/ Design notes, incl. clean-room Dante protocol notes reference/ Local clones of both source repos, for reading only (gitignored, not part of this repo) ``` ## Build Requires ESP-IDF v5.5+ with the ESP32-P4 target. ```bash idf.py set-target esp32p4 idf.py build idf.py flash monitor ``` `components/aes67` is vendored in (from `aes67-esp32p4`, Apache-2.0) and `main/` wires it up via `main/board_config.h` (pins confirmed for the Waveshare ESP32-P4-ETH). Not yet build-verified — needs an ESP-IDF v5.5+ toolchain. ## Roadmap - [x] Fork `aes67-esp32p4`'s `components/aes67` in as the starting point - [x] Confirm pinout against actual target hardware (Waveshare ESP32-P4-ETH) - [ ] Build-verify with ESP-IDF v5.5+ (`idf.py set-target esp32p4 build`) - [ ] Get AES67 send/receive verified against real Dante gear in AES67 mode - [x] Write clean-room Dante protocol notes (`docs/dante-protocol-notes.md`) - [x] Prototype Dante mDNS **discovery** (`components/dante`, read-only browse) - [x] Prototype Dante mDNS **advertisement** (`_netaudio-arc`/`-cmc`/`-chan`; gated off until ARC/CMC responders back it) - [x] Prototype Dante **CMC** responder (device-announce, UDP 8800) - [ ] Prototype Dante **ARC** control protocol (routing/subscriptions, UDP 4440) - [ ] Investigate PTPv1 support alongside the existing PTPv2 stack ## License Apache-2.0 (see `LICENSE`), matching the `aes67-esp32p4` base this project forks from.