Programming of the DDS-60 (AD9851) frequency synthesizer from AmQRP http://midnightdesignsolutions.com/dds60/index.html I had to use long, floating math in order to get accurate frequency output.

Dependencies:   TextLCD mbed ChaNFS

Committer:
loopsva
Date:
Wed Apr 04 18:14:54 2012 +0000
Revision:
0:1ed24aaf786d
050511

Who changed what in which revision?

UserRevisionLine numberNew contents of line
loopsva 0:1ed24aaf786d 1 #include "mbed.h"
loopsva 0:1ed24aaf786d 2 #include "AD9851.h"
loopsva 0:1ed24aaf786d 3
loopsva 0:1ed24aaf786d 4 extern int gDebug; // defined in main.cpp, used for printing verbose-ness level (0-3)
loopsva 0:1ed24aaf786d 5 //extern double StepFreq; // step frequency (used for gDebug lines only)
loopsva 0:1ed24aaf786d 6
loopsva 0:1ed24aaf786d 7 // power up default values
loopsva 0:1ed24aaf786d 8 double BaseFreq = 10000000.000; // base frequency - if frequency
loopsva 0:1ed24aaf786d 9 double IfFreq = 455000.0; // IF frequency
loopsva 0:1ed24aaf786d 10 double RealFreq = BaseFreq + IfFreq; // sum of the two frequencies
loopsva 0:1ed24aaf786d 11 double RefOsc = 30000000.000; // reference oscillator frequency
loopsva 0:1ed24aaf786d 12 char MultSix = 'A'; // x1 or x6 frequency oscillator - 0, 1 or A only
loopsva 0:1ed24aaf786d 13 bool ErrorFlag = false; // error flag
loopsva 0:1ed24aaf786d 14 bool FirstEnable = false; // used for DDS-60 bug fix
loopsva 0:1ed24aaf786d 15
loopsva 0:1ed24aaf786d 16 double OldBaseFreq = BaseFreq; // old base frequency - if frequency
loopsva 0:1ed24aaf786d 17 double OldIfFreq = IfFreq; // old IF frequency
loopsva 0:1ed24aaf786d 18 char OldMultSix = MultSix; // old x1 or x6 frequency oscillator - 0, 1 or A only
loopsva 0:1ed24aaf786d 19
loopsva 0:1ed24aaf786d 20 double SerCount = 1431655765.0; // calculated final value of data to AD9851
loopsva 0:1ed24aaf786d 21 unsigned int FreqDiv = 0x55555555; // calculated value of SerCount to be divided into SerData[0-4]
loopsva 0:1ed24aaf786d 22
loopsva 0:1ed24aaf786d 23 const char LsbPhase = 0x08; // LSB of phase setting, 0-31 (0-0x1f), 11.25 degrees per step
loopsva 0:1ed24aaf786d 24 const char PwrDnFlag = 0x04; // + power down flag
loopsva 0:1ed24aaf786d 25 const char Mult6Flag = 0x01; // + 180MHz - 30MHz multiplier x6 flag
loopsva 0:1ed24aaf786d 26 char FortyBitWd = PwrDnFlag + (LsbPhase * 1); // calculated 5th byte fo 40 bit word to be divided into SerData[0-4]
loopsva 0:1ed24aaf786d 27
loopsva 0:1ed24aaf786d 28 // constructor takes paramters and initializes I2C bus
loopsva 0:1ed24aaf786d 29 AD9851::AD9851(PinName CLK, PinName SDO, PinName LEN)
loopsva 0:1ed24aaf786d 30 : _clk(CLK)
loopsva 0:1ed24aaf786d 31 , _sdo(SDO)
loopsva 0:1ed24aaf786d 32 , _len(LEN)
loopsva 0:1ed24aaf786d 33 {
loopsva 0:1ed24aaf786d 34 _clk = 0;
loopsva 0:1ed24aaf786d 35 _sdo = 0;
loopsva 0:1ed24aaf786d 36 _len = 0;
loopsva 0:1ed24aaf786d 37 OutNewValue(); // initialize the AD9851
loopsva 0:1ed24aaf786d 38 }
loopsva 0:1ed24aaf786d 39
loopsva 0:1ed24aaf786d 40 // destructor
loopsva 0:1ed24aaf786d 41 AD9851::~AD9851() {
loopsva 0:1ed24aaf786d 42 }
loopsva 0:1ed24aaf786d 43
loopsva 0:1ed24aaf786d 44 // return base frequency value
loopsva 0:1ed24aaf786d 45 double AD9851::GetBaseValue() {
loopsva 0:1ed24aaf786d 46 return BaseFreq;
loopsva 0:1ed24aaf786d 47 }
loopsva 0:1ed24aaf786d 48
loopsva 0:1ed24aaf786d 49 // return IF frequency value
loopsva 0:1ed24aaf786d 50 double AD9851::GetIfValue() {
loopsva 0:1ed24aaf786d 51 return IfFreq;
loopsva 0:1ed24aaf786d 52 }
loopsva 0:1ed24aaf786d 53
loopsva 0:1ed24aaf786d 54 // return 32 serial word value
loopsva 0:1ed24aaf786d 55 unsigned int AD9851::GetFD32Value() {
loopsva 0:1ed24aaf786d 56 return FreqDiv;
loopsva 0:1ed24aaf786d 57 }
loopsva 0:1ed24aaf786d 58
loopsva 0:1ed24aaf786d 59 // return 5th "control" byte for 40 bit serial word value
loopsva 0:1ed24aaf786d 60 char AD9851::GetFortyValue() {
loopsva 0:1ed24aaf786d 61 return FortyBitWd;
loopsva 0:1ed24aaf786d 62 }
loopsva 0:1ed24aaf786d 63
loopsva 0:1ed24aaf786d 64 // return error flag
loopsva 0:1ed24aaf786d 65 bool AD9851::GetErrFlagValue() {
loopsva 0:1ed24aaf786d 66 return ErrorFlag;
loopsva 0:1ed24aaf786d 67 }
loopsva 0:1ed24aaf786d 68
loopsva 0:1ed24aaf786d 69 //---------------------------------------------------------------
loopsva 0:1ed24aaf786d 70 // set base frequency value
loopsva 0:1ed24aaf786d 71 double AD9851::SetBaseValue(double bv) {
loopsva 0:1ed24aaf786d 72 if(bv >= 0.0) {
loopsva 0:1ed24aaf786d 73 BaseFreq = bv;
loopsva 0:1ed24aaf786d 74 } else {
loopsva 0:1ed24aaf786d 75 printf("Base neg number!!!\n");
loopsva 0:1ed24aaf786d 76 }
loopsva 0:1ed24aaf786d 77 return(bv);
loopsva 0:1ed24aaf786d 78 }
loopsva 0:1ed24aaf786d 79
loopsva 0:1ed24aaf786d 80 // set IF frequency value
loopsva 0:1ed24aaf786d 81 double AD9851::SetIfValue(double bv) {
loopsva 0:1ed24aaf786d 82 if(bv >= 0.0) {
loopsva 0:1ed24aaf786d 83 IfFreq = bv;
loopsva 0:1ed24aaf786d 84 } else {
loopsva 0:1ed24aaf786d 85 printf("IF neg number!!!\n");
loopsva 0:1ed24aaf786d 86 }
loopsva 0:1ed24aaf786d 87 return(bv);
loopsva 0:1ed24aaf786d 88 }
loopsva 0:1ed24aaf786d 89
loopsva 0:1ed24aaf786d 90 // set base frequency value, ascii 0 1 or A
loopsva 0:1ed24aaf786d 91 char AD9851::SetM6Value(char bx) {
loopsva 0:1ed24aaf786d 92 MultSix = bx;
loopsva 0:1ed24aaf786d 93 return(bx);
loopsva 0:1ed24aaf786d 94 }
loopsva 0:1ed24aaf786d 95
loopsva 0:1ed24aaf786d 96 //---------------------------------------------------------------
loopsva 0:1ed24aaf786d 97 // turn on AD9851
loopsva 0:1ed24aaf786d 98 void AD9851::AD9851Enable() {
loopsva 0:1ed24aaf786d 99 FortyBitWd = FortyBitWd & (-1-(PwrDnFlag));
loopsva 0:1ed24aaf786d 100 FirstAccess();
loopsva 0:1ed24aaf786d 101 // OutNewValue();
loopsva 0:1ed24aaf786d 102 }
loopsva 0:1ed24aaf786d 103
loopsva 0:1ed24aaf786d 104 // turn off AD9851
loopsva 0:1ed24aaf786d 105 void AD9851::AD9851Disable() {
loopsva 0:1ed24aaf786d 106 FirstEnable = false;
loopsva 0:1ed24aaf786d 107 FortyBitWd = FortyBitWd | PwrDnFlag;
loopsva 0:1ed24aaf786d 108 OutNewValue();
loopsva 0:1ed24aaf786d 109 }
loopsva 0:1ed24aaf786d 110
loopsva 0:1ed24aaf786d 111 // calculate new value based on change. If an over frequency condition exists, then resort back to original values
loopsva 0:1ed24aaf786d 112 bool AD9851::CalcNewValue() {
loopsva 0:1ed24aaf786d 113 RealFreq = BaseFreq + IfFreq;
loopsva 0:1ed24aaf786d 114 ErrorFlag = false;
loopsva 0:1ed24aaf786d 115 if(RealFreq >= 0.0) { // error if RealFreq is negative number
loopsva 0:1ed24aaf786d 116 if(((RealFreq >= RefOsc) && (MultSix == '0')) || (((RealFreq >= (RefOsc * 6.0)) && ((MultSix == '1') || (MultSix == 'A') || (MultSix == 'a'))))) {
loopsva 0:1ed24aaf786d 117 //error if >30MHz and multiplier = 0
loopsva 0:1ed24aaf786d 118 //error if >180MHz and multiplier = 1 or A
loopsva 0:1ed24aaf786d 119 ErrorFlag = true;
loopsva 0:1ed24aaf786d 120 BaseFreq = OldBaseFreq;
loopsva 0:1ed24aaf786d 121 IfFreq = OldIfFreq;
loopsva 0:1ed24aaf786d 122 RealFreq = BaseFreq + IfFreq;
loopsva 0:1ed24aaf786d 123 MultSix = OldMultSix;
loopsva 0:1ed24aaf786d 124 } else {
loopsva 0:1ed24aaf786d 125 OldBaseFreq = BaseFreq;
loopsva 0:1ed24aaf786d 126 OldIfFreq = IfFreq;
loopsva 0:1ed24aaf786d 127 RealFreq = BaseFreq + IfFreq;
loopsva 0:1ed24aaf786d 128 OldMultSix = MultSix;
loopsva 0:1ed24aaf786d 129 if((MultSix == '0') || ((MultSix == 'A') && (RealFreq < RefOsc))) { //less than 30MHz
loopsva 0:1ed24aaf786d 130 SerCount = 1.0 / (RefOsc / 4294967296.0 / RealFreq); // 4294967296 = 2^32
loopsva 0:1ed24aaf786d 131 FortyBitWd = FortyBitWd & (-1-(Mult6Flag));
loopsva 0:1ed24aaf786d 132 // if(gDebug > 1) printf("1- m6: %c rF: %f sF: %f 40bw: 0x%02x sc: %f\n ref: %f", MultSix, RealFreq, StepFreq, FortyBitWd, SerCount, RefOsc);
loopsva 0:1ed24aaf786d 133 } else { //less than 180MHz
loopsva 0:1ed24aaf786d 134 SerCount = 1.0 / ((RefOsc * 6.0) / 4294967296.0 / RealFreq);
loopsva 0:1ed24aaf786d 135 FortyBitWd = FortyBitWd | Mult6Flag;
loopsva 0:1ed24aaf786d 136 // if(gDebug > 1) printf("2- m6: %c rF: %f sF: %f 40bw: 0x%02x sc: %f\n", MultSix, RealFreq, StepFreq, FortyBitWd, SerCount);
loopsva 0:1ed24aaf786d 137 }
loopsva 0:1ed24aaf786d 138 FreqDiv = (unsigned int)SerCount;
loopsva 0:1ed24aaf786d 139 if(gDebug > 1) printf("3- out: 0x%02x%08x\n", FortyBitWd, FreqDiv);
loopsva 0:1ed24aaf786d 140 OutNewValue();
loopsva 0:1ed24aaf786d 141 }
loopsva 0:1ed24aaf786d 142 } else {
loopsva 0:1ed24aaf786d 143 printf("calc neg number!!!\n");
loopsva 0:1ed24aaf786d 144 ErrorFlag = true;
loopsva 0:1ed24aaf786d 145 }
loopsva 0:1ed24aaf786d 146 if(gDebug) printf("\nBase: %.3f IF: %.3f Freq: %.3f Mult: %c Out: 0x%02x%08x\n", BaseFreq, IfFreq, RealFreq, MultSix, FortyBitWd, FreqDiv);
loopsva 0:1ed24aaf786d 147 return (ErrorFlag);
loopsva 0:1ed24aaf786d 148 }
loopsva 0:1ed24aaf786d 149
loopsva 0:1ed24aaf786d 150 /* Private routines: */
loopsva 0:1ed24aaf786d 151 // set new value to AD9851
loopsva 0:1ed24aaf786d 152 void AD9851::OutNewValue() {
loopsva 0:1ed24aaf786d 153 unsigned int ShiftOut = FreqDiv;
loopsva 0:1ed24aaf786d 154 unsigned int TestOut = FreqDiv;
loopsva 0:1ed24aaf786d 155 char i = 0;
loopsva 0:1ed24aaf786d 156 for(i=0; i<32; i++) {
loopsva 0:1ed24aaf786d 157 TestOut = ShiftOut & 1;
loopsva 0:1ed24aaf786d 158 if(TestOut==1) {
loopsva 0:1ed24aaf786d 159 _sdo = 1;
loopsva 0:1ed24aaf786d 160 } else {
loopsva 0:1ed24aaf786d 161 _sdo = 0;
loopsva 0:1ed24aaf786d 162 }
loopsva 0:1ed24aaf786d 163 _clk = 1;
loopsva 0:1ed24aaf786d 164 ShiftOut = ShiftOut >> 1;
loopsva 0:1ed24aaf786d 165 _clk = 0;
loopsva 0:1ed24aaf786d 166 }
loopsva 0:1ed24aaf786d 167 ShiftOut = FortyBitWd;
loopsva 0:1ed24aaf786d 168 for(i=0; i<8; i++) {
loopsva 0:1ed24aaf786d 169 TestOut = ShiftOut & 1;
loopsva 0:1ed24aaf786d 170 if(TestOut==1) {
loopsva 0:1ed24aaf786d 171 _sdo = 1;
loopsva 0:1ed24aaf786d 172 } else {
loopsva 0:1ed24aaf786d 173 _sdo = 0;
loopsva 0:1ed24aaf786d 174 }
loopsva 0:1ed24aaf786d 175 _clk = 1;
loopsva 0:1ed24aaf786d 176 ShiftOut = ShiftOut >> 1;
loopsva 0:1ed24aaf786d 177 _clk = 0;
loopsva 0:1ed24aaf786d 178 }
loopsva 0:1ed24aaf786d 179 _len = 1;
loopsva 0:1ed24aaf786d 180 _len = 0;
loopsva 0:1ed24aaf786d 181 }
loopsva 0:1ed24aaf786d 182
loopsva 0:1ed24aaf786d 183 // BUG FIX, on the very first access after an enable, first force 100KHz w/Mult6 = 0, set Mult6 = 1 forever
loopsva 0:1ed24aaf786d 184 void AD9851::FirstAccess() {
loopsva 0:1ed24aaf786d 185 if(FirstEnable == false) {
loopsva 0:1ed24aaf786d 186 FirstEnable = true;
loopsva 0:1ed24aaf786d 187 unsigned int TempDiv = FreqDiv;
loopsva 0:1ed24aaf786d 188 FreqDiv =0x00da740d;
loopsva 0:1ed24aaf786d 189 char Temp40 = FortyBitWd;
loopsva 0:1ed24aaf786d 190 FortyBitWd = 0x0c;
loopsva 0:1ed24aaf786d 191 OutNewValue();
loopsva 0:1ed24aaf786d 192 wait_ms(5);
loopsva 0:1ed24aaf786d 193 FortyBitWd = Temp40;
loopsva 0:1ed24aaf786d 194 FreqDiv = TempDiv;
loopsva 0:1ed24aaf786d 195 SetM6Value(1);
loopsva 0:1ed24aaf786d 196 }
loopsva 0:1ed24aaf786d 197 CalcNewValue();
loopsva 0:1ed24aaf786d 198 }
loopsva 0:1ed24aaf786d 199 /*
loopsva 0:1ed24aaf786d 200 void AD9851::FirstAccess() {
loopsva 0:1ed24aaf786d 201 if(FirstEnable == false) {
loopsva 0:1ed24aaf786d 202 FirstEnable = true;
loopsva 0:1ed24aaf786d 203 unsigned int TempDiv = FreqDiv;
loopsva 0:1ed24aaf786d 204 FreqDiv =0;
loopsva 0:1ed24aaf786d 205 char Temp40 = FortyBitWd;
loopsva 0:1ed24aaf786d 206 FortyBitWd = 0x01;
loopsva 0:1ed24aaf786d 207 OutNewValue();
loopsva 0:1ed24aaf786d 208 wait_ms(5);
loopsva 0:1ed24aaf786d 209 OutNewValue();
loopsva 0:1ed24aaf786d 210 wait_ms(5);
loopsva 0:1ed24aaf786d 211 FortyBitWd = Temp40;
loopsva 0:1ed24aaf786d 212 FreqDiv = TempDiv;
loopsva 0:1ed24aaf786d 213 SetM6Value(1);
loopsva 0:1ed24aaf786d 214 }
loopsva 0:1ed24aaf786d 215 CalcNewValue();
loopsva 0:1ed24aaf786d 216 }
loopsva 0:1ed24aaf786d 217 */