05 — Keybed & MIDI
Electrical distinction: The S90 keybed is a passive contact matrix, not an I²C device. USB-MIDI remains the software/bench transport; the integrated FPGA card must scan the matrix or receive bounded scanner events and deliver timestamped notes to the N100 without a polled I²C note path.
1. What the S90 keybed actually is
Section titled “1. What the S90 keybed actually is”The Yamaha S90 (2002) uses the Balanced Hammer (BH) weighted action. Electrically it is a passive key-contact matrix:12
- Each key has a rubber-dome with two carbon contacts at slightly different heights, pressing onto traces on segmented L / M / H contact boards (Low/Mid/High). These boards carry no active ICs — just copper.
- Velocity is the time delta between the first contact closing (break-from-rest) and the second closing (make-at-bottom): a hard strike ≈ 4–6 ms, a soft one ≈ 80–100 ms. The host times this and maps it to MIDI velocity 0–127.1
- The boards daisy-chain via ribbon cables to a wide flat-flex (third-party repair notes suggest ~36 wires for the S90-class action — [verify] on your unit).3
flowchart LR
subgraph KEY["One key"]
C1["Contact 1<br/>(breaks first)"]
C2["Contact 2<br/>(makes at bottom)"]
end
C1 -->|"t0"| T["Δt = t1 − t0<br/>→ velocity"]
C2 -->|"t1"| T
T --> V["MIDI velocity 0–127"]
Does the raw keybed use I²C?
Section titled “Does the raw keybed use I²C?”The available key-contact evidence points to a passive matrix, not an I²C peripheral. Later Yamaha instruments do have internal scanner buses, but that does not establish a usable I²C endpoint on this S90.45 A retained Yamaha scanner/control board, if any, must be inspected separately.
Working assumption: the raw S90 key contacts form a passive two-contact matrix. The exact ribbon pinout and any retained Yamaha scanner-board protocol are not verified on this instrument and must be measured.3
2. Bench approach: an RP2350 scanner → USB-MIDI
Section titled “2. Bench approach: an RP2350 scanner → USB-MIDI”flowchart LR
KB["S90 BH keybed<br/>2-contact matrix"] -->|"ribbon"| LS["Level shift / protect<br/>(3.3 V, series R, ESD)"]
LS --> RP["RP2350<br/>matrix scan + velocity timing<br/>(PIO for precise edges)"]
RP -->|"USB-MIDI<br/>(TinyUSB, class-compliant)"| HOST["N100 host"]
RP -. "optional" .-> DIN["DIN/UART MIDI<br/>(lowest jitter)"]
- Scan the matrix at ≥ 1 kHz full-keyboard. The RP2350’s PIO state machines are ideal for sub-microsecond contact-edge timing, which matters for accurate velocity at the soft end.6
- Derive velocity from the make/break Δt per key, via a calibration curve.
- Emit Note-On/Off/aftertouch as USB-MIDI using TinyUSB — the RP2350 enumerates as a standard class-compliant USB-MIDI device, so any host (Linux/macOS/Windows) sees it with no driver.6
- Electrical care: the keybed is passive, so the RP2350 supplies the scan strobes and senses returns at 3.3 V; add series resistors and ESD protection on the ribbon. [verify] the matrix dimensions and pinout by continuity-measuring the actual S90 ribbon before wiring.
Why USB-MIDI and not the I²C control bus
Section titled “Why USB-MIDI and not the I²C control bus”| USB-MIDI | I²C (as note transport) | |
|---|---|---|
| Jitter | bounded ~0–1 ms (USB FS frame); avg ~500 µs7 | adds poll-interval jitter on top |
| RP2040/RP2350 quirks | none (native USB) | HW I²C mis-clocks & is intolerant of clock-stretch8 |
| Standard | universal, driverless | bespoke register protocol |
| Verdict | use this for notes | reserve for slow control data (06) |
If you ever need sub-100 µs jitter (e.g. tight multi-instrument recording), add a DIN-MIDI/UART output (worst-case ~32 µs) via a 3.3 V→5 V buffer; for live playing, USB-MIDI’s jitter is imperceptible.9
2.1 Integrated FPGA path
Section titled “2.1 Integrated FPGA path”The selected Tang card replaces the bench transport, not the keybed’s
electrical reality. Measure the S90 ribbon and the original panel interfaces
first. A protected FPGA GPIO matrix scanner is preferred if pin count, voltage,
timing and routing allow it; otherwise a nearby scanner MCU can send
timestamped contact/note events over a bounded dedicated link to the FPGA.
The FPGA exposes those events over PCIe to a Linux input/MIDI adapter, which
maps them into Auvra’s existing protocol-independent musical-event model.
Neither scanner choice depends on the AE350 or Linux userspace polling each
key contact. I²C may configure a scanner or connect genuine I²C peripherals.
If the original Yamaha scanner board is retained and a usable I²C endpoint is
actually measured, it can be evaluated as a bridge with explicit note-latency
and recovery tests; no such endpoint is established by the current sources.
Do not assume the raw keybed speaks I²C or put notes on an unbounded polled
control bus. See 17 F9.
3. Internal event model
Section titled “3. Internal event model”Implemented (2026-08-30): Auvra’s engine uses a protocol-independent, MIDI-2-capable musical-event model. MIDI 1 byte streams and MIDI 2 UMP are I/O formats handled by platform adapters; neither wire representation leaks into the patch router or plugin-independent engine.10
The real-time event contract carries block-relative timing, group/channel, a
host-assigned note id, full-resolution velocity/controller data, and semantic
note expression. The MIDI 1 adapter expands 7/14-bit values into that model and
assigns note ids. auvra-clap then prefers CLAP note/note-expression events and
uses a plugin port’s MIDI dialect for channel controllers where available. This
preserves MIDI 1 compatibility with the S90 prototype while avoiding another
engine rewrite for overlapping notes, MPE, MIDI 2 controllers, or future
keybeds.
Initial scope:
- note on/off with stable note identity and sample offset;
- control change (including pedals), pitch bend, channel pressure, and poly pressure;
- protocol-neutral scaling with MIDI 1 input and CLAP output adapters;
- bounded event storage and no allocation or locks on the audio thread.
Native CoreMIDI/ALSA UMP input, MIDI-CI, Profiles, Property Exchange, SysEx 8, and MIDI 2 output/thru are later transport/control-plane work. They must plug into the same semantic event contract rather than replace it.
4. Reference projects
Section titled “4. Reference projects”No published project targets the S90 BH keybed on RP2350 — you would be among the first. Closest templates:111213
| Project | Keybed / MCU | Why relevant |
|---|---|---|
floretan/p150 |
Yamaha P150 (GH, 2-contact) · Teensy | Same dual-contact rubber-dome principle as BH. |
oxesoft/keyboardscanner |
multiple (incl. Yamaha PSR530) · Arduino Mega | Best-maintained general scanner; reusable scan engine. |
djbottrill/RP2040_Midi_Scanner |
Fatar matrix · RP2040 | Only confirmed RP2040 keybed scanner (organ, no velocity). |
chamodhk/midi_keyboard |
Casio · RP2040 + TinyUSB MIDI | TinyUSB USB-MIDI pattern on the RP family. |
Practical recipe: combine the dual-contact velocity timing of floretan/p150 with the TinyUSB USB-MIDI pattern of chamodhk/midi_keyboard, using RP2350 PIO for edge timing.
5. Open questions ([verify])
Section titled “5. Open questions ([verify])”- Exact S90 ribbon pinout and matrix size — measure continuity on the real keybed; do not trust the ~36-wire third-party figure.3
- Contacts per key — confirm 2 (assumed) vs any 3-contact variant.
- Strobe voltage/timing tolerances of the original contacts at 3.3 V.
- Silicon stepping of the RP2350 (use A3/A4 to avoid the early GPIO pull-down errata).6
- FPGA GPIO budget versus a nearby scanner MCU; event-link latency/jitter, protection and fault recovery under concurrent PCIe audio/display load.
Footnotes
Section titled “Footnotes”-
Syntaur, “Keys not responding correctly? Check the contact strips.” https://blog.syntaur.com/?p=38 ↩ ↩2
-
E. Bruchez, “Fixing a Yamaha Clavinova CLP-280” (passive L/M/H membrane contacts). https://blog.bruchez.name/posts/fixing-yamaha-clavinova-clp-280/ ↩
-
Syntaur, “Yamaha S90 XS repair parts” (ribbon cables). https://syntaur.com/keyboard.php?keyboard=Yamaha_S90+XS ↩ ↩2 ↩3
-
P. Drongowski, “Yamaha MODX: Inside stuff” (E-GKS + I²C EBUS). http://sandsoftwaresound.net/yamaha-modx-inside-stuff/ ↩
-
PJRC forum, “Converting a Yamaha keyboard assembly with a Teensy” (CVP-409/509 smart keybed, I²C). https://forum.pjrc.com/index.php?threads/converting-a-yamaha-keyboard-assembly-with-a-teensy-to-a-midi-controller.35858/ ↩
-
Raspberry Pi, “RP2350 datasheet” (PIO, USB, ADC; A3/A4 stepping). https://datasheets.raspberrypi.com/rp2350/rp2350-datasheet.pdf ↩ ↩2 ↩3
-
MIDI Association, “Jitter and latency.” https://midi.org/community/midi-connections/jitter-and-latency-usb-firewire-thunderbolt ↩
-
MicroPython issue #8167 (RP2040 HW I²C clock-stretch failures). https://github.com/micropython/micropython/issues/8167 ↩
-
“MIDI throughput, latency & jitter” (DIN-MIDI worst-case ~32 µs). https://calcsandcomps.blogspot.com/2021/10/midi-throughput-latency-jitter.html ↩
-
MIDI Association, “Universal MIDI Packet (UMP) and MIDI 2.0 Protocol Specification.” https://midi.org/universal-midi-packet-ump-and-midi-2-0-protocol-specification ↩
-
floretan/p150— Yamaha P150 + Teensy MIDI scanner. https://github.com/floretan/p150 ↩ -
oxesoft/keyboardscanner— multi-keyboard scanner. https://github.com/oxesoft/keyboardscanner ↩ -
djbottrill/RP2040_Midi_Scanner— RP2040 keybed scanner. https://github.com/djbottrill/RP2040_Midi_Scanner ↩