10 years, 8 months ago.

Which is fastest ? an SPI DAC or a Parallel DAC with PortOut ?

Hi, I need to interface a DAC to my mBed and I want to do it the "fastest" way ... I'm trying to evaluate which will be quicker (least clock cycles per write) SPI or parallel ...

Assuming a 12 bit DAC, that's 16+ clock cycles to send the 12 bits of data over SPI (2 x 8bit words, plus overhead). The SPI bus will run at less than the clock frequency. Probably 1/2 or 1/4 speed. So, the time it takes to write the value to a 12bit DAC will be at least 50-100 clock cycles ?

The alternative is to use a parallel DAC, in ideal conditions this will write a 12 bit value out to a parallel port in only a few clock cycles, but looking at the data sheet, I'm not sure there is a contiguous 12 bit port I can use or how efficient the PortOut function is ?

So, questions :

Is the SPI bus and API on mBed an asynchronous hardware SPI bus, i.e. when I ask the API to send data via the SPI, does the API returns immediately and my code can continues to do something else, while the SPI bus clocks out the data serially and asynchronously ? I don't have to wait in the code for the SPI bus to clock out all the data before it returns ?

To write the data in parallel quickly, I can use PortOut ? But looking at the pin out on the LPC1768 it's difficult to see 12 contiguous pins ? am I misunderstanding something. The other issue is the other useful ports I need like SPI and UART as in the middle of the contiguous pins I would need to use ?

I'm guessing PortOut is pretty quick ? A few clock cycles ? Is there a metric ? how much quicker or slower is it that SPI ?

The other more flexible way is to use BusOut, which means my 12 bit DAC could be connected to any 12 pins, not necessarily contiguous, but I'm guessing BusOut is less efficient ? Again are there any metrics for this ? would writing to my 12 bit parallel DAC using BusOut be more of less clock cycles than write to a 12 bit SPI DAC ?

Any useful advice warmly welcomed.

Some context on the project ... I've built a laser projector, and the DACs control two 40 KPPS X & Y galvanometers. In addition there are 8 bit values for each of the R, G & B lasers. So, that's 2 x 12 bit DACs and 3 x 8 bit DACs, all updating continuously. I am currently prototyping with an MCP4922 SPI DAC (dual output) and an AD5348 Parallel DAC (octal output).

I need as many clock cycles as I can, as I'm running a Bresenham line algorithm, plus trigonometry (cos & sin) to rotate the vector images, etc. So, I'm looking for the most efficient way of writing to the DACs, so I leave as much CPU power as I can for the maths and trig functions.

The current prototype is up and running on an Arduino. I have the parallel and SPI DAC both running, but I just don't have the power in the Arduino to run the Bresenham line algorithm and the trigonometry. I'm getting less than 1000 points per second, nowhere near the 40 KPPS the galvos can handle... so I'm porting the project to mBed ...

Thanks in advance ...

Regards,

Jon.

2 Answers

10 years, 8 months ago.

For portout you can look at this topic: http://mbed.org/users/igorsk/notebook/fast-gpio-with-c-templates/. Note it is old, I believe currently the mbed library comes closer to the library mentioned there, but it gives a reasonable indications.

But as you noticed, getting 8 pins in a row is already hard enough, 12 is not possible I think on the LPC1768 mbed. BusOut is definately not suitable for this, it just calls DigitalOut in a row. Nice for writing to 4 leds you want to address in a binary version, but not high speed IO.

So SPI it is. The mbed SPI library waits until SPI writing is done, simply because it also reads what comes back. You can get clock speed up to 48MHz, but at least your first DAC does not support that. And then you also really have to watch your wiring. To reduce overhead you can use this library: http://mbed.org/users/Sissors/code/BurstSPI/docs/7d9b64d67b22/classBurstSPI.html. It was designed for SPI TFT screens, but the idea is simply it waits until there is space in SPI FIFO buffer, puts in data, returns. It won't wait until there is a response.

Two things: setFormat is only required if another library used the same SPI hardware. It takes (relatively) an enormous amount of time to do, which is irrelevant when writing a complete TFT screen, but will be very relevant for you: Do not use it unless another library used the same SPI hardware with different settings.

Second thing: clearRX, receives all data left in the FIFO buffer and throws it away. For this it needs to wait until the SPI operations are finished. This is only required if you want to receive data. If you don't there is no need to call this function.

Accepted Answer
10 years, 8 months ago.

If you use DMA you can speed up the SPI connection to the maximum, but you will get problems to address different chips. There is no methode to specyfy different cs signals. If you find a single multi channel DAC which can be feed by spi, you will be able to use DMA. I use SPI DMA in my TFT library, but you have to code it for a specific plattform.

BurstSPI lib is just as fast as DMA operation. In general for fast SPI I agree DMA is advantageous, because if you want you can be doing other stuff at the same time. But for 2 bytes I wonder if the overhead due to setting up DMA isn't at least as big as just sending two bytes to the SPI FIFO.

posted by Erik - 04 Sep 2013