Fast ADC using PRU to bitbang SPI

Hi guys,

I would like to know if someone here has already tried bitbanging SPI with the PRU units?

I have a 12bit ADC (TI ADS7883) which takes a clock signal and outputs 12 bits of data, and I would like to use the PRU to achieve high sampling rate.

See http://www.ti.com/lit/ds/symlink/ads7883.pdf for the ADC documentation with the interface timing diagram.

Basically, the PRU program would do the following (assuming a cycle time of 5ns and one cycle for each line of the loop):

  • Initiate 3 GPIO channels (2 outputs: SCLK and CS, 1 input: SDO)

  • Allocate memory (a lot! I’d like to capture millions of samples)
    Loop for N samples:

  • Pull CS high

  • Wait 3 cycles

  • Pull SCLK high

  • Wait 2 cycles

  • Pull CS low (initiate output)

  • Wait 2 cycles

  • Pull SCLK low

  • Wait 5 cycles

  • Pull SCLK high

  • Wait 5 cycles

  • Pull SCLK low

  • Wait 5 cycles

  • Pull SCLK high

  • Wait 5 cycles

  • Pull SCLK low

  • Read SDO (first bit)

  • Store it somewhere

  • Wait 3 cycles

  • Pull SCLK high

  • Wait 5 cycles

  • Pull SCLK low

  • Read SDO (2nd bit)

  • Store it somewhere

  • Wait 3 cycles

  • Pull SCLK high

  • Wait 5 cycles

  • Pull SCLK low

  • Read SDO (3rd bit)

  • Store it somewhere … and so on until 12th bit

  • Wait 60ns (acquisition time) while always pulling CLK high and low every 6 cycles
    End of loop

The problem is that I have never programmed in assembly code. I have tried looking at examples but have a really hard time understanding the simplest commands (ex: what is a simple MOV r3, 1<<7 doing?).

I’d like to have a thoroughly commented, simple example to start if possible.

Memory issues are also a big problem. How can I store all the captured data so that it is fast and doesn’t overflow the PRU memory?

Many thanks for your help!

Touste

Why don’t you use SPI with DMA? DMA is automatically used when the size of transfer exceeds 160 bytes. You would have to create a kernel driver because SPIDEV has too much overhead. The SPI interface can transfer up to 48MHz clock, which is the max clock of the device you want to use.

Regards,
John

Hi John, thanks for your suggestion. What frequency can I expect using this method? I need at least a 1MSPS sampling rate.
Also, do you have any code example of this? I tried googling it but I didn’t find what I was looking for.

Many thanks

Hi John, thanks for your suggestion. What frequency can I expect using this method? I need at least a 1MSPS sampling rate.
Also, do you have any code example of this? I tried googling it but I didn’t find what I was looking for.

Theoretically you should be able to run at 3MSPS. Regarding sample code, look at Linux Kernel source under drivers/staging/iio. Look for any driver that uses SPI. What you need to do is setup SPI transfer in large blocks so that DMA will be used. I also recommend that you post your question of e2e.ti.com as TI might have some example code that will help.

Alternatively, you could always use a I2S ADC and then use the MCASP to stream the samples. It is also possible to convert the SPI signal format to I2S so that you can use the ADS7883 with MCASP. What you do is write a SPDIF style codec and then use the ALSA (Linux Audio) framework to capture your samples. Here is an example of doing this for a DAC, but just do a capture version for ADC.

http://processors.wiki.ti.com/index.php/Sitara_Linux_SDK_Audio_DAC_Example

Regards,
John