Teensy 4.1 and DAC high-speed demux

Anoat

Active member
Hello everyone.

I allow myself to consult you about one of my projects.

I have just made a monophonic analog synthesizer driven by midi. For this I use a teensy 4.1. The teensy itself drives 36 DACs and 26 Boolean outputs for the switches. Everything works wonderfully!

However, I now want to build a 6-channel polyphonic synthesizer, for this I have two solutions:
-The first is to make another monophonic card (simple to implement but expensive)
-The second solution is to demultiplex a DAC into 36x6 (216) analog outputs, and use 10 output expanders (MCP23S17) to get 26x6 (156) boolean outputs.

The second solution is certainly audacious but seems more interesting, from what I have been able to understand it would be necessary at the output of each of my multiplexers to sample and hold, so I would have to sample at least my output at a frequency of 44000Khz . In short, the DAC must work at a frequency of 10Mhz.

Can the Teensy work at this frequency? Knowing that it must also manage the 156 outputs of the MCP23S17 :confused:.
 
I was looking in to using a MUX in that way, It seems that some synthesizers use the MUX itself as the sample and hold switch, so you just need a capacitor and some times a voltage follower per channel. (depending on the input impedance of the circuit that CV is driving).

you don't need to run the synth controls at the full sample rate, except for modulation (say you had LFOs implemented in the teensy, and you wanted to modulate an analog signal with them. things that emulate "human speed knob turns" like analog ADSR controls can update at a lower rate. some synths just use 8 bits for them as well (but you can hear stepping on certain controls).
 
Update rate for LFOs and the like should be sufficient with 100-200Hz. Envelopes do not need to be faster than 1kHz, heres my favourite piece of information about the attack phase of envelopes:

Code:
Fro the unofficial Waldorf User FAQs:

faq.waldorfian.info


Q: Why do some synths produce clicks?

A: Chapter 1: The click in theory A click is produced when a very fast level change in the audio signal
occurs. You can easily check that on your home stereo when you play
back a CD and switch the Source Selector back and forth between CD
and a source that doesn't play anything.

The brightness of the click depends on the speed of the level change.
The faster the level changes, the brighter is the click. So, the
level change speed can be compared with the cutoff of a lowpass
filter. There is an easy formula for it:

Let's consider a level change from full to zero (or from zero to
full) output from one sample to another on a machine that uses
44.1kHz sample rate. So, we first transfer the sample to milli
seconds:

1 sample equals 1/44100 second, which is = 0.02267573696ms.

To calculate the cutoff frequency of the click, just use this formula:

Cutoff (Hz) = 1000 / Level Change Time (ms)

which in the example results in:

44100Hz = 1000 / 0.02267573696ms


Whoops? This the sampling frequency and, err, very bright.


Chapter 2: The click in the real world Now, how could this knowledge help you and what has it to do with
Waldorf synthesizers? Easy:

When you play a sine wave sound, only the base frequency (the
fundamental or the 1st harmonic) is present. That means, when you
play note A=110Hz, no other frequencies are involved except this
110Hz oscillation.

Now, what happens when you abruptly cut the sine wave to zero when it
just is at its maximum level? You get the same effect as with your
home stereo.
From one sample to the next, the waveform is brought from maximum to
zero, resulting in the forementioned bright click.

The same applies when the opposite happens. On Waldorf synthesizers,
you can setup the oscillators so that their phases start randomly
when a new note is played. So, you never know at which level the sine
wave is when you hit a note.
Consider it would be at the maximum level, you would get an immediate
change from zero to maximum when the amp envelope's attack rate is
set to 0.

BTW: the effect is the same, when you have a bright waveform but
filter it so that it is very hollow.

Chapter 3: In which situations does the click occur on my Waldorf synth? There are several situations when you can get a click and when you
know where they happen, you can try to prevent them:

* Amp Envelope Attack. On digital Waldorf synthesizers like the MWII
and the Q, the Attack rate can be as short as 1 sample. This means
that the amp volume of a note can change from zero to maximum in one
sample, or in ms: 0.02267573696ms. This results in a very bright
click.
On the Pulse, we chose a minimum attack rate of 1.9ms, resulting in a
click with a maximum cutoff of around 526Hz. When you own a Pulse,
you probably know of the 1.9ms number from the user's manual, because
that's the update speed of all CVs that are used in it.
So, when you hear a click on note start every now and then, just
increase the Amp Envelope Attack rate until you don't hear a click
anymore.

* Amp Envelope Release. Here, the same as with the Attack rate applies.
When you hear a click when you release a note, increase the Amp
Envelope's Release rate.
If the click still persists, you should also check the Release rate
of the Filter Envelope. Maybe the filter closes very fast, which can
result in a click, too.

* Voice Stealing. We know that this is the most annoying situation.
But, the click helps you: When you hear a click at a certain position
in your song, you know that a voice stealing happened and you can
easily shorten or delete notes in the editors of your sequencer.
When you count the notes and say that they don't exceed the maximum
number of voices of your synthesizer, just keep in mind that other
notes might still be in their release phases and therefore have to be
added, too.

* Mono mode. In Mono mode, a click might occur when any envelopes
(Amp or maybe Filter, too) are set to retrigger on new notes. When
the Attack rate of a sound is greater than 0, they are brought to
zero so that they can go up to their full level again. This rapid
change to zero results in a click.

* Unisono sounds. Here, a click might occur even heavier. Unisono
sounds easily exceed the maximum number of voices and because they
steal not only one but **several** notes at once, a click can be a
lot more present. It is louder and happens more often. You should
check several points on unisono sounds to lower clicks as much as
possible: are the envelope rates set to reasonable values, are the
oscillator phases set to free, is filter keytrack set to 0% (because
this can also be a rapid change) and so on.

Chapter 4: Why does my synth xy (insert product name here) produce no clicks Should I really answer that? Because it is slooooow.
Some japanese manufacturers (I don't say names here) prevent voice
stealing clicks by fading out voices slowly before they start new
notes. Hey, brillant idea, why doesn't Waldorf do that? Because it
ends up in a very bad MIDI timing (and those japanese synths are
**well-known** for that).
Furthermore, most of these synths are sample-based, which means that
their attack behaviour is stored in the sample that they should play.
So, a click on note start is also not possible because the sample
somehow gradually fades from zero to maximum.
If those synths allow you to change the sample start position, they
hopefully produce clicks, too (if not, they also have slow envelopes
which we don't hope).

A couple of days ago, someone mentioned the Matrix 12 producing no
clicks on retriggering envelopes. Yes, that's correct, because the
Matrix 12's minimum attack rate is around 20ms. Or in other words:
its envelopes are among the slowest you can find in a synthesizer.
The same applies to all synthesizers of the Matrix series, because
they all used Curtis chips that had an automatic smoothing filter to
prevent steppiness. The older Oberheim synths like the 4-Voice were
better here.
Also, the Waldorf Microwave and the Waldorf Wave used those Curtis
chips, but when the Attack rates of the envelopes were set to 0, this
smoothing filter was temporarily switched off, resulting in an abrupt
change. Attack 1 there is the same as minimum attack on a Matrix
synthesizer.

Chapter 5: Conclusion You know that we at Waldorf could prevent clicks by increasing the
minimum envelope rates or allowing bad MIDI timing. We could also
prevent that the filter resonance can destroy your hearing ability or
that you could play a C major chord. But who are we that we could
decide what **you** want from a synthesizer. Clicks can even be
musically useful and add a kind of randomness to a song that brings
it to live. A very good example is the bad, ugly, annoying, but
famous and beloved keyclick on Hammond organs.
Recently I bought the latest Art Of Noise album "the seduction of
Claude Debussy" produced by Trevor Horn and played by the creme de la
creme (even including Lol Creme of 10CC and Godley&Creme) of
musicians and I heard a lot of clicks during a couple of tracks. I am
even quite sure that they came from Waldorf synths but I don't know
if. You can easily imagine that I had a smile on my face.


I hope you now have even more fun with your "clicking" Waldorf synth.
 
old thread here .. the OP is likely well past this stage but for others I will add my experience. Having used the NXP i.MX RT1062 you can certainly demux many CV's from one or multiple DAC's. The ideal solution may be to have an 8ch DAC on each voice module. The RT1062 operates at 528MHz (some versions 600MHz), and hardware SPI works up to 50MHz (even though the manual says 35MHz max I have used SPI at 50MHz on multiple projects as have countless others - just make sure your layout is good). Your max CV refresh rate is then determined by the SPI baudrate and any other stuff your software needs to do. A few notes:

1. Each time you load data into the DAC(s) you will need to wait (delay) about 12us for the DAC's to settle. Then when you sample & hold each group of CV's you will need to delay about 3us to allow S&H cap to charge/discharge & settle (assuming the typical inexpensive analog switch IC's with mediocre on resistance (Ron) and proper S&H cap selection). When using an 8ch DAC and loading all 8ch and then sampling this takes approx. 24us per 8ch group. To update five groups (36 to 40 CV's) it takes right about 120us. So you can safely get >1kHz refresh rates assuming your operating systems isn't doing tones of other CPU intensive stuff, and likely 4kHz is possible. Also keep in mind you don't have to sequentially update all the CV's every time, you can come up with a custom sequence to update important CV's more frequently. It is very easy and very low CPU overhead to implement DDS LFO/ADSR using the CV timer interrupt (say it's 4kHz), it's just a matter of if it's fast enough for what you want.

2. Many 16-bit DAC's have 24bit command+data widths... which is incompatible w/ the RT1062 DMA bus widths (8/16/32 bits only), so it can be a real pain in the ass trying to get DMA working to off-load the CPU. This is because for hardware SPI (and most SPI DAC IC's) you need to toggle /CS at start and end of every data write and it can't be a 24 bits frame size w/ DMA. I believe we got it working by using 8bit frame size and using chaining/scatter multiple TDR's etc... but if I remember it was diminishing returns anyways. Carefully study the datasheet of the DAC's looking to use. Ideally you would want to use DMA is possible.

3. When sampling you will want to be careful of the sequence & timing. For this use case of the OP, say you can get each voice down to 32 CV's and use an 8ch DAC with four 4052 analog switches (each as two 1:4 demuxes). The sequence would be
a) Load the DAC (generally you can just load the DAC outputs asynchronously and eliminate the need for the LDAC pin).
b) set the demux output.
c) Wait ~12us for the DAC outputs to settle... it's the last DAC output ch8 that you want to keep your eye on if you are latching the data to the DAC outputs automatically and asyncronously.
d) toggle the demux enable pins for ~3us to sample the DAC outputs.
e) go to next group...

4. I think the OP was planning to use the DAC for the control data. That would be a waste. There's tons of pins on the Teensy 4.1. Setup a little 6bit wide bus and use hex latches for the control data, or just use a shift register to load a bunch of latches sequentially from one pin. You don't have to refresh the latch data as it...well.. latches :) until you update it.

Incidentally, the Waldorf response above is partly true. However, having the attack or release phase of an ADSR be 1 sample on/off is very non-ideal. There are no rules, but ideally you want say 10 samples minimum for these for at least a pseudo-exponential shape w/ minimal clicking. So for the old Waldorf stuff it would have been better to have the CV's refresh at 5kHz not 526Hz as they are.. then you have the ability for a proper
attack/release curves. Obviously with the limited resources and speeds of the time something has to give, and instead of having ideal attack/release shapes at slower minimum times of say 20ms, they allowed interpolated shapes down to 1 sample simply on/off. The blanket statement made was disingenuous in this regards.
 
Last edited:
2. Many 16-bit DAC's have 24bit command+data widths... which is incompatible w/ the RT1062 DMA bus widths (8/16/32 bits only), so it can be a real pain in the ass trying to get DMA working to off-load the CPU. This is because for hardware SPI (and most SPI DAC IC's) you need to toggle /CS at start and end of every data write and it can't be a 24 bits frame size w/ DMA.

The SPI hardware can indeed do 24 bit frame size. Of course you have to use direct access to the hardware registers, since this isn't supported by the SPI library which aims for Arduino compatibility.

Frame size is controlled by the FRAMESZ field in the TCR register. It's documented on page 2857 and pages 2885-2888 in the reference manual.

For an example using 24 bit frame size, check out the Phazerville firmware for Ornament and Crime modules using DAC8565. That firmware supports lots of hardware, but this case is the old O_C modules originally designed for Teensy 3.2 using a 4 channel DAC8565 chip but they have been updated by replacing Teensy 3.2 with Teensy 4.0 (which gives enough memory for all features in 1 firmware image, unlike Teensy 3.2 which has much less memory). The configuration for 24 bit frame size can be found in OC_DAC.cpp on line 339. To understand that code, the basic idea is it runs from a timer interrupt. Those 4 functions for each channel are called only from the Update function in OC_DAC.h, so even though it's written as 4 functions due to the firmware's long history, read as if those 4 are just 1 large function which transmits all 4 channels.

Because the SPI hardware has FIFO large enough to hold all 4 outgoing messages, no DMA is needed. It just writes everything into the FIFO with the assumption the hardware will fully perform all the transfers including all CS pin stuff before the timer interrupt runs again. The first of the 4 functions configures the frame size and the last puts the complete flag into the FIFO, so some minor details besides just writing 4 channels the same way. But then the hardware just does all the work, without needing DMA. The big FIFO and hardware support for 24 bit frame size makes this really simple. :)

However, one not-so-simple detail to keep in mind while reading that code is that old hardware had a OLED display on the same SPI bus as the 4 channel DAC chip. So some of the stuff you'll see it doing is meant to interleave the DAC with display updates, which is done in 8 segments. If you're building a new system like the newer O_C T4.1 hardware, you probably wouldn't choose to share the same SPI port. Remember, it's old hardware designed originally for Teensy 3.2 which had a single SPI port. Still, this is probably one of the best known-good examples of 24 bit SPI frame size. It definitely does work because a large number of those old Ornament and Crime Eurorack modules where made, and many are in active use today with Teensy 4.0 rather than Teensy 3.2.
 
Last edited:
^ this is great info for me and I'm sure other in the future. Thanks! This is also basically what we did. We didn't actually use the Arduino library or higher level NXP HAL, we ended up just using the direct/lower level LPSPI_WriteData function in fsl_lpspi.c of the NXP SDK. This is less helpful for those using Arduino so the above is great info. We did also get DMA working but as mentioned above it's not much CPU overhead to send 3 bytes or even a chain of 8 channels (24 bytes), and you need constant CPU intervention anyways to update the DAC so DMA is less useful here w/ such small streams of data.
 
Last edited:
Back
Top