Function generator code modified to work on the Freescale KL25Z

Dependencies:   mbed

Fork of AD9850 function generator SPI driver by Liam G

This is an update to the original AD9850 SPI driver produced by Liam Goudge.

The main changes are to assign the appropriate pins and to send the 40-bit AD9850 programming word as five 8-bit packets. This is necessary because the KL25Z only supports 8-bit SPI transfers.

Committer:
ptamike
Date:
Wed Oct 23 23:17:55 2013 +0000
Revision:
2:e9d2346ea1bb
Parent:
1:b0e6c82af2ef
Child:
3:a643b6a454aa
Liam's original code modified to work with the Freescale KL25Z

Who changed what in which revision?

UserRevisionLine numberNew contents of line
liamg 0:b5fb7b3adfe2 1 // MBED driver for AD9850 digital synthesizer using hacked SPI interface
ptamike 2:e9d2346ea1bb 2 // Original code by Liam Goudge Sept 2013
ptamike 2:e9d2346ea1bb 3 // Modified for KL25Z by Mike Richards Oct 2013
liamg 0:b5fb7b3adfe2 4
liamg 0:b5fb7b3adfe2 5 #include "mbed.h"
liamg 0:b5fb7b3adfe2 6
ptamike 2:e9d2346ea1bb 7
ptamike 2:e9d2346ea1bb 8 SPI device (PTD2, PTD3, PTD1); // Set the KL25Z SPI pins
ptamike 2:e9d2346ea1bb 9 DigitalOut CS(PTD0); // Use pin P0_17 as a fake Chip select
ptamike 2:e9d2346ea1bb 10 DigitalOut ADReset(PTA13); // Use Pin P0_7 as the reset line for AD9850
ptamike 2:e9d2346ea1bb 11
liamg 0:b5fb7b3adfe2 12
liamg 0:b5fb7b3adfe2 13 Serial pc(USBTX, USBRX); // tx, rx for debug terminal
liamg 0:b5fb7b3adfe2 14
liamg 0:b5fb7b3adfe2 15 int reverseBits (int source)
liamg 0:b5fb7b3adfe2 16 {
liamg 0:b5fb7b3adfe2 17 // Unfortunately need to invert bit order of the desired frequency setting since MBED only allows for MSB first from SPI. We need LSB first for AD9850
liamg 0:b5fb7b3adfe2 18 int mask=0;;
liamg 0:b5fb7b3adfe2 19 int i=0;
liamg 0:b5fb7b3adfe2 20 int target=0;
liamg 0:b5fb7b3adfe2 21 int bitTarget=0x80000000; // Hard-wired for 32-bit inversion
liamg 0:b5fb7b3adfe2 22
liamg 0:b5fb7b3adfe2 23 for (i=0;i<32;i++) { // ditto
liamg 0:b5fb7b3adfe2 24 mask=1<<i;
liamg 0:b5fb7b3adfe2 25 bitTarget=1<<(31-i); // ditto
liamg 0:b5fb7b3adfe2 26
liamg 0:b5fb7b3adfe2 27 if (source & mask)
liamg 0:b5fb7b3adfe2 28 target=target | bitTarget;
liamg 0:b5fb7b3adfe2 29 }
liamg 0:b5fb7b3adfe2 30 return target;
liamg 0:b5fb7b3adfe2 31 }
liamg 0:b5fb7b3adfe2 32
liamg 0:b5fb7b3adfe2 33 void writeSPI(int frq, int phase)
liamg 0:b5fb7b3adfe2 34 {
ptamike 2:e9d2346ea1bb 35 // Send the 40-bit packet. NB: KL25Z only supports 8-bit SPI so send five 8-bit packets
ptamike 2:e9d2346ea1bb 36
ptamike 2:e9d2346ea1bb 37 device.format(8,0); // 8-bits per packet, mode 0 (CPOL=0 CPHA=0)
liamg 0:b5fb7b3adfe2 38 device.frequency(1000000); //SPI clock set to 1MHz
liamg 0:b5fb7b3adfe2 39
ptamike 2:e9d2346ea1bb 40 wait_ms(1);
liamg 0:b5fb7b3adfe2 41
liamg 0:b5fb7b3adfe2 42 // First do chip select. Need to use a GPIO to fake the chip select since MBED doesn't allow to set positive logic CS signal
liamg 0:b5fb7b3adfe2 43 CS=1; // assert chip select (a.k.a FQ_UD frequency update input to AD9850)
ptamike 2:e9d2346ea1bb 44 wait_ms(1);
liamg 0:b5fb7b3adfe2 45 CS=0;
liamg 0:b5fb7b3adfe2 46
ptamike 2:e9d2346ea1bb 47 device.write(frq>>24); // Write upper 8-bits
ptamike 2:e9d2346ea1bb 48 device.write(frq>>16);
ptamike 2:e9d2346ea1bb 49 device.write(frq>>8);
ptamike 2:e9d2346ea1bb 50 device.write(frq); // Now the last 8 bits
liamg 0:b5fb7b3adfe2 51 device.write(phase); // This is phase and factory settings byte
liamg 0:b5fb7b3adfe2 52
ptamike 2:e9d2346ea1bb 53 // Now pulse FQ_UD again to load the word into the DDS
liamg 0:b5fb7b3adfe2 54 CS=0;
ptamike 2:e9d2346ea1bb 55 wait_ms(1);
liamg 0:b5fb7b3adfe2 56 CS=1;
ptamike 2:e9d2346ea1bb 57 wait_ms(1);
liamg 0:b5fb7b3adfe2 58 CS=0;
liamg 0:b5fb7b3adfe2 59 }
liamg 0:b5fb7b3adfe2 60
liamg 0:b5fb7b3adfe2 61
liamg 0:b5fb7b3adfe2 62 int main()
liamg 0:b5fb7b3adfe2 63 {
ptamike 2:e9d2346ea1bb 64 // This routine produces a continuous frequency sweep
ptamike 2:e9d2346ea1bb 65 int targetFrq=0x147AE148; // Frequency word = ([Desired freq in MHz] * 34.3597384)
ptamike 2:e9d2346ea1bb 66 int increment=0xD6B; //100Hz step
ptamike 2:e9d2346ea1bb 67
liamg 0:b5fb7b3adfe2 68 // Reset the AD9850. Active high logic. Minimum reset period 5 clock cycles (5/125MHz)
liamg 0:b5fb7b3adfe2 69 ADReset=0;
liamg 0:b5fb7b3adfe2 70 wait_ms(5);
liamg 0:b5fb7b3adfe2 71 ADReset=1;
liamg 0:b5fb7b3adfe2 72 wait_ms(5);
liamg 0:b5fb7b3adfe2 73 ADReset=0;
liamg 0:b5fb7b3adfe2 74
liamg 0:b5fb7b3adfe2 75 while(1)
liamg 0:b5fb7b3adfe2 76 {
liamg 0:b5fb7b3adfe2 77
ptamike 2:e9d2346ea1bb 78
ptamike 2:e9d2346ea1bb 79
ptamike 2:e9d2346ea1bb 80 while (targetFrq<0x148bFFFF) // up to 10.001MHz
liamg 0:b5fb7b3adfe2 81 {
liamg 1:b0e6c82af2ef 82 writeSPI(reverseBits(targetFrq),0); // Don't use phase so set to zero.
liamg 0:b5fb7b3adfe2 83 targetFrq=targetFrq+increment;
ptamike 2:e9d2346ea1bb 84 //wait_ms(200);
liamg 0:b5fb7b3adfe2 85 }
liamg 0:b5fb7b3adfe2 86
liamg 1:b0e6c82af2ef 87 while (targetFrq>0x147AE148) // down to 10MHz
liamg 0:b5fb7b3adfe2 88 {
liamg 0:b5fb7b3adfe2 89 writeSPI(reverseBits(targetFrq),0);
liamg 0:b5fb7b3adfe2 90 targetFrq=targetFrq-increment;
ptamike 2:e9d2346ea1bb 91 //wait_ms(200);
liamg 0:b5fb7b3adfe2 92 }
liamg 0:b5fb7b3adfe2 93
liamg 0:b5fb7b3adfe2 94 }
liamg 0:b5fb7b3adfe2 95
liamg 0:b5fb7b3adfe2 96
liamg 0:b5fb7b3adfe2 97 }