From d5013082c93c092e7024d8a7a27960f63e88a4fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?King=20K=C3=A9vin?= Date: Tue, 6 Oct 2026 20:42:06 +0200 Subject: [PATCH 1/2] Port the ES8311 audio-reactive board definition to the Waveshare ESP32-P4-ETH MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Writes the hardware reference page for the Waveshare ESP32-P4-ETH's onboard ES8311 codec and Ethernet wiring, which PR #128's firmware-variant approach never landed on main after PR #129 made the codec runtime configuration. Also renames the shared P4 Ethernet preset to "P4-NANO/ETH" so its UI label doesn't imply it's NANO-only. **Core** - `EthernetModule.h`: `kEthPresets`' shared P4 RMII row renamed `"P4-NANO"` → `"P4-NANO/ETH"`, naming both boards that use it; doc comment updated to match. **Scripts/MoonDeck** - `check_devices.py`: its own restatement of the preset label (cross-checked against `platform_config.h`'s chip default) updated to match the rename — this is the check that caught the miss on the first pass. **Docs/CI** - New `docs/reference/hardware/esp32-p4-eth.md`: audio (ES8311) and Ethernet pin tables, free-GPIO table, bench-verification notes, written against the current runtime-codec architecture (`AudioService`/`I2cBusModule`), not copied from the closed PR #128. - `firmware-variants.md`, `gpio-usage.md`: P4-ETH named alongside the P4-NANO as sharing `esp32p4rev1-eth`. - `mkdocs.yml`: nav entry for the new page. - `mooninstaller/deviceModels.json`: the renamed preset label carried into all 5 P4-family catalog entries that reference it. Bench-verified on the Waveshare ESP32-P4-ETH (plain `esp32p4rev1-eth` firmware, no new variant): I2C bus scan ACKs the codec at 0x18, `AudioService` reports live mic data, Ethernet link + DHCP hold, and the renamed preset round-trips cleanly on an already-provisioned board (auto-resolves to the new label, same pins, no reseed to Custom). Reviews - Pre-existing, unrelated to this diff (confirmed by reproducing on a clean `main`): `check_docgen` carries 1 pre-existing error (`Hub75Slots.h`) and `check_code` a 4-finding drift, both from commits already on `main` before this branch started — named here rather than fixed, since neither file is touched by this change. Co-Authored-By: Claude Sonnet 5 --- docs/reference/hardware/esp32-p4-eth.md | 63 ++++++++++++++++++++ docs/reference/hardware/firmware-variants.md | 2 +- docs/reference/hardware/gpio-usage.md | 3 +- mkdocs.yml | 1 + moondeck/check/check_devices.py | 2 +- mooninstaller/deviceModels.json | 10 ++-- src/core/system/EthernetModule.h | 8 +-- 7 files changed, 77 insertions(+), 12 deletions(-) create mode 100644 docs/reference/hardware/esp32-p4-eth.md diff --git a/docs/reference/hardware/esp32-p4-eth.md b/docs/reference/hardware/esp32-p4-eth.md new file mode 100644 index 000000000..ff6169c5d --- /dev/null +++ b/docs/reference/hardware/esp32-p4-eth.md @@ -0,0 +1,63 @@ +# Waveshare ESP32-P4-ETH hardware reference + +Pin maps and onboard features for the **Waveshare ESP32-P4-ETH**, read from the official schematic so MoonLight work (Ethernet, audio) reads this instead of re-scraping the PDF. The board runs the plain `esp32p4rev1-eth` firmware (the same build the P4-NANO uses) and is `"Waveshare ESP32-P4-ETH"` in the device catalog. + +**Sources** +- Product page: +- Wiki: +- Schematic (local): `datasheet/ESP32-P4-ETH/ESP32-P4-ETH-datasheet.pdf` + +Same family as the Waveshare ESP32-P4-NANO (see [gpio-usage.md § ESP32-P4](gpio-usage.md#esp32-p4) for its pin map): ESP32-P4 (RISC-V dual-core), same onboard IP101 Ethernet PHY wiring, same CSI/DSI/I2C accessory-bus convention, same onboard **ES8311** audio codec feeding an SMD mic + a 2-pin JST speaker header. The [MHC-WLED ESP32-P4 shield](mhc-wled-esp32-p4-shield.md) is a different, unrelated P4 carrier board (RS-485/line-in, no onboard codec). + +## Audio (ES8311 codec) + +The onboard SMD mic and speaker header connect through an **ES8311 mono codec**. The ESP is the I2S master (it drives MCLK). + +| Signal | GPIO | Direction / role | +|---|---|---| +| I2S MCLK | 13 | master clock → codec (ESP is I2S master; MCLK = 256 × sample_rate) | +| I2S SCLK (BCLK) | 12 | bit clock | +| I2S LRCK (WS) | 10 | word select | +| I2S ASDOUT | 11 | **mic / ADC data: codec → ESP** (the record path) | +| I2S DSDIN | 9 | playback / DAC data: ESP → codec (speaker path, **not wired up** — out of scope, mic-only) | +| **ESP_I2C_SDA** | **7** | codec control bus (shared with the CSI/DSI accessory headers) | +| **ESP_I2C_SCL** | **8** | codec control bus | +| PA_Ctrl | 53 | speaker amp enable (not wired up — speaker is out of scope) | + +- **ES8311 I2C address: `0x18`** (the hardware default; no address-select strap). +- The codec is runtime configuration, not a firmware variant: the catalog entry opens the **[I2C bus](../../moonmodules/core/moxygen/I2cBusModule.md)** on SDA 7 / SCL 8 and sets **[AudioService](../../moonmodules/core/moxygen/AudioService.md)**'s `codec` to `ES8311` with `codecAddr` `0x18`, `mclkPin` 13, `sckPin` 12, `wsPin` 10, `sdPin` 11, `mode` local audio. Applying the device model is what turns the codec on; `esp_codec_dev` is built into every `esp32s31`/`esp32p4` firmware, so no board-specific Kconfig or sdkconfig fragment is needed — the same binary the P4-NANO ships drives this board's codec too. +- Driven by Espressif's **`esp_codec_dev`** managed component (the same driver and the same `platform_esp32_es8311.cpp` the ESP32-S31 and the P4-NANO use), including its two address-shift / null-`data_if` fixes — neither is P4-ETH-specific, see that file's header comment. +- The codec needs **MCLK running before it answers I2C**; `AudioService` brings up the I2S channel (which drives MCLK) before the codec I2C config, same ordering as every other ES8311 board. +- **Mic-only path** (audio-reactive input): all pins above confirmed independently from the schematic netlist *and* the Waveshare wiki (which separately publishes the same I2C/I2S pin set). The speaker path (DSDIN + PA_Ctrl) is a separate capability, not implemented here. +- **Bench-verified end to end** 2026-10-06, on the plain `esp32p4rev1-eth` firmware: the I2C bus scan ACKs the codec at `0x18`, named `0x18 Audio (ES8311)`, and `AudioService` reports live mic data (level RMS tracking ambient room noise, onsets, a peak-Hz reading) once `codec`/`mclkPin` are set from the catalog entry. + +## Ethernet (IP101 PHY, RMII) + +On-chip EMAC → **IP101GRI** PHY → RJ45, **RMII** with a 25 MHz crystal, externally-fed 50 MHz reference clock. Same reference design as the Waveshare P4-NANO — confirmed pin-for-pin identical: + +| Signal | GPIO | Source | +|---|---|---| +| MDC | 31 | schematic netlist (unambiguous two-pin net, matches the P4 pin table) | +| MDIO | 52 | schematic netlist (same) | +| PHY reset | 51 | direct schematic inspection (the flattened PDF text extraction was ambiguous here; confirmed by eye against the drawing) | +| RMII ref clock (external in) | 50 | carried over from the P4-NANO preset, consistent with the other three now-confirmed pins | + +Catalog entry: `EthernetModule.ethBoard = "P4-NANO/ETH"` — one shared preset, not a separate row per board, since the pins read pin-for-pin identical between the two; see [gpio-usage.md § ESP32-P4](gpio-usage.md#esp32-p4) for the shared preset. + +**Bench-verified** 2026-10-06: link up and a DHCP lease at 100 Mbit on the plain `esp32p4rev1-eth` firmware. + +## Other onboard features (not wired up here) + +From the Waveshare wiki: MIPI-CSI (2-lane, OV5647-compatible), MIPI-DSI (2-lane, 5"/7"/8"/10.1" panels), SDIO 3.0 microSD slot, USB-C (native + UART bridge), BOOT/RESET buttons. None of these conflict with the audio (GPIO 7-13) or Ethernet (GPIO 28-31/49-52) pins above. + +## Free GPIO for user peripherals (LED strips) + +Following the P4-NANO's own reference set (`ParallelLedDriver` default `pins="20,21,22,23,24,25,26,27"`), with this board's audio pins added to the committed set: + +| Peripheral | GPIOs | +|---|---| +| Ethernet RMII (fixed silicon pads) | 28-31, 49-52 | +| ES8311 audio (I²S + I²C) | 7-13 | +| CSI/DSI accessory headers | share the I2C bus (7-8) plus their own dedicated MIPI diff-pairs | + +**Clear, following the P4-NANO's documented set**: 20-27, 32-33, 39-48 (the catalog's `ParallelLedDriver` default is `pins="20,21,22,23,24,25,26,27"`, same as the P4-NANO). GPIO 20/21 also appear as spare IO on this board's CSI header (same situation as the P4-NANO, which treats them as free LED pins regardless) — only relevant if a camera module is actually plugged in. See [gpio-usage.md § ESP32-P4](gpio-usage.md#esp32-p4) for the general P4 pin map this board extends. diff --git a/docs/reference/hardware/firmware-variants.md b/docs/reference/hardware/firmware-variants.md index 62f4c7b15..2bca970b4 100644 --- a/docs/reference/hardware/firmware-variants.md +++ b/docs/reference/hardware/firmware-variants.md @@ -12,7 +12,7 @@ Selected by `build_esp32.py --firmware `, reported by `SystemModule.firmwar | `esp32-eth` | classic | Ethernet only, WiFi excluded | | `esp32-16mb` | classic, 16 MB flash | WiFi and Ethernet | | `esp32s3-n16r8`, `esp32s3-n8r8` | S3 | WiFi and W5500 SPI Ethernet | -| `esp32p4rev1-eth` | P4 rev 1 (Waveshare ESP32-P4-NANO) | Ethernet only | +| `esp32p4rev1-eth` | P4 rev 1 (Waveshare ESP32-P4-NANO, Waveshare ESP32-P4-ETH) | Ethernet only | | `esp32p4rev1-eth-wifi` | P4 rev 1 | Ethernet, plus WiFi via the on-board ESP32-C6 over esp_hosted | | `esp32p4rev3-eth`, `esp32p4rev3-eth-wifi` | P4 rev 3 silicon | As rev 1. Rev 3 is not binary-compatible with rev 1; untested, no v3 board on the bench | diff --git a/docs/reference/hardware/gpio-usage.md b/docs/reference/hardware/gpio-usage.md index 66a78575f..a09b1c605 100644 --- a/docs/reference/hardware/gpio-usage.md +++ b/docs/reference/hardware/gpio-usage.md @@ -70,8 +70,9 @@ For **LED output** specifically — the pins a WS2812-class strand data line can | Role-conflict | **34-38** | Strapping pins (boot mode). Don't drive at reset; the first LED-driver default wrongly landed here (see [lessons.md](../../work/past/lessons.md)). | | Role-conflict | **37, 38** | UART0 console on the P4-NANO (`CONFIG_ESP_CONSOLE_UART_DEFAULT`) — the runtime `ESP_LOGI` lines come out here, not over USB. | | Board-wired (P4-NANO) | **Ethernet RMII** 28-31 / 49-52, **C6 SDIO** 14-19 / 54, **I2C** 7-8 | Consumed by the NANO's on-board Ethernet PHY, the C6 WiFi co-processor, and the I2C bus. | +| Board-wired (P4-ETH) | **Ethernet RMII** 28-31 / 49-52 (same preset as the NANO), **ES8311 audio** 7-13 | The [Waveshare ESP32-P4-ETH](esp32-p4-eth.md) has no C6/WiFi, but carries its own onboard ES8311 codec on the same I2C pins (7-8) plus I2S 9-13. | -**Clear on the P4-NANO:** 20-27, 32-33, 39-48 (the LED-driver default is `pins="20,21,22,23,24,25,26,27"`). Exact free set is board-specific; the NANO's is the reference. A carrier board changes what's exposed and how — the [MHC-WLED ESP32-P4 shield](mhc-wled-esp32-p4-shield.md) routes every terminal through level shifters / RS-485 transceivers / protected inputs (no bare GPIO), which is why a direct loopback jumper fails on it; its full terminal map is on that page. +**Clear on the P4-NANO:** 20-27, 32-33, 39-48 (the LED-driver default is `pins="20,21,22,23,24,25,26,27"`). Exact free set is board-specific; the NANO's is the reference. A carrier board changes what's exposed and how — the [MHC-WLED ESP32-P4 shield](mhc-wled-esp32-p4-shield.md) routes every terminal through level shifters / RS-485 transceivers / protected inputs (no bare GPIO), which is why a direct loopback jumper fails on it; its full terminal map is on that page. The [Waveshare ESP32-P4-ETH](esp32-p4-eth.md) clears the same 20-27/32-33/39-48 set, its own audio codec pins (7-13) already counted above. ## ESP32-S31 diff --git a/mkdocs.yml b/mkdocs.yml index b13d16b40..30fbde4f8 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -232,6 +232,7 @@ nav: - GPIO usage per MCU: reference/hardware/gpio-usage.md - ESP32-S31 coreboard: reference/hardware/esp32-s31-coreboard.md - MHC-WLED ESP32-P4 shield: reference/hardware/mhc-wled-esp32-p4-shield.md + - Waveshare ESP32-P4-ETH: reference/hardware/esp32-p4-eth.md - Light fixtures and DMX nodes: reference/hardware/light-fixtures.md - Control surfaces: reference/hardware/control-surfaces.md # The rules bind a contributor rather than serving a reader need, so they sit outside diff --git a/moondeck/check/check_devices.py b/moondeck/check/check_devices.py index 017f59c16..84dc235cb 100644 --- a/moondeck/check/check_devices.py +++ b/moondeck/check/check_devices.py @@ -91,7 +91,7 @@ def eth_preset_drift(): rows[m.group(1)] = [f.strip() for f in m.group(2).split(",")] # label -> the PHY constant naming that chip's arm of the ethConfigDefault ternary. - PAIRS = {"Classic RMII": "ethLan8720", "P4-NANO": "ethIp101", "S31 CoreBoard": "ethYt8531"} + PAIRS = {"Classic RMII": "ethLan8720", "P4-NANO/ETH": "ethIp101", "S31 CoreBoard": "ethYt8531"} # Every field `seedEthPresetFromPins` compares, or a drift it ignores reseeds a board to Custom. FIELDS = ["phyAddr", "mdc", "mdio", "rst", "rmiiClk", "rmiiClockExtIn"] # The preset table writes the PHY as its enum VALUE and the header names the constant. diff --git a/mooninstaller/deviceModels.json b/mooninstaller/deviceModels.json index 3f5dfd78a..2d763d535 100644 --- a/mooninstaller/deviceModels.json +++ b/mooninstaller/deviceModels.json @@ -765,7 +765,7 @@ "id": "Ethernet", "parent_id": "Network", "controls": { - "ethBoard": "P4-NANO" + "ethBoard": "P4-NANO/ETH" } } ] @@ -1000,7 +1000,7 @@ "id": "Ethernet", "parent_id": "Network", "controls": { - "ethBoard": "P4-NANO" + "ethBoard": "P4-NANO/ETH" } }, { @@ -1068,7 +1068,7 @@ "id": "Ethernet", "parent_id": "Network", "controls": { - "ethBoard": "P4-NANO" + "ethBoard": "P4-NANO/ETH" } }, { @@ -1125,7 +1125,7 @@ "id": "Ethernet", "parent_id": "Network", "controls": { - "ethBoard": "P4-NANO" + "ethBoard": "P4-NANO/ETH" } }, { @@ -1215,7 +1215,7 @@ "id": "Ethernet", "parent_id": "Network", "controls": { - "ethBoard": "P4-NANO" + "ethBoard": "P4-NANO/ETH" } } ] diff --git a/src/core/system/EthernetModule.h b/src/core/system/EthernetModule.h index 9399cef08..91038c90a 100644 --- a/src/core/system/EthernetModule.h +++ b/src/core/system/EthernetModule.h @@ -23,10 +23,10 @@ namespace mm { /// /// The preset list is filtered per chip, and the default is Custom rather than row 0. /// Where the filter leaves exactly ONE real preset that reasoning inverts, because the single survivor IS this chip's board. -/// A P4 offers P4-NANO and an S31 offers S31 CoreBoard, so Custom there ships an unconfigured interface on a board whose wiring is known. +/// A P4 offers P4-NANO/ETH and an S31 offers S31 CoreBoard, so Custom there ships an unconfigured interface on a board whose wiring is known. /// A classic keeps Custom, where several survive and only the catalog knows the board: an Olimex takes Classic RMII, a QuinLED Dig-Octa the no-reset variant. /// -/// The applied-tracker starts on a sentinel rather than row 0, or a virgin P4 would select P4-NANO and still boot with the interface at ethNone. +/// The applied-tracker starts on a sentinel rather than row 0, or a virgin P4 would select P4-NANO/ETH and still boot with the interface at ethNone. class EthernetModule : public MoonModule { public: /// Keep the interface configured whatever the toggle says, or the device drops off the network. @@ -283,8 +283,8 @@ class EthernetModule : public MoonModule { {"Classic RMII", 1, 0, 23, 18, 5, 17, false, -1, -1, -1, -1, -1, false}, // The same wiring with no reset, for a board using GPIO 5 as an LED lane: the PHY resets by jumper. {"Classic RMII (no reset)", 1, 0, 23, 18, -1, 17, false, -1, -1, -1, -1, -1, false}, - // Waveshare P4-NANO and the boards following its shield pinout: IP101, the clock fed in. - {"P4-NANO", 2, 1, 31, 52, 51, 50, true, -1, -1, -1, -1, -1, false}, + // Waveshare P4-NANO and P4-ETH, and the boards following the NANO's shield pinout: IP101, the clock fed in. + {"P4-NANO/ETH", 2, 1, 31, 52, 51, 50, true, -1, -1, -1, -1, -1, false}, // The S31's 1 Gb PHY, addressed by scan rather than by a fixed address. {"S31 CoreBoard", 4, -1, 5, 6, 7, -1, false, -1, -1, -1, -1, -1, false}, {"Custom", 0, -1, -1, -1, -1, -1, false, -1, -1, -1, -1, -1, true}, From aa98fab67ee609191904a90feb8697b22e55cb14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?King=20K=C3=A9vin?= Date: Wed, 7 Oct 2026 12:22:02 +0200 Subject: [PATCH 2/2] Address PR #130 review: drop the preset rename, trim the ETH page, fix pins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reverts this branch's P4-NANO -> P4-NANO/ETH preset rename in full, since the maintainer is renaming shared Ethernet presets by their wiring rather than by the boards that share one, in a separate upcoming PR. Trims the ESP32-P4-ETH hardware page to what it alone records, fixes its sourcing and prose style, and corrects two wrong pin claims the page and the catalog entry both carried. **Core** - `EthernetModule.h`: reverted to `main`, no `P4-NANO/ETH` rename. **Scripts/MoonDeck** - `check_devices.py`: reverted to `main`, same reason. **Docs/CI** - `esp32-p4-eth.md`: rewritten per review — the Ethernet section keeps only the RMII data lines (TXD0/1, RXD0/1, TXEN, RXDV) that `EthernetModule.h`'s preset row doesn't already carry, one sentence replaces the duplicated 4-field table; the audio software-config sentence now links `AudioService`/`I2cBusModule` instead of repeating control values; the free-GPIO section is gone (lives in `gpio-usage.md`). DSDIN (9) and PA_Ctrl (53) now read as wired on the board rather than "not wired up" — MoonLight just doesn't implement playback. Added the amplifier's name (NS4150B, same chip the S31 uses) and a new microSD section (D0 39, D1 40, D2 41, CD/D3 42, CLK 43, CMD 44, VDD gate 45): wired, unimplemented, and not recorded anywhere else in the repo. Sources now cite the real Waveshare schematic/drawing URLs instead of a local path that was never in the repo. No em-dashes, no process history, present tense throughout. - `gpio-usage.md`: the P4-ETH row's free-GPIO set was wrong (copied the P4-NANO's blind of the board having no C6/WiFi, and of GPIO 24/25 actually being USB D-/D+); now `2-6, 14-23, 26, 27, 32, 33, 46-48, 54`, with Ethernet RMII, audio, USB, and the microSD slot named as the reserved set. - `deviceModels.json`: reverted the preset rename on all 5 P4-family entries; separately fixed the Waveshare ESP32-P4-ETH's `ParallelLedDriver` default from `20,21,22,23,24,25,26,27` to `16,17,18,19,20,21,22,23`, since the original drove the board's USB D-/D+ pins as LED lanes. Checks run: `check_prose.py` (vale newly installed this session; added lines clean, confirmed directly against the final file content since the script's own `main...HEAD` diff still includes this branch's pre-fix commit until this one lands), `build_docs.py --strict`, `check_devices.py`, `check_specs.py`, `check_docgen.py` — all clean, no new findings. The committed `prose.md` baseline is left untouched: vale's first real run in this environment shows it's far out of date (pre-existing debt, unrelated to this diff), and refreshing it is its own sweep. Co-Authored-By: Claude Sonnet 5 --- docs/reference/hardware/esp32-p4-eth.md | 78 ++++++++++++------------- docs/reference/hardware/gpio-usage.md | 6 +- moondeck/check/check_devices.py | 2 +- mooninstaller/deviceModels.json | 12 ++-- src/core/system/EthernetModule.h | 8 +-- 5 files changed, 51 insertions(+), 55 deletions(-) diff --git a/docs/reference/hardware/esp32-p4-eth.md b/docs/reference/hardware/esp32-p4-eth.md index ff6169c5d..d6f7916f7 100644 --- a/docs/reference/hardware/esp32-p4-eth.md +++ b/docs/reference/hardware/esp32-p4-eth.md @@ -1,63 +1,57 @@ # Waveshare ESP32-P4-ETH hardware reference -Pin maps and onboard features for the **Waveshare ESP32-P4-ETH**, read from the official schematic so MoonLight work (Ethernet, audio) reads this instead of re-scraping the PDF. The board runs the plain `esp32p4rev1-eth` firmware (the same build the P4-NANO uses) and is `"Waveshare ESP32-P4-ETH"` in the device catalog. +Pin maps and onboard features for the **Waveshare ESP32-P4-ETH**, read from the schematic so MoonLight work reads this instead of re-scraping the PDF. The board runs the plain `esp32p4rev1-eth` firmware, the same build the P4-NANO uses, and is `"Waveshare ESP32-P4-ETH"` in the device catalog. **Sources** -- Product page: -- Wiki: -- Schematic (local): `datasheet/ESP32-P4-ETH/ESP32-P4-ETH-datasheet.pdf` +- Schematic: +- Board drawing: -Same family as the Waveshare ESP32-P4-NANO (see [gpio-usage.md § ESP32-P4](gpio-usage.md#esp32-p4) for its pin map): ESP32-P4 (RISC-V dual-core), same onboard IP101 Ethernet PHY wiring, same CSI/DSI/I2C accessory-bus convention, same onboard **ES8311** audio codec feeding an SMD mic + a 2-pin JST speaker header. The [MHC-WLED ESP32-P4 shield](mhc-wled-esp32-p4-shield.md) is a different, unrelated P4 carrier board (RS-485/line-in, no onboard codec). +Same family as the Waveshare ESP32-P4-NANO: ESP32-P4, RISC-V dual-core, the same onboard IP101 Ethernet PHY wiring, and the same CSI/DSI/I2C accessory-bus convention. See [gpio-usage.md § ESP32-P4](gpio-usage.md#esp32-p4) for the pin map. It carries the same onboard **ES8311** audio codec, feeding an SMD mic and a 2-pin JST speaker header. The [MHC-WLED ESP32-P4 shield](mhc-wled-esp32-p4-shield.md) is a different, unrelated P4 carrier board, with RS-485/line-in and no onboard codec. ## Audio (ES8311 codec) -The onboard SMD mic and speaker header connect through an **ES8311 mono codec**. The ESP is the I2S master (it drives MCLK). +The onboard SMD mic and speaker header connect through an **ES8311 mono codec** and an **NS4150B** class-D amplifier, the same amplifier chip the ESP32-S31 uses. The ESP is the I2S master, driving MCLK. -| Signal | GPIO | Direction / role | +| Signal | GPIO | Role | |---|---|---| -| I2S MCLK | 13 | master clock → codec (ESP is I2S master; MCLK = 256 × sample_rate) | +| I2S MCLK | 13 | master clock to the codec, 256 × sample_rate | | I2S SCLK (BCLK) | 12 | bit clock | | I2S LRCK (WS) | 10 | word select | -| I2S ASDOUT | 11 | **mic / ADC data: codec → ESP** (the record path) | -| I2S DSDIN | 9 | playback / DAC data: ESP → codec (speaker path, **not wired up** — out of scope, mic-only) | -| **ESP_I2C_SDA** | **7** | codec control bus (shared with the CSI/DSI accessory headers) | -| **ESP_I2C_SCL** | **8** | codec control bus | -| PA_Ctrl | 53 | speaker amp enable (not wired up — speaker is out of scope) | +| I2S ASDOUT | 11 | mic data, codec to ESP, the record path | +| I2S DSDIN | 9 | speaker data, ESP to codec; wired on the board, playback is not implemented | +| ESP_I2C_SDA | 7 | codec control bus, shared with the CSI/DSI accessory headers | +| ESP_I2C_SCL | 8 | codec control bus | +| PA_Ctrl | 53 | NS4150B amplifier enable; wired on the board, not implemented | -- **ES8311 I2C address: `0x18`** (the hardware default; no address-select strap). -- The codec is runtime configuration, not a firmware variant: the catalog entry opens the **[I2C bus](../../moonmodules/core/moxygen/I2cBusModule.md)** on SDA 7 / SCL 8 and sets **[AudioService](../../moonmodules/core/moxygen/AudioService.md)**'s `codec` to `ES8311` with `codecAddr` `0x18`, `mclkPin` 13, `sckPin` 12, `wsPin` 10, `sdPin` 11, `mode` local audio. Applying the device model is what turns the codec on; `esp_codec_dev` is built into every `esp32s31`/`esp32p4` firmware, so no board-specific Kconfig or sdkconfig fragment is needed — the same binary the P4-NANO ships drives this board's codec too. -- Driven by Espressif's **`esp_codec_dev`** managed component (the same driver and the same `platform_esp32_es8311.cpp` the ESP32-S31 and the P4-NANO use), including its two address-shift / null-`data_if` fixes — neither is P4-ETH-specific, see that file's header comment. -- The codec needs **MCLK running before it answers I2C**; `AudioService` brings up the I2S channel (which drives MCLK) before the codec I2C config, same ordering as every other ES8311 board. -- **Mic-only path** (audio-reactive input): all pins above confirmed independently from the schematic netlist *and* the Waveshare wiki (which separately publishes the same I2C/I2S pin set). The speaker path (DSDIN + PA_Ctrl) is a separate capability, not implemented here. -- **Bench-verified end to end** 2026-10-06, on the plain `esp32p4rev1-eth` firmware: the I2C bus scan ACKs the codec at `0x18`, named `0x18 Audio (ES8311)`, and `AudioService` reports live mic data (level RMS tracking ambient room noise, onsets, a peak-Hz reading) once `codec`/`mclkPin` are set from the catalog entry. +The ES8311's I2C address is `0x18`, the hardware default with no address-select strap. The catalog entry configures [AudioService](../../moonmodules/core/moxygen/AudioService.md)'s ES8311 codec on these pins, through the board's [I2cBusModule](../../moonmodules/core/moxygen/I2cBusModule.md). The speaker path (DSDIN, PA_Ctrl) is a separate, unimplemented capability. -## Ethernet (IP101 PHY, RMII) +## Ethernet (IP101GRI PHY, RMII) -On-chip EMAC → **IP101GRI** PHY → RJ45, **RMII** with a 25 MHz crystal, externally-fed 50 MHz reference clock. Same reference design as the Waveshare P4-NANO — confirmed pin-for-pin identical: +The board uses the `P4 RMII` preset, shared with the Waveshare P4-NANO: MDC 31, MDIO 52, PHY reset 51, reference clock 50 (see [EthernetModule](../../moonmodules/core/moxygen/EthernetModule.md)). The RMII data lines, fixed by the chip and not part of that preset, read from the schematic: -| Signal | GPIO | Source | -|---|---|---| -| MDC | 31 | schematic netlist (unambiguous two-pin net, matches the P4 pin table) | -| MDIO | 52 | schematic netlist (same) | -| PHY reset | 51 | direct schematic inspection (the flattened PDF text extraction was ambiguous here; confirmed by eye against the drawing) | -| RMII ref clock (external in) | 50 | carried over from the P4-NANO preset, consistent with the other three now-confirmed pins | - -Catalog entry: `EthernetModule.ethBoard = "P4-NANO/ETH"` — one shared preset, not a separate row per board, since the pins read pin-for-pin identical between the two; see [gpio-usage.md § ESP32-P4](gpio-usage.md#esp32-p4) for the shared preset. - -**Bench-verified** 2026-10-06: link up and a DHCP lease at 100 Mbit on the plain `esp32p4rev1-eth` firmware. - -## Other onboard features (not wired up here) - -From the Waveshare wiki: MIPI-CSI (2-lane, OV5647-compatible), MIPI-DSI (2-lane, 5"/7"/8"/10.1" panels), SDIO 3.0 microSD slot, USB-C (native + UART bridge), BOOT/RESET buttons. None of these conflict with the audio (GPIO 7-13) or Ethernet (GPIO 28-31/49-52) pins above. +| Signal | GPIO | +|---|---| +| TXD0 | 34 | +| TXD1 | 35 | +| TXEN | 49 | +| RXD0 | 29 | +| RXD1 | 30 | +| RXDV | 28 | -## Free GPIO for user peripherals (LED strips) +## microSD slot -Following the P4-NANO's own reference set (`ParallelLedDriver` default `pins="20,21,22,23,24,25,26,27"`), with this board's audio pins added to the committed set: +Wired on the board; MoonLight does not mount it: -| Peripheral | GPIOs | +| Signal | GPIO | |---|---| -| Ethernet RMII (fixed silicon pads) | 28-31, 49-52 | -| ES8311 audio (I²S + I²C) | 7-13 | -| CSI/DSI accessory headers | share the I2C bus (7-8) plus their own dedicated MIPI diff-pairs | +| D0 | 39 | +| D1 | 40 | +| D2 | 41 | +| CD/D3 | 42 | +| CLK | 43 | +| CMD | 44 | +| VDD gate (pMOS) | 45 | + +## Other onboard features -**Clear, following the P4-NANO's documented set**: 20-27, 32-33, 39-48 (the catalog's `ParallelLedDriver` default is `pins="20,21,22,23,24,25,26,27"`, same as the P4-NANO). GPIO 20/21 also appear as spare IO on this board's CSI header (same situation as the P4-NANO, which treats them as free LED pins regardless) — only relevant if a camera module is actually plugged in. See [gpio-usage.md § ESP32-P4](gpio-usage.md#esp32-p4) for the general P4 pin map this board extends. +From the Waveshare wiki: MIPI-CSI (2-lane, OV5647-compatible) and MIPI-DSI (2-lane, 5, 7, 8 and 10.1-inch panels) accessory headers, plus BOOT and RESET buttons. USB-C is native, with D- on GPIO 24 and D+ on GPIO 25, and a UART-bridge variant also exists. diff --git a/docs/reference/hardware/gpio-usage.md b/docs/reference/hardware/gpio-usage.md index a09b1c605..2d2d6493e 100644 --- a/docs/reference/hardware/gpio-usage.md +++ b/docs/reference/hardware/gpio-usage.md @@ -70,9 +70,11 @@ For **LED output** specifically — the pins a WS2812-class strand data line can | Role-conflict | **34-38** | Strapping pins (boot mode). Don't drive at reset; the first LED-driver default wrongly landed here (see [lessons.md](../../work/past/lessons.md)). | | Role-conflict | **37, 38** | UART0 console on the P4-NANO (`CONFIG_ESP_CONSOLE_UART_DEFAULT`) — the runtime `ESP_LOGI` lines come out here, not over USB. | | Board-wired (P4-NANO) | **Ethernet RMII** 28-31 / 49-52, **C6 SDIO** 14-19 / 54, **I2C** 7-8 | Consumed by the NANO's on-board Ethernet PHY, the C6 WiFi co-processor, and the I2C bus. | -| Board-wired (P4-ETH) | **Ethernet RMII** 28-31 / 49-52 (same preset as the NANO), **ES8311 audio** 7-13 | The [Waveshare ESP32-P4-ETH](esp32-p4-eth.md) has no C6/WiFi, but carries its own onboard ES8311 codec on the same I2C pins (7-8) plus I2S 9-13. | +| Board-wired (P4-ETH) | **Ethernet RMII** 28-31 / 34-35 / 49-52, **ES8311 audio** 7-13, **USB D-/D+** 24-25, **microSD** (unimplemented) 39-45 | The [Waveshare ESP32-P4-ETH](esp32-p4-eth.md) has no C6/WiFi. It carries its own onboard ES8311 codec, a native USB-C port, and a microSD slot; that page has the full per-signal map. | -**Clear on the P4-NANO:** 20-27, 32-33, 39-48 (the LED-driver default is `pins="20,21,22,23,24,25,26,27"`). Exact free set is board-specific; the NANO's is the reference. A carrier board changes what's exposed and how — the [MHC-WLED ESP32-P4 shield](mhc-wled-esp32-p4-shield.md) routes every terminal through level shifters / RS-485 transceivers / protected inputs (no bare GPIO), which is why a direct loopback jumper fails on it; its full terminal map is on that page. The [Waveshare ESP32-P4-ETH](esp32-p4-eth.md) clears the same 20-27/32-33/39-48 set, its own audio codec pins (7-13) already counted above. +**Clear on the P4-NANO:** 20-27, 32-33, 39-48 (the LED-driver default is `pins="20,21,22,23,24,25,26,27"`). Exact free set is board-specific; the NANO's is the reference. A carrier board changes what's exposed and how. The [MHC-WLED ESP32-P4 shield](mhc-wled-esp32-p4-shield.md) routes every terminal through level shifters, RS-485 transceivers, or protected inputs, with no bare GPIO. A direct loopback jumper fails on it for that reason. Its full terminal map is on that page. + +**Clear on the P4-ETH:** 2-6, 14-23, 26, 27, 32, 33, 46-48, 54. ## ESP32-S31 diff --git a/moondeck/check/check_devices.py b/moondeck/check/check_devices.py index 84dc235cb..017f59c16 100644 --- a/moondeck/check/check_devices.py +++ b/moondeck/check/check_devices.py @@ -91,7 +91,7 @@ def eth_preset_drift(): rows[m.group(1)] = [f.strip() for f in m.group(2).split(",")] # label -> the PHY constant naming that chip's arm of the ethConfigDefault ternary. - PAIRS = {"Classic RMII": "ethLan8720", "P4-NANO/ETH": "ethIp101", "S31 CoreBoard": "ethYt8531"} + PAIRS = {"Classic RMII": "ethLan8720", "P4-NANO": "ethIp101", "S31 CoreBoard": "ethYt8531"} # Every field `seedEthPresetFromPins` compares, or a drift it ignores reseeds a board to Custom. FIELDS = ["phyAddr", "mdc", "mdio", "rst", "rmiiClk", "rmiiClockExtIn"] # The preset table writes the PHY as its enum VALUE and the header names the constant. diff --git a/mooninstaller/deviceModels.json b/mooninstaller/deviceModels.json index 2d763d535..db177e513 100644 --- a/mooninstaller/deviceModels.json +++ b/mooninstaller/deviceModels.json @@ -765,7 +765,7 @@ "id": "Ethernet", "parent_id": "Network", "controls": { - "ethBoard": "P4-NANO/ETH" + "ethBoard": "P4-NANO" } } ] @@ -1000,7 +1000,7 @@ "id": "Ethernet", "parent_id": "Network", "controls": { - "ethBoard": "P4-NANO/ETH" + "ethBoard": "P4-NANO" } }, { @@ -1060,7 +1060,7 @@ "parent_id": "Drivers", "controls": { "peripheral": "Parlio", - "pins": "20,21,22,23,24,25,26,27" + "pins": "16,17,18,19,20,21,22,23" } }, { @@ -1068,7 +1068,7 @@ "id": "Ethernet", "parent_id": "Network", "controls": { - "ethBoard": "P4-NANO/ETH" + "ethBoard": "P4-NANO" } }, { @@ -1125,7 +1125,7 @@ "id": "Ethernet", "parent_id": "Network", "controls": { - "ethBoard": "P4-NANO/ETH" + "ethBoard": "P4-NANO" } }, { @@ -1215,7 +1215,7 @@ "id": "Ethernet", "parent_id": "Network", "controls": { - "ethBoard": "P4-NANO/ETH" + "ethBoard": "P4-NANO" } } ] diff --git a/src/core/system/EthernetModule.h b/src/core/system/EthernetModule.h index 91038c90a..9399cef08 100644 --- a/src/core/system/EthernetModule.h +++ b/src/core/system/EthernetModule.h @@ -23,10 +23,10 @@ namespace mm { /// /// The preset list is filtered per chip, and the default is Custom rather than row 0. /// Where the filter leaves exactly ONE real preset that reasoning inverts, because the single survivor IS this chip's board. -/// A P4 offers P4-NANO/ETH and an S31 offers S31 CoreBoard, so Custom there ships an unconfigured interface on a board whose wiring is known. +/// A P4 offers P4-NANO and an S31 offers S31 CoreBoard, so Custom there ships an unconfigured interface on a board whose wiring is known. /// A classic keeps Custom, where several survive and only the catalog knows the board: an Olimex takes Classic RMII, a QuinLED Dig-Octa the no-reset variant. /// -/// The applied-tracker starts on a sentinel rather than row 0, or a virgin P4 would select P4-NANO/ETH and still boot with the interface at ethNone. +/// The applied-tracker starts on a sentinel rather than row 0, or a virgin P4 would select P4-NANO and still boot with the interface at ethNone. class EthernetModule : public MoonModule { public: /// Keep the interface configured whatever the toggle says, or the device drops off the network. @@ -283,8 +283,8 @@ class EthernetModule : public MoonModule { {"Classic RMII", 1, 0, 23, 18, 5, 17, false, -1, -1, -1, -1, -1, false}, // The same wiring with no reset, for a board using GPIO 5 as an LED lane: the PHY resets by jumper. {"Classic RMII (no reset)", 1, 0, 23, 18, -1, 17, false, -1, -1, -1, -1, -1, false}, - // Waveshare P4-NANO and P4-ETH, and the boards following the NANO's shield pinout: IP101, the clock fed in. - {"P4-NANO/ETH", 2, 1, 31, 52, 51, 50, true, -1, -1, -1, -1, -1, false}, + // Waveshare P4-NANO and the boards following its shield pinout: IP101, the clock fed in. + {"P4-NANO", 2, 1, 31, 52, 51, 50, true, -1, -1, -1, -1, -1, false}, // The S31's 1 Gb PHY, addressed by scan rather than by a fixed address. {"S31 CoreBoard", 4, -1, 5, 6, 7, -1, false, -1, -1, -1, -1, -1, false}, {"Custom", 0, -1, -1, -1, -1, -1, false, -1, -1, -1, -1, -1, true},