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
AD9851.cpp
00001 #include "mbed.h" 00002 #include "AD9851.h" 00003 00004 extern int gDebug; // defined in main.cpp, used for printing verbose-ness level (0-3) 00005 //extern double StepFreq; // step frequency (used for gDebug lines only) 00006 00007 // power up default values 00008 double BaseFreq = 10000000.000; // base frequency - if frequency 00009 double IfFreq = 455000.0; // IF frequency 00010 double RealFreq = BaseFreq + IfFreq; // sum of the two frequencies 00011 double RefOsc = 30000000.000; // reference oscillator frequency 00012 char MultSix = 'A'; // x1 or x6 frequency oscillator - 0, 1 or A only 00013 bool ErrorFlag = false; // error flag 00014 bool FirstEnable = false; // used for DDS-60 bug fix 00015 00016 double OldBaseFreq = BaseFreq; // old base frequency - if frequency 00017 double OldIfFreq = IfFreq; // old IF frequency 00018 char OldMultSix = MultSix; // old x1 or x6 frequency oscillator - 0, 1 or A only 00019 00020 double SerCount = 1431655765.0; // calculated final value of data to AD9851 00021 unsigned int FreqDiv = 0x55555555; // calculated value of SerCount to be divided into SerData[0-4] 00022 00023 const char LsbPhase = 0x08; // LSB of phase setting, 0-31 (0-0x1f), 11.25 degrees per step 00024 const char PwrDnFlag = 0x04; // + power down flag 00025 const char Mult6Flag = 0x01; // + 180MHz - 30MHz multiplier x6 flag 00026 char FortyBitWd = PwrDnFlag + (LsbPhase * 1); // calculated 5th byte fo 40 bit word to be divided into SerData[0-4] 00027 00028 // constructor takes paramters and initializes I2C bus 00029 AD9851::AD9851(PinName CLK, PinName SDO, PinName LEN) 00030 : _clk(CLK) 00031 , _sdo(SDO) 00032 , _len(LEN) 00033 { 00034 _clk = 0; 00035 _sdo = 0; 00036 _len = 0; 00037 OutNewValue(); // initialize the AD9851 00038 } 00039 00040 // destructor 00041 AD9851::~AD9851() { 00042 } 00043 00044 // return base frequency value 00045 double AD9851::GetBaseValue() { 00046 return BaseFreq; 00047 } 00048 00049 // return IF frequency value 00050 double AD9851::GetIfValue() { 00051 return IfFreq; 00052 } 00053 00054 // return 32 serial word value 00055 unsigned int AD9851::GetFD32Value() { 00056 return FreqDiv; 00057 } 00058 00059 // return 5th "control" byte for 40 bit serial word value 00060 char AD9851::GetFortyValue() { 00061 return FortyBitWd; 00062 } 00063 00064 // return error flag 00065 bool AD9851::GetErrFlagValue() { 00066 return ErrorFlag; 00067 } 00068 00069 //--------------------------------------------------------------- 00070 // set base frequency value 00071 double AD9851::SetBaseValue(double bv) { 00072 if(bv >= 0.0) { 00073 BaseFreq = bv; 00074 } else { 00075 printf("Base neg number!!!\n"); 00076 } 00077 return(bv); 00078 } 00079 00080 // set IF frequency value 00081 double AD9851::SetIfValue(double bv) { 00082 if(bv >= 0.0) { 00083 IfFreq = bv; 00084 } else { 00085 printf("IF neg number!!!\n"); 00086 } 00087 return(bv); 00088 } 00089 00090 // set base frequency value, ascii 0 1 or A 00091 char AD9851::SetM6Value(char bx) { 00092 MultSix = bx; 00093 return(bx); 00094 } 00095 00096 //--------------------------------------------------------------- 00097 // turn on AD9851 00098 void AD9851::AD9851Enable() { 00099 FortyBitWd = FortyBitWd & (-1-(PwrDnFlag)); 00100 FirstAccess(); 00101 // OutNewValue(); 00102 } 00103 00104 // turn off AD9851 00105 void AD9851::AD9851Disable() { 00106 FirstEnable = false; 00107 FortyBitWd = FortyBitWd | PwrDnFlag; 00108 OutNewValue(); 00109 } 00110 00111 // calculate new value based on change. If an over frequency condition exists, then resort back to original values 00112 bool AD9851::CalcNewValue() { 00113 RealFreq = BaseFreq + IfFreq; 00114 ErrorFlag = false; 00115 if(RealFreq >= 0.0) { // error if RealFreq is negative number 00116 if(((RealFreq >= RefOsc) && (MultSix == '0')) || (((RealFreq >= (RefOsc * 6.0)) && ((MultSix == '1') || (MultSix == 'A') || (MultSix == 'a'))))) { 00117 //error if >30MHz and multiplier = 0 00118 //error if >180MHz and multiplier = 1 or A 00119 ErrorFlag = true; 00120 BaseFreq = OldBaseFreq; 00121 IfFreq = OldIfFreq; 00122 RealFreq = BaseFreq + IfFreq; 00123 MultSix = OldMultSix; 00124 } else { 00125 OldBaseFreq = BaseFreq; 00126 OldIfFreq = IfFreq; 00127 RealFreq = BaseFreq + IfFreq; 00128 OldMultSix = MultSix; 00129 if((MultSix == '0') || ((MultSix == 'A') && (RealFreq < RefOsc))) { //less than 30MHz 00130 SerCount = 1.0 / (RefOsc / 4294967296.0 / RealFreq); // 4294967296 = 2^32 00131 FortyBitWd = FortyBitWd & (-1-(Mult6Flag)); 00132 // 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); 00133 } else { //less than 180MHz 00134 SerCount = 1.0 / ((RefOsc * 6.0) / 4294967296.0 / RealFreq); 00135 FortyBitWd = FortyBitWd | Mult6Flag; 00136 // if(gDebug > 1) printf("2- m6: %c rF: %f sF: %f 40bw: 0x%02x sc: %f\n", MultSix, RealFreq, StepFreq, FortyBitWd, SerCount); 00137 } 00138 FreqDiv = (unsigned int)SerCount; 00139 if(gDebug > 1) printf("3- out: 0x%02x%08x\n", FortyBitWd, FreqDiv); 00140 OutNewValue(); 00141 } 00142 } else { 00143 printf("calc neg number!!!\n"); 00144 ErrorFlag = true; 00145 } 00146 if(gDebug) printf("\nBase: %.3f IF: %.3f Freq: %.3f Mult: %c Out: 0x%02x%08x\n", BaseFreq, IfFreq, RealFreq, MultSix, FortyBitWd, FreqDiv); 00147 return (ErrorFlag); 00148 } 00149 00150 /* Private routines: */ 00151 // set new value to AD9851 00152 void AD9851::OutNewValue() { 00153 unsigned int ShiftOut = FreqDiv; 00154 unsigned int TestOut = FreqDiv; 00155 char i = 0; 00156 for(i=0; i<32; i++) { 00157 TestOut = ShiftOut & 1; 00158 if(TestOut==1) { 00159 _sdo = 1; 00160 } else { 00161 _sdo = 0; 00162 } 00163 _clk = 1; 00164 ShiftOut = ShiftOut >> 1; 00165 _clk = 0; 00166 } 00167 ShiftOut = FortyBitWd; 00168 for(i=0; i<8; i++) { 00169 TestOut = ShiftOut & 1; 00170 if(TestOut==1) { 00171 _sdo = 1; 00172 } else { 00173 _sdo = 0; 00174 } 00175 _clk = 1; 00176 ShiftOut = ShiftOut >> 1; 00177 _clk = 0; 00178 } 00179 _len = 1; 00180 _len = 0; 00181 } 00182 00183 // BUG FIX, on the very first access after an enable, first force 100KHz w/Mult6 = 0, set Mult6 = 1 forever 00184 void AD9851::FirstAccess() { 00185 if(FirstEnable == false) { 00186 FirstEnable = true; 00187 unsigned int TempDiv = FreqDiv; 00188 FreqDiv =0x00da740d; 00189 char Temp40 = FortyBitWd; 00190 FortyBitWd = 0x0c; 00191 OutNewValue(); 00192 wait_ms(5); 00193 FortyBitWd = Temp40; 00194 FreqDiv = TempDiv; 00195 SetM6Value(1); 00196 } 00197 CalcNewValue(); 00198 } 00199 /* 00200 void AD9851::FirstAccess() { 00201 if(FirstEnable == false) { 00202 FirstEnable = true; 00203 unsigned int TempDiv = FreqDiv; 00204 FreqDiv =0; 00205 char Temp40 = FortyBitWd; 00206 FortyBitWd = 0x01; 00207 OutNewValue(); 00208 wait_ms(5); 00209 OutNewValue(); 00210 wait_ms(5); 00211 FortyBitWd = Temp40; 00212 FreqDiv = TempDiv; 00213 SetM6Value(1); 00214 } 00215 CalcNewValue(); 00216 } 00217 */
Generated on Wed Jul 13 2022 20:00:24 by 1.7.2