# CLAUDE.md Context for any Claude Code session working in this repo. ## What this is An ESP-IDF firmware project putting a Dante-interoperable audio-over-IP endpoint on the ESP32-P4. Phase 1 is AES67 interop; native Dante protocol support is a phase 2 stretch goal. Full background/rationale is in `README.md` — read that first if you haven't. ## Hard rule: licensing boundary (read this before touching Dante protocol work) This repo is Apache-2.0. It forks `components/aes67` from `DatanoiseTV/aes67-esp32p4` (also Apache-2.0). That's fine to build on directly. `reference/inferno` (teodly/inferno) is **GPL-3.0-or-later / AGPL-3.0-or-later** and is present locally **for reading only** — it is not part of this repo and must never be copied into it. - Never copy, translate, or closely paraphrase code from `reference/inferno` into any file in this repo. - It's fine to read `inferno_aoip` to understand *what* Dante devices do on the wire (message shapes, mDNS service records, control flow) — but the resulting implementation here must be written independently, from that understanding, not from their source. - Write protocol understanding as plain-English behavioural notes in `docs/dante-protocol-notes.md` (what the protocol does), not as annotated/translated code (how their code does it). - If a task would involve porting or closely mirroring a specific `inferno_aoip` file, stop and flag it instead of proceeding — don't make that judgment call silently. ## Repo layout ``` components/aes67/ AES67 engine, forked from aes67-esp32p4 (PTP, RTP, I2S, SAP/SDP, mDNS) main/ App entry point, board/pin config docs/ Design notes, incl. dante-protocol-notes.md reference/ Local clones of both source repos — read-only, gitignored aes67-esp32p4/ Fork basis inferno/ Dante protocol reference — see licensing rule above ``` ## Build & flash Requires ESP-IDF v5.5+. ```bash idf.py set-target esp32p4 idf.py build idf.py flash monitor ``` ## Target hardware Target board is the **Waveshare ESP32-P4-ETH** — Ethernet via IP101 GRI PHY (RMII), onboard ES8311 codec (APLL-clocked I2S) + NS4150B amplifier + mic + 8ohm speaker connector, 32MB PSRAM, 32MB flash. Pins are verified against the board schematic (`docs/esp32-p4_schematic_en.pdf`) and live in `main/board_config.h`, with the full table in README.md. Board datasheet and the P4 SoC TRM are also in `docs/`. If the board ever changes, update `main/board_config.h` and the README table together. ## Known hard problems - **PTPv1**: Dante needs it; the forked AES67 stack's PTP code (`components/aes67/third_party/ptpd`, `aes67_ptp.c`, `aes67_hw_timer.c`) targets PTPv2 against the P4's hardware timestamp path. Scope of adding v1 isn't assessed yet. - **Dante's control protocol** (routing/subscription — Inferno calls this ARC/CMC) is undocumented and proprietary. The only way to understand it is reading Inferno's protocol handling, read-only, per the licensing rule above — there's no spec to implement against. - **No multi-process model on FreeRTOS/ESP-IDF**: Inferno's Linux design relies on its PTP daemon (Statime) running as a separate OS process communicating over a socket/clock device. There's no equivalent process boundary here — any PTPv1 work has to live inside the single firmware image, most likely inside the existing `aes67_ptp` task structure rather than as a separate cooperating component. ## Conventions Match the existing `aes67-esp67p4` component style: - `-O2`, hot-path conversion/ISR functions placed in IRAM - Tasks pinned to core 0 for cache coherency - ISR-driven DMA playback where possible, avoid task-scheduling on the audio hot path - Quiet logging by default (errors + first PTP lock only) ## Useful links - Foundation: https://github.com/DatanoiseTV/aes67-esp32p4 - Dante protocol reference (read-only): https://github.com/teodly/inferno - AES67 Linux daemon (what the P4 component patterns itself on): https://github.com/bondagit/aes67-linux-daemon