69b4e18118
- aes67_board: Waveshare ESP32-P4-ETH pin profile and EMAC + IP101 driver install (PHY addr 1, reset GPIO51, ref clock in on GPIO50). - aes67_net: Ethernet netif with DHCP client; logs link up/down (speed, duplex, MAC) and the DHCP lease. - Verified on board: 100 Mbps full duplex, DHCP lease in ~8 s, ping 0% loss, ~0.2 ms RTT. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3.8 KiB
3.8 KiB
aes67-ESP32-P4
AES67 sender on a Waveshare ESP32-P4-ETH (PoE). Sources: Spotify Connect (cspot) and HLS/m3u8, with failover. Riedel-style web UI and a reusable AES67 core (PTP, RTP TX, SDP/SAP, VLAN, syslog, health) meant for later AES67 projects.
Repo: https://gitea.apointless.space/bsncubed/aes67-ESP32-P4
Read first
docs/aes67-core-base.md: reusable core. Config schema, API, PTP (roles, Riedel defaults, status fields), AES67 TX/SDP/SAP, VLAN, syslog, temperatures, component layout.docs/hardware-and-design-notes.md: board pinout, chip revision caveat, project pipeline (cspot/HLS), failover, player API.web/index.html: finished web UI (single file). It is the API contract; firmware must match the JSON it reads and writes.
Working rules
- One change at a time ("one fuckup at a time"). Change or test one variable per step; never stack several fixes or hypotheses. If something breaks, go back to the last known-good state.
- Follow the build order below. Finish and verify a step on hardware before starting the next.
- After every change:
idf.py build, flash, and check the serial monitor output. Show the relevant log lines. - Don't mark a step done until it has been verified on the board.
- Keep core and project separate:
components/aes67_*must not depend onmain/(sources/player). Project code plugs in through the config, status and route registries. web/index.html: keep the CORE / PROJECT markers. If the firmware needs an API change, change the doc and the page together.- Small, focused commits per step.
Toolchain
- ESP-IDF 5.5 or later (needed for the P4 and for
examples/network/vlan_support). Targetesp32p4. idf.py set-target esp32p4,idf.py build,idf.py -p <PORT> flash monitor- Before first build: run
esptool.py chip_idandesptool.py flash_id.- Chip revision < v3.0 (engineering silicon, seen on some of these boards) needs
CONFIG_ESP32P4_SELECTS_REV_LESS_V3=y. Our board: v1.3 (set in sdkconfig.defaults, min rev v1.0). - Our board: 32 MB flash (GigaDevice c8/4019). App slots must stay below 16 MB (cache mapping above 16 MB is experimental in IDF).
- Chip revision < v3.0 (engineering silicon, seen on some of these boards) needs
- Embed
web/index.htmlviaEMBED_TXTFILESinaes67_web.
Board quick reference (full details in docs)
- Ethernet: IP101GRI, RMII, PHY addr 1, ref clock from PHY into GPIO50 (EMAC_CLK_EXT_IN). MDC 31, MDIO 52, PHY reset/power 51, TX_EN 49, TXD0 34, TXD1 35, CRS_DV 28, RXD0 29, RXD1 30.
- No Wi-Fi/BT on this board.
- On-die temperature sensor only (driver/temperature_sensor.h).
Build order / status
- 0. Check chip revision and flash size; create IDF project and empty component stubs (layout in aes67-core-base.md). Set up the OTA partition table (two app slots, no factory) and PROJECT_VER from git now, so the layout never changes later.
- 1. Ethernet: IP101 up, DHCP, IP logged. Ping works.
- 2. Web server + config store (cJSON in NVS) + embedded index.html; /api/config, /api/status (stub values), /api/reboot.
- 2b. Firmware update: /api/ota upload + rollback self-test. Test: update to a new build, then deliberately flash a build that fails its self-test and confirm it rolls back. After this, flash over the network; keep USB for recovery.
- 3. PTP TimeReceiver: lock to an existing GM (Riedel), fill
status.ptp. Confirm EMAC hardware timestamps work. First check whether the installed ESP-IDF has a PTP example/component for the P4 before writing one. - 4. AES67 TX with a 1 kHz test tone, PTP-paced; /stream.sdp. Verify: import SDP on a Riedel Artist 4-wire AES67 port, and check packets/timestamps in Wireshark.
- 5. SAP discovery, then syslog, then health/temperatures, then VLAN split (one at a time).
- 6. PTP TimeTransmitter: BMCA roles (auto/master), hybrid mode.
- 7. Sources: HLS player, then cspot (Spotify Connect), then failover + /api/player.
- 8. Mono sum, gain, polish.