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

main.cpp

Committer:
ahambi
Date:
2012-07-04
Revision:
3:62e50cb85890
Parent:
0:2160f1821475
Child:
4:535692f9e205

File content as of revision 3:62e50cb85890:

// compile --> copy to mbed
// ALT + B in serial terminal --> break command for mbed

//      ****************************************
//      *** frequency ramps with the the RAM ***
//      ****************************************

#include "mbed.h"
#include "DDS.h"

Serial          pc(USBTX, USBRX);
DigitalOut      myled(LED1);
DigitalOut      cs2(p11);
DigitalOut      cs1(p8);
DigitalOut      rst(p9);
DigitalOut      update(p10);
DigitalOut      ps0(p12);
DigitalOut      ps1(p14);
DigitalOut      trigger(p13);
DigitalOut      trigger1(p23);
DigitalOut      trigger2(p24);
InterruptIn     mcs(p21);  //InterruptIn description: http://mbed.org/handbook/InterruptIn
DigitalIn       mexp(p22);   //DigitalIn description: http://mbed.org/handbook/DigitalIn
DDS             DDS(p5, p6, p7, p8, p9, p10);

// counting variables:
int     i = 0;
int     j = 0;
// frequency of reference clock connected to the DDS board:
double  ref_clock = 400.0e6;

// ##################### definition of functions ############################
int reset() {
    rst = 0;
    rst = 1;
    wait(0.1);
    rst = 0 ;
    return 0;
}

// choosing one of the two output channels is done with this functions:
int ch_1() {
    cs1 = 0;
    cs2 = 1;
    return 0;
}
int ch_2() {
    cs1 = 1;
    cs2 = 0;
    return 0;
}

int round(double a) {
    return int(a + 0.5);
}

uint32_t FTWO_func(double frequency) {
    return 0xFFFFFFFF & round(frequency/ref_clock*pow(2.0,32.0));
    }
    
uint32_t PHWO_func(double phase) {
    return 0x3FFF & int(phase/360.0*pow(2.0,14.0));
    }
    
void writePhaseRAM(int r0, int r1, uint32_t RSCW, double f[]) {
    int         R_used        = r1-r0;
    uint32_t    FTWO[R_used];
    ps0 = 0;
    ps1 = 0; 
    update = 0;
    // Instruction byte: page 25, we want to write (0), so 0100
    // + internal adress of the register to be written in
    DDS._spi.write(0x00 | (0x07 & 0x1F));
    // byte 5: Ramp rate first part
    DDS._spi.write(0xFF & RSCW);
    // byte 4: Ramp rate second part
    DDS._spi.write(0xFF & (RSCW >> 8));
    // byte 3: final address <7:0>
    DDS._spi.write(0xFF & r1);
    // byte 2
    DDS._spi.write(((r0 << 2) & 0xFC) | ((r1 >> 8) & 0x03));
    // byte 1: beginning address <9:6>
    DDS._spi.write(0x40 | (((r0 >> 6) & 0x0F)));
        update = 1;
        wait_us(10);//5*1/(12.0e6));
        update =0;
      
    i = 0;
    while (i<=(R_used)) {
        //FTWO[i] = FTWO_func(frequency[i]);
        FTWO[R_used-i] = PHWO_func(f[i]);
        //pc.printf("written %i %lf \r \n", i, f[i]);
        i += 1;
        }

    pc.printf("RSCW0 written: %lf %lf \r\n", f[0], f[R_used]);
        
    ps0 = 0;
    ps1 = 0; 
   
    DDS._spi.write(0x0B);
    
    i = 0;
    while (i<=(R_used)) {
        DDS.RAM_write_FTWO((FTWO[i] << 18) & 0xFFFFFFFF);
       // pc.printf("calculated %d : %x, %f \n", i, FTWO[i], frequency[i]);
        i += 1;
        }
    }
    
void writeRSCW0(int r0, int r1, uint32_t RSCW, double f[]) {
    int         R_used        = r1-r0;
    uint32_t    FTWO[R_used];
    ps0 = 0;
    ps1 = 0; 
    update = 0;
    // Instruction byte: page 25, we want to write (0), so 0100
    // + internal adress of the register to be written in
    DDS._spi.write(0x00 | (0x07 & 0x1F));
    // byte 5: Ramp rate first part
    DDS._spi.write(0xFF & RSCW);
    // byte 4: Ramp rate second part
    DDS._spi.write(0xFF & (RSCW >> 8));
    // byte 3: final address <7:0>
    DDS._spi.write(0xFF & r1);
    // byte 2
    DDS._spi.write(((r0 << 2) & 0xFC) | ((r1 >> 8) & 0x03));
    // byte 1: beginning address <9:6>
    DDS._spi.write(0x20 | (((r0 >> 6) & 0x0F)));
        update = 1;
        wait_us(10);//5*1/(12.0e6));
        update =0;
      
    i = 0;
    while (i<=(R_used)) {
        //FTWO[i] = FTWO_func(frequency[i]);
        FTWO[R_used-i] = FTWO_func(f[i]);
        //pc.printf("written %i %lf \r \n", i, f[i]);
        i += 1;
        }

    pc.printf("RSCW0 written: %lf %lf \r\n", f[0], f[R_used]);
        
    ps0 = 0;
    ps1 = 0; 
   
    DDS._spi.write(0x0B);
    
    i = 0;
    while (i<=(R_used)) {
        DDS.RAM_write_FTWO(FTWO[i]);
       // pc.printf("calculated %d : %x, %f \n", i, FTWO[i], frequency[i]);
        i += 1;
        }
    }
    
void writeRSCW1(int r0, int r1, uint32_t RSCW, double f[]) {
    int         R_used        = r1-r0;
    uint32_t    FTWO[R_used];
    ps0 = 1;
    ps1 = 0; 
    update = 0;
    // Instruction byte: page 25, we want to write (0), so 0100
    // + internal adress of the register to be written in
    DDS._spi.write(0x00 | (0x08 & 0x1F));
    // byte 5: Ramp rate first part
    DDS._spi.write(0xFF & RSCW);
    // byte 4: Ramp rate second part
    DDS._spi.write(0xFF & (RSCW >> 8));
    // byte 3: final address <7:0>
    DDS._spi.write(0xFF & r1);
    // byte 2
    DDS._spi.write(((r0 << 2) & 0xFC) | ((r1 >> 8) & 0x03));
    // byte 1: beginning address <9:6>
    DDS._spi.write(0x20 | (((r0 >> 6) & 0x0F)));
        update = 1;
        wait_us(10);//5*1/(12.0e6));
        update =0;
       
    i = 0;
    while (i<=(R_used)) {
        //FTWO[i] = FTWO_func(frequency[i]);
        FTWO[R_used-i] = FTWO_func(f[i]);
        //pc.printf("written %i %lf \r \n", i, f[i]);
        i += 1;
        }
        
    pc.printf("RSCW1 written: %lf %lf \r\n", f[0], f[R_used]);
        
    ps0 = 1;
    ps1 = 0; 
   
    DDS._spi.write(0x0B);
    
    i = 0;
    while (i<=(R_used)) {
        DDS.RAM_write_FTWO(FTWO[i]);
       // pc.printf("calculated %d : %x, %f \n", i, FTWO[i], frequency[i]);
        i += 1;
        }
    }
    
void writeRSCW2(int r0, int r1, uint32_t RSCW, double f[]) {
    int         R_used        = r1-r0;
    uint32_t    FTWO[R_used];
    ps0 = 0;
    ps1 = 1; 
    update = 0;
    // Instruction byte: page 25, we want to write (0), so 0100
    // + internal adress of the register to be written in
    DDS._spi.write(0x00 | (0x09 & 0x1F));
    // byte 5: Ramp rate first part
    DDS._spi.write(0xFF & RSCW);
    // byte 4: Ramp rate second part
    DDS._spi.write(0xFF & (RSCW >> 8));
    // byte 3: final address <7:0>
    DDS._spi.write(0xFF & r1);
    // byte 2
    DDS._spi.write(((r0 << 2) & 0xFC) | ((r1 >> 8) & 0x03));
    // byte 1: beginning address <9:6>
    DDS._spi.write(0x20 | (((r0 >> 6) & 0x0F)));
        update = 1;
        wait_us(10);//5*1/(12.0e6));
        update =0;
      
    i = 0;
    while (i<=(R_used)) {
        //FTWO[i] = FTWO_func(frequency[i]);
        FTWO[R_used-i] = FTWO_func(f[i]);
        //pc.printf("written %i %lf \r \n", i, f[i]);
        i += 1;
        }

    pc.printf("RSCW0 written: %lf %lf \r\n", f[0], f[R_used]);
        
    ps0 = 0;
    ps1 = 1; 
   
    DDS._spi.write(0x0B);
    
    i = 0;
    while (i<=(R_used)) {
        DDS.RAM_write_FTWO(FTWO[i]);
       // pc.printf("calculated %d : %x, %f \n", i, FTWO[i], frequency[i]);
        i += 1;
        }
    }
    
    
void writeRSCW3(int r0, int r1, uint32_t RSCW, double f[]) {
    int         R_used        = r1-r0;
    uint32_t    FTWO[R_used];
    ps0 = 1;
    ps1 = 1; 
    update = 0;
    // Instruction byte: page 25, we want to write (0), so 0100
    // + internal adress of the register to be written in
    DDS._spi.write(0x00 | (0x10 & 0x1F));
    // byte 5: Ramp rate first part
    DDS._spi.write(0xFF & RSCW);
    // byte 4: Ramp rate second part
    DDS._spi.write(0xFF & (RSCW >> 8));
    // byte 3: final address <7:0>
    DDS._spi.write(0xFF & r1);
    // byte 2
    DDS._spi.write(((r0 << 2) & 0xFC) | ((r1 >> 8) & 0x03));
    // byte 1: beginning address <9:6>
    DDS._spi.write(0x20 | (((r0 >> 6) & 0x0F)));
        update = 1;
        wait_us(10);//5*1/(12.0e6));
        update =0;
      
    i = 0;
    while (i<=(R_used)) {
        //FTWO[i] = FTWO_func(frequency[i]);
        FTWO[R_used-i] = FTWO_func(f[i]);
        //pc.printf("written %i %lf \r \n", i, f[i]);
        i += 1;
        }

    pc.printf("RSCW0 written: %lf %lf \r\n", f[0], f[R_used]);
        
    ps0 = 1;
    ps1 = 1; 
   
    DDS._spi.write(0x0B);
    
    i = 0;
    while (i<=(R_used)) {
        DDS.RAM_write_FTWO(FTWO[i]);
       // pc.printf("calculated %d : %x, %f \n", i, FTWO[i], frequency[i]);
        i += 1;
        }
    }

uint64_t RSCW_func(int ram0, int ram1, double trise) {
    int RAM_used = ram1-ram0+1;
    double tmin = 1.0*4.0/ref_clock*RAM_used;       // minimum 1 dwell of time 4/clock at each address
    double tmax = 65535.0*4.0/ref_clock*RAM_used;   // 16 bit register corresponding to 65535 dwells
    if (trise < tmin) { pc.printf("ERROR: ramp time too small. Minimum: %f \r \n", tmin); };
    if (trise > tmax) { pc.printf("ERROR: ramp time too large. Maximum: %f \r \n", tmax); };
    int dwells  = round(trise/(4.0/ref_clock*RAM_used));
    pc.printf(" %i dwells at each address ---> %f ramp time. \r \n", dwells, dwells*RAM_used*4.0/ref_clock);
    return 0xFFFF & dwells;
    }
   
int counter(double t) {// for t in us
    int bins = int((t-91.8160e-9)/(41.6664e-9) + 0.5);
    //pc.printf("bins = %i", bins);
    return bins;
     };
   
int start_ramp(double trise, double tstay) {
            int i = 0;
            int count = counter(trise+tstay);
            ps0 = 1;
            ps1 = 0;
            //-----------------------------
            // NEVER EVER change this loop!
            trigger = 0;
            trigger = 1;
            while(i<count){
                i += 1;
            }
            trigger = 0;
            //-----------------------------
            ps0 = 0;
            ps1 = 0;
            i = 0;
    return 0;
    };
   
void check_up(){
    // try to avoid initialization ramp
    ps0 = 0;
    ps1 = 1;
    ch_1(); DDS.CFR1_write(0x00000200);
    ch_2(); DDS.CFR1_write(0x80000200);
    };
   
void check_down() {
    // try to avoid initialization ramp
    ps0 = 0;
    ps1 = 1;
    ch_2(); DDS.CFR1_write(0x00000200);
    ch_1(); DDS.CFR1_write(0x80000200);
    };

// ############################################################
    
    
// ##################### main part ############################

int main() {

    pc.printf(" \r \r \n \n ***** frequency sweep with DDS in RAM mode***** \r \r \n \n");

    reset();
    
    double      tstay           = 500.0e-6;
    
    // intermediate frequencies
    double      frequency0      = 78.98e6;//100.0e6; // both channels are initiated on this frequency
    double      frequency1      = 79.02e6;//110.0e6; 
    // tuning word RSCW0 variables
    double      trise_00        = 0.1e-6;//20.0e-6;
    int         ram0_00         = 50;
    int         ram1_00         = 55;//100; 
    const int   RAM_used_00     = ram1_00 - ram0_00;
    double      f00 [RAM_used_00+1];
    double      frequency_init [1];
    frequency_init[0] = frequency0;
    
    j = 0;
    while (j<=(RAM_used_00)) {
        f00[j] = frequency1 - (frequency1-frequency0)/trise_00*j*trise_00/(RAM_used_00);
        j += 1;
    }
    
    // tuning word RSCW1 variables 
    double      trise_10        = 0.1e-6;
    int         ram0_10         = 250;
    int         ram1_10         = 255;//500;
    int         RAM_used_10     = ram1_10-ram0_10; 
    double      f10 [RAM_used_10+1];   
    double      P [RAM_used_10+1];
    
    j = 0;
    while (j<=(RAM_used_10)) {
        f10[j] = frequency1 + (frequency1-frequency0)/trise_10*j*trise_10/(RAM_used_10);
        j += 1;
    }
    //### logistic function 
    /*
    j = 0;
    double alpha = log(double((RAM_used_10-1.0)*(RAM_used_10-1.0)))*1/RAM_used_10;
    pc.printf("alpha %f\r\n",alpha);
    double beta = 1/alpha*log(double(RAM_used_10-1));
    pc.printf("beta %f\r\n",beta);
    while (j<=(RAM_used_10)) {
        P[j] = 1.0/(1.0+exp(-(j-beta)*alpha));
        f10[j] = frequency0*(1-P[j]) + frequency1*P[j];
        j += 1;
    }
    f10[0]              = frequency0;
    f10[RAM_used_10]    = frequency1;
    pc.printf("P(0) = %f P(RAM_used) = %f \r\n", P[0], P[RAM_used_10]);*/
    
    // ### calculation of RSCW-words ### 
    uint64_t RSCW0 = RSCW_func(ram0_00, ram1_00, trise_00);
    uint64_t RSCW1 = RSCW_func(ram0_10, ram1_10, trise_10);
    uint64_t RSCW2 = RSCW_func(501, 501, 10.0e-6);
    
    // ### initialize both channels on the first intermediate frequency and write into their RAM

    ch_1();
   
    DDS.CFR1_write(0x00000200);
    DDS.FTW0_write(FTWO_func(frequency0));
    /* Taken out for PHASE RAMP TEST
    writeRSCW1(ram0_10, ram1_10, RSCW1, f10);
    writeRSCW0(ram0_00, ram1_00, RSCW0, f00); 
    writeRSCW2(501, 501, RSCW2, frequency_init);
    */
    
    ch_2();

    DDS.CFR1_write(0x00000200);
    DDS.FTW0_write(FTWO_func(frequency0));
    /* Taken out for PHASE RAMP TEST
    writeRSCW1(ram0_10, ram1_10, RSCW1, f10); 
    writeRSCW0(ram0_00, ram1_00, RSCW0, f00);
    writeRSCW2(501, 501, RSCW2, frequency_init);
    */

    //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");
    
    char up_or_down = '0';
    double trise = trise_00;
    
    
    while(1) {
            if(pc.readable()) {
                up_or_down = pc.getc();
                if(up_or_down == 'a') {
                    while(1) {
                        start_ramp(trise, tstay);
                        wait(2e-2);
                        if(pc.readable()) break;
                        }
                    //start_ramp(trise, tstay);
                    //pc.printf("sequence over ST \r \n");
                    }
                if(up_or_down == 'p') {
                    double trisephase = 1e-3;
                    int r0phase = 0;
                    int r1phase = 1;
                    double phase0 = 0;
                    double phase1 = 359;
                 
                    uint64_t RSCWphase = RSCW_func(r0phase, r1phase, trisephase);
                    int         RAM_used_phase    = r1phase-r0phase; 
                    double      phase_array [RAM_used_phase+1]; 
                    
                    j = 0;
                    while (j<=(RAM_used_phase)) {
                        phase_array[j] = phase0 + (phase1-phase0)/trisephase*j*trisephase/(RAM_used_phase);
                        j += 1;
                    }
                    ch_1();
                    writePhaseRAM(r0phase,r1phase,RSCWphase,phase_array);//(int r0, int r1, uint32_t RSCW, double f[])
                    DDS.CFR1_write(0xC0000200);
                    
                    while(1) {
                        ps0 = 0;
                        trigger = 0;
                        ps0 = 1;
                        trigger = 1;
                        wait(2e-2);
                        ps0 = 0;
                        trigger = 0;
                        if(pc.readable()) break;
                        }
                    //start_ramp(trise, tstay);
                    //pc.printf("sequence over ST \r \n");
                    }       
                /*if (up_or_down == 'r') {
                    pc.printf("enter new time value in us: \n");
                    pc.scanf("%lf", &trise);
                    trise = trise*1.0e-6;
                    initialize(frequency0, frequency1, RAM_start, RAM_final, trise);
                    check_down();
                    }*/
                 if (up_or_down == 't') {
                    pc.printf("enter new tstay value in us: \n");
                    pc.scanf("%lf", &tstay);
                    tstay = tstay*1.0e-6;
                    }
                if (up_or_down == 'u') {
                        pc.printf("u");
                        trigger = 1;
                        wait(trise/4.0);
                        trigger = 0;
                         /////
                        ps0 = 1;
                        ps1 = 0;
                         /////
                        }
               if (up_or_down == 'd') {
                        pc.printf("d");
                        trigger = 1;
                        wait(trise/4.0);
                        trigger = 0;
                        /////
                        ps0 = 0;
                        ps1 = 0;
                        /////
                         }
                if (up_or_down == '1') {
                    trigger = 0;
                    trigger = 1;
                    /*ps0 = 0;
                    ch_2(); DDS.CFR1_write(0x00000200);
                    ch_1(); DDS.CFR1_write(0x80000200);*/
                    check_down();
                    trigger = 0;
                    pc.printf("ramping channel 1 \r\n");
                    }
                if (up_or_down == '2') {
                    trigger = 0;
                    trigger = 1;
                    /*ps0 = 0;
                    ch_1(); DDS.CFR1_write(0x00000200);
                    ch_2(); DDS.CFR1_write(0x80000200);*/
                    check_up();
                    trigger = 0;
                    pc.printf("ramping channel 2 \r\n");
                    }
                /*if (up_or_down == 's') {
                    pc.printf("enter new frequency0 value in MHz: \n");
                    pc.scanf("%lf", &frequency0);
                    frequency0 = frequency0*1.0e6;
                    initialize(frequency0, frequency1, RAM_start, RAM_final, trise);
                    }*/
                /*if (up_or_down == 'e') {
                    pc.printf("enter new frequency1 value in MHz: \n");
                    pc.scanf("%lf", &frequency1);
                    frequency1 = frequency1*1.0e6;
                    initialize(frequency0, frequency1, RAM_start, RAM_final, trise);
                    }*/
            }
            mcs.rise(&check_up);
            mcs.fall(&check_down);
            if(mexp) {
                    while(mexp);
                    start_ramp(trise, tstay);
                   // pc.printf(" exp trigger in registered \r \n");
                }
    }
   
    return 0;
}