Tuesday, May 12, 2015


Some while ago, I wrote about experiments with driving a MCP4921 DAC from an Arduino. The idea was to make an arbitrary signal generator. I was able to get square waves up to about 20kHz, limited by how fast the Arduino could send sample values to it. To generate anything other than square waves, you probably need at least 50 samples per cycle, so this would limit arbitrary waveforms to 400Hz. Note that this DAC takes serial input, with two bytes per sample. So in principle, a parallel DAC might get you about 16 times this, that is 6.4kHz.

The XMOS is much faster than the Arduino. It has a clever hardware trick which allows you to control the exact timing of when values appear on its output ports. So if you can get a good frequency from it, you could also have high precision on the timing. The MCP4921 can be set to buffer the new samples and only apply them on toggling a pin called -LDAC. So you could connect this to a port of the XMOS and use it to control precisely when the samples take effect. I didn't actually do this, it's just something to note.

So how fast can you drive the DAC from XMOS? The first thing I did was to see what the maximum rate I could get on an output port is. I wrote a very simple program which just toggles a port between zero and one and loops round. This gives 14MHz.

The DAC uses the SPI interface, and XMOS provides a library for controlling it. There are synchronous and asynchronous flavors. Note that although we are only writing to the DAC (using the MOSI), you do also have to read from it (MISO). However, the SPI protocol is supposed to do both simultaneously, so I don't think this affects the speed. For the synchronous version, I got 25kHz, and for the asynchronous one 33KHz. These figures are quite disappointing, and suggest that the library has quite a lot of overhead. I found another SPI library on Github, and this got me to 128kHz. Note that at this frequency, we are well beyond the settling time of the DAC, and so even toggling the DAC value between it minimum and maximum of 4095, the output looks triangular. For the MCP4921, the settling time is 4.5us, which is close to the half-wave period at 128kHz. Note that this means we are sending bits over the serial line at 2MHz - a long way off the tight loop value of 14MHz, but in a believable range.

Here's a summary of the numbers, with estimates of the frequency at 50 samples per cycle, and for a parallel DAC, calculated as above.

Platform Max freq Max @ 50 samples Parallel @ 50 samples
Arduino 20 kHz 400 Hz 6400 kHz
XMOS sync 25 kHz 500 Hz 8000 Hz
XMOS async 33 kHz 660 Hz 10560 Hz
XMOS Github library 128 kHz 2560 Hz 40960 Hz

No comments: