With the DDS RAM registers a desired function "frequency (time)" can be implemented for one of the output channels and triggered either by the serial terminal or by an external signal on one of the mbed pins.

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 //      ****************************************
00002 //      *** frequency ramps with the RAM ***
00003 //      ****************************************
00004 
00005 #include "mbed.h"
00006 #include "DDS.h"
00007 
00008 Serial          pc(USBTX, USBRX);
00009 DigitalOut      myled(LED1);
00010 DigitalOut      cs2(p11);
00011 DigitalOut      cs1(p8);
00012 DigitalOut      rst(p9);
00013 DigitalOut      update(p10);
00014 DigitalOut      ps0(p12);
00015 DigitalOut      ps1(p14);
00016 DigitalOut      trigger(p13);
00017 DigitalOut      trigger1(p23);
00018 DigitalOut      trigger2(p24);
00019 InterruptIn     mcs(p21);  //InterruptIn description: http://mbed.org/handbook/InterruptIn
00020 DigitalIn       mexp(p22);   //DigitalIn description: http://mbed.org/handbook/DigitalIn
00021 DDS             DDS(p5, p6, p7, p8, p9, p10);
00022 
00023 // counting variables:
00024 int     i = 0;
00025 int     j = 0;
00026 // frequency of reference clock connected to the DDS board:
00027 double  ref_clock = 400.0e6;
00028 
00029 // ##################### definition of functions ############################
00030 
00031 // reset the DDS: 
00032 int reset() {
00033     rst = 0;
00034     rst = 1;
00035     wait(0.1);
00036     rst = 0 ;
00037     return 0;
00038 }
00039 
00040 // choosing one of the two output channels is done with this functions:
00041 int ch_1() {
00042     cs1 = 0;
00043     cs2 = 1;
00044     return 0;
00045 }
00046 int ch_2() {
00047     cs1 = 1;
00048     cs2 = 0;
00049     return 0;
00050 }
00051 
00052 // This function always rounds values up (in mode ?? of the DDS a problem occurs
00053 // if the final value is not reached
00054 int round(double a) {
00055     return int(a + 0.5);
00056 }
00057 
00058 // Calculate the "Frequency Tuning Word (FTWO)" for the DDS registers:
00059 uint32_t FTWO_func(double frequency) {
00060     return 0xFFFFFFFF & round(frequency/ref_clock*pow(2.0,32.0));
00061     }
00062 
00063 // RSCW0, RSCW1, RSCW2 and RSCW3 are the RAM profiles of the DDS which can be filled with different
00064 // parts of the ramp: 
00065 // ************* RSCW0 ******************    
00066 void writeRSCW0(int r0, int r1, uint32_t RSCW, double f[]) {
00067     int         R_used        = r1-r0;
00068     uint32_t    FTWO[R_used];
00069     ps0 = 0;
00070     ps1 = 0; 
00071     update = 0;
00072     // For the structure of the RSCW0 byte see the register map of the DDS.
00073     // Instruction byte: page 25, we want to write (0), so 0100
00074     // and internal adress of the register to be written in
00075     DDS._spi.write(0x00 | (0x07 & 0x1F));
00076     // byte 5: Ramp rate first part
00077     DDS._spi.write(0xFF & RSCW);
00078     // byte 4: Ramp rate second part
00079     DDS._spi.write(0xFF & (RSCW >> 8));
00080     // byte 3: final address <7:0>
00081     DDS._spi.write(0xFF & r1);
00082     // byte 2
00083     DDS._spi.write(((r0 << 2) & 0xFC) | ((r1 >> 8) & 0x03));
00084     // byte 1: beginning address <9:6>
00085     DDS._spi.write(0x20 | (((r0 >> 6) & 0x0F)));
00086         update = 1;
00087         wait_us(10);//5*1/(12.0e6));
00088         update =0;
00089     
00090     // The frequency ramp is given as an array of frequencies. Here the frequency tuning 
00091     // words (FTWOs) are calculated:  
00092     i = 0;
00093     while (i<=(R_used)) {
00094         FTWO[R_used-i] = FTWO_func(f[i]);
00095         i += 1;
00096         }
00097     // Print start and final value of the RAM part:
00098     pc.printf("RSCW0 written: %lf %lf \r\n", f[0], f[R_used]);
00099     // Select the combination of ps0 and ps1 belonging to RSCW0 and start the RAM writing process:    
00100     ps0 = 0;
00101     ps1 = 0; 
00102     // Send instruction byte to start the RAM writing process:   
00103     DDS._spi.write(0x0B);
00104     // Write the frequency tuning words into the RAM:
00105     i = 0;
00106     while (i<=(R_used)) {
00107         DDS.RAM_write_FTWO(FTWO[i]);
00108         i += 1;
00109         }
00110     }
00111     
00112 // ************* RSCW1 ******************  
00113 void writeRSCW1(int r0, int r1, uint32_t RSCW, double f[]) {
00114     int         R_used        = r1-r0;
00115     uint32_t    FTWO[R_used];
00116     ps0 = 1;
00117     ps1 = 0; 
00118     update = 0;
00119     DDS._spi.write(0x00 | (0x08 & 0x1F));
00120     DDS._spi.write(0xFF & RSCW);
00121     DDS._spi.write(0xFF & (RSCW >> 8));
00122     DDS._spi.write(0xFF & r1);
00123     DDS._spi.write(((r0 << 2) & 0xFC) | ((r1 >> 8) & 0x03));
00124     DDS._spi.write(0x20 | (((r0 >> 6) & 0x0F)));
00125         update = 1;
00126         wait_us(10);
00127         update =0;
00128        
00129     i = 0;
00130     while (i<=(R_used)) {
00131         FTWO[R_used-i] = FTWO_func(f[i]);
00132         i += 1;
00133         } 
00134     pc.printf("RSCW1 written: %lf %lf \r\n", f[0], f[R_used]);
00135         
00136     ps0 = 1;
00137     ps1 = 0; 
00138     DDS._spi.write(0x0B);
00139     i = 0;
00140     while (i<=(R_used)) {
00141         DDS.RAM_write_FTWO(FTWO[i]);
00142         i += 1;
00143         }
00144     }
00145 
00146 // ************* RSCW2 ******************     
00147 void writeRSCW2(int r0, int r1, uint32_t RSCW, double f[]) {
00148     int         R_used        = r1-r0;
00149     uint32_t    FTWO[R_used];
00150     ps0 = 0;
00151     ps1 = 1; 
00152     update = 0;
00153     DDS._spi.write(0x00 | (0x09 & 0x1F));
00154     DDS._spi.write(0xFF & RSCW);
00155     DDS._spi.write(0xFF & (RSCW >> 8));
00156     DDS._spi.write(0xFF & r1);
00157     DDS._spi.write(((r0 << 2) & 0xFC) | ((r1 >> 8) & 0x03));
00158     DDS._spi.write(0x20 | (((r0 >> 6) & 0x0F)));
00159         update = 1;
00160         wait_us(10);
00161         update =0;
00162       
00163     i = 0;
00164     while (i<=(R_used)) {
00165         FTWO[R_used-i] = FTWO_func(f[i]);
00166         i += 1;
00167         }
00168 
00169     pc.printf("RSCW0 written: %lf %lf \r\n", f[0], f[R_used]);        
00170     ps0 = 0;
00171     ps1 = 1; 
00172    
00173     DDS._spi.write(0x0B);
00174     i = 0;
00175     while (i<=(R_used)) {
00176         DDS.RAM_write_FTWO(FTWO[i]);
00177         i += 1;
00178         }
00179     }
00180     
00181 // ************* RSCW3 ****************** 
00182 void writeRSCW3(int r0, int r1, uint32_t RSCW, double f[]) {
00183     int         R_used        = r1-r0;
00184     uint32_t    FTWO[R_used];
00185     ps0 = 1;
00186     ps1 = 1; 
00187     update = 0;
00188     DDS._spi.write(0x00 | (0x0A & 0x1F));
00189     DDS._spi.write(0xFF & RSCW);
00190     DDS._spi.write(0xFF & (RSCW >> 8));
00191     DDS._spi.write(0xFF & r1);
00192     DDS._spi.write(((r0 << 2) & 0xFC) | ((r1 >> 8) & 0x03));
00193     DDS._spi.write(0x20 | (((r0 >> 6) & 0x0F)));
00194         update = 1;
00195         wait_us(10);
00196         update =0;
00197       
00198     i = 0;
00199     while (i<=(R_used)) {
00200         FTWO[R_used-i] = FTWO_func(f[i]);
00201         i += 1;
00202         }
00203 
00204     pc.printf("RSCW0 written: %lf %lf \r\n", f[0], f[R_used]);
00205         
00206     ps0 = 1;
00207     ps1 = 1; 
00208     DDS._spi.write(0x0B);
00209     i = 0;
00210     while (i<=(R_used)) {
00211         DDS.RAM_write_FTWO(FTWO[i]);
00212         i += 1;
00213         }
00214     }
00215 
00216 // Function to calculate the RSCW-word used in RSCW1, RSCW2, RSCW3 and RSCW4
00217 uint64_t RSCW_func(int ram0, int ram1, double trise) {
00218     int RAM_used = ram1-ram0+1;
00219     double tmin = 1.0*4.0/ref_clock*RAM_used;       // minimum 1 dwell of time 4/clock at each address
00220     double tmax = 65535.0*4.0/ref_clock*RAM_used;   // 16 bit register corresponding to 65535 dwells
00221     if (trise < tmin) { pc.printf("ERROR: ramp time too small. Minimum: %f \r \n", tmin); };
00222     if (trise > tmax) { pc.printf("ERROR: ramp time too large. Maximum: %f \r \n", tmax); };
00223     int dwells  = round(trise/(4.0/ref_clock*RAM_used));
00224     pc.printf(" %i dwells at each address ---> %f ramp time. \r \n", dwells, dwells*RAM_used*4.0/ref_clock);
00225     return 0xFFFF & dwells;
00226     }
00227    
00228 // The wait-function doesn't offer time resolution of mikroseconds. By using a process like
00229 // counting up an integer number and measuring the time the mbed needs for this process a time
00230 // resolution of some tens of nano-seconds can be reached. "counter()" is used in "start_ramp()" 
00231 // below:
00232 int counter(double t) {
00233     int bins = int((t-91.8160e-9)/(41.6664e-9) + 0.5);
00234     return bins;
00235      };
00236    
00237 int start_ramp(double trise, double tstay) {
00238             int i = 0;
00239             int count = counter(trise+tstay);
00240             ps0 = 1;
00241             ps1 = 0;
00242             //-----------------------------
00243             // NEVER EVER change this loop! (Allows for time measurement, see above)
00244             trigger = 0;
00245             trigger = 1;
00246             while(i<count){
00247                 i += 1;
00248             }
00249             trigger = 0;
00250             //-----------------------------
00251             ps0 = 0;
00252             ps1 = 0;
00253             i = 0;
00254             while(i<count){
00255                 i += 1;
00256             }
00257     return 0;
00258     };
00259    
00260 // Functions used to select output channel 1 or 2 upon receive of an external trigger signal:
00261 void check_up(){
00262     ps0 = 0;
00263     ps1 = 1;
00264     ch_1(); DDS.CFR1_write(0x00000200);
00265     ch_2(); DDS.CFR1_write(0x80000200);
00266     };
00267    
00268 void check_down() {
00269     ps0 = 0;
00270     ps1 = 1;
00271     ch_2(); DDS.CFR1_write(0x00000200);
00272     ch_1(); DDS.CFR1_write(0x80000200);
00273     };
00274 
00275 // ############################################################
00276 // ##################### main part ############################
00277 
00278 int main() {
00279 
00280     pc.printf(" \r \r \n \n ***** frequency sweep with DDS in RAM mode***** \r \r \n \n");
00281     pc.printf("Enter: \r \n");
00282     pc.printf("'1' or '2' --> select which of the two output channel should be ramped. \r \n");
00283     pc.printf("'a' --> frequency ramp with parameters 'trise' and 'tstay' and the frequency values in the mbed code is started and repeated with about 50 Hz. A trigger signal lies on output pin 13 of the mbed. \r \n");
00284     pc.printf("'t' --> read in a new value for 'tstay' \r \n");
00285 
00286     reset();
00287     
00288     double      tstay           = 50.0e-6;
00289     
00290     // intermediate frequencies
00291     double      frequency0      = 79.5e6;// both channels are initiated on this frequency
00292     double      frequency1      = 80.5e6;
00293     // tuning word RSCW0 variables
00294     double      trise_00        = 100e-6;
00295     int         ram0_00         = 1;
00296     int         ram1_00         = 156; 
00297     const int   RAM_used_00     = ram1_00 - ram0_00;
00298     double      f00 [RAM_used_00+1];
00299     double      frequency_init [1];
00300     frequency_init[0] = frequency0;
00301     
00302     j = 0;
00303     while (j<=(RAM_used_00)) {
00304         f00[j] = frequency1 - (frequency1-frequency0)/trise_00*j*trise_00/(RAM_used_00);
00305         j += 1;
00306     }
00307     
00308     // tuning word RSCW1 variables 
00309     double      trise_10        = 10.0e-6;//0.1e-6;
00310     int         ram0_10         = 250;
00311     int         ram1_10         = 500;
00312     int         RAM_used_10     = ram1_10-ram0_10; 
00313     double      f10 [RAM_used_10+1];   
00314     double      P [RAM_used_10+1];
00315     
00316     j = 0;
00317     while (j<=(RAM_used_10)) {
00318         f10[j] = frequency0 + (frequency1-frequency0)/trise_10*j*trise_10/(RAM_used_10);
00319         j += 1;
00320     }
00321     
00322     // (Logistic function from below could be added here) 
00323     
00324     // ### calculation of RSCW-words ### 
00325     uint64_t RSCW0 = RSCW_func(ram0_00, ram1_00, trise_00);
00326     uint64_t RSCW1 = RSCW_func(ram0_10, ram1_10, trise_10);
00327     uint64_t RSCW2 = RSCW_func(501, 501, 10.0e-6);
00328     
00329     // ### initialize both channels on the first intermediate frequency and write into their RAM
00330     ch_1();
00331    
00332     DDS.CFR1_write(0x00000200);
00333     DDS.FTW0_write(FTWO_func(frequency0));
00334     writeRSCW1(ram0_10, ram1_10, RSCW1, f10);
00335     writeRSCW0(ram0_00, ram1_00, RSCW0, f00); 
00336     writeRSCW2(501, 501, RSCW2, frequency_init);
00337     
00338     ch_2();
00339 
00340     DDS.CFR1_write(0x00000200);
00341     DDS.FTW0_write(FTWO_func(frequency0));
00342     writeRSCW1(ram0_10, ram1_10, RSCW1, f10); 
00343     writeRSCW0(ram0_00, ram1_00, RSCW0, f00);
00344     writeRSCW2(501, 501, RSCW2, frequency_init);
00345 
00346     //pc.printf("enter: \r \n 'u' to trigger ramp up \r \n 'd' to trigger ramp down \r \n 't' to enter new ramp time \r \n 's' for new start frequency \r \n 'e' for new end frequency \r \n");
00347     char up_or_down = '0';
00348     double trise = trise_00;  
00349     
00350     while(1) {
00351             if(pc.readable()) {
00352                 up_or_down = pc.getc();
00353                 if(up_or_down == 'a') {
00354                     pc.printf("a --> ramp started");
00355                     while(1) {
00356                         start_ramp(trise, tstay);
00357                         wait(2e-2);
00358                         if(pc.readable()) break;
00359                         }
00360                  if (up_or_down == 't') {
00361                     pc.printf("enter new tstay value in us: \n");
00362                     pc.scanf("%lf", &tstay);
00363                     tstay = tstay*1.0e-6;
00364                     }
00365                 if (up_or_down == 'u') {
00366                         pc.printf("u");
00367                         trigger = 1;
00368                         wait(trise/4.0);
00369                         trigger = 0;
00370                          /////
00371                         ps0 = 1;
00372                         ps1 = 0;
00373                          /////
00374                         }
00375                if (up_or_down == 'd') {
00376                         pc.printf("d");
00377                         trigger = 1;
00378                         wait(trise/4.0);
00379                         trigger = 0;
00380                         /////
00381                         ps0 = 0;
00382                         ps1 = 0;
00383                         /////
00384                          }
00385                 if (up_or_down == '1') {
00386                     trigger = 0;
00387                     trigger = 1;
00388                     /*ps0 = 0;
00389                     ch_2(); DDS.CFR1_write(0x00000200);
00390                     ch_1(); DDS.CFR1_write(0x80000200);*/
00391                     check_down();
00392                     trigger = 0;
00393                     pc.printf("ramping channel 1 \r\n");
00394                     }
00395                 if (up_or_down == '2') {
00396                     trigger = 0;
00397                     trigger = 1;
00398                     /*ps0 = 0;
00399                     ch_1(); DDS.CFR1_write(0x00000200);
00400                     ch_2(); DDS.CFR1_write(0x80000200);*/
00401                     check_up();
00402                     trigger = 0;
00403                     pc.printf("ramping channel 2 \r\n");
00404                     }
00405                 /*if (up_or_down == 's') {
00406                     pc.printf("enter new frequency0 value in MHz: \n");
00407                     pc.scanf("%lf", &frequency0);
00408                     frequency0 = frequency0*1.0e6;
00409                     initialize(frequency0, frequency1, RAM_start, RAM_final, trise);
00410                     }*/
00411                 /*if (up_or_down == 'e') {
00412                     pc.printf("enter new frequency1 value in MHz: \n");
00413                     pc.scanf("%lf", &frequency1);
00414                     frequency1 = frequency1*1.0e6;
00415                     initialize(frequency0, frequency1, RAM_start, RAM_final, trise);
00416                     }*/
00417             }
00418             // Wait for a rising or falling edge on the mbed-mcs pin and select accordingly channel 1 or 
00419             // channel 2 for ramping
00420             mcs.rise(&check_up);
00421             mcs.fall(&check_down);
00422             // start the ramp when a signal sets the mbed pin 'mexp' to '1'
00423             if(mexp) {
00424                     while(mexp);
00425                     start_ramp(trise, tstay);
00426                    // pc.printf(" exp trigger in registered \r \n");
00427                 }
00428     }
00429    
00430     return 0;
00431 }
00432 
00433     /* LOGISTIC FUNCTION
00434     j = 0;
00435     double alpha = log(double((RAM_used_10-1.0)*(RAM_used_10-1.0)))*1/RAM_used_10;
00436     pc.printf("alpha %f\r\n",alpha);
00437     double beta = 1/alpha*log(double(RAM_used_10-1));
00438     pc.printf("beta %f\r\n",beta);
00439     while (j<=(RAM_used_10)) {
00440         P[j] = 1.0/(1.0+exp(-(j-beta)*alpha));
00441         f10[j] = frequency0*(1-P[j]) + frequency1*P[j];
00442         j += 1;
00443     }
00444     f10[0]              = frequency0;
00445     f10[RAM_used_10]    = frequency1;
00446     pc.printf("P(0) = %f P(RAM_used) = %f \r\n", P[0], P[RAM_used_10]);*/
00447 
00448