DDS AD9854, library to configure a AD9854 Serial Interface (SPI)

Dependents:   JRO_DDSv2 JRO_DDSv2_rev2019

Revision:
0:156a9e15919e
Child:
1:d81fca2297fb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AD9854.cpp	Tue Feb 24 20:08:13 2015 +0000
@@ -0,0 +1,774 @@
+#include "AD9854.h"
+
+static char controlRegister[4];
+static char read_spi_data[6];
+
+static char* KO_MSG = "KO";
+static char* OK_MSG = "OK";
+static char* NI_MSG = "NI";
+
+static char* ZERO_MSG = "\x00";
+static char* ONE_MSG = "\x01";
+
+static char *MODULATION[6] = {"None         ", "FSK          ", "Ramped FSK   ", "Chirp        ", "BPSK         ", "Not Allowed  "};
+
+DDS::DDS(SPI *spi_dev, DigitalOut *mreset, DigitalOut *outramp, DigitalOut *spmode, DigitalOut *cs, DigitalOut *ioreset, DigitalInOut *updclk){
+    
+    spi_device      = spi_dev;
+    
+    dds_mreset      = mreset;
+    dds_outramp     = outramp;
+    dds_sp_mode     = spmode;
+    dds_cs          = cs;
+    dds_io_reset    = ioreset;
+    dds_updclk      = updclk;
+    
+    dds_updclk->input();
+    *dds_sp_mode = 0;
+    *dds_cs = 1;
+    *dds_outramp = 0;
+    
+    cmd_answer = NULL;
+    cmd_answer_len = 0;
+    
+    spi_device->format(SPI_BITS, SPI_MODE);
+    spi_device->frequency(SPI_FREQ);
+    
+    this->isConfig = false;
+    
+}
+    
+int DDS::__writeData(char addr, char ndata, const char* data){
+    
+    // I/O reset
+    *dds_updclk = 0;
+    *dds_io_reset = 1;
+    wait_us(10);
+    *dds_io_reset = 0;
+    wait_us(10);
+    
+    *dds_cs = 0;
+    
+    //Sending serial address
+    //printf("\r\nWriting Addr = %d", addr);
+    spi_device->write(addr & 0x0F);
+    
+    for(char i = 0; i < ndata; i++)
+    {
+        wait_us(150);
+        spi_device->write(data[i]);
+    }
+       
+    *dds_cs = 1;
+    /*
+    for(char i = 0; i < ndata; i++)
+    {
+        printf("\tData[%d] = 0x%x", i, data[i]);
+    }
+    */
+    
+    
+    wait_us(10);
+    *dds_updclk = 1;
+    wait_us(10);
+    *dds_updclk = 0;
+    wait_us(10);
+    
+    return 1;
+}
+
+
+char* DDS::__readData(char addr, char ndata){
+    
+    // I/O reset
+    *dds_io_reset = 1;
+    wait_us(10);
+    *dds_io_reset = 0;
+    wait_us(10);
+    
+    *dds_cs = 0;
+    
+    //Sending serial address
+    //printf("\r\nReading Addr = %d", addr);
+    spi_device->write((addr & 0x0F) | 0x80);
+    
+    for(char i = 0; i < ndata; i++)
+    {
+        wait_us(150);
+        read_spi_data[i] = spi_device->write(0x00);
+    }
+    
+    *dds_cs = 1;
+    /*
+    for(char i = 0; i < ndata; i++)
+    {
+        printf("\r\nData[%d] = 0x%x", i, read_spi_data[i]);
+    } 
+    */
+    
+    wait_us(10);
+    
+    return read_spi_data;
+    }
+
+int DDS::__writeDataAndVerify(char addr, char ndata, const char* wr_spi_data, SerialDriver *screen){
+    
+    int    success;
+    char*  rd_spi_data;
+    
+    this->__writeData(addr, ndata, wr_spi_data);
+    rd_spi_data = this->__readData(addr, ndata);
+    
+    success = 1;
+    
+    for(char i = 0; i < ndata; i++)
+    {
+        if (screen != NULL){
+            screen->putc(wr_spi_data[i]);
+            screen->putc(0x3D);
+            screen->putc(rd_spi_data[i]);
+        }
+        
+        if (wr_spi_data[i] != rd_spi_data[i])
+        {
+            success = 0;
+            break;
+        }
+        
+    }
+    
+    //Update Control Register
+    if ((success == 1) && (addr==0x07)){
+        cr_multiplier = rd_spi_data[1] & 0x1F;
+        cr_mode = (rd_spi_data[2] & 0x0E) >> 1;
+    }
+    //printf("\r\nSuccessful writting = %d\r\n", success);
+    
+    return success;
+}
+
+char* DDS::__getControlRegister(){
+    
+    bool pll_range = 0;
+    bool pll_bypass = 1;
+    
+    if (cr_multiplier >= 4){
+        pll_bypass = 0;
+    }
+
+    if (clock >= 200){
+        pll_range = 1;
+    }
+       
+    controlRegister[0] = 0x10 + cr_qdac_pwdn*4;
+    controlRegister[1] = pll_range*64 + pll_bypass*32 + (cr_multiplier & 0x1F);
+    controlRegister[2] = (cr_mode & 0x07)*2 + cr_ioupdclk;
+    controlRegister[3] = cr_inv_sinc*64 + cr_osk_en*32 + cr_osk_int*16 + cr_msb_lsb*2 + cr_sdo;
+    
+    return controlRegister;
+    
+    }
+    
+int DDS::__writeControlRegister(){
+    
+    bool            success;
+    char*  wr_spi_data;
+    char*  rd_spi_data;
+    char   addr = 0x07, ndata = 4;
+    
+    wr_spi_data = this->__getControlRegister();
+    
+    success = this->__writeData(addr, ndata, wr_spi_data);
+    
+    ////printf("\r\nChanging UPD_CLK as an OUTPUT ...");
+    dds_updclk->output();
+    
+    wait_us(100);
+    *dds_updclk = 1;
+    wait_us(10);
+    *dds_updclk = 0;
+    wait_us(10);
+    
+    rd_spi_data = this->__readData(addr, ndata);
+    
+    success = true;
+    
+    for(char i = 0; i < ndata; i++)
+    {
+        if (wr_spi_data[i] != rd_spi_data[i])
+        {
+            success = false;
+            break;
+        }
+    }
+    
+    return success;
+}   
+
+                    
+int DDS::reset(){
+    
+    // Master reset
+    //Set as a input, temporary
+    //printf("\r\nChange updclk direction as an INPUT ...\r\n");
+    dds_updclk->input();
+    dds_updclk->mode(PullDown);
+    
+    //printf("\r\nReseting DDS ...\r\n");
+    *dds_mreset = 1;
+    wait_ms(1);
+    *dds_mreset = 0;
+    wait_ms(1);
+    
+    this->rf_enabled = false;
+    
+    return 0;
+    }
+    
+int DDS::scanIOUpdate(){
+    
+    unsigned int cont = 0;
+    
+    this->reset();
+    
+    //printf("\r\nWaiting a upd_clk ...\r\n");
+    while(true){
+        if (*dds_updclk == 1)
+            break;
+        
+        cont += 1;
+        if (cont > 10000)
+            break;
+            
+        wait_us(1);
+    }
+    
+    if (cont > 10000){
+        //printf("\r\nA upd_clk was not found\r\n");
+        return 0;
+    }
+    
+    //printf("\r\nA upd_clk was found ...\r\n");
+    
+    return 1;
+    }
+    
+int DDS::find(){
+    /*
+    char phase[];
+    
+    phase[0] = 0x0A;
+    phase[1] = 0x55;
+    
+    this->__writeDataAndVerify(0x00, 5, phase);
+    */
+    this->__readData(0x05, 4);
+    this->__readData(0x0A, 1);
+    return 1;
+    
+    }
+    
+    
+int DDS::init(){
+    
+    //printf("\r\nSetting default parameters in CR ...\r\n");
+    
+    //Serial mode enabled
+    this->clock = 200.0;        // Work clock in MHz
+    this->cr_multiplier = 4;        // Multiplier 4- 20
+    this->cr_mode = 0;              // Single, FSK, Ramped FSK, Chirp, BPSK
+    this->cr_qdac_pwdn = 0;         // QDAC power down enabled: 0 -> disable
+    this->cr_ioupdclk = 0;          // IO Update clock direction: 0 -> input,  1 -> output
+    this->cr_inv_sinc  = 0;         // Sinc inverser filter enable: 0 -> enable
+    this->cr_osk_en = 1;            // Enable Amplitude multiplier: 0 -> disabled
+    this->cr_osk_int = 0;           // register/counter output shaped control: 0 -> register, 1 -> counter
+    this->cr_msb_lsb = 0;           // msb/lsb bit first: 0 -> MSB, 1 -> LSB
+    this->cr_sdo = 1;               // SDO pin active: 0 -> inactive
+
+    //printf("\r\nSetting in serial mode ...\r\n");
+    *dds_sp_mode = 0;
+    *dds_cs = 1;
+     
+    this->reset();
+    
+    //printf("\r\nWritting CR ...\r\n");
+    
+    if (not this->__writeControlRegister()){
+        //printf("\r\nUnsuccessful DDS initialization");
+        this->isConfig = false;
+        return false;
+        }
+        
+    //printf("\r\nSuccessfull DDS initialization");
+    
+    this->isConfig = true;
+    
+    return true;
+}
+
+char* DDS::rdMode(){
+    
+    char* rd_data;
+    char mode;
+    
+    rd_data = this->__readData(0x07, 4);
+    mode = (rd_data[2] & 0x0E) >> 1;
+    
+    this->cr_mode = mode;
+    
+    rd_data[0] = mode;
+    
+    return rd_data;
+    }
+    
+char* DDS::rdMultiplier(){
+    
+    char* rd_data;
+    char mult;
+    
+    rd_data = this->__readData(0x07, 4);
+    mult = (rd_data[1] & 0x1F);
+    this->cr_multiplier = mult;
+    
+    //Reaconditioning data to return
+    rd_data[0] = mult;
+    rd_data[1] = ((int)clock >> 8) & 0xff; 
+    rd_data[2] = (int)clock & 0xff; 
+    
+    return rd_data;    
+    }
+char* DDS::rdPhase1(){
+
+    char* rd_data;
+    
+    rd_data = this->__readData(0x00, 2);
+    
+    return rd_data;
+    
+    }
+char* DDS::rdPhase2(){
+
+    char* rd_data;
+    
+    rd_data = this->__readData(0x01, 2);
+    
+    return rd_data;
+    }
+char* DDS::rdFrequency1(){
+
+    char* rd_data;
+    
+    rd_data = this->__readData(0x02, 6);
+    
+    for (int i=0; i<6; i++)
+        frequency1[i] = rd_data[i];
+    
+    return rd_data;
+    
+    }
+char* DDS::rdFrequency2(){
+
+    char* rd_data;
+    
+    rd_data = this->__readData(0x03, 6);
+    
+    for (int i=0; i<6; i++)
+        frequency2[i] = rd_data[i];
+        
+    return rd_data;
+    }
+char* DDS::rdAmplitudeI(){
+
+    char* rd_data;
+    
+    rd_data = this->__readData(0x08, 2);
+    
+    return rd_data;
+    }
+char* DDS::rdAmplitudeQ(){
+
+    char* rd_data;
+    
+    rd_data = this->__readData(0x09, 2);
+    
+    return rd_data;
+    }
+
+int DDS::isRFEnabled(){
+    
+    if (this->rf_enabled)
+        return 1;
+    
+    return 0;
+    }
+    
+int DDS::wrMode(char mode){
+    
+    this->cr_mode = mode & 0x07;
+    
+    return this->__writeControlRegister();
+    }
+
+int DDS::wrMultiplier(char multiplier, float clock){
+    
+    this->cr_multiplier = multiplier & 0x1F;
+    this->clock = clock;
+    
+    //printf("\r\n mult = %d, clock = %f", multiplier, clock);
+    //printf("\r\n cr_mult = %d", cr_multiplier);
+    
+    return this->__writeControlRegister();
+    }
+        
+int DDS::wrPhase1(char* phase, SerialDriver *screen){
+    
+    return this->__writeDataAndVerify(0x00, 2, phase, screen);
+    
+    }
+    
+int DDS::wrPhase2(char* phase, SerialDriver *screen){
+    
+    return this->__writeDataAndVerify(0x01, 2, phase, screen);
+    
+    }
+    
+int DDS::wrFrequency1(char* freq, SerialDriver *screen){
+    int sts;
+    
+    sts =  this->__writeDataAndVerify(0x02, 6, freq, screen);
+    
+    if (sts){
+        for (int i=0; i<6; i++)
+            frequency1[i] = freq[i];
+    }
+    return sts;
+    
+    }
+int DDS::wrFrequency2(char* freq, SerialDriver *screen){
+    int sts;
+    
+    sts = this->__writeDataAndVerify(0x03, 6, freq, screen);
+    
+    if (sts){
+        for (int i=0; i<6; i++)
+            frequency2[i] = freq[i];
+    }
+    return sts;
+    }
+
+int DDS::wrAmplitudeI(char* amplitude, SerialDriver *screen){
+    
+    amplitudeI[0] = amplitude[0];
+    amplitudeI[1] = amplitude[1];
+    
+    this->rf_enabled = true;
+    
+    return this->__writeDataAndVerify(0x08, 2, amplitude, screen);
+    
+    }
+
+int DDS::wrAmplitudeQ(char* amplitude, SerialDriver *screen){
+    
+    amplitudeQ[0] = amplitude[0];
+    amplitudeQ[1] = amplitude[1];
+     
+    this->rf_enabled = true;
+    
+    return this->__writeDataAndVerify(0x09, 2, amplitude, screen);
+    
+    }
+
+int DDS::enableRF(){
+    
+    this->rf_enabled = true;
+    
+    this->__writeDataAndVerify(0x08, 2, this->amplitudeI);
+    return this->__writeDataAndVerify(0x09, 2, this->amplitudeQ);
+
+    }
+
+int DDS::disableRF(){
+    
+    this->rf_enabled = false;
+    
+    this->__writeDataAndVerify(0x08, 2, "\x00\x00");
+    return this->__writeDataAndVerify(0x09, 2, "\x00\x00");
+    
+    }
+       
+int DDS::defaultSettings(SerialDriver *screen){
+    
+    if (!(screen == NULL)){
+        screen->putc(0x37);
+        screen->putc(0x30);
+    }
+    
+    this->wrMultiplier(1, 0.0);
+    this->wrAmplitudeI("\x0F\xC0", screen);                //0xFC0 produces best SFDR than 0xFFF
+    this->wrAmplitudeQ("\x0F\xC0");                        //0xFC0 produces best SFDR than 0xFFF    
+    this->wrFrequency1("\x00\x00\x00\x00\x00\x00");        // 49.92 <> 0x3f 0xe5 0xc9 0x1d 0x14 0xe3 <> 49.92/clock*(2**48) \x3f\xe5\xc9\x1d\x14\xe3
+    this->wrFrequency2("\x00\x00\x00\x00\x00\x00");
+    this->wrPhase1("\x00\x00");                            //0 grados
+    this->wrPhase2("\x20\x00");                            //180 grados <> 0x20 0x00 <> 180/360*(2**14)
+    this->disableRF();
+        
+    if (!(screen == NULL)){
+        screen->putc(0x37);
+        screen->putc(0x31);
+    }
+    
+    return this->wrMode(4);                                //BPSK mode
+    
+    }
+    
+char* DDS::setCommand(unsigned short cmd, char* payload, unsigned long payload_len){
+    
+    bool success = false;    
+    char* tx_msg;
+    unsigned long tx_msg_len;
+    
+    tx_msg = KO_MSG;
+    tx_msg_len = 2;
+    
+    //printf("cmd = %d, payload_len = %d", cmd, payload_len);
+
+    //printf("\r\nPayload = ");
+    //for(unsigned long i=0; i< payload_len; i++)
+        //printf("0x%x ", payload[i]);
+    
+    //Si el DDS no esta inicializado siempre retornar NI_MSG
+    if (not this->isConfig){
+        this->cmd_answer = NI_MSG;
+        this->cmd_answer_len = 2;
+        
+        return this->cmd_answer;
+    }
+    
+    switch ( cmd )
+      {
+        case DDS_CMD_RESET:
+            success = this->init();
+            break;
+            
+        case DDS_CMD_ENABLE_RF:
+            if (payload_len == 1){
+                if (payload[0] == 0)
+                    success = this->disableRF();
+                else
+                    success = this->enableRF();
+            }
+            break;
+            
+        case DDS_CMD_MULTIPLIER:
+            if (payload_len == 1){
+                success = this->wrMultiplier(payload[0]);
+            }
+            if (payload_len == 3){
+                unsigned short clock = payload[1]*256 + payload[2];
+                success = this->wrMultiplier(payload[0], (float)clock);
+            }
+            break;
+            
+        case DDS_CMD_MODE:
+            if (payload_len == 1){
+                success = this->wrMode(payload[0]);
+            }
+            break;
+            
+        case DDS_CMD_FREQUENCYA:
+            if (payload_len == 6){
+                success = this->wrFrequency1(payload);
+            }
+            break;
+            
+        case DDS_CMD_FREQUENCYB:
+            if (payload_len == 6){
+                success = this->wrFrequency2(payload);
+            }
+            break;
+            
+        case DDS_CMD_PHASEA:
+            if (payload_len == 2){
+                success = this->wrPhase1(payload);
+            }
+            break;
+            
+        case DDS_CMD_PHASEB:
+            if (payload_len == 2){
+                success = this->wrPhase2(payload);
+            }
+            break;
+
+        case DDS_CMD_AMPLITUDE1:
+            if (payload_len == 2){
+                success = this->wrAmplitudeI(payload);
+            }
+            break;
+
+        case DDS_CMD_AMPLITUDE2:
+            if (payload_len == 2){
+                success = this->wrAmplitudeQ(payload);
+            }
+            break;
+
+        case DDS_CMD_READ | DDS_CMD_ENABLE_RF:
+            if (this->isRFEnabled() == 1)
+                tx_msg = ONE_MSG;
+            else
+                tx_msg = ZERO_MSG;
+                
+            tx_msg_len = 1;
+            
+            break;
+            
+        case DDS_CMD_READ | DDS_CMD_MULTIPLIER:
+            tx_msg = this->rdMultiplier();
+            tx_msg_len = 1;
+            break;
+            
+        case DDS_CMD_READ | DDS_CMD_MODE:
+            tx_msg = this->rdMode();
+            tx_msg_len = 1;
+            break;
+            
+        case DDS_CMD_READ | DDS_CMD_FREQUENCYA:
+            tx_msg = this->rdFrequency1();
+            tx_msg_len = 6;
+            break;
+            
+        case DDS_CMD_READ | DDS_CMD_FREQUENCYB:
+            tx_msg = this->rdFrequency2();
+            tx_msg_len = 6;
+            break;
+            
+        case DDS_CMD_READ | DDS_CMD_PHASEA:
+            tx_msg = this->rdPhase1();
+            tx_msg_len = 2;
+            break;
+            
+        case DDS_CMD_READ | DDS_CMD_PHASEB:
+            tx_msg = this->rdPhase2();
+            tx_msg_len = 2;
+            break;
+
+        case DDS_CMD_READ | DDS_CMD_AMPLITUDE1:
+            tx_msg = this->rdAmplitudeI();
+            tx_msg_len = 2;
+            break;
+
+        case DDS_CMD_READ | DDS_CMD_AMPLITUDE2:
+            tx_msg = this->rdAmplitudeQ();
+            tx_msg_len = 2;
+            break;
+            
+        default:
+            success = false;
+        
+      }
+    
+    if (success){
+        tx_msg = OK_MSG;
+        tx_msg_len = 2;
+        }
+    
+    this->cmd_answer = tx_msg;
+    this->cmd_answer_len = tx_msg_len;
+    
+    return tx_msg;
+}
+
+char* DDS::getCmdAnswer(){
+    
+    return this->cmd_answer;
+    
+    }
+    
+unsigned long DDS::getCmdAnswerLen(){
+    
+    return this->cmd_answer_len;
+    
+    }
+
+int DDS::setAllDevice(char* payload, SerialDriver *screen){
+    
+    int sts;
+    char* phase1, *phase2;
+    char* freq1, *freq2;
+    char* delta_freq, *upd_rate_clk, *ramp_rate_clk;
+    char* control_reg;
+    char* amplitudeI, *amplitudeQ, *ampl_ramp_rate;
+    char* qdac;
+    
+    phase1 = &payload[0x00];
+    phase2 = &payload[0x02];
+    freq1 = &payload[0x04];
+    freq2 = &payload[0x0A];
+    delta_freq = &payload[0x10];
+    upd_rate_clk = &payload[0x16];
+    ramp_rate_clk = &payload[0x1A];
+    control_reg = &payload[0x1D];
+    amplitudeI = &payload[0x21];
+    amplitudeQ = &payload[0x23];
+    ampl_ramp_rate = &payload[0x25];
+    qdac = &payload[0x26];
+    
+    control_reg[2] = control_reg[2] & 0xFE;     //cr_ioupdclk always as an input = 0
+    control_reg[3] = control_reg[3] & 0xFD;     //LSB first = 0, MSB first enabled
+    control_reg[3] = control_reg[3] | 0x01;     //cr_sdo enable = 1
+    
+    this->__writeDataAndVerify(0x04, 6, delta_freq);
+    this->__writeDataAndVerify(0x05, 4, upd_rate_clk);
+    this->__writeDataAndVerify(0x06, 3, ramp_rate_clk);
+    this->__writeDataAndVerify(0x07, 4, control_reg);
+    
+    this->__writeDataAndVerify(0x0A, 1, ampl_ramp_rate);
+    this->__writeDataAndVerify(0x0B, 2, qdac, screen);  
+
+    this->wrPhase1(phase1);
+    this->wrPhase2(phase2);
+    this->wrFrequency1(freq1);
+    this->wrFrequency2(freq2);
+    this->wrAmplitudeI(amplitudeI);
+    this->wrAmplitudeQ(amplitudeQ);
+    
+    //Enabling RF
+    sts = this->enableRF();
+    
+    return sts;
+    
+    }
+
+bool DDS::wasInitialized(){
+    
+    return this->isConfig;
+}
+
+char DDS::getMultiplier(){
+    return this->cr_multiplier;
+}
+
+double DDS::getFreqFactor1(){
+    factor_freq1 = ((double)frequency1[0])/256.0 + ((double)frequency1[1])/65536.0  + ((double)frequency1[2])/16777216.0 + ((double)frequency1[3])/4294967296.0;
+    factor_freq1 *= ((double)this->cr_multiplier);
+    
+    return factor_freq1;
+}
+
+double DDS::getFreqFactor2(){
+    factor_freq2 = ((double)frequency2[0])/256.0 + ((double)frequency2[1])/65536.0  + ((double)frequency2[2])/16777216.0 + ((double)frequency2[3])/4294967296.0;
+    factor_freq2 *= ((double)this->cr_multiplier);
+    
+    return factor_freq2;
+}
+
+char DDS::getMode(){
+    return this->cr_mode;   
+}
+
+char* DDS::getModeStr(){
+    
+    if (this->cr_mode > 4)
+        return MODULATION[5];
+    
+    return MODULATION[this->cr_mode];   
+}
\ No newline at end of file