Skip to content

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.

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"]

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.
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

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.

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.

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.

  1. Exact S90 ribbon pinout and matrix size — measure continuity on the real keybed; do not trust the ~36-wire third-party figure.3
  2. Contacts per key — confirm 2 (assumed) vs any 3-contact variant.
  3. Strobe voltage/timing tolerances of the original contacts at 3.3 V.
  4. Silicon stepping of the RP2350 (use A3/A4 to avoid the early GPIO pull-down errata).6
  5. FPGA GPIO budget versus a nearby scanner MCU; event-link latency/jitter, protection and fault recovery under concurrent PCIe audio/display load.
  1. Syntaur, “Keys not responding correctly? Check the contact strips.” https://blog.syntaur.com/?p=38 ↩ ↩2

  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/ ↩

  3. Syntaur, “Yamaha S90 XS repair parts” (ribbon cables). https://syntaur.com/keyboard.php?keyboard=Yamaha_S90+XS ↩ ↩2 ↩3

  4. P. Drongowski, “Yamaha MODX: Inside stuff” (E-GKS + I²C EBUS). http://sandsoftwaresound.net/yamaha-modx-inside-stuff/ ↩

  5. 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/ ↩

  6. Raspberry Pi, “RP2350 datasheet” (PIO, USB, ADC; A3/A4 stepping). https://datasheets.raspberrypi.com/rp2350/rp2350-datasheet.pdf ↩ ↩2 ↩3

  7. MIDI Association, “Jitter and latency.” https://midi.org/community/midi-connections/jitter-and-latency-usb-firewire-thunderbolt ↩

  8. MicroPython issue #8167 (RP2040 HW I²C clock-stretch failures). https://github.com/micropython/micropython/issues/8167 ↩

  9. “MIDI throughput, latency & jitter” (DIN-MIDI worst-case ~32 µs). https://calcsandcomps.blogspot.com/2021/10/midi-throughput-latency-jitter.html ↩

  10. 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 ↩

  11. floretan/p150 — Yamaha P150 + Teensy MIDI scanner. https://github.com/floretan/p150 ↩

  12. oxesoft/keyboardscanner — multi-keyboard scanner. https://github.com/oxesoft/keyboardscanner ↩

  13. djbottrill/RP2040_Midi_Scanner — RP2040 keybed scanner. https://github.com/djbottrill/RP2040_Midi_Scanner ↩