r/raspberrypipico • u/LouDNL • 36m ago
c/c++ Driving real SID chips from a Pico: five PIO state machines, DMA, and a cycle counter slaved to the clock pin
I have been building USBSID-Pico for a while, an RP2040/RP2350 board that talks to real MOS SID chips over USB. Most of the fun was on the Pico side, and that part is what I want to share.
PIO layout (PIO0)
- The SID clock is generated by a tiny PIO program on GPIO 22. It is two instructions with side-set, and the clock divider is computed from the system clock and the configured SID clock rate.
- Three more state machines run off that same clock pin. One latches the control lines (RW, CS1, CS2), one drives the 16 data/address pins, and one is a delay timer that counts SID clock edges and then raises PIO IRQs to release the other two. That is how a write lands on an exact SID cycle.
- A fifth state machine on PIO1 is a free-running cycle counter that waits on the clock pin and pushes into the FIFO. DMA drains it (endless transfer count on RP2350, two chained channels on RP2040). This creates a 32-bit wide cycle counter.
DMA and cores
- Separate DMA channels feed the control, data and delay FIFOs and read data back from the bus. A hardware spinlock guards the shared words.
- Core 0 runs TinyUSB and config. Core 1 runs MIDI and Network SID Device writes, the LED, and the optional embedded c64 emulator for playing SID tunes without an external player.
Other bits
- USB composite device: 2x CDC (1 for Data and 1 for WebSerial), MIDI, and two vendor interfaces (WebUSB and a second one for fast reads).
- pico_w/pico2_w builds can run a Network SID Device server over TCP with UDP discovery.
- Builds exist for pico, pico_w, pico2 and pico2_w. Default optimization in CMake is -O3 to be sure everything stays in sync.
It plays C64 music with real chips, but I am posting for the Pico side. Source: https://github.com/LouDnl/USBSID-Pico
Happy to answer questions about the PIO side, especially the timing handshake between the SMs. Has anyone else used a PIO cycle counter slaved to an external pin like this?
