Add ATmega32U4 USB MIDI 2.0 device example (stock Arduino core)#1
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2c1ff13233
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| void Midi2Usb::begin() { | ||
| midi2_dispatch_init(&g_dp); | ||
| stream_responder_attach(&g_dp); | ||
| midi2_proc_init(&g_proc, g_sysex7_buf, sizeof g_sysex7_buf, NULL, 0); |
There was a problem hiding this comment.
Keep Data128 messages on the echo path
When a host sends MT 0x5 Data128 traffic (SysEx8 or MDS), this processor consumes those messages before on_ump is called; because the SysEx8 buffer/callback is disabled here, they are then silently dropped. That contradicts the example's advertised/validated Data128 surface and its echo behavior, so SysEx8/MDS sent by a host will not come back unless Data128 is explicitly forwarded or handled.
Useful? React with 👍 / 👎.
| for (uint32_t i = 0; i < count; i++) | ||
| if (!midi2duino_write_word(words[i])) | ||
| return i; /* ring full: partial write reported */ |
There was a problem hiding this comment.
Write MIDI-CI SysEx7 packets atomically
MIDI-CI replies are emitted as two-word SysEx7 UMP packets, but this callback queues each word separately; if the TX ring has only one free slot while a Discovery reply is being generated, the first word is accepted and the second fails, leaving an incomplete UMP at the head of the ring that can block or corrupt later USB output. Use the complete-message write path so either the whole packet is queued or none of it is.
Useful? React with 👍 / 👎.
This adds
examples/atmega32u4-device-arduino, a complete USB MIDI 2.0 device that runs on a plain 8-bit ATmega32U4 (Arduino Leonardo, Pro Micro, Micro). It enumerates as a native MIDI 2.0 endpoint, answers UMP Stream and MIDI-CI Discovery, and loops a small showcase of the message surface. It flashes with a normal Arduino upload and fits in about 17 KB of flash and 1.3 KB of SRAM.The interesting part is the transport: it rides the stock Arduino core through PluggableUSB, so there is no LUFA, no TinyUSB and no extra USB stack. The midi2 core in this repo builds and parses the UMP, reassembles SysEx7 and answers MIDI-CI, while the midi2duino library carries the packets over USB. A thin
Midi2Usbveneer wires the responders and the message processor onto the transport and exposes readablesend*helpers, with nostd::functionand no heap.The showcase covers, on group 0:
MIDI-CI Discovery is answered with a per-boot randomized MUID. Anything the device does not support is NAKed, and its capabilities are advertised as
0x00, so nothing is over-promised.It passes the MIDI 2.0 Workbench self-certification and is validated on hardware. On Linux the kernel reads the Group Terminal Block and exposes one bidirectional Function Block named
Main; on Windows MIDI Services it shows up asATmega32U4 MIDI 2.0with UMP as the native format. A board photo and the Windows captures are in the example folder.One caveat: the stock Arduino core does not forward
SET_INTERFACEto PluggableUSB, so the device always speaks UMP and targets MIDI 2.0 hosts. The README explains it.