midi2cpp | Device MIDI 2.0
Full-spec USB MIDI 2.0 device on the Waveshare ESP32-P4-WIFI6-DEV-KIT (RISC-V Cortex-M-class core, USB-OTG internal PHY). Headless single-file showcase of every MIDI 2.0 message category beyond MIDI 1.0. ESP-IDF v5.4 build, no Arduino IDE.
The Waveshare kit exposes two USB-C jacks: USB-Device routes the P4 internal PHY (used here for USB MIDI 2.0); ToUART routes the CH343 USB-Serial-JTAG bridge for console + flashing. The two USB-A jacks tied to the UTMI host PHY are not used in this device-only recipe.
| Field | Value |
|---|---|
| VID:PID | cafe:4091 (development-only) |
| Product | ESP32P4DevKit |
| Manufacturer | github.com/sauloverissimo |
Requires ESP-IDF v5.4+ with . $IDF_PATH/export.sh sourced and the RISC-V toolchain installed ($IDF_PATH/install.sh esp32p4 once on a fresh IDF).
cd idf
./scripts/fetch_tinyusb.sh # one-off, ~36 MB clone of TinyUSB upstream
. $IDF_PATH/export.sh
idf.py set-target esp32p4
idf.py build
idf.py -p /dev/ttyACM0 flash monitor # ToUART jackThe CH343 USB-Serial-JTAG bridge (VID 1a86:55d3) on the ToUART jack binds to cdc_acm (/dev/ttyACM0). Real DTR / RTS, so idf.py flash auto-resets without a button press.
To override TinyUSB with a local working copy: ln -sfn /path/to/your/tinyusb idf/external/tinyusb && idf.py reconfigure.
| Connector / Pin | Use |
|---|---|
| USB-C USB-Device | Native USB-OTG (internal PHY, device role), MIDI 2.0 device interface |
| USB-C ToUART | CH343 USB-Serial-JTAG bridge, console stdio @ 115200 8N1, flashing |
| USB-A jacks (×2) | UTMI host PHY, not used in this device-only recipe |
| BOOT button | Hold during reset to enter download mode (rarely needed; CH343 auto-reset handles it) |
| RESET button | Reboot |
lsusb | grep cafe:4091
amidi -l # IO hw:N,1,0 Group 1 (Main)
PORT=$(aseqdump -l | grep -i ESP32P4DevKit | awk '{print $1}' | tr -d ':')
timeout 30 aseqdump -p ${PORT}Microsoft MIDI Services Console (Windows) shows ESP32P4DevKit with Native data format = UMP, MIDI 2.0 Protocol = True.
Tier A (full spec). The ESP32-P4's 768 KB SRAM affords the complete UMP + MIDI-CI surface.
| UMP MT | Spec | Notes |
|---|---|---|
| 0x0 Utility | M2-104-UM §3 | JR heartbeat 500 ms, Delta Clockstamp |
| 0x4 MIDI 2.0 Channel Voice | M2-104-UM §7 | 32-bit CCs, Per-Note family, Note Attribute, RPN/NRPN, Relative RPN/NRPN |
| 0x3 SysEx7 | M2-104-UM §7.7 | up to 6 bytes per packet, auto-fragmented |
| 0xD Flex Data | M2-104-UM §10 | Tempo, Time Sig, Key Sig, Metronome, Chord Name, Start/End of Clip |
| 0xF UMP Stream | M2-104-UM §11 | full Endpoint + FB Discovery |
MIDI-CI: Discovery + Profiles (1 custom registered) + Property Exchange (3 properties: static, dynamic, subscribable) + Process Inquiry, all via the m2ci Appendix E convenience responder.
Always on while mounted: JR heartbeat (500 ms), UMP Stream + MIDI-CI Discovery responders, 1 custom Profile, 3 PE properties, Process Inquiry replies.
Per cycle (~22 s):
| Scene | Content | MIDI 2.0 only because |
|---|---|---|
| A. Flex Data | Tempo (120 BPM), Time Sig (4/4), Key Sig (C), Metronome, Chord Name (Cmaj7), Start of Clip | MT 0xD + 0xF |
| B. Per-Note | Sustained C4 with Per-Note Pitch Bend (5 Hz vibrato), Registered Per-Note Controller #7, Assignable Per-Note Controller #74, Per-Note Management Reset | Per-Note family is MIDI 2.0 only |
| C. Resolution | Chromatic walk C5→G#5 with 16-bit velocity ramp, 32-bit CC #74 sweep, 32-bit Pitch Bend, 32-bit Poly Pressure, 32-bit Channel Pressure | MIDI 1.0 caps at 7/14-bit |
| D. Program + Bank | Program Change with bank MSB/LSB in a single UMP | MIDI 1.0 needs three messages |
| E. RPN/NRPN | RPN 0/0, NRPN, Relative RPN (+delta), Relative NRPN (-delta) | RPN/NRPN first-class + Relative |
| F. Note Attribute | Note On with attribute_type=0x03 (pitch_7_9), E4 +50 cents |
Microtonal attribute |
| G. SysEx7 | Universal SysEx Identity Reply, 12 bytes, auto-fragmented (Start + End) | MT 0x3 |
| H. Delta Clockstamp | DCTPQ=480 + Delta Clockstamp=240 ticks | MT 0x0 utility |
| I. PE Notify | Broadcast OverlayRate change to subscribers (value increments per cycle) |
Property Exchange |
| J. End of Clip | Sequencer End of Clip marker | MT 0xF status 0x21 |
Every scene logs to UART via the CH343 bridge on the ToUART jack at 115200 8N1.
MIT, inherits parent midi2cpp LICENSE.
