I was looking for a way to test the frequency response of a new oscilloscope.
Analog Devices has a nice IC that can produce a digitally synthesized sine wave of frequency between 0 and about 70 MHz. AD9850 link is here.
The quickest way to throw together a prototype was using an MBED platform. My code is here
What made things even easier was the availability of ready-to-go evaluation boards from China on Ebay for less than $5. This is the one I used.
This design is limited to about 40MHz if you want a clean signal without aliasing.
Frequency and phase are set by a 40-bit command that has:
- 32-bit frequency setting
- 5-bit phase setting
- 1-bit power up/down
- 2-bits factory debug access
Output frequency is given by: fOUT = (frq × CLKIN)/(2^32)
where frq is the 32-bit frequency and CLKIN is the frequency of the on-board crystal (125MHz in this case) So, for example 0x147AE148 is 10MHz.
Frequency resolution has a step size of 29KHz with the 125MHz clock.
You can also change phase in increments of 180°, 90°, 45°, 22.5°, 11.25° or any combination thereof using the 5-bit phase command. However I didn’t implement this and left phase as zero.
I used a serial interface from the LPC1768 MBED to the AD9850 board as I didn’t want to be bothered with all the wiring of a parallel bus. The required timing looks like this:
This looks quite like an SPI interface. Much easier to use the LPC’s SPI block than to do bit-banging.
AD9850 wants low base clock state and clock falling edge data latching which adds up to SPI mode 0.
Only significant difference to SPI is the FQ_UD (frequency update) command. This looks quite like SPI’s chip select line except using positive logic. Can use a GPIO line to fake that.
The other hacks that are required are:
(1) MBED SPI limits the bits per packet to 16. Work around is to use 2 x 16-bit packets and then 1 x 8-bit packet. Another benefit of directly controlling the CS signal with a GPIO line is that CS can be kept low even between the 3 packets required to make up the 40-bits. Normally an SPI block would automatically take CS high again.
(2) Even though the LPC allows for setting LSB or MSB first, MBED only provides for MSB first whereas the AD9850 wants LSB first. Could work around that by writing a direct driver for the LPC. However I thought it was simpler just to write a function that swaps bit 31 with bit 0, bit 30 with bit 1 etc. High performance SPI isn’t needed so that is the simplest solution. There are bit swapping algorithms out there, however they are made for single bytes.
Connection of the boards is like this:
D2-D0 are hardwired 1,0,0 to force the AD9850 into serial mode. The AD9850 board is powered at 3V since this is the MBED GPIO voltage.
I used a Saleae Logic logic analyzer to watch the signals:
This shows the 3 packets that make up the 40-bit command. Luckily the AD9850 only specifies the minimum time between bits; there doesn’t seem to be a maximum as long as the next FQ_UD pulse does not arrive.
Code loops from 10MHz to 20MHz and back down again: