01 — System Architecture
This document separates the selected integrated-hardware target from the
working software/bench path. The target uses the Tang Mega 138K Pro card; the
bench path keeps software and latency experiments possible before that card’s
drivers and physical interfaces pass their gates (17).
1. Selected integrated target
Section titled “1. Selected integrated target”flowchart LR
subgraph HOST["N100 · real-time Linux"]
APP["Auvra engine + GUI<br/>CLAP · SDL3/egui"]
ALSA["ALSA PCM"]
DRM["DRM/KMS + evdev"]
APP <--> ALSA
APP <--> DRM
end
subgraph FPGA["Tang Mega 138K Pro · GW5AST-138"]
PCIE["PCIe endpoint<br/>priority DMA + event queues"]
AUDIO["I²S/TDM audio fabric"]
FB["DDR3 framebuffer<br/>RGB888/DVI scanout"]
CTRL["key scanner + I²C/GPIO<br/>timestamped input"]
PCIE <--> AUDIO
PCIE <--> FB
PCIE <--> CTRL
end
ALSA <--> PCIE
DRM <--> PCIE
AUDIO <--> ADC["PCM1822 ADC ×1<br/>2 analog inputs"]
AUDIO <--> DAC["PCM5122 DAC ×2<br/>4 analog outputs"]
ADC <--> JACKS["Balanced XLR + unbalanced jack<br/>line I/O"]
DAC <--> JACKS
FB --> PANEL["Touch display"]
PANEL --> CTRL
MATRIX["S90 passive key matrix"] --> SCANNER["protected FPGA or MCU scanner"] --> CTRL
BUTTONS["S90 controls · later buttons/LEDs"] <--> CTRL
The N100 always renders the GUI and runs synthesis. The FPGA scans out its host-written framebuffer and exposes audio through an Auvra ALSA driver; touch/controls use Linux input interfaces. The S90 key contacts are not I²C: the scanner topology and existing panel wiring must be measured. I²C applies only to peripherals that actually speak it. Audio DMA and sample timing have priority over display and control traffic. AES67 and AE350 autonomy are later stages; neither blocks local audio/display/control bring-up.
2. Software MVP and bench block diagram
Section titled “2. Software MVP and bench block diagram”flowchart TB
subgraph S90["Yamaha S90 chassis"]
direction TB
subgraph INPUTS["Physical inputs"]
KEYBED["88-key BH keybed<br/>passive 2-contact matrix"]
POTS["Potentiometers<br/>(knobs)"]
FADERS["Motor-faders<br/>(position + motor)"]
BTNS["Buttons / switches"]
end
subgraph OUTPUTS["Physical outputs"]
LEDS["LEDs / indicators"]
DISP["Touch display<br/>7–10″ capacitive"]
end
end
subgraph MCU["RP2350 microcontroller layer"]
direction TB
KSCAN["RP2350 — Keybed scanner<br/>matrix scan + velocity timing"]
NODE1["RP2350 node A<br/>pots + buttons + LEDs"]
NODE2["RP2350 node B<br/>motor-faders (+ driver)"]
NODEX["RP2350 node …"]
end
subgraph HOST["Sound engine — Intel N100 ITX"]
direction TB
RTOS["PREEMPT_RT Linux"]
SYNTH["Auvra app<br/>UI + plugin host + mixer<br/>(cpal → ALSA, doc 12)"]
UI["Kiosk UI<br/>(full-screen)"]
I2CBR["USB→I²C bridge<br/>MCP2221A → /dev/i2c-N"]
AUDIF["Audio interface<br/>(class-compliant)"]
end
AOUT["Balanced stereo/▶ out<br/>TRS / XLR"]
AIN["Line/mic in<br/>(optional)"]
KEYBED --> KSCAN
POTS --> NODE1
BTNS --> NODE1
FADERS <--> NODE2
NODE1 --> LEDS
KSCAN -->|"USB-MIDI"| RTOS
NODE1 -->|"I²C"| I2CBR
NODE2 -->|"I²C"| I2CBR
NODEX -->|"I²C"| I2CBR
I2CBR -->|"USB"| RTOS
DISP -->|"HDMI"| UI
DISP -->|"USB-HID"| UI
RTOS --- SYNTH
RTOS --- UI
SYNTH <--> AUDIF
AUDIF --> AOUT
AIN --> AUDIF
2.1 Bench subsystem responsibilities
Section titled “2.1 Bench subsystem responsibilities”| Block | Responsibility | Detail doc |
|---|---|---|
| Keybed scanner (RP2350) | Scan the 88-key matrix, derive velocity from make/break timing, emit Note-On/Off as USB-MIDI. | 05-keybed-and-midi.md |
| Control-surface nodes (RP2350) | Read pots (ADC), buttons (GPIO), drive LEDs, drive/track motor-faders. Expose state as I²C registers. | 06-control-surface.md |
| USB→I²C bridge | Give the N100 a real /dev/i2c-N since the board has no I²C header. |
06-control-surface.md |
| Sound engine (N100 + RT Linux) | Host synth/effect plugins in patches, run the mixer and the UI; own the audio device; route MIDI. | 12, 02, 03 |
| Audio interface | Convert to balanced analog with low latency. | 04-audio-io.md |
| Touch display | Kiosk UI surface (HDMI video + USB touch); never shows boot. | 07-display-and-boot.md |
| Power | One 19 V DC-in feeds the N100; derived rails feed MCUs, panel, faders. | 08-power-and-chassis.md |
The diagram and table describe the software MVP/bench path, not the selected
integrated product topology. The FPGA card replaces the external audio device,
host HDMI scanout and USB control links only after the corresponding gates pass
(17-fpga-audio-interface.md).
3. Bench control planes
Section titled “3. Bench control planes”A deliberate split keeps the hard-real-time path clean:
flowchart LR
subgraph HARD["Hard real-time — note events"]
K["Keybed RP2350"] -->|"USB-MIDI<br/>~0–1 ms jitter"| H1["Host MIDI in"]
end
subgraph SOFT["Soft real-time — control surface"]
C["RP2350 nodes"] -->|"I²C 100–400 kHz<br/>polled ~1 kHz"| H2["Host /dev/i2c-N"]
end
H1 --> ENG["Synth engine"]
H2 --> ENG
- Hard real-time (USB-MIDI): key strikes need bounded, low jitter. USB Full-Speed MIDI bounds jitter to roughly one 1 ms frame; it is the universal, driverless transport.1 Optional DIN-MIDI/UART path exists if sub-100 µs jitter is ever required.2
- Soft real-time (I²C): a knob moving from 0→127 over tens of milliseconds is fine on a ~1 kHz polled I²C bus. This also matches the host’s only practical option — a USB→I²C bridge — because the N100 board exposes no I²C header.3
Why not put everything on one bus? Because mixing time-critical note events with bulk control polling on a single I²C bus would couple their timing and inherit I²C’s clock-stretching quirks on the RP2350.4 Keeping them separate is the single most important architectural decision in Auvra.
4. Bench end-to-end latency budget
Section titled “4. Bench end-to-end latency budget”The target is a measured key-to-sound latency below 10 ms. The following unverified estimate applies to the bench USB path only; PCIe, converter and scanner contributions must be measured separately for the integrated card.5
| Stage | Typical | Notes |
|---|---|---|
| Keybed contact → scan detects make | 0.2–1 ms | Depends on scan rate (target ≥ 1 kHz full-matrix). |
| RP2350 processing + USB-MIDI frame | 0.5–1 ms | USB FS frame jitter ≤ 1 ms.1 |
| Host MIDI handling → synth voice start | < 0.5 ms | RT-scheduled MIDI thread. |
| Synth DSP one audio period | 1.3 ms | 64 frames @ 48 kHz.6 |
| Audio interface output buffer (RTL) | 1.3–2.7 ms | Device + driver; see 04. |
| Total (key→sound) | ≈ 4–6 ms | Comfortably below the 10 ms threshold. |
sequenceDiagram
participant K as Key contact
participant M as RP2350 scanner
participant U as USB-MIDI
participant S as Synth engine (N100)
participant A as Audio interface
K->>M: contact make/break (velocity timing)
M->>U: Note-On (note, velocity)
U->>S: MIDI event (≤1 ms frame)
S->>S: allocate voice, render 1 period (64f ≈ 1.33 ms)
S->>A: audio buffer
A-->>K: balanced analog out (audible)
Note over K,A: budget ≈ 4–6 ms total
5. Bench connectivity map (host ports)
Section titled “5. Bench connectivity map (host ports)”How the N100’s real ports are allocated:
| N100 port | Used by |
|---|---|
| HDMI | Touch display video |
| USB (×1) | Touch display touch (USB-HID) |
| USB (×1) | Keybed scanner (USB-MIDI) |
| USB (×1) | USB→I²C bridge (control surface) |
| USB (×1) | Audio interface (if USB) |
| PCIe 3.0 x4 (x2) | Free in the bench setup; allocated to the selected Auvra FPGA card for integrated hardware (17) |
| M.2 (M-key) | NVMe boot SSD |
| 19 V DC-in | System power |
The board has 4× USB 3.2 Gen1 + 8× USB 2.0,7 so USB device count is not a constraint. A small powered USB hub is optional for tidy internal wiring.
6. Failure & degradation behaviour
Section titled “6. Failure & degradation behaviour”| Failure | Designed behaviour |
|---|---|
| Control-surface node drops off I²C | Synth keeps playing; UI flags the node; no audio glitch (separate plane). |
| USB-MIDI scanner disconnects | Keys stop; UI warns; reconnect is hot-pluggable. |
| Power loss mid-use | Immutable rootfs → clean boot next time; only unsaved patch edits lost (writable partition). |
| Audio xrun (buffer underrun) | Logged; if frequent, UI suggests raising buffer; see RT tuning in 03. |
Footnotes
Section titled “Footnotes”-
MIDI Association, “Jitter and latency: USB/FireWire/Thunderbolt.” https://midi.org/community/midi-connections/jitter-and-latency-usb-firewire-thunderbolt ↩ ↩2
-
DIN-MIDI/UART worst-case jitter ≈ 32 µs vs ~500 µs average for USB-MIDI. “MIDI throughput, latency & jitter.” https://calcsandcomps.blogspot.com/2021/10/midi-throughput-latency-jitter.html ↩
-
Linux kernel, “i2c-i801” driver docs (SMBus reserved for SPD/sensors). https://docs.kernel.org/i2c/busses/i2c-i801.html ↩
-
RP2040/RP2350 hardware I²C clock-stretch limitations. MicroPython issue #8167. https://github.com/micropython/micropython/issues/8167 ↩
-
Round-trip audio under ~10 ms is generally imperceptible to players. See
03-realtime-os.md. ↩ -
64 frames @ 48 kHz = 1.33 ms/period; ≈ 2.7 ms round-trip on a tuned RT kernel. LinuxMusicians, “lowest latency PipeWire or JACK.” https://linuxmusicians.com/viewtopic.php?t=27901 ↩
-
ASRock, “N100DC-ITX” specification. https://www.asrock.com/mb/Intel/N100DC-ITX/index.asp ↩