Skip to main content

synth0

synth0

Based on the Raspberry Pi Pico, it uses 6 of it’s PIO state machines to create pulse density modulated waves. Work with PIO is something I’ve wanted to do for quite a while. It’s always seemed scary complex, but it truly is not that bad. It does take a bit to get used to PIO assembly, but when it clicks the instructions aren’t that complicated.

I used PIO to shift bits out really really quickly so I could use a digital modulation to make an analog wave. The wave itself is hardcoded. The rp2040 is set up to send the modulated wave from double-buffered DMA to the PIO state machine FIFO. This allows me to continuously emmit the wave without any interrupions.

As the wave modulation is hardcoded, in order to achieve different frequencies, I change the state machine’s frequency on the fly:

Calculating the state machine's frequency as keys are pressed in order to make the correct audible tone. I could have used a lookup table, after all there aren't that many notes. But the rp2040 proved plenty fast enough to do the calculations, despite it having no FPU.
// f = 440 * 2^((n - 69) / 12)
// Where n is the midi note number and f is the audible frequency,
// assuming A4 = 440Hz
//
// There are 128 bits per wave, and the PIO state machine takes 2 clock cycles to get each bit out
#[inline(always)]
fn note_to_pio_div(note: u8, clock: u32) -> f32 {
    let freq = 440.0 * exp2f((f32::from(note) - 69.0) / 12.0) * 128.0 * 2.0;
    clock as f32 / freq
}

It’s neat that there’s a proportional realtion between the MIDI spec note number and the audible frequency of a note.

I calculate the modulation with a python script. Here’s what they look like: (Red: Original wave, Blue: Modulated wave)

Sine #

sine

Sawtooth #

sawtooth

Rhodes / Electronic organ-like #

(with a lot of imagination)

rhodes
Rhodes and Electronic organs’ sound is mostly a sum of three or four harmonic sines.

And you can imagine what the square wave looks like.

The modulated waves consist of 128 bits, so when low-passed it all blends together:

oscilloscope

The synth connects to a MIDI controller through an old school DIN-5 MIDI port. Implementing USB MIDI was out of the scope of the project. The old school port is just UART, and it was fun to implement. Here’s a video from when I got it working:

Here’s how some basic waves sound on it:

Sine #

Square #

Sawtooth #

“Rhodes” #

As you can see, it’s got a terrible noise floor and some constant peeks above 7kHz. That’s an artifact of my computer’s power supply and the pico’s voltage regulator, as it happens with any firmware. It sounds quite awful, but you can tell the wave it’s trying to play, which is enough for me. The goal was learning and not a musical instrument after all.

The clips above do use some after processing. I attenuated those peaks and added a gate so you don’t constantly hear the noise floor. The Rhodes-like clip has added chorus and reverb, to make it a bit closer to the sound it’s trying to imitate.

Update! I got an audio interface with a nice pre-amp and I powered the synth with a cleaner power supply. While there’s some 50Hz humm, the signal is now clean of all of those high frequency spikes! Here I re-recorded some of the songs I had played above:

And here’s a little bass jam, since I think the bass tones it makes, while a bit harsh, sound cool.

Big thanks to Stephen with the counceling (and emotional support) on electronics, this wouldn’t have been possible without them.

As always, here’s the firmware: https://gitlab.com/slusheea/synth0