Adding d-mux support to the Yocto
2025-02-03
I modified my Yocto drum machine to work with the proprietary Sequentix d-mux music interface.
The d-mux protocol
I make my music using a Sequentix Cirklon sequencer. Although the Cirklon is designed around MIDI it also supports CV/gate communication and its own proprietary "Drum Mux" or d-mux protocol. "Mux" stands for "multiplexer". This protocol is meant to be used with percussion sounds.
MIDI timing limitations
Using MIDI for percussion can be iffy because of the inherent timing limitations of the protocol. The problem is that MIDI is slow and messages contain single notes with no timing information. The usual interpretation of a "note on" message is "play this note right now". If you want to play three notes at the same time then really you can't: three notes means three messages that will arrive at distinct times and each will get played at its time of arrival.
It depends on the kind of instrument you're controlling whether this staggered one-note-at-a-time timing is a problem. Often enough you don't notice the effect at all. It's most likely to be noticeable with percussive sounds, such as drums.
This is probably a solved problem for most people. USB MIDI is much faster and I imagine the same is true for virtual synthesizers that run on the same computer as the sequencer. But in my 1980s retro world of hardware synths and sequencers this problem still exists.
The d-mux solution: batch messages
The d-mux protocol addresses this problem (simultaneous notes becoming staggered) by sending notes in batch messages. Now you can have simultaneous notes, provided they arrive in the same batch.
All this is proprietary to the Cirklon ecosystem. You can buy a break-out box from Sequentix that connects to the Cirklon with a 5-pin DIN cable. The break-out box has jack sockets that allow you to connect individual cables for each trigger signal to something like a Simmons SDS-800 or Eurorack drum modules.
Yocto + d-mux = profit?
A while back I came across a video from Sequentix where Cirklon designer Colin Fraser demonstrates the difference d-mux makes by using a custom modified TR-808 drum machine. If you don't have time to watch the whole thing, jump to 4:53.
This got me thinking about whether I could add d-mux to my Yocto DIY 808 clone. The problem is that a d-mux receiver is expensive (about €400) and I'd have to buy a new one just for the Yocto. Also the way Colin does it in his video he is customizing the 808 circuit in a way that feels a little over my head.
But then a while later Colin shared some of the details of how the d-mux protocol works. The cool thing about the Yocto is that I wrote my own firmware for it and most of what's needed to receive the d-mux signals is already there.
The hardware mod
The Yocto has the 3 standard MIDI DIN ports (In, Out, Thru) but it also has a fourth DIN port to send out Roland "Sync" signals. People call this "DIN sync" nowadays but that is a weird name because DIN is a German standards body and Roland's 1980s sync protocol is not standardized with DIN. I digress.
The DinSync port of the Yocto connects pin 1 and 3 to the MCU and pin 2 to ground. The d-mux protocol uses all 5 pins, with pin 2 as ground, but I have to ignore one of the pins because of Yocto hardware limitations (the global accent design discussed below). This leaves 4 pins, 3 of which are already connected. Luckily for me there is a pad on the circuit board right next to the Yocto DinSync port that leads to an unused GPIO pin of the MCU. So all I had to do to connect the remaining d-mux signal was to connect pin 5 of the DIN port to the unused pad.
d-mux signal | DIN socket pin | Yocto MCU GPIO pin |
---|---|---|
Clock | 1 | PORTD5 |
Accent CV | 4 | (ignored) |
Ground | 2 | digital ground |
Trigger | 5 | PORTB0 (using jumper) |
Frame | 3 | PORTD4 |
Instead of spending €400 on an official d-mux receiver and ripping out its circuit board, I spent €0 on a leftover piece of wire.
Adapting the firmware
The d-mux protocol works like a latched serial in parallel out shift register. I modified the Yocto firmware so that it receives the d-mux trigger bits that are being transmitted in RAM and when the sender unlatches the data the Yocto MCU (an ATmega1284P) triggers the drum voices.
I struggled with the timing of reading the incoming d-mux serial transmission but I got it working alright using a "pin change interrupt" on the MCU. The MCU has to do its own SPI transmissions to the internal hardware. These are slow and waiting for SPI to complete causes me to miss incoming d-mux bits. By using a pin change interrupt I can keep up with the d-mux transmission in spite of being stuck waiting for SPI.
The other problem I ran into was communication between the pin change interrupt and the main thread. I ended up making a very simple lock-free queue that seems to do the job. You can see how I got it working in this commit. I had to move some code around to make it work but in the end it's fairly simple.
There is the pin change interrupt:
ISR(PCINT3_vect) {
uint8_t new_state = PIND;
if (!(dmux.state & DMUX_FRAME) &&
(new_state & DMUX_FRAME)) { /* frame rise */
dmux.n = 0;
dmux.bitmap = 0;
} else if ((dmux.state & DMUX_FRAME) &&
!(new_state & DMUX_FRAME)) { /* frame fall */
if (dmux.bitmap) {
dmux_queue.idx =
(dmux_queue.idx + 1) % nelem(dmux_queue.frame);
dmux_queue.frame[dmux_queue.idx] = dmux.bitmap;
}
} else if (!(dmux.state & DMUX_CLOCK) &&
(new_state & DMUX_CLOCK)) { /* clock rise */
;
} else if ((dmux.state & DMUX_CLOCK) &&
!(new_state & DMUX_CLOCK)) { /* clock fall */
if ((PINB & DMUX_TRIG) && dmux.n < nelem(voicetab))
dmux.bitmap |= (1 << dmux.n);
dmux.n++;
}
dmux.state = new_state;
}
And then in the main loop we check if there is a new frame in the queue:
if (dmux_idx = dmux_queue.idx, dmux_idx != last_dmux_idx) {
for (i = 0; i < nelem(voicetab); i++)
if (dmux_queue.frame[dmux_idx] & (1 << i))
voicetab[i].pulse = PULSE;
note_on = 1;
last_dmux_idx = dmux_idx;
}
And the rest of the main loop then handles this just as if a bunch of MIDI notes arrived all at the same time.
How my hack is different from what Colin showed
I am happy that this works and that I avoided paying €400 for an official d-mux receiver but I have to admit that my solution is not equivalent to what Colin showed in his video.
The 808 lets you program drum hits with two strengths: "normal" and "accent". The strength is a global setting. If a step is accented then all drum hits on that step are louder. There is a knob on the machine that lets you dial in how big the difference between "normal" and "accent" is. This system works pretty well but it's not what people expect from a modern drum machine. With MIDI you could make a snare drum roll with a crescendo. That doesn't work on the 808; even if you manually moved the accent knob during the roll to create the crescendo swell you'd be raising the volume of all drum hits coming out of the machine, not just the snare drum.
The hardware modification Colin made to his 808 gives him control over the strength of each individual drum hit. This is a more complex modification and if I wanted to do this I would probably need a proper d-mux receiver after all.
What my solution does is to treat the "accent" as a silent "meta" drum hit. On the Cirklon I program it as any other drum hit and then the Yocto raises the volume as expected. This is also how it works in the original 808 user interface. While this is less flexible then varying the strength per instrument, it does give me the authentic 808 sound, with the associated improved timing, and all controlled from the Cirklon along with the rest of my song.
One of the example patterns from the 808 manual, sequenced by the Cirklon and played back by the Yocto via d-mux. Note how the global accent "AC" is written on a line of its own the same way as the instruments (bass drum "BD", snare drum "SD" etc.).
Conclusion
This was a fun project. I got better at embedded programming and I got the protocol working with a very simple hardware mod. I also have a Nava DIY clone of the TR-909 that I built myself and I think I may be able to repeat this hack there. I'll write about it if it works out. Thank you for reading!