Library for the JRO Radar Controller

Dependents:   JRO_CR2 frdm_test

CR2.cpp

Committer:
joaquinbvw
Date:
2016-03-14
Revision:
0:e3f3fe2e689b

File content as of revision 0:e3f3fe2e689b:

#include "CR2.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  "};

CR2::CR2(SPI *spi_dev, DigitalOut *mreset, DigitalOut *outramp, DigitalOut *spmode, DigitalOut *cs, DigitalOut *ioreset, DigitalInOut *updclk){
    
    spi_device      = spi_dev;
    
    cr2_mreset      = mreset;
    cr2_outramp     = outramp;
    cr2_sp_mode     = spmode;
    cr2_cs          = cs;
    cr2_io_reset    = ioreset;
    cr2_updclk      = updclk;
    
    cr2_updclk->input();
    *cr2_sp_mode = 0;
    *cr2_cs = 1;
    *cr2_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 CR2::__writeData(char addr, char data){
    
    // I/O reset
    *cr2_updclk = 0;
    *cr2_io_reset = 1;
    wait_us(10);
    *cr2_io_reset = 0;
    wait_us(10);
    
    *cr2_cs = 0;
    
    //Sending serial address
    //printf("\r\nWriting Addr = %d", addr);
    spi_device->write(addr | 0x80);
    wait_us(150);
    spi_device->write(data);
    
    *cr2_cs = 1;
    /*
    for(char i = 0; i < ndata; i++)
    {
        printf("\tData[%d] = 0x%x", i, data[i]);
    }
    */
    
    
    wait_us(10);
    *cr2_updclk = 1;
    wait_us(10);
    *cr2_updclk = 0;
    wait_us(10);
    
    return 1;
}

int CR2::writeBlock(char ndata, const char* data){
    
    // I/O reset
    *cr2_updclk = 0;
    *cr2_io_reset = 1;
    wait_us(10);
    *cr2_io_reset = 0;
    wait_us(10);
    
    *cr2_cs = 0;
    
    for(char i = 0; i < (ndata/2); i++)
    {
        wait_us(150);
        char addr = data[2*i];
        char dat = data[2*i+1];
        this->__writeData(addr,dat);
    }
    
    *cr2_cs = 1;
    /*
    for(char i = 0; i < ndata; i++)
    {
        printf("\tData[%d] = 0x%x", i, data[i]);
    }
    */
    
    
    wait_us(10);
    *cr2_updclk = 1;
    wait_us(10);
    *cr2_updclk = 0;
    wait_us(10);
    
    if (ndata%2)
    {
        return 0;
    }
    else
    {
        return 1;
    }
}

char CR2::__readData(char addr){
    
    char spi_data = 0;
    // I/O reset
    *cr2_io_reset = 1;
    wait_us(10);
    *cr2_io_reset = 0;
    wait_us(10);
    
    *cr2_cs = 0;
    
    //Sending serial address
    //printf("\r\nReading Addr = %d", addr);
    spi_device->write(addr & 0x7F);
    
    wait_us(150);
    spi_data = spi_device->write(0x00);
    
    *cr2_cs = 1;
    /*
    for(char i = 0; i < ndata; i++)
    {
        printf("\r\nData[%d] = 0x%x", i, read_spi_data[i]);
    } 
    */
    
    wait_us(10);
    
    return spi_data;
    }

int CR2::__writeDataAndVerify(char addr, char wr_spi_data, SerialDriver *screen){
    
    int    success;
    char  rd_spi_data;
    
    this->__writeData(addr, wr_spi_data);
    rd_spi_data = this->__readData(addr);
    
    success = 1;
    
    screen->putc(wr_spi_data);
    screen->putc(0x3D);
    screen->putc(rd_spi_data);
    if (wr_spi_data != rd_spi_data)
    {
        success = 0;
    }
    
    //Update Control Register
    /*
    if ((success == 1) && (addr==0x07)){
        cr2_multiplier = rd_spi_data[1] & 0x1F;
        cr2_mode = (rd_spi_data[2] & 0x0E) >> 1;
    }
    */
    //printf("\r\nSuccessful writting = %d\r\n", success);
    
    return success;
}
/*
char* CR2::__getControlRegister(){
    
    bool pll_range = 0;
    bool pll_bypass = 1;
    
    if (cr2_multiplier >= 4){
        pll_bypass = 0;
    }

    if (clock >= 200){
        pll_range = 1;
    }
       
    controlRegister[0] = 0x10 + cr2_qdac_pwdn*4;
    controlRegister[1] = pll_range*64 + pll_bypass*32 + (cr2_multiplier & 0x1F);
    controlRegister[2] = (cr2_mode & 0x07)*2 + cr2_ioupdclk;
    controlRegister[3] = cr2_inv_sinc*64 + cr2_osk_en*32 + cr2_osk_int*16 + cr2_msb_lsb*2 + cr2_sdo;
    
    return controlRegister;
    
    }
    
int CR2::__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, wr_spi_data);
    
    ////printf("\r\nChanging UPD_CLK as an OUTPUT ...");
    cr2_updclk->output();
    
    wait_us(100);
    *cr2_updclk = 1;
    wait_us(10);
    *cr2_updclk = 0;
    wait_us(10);
    
    rd_spi_data = this->__readData(addr);
    
    success = true;
    
    for(char i = 0; i < ndata; i++)
    {
        if (wr_spi_data[i] != rd_spi_data[i])
        {
            success = false;
            break;
        }
    }
    
    return success;
}   
*/
                    
int CR2::reset(){
    
    // Master reset
    //Set as a input, temporary
    //printf("\r\nChange updclk direction as an INPUT ...\r\n");
    cr2_updclk->input();
    cr2_updclk->mode(PullDown);
    
    //printf("\r\nReseting CR2 ...\r\n");
    *cr2_mreset = 1;
    wait_ms(1);
    *cr2_mreset = 0;
    wait_ms(1);
    
    this->rf_enabled = false;
    
    return 0;
    }
    
int CR2::scanIOUpdate(){
    
    unsigned int cont = 0;
    
    this->reset();
    
    //printf("\r\nWaiting a upd_clk ...\r\n");
    while(true){
        if (*cr2_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 CR2::find(){
    /*
    char phase[];
    
    phase[0] = 0x0A;
    phase[1] = 0x55;
    
    this->__writeDataAndVerify(0x00, 5, phase);
    */
    this->__readData(0x05);
    this->__readData(0x0A);
    return 1;
    
    }
    
    
int CR2::init(){
    
    //printf("\r\nSetting default parameters in CR ...\r\n");
    
    //Serial mode enabled
    this->clock = 200.0;        // Work clock in MHz
    this->cr2_multiplier = 4;        // Multiplier 4- 20
    this->cr2_mode = 0;              // Single, FSK, Ramped FSK, Chirp, BPSK
    this->cr2_qdac_pwdn = 0;         // QDAC power down enabled: 0 -> disable
    this->cr2_ioupdclk = 0;          // IO Update clock direction: 0 -> input,  1 -> output
    this->cr2_inv_sinc  = 0;         // Sinc inverser filter enable: 0 -> enable
    this->cr2_osk_en = 1;            // Enable Amplitude multiplier: 0 -> disabled
    this->cr2_osk_int = 0;           // register/counter output shaped control: 0 -> register, 1 -> counter
    this->cr2_msb_lsb = 0;           // msb/lsb bit first: 0 -> MSB, 1 -> LSB
    this->cr2_sdo = 1;               // SDO pin active: 0 -> inactive

    //printf("\r\nSetting in serial mode ...\r\n");
    *cr2_sp_mode = 0;
    *cr2_cs = 1;
     
    this->reset();
    
    //printf("\r\nWritting CR ...\r\n");
    /*
    if (not this->__writeControlRegister()){
        //printf("\r\nUnsuccessful CR2 initialization");
        this->isConfig = false;
        return false;
        }
        */
    //printf("\r\nSuccessfull CR2 initialization");
    
    this->isConfig = true;
    
    return true;
}
/*
char* CR2::rdMode(){
    
    char* rd_data;
    char mode;
    
    rd_data = this->__readData(0x07);
    mode = (rd_data[2] & 0x0E) >> 1;
    
    this->cr2_mode = mode;
    
    rd_data[0] = mode;
    
    return rd_data;
    }
    
char* CR2::rdMultiplier(){
    
    char* rd_data;
    char mult;
    
    rd_data = this->__readData(0x07);
    mult = (rd_data[1] & 0x1F);
    this->cr2_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* CR2::rdPhase1(){

    char* rd_data;
    
    rd_data = this->__readData(0x00);
    
    return rd_data;
    
    }
char* CR2::rdPhase2(){

    char* rd_data;
    
    rd_data = this->__readData(0x01);
    
    return rd_data;
    }
char* CR2::rdFrequency1(){

    char* rd_data;
    
    rd_data = this->__readData(0x02);
    
    for (int i=0; i<6; i++)
        frequency1[i] = rd_data[i];
    
    return rd_data;
    
    }
char* CR2::rdFrequency2(){

    char* rd_data;
    
    rd_data = this->__readData(0x03);
    
    for (int i=0; i<6; i++)
        frequency2[i] = rd_data[i];
        
    return rd_data;
    }
char* CR2::rdAmplitudeI(){

    char* rd_data;
    
    rd_data = this->__readData(0x08);
    
    return rd_data;
    }
char* CR2::rdAmplitudeQ(){

    char* rd_data;
    
    rd_data = this->__readData(0x09);
    
    return rd_data;
    }

int CR2::isRFEnabled(){
    
    if (this->rf_enabled)
        return 1;
    
    return 0;
    }
    
int CR2::wrMode(char mode){
    
    this->cr2_mode = mode & 0x07;
    
    return this->__writeControlRegister();
    }

int CR2::wrMultiplier(char multiplier, float clock){
    
    this->cr2_multiplier = multiplier & 0x1F;
    this->clock = clock;
    
    //printf("\r\n mult = %d, clock = %f", multiplier, clock);
    //printf("\r\n cr2_mult = %d", cr2_multiplier);
    
    return this->__writeControlRegister();
    }
        
int CR2::wrPhase1(char* phase, SerialDriver *screen){
    
    return this->__writeDataAndVerify(0x00, phase, screen);
    
    }
    
int CR2::wrPhase2(char* phase, SerialDriver *screen){
    
    return this->__writeDataAndVerify(0x01, phase, screen);
    
    }
    
int CR2::wrFrequency1(char* freq, SerialDriver *screen){
    int sts;
    
    sts =  this->__writeDataAndVerify(0x02, freq, screen);
    
    if (sts){
        for (int i=0; i<6; i++)
            frequency1[i] = freq[i];
    }
    return sts;
    
    }
int CR2::wrFrequency2(char* freq, SerialDriver *screen){
    int sts;
    
    sts = this->__writeDataAndVerify(0x03, freq, screen);
    
    if (sts){
        for (int i=0; i<6; i++)
            frequency2[i] = freq[i];
    }
    return sts;
    }

int CR2::wrAmplitudeI(char* amplitude, SerialDriver *screen){
    
    amplitudeI[0] = amplitude[0];
    amplitudeI[1] = amplitude[1];
    
    this->rf_enabled = true;
    
    return this->__writeDataAndVerify(0x08, amplitude, screen);
    
    }

int CR2::wrAmplitudeQ(char* amplitude, SerialDriver *screen){
    
    amplitudeQ[0] = amplitude[0];
    amplitudeQ[1] = amplitude[1];
     
    this->rf_enabled = true;
    
    return this->__writeDataAndVerify(0x09, amplitude, screen);
    
    }

int CR2::enableRF(){
    
    this->rf_enabled = true;
    
    this->__writeDataAndVerify(0x08, this->amplitudeI);
    return this->__writeDataAndVerify(0x09, this->amplitudeQ);

    }

int CR2::disableRF(){
    
    this->rf_enabled = false;
    
    this->__writeDataAndVerify(0x08, "\x00\x00");
    return this->__writeDataAndVerify(0x09, "\x00\x00");
    
    }
       
int CR2::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* CR2::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 CR2 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 CR2_CMD_RESET:
            success = this->init();
            break;
            
        case CR2_CMD_ENABLE_RF:
            if (payload_len == 1){
                //if (payload[0] == 0)
                    //success = this->disableRF();
                //else
                    //success = this->enableRF();
            }
            break;
            
        case CR2_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 CR2_CMD_MODE:
            if (payload_len == 1){
                //success = this->wrMode(payload[0]);
            }
            break;
            
        case CR2_CMD_FREQUENCYA:
            if (payload_len == 6){
                //success = this->wrFrequency1(payload);
            }
            break;
            
        case CR2_CMD_FREQUENCYB:
            if (payload_len == 6){
                //success = this->wrFrequency2(payload);
            }
            break;
            
        case CR2_CMD_PHASEA:
            if (payload_len == 2){
                //success = this->wrPhase1(payload);
            }
            break;
            
        case CR2_CMD_PHASEB:
            if (payload_len == 2){
                //success = this->wrPhase2(payload);
            }
            break;

        case CR2_CMD_AMPLITUDE1:
            if (payload_len == 2){
                //success = this->wrAmplitudeI(payload);
            }
            break;

        case CR2_CMD_AMPLITUDE2:
            if (payload_len == 2){
                //success = this->wrAmplitudeQ(payload);
            }
            break;

        case CR2_CMD_READ | CR2_CMD_ENABLE_RF:
            //if (this->isRFEnabled() == 1)
            //    tx_msg = ONE_MSG;
            //else
            //    tx_msg = ZERO_MSG;
                
            tx_msg_len = 1;
            
            break;
            
        case CR2_CMD_READ | CR2_CMD_MULTIPLIER:
            //tx_msg = this->rdMultiplier();
            tx_msg_len = 1;
            break;
            
        case CR2_CMD_READ | CR2_CMD_MODE:
            //tx_msg = this->rdMode();
            tx_msg_len = 1;
            break;
            
        case CR2_CMD_READ | CR2_CMD_FREQUENCYA:
            //tx_msg = this->rdFrequency1();
            tx_msg_len = 6;
            break;
            
        case CR2_CMD_READ | CR2_CMD_FREQUENCYB:
            //tx_msg = this->rdFrequency2();
            tx_msg_len = 6;
            break;
            
        case CR2_CMD_READ | CR2_CMD_PHASEA:
            //tx_msg = this->rdPhase1();
            tx_msg_len = 2;
            break;
            
        case CR2_CMD_READ | CR2_CMD_PHASEB:
            //tx_msg = this->rdPhase2();
            tx_msg_len = 2;
            break;

        case CR2_CMD_READ | CR2_CMD_AMPLITUDE1:
            //tx_msg = this->rdAmplitudeI();
            tx_msg_len = 2;
            break;

        case CR2_CMD_READ | CR2_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* CR2::getCmdAnswer(){
    
    return this->cmd_answer;
    
    }
    
unsigned long CR2::getCmdAnswerLen(){
    
    return this->cmd_answer_len;
    
    }
/*
int CR2::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;     //cr2_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;     //cr2_sdo enable = 1
    
    this->__writeDataAndVerify(0x04, delta_freq);
    this->__writeDataAndVerify(0x05, upd_rate_clk);
    this->__writeDataAndVerify(0x06, ramp_rate_clk);
    this->__writeDataAndVerify(0x07, control_reg);
    
    this->__writeDataAndVerify(0x0A, ampl_ramp_rate);
    this->__writeDataAndVerify(0x0B, 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 CR2::wasInitialized(){
    
    return this->isConfig;
}

char CR2::getMultiplier(){
    return this->cr2_multiplier;
}

double CR2::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->cr2_multiplier);
    
    return factor_freq1;
}

double CR2::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->cr2_multiplier);
    
    return factor_freq2;
}

char CR2::getMode(){
    return this->cr2_mode;   
}

char* CR2::getModeStr(){
    
    if (this->cr2_mode > 4)
        return MODULATION[5];
    
    return MODULATION[this->cr2_mode];   
}