Files
midi-router/docs/hardware-plan.md
T
nils 9123f7691d Hardware plan: RM2 module, RP2040->RP2350 target
Use the pre-certified Raspberry Pi Radio Module 2 (RM2, CYW43439 + PCB
antenna) instead of a bare CYW43439 — eliminates RF design + cert; only
the datasheet antenna keepout remains. Dev/test on RP2040 (Pico W),
product on RP2350; firmware dual-builds via embassy-rp features.
2026-08-21 10:54:24 +02:00

156 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Hardware Plan — flexible MIDI router (v1)
Status: draft 2026-08-21. Custom all-in-one PCB, desktop, USB-powered, 0-10 V
CV via onboard boost, 3.5 mm TRS MIDI, 4× stereo CV, 64×32 OLED + tact buttons
(no encoder, low profile).
**MCU target:** develop/test on **RP2040** (Pico W dev board — the firmware
already runs on it), product on **RP2350**. The RM2 radio module is compatible
with both. The Rust firmware builds for either via embassy-rp features
(`rp2040` → `thumbv6m-none-eabi`; `rp235xa` for the RP2350A used in the Pico 2 W
→ `thumbv8m.main-none-eabihf`). Pin assignments below are RP2040/Pico-W; the
RP2350 product PCB keeps the Pico-2-W-compatible RM2 bus and reuses the same
peripheral choices.
See `midi-router-architecture` (session memory) for the software/firmware
architecture this hardware serves.
## 1. Block diagram
```
USB-C 5V ──┬── 3.3 V buck ── RP2040 + W25Q16 flash + RM2 module (CYW43439, BLE/WiFi)
│ │
│ ├── PIO0 SPI ── RM2 (CYW43439 gSPI, Pico-W pinout)
│ ├── USB DP/DM ── (USB-MIDI composite, CDC+MIDI)
│ ├── UART0 ──── MIDI TRS in (6N138) / out
│ ├── I2C0 ───── Pimoroni RGB Keypad (buttons)
│ ├── SPI0 ───── Pimoroni RGB Keypad (APA102 LEDs)
│ ├── SPI1 ───── 8-ch 16-bit DAC (CV outs)
│ ├── I2C1 ───── 64×32 SSD1306 OLED
│ └── GPIOs ──── 4× tact buttons (UI)
│
└── 12 V boost ── CV op-amp rails (+12 V) ── 4× stereo TRS (8 CV/gate)
│
4.096 V ref ── DAC ── op-amp gain ×2.44 ── 0-10 V ── 1 k series + TVS ── TRS tip/ring
```
## 2. RP2040 pin map
Peripherals follow the Pico W reference for the RM2/CYW43 bus (so the cyw43
driver and our firmware work unchanged) and our existing keypad wiring.
| Function | RP2040 pins | Notes |
|--------------------|------------------------|-----------------------------------------|
| USB device | GP14 (DM), GP15 (DP) | USB-C; CDC + MIDI composite |
| RM2 (CYW43) bus | GP29 (CLK), GP24 (DAT), GP25 (CS-out), GP23 (PWR), PIO0, DMA CH0/CH1 | copy Pico W |
| RM2 onboard LED | CYW43 WL_GPIO0 | status/heartbeat |
| Keypad buttons | GP4 (SDA), GP5 (SCL) | I2C0, expander @0x20 |
| Keypad LEDs | GP17 (CS), GP18 (SCK), GP19 (MOSI) | SPI0 tx-only, 4 MHz, APA102 |
| DAC (CV outs) | GP10 (SCK), GP11 (MOSI), GP13 (CS) | SPI1 tx-only, 16-bit DAC; MISO unused |
| DAC LDAC/RESET | GP20, GP21 | GPIO (optional, immediate-update) |
| MIDI TRS UART | GP0 (TX), GP1 (RX) | UART0 @31250 baud |
| OLED | GP2 (SDA), GP3 (SCL) | I2C1, SSD1306 64×32 |
| UI buttons | GP6, GP7, GP8, GP9 | 4× low-profile tact: Up/Down/Select/Back|
| SWD debug header | SWCLK, SWDIO | 2×3 header for Picoprobe (first-flash) |
| Spare | GP16, GP22, GP26-28 | status LEDs / future analog in |
No conflicts; GP14/15 (USB) and GP23-25/29 (CYW43) kept clear of everything else.
## 3. Power tree (USB-only, with CV boost)
- USB-C 5 V → polyfuse + ESD → **VBUS_5V**.
- VBUS_5V → **3.3 V buck** (RT6150 / TPS62A01) → RP2040, CYW43, flash, DAC VDD,
OLED, pull-ups. Budget ~400 mA peak (CYW43 BT/WiFi TX spikes).
- VBUS_5V → **12 V boost** (MT3608 / TPS61088, ~80 mA) → +12 V CV op-amp rail,
LC-filtered (pitch noise).
- **4.096 V reference** (REF3040 / LM4040-4.096) for the DAC — NOT the 3.3 V
rail (too noisy for 1 V/oct pitch).
Rationale: USB-only power (single cable, no external PSU) while still delivering
0-10 V CV via a small boost. The boost + LC filter + dedicated Vref keeps pitch
clean. If 0-5 V (5 octaves) is acceptable, drop the boost and use RRO op-amps
on 5 V (simpler, fewer parts, but half the CV range).
## 4. CV analog section (4 stereo = 8 channels)
- **DAC:** 8-channel 16-bit SPI (DAC8568 or AD5668), Vref = 4.096 V → 0-4.096 V out.
16-bit over 0-10 V ≈ 0.15 mV/step ≈ 0.002 semitone — plenty for 1 V/oct pitch.
- **Scaling:** non-inverting op-amp, gain ×2.44 → 0-10 V from the 4.096 V DAC
span, rail = +12 V. Needs rail-to-rail-output (TL074 is NOT RRO and can't do
0-10 V on a single +12 V rail). Use **OPA4192** (quad RRO) ×2 for 8 channels,
or TLV9154.
- **Per-channel model:** every CV channel is an independent
`(midi_channel, function)` sink (pitch/gate/velocity/CC). Gate = DAC channel
driven to 0 or 10 V (keeps the routing uniform; no separate gate GPIOs).
- **Output protection:** 1 kΩ series + TVS per output to TRS tip/ring.
## 5. MIDI TRS (3.5 mm) — 2 jacks (in + out), TRS-A wiring
- **In:** tip → 220 Ω → 6N138 optocoupler LED → cathode to ring. Transistor:
collector to 3.3 V via 1 k pull-up → UART0 RX (GP1); emitter to GND; base
speed-up (1N4148 + 1 k). Isolated; powered from the input loop.
- **Out:** UART0 TX (GP0) → 220 Ω → tip; ring to 3.3 V. (3.3 V/220 Ω ≈ 15 mA,
fine for MIDI-out LED.)
- TRS-A: tip = signal, ring = return (Korg / Make Noise convention).
## 6. Display + UI
- **OLED:** SSD1306 64×32 (0.42"), I2C1. Small — UI is paginated (≈2 lines of
small text); routing/CV assignments shown a few at a time.
- **Buttons:** 4× low-profile SMD tact (Up / Down / Select / Back) on GP6-9. No
rotary encoder (height constraint).
## 7. RM2 radio module — risk largely eliminated
Use the **Raspberry Pi Radio Module 2 (RM2, part RMC20452T)**: a CYW43439-based
module (16.5 × 14.5 mm, 21 castellated pads) with integrated inverted-F PCB
antenna and internal PA/LNA/T-R switch. Full modular radio approval in US/EU/
UK/CA (FCC ID 2ABCB-RMC2GW4B52) — no radio design or certification needed on
the host board. Software-compatible with the Pico W SDK, so our cyw43 firmware
works unchanged.
Host PCB responsibilities (from the RM2 datasheet):
- Mount the 21 castellated pads; route the gSPI host pins to RP2040 (Pico W
pinout: CLK=GP29, DAT=GP24, CS=GP25, PWR=GP23, on PIO0 + DMA CH0/CH1).
- 3.3 V supply (no other rails).
- **Antenna keepout area** must remain free of metal per the datasheet for
the module's PCB antenna to perform.
## 8. BOM sketch
- RP2040 (dev) / **RP2350A** (product) MCU, W25Q16JV-equivalent flash,
**RM2 radio module (RMC20452T, CYW43439 + PCB antenna, pre-certified)**.
- DAC8568IAPW (8-ch 16-bit SPI, TSSOP-16) — or AD5668.
- OPA4192IPW ×2 (quad RRO op-amp, TSSOP-14).
- REF3040AIDBZ (4.096 V ref, SOT-23).
- 6N138 optocoupler (MIDI in).
- USB-C receptacle; 6× 3.5 mm TRS jacks (2 MIDI + 4 CV stereo).
- 3.3 V buck (RT6150/TPS62A01), 12 V boost (MT3608/TPS61088).
- SSD1306 64×32 OLED; 4× low-profile SMD tact switches.
- SWD 2×3 header (Picoprobe for first-flash).
- Passives, polyfuse, TVS array.
## 9. Risks / open items
1. **0-10 V CV noise from the boost** — LC filter + dedicated 4.096 V Vref.
2. **Custom RP2040 bring-up** — needs a SWD header + Picoprobe; USB bootloader
only works after first flash.
3. **64×32 OLED UI** — tight; menu must be paginated and minimal.
4. **Boost current budget** — RM2 TX spikes + 8 CV op-amps on a single USB
5 V/500 mA (USB 2.0) port is tight; specify USB-C 5 V/900 mA-3 A, or limit
CV op-amp current.
5. **RM2 antenna keepout** — follow the datasheet keepout; the one layout
constraint the radio imposes.
## 10. Build order (hardware)
1. Schematic (this doc is the spec).
2. RM2 module footprint + antenna keepout.
3. RP2040 + flash + USB + SWD.
4. Power (3.3 V buck, 12 V boost, Vref).
5. CV analog (DAC + op-amps + protection + TRS).
6. MIDI TRS circuit.
7. OLED + buttons.
8. Keypad header (the Pimoroni keypad connects via a header or is integrated).
9. PCB layout, DRC, review, fab.