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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers AD9851.cpp Source File

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 */