This looks really interesting, and is relevant to my current interests
I see that so far you’ve done some (all?) of the tricky low level stuff, but there don’t appear to be any simple examples of e.g. a keyboard or control surface sketch so one can add a couple of switches or pots to a Teensy and get a feel for how it’d all work. Or send it events that get parsed and printed to Serial.
I may be alone in this, but I’m always much more inclined to try stuff out if I can hack together a few parts I already own and have a play with simple but known-working examples. I’m sure the Roland and Korg products are great, but they’re still not exactly impulse buys…
Hi
@h4yn0nnym0u5e , thanks for reading the post carefully.
You pinpointed exactly what I chose not to bring into this
conversation yet: the application layer. The initial post covered
only USB descriptors and raw UMP I/O because I wanted to first
understand how Paul and the community see that low-level piece.
The application layer (UMP parsing, MIDI-CI, Property Exchange,
Discovery, 14/16/32-bit controllers) still involves an
architectural decision that isn't mine to make, it's Paul's:
- vendored inside cores (zero external dependency)?
- external Arduino lib dependency (cores just calls into it)?
- Paul writes it from scratch, no dependency at all?
The three have tradeoffs and it feels natural to hear how Paul
prefers to work before proposing anything to cores at that layer.
MIDI 2.0's semantics are broader than MIDI 1.0's (Discovery,
Profiles, Property Exchange come into play alongside the
messages), so the decision of where that lives in the stack
carries more weight.
About Teensy examples: I ran a proof of concept of the application
layer in a lib of mine called midi2cpp (sauloverissimo/midi2cpp on
github). It has a Teensy 4.1 sketch (teensy41-midi2.ino) that
shows the full path: UMP Stream identity (Endpoint Discovery,
Function Block), MIDI-CI with Discovery + Profile + 2 Properties,
and a demo loop that fires the MIDI 2.0 repertoire: NoteOn with
32-bit velocity, 32-bit CC, Per-Note Pitch Bend, Per-Note
Controllers, Flex Data (Tempo + Time Signature). It's the
skeleton. Right now I'm working on an adaptation with pot and
switch reading, to close exactly the use case you described.
Today it runs on top of the cores fork as experimental overrides;
if the conversation with Paul lands on a different path, it
adapts. But I built it driven by the desire to see Teensy
operating in MIDI 2.0, more as an experiment than anything.
I agree 100% with you about the products. I cited Roland A-88MKII
and Korg Keystage only because Paul set that premise back in 2020.
They check the box, but you're right: real hobbyist work calls for
something more accessible.
---
Edit: Follow-up: the adaptation I mentioned is up.
teensy41-control-surface in midi2cpp covers exactly what you
described: 4 pots on A0..A3 sending 32-bit CC (CC1 Modulation,
CC74 Brightness, CC71 Resonance, CC91 Reverb Send), 4 switches
on D2..D5 sending NoteOn/Off (C4..D#4), and any UMP received from
the host decoded line by line to Serial at 115200: NoteOn/Off,
CC, PitchBend, ChannelPressure, Program, Per-Note PitchBend,
Flex Data Set Tempo + Set Time Signature.
~175 LOC sketch, MIDI-CI left out to keep it simple. EMA smoothing
+ deadband on pots, millis debounce on switches, 12-bit ADC
expanded to 32-bit by replicating the MSB so the full range
reaches MIDI 2.0 receivers. Hardware-validated on Teensy 4.1
today against Linux ALSA (/dev/snd/umpC*D0).
Repo: github -> sauloverissimo/midi2cpp, examples/teensy41-control-surface.
README has pin map, wiring, build command, and what each block
does.
