Saturday, 8 March 2014

Arduino Due and the DDS

The SDR receiver is now running completely on the Arduino DUE...

Previously, I had only the DSP functions on the Due, whilst the VFO and user interface were managed on an Arduino Mega. Now, all these support functions have migrated to the Due.

When I say "migrated", I did have to give them a push - and the most interesting part of that push was the work required to move the DDS. So this post describes controlling an AD9850 DDS module from the Due.

The first point of resistance to be overcome in moving the DDS to its new Due host concerns the operating voltage. Most Arduinos run with 5V supply and logic - but the Due operates at 3.3 Volts. Fortunately, this isn't as hard to deal with as it sounds.

The DDS module will run on 3V3 - indeed it may prefer to run at 3V3 - indeed some samples of the module may ONLY safely run at 3V3 (because of the oscillator module). So switching to 3V3 operation is a blessing rather than a curse.

The next issue is the clock divider chain, required to derive the quadrature VFO square wave signals for the Tayloe mixer from the original clock (at four times the frequency of the VFO). Again, this turns out to be a walk in the park, as the 74AC74 flip flops I used run happily on 3V3.

With all the physical issues like voltage out of the way, the next thing to do was to look at the code. Here again, things turned out to be easy - in fact an opportunity presented itself which works out very much to our advantage...

Let's remind ourselves of the interface between the DDS module and its controller...

The DDS module has four control lines. Of these, two form a conventional serial interface (with a clock and data line). Their functionality can be replaced by the set of 8 parallel data lines - but we're not using these. The other two of the four lines mentioned are what we might call "chip control" lines; a reset and a latching input. Notice here that there is no overall "Chip select" line.

My original experiments with the DDS module were conducted last year in the context of Raspberry Pi. I copied Ron, nr8o's original code...

Ron achieves the required pulse on the FQ_UD line using his function 'pulseHigh()' and manages the serial data exchange by "bit-banging" in C in his 'tfr-byte()' function...

When I came to use the DDS module in my Arduino projects, I replaced the 'tfr_byte()' function with the Arduino equivalent...

There was nothing clever about this (in fact, I'm confident it will be slower than Ron's approach). However, I wanted to keep the code as simple and readable and Arduino as possible to ensure widest access for all including, dear reader, you!

The Arduino reference describes the shiftOut() function as "soft SPI". SPI is an abbreviation of Serial Peripheral Interface, a loosely-defined standard for interconnections between digital devices. In addition to the soft implementation, Arduino also supports hardware SPI which, in the case of the Due, offers some enhanced functionality. It also has the attraction of speed.

Remember that in the present application, the Arduino Due is working its socks off to sustain the DSP task central to software defined radio. I can't afford to have the processor spend time on mundane tasks like controlling the DDS - so I decided to investigate the benefits of interface to the DDS module using hardware SPI.

Here's how my sendFrequency() function looks with the SPI interface...

Not significantly different from before; the shiftOut() function is now replaced by the SPI.transfer() call. Notice that I still manage the FQ_UD line using the same techniques as before - this is not a part of the SPI protocol, as neither is the RESET line.

To set up for the hard SPI interface in software requires only a little work ...

whilst the hardware setup is simpler yet; the DATA line on the DDS module is connected to MOSI (Master Out Slave In), and the W_CLOCK line on the DDS module is connected to SCK. MOSI and SCK are found on the ICSP header of the Due.

So - was it worth it?

The "soft SPI" interface between Due and the DDS took 250 microseconds for one frequency change operation. The new "hard SPI" interface achieves the same result in 9 microseconds. Not a bad saving for no cost (other than writing a few lines of code and plugging two wires into different sockets)! In fact, the "traditional" management of the pulse on the FQ_UD line is now probably limiting the speed of the hard SPI transfer - but more on that later.

Whilst the most interesting part of pushing the functionality over to the Due surrounded the DDS, porting the user interface formed by display and tuning was more of a chore - and still requires more work...

The Due has more IO pins than anyone brought up on an Arduino Due (or an RPi) could ever wish for - so I abandoned the I2C interface used previously for the display and reverted to the conventional (nibble-wide) parallel "Hitachi" interface. This is represented in Arduino by the standard 'LiquidCrystal' library and in hardware - in the present instance - by one of the little 2*16 units I picked up in Shenzhen...

The display looks great in real life - but the flash hasn't done it any favours in the photo above. Notice that I've used the same interface board developed for the original Arduino VFO, as this carries the required rotary encoder to tune the system. This is the place I need to do some work - the software supporting the rotary encoder isn't working nearly as sweetly as I'd like on the Due. I'm sure the fix will be easy but tedious!

The entire system now looks like this...

What you see (compared to last time) is a missing Arduino Mega at stage right. What you see instead in the foreground is an early prototype of the Kanga/m0xpd DDS shield (seen "upside down").

The shield is being run on 3.3 Volts (from the Due) and the DDS module (hiding from the camera on the other side of the shield) is receiving its control signals down the colourful ribbon cable. The Tayloe mixer (realised on a 74BCT3253) is still running with a 5V supply, but is happily accepting the 3V3 quadrature clocks from the DDS shield.

Everything is working as intended - apart from the clunky rotary encoder response, which I'll sort out today.

I've put together a new library to make it easy for you to run a DDS module via hard SPI - I'll be publishing that shortly - watch this space!

...-.- de m0xpd


  1. Very nice work. I hope you will make the code available. Thanks!

  2. You are ahead of me, in both thinking and action! Well done. My dream is to have a series of Arduino shields, SDR RX, SDR TX/PA, Auto ATU. Multi-band if possible, if not 20m & 40m versions. Look forward to more from your side. 73 M6KWH

  3. Hi friends,

    i am moni from delhi The display looks great in real life - but the flash hasn't done it any favours in the photo above. and very good work and lomg days work,

    Thank you,

  4. This is great and super-helpful. A couple of questions:
    1. Have you tested the speed on the 'bit-banging' version on a Uno?
    2. Does parallel data input increase speed? It seems from the spec sheet that you can enter 5 words at a time, do you think this would lead to a speed gain? Or a pause after 5 words while the next are loaded?
    My application is to run 3 words into the AD9850 and then cycle them quickly so if parallel is better that would be good to know.