firstTest

Dependencies:   mbed lib_sx9500 SX127x lib_mpl3115a2 lib_mma8451q lib_gps libscpi

scpi-def.cpp

Committer:
bongkwan
Date:
2020-04-14
Revision:
0:1aa6d4a96bf1
Child:
1:96123698b488

File content as of revision 0:1aa6d4a96bf1:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "scpi/scpi.h"
#include "scpi-def.h"

//#include "sx12xx.h"
#include "sx127x_lora.h"
#include "sx127x_fsk.h"

/******************************************************************************/
#ifdef TARGET_MOTE_L152RC
#include "gps.h"
#include "mma8451q.h"
#include "mpl3115a2.h"
#include "sx9500.h"

#define RFSW1                    PC_4 //NorAm_Mote RFSwitch_CNTR_1
#define RFSW2                    PC_13 //NorAm_Mote RFSwitch_CNTR_2
#define RADIO_RESET              PC_2 //NorAm_Mote Reset_sx
#define RADIO_MOSI               PB_15 //NorAm_Mote SPI2 Mosi
#define RADIO_MISO               PB_14 //NorAm_Mote SPI2 Miso
#define RADIO_SCLK               PB_13 //NorAm_Mote  SPI2 Clk
#define RADIO_NSS                PB_12 //NorAm_Mote SPI2 Nss
#define RADIO_DIO_0              PC_6 //NorAm_Mote DIO0 
#define RADIO_DIO_1              PC_10 //NorAm_Mote DIO1
#define RADIO_DIO_2              PC_8 //NorAm_Mote DIO2 
#define RADIO_DIO_3              PB_4 //NorAm_Mote DIO3 
#define RADIO_DIO_4              PB_5 //NorAm_Mote DIO4 
#define RADIO_DIO_5              PB_6 //NorAm_Mote DIO5

SPI spi(RADIO_MOSI, RADIO_MISO, RADIO_SCLK);
//             dio0, dio1, nss, spi, rst
SX127x radio(RADIO_DIO_0, RADIO_DIO_1, RADIO_NSS, spi, RADIO_RESET);

DigitalOut rfsw1(RFSW1);
DigitalOut rfsw2(RFSW2);

void rfsw_callback()
{
    if (radio.RegOpMode.bits.Mode == RF_OPMODE_TRANSMITTER) {  // start of transmission
        //if (radio.HF)
        if (radio.RegPaConfig.bits.PaSelect) { // if PA_BOOST
            rfsw2 = 0;
            rfsw1 = 1;
        } else { // RFO to power amp
            rfsw2 = 1;
            rfsw1 = 0;            
        }
        //hdr_fem_csd = 1;    //debug
    } else if (radio.RegOpMode.bits.Mode == RF_OPMODE_RECEIVER || radio.RegOpMode.bits.Mode == RF_OPMODE_CAD) { // start of reception
        //if (radio.HF)
        rfsw2 = 1;
        rfsw1 = 1;
        //hdr_fem_csd = 0;    //debug
    } else { // RF switch shutdown
        rfsw2 = 0;
        rfsw1 = 0;     
        //hdr_fem_csd = 0;    //debug         
    }
}

DigitalOut pd2(PD_2);

DigitalIn dio2_pin(RADIO_DIO_2);
DigitalIn dio3_pin(RADIO_DIO_3);
DigitalIn dio4_pin(RADIO_DIO_4);
DigitalIn dio5_pin(RADIO_DIO_5);

AnalogIn *bat;
#define AIN_VREF        3.3     // stm32 internal refernce
#define AIN_VBAT_DIV    2       // resistor divider

/*  gps(tx, rx, en); */
DigitalOut gps_en(PB_11);
GPS gps(PB_6, PB_7, PB_11);
uint32_t gps_coord_cnt;

DigitalIn i2c_int_pin(PB_4);
I2C i2c(I2C_SDA, I2C_SCL);
MMA8451Q mma8451q(i2c, i2c_int_pin);
MPL3115A2 mpl3115a2(i2c, i2c_int_pin);
SX9500 sx9500(i2c, PA_9, PA_10);

typedef enum {
    MOTE_NONE = 0,
    MOTE_V2,
    MOTE_V3
} mote_version_e;
mote_version_e mote_version = MOTE_NONE;

DigitalOut pc_7(PC_7);
DigitalIn pc_1(PC_1);
#else // sx1276 shield...

SPI spi(D11, D12, D13); // mosi, miso, sclk
//           dio0, dio1, nss, spi, rst
SX127x radio(  D2,   D3, D10, spi, A0); // sx1276 arduino shield

#ifdef TARGET_LPC11U6X
DigitalOut rfsw(P0_23);
#else
DigitalOut rfsw(A4);    // for SX1276 arduino shield
#endif

void rfsw_callback()
{
    if (radio.RegOpMode.bits.Mode == RF_OPMODE_TRANSMITTER)
        rfsw = 1;
    else
        rfsw = 0;
}

DigitalIn dio2_pin(D4);
DigitalIn dio3_pin(D5);
DigitalIn dio4_pin(A3);
DigitalIn dio5_pin(D9);

#endif /* !TARGET_MOTE_L152RC */

SX127x_fsk fsk(radio);
SX127x_lora lora(radio);

volatile bool tx_busy = false;

bool is_lora()
{
    radio.RegOpMode.octet = radio.read_reg(REG_OPMODE);
    return radio.RegOpMode.bits.LongRangeMode;
}

void
service_radio()
{
    service_action_e act;
    
    if (radio.RegOpMode.bits.LongRangeMode) {
        act = lora.service();
        switch (act) {
            case SERVICE_READ_FIFO:
                //printf("lora SERVICE_READ_FIFO\r\n");
                SCPI_RegSetBits(&scpi_context, SCPI_REG_QUES, 0x200);    // bit 9 for packet received
                break;
            case SERVICE_TX_DONE:
                tx_busy = false;
                break;
            case SERVICE_ERROR:
            case SERVICE_NONE:
                break;
        } // ...switch (act)
    } else {
        /* FSK: */
        act = fsk.service();     
        switch (act) {
            case SERVICE_READ_FIFO:
                SCPI_RegSetBits(&scpi_context, SCPI_REG_QUES, 0x200);    // bit 9 for packet received
                break;            
            case SERVICE_TX_DONE:
                tx_busy = false;
                break;
            case SERVICE_ERROR:
            case SERVICE_NONE:
                break;
        } // ...switch (act)           
    }
    
#ifdef TARGET_MOTE_L152RC
    gps.service();
    if (gps.LatitudeBinary != 0) {
        gps.LatitudeBinary = 0;
        //printf("gps long:%f, lat:%f  Vbat:%.2fV\r\n", gps.Longitude, gps.Latitude, ain_bat->read()*AIN_VREF*AIN_VBAT_DIV);
        gps_coord_cnt++;
    }    
#endif /* TARGET_MOTE_L152RC */
}

scpi_result_t tx_busyQ(scpi_t * context)
{
    SCPI_ResultBool(context, tx_busy);
    return SCPI_RES_OK;
}

scpi_result_t SCPI_Reset(scpi_t * context)
{
    radio.hw_reset();
    printf("**Reset\r\n");
    tx_busy = false;
    return SCPI_RES_OK;
}

const scpi_choice_def_t pa_selects[] = {
    { "RFO", 0 },
    { "PA_BOOST", 1 },       
    SCPI_CHOICE_LIST_END
};

scpi_result_t radio_PASelect(scpi_t* context)
{
    int32_t value;
    
    if (!SCPI_ParamChoice(context, pa_selects, &value, TRUE))
        return SCPI_RES_ERR;  
        
    radio.RegPaConfig.octet = radio.read_reg(REG_PACONFIG);
    radio.RegPaConfig.bits.PaSelect = value;
    radio.write_reg(REG_PACONFIG, radio.RegPaConfig.octet);
    
    if (radio.RegOpMode.bits.Mode == RF_OPMODE_TRANSMITTER)
        rfsw_callback();    
    
    return SCPI_RES_OK;
}
    
scpi_result_t radio_PASelectQ(scpi_t* context)
{
    int idx;
    
    radio.RegPaConfig.octet = radio.read_reg(REG_PACONFIG);
    idx = radio.RegPaConfig.bits.PaSelect;
        
    SCPI_ResultText(context, pa_selects[idx].name);
    return SCPI_RES_OK;    
}

const scpi_choice_def_t modulations[] = {
    { "FSK", 1 },
    { "OOK", 2 },
    { "LORa", 3 },        
    SCPI_CHOICE_LIST_END
};

scpi_result_t radio_modulation(scpi_t* context)
{
    int32_t value;
    
    /* scpi_bool_t SCPI_ParamChoice(scpi_t * context, const scpi_choice_def_t * options, int32_t * value, scpi_bool_t mandatory); */
    if (!SCPI_ParamChoice(context, modulations, &value, TRUE))
        return SCPI_RES_ERR;

    radio.RegOpMode.octet = radio.read_reg(REG_OPMODE);
    if (value == 3) {
        if (!radio.RegOpMode.bits.LongRangeMode)
            lora.enable();
    } else {
        if (radio.RegOpMode.bits.LongRangeMode)
            fsk.enable(false);
        if (radio.RegOpMode.bits.ModulationType) { // radio is OOK
            if (value == 1) {   // change to FSK
                radio.RegOpMode.bits.ModulationType = 0;
                radio.write_reg(REG_OPMODE, radio.RegOpMode.octet);
            }
        } else { // radio is FSK
            if (value == 2) {   // change to OOK
                radio.RegOpMode.bits.ModulationType = 1;
                radio.write_reg(REG_OPMODE, radio.RegOpMode.octet);
            }
        }
    }
 
   return SCPI_RES_OK;
}

scpi_result_t radio_modulationQ(scpi_t* context)
{
    int idx;
    
    if (is_lora()) {
        idx = 2;    // lora
    } else {
        if (radio.RegOpMode.bits.ModulationType)
            idx = 1;    // ook
        else
            idx = 0;    // fsk
    }
    
    SCPI_ResultText(context, modulations[idx].name);
    return SCPI_RES_OK;
}

scpi_result_t fsk_fdev(scpi_t* context)
{
    int32_t i;
    
    if (!SCPI_ParamInt(context, &i, TRUE))
        return SCPI_RES_ERR;
            
    if (is_lora())
        return SCPI_RES_ERR;
        
    fsk.set_tx_fdev_hz(i);
    return SCPI_RES_OK;
}

scpi_result_t fsk_fdevQ(scpi_t* context)
{
    if (is_lora())
        return SCPI_RES_ERR;
        
    SCPI_ResultInt(context, fsk.get_tx_fdev_hz());    
    return SCPI_RES_OK;      
}

const scpi_choice_def_t rxtrigs[] = {
    { "OFF", 0 },
    { "RSSI", 1 },
    { "PRE", 6 },        
    { "BOTH", 7 },          
    SCPI_CHOICE_LIST_END
};

scpi_result_t fsk_rxtrig(scpi_t* context)
{
    int32_t value;
    
    if (is_lora())
        return SCPI_RES_ERR;
        
    if (!SCPI_ParamChoice(context, rxtrigs, &value, TRUE))
        return SCPI_RES_ERR;           
        
    fsk.RegRxConfig.octet = radio.read_reg(REG_FSK_RXCONFIG);       
    fsk.RegRxConfig.bits.RxTrigger = value;
    radio.write_reg(REG_FSK_RXCONFIG, fsk.RegRxConfig.octet);
    return SCPI_RES_OK;
}

scpi_result_t fsk_rxtrigQ(scpi_t* context)
{
    int idx;
    
    if (is_lora())
        return SCPI_RES_ERR;    
        
    fsk.RegRxConfig.octet = radio.read_reg(REG_FSK_RXCONFIG);
    idx = fsk.RegRxConfig.bits.RxTrigger;
    SCPI_ResultText(context, rxtrigs[idx].name);
    return SCPI_RES_OK;             
}

scpi_result_t fsk_bt(scpi_t* context)
{
    double bt;    
    
    if (is_lora())
        return SCPI_RES_ERR;        
    
    if (!SCPI_ParamDouble(context, &bt, TRUE))
        return SCPI_RES_ERR; 
                
    if (bt < 0.2)                
        radio.RegOpMode.bits.ModulationShaping = 0; // no shaping
    else if (bt < 0.4)
        radio.RegOpMode.bits.ModulationShaping = 3; // BT0.3  (most shaping)
    else if (bt < 0.9)
        radio.RegOpMode.bits.ModulationShaping = 2; // BT0.5
    else
        radio.RegOpMode.bits.ModulationShaping = 1; // BT1.0
        
    radio.write_reg(REG_OPMODE, radio.RegOpMode.octet);       
    return SCPI_RES_OK;    
}

scpi_result_t fsk_btQ(scpi_t* context)
{
    double bt;
    
    if (is_lora())
        return SCPI_RES_ERR;        
        
    switch (radio.RegOpMode.bits.ModulationShaping) {
        case 0: bt = 0.0; break;
        case 1: bt = 1.0; break;
        case 2: bt = 0.5; break;
        case 3: bt = 0.3; break;
    }
    
    SCPI_ResultDouble(context, bt);
    return SCPI_RES_OK;    
}

const scpi_choice_def_t datamodes[] = {
    { "CONT", 0 },
    { "PKT", 1 },       
    SCPI_CHOICE_LIST_END
};

scpi_result_t fsk_datamode(scpi_t* context)
{
    int32_t value;
    
    if (!SCPI_ParamChoice(context, datamodes, &value, TRUE))
        return SCPI_RES_ERR;
            
    if (is_lora())
        return SCPI_RES_ERR;  
        
    fsk.RegPktConfig2.word = radio.read_u16(REG_FSK_PACKETCONFIG2);
    fsk.RegPktConfig2.bits.DataModePacket = value;
    radio.write_u16(REG_FSK_PACKETCONFIG2, fsk.RegPktConfig2.word);
    return SCPI_RES_OK;
}

scpi_result_t fsk_datamodeQ(scpi_t* context)
{
    int idx;
    
    if (is_lora())
        return SCPI_RES_ERR;       
    
    fsk.RegPktConfig2.word = radio.read_u16(REG_FSK_PACKETCONFIG2);
    idx = fsk.RegPktConfig2.bits.DataModePacket;    
    SCPI_ResultText(context, datamodes[idx].name);
    return SCPI_RES_OK;
}
  
const scpi_choice_def_t dcfrees[] = {
    { "OFF", 0 },
    { "MAN", 1 },
    { "WHIT", 2 },        
    SCPI_CHOICE_LIST_END
};

scpi_result_t fsk_dcfree(scpi_t* context)
{
    int32_t value;
        
    if (is_lora())
        return SCPI_RES_ERR;    
   
    if (!SCPI_ParamChoice(context, dcfrees, &value, TRUE))
        return SCPI_RES_ERR;        
        
    fsk.RegPktConfig1.octet = radio.read_reg(REG_FSK_PACKETCONFIG1);        
    fsk.RegPktConfig1.bits.DcFree = value;
    radio.write_reg(REG_FSK_PACKETCONFIG1, fsk.RegPktConfig1.octet);
    return SCPI_RES_OK;    
}

scpi_result_t fsk_dcfreeQ(scpi_t* context)
{
    int idx;
    
    if (is_lora())
        return SCPI_RES_ERR;
        
    fsk.RegPktConfig1.octet = radio.read_reg(REG_FSK_PACKETCONFIG1);        
    idx = fsk.RegPktConfig1.bits.DcFree ;
    SCPI_ResultText(context, dcfrees[idx].name);
    return SCPI_RES_OK;
}

scpi_result_t fsk_rxbw(scpi_t* context)
{
    int32_t i;
    
    if (!SCPI_ParamInt(context, &i, TRUE))
        return SCPI_RES_ERR; 
        
    if (is_lora())
        return SCPI_RES_ERR;
        
    fsk.set_rx_dcc_bw_hz(i, 0);
    return SCPI_RES_OK;
}

scpi_result_t fsk_rxbwQ(scpi_t* context)
{
    if (is_lora())
        return SCPI_RES_ERR;    
        
    SCPI_ResultInt(context, fsk.get_rx_bw_hz(REG_FSK_RXBW));    
    return SCPI_RES_OK;          
}

scpi_result_t fsk_afcbw(scpi_t* context)
{
    int32_t i;
    
    if (!SCPI_ParamInt(context, &i, TRUE))
        return SCPI_RES_ERR; 
        
    if (is_lora())        
        return SCPI_RES_ERR;
        
    fsk.set_rx_dcc_bw_hz(i, 1);
    return SCPI_RES_OK;
}

scpi_result_t fsk_afcbwQ(scpi_t* context)
{
    if (is_lora())    
        return SCPI_RES_ERR;    
        
    SCPI_ResultInt(context, fsk.get_rx_bw_hz(REG_FSK_AFCBW));    
    return SCPI_RES_OK;          
} 

scpi_result_t fsk_bitrate(scpi_t* context)
{
    int32_t i;
    
    if (!SCPI_ParamInt(context, &i, TRUE))
        return SCPI_RES_ERR;
            
    if (is_lora())            
        return SCPI_RES_ERR;    
        
    fsk.set_bitrate(i);
    return SCPI_RES_OK;     
}

scpi_result_t fsk_bitrateQ(scpi_t* context)
{
    if (is_lora())    
        return SCPI_RES_ERR;    
    
    SCPI_ResultInt(context, fsk.get_bitrate());    
    return SCPI_RES_OK;    
}

scpi_result_t fsk_prelen(scpi_t* context)
{
    int32_t i;
    
    if (!SCPI_ParamInt(context, &i, TRUE))
        return SCPI_RES_ERR;
        
    if (is_lora())        
        return SCPI_RES_ERR;     
        
    radio.write_u16(REG_FSK_PREAMBLEMSB, i); 
    return SCPI_RES_OK;          
}

scpi_result_t fsk_prelenQ(scpi_t* context)
{
    if (is_lora())    
        return SCPI_RES_ERR;     
        
    SCPI_ResultInt(context, radio.read_u16(REG_FSK_PREAMBLEMSB) );    
    return SCPI_RES_OK;      
} 

scpi_result_t fsk_sync(scpi_t* context)
{
    char buffer[100];
    size_t _copy_len, _len, i;
    uint8_t addr;
    uint8_t sync_size;
        
    if (is_lora())        
        return SCPI_RES_ERR;
        
    memset(buffer, 0, sizeof(buffer));    
    SCPI_ParamCopyText(context, buffer, 100, &_copy_len, false);
    for (_len = 0; buffer[_len] != 0; _len++)
        ;  
   
    fsk.RegSyncConfig.octet = radio.read_reg(REG_FSK_SYNCCONFIG);
    sync_size = 0;
    addr = REG_FSK_SYNCVALUE1;
    for (i = 0; i < _len; i+=2) {
        int o;
        sscanf(buffer+i, "%02x", &o);
        radio.write_reg(addr++, o);
        sync_size++;
    }    
    if (sync_size > 0)
        fsk.RegSyncConfig.bits.SyncSize = sync_size - 1;
        
    radio.write_reg(REG_FSK_SYNCCONFIG, fsk.RegSyncConfig.octet);
    
    return SCPI_RES_OK;
}

scpi_result_t fsk_syncQ(scpi_t* context)
{
    int i;
    char txt[64];
    char *ptr = txt;
    
    if (is_lora())    
        return SCPI_RES_ERR;
        
    fsk.RegSyncConfig.octet = radio.read_reg(REG_FSK_SYNCCONFIG);
    for (i = 0; i <= fsk.RegSyncConfig.bits.SyncSize; i++) {
        uint8_t o = radio.read_reg(i + REG_FSK_SYNCVALUE1);
        sprintf(ptr, "%02x", o);
        ptr += 2;
    }
    
    SCPI_ResultText(context, txt);
    return SCPI_RES_OK;
}

scpi_result_t radio_rssiQ(scpi_t* context)
{
    int reg_val;
    
    radio.RegOpMode.octet = radio.read_reg(REG_OPMODE);
    if (radio.RegOpMode.bits.Mode != RF_OPMODE_RECEIVER)
        return SCPI_RES_ERR;

    if (is_lora()) {
        reg_val = radio.read_reg(REG_LR_RSSIVALUE);    // 0x1b: dbm = -125 + regvalue
        SCPI_ResultDouble(context, -125 + reg_val);
    } else {
        reg_val = radio.read_reg(REG_FSK_RSSIVALUE);   // 0x11: dBm = -regvalue/2
        SCPI_ResultDouble(context, -reg_val/2.0);
    }
    
    return SCPI_RES_OK;
}

scpi_result_t radio_binFifo(scpi_t* context)
{
    size_t len;
    const char* buf = (const char *)radio.tx_buf;
             
     /*scpi_bool_t SCPI_ParamArbitraryBlock(scpi_t * context, const char ** value, size_t * len, scpi_bool_t mandatory);*/
     if (!SCPI_ParamArbitraryBlock(context, &buf, &len, TRUE))
        return SCPI_RES_ERR; 

    radio.RegPaConfig.octet = radio.read_reg(REG_PACONFIG); // pull PaSelect
    if (is_lora()) {
        lora.RegPayloadLength = len;
        radio.write_reg(REG_LR_PAYLOADLENGTH, lora.RegPayloadLength);
        lora.start_tx(lora.RegPayloadLength);        
    } else {
        fsk.start_tx(len);
    }    
    
    tx_busy = true;
    
    return SCPI_RES_OK;            
}

scpi_result_t radio_binFifoQ(scpi_t* context)
{
    size_t len;
    const char* buf = (const char *)radio.rx_buf;

    if (is_lora()) {
        len = lora.RegRxNbBytes;  
    } else {
        len = fsk.rx_buf_length;
    }
    
    //size_t SCPI_ResultArbitraryBlock(scpi_t * context, const char * data, size_t len);
    if (SCPI_ResultArbitraryBlock(context, buf, len) == len)
        return SCPI_RES_OK;    
    else
        return SCPI_RES_ERR; 
}

scpi_result_t radio_fifoQ(scpi_t* context)
{
    int i;
    char txt[520];
    char *ptr = txt;
        
    if (is_lora()) {
        for (i = 0; i < lora.RegRxNbBytes; i++) {
            sprintf(ptr, "%02x", radio.rx_buf[i]);
            ptr += 2;
        }        
    } else {
        for (i = 0; i < fsk.rx_buf_length; i++) {
            sprintf(ptr, "%02x", radio.rx_buf[i]);
            ptr += 2;
        }   
    }
    
    SCPI_ResultText(context, txt);
    return SCPI_RES_OK;
}

scpi_result_t radio_fifo(scpi_t* context)
{
    char buffer[100];
    size_t copy_len, i, len;
    
    if (tx_busy)
        return SCPI_RES_ERR;
                
    memset(buffer, 0, sizeof(buffer));
    SCPI_ParamCopyText(context, buffer, 100, &copy_len, false);

    for (len = 0; buffer[len] != 0; len++)
        ;

    for (i = 0; i < len; i++)
        radio.tx_buf[i] = buffer[i];
    
    radio.RegPaConfig.octet = radio.read_reg(REG_PACONFIG);    
    if (is_lora()) {
        lora.RegPayloadLength = len;
        radio.write_reg(REG_LR_PAYLOADLENGTH, lora.RegPayloadLength);
        lora.start_tx(lora.RegPayloadLength);        
    } else {
        /* fsk todo */
        fsk.start_tx(len);
    }    
    
    tx_busy = true;
    
    return SCPI_RES_OK;    
}

const scpi_choice_def_t opmodes[] = {
    { "SLE", 0 },
    { "STB", 1 },
    { "FST", 2 },        
    { "TX", 3 },
    { "FSR", 4 },
    { "RXC", 5 },       
    { "RXS", 6 },         
    { "CAD", 7 },         
    SCPI_CHOICE_LIST_END
};

scpi_result_t radio_opmode(scpi_t* context)
{
    int32_t value;
    
    if (!SCPI_ParamChoice(context, opmodes, &value, TRUE))
        return SCPI_RES_ERR;    
 
    if (value == RF_OPMODE_TRANSMITTER)
        radio.RegPaConfig.octet = radio.read_reg(REG_PACONFIG);     // pull PaSelect
    else
        tx_busy = false;        
               
    radio.RegOpMode.octet = radio.read_reg(REG_OPMODE);   
    radio.set_opmode((chip_mode_e)value);

    return SCPI_RES_OK;        
}

scpi_result_t radio_opmodeQ(scpi_t* context)
{
    int idx;
    
    radio.RegOpMode.octet = radio.read_reg(REG_OPMODE);
    idx = radio.RegOpMode.bits.Mode;
    SCPI_ResultText(context, opmodes[idx].name);
    
    return SCPI_RES_OK;
}


/*scpi_result_t wbr_set_bit9(scpi_t* context)
{
    SCPI_RegSetBits(context, SCPI_REG_QUES, 0x200);
    printf("set bit9\r\n");
    return SCPI_RES_OK;
}*/
scpi_result_t radio_ocp(scpi_t* context)
{
    int32_t i;
    
    if (!SCPI_ParamInt(context, &i, TRUE))
        return SCPI_RES_ERR;     
        
    radio.RegOcp.octet = radio.read_reg(REG_OCP);
    if (i < 130)
        radio.RegOcp.bits.OcpTrim = (i - 45) / 5;
    else
        radio.RegOcp.bits.OcpTrim = (i + 30) / 10;
    radio.write_reg(REG_OCP, radio.RegOcp.octet);   
    return SCPI_RES_OK; 
}

scpi_result_t radio_ocpQ(scpi_t* context)
{
    int32_t i;
    
    radio.RegOcp.octet = radio.read_reg(REG_OCP);
    
    if (radio.RegOcp.bits.OcpTrim < 16)
        i = 45 + (5 * radio.RegOcp.bits.OcpTrim);
    else if (radio.RegOcp.bits.OcpTrim < 28)
        i = (10 * radio.RegOcp.bits.OcpTrim) - 30;
    else
        i = 240;    
        
    SCPI_ResultInt(context, i);    
    return SCPI_RES_OK;         
}

scpi_result_t radio_bgr(scpi_t* context)
{
    RegPdsTrim1_t pds_trim;
    int32_t i;
    
    if (!SCPI_ParamInt(context, &i, TRUE))
        return SCPI_RES_ERR;  
            
    if (radio.type == SX1276) {
        pds_trim.octet = radio.read_reg(REG_PDSTRIM1_SX1276);
        pds_trim.bits.prog_txdac = i;
        radio.write_reg(REG_PDSTRIM1_SX1276, pds_trim.octet);
    } else if (radio.type == SX1272) { 
        pds_trim.octet = radio.read_reg(REG_PDSTRIM1_SX1272);       
        pds_trim.bits.prog_txdac = i;
        radio.write_reg(REG_PDSTRIM1_SX1272, pds_trim.octet);
    } else
        return SCPI_RES_ERR; 
    
    return SCPI_RES_OK;
}

scpi_result_t radio_bgrQ(scpi_t* context)
{
    RegPdsTrim1_t pds_trim;
      
    if (radio.type == SX1276)
        pds_trim.octet = radio.read_reg(REG_PDSTRIM1_SX1276);    
    else if (radio.type == SX1272)
        pds_trim.octet = radio.read_reg(REG_PDSTRIM1_SX1272);
    else
        return SCPI_RES_ERR;
        
    SCPI_ResultInt(context, pds_trim.bits.prog_txdac);  
    return SCPI_RES_OK;        
}

scpi_result_t radio_lnaBoost(scpi_t* context)
{
    scpi_bool_t param1;
    
    if (!SCPI_ParamBool(context, &param1, TRUE))
        return SCPI_RES_ERR;
            
    radio.RegLna.octet = radio.read_reg(REG_LNA);  
    if (param1)
        radio.RegLna.bits.LnaBoostHF = 3;
    else
        radio.RegLna.bits.LnaBoostHF = 0;
        
    radio.write_reg(REG_LNA, radio.RegLna.octet);
    return SCPI_RES_OK;
}

scpi_result_t radio_lnaBoostQ(scpi_t* context)
{
    radio.RegLna.octet = radio.read_reg(REG_LNA);
    if (radio.RegLna.bits.LnaBoostHF)
        SCPI_ResultBool(context, 1);
    else
        SCPI_ResultBool(context, 0);
    
    return SCPI_RES_OK;     
}

scpi_result_t radio_power(scpi_t* context)
{
    int32_t i;
    
    if (!SCPI_ParamInt(context, &i, TRUE))
        return SCPI_RES_ERR;  
            
    radio.RegPaConfig.octet = radio.read_reg(REG_PACONFIG);
    radio.RegPaConfig.bits.OutputPower = i;
    radio.write_reg(REG_PACONFIG, radio.RegPaConfig.octet);

    return SCPI_RES_OK;    
}

scpi_result_t radio_powerQ(scpi_t* context)
{
    radio.RegPaConfig.octet = radio.read_reg(REG_PACONFIG);
    SCPI_ResultInt(context, radio.RegPaConfig.bits.OutputPower);  
    return SCPI_RES_OK;
}

scpi_result_t radio_diomap(scpi_t* context)
{
    int32_t dioN, map_value;
    
    if (!SCPI_ParamInt(context, &dioN, TRUE))
        return SCPI_RES_ERR;  
        
    if (!SCPI_ParamInt(context, &map_value, TRUE))
        return SCPI_RES_ERR;    
      
    if (dioN < 4) {
        radio.RegDioMapping1.octet = radio.read_reg(REG_DIOMAPPING1);
        switch (dioN) {
            case 0: radio.RegDioMapping1.bits.Dio0Mapping = map_value; break;
            case 1: radio.RegDioMapping1.bits.Dio1Mapping = map_value; break;
            case 2: radio.RegDioMapping1.bits.Dio2Mapping = map_value; break;
            case 3: radio.RegDioMapping1.bits.Dio3Mapping = map_value; break;
        } // ...switch (dioN)
        radio.write_reg(REG_DIOMAPPING1, radio.RegDioMapping1.octet);
    } else {
        radio.RegDioMapping2.octet = radio.read_reg(REG_DIOMAPPING2);
        switch (dioN) {
            case 4: radio.RegDioMapping2.bits.Dio4Mapping = map_value; break;
            case 5: radio.RegDioMapping2.bits.Dio5Mapping = map_value; break;
        } // ...switch (dioN)        
        radio.write_reg(REG_DIOMAPPING2, radio.RegDioMapping2.octet);
    }
    
    return SCPI_RES_OK;
}

scpi_result_t radio_diomapQ(scpi_t* context)
{
    int32_t dioN, map_value = -1;
    
    if (!SCPI_ParamInt(context, &dioN, TRUE))
        return SCPI_RES_ERR; 
        
    if (dioN < 4) {
        radio.RegDioMapping1.octet = radio.read_reg(REG_DIOMAPPING1);
        switch (dioN) {
            case 0: map_value = radio.RegDioMapping1.bits.Dio0Mapping; break;
            case 1: map_value = radio.RegDioMapping1.bits.Dio1Mapping; break;
            case 2: map_value = radio.RegDioMapping1.bits.Dio2Mapping; break;
            case 3: map_value = radio.RegDioMapping1.bits.Dio3Mapping; break;
        } // ...switch (dioN)        
    } else {
        radio.RegDioMapping2.octet = radio.read_reg(REG_DIOMAPPING2);
        switch (dioN) {
            case 4: map_value = radio.RegDioMapping2.bits.Dio4Mapping; break;
            case 5: map_value = radio.RegDioMapping2.bits.Dio5Mapping; break;
        } // ...switch (dioN)          
    }
    
    SCPI_ResultInt(context, map_value);
    return SCPI_RES_OK;    
}

scpi_result_t radio_reg(scpi_t* context)
{
    int32_t addr, data;

    if (!SCPI_ParamInt(context, &addr, TRUE))
        return SCPI_RES_ERR;  
        
    if (!SCPI_ParamInt(context, &data, TRUE))
        return SCPI_RES_ERR;  

    radio.write_reg(addr, data);
        
    return SCPI_RES_OK;
}

scpi_result_t radio_regQ(scpi_t* context)
{
    int32_t addr;
    
    if (!SCPI_ParamInt(context, &addr, TRUE))
        return SCPI_RES_ERR; 
     
    SCPI_ResultIntBase(context, radio.read_reg(addr), 16);
    return SCPI_RES_OK;     
}


scpi_result_t radio_dioQ(scpi_t* context)
{
    int32_t dioN, value = -1;
    
    if (!SCPI_ParamInt(context, &dioN, TRUE))
        return SCPI_RES_ERR;     
        
    switch (dioN) {
        case 0: value = radio.dio0.read(); break;
        case 1: value = radio.dio1.read(); break;
        case 2: value = dio2_pin.read(); break;
        case 3: value = dio3_pin.read(); break;
        case 4: value = dio4_pin.read(); break;
        case 5: value = dio5_pin.read(); break;
        default:      
            return SCPI_RES_ERR;          
    } // ..switch (dioN)      
    
    SCPI_ResultInt(context, value);
    return SCPI_RES_OK;    
}

scpi_result_t radio_freq(scpi_t* context)
{
    double MHz;
    
    if (!SCPI_ParamDouble(context, &MHz, TRUE))
        return SCPI_RES_ERR; 
    
    radio.set_frf_MHz(MHz);
    
    return SCPI_RES_OK;
}

scpi_result_t radio_freqQ(scpi_t* context)
{
    SCPI_ResultDouble(context, radio.get_frf_MHz());
    return SCPI_RES_OK;
}

scpi_result_t lora_cr(scpi_t* context)
{
    int32_t i;
    
    if (!SCPI_ParamInt(context, &i, TRUE))
        return SCPI_RES_ERR;

    if (!is_lora())            
        return SCPI_RES_ERR;    
        
    lora.setCodingRate(i);
    return SCPI_RES_OK;    
}

scpi_result_t lora_crQ(scpi_t* context)
{
    if (!is_lora())     
        return SCPI_RES_ERR;    

     SCPI_ResultInt(context, lora.getCodingRate(false));
     return SCPI_RES_OK;   
}  

scpi_result_t lora_invrx(scpi_t* context)
{
    scpi_bool_t param1;
    
    if (!SCPI_ParamBool(context, &param1, TRUE))
        return SCPI_RES_ERR;
            
    if (!is_lora())     
        return SCPI_RES_ERR;   
        
    lora.invert_rx(param1);
    return SCPI_RES_OK; 
}

scpi_result_t lora_invrxQ(scpi_t* context)
{
    if (!is_lora())     
        return SCPI_RES_ERR;   
        
    lora.RegTest33.octet = radio.read_reg(REG_LR_TEST33);
    SCPI_ResultBool(context, lora.RegTest33.bits.invert_i_q );
    return SCPI_RES_OK;                
}

scpi_result_t lora_invtx(scpi_t* context)
{
    scpi_bool_t param1;
    
    if (!SCPI_ParamBool(context, &param1, TRUE))
        return SCPI_RES_ERR;
            
    if (!is_lora())     
        return SCPI_RES_ERR;  
        
    lora.invert_tx(param1);
    return SCPI_RES_OK;           
}

scpi_result_t lora_invtxQ(scpi_t* context)
{
    if (!is_lora())     
        return SCPI_RES_ERR;  
        
    lora.RegTest33.octet = radio.read_reg(REG_LR_TEST33);
    SCPI_ResultBool(context, !lora.RegTest33.bits.chirp_invert_tx);        
    return SCPI_RES_OK;    
}

scpi_result_t lora_crc(scpi_t* context)
{
    scpi_bool_t param1;
    
    if (!SCPI_ParamBool(context, &param1, TRUE))
        return SCPI_RES_ERR;
            
    if (!is_lora())             
        return SCPI_RES_ERR;       

    lora.setRxPayloadCrcOn(param1);
    return SCPI_RES_OK;    
}

scpi_result_t lora_crcQ(scpi_t* context)
{
    if (!is_lora())     
        return SCPI_RES_ERR;   
        
    SCPI_ResultBool(context, lora.getRxPayloadCrcOn());
    return SCPI_RES_OK;         
}
 
scpi_result_t lora_ih(scpi_t* context)
{
    scpi_bool_t param1;
    
    if (!SCPI_ParamBool(context, &param1, TRUE))
        return SCPI_RES_ERR;
            
    if (!is_lora())             
        return SCPI_RES_ERR;    

    lora.setHeaderMode(param1);   
    return SCPI_RES_OK;    
}

scpi_result_t lora_ihQ(scpi_t* context)
{
    if (!is_lora())     
        return SCPI_RES_ERR;     
        
    SCPI_ResultBool(context, lora.getHeaderMode());
    return SCPI_RES_OK;
}

scpi_result_t lora_ldro(scpi_t* context)
{
    scpi_bool_t param1;
    
    if (!SCPI_ParamBool(context, &param1, TRUE))
        return SCPI_RES_ERR;

    if (!is_lora())             
        return SCPI_RES_ERR; 
        
    if (radio.type == SX1272) {
        lora.RegModemConfig.octet = radio.read_reg(REG_LR_MODEMCONFIG);
        lora.RegModemConfig.sx1272bits.LowDataRateOptimize = param1;
        radio.write_reg(REG_LR_MODEMCONFIG, lora.RegModemConfig.octet);
    } else if (radio.type == SX1276) {
        lora.RegModemConfig3.octet = radio.read_reg(REG_LR_MODEMCONFIG3);
        lora.RegModemConfig3.sx1276bits.LowDataRateOptimize = param1;
        radio.write_reg(REG_LR_MODEMCONFIG3, lora.RegModemConfig3.octet);
    } else
        return SCPI_RES_ERR; 
    
    return SCPI_RES_OK;                
}

scpi_result_t lora_ldroQ(scpi_t* context)
{
    scpi_bool_t param1;
    
    if (!is_lora())     
        return SCPI_RES_ERR;   
        
    if (radio.type == SX1272) {
        lora.RegModemConfig.octet = radio.read_reg(REG_LR_MODEMCONFIG);
        param1 = lora.RegModemConfig.sx1272bits.LowDataRateOptimize;
    } else if (radio.type == SX1276) {
        lora.RegModemConfig3.octet = radio.read_reg(REG_LR_MODEMCONFIG3);
        param1 = lora.RegModemConfig3.sx1276bits.LowDataRateOptimize;
    } else
        return SCPI_RES_ERR;         
        
    SCPI_ResultBool(context, param1);
    return SCPI_RES_OK;    
}

scpi_result_t lora_bw(scpi_t* context)
{
    double KHz;
        
    if (!is_lora())         
        return SCPI_RES_ERR;
        
    if (!SCPI_ParamDouble(context, &KHz, TRUE))
        return SCPI_RES_ERR;         
            
    lora.setBw_KHz(KHz);
    return SCPI_RES_OK;
}

scpi_result_t lora_bwQ(scpi_t* context)
{
    int bw;
    double khz;
    
    if (!is_lora()) 
        return SCPI_RES_ERR;
        
    bw = lora.getBw();
    
    if (radio.type == SX1272) {
        switch (bw) {
            case 0: khz = 125; break;
            case 1: khz = 250; break;
            case 2: khz = 500; break;                
            default: return SCPI_RES_ERR;
        }
    } else if (radio.type == SX1276) {
        switch (bw) {
            case 0: khz = 7.8; break;
            case 1: khz = 10.4; break;
            case 2: khz = 15.6; break;
            case 3: khz = 20.8; break;
            case 4: khz = 31.25; break;
            case 5: khz = 41.7; break;
            case 6: khz = 62.5; break;
            case 7: khz = 125; break;
            case 8: khz = 250; break;
            case 9: khz = 500; break;            
            default: return SCPI_RES_ERR;
        }
    } else
        return SCPI_RES_ERR;
    
    SCPI_ResultDouble(context, khz);
    return SCPI_RES_OK;    
}

scpi_result_t lora_sf(scpi_t* context)
{
    int32_t i;
        
    if (!is_lora())         
        return SCPI_RES_ERR;      
    
    if (!SCPI_ParamInt(context, &i, TRUE))
        return SCPI_RES_ERR;          
        
    lora.setSf(i);
    return SCPI_RES_OK; 
}

scpi_result_t lora_sfQ(scpi_t* context)
{
    if (!is_lora())     
        return SCPI_RES_ERR;    
        
     SCPI_ResultInt(context, lora.getSf());
     return SCPI_RES_OK; 
}

scpi_result_t lora_feiQ(scpi_t* context)
{
    if (!is_lora())     
        return SCPI_RES_ERR;     
        
    SCPI_ResultInt(context, lora.get_freq_error_Hz());    
    return SCPI_RES_OK;                
}

scpi_result_t lora_pktsnrQ(scpi_t* context)
{
    if (!is_lora())     
        return SCPI_RES_ERR;     
        
    SCPI_ResultDouble(context, lora.RegPktSnrValue / 4.0);
    return SCPI_RES_OK;                
}

scpi_result_t lora_pktrssiQ(scpi_t* context)
{
    if (!is_lora())     
        return SCPI_RES_ERR;
        
    SCPI_ResultDouble(context, lora.get_pkt_rssi());
    return SCPI_RES_OK;
}


scpi_result_t lora_prelen(scpi_t* context)
{
    int32_t i;
        
    if (!is_lora())         
        return SCPI_RES_ERR;
    
    if (!SCPI_ParamInt(context, &i, TRUE))
        return SCPI_RES_ERR;    
        
    lora.RegPreamble = i;
    radio.write_u16(REG_LR_PREAMBLEMSB, lora.RegPreamble);  
    return SCPI_RES_OK;       
}

scpi_result_t lora_prelenQ(scpi_t* context)
{
    if (!is_lora())     
        return SCPI_RES_ERR;
        
    lora.RegPreamble = radio.read_u16(REG_LR_PREAMBLEMSB);
    SCPI_ResultInt(context, lora.RegPreamble);    
    return SCPI_RES_OK;      
}

scpi_result_t lora_txc(scpi_t* context)
{
    scpi_bool_t param1;
    
    if (!is_lora())     
        return SCPI_RES_ERR;         
    
    if (!SCPI_ParamBool(context, &param1, TRUE))
        return SCPI_RES_ERR;
        
    lora.RegModemConfig2.octet = radio.read_reg(REG_LR_MODEMCONFIG2);        
    lora.RegModemConfig2.sx1276bits.TxContinuousMode = param1;
    radio.write_reg(REG_LR_MODEMCONFIG2, lora.RegModemConfig2.octet);    
    
    return SCPI_RES_OK;
}

scpi_result_t lora_txcQ(scpi_t* context)
{
    if (!is_lora())     
        return SCPI_RES_ERR;        
        
    lora.RegModemConfig2.octet = radio.read_reg(REG_LR_MODEMCONFIG2);        
    SCPI_ResultBool(context, lora.RegModemConfig2.sx1276bits.TxContinuousMode);
    
    return SCPI_RES_OK;    
}


#ifdef TARGET_MOTE_L152RC
scpi_result_t pd2_set(scpi_t* context)
{
    scpi_bool_t param1;
    
    if (!SCPI_ParamBool(context, &param1, TRUE))
        return SCPI_RES_ERR;

    pd2 = param1;
    return SCPI_RES_OK;
}

scpi_result_t pd2_get(scpi_t* context)
{
    SCPI_ResultBool(context, pd2.read());
    return SCPI_RES_OK;
}

scpi_result_t rfswQ(scpi_t* context)
{
    SCPI_ResultBool(context, rfsw1.read());
    SCPI_ResultBool(context, rfsw2.read());
    return SCPI_RES_OK;
}

scpi_result_t vbatQ(scpi_t* context)
{
    bool bat_flag = false;
    bool BatOffState;
    
    if(gps.en_invert == true)
        BatOffState = true;
    else
        BatOffState = false;
    
    if(gps_en == BatOffState)
    {
        bat_flag = true;
        gps.enable(1);
    }
        
    SCPI_ResultDouble(context, bat->read()*AIN_VREF*AIN_VBAT_DIV);
    
    if(bat_flag)
        gps.enable(0);
        
    return SCPI_RES_OK;      
}

scpi_result_t gps_enable(scpi_t* context)
{
    scpi_bool_t param1;
    
    if (!SCPI_ParamBool(context, &param1, TRUE))
        return SCPI_RES_ERR;    
        
    gps.enable(param1);
    return SCPI_RES_OK;
}

scpi_result_t gps_enableQ(scpi_t* context)
{
    SCPI_ResultBool(context, gps.enabled());
    
    return SCPI_RES_OK;      
}

scpi_result_t gps_numCords(scpi_t* context)
{
    int32_t i;
    
    if (!SCPI_ParamInt(context, &i, TRUE))
        return SCPI_RES_ERR;   
        
    gps_coord_cnt = i; 
    return SCPI_RES_OK;
}

scpi_result_t gps_numCordsQ(scpi_t* context)
{
    SCPI_ResultInt(context, gps_coord_cnt);    
    return SCPI_RES_OK;    
}

scpi_result_t gps_longitude(scpi_t* context)
{
    if (!SCPI_ParamDouble(context, &gps.Longitude, TRUE))
        return SCPI_RES_ERR;   
        
    return SCPI_RES_OK;         
}

scpi_result_t gps_longitudeQ(scpi_t* context)
{
    SCPI_ResultDouble(context, gps.Longitude);
    return SCPI_RES_OK;     
}

scpi_result_t gps_latitude(scpi_t* context)
{
    if (!SCPI_ParamDouble(context, &gps.Latitude, TRUE))
        return SCPI_RES_ERR;   
        
    return SCPI_RES_OK;           
}

scpi_result_t gps_latitudeQ(scpi_t* context)
{
    SCPI_ResultDouble(context, gps.Latitude);
    return SCPI_RES_OK; 
} 

scpi_result_t mma_idQ(scpi_t* context)
{
    SCPI_ResultIntBase(context, mma8451q.read_single(MMA8451_ID), 16);
    return SCPI_RES_OK;      
}

scpi_result_t mpl_idQ(scpi_t* context)
{
    SCPI_ResultIntBase(context, mpl3115a2.read(MPL3115_ID), 16);
    return SCPI_RES_OK;       
}

scpi_result_t sx9500_reset(scpi_t* context)
{
    sx9500.reset();
    return SCPI_RES_OK;
}

scpi_result_t sx9500_reg(scpi_t* context)
{
    int32_t addr, data;

    if (!SCPI_ParamInt(context, &addr, TRUE))
        return SCPI_RES_ERR;  
        
    if (!SCPI_ParamInt(context, &data, TRUE))
        return SCPI_RES_ERR;  

    sx9500.write(addr, data);
        
    return SCPI_RES_OK;
}

scpi_result_t sx9500_regQ(scpi_t* context)
{
    int32_t addr;
    
    if (!SCPI_ParamInt(context, &addr, TRUE))
        return SCPI_RES_ERR; 
     
    SCPI_ResultIntBase(context, sx9500.read_single(addr), 16);
    return SCPI_RES_OK;     
}

#endif /* TARGET_MOTE_L152RC */

static const scpi_command_t scpi_commands[] = {
    // http://na.support.keysight.com/pna/help/latest/Programming/GP-IB_Command_Finder/Common_Commands.htm
    /* IEEE Mandated Commands (SCPI std V1999.0 4.1.1) */
    { .pattern = "*CLS", .callback = SCPI_CoreCls,},    // clear status
    { .pattern = "*ESE", .callback = SCPI_CoreEse,},    // standard event status enable
    { .pattern = "*ESE?", .callback = SCPI_CoreEseQ,},
    { .pattern = "*ESR?", .callback = SCPI_CoreEsrQ,},  // event status query
    { .pattern = "*IDN?", .callback = SCPI_CoreIdnQ,},  // identification query
    { .pattern = "*OPC", .callback = SCPI_CoreOpc,},    // operation complete command
    { .pattern = "*OPC?", .callback = SCPI_CoreOpcQ,},  // operation complete query
    { .pattern = "*RST", .callback = SCPI_CoreRst,},    // reset command
    { .pattern = "*SRE", .callback = SCPI_CoreSre,},    // service request enable command
    { .pattern = "*SRE?", .callback = SCPI_CoreSreQ,},  // service request enable query
    { .pattern = "*STB?", .callback = SCPI_CoreStbQ,},  // status byte register query
    { .pattern = "*TST?", .callback = SCPI_CoreTstQ,},  // self-test query
    { .pattern = "*WAI", .callback = SCPI_CoreWai,},    // wait to continue

    /* Required SCPI commands (SCPI std V1999.0 4.2.1) */
    {.pattern = "SYSTem:ERRor[:NEXT]?", .callback = SCPI_SystemErrorNextQ,},
    {.pattern = "SYSTem:ERRor:COUNt?", .callback = SCPI_SystemErrorCountQ,},
    {.pattern = "SYSTem:VERSion?", .callback = SCPI_SystemVersionQ,},

    //{.pattern = "STATus:OPERation?", .callback = scpi_stub_callback,},
    //{.pattern = "STATus:OPERation:EVENt?", .callback = scpi_stub_callback,},
    //{.pattern = "STATus:OPERation:CONDition?", .callback = scpi_stub_callback,},
    //{.pattern = "STATus:OPERation:ENABle", .callback = scpi_stub_callback,},
    //{.pattern = "STATus:OPERation:ENABle?", .callback = scpi_stub_callback,},

    {.pattern = "STATus:QUEStionable[:EVENt]?", .callback = SCPI_StatusQuestionableEventQ,},
    //{.pattern = "STATus:QUEStionable:CONDition?", .callback = scpi_stub_callback,},
    {.pattern = "STATus:QUEStionable:ENABle", .callback = SCPI_StatusQuestionableEnable,},
    {.pattern = "STATus:QUEStionable:ENABle?", .callback = SCPI_StatusQuestionableEnableQ,},

    {.pattern = "STATus:PRESet", .callback = SCPI_StatusPreset,},

    /* DMM */
    /*   
    {.pattern = "SYSTem:COMMunication:TCPIP:CONTROL?", .callback = SCPI_SystemCommTcpipControlQ,},

    {.pattern = "TEST:BOOL", .callback = TEST_Bool,},
    {.pattern = "TEST#:NUMbers#", .callback = TEST_Numbers,},*/
    
    /*{.pattern = "TEST:CHOice?", .callback = TEST_ChoiceQ,},*/
    
    {.pattern = "BUSY?", .callback = tx_busyQ,},

    {.pattern = "RAdio:FIfo", .callback = radio_fifo,},
    {.pattern = "RAdio:FIfo?", .callback = radio_fifoQ,},
    {.pattern = "RAdio:BINFIfo", .callback = radio_binFifo,},
    {.pattern = "RAdio:BINFIfo?", .callback = radio_binFifoQ,},
    {.pattern = "RAdio:MODulation", .callback = radio_modulation,},
    {.pattern = "RAdio:MODulation?", .callback = radio_modulationQ,},
    {.pattern = "RAdio:RSSI?", .callback = radio_rssiQ,},
    {.pattern = "RAdio:OPmode", .callback = radio_opmode,},
    {.pattern = "RAdio:OPmode?", .callback = radio_opmodeQ,},
    {.pattern = "RAdio:PASelect", .callback = radio_PASelect,},
    {.pattern = "RAdio:PASelect?", .callback = radio_PASelectQ,},
    {.pattern = "RAdio:OCP", .callback = radio_ocp,},
    {.pattern = "RAdio:OCP?", .callback = radio_ocpQ,},
    {.pattern = "RAdio:POWer", .callback = radio_power,},
    {.pattern = "RAdio:POWer?", .callback = radio_powerQ,},
    {.pattern = "RAdio:BGR", .callback = radio_bgr,},
    {.pattern = "RAdio:BGR?", .callback = radio_bgrQ,},
    {.pattern = "RAdio:LNABoost", .callback = radio_lnaBoost,},
    {.pattern = "RAdio:LNABoost?", .callback = radio_lnaBoostQ,},    
    {.pattern = "RAdio:FREQuency", .callback = radio_freq,},
    {.pattern = "RAdio:FREQuency?", .callback = radio_freqQ,},
    {.pattern = "RAdio:DIOMap", .callback = radio_diomap,},
    {.pattern = "RAdio:DIOMap?", .callback = radio_diomapQ,},
    {.pattern = "RAdio:DIO?", .callback = radio_dioQ,},
    {.pattern = "RAdio:REGister", .callback = radio_reg,},
    {.pattern = "RAdio:REGister?", .callback = radio_regQ,},
       
    {.pattern = "RAdio:FSK:SYNC", .callback = fsk_sync,},
    {.pattern = "RAdio:FSK:SYNC?", .callback = fsk_syncQ,}, 
    {.pattern = "RAdio:FSK:FDev", .callback = fsk_fdev,},
    {.pattern = "RAdio:FSK:FDev?", .callback = fsk_fdevQ,}, 
    {.pattern = "RAdio:FSK:BITRate", .callback = fsk_bitrate,},
    {.pattern = "RAdio:FSK:BITRate?", .callback = fsk_bitrateQ,},     
    {.pattern = "RAdio:FSK:PRELen", .callback = fsk_prelen,},
    {.pattern = "RAdio:FSK:PRELen?", .callback = fsk_prelenQ,},  
    {.pattern = "RAdio:FSK:RXBW", .callback = fsk_rxbw,},
    {.pattern = "RAdio:FSK:RXBW?", .callback = fsk_rxbwQ,},        
    {.pattern = "RAdio:FSK:AFCBW", .callback = fsk_afcbw,},
    {.pattern = "RAdio:FSK:AFCBW?", .callback = fsk_afcbwQ,}, 
    {.pattern = "RAdio:FSK:DCFree", .callback = fsk_dcfree,},
    {.pattern = "RAdio:FSK:DCFree?", .callback = fsk_dcfreeQ,},       
    {.pattern = "RAdio:FSK:RXTrigger", .callback = fsk_rxtrig,},
    {.pattern = "RAdio:FSK:RXTrigger?", .callback = fsk_rxtrigQ,},     
    {.pattern = "RAdio:FSK:DATAMode", .callback = fsk_datamode,},
    {.pattern = "RAdio:FSK:DATAMode?", .callback = fsk_datamodeQ,}, 
    {.pattern = "RAdio:FSK:BT", .callback = fsk_bt,},
    {.pattern = "RAdio:FSK:BT?", .callback = fsk_btQ,},     
    
    {.pattern = "RAdio:LORa:BW", .callback = lora_bw,},
    {.pattern = "RAdio:LORa:BW?", .callback = lora_bwQ,},    
    {.pattern = "RAdio:LORa:SF", .callback = lora_sf,},
    {.pattern = "RAdio:LORa:SF?", .callback = lora_sfQ,},     
    {.pattern = "RAdio:LORa:TXContinuous", .callback = lora_txc,},
    {.pattern = "RAdio:LORa:TXContinuous?", .callback = lora_txcQ,},         
    {.pattern = "RAdio:LORa:PRELen", .callback = lora_prelen,},
    {.pattern = "RAdio:LORa:PRELen?", .callback = lora_prelenQ,},    
    {.pattern = "RAdio:LORa:CR", .callback = lora_cr,},
    {.pattern = "RAdio:LORa:CR?", .callback = lora_crQ,},      
    {.pattern = "RAdio:LORa:LDRO", .callback = lora_ldro,},
    {.pattern = "RAdio:LORa:LDRO?", .callback = lora_ldroQ,},
    {.pattern = "RAdio:LORa:FEI?", .callback = lora_feiQ,},         
    {.pattern = "RAdio:LORa:PKTSnr?", .callback = lora_pktsnrQ,},   
    {.pattern = "RAdio:LORa:PKTRssi?", .callback = lora_pktrssiQ,},     
    {.pattern = "RAdio:LORa:Ih", .callback = lora_ih,},
    {.pattern = "RAdio:LORa:Ih?", .callback = lora_ihQ,},        
    {.pattern = "RAdio:LORa:CRC", .callback = lora_crc,},
    {.pattern = "RAdio:LORa:CRC?", .callback = lora_crcQ,},  
    {.pattern = "RAdio:LORa:INVRx", .callback = lora_invrx,},
    {.pattern = "RAdio:LORa:INVRx?", .callback = lora_invrxQ,},  
    {.pattern = "RAdio:LORa:INVTx", .callback = lora_invtx,},
    {.pattern = "RAdio:LORa:INVTx?", .callback = lora_invtxQ,},            
    
#ifdef TARGET_MOTE_L152RC
    {.pattern = "PD2", .callback = pd2_set,},
    {.pattern = "PD2?", .callback = pd2_get,},
    {.pattern = "RFSW?", .callback = rfswQ,},
    {.pattern = "VBAT?", .callback = vbatQ,},
    
    {.pattern = "GPS:ENable", .callback = gps_enable,},
    {.pattern = "GPS:ENable?", .callback = gps_enableQ,},
    {.pattern = "GPS:NUMCoords", .callback = gps_numCords,},
    {.pattern = "GPS:NUMCoords?", .callback = gps_numCordsQ,},   
    {.pattern = "GPS:LOngitude", .callback = gps_longitude,},
    {.pattern = "GPS:LOngitude?", .callback = gps_longitudeQ,},  
    {.pattern = "GPS:LAtitude", .callback = gps_latitude,},
    {.pattern = "GPS:LAtitude?", .callback = gps_latitudeQ,},  
    
    {.pattern = "MMA:ID?", .callback = mma_idQ,}, 
    
    {.pattern = "MPL:ID?", .callback = mpl_idQ,},
    
    {.pattern = "SX9500:RST", .callback = sx9500_reset,},
    {.pattern = "SX9500:REGister", .callback = sx9500_reg,},
    {.pattern = "SX9500:REGister?", .callback = sx9500_regQ,},
    
#endif /* TARGET_MOTE_L152RC */
    
    SCPI_CMD_LIST_END
};

#ifdef TARGET_MOTE_L152RC
void get_mote_version()
{
    char first;
      
    pc_7 = 1;
    first = pc_1;
    pc_7 = 0;
    if (first && !pc_1) {
        mote_version = MOTE_V2;
        bat = new AnalogIn(PA_0);
    } else {
        mote_version = MOTE_V3;
        bat = new AnalogIn(PA_1);
    }
}
#endif

static scpi_interface_t scpi_interface = {
    .error = SCPI_Error,
    .write = SCPI_Write,
    .control = SCPI_Control,
    .flush = SCPI_Flush,
    .reset = SCPI_Reset,
};

#define SCPI_INPUT_BUFFER_LENGTH 256
static char scpi_input_buffer[SCPI_INPUT_BUFFER_LENGTH];
static scpi_reg_val_t scpi_regs[SCPI_REG_COUNT];

scpi_t scpi_context = {
    cmdlist : scpi_commands,
    buffer : {
        length : SCPI_INPUT_BUFFER_LENGTH,
        position : 0,
        data : scpi_input_buffer
    },
    param_list : { 0 }, 
    interface : &scpi_interface,
    output_count : 0,
    input_count : 0,
    cmd_error : false,
    error_queue : NULL,
    registers : scpi_regs,
    units : scpi_units_def,
    user_context : NULL,
    parser_state : {
        programHeader : { SCPI_TOKEN_UNKNOWN, NULL, 0 },
        programData : { SCPI_TOKEN_UNKNOWN, NULL, 0 },
        numberOfParameters : 0,
        termination : SCPI_MESSAGE_TERMINATION_NONE
    },
    idn : {"semtech", "na-mote", NULL, "01-02"}
};

void scpi_def_init()
{
    radio.rf_switch = rfsw_callback;
    radio.get_frf_MHz();    // get HF bit
    
#ifdef TARGET_MOTE_L152RC

    get_mote_version();
    if (mote_version == MOTE_V3) {
        gps.en_invert = false;
        scpi_context.idn[3] = "3";
    } else {
        gps.en_invert = true;
        scpi_context.idn[3] = "2";
    }
        
    gps.init();

#endif /* TARGET_MOTE_L152RC */
}