SCPI interface to SX1272 and SX1276

Dependencies:   SX127x lib_gps lib_mma8451q lib_mpl3115a2 lib_sx9500 libscpi mbed

Description

This program implements a SCPI command parser. When connected via the debug virtual comm port, you can command the radio and peripherals to perform specific tasks or to set specific parameters. The serial port defaults to 9600bps N-8-1.

Example

The following exampling causes the NA Mote to transmit a continuous LoRa signal.

Example SCPI Commands

*IDN?
RA:MOD LORA
RA:FREQ 903
RA:PAS PA_BOOST
RA:OCP 170
RA:BGR 7
RA:POW 15
RA:LORA:TXContinuous ON
RA:FI "test"

Commands

SCPI is case-insensitive. Commands can be entered lower case.

  • RAdio
    • :FIfo "text" write to fifo, and transmit packet
    • :FIfo? read from fifo (last received packet)
    • :REGister { address }, {value} write radio register (SCPI takes #H for hex prefix)
    • :REGister? { address } read radio register (SCPI takes #H for hex prefix)
    • :MODulation { FSK | OOK | LORa } set modem type
    • :MODulation? get modem type
    • :OPmode { SLE | STB | FST | TX | FSR | RXC | RXS | CAD } set mode
    • :OPmode? get mode
    • :DIOMap { 0 - 5 }, { 0 - 3 } set DIO pin function {pin number}, {map value}
    • :DIOMap? { 0 - 5 } get DIO pin function {pin number}
    • :DIO? { 0 - 5 } read DIO pin level
    • :RSSI? read received signal strength (if in RXC mode)
    • :PASelect { RFO | PA_BOOST } set RF output pin
    • :PASelect? get RF output pin selected
    • :OCP {mA} set over current protection
    • :OCP? read current limit
    • :POWer {0 to 15} set OutputPower
    • :POWer? get OutputPower
    • :BGR { 0 - 7 } set PA ref current
    • :BGR? get PA ref current
    • :FREQuency {MHz} set FRF
    • :FREQuency? get FRF
    • :LNABoost { OFF | ON } set LNA boost
    • :LNABoost? get LNA boost
    • :LORa
      • :BW {KHz} set lora bandwidth
      • :BW? get lora bandwidth (in KHz)
      • :SF {7 to 12} set spreading factor
      • :SF? get spreading factor
      • :TXContinuous { OFF | ON } set continuous TX (end transmit by turning off)
      • :TXContinuous? get continuous TX
      • :PRELen {n-symbols} set preamble length
      • :PRELen? get preamble length
      • :CR {0-4} set coding rate
      • :CR? get coding rate
      • :LDRO { OFF | ON } set LowDataRateOptimize bit
      • :LDRO? get LowDataRateOptimize bit
      • :CRC { OFF | ON} enable CRC in transmitted packet
      • :CRC? read CRC enabled state
      • :INVRx { OFF | ON } enable receiver spectral invert
      • :INVRx? get receiver inversion state
      • :INVTx { OFF | ON } enable transmitter spectral invert
      • :INVTx? get transmitter inversion state
      • :FEI? get frequency error of last received packet
      • :PKTSnr? get S/N (dB) of last received packet
    • :FSK
      • :DATAMode { CONT | PKT } select continuous/packet mode
      • :DATAMode? get packet mode / continuous
      • :FDev {Hz} set TX frequency deviation
      • :FDev? get TX frequency deviation
      • :BITRate {bps} set bit rate
      • :BITRate? get bit rate
      • :BT { 1.0 | 0.5 | 0.3 | 0.0 } set transmit shaping
      • :BT? get transmit shaping
      • :PRELen {n} set preamble size
      • :PRELen? get preamble size
      • :RXBW {Hz} set receive bandwidth
      • :RXBW? set receive bandwidth
      • :AFCBW {Hz} set receive bandwidth (during preamble)
      • :AFCBW? set receive bandwidth (during preamble)
      • :DCFree { OFF | MAN | WHIT } set DC-free encoding
      • :DCFree? get DC-free encoding
      • :RXTrigger { OFF | RSSI | PRE | BOTH } set RX trigger mode
      • :RXTrigger? get RX trigger selection

radio events

Radio events are reported into the Questionable Data Status Event Register, which is summarized in Bit 3 (QSB) of Status Byte Register.

enabling event and reading event

RA:MOD?
"LORa"
RA:OP?
"RXC"
STAT:QUES:ENAB 512
*STB?
8
STAT:QUES:EVEN?
512
RA:FI?
"4747474747474747"
*STB?
0

Bit 9 of QUEStionable event register indicates DIO0 event occurred upon radio packet reception.

NA Mote-72 specific commands

  • PD2 { OFF | ON } set power amplifier voltage state
  • PD2? get power amplifier voltage state
  • VBAT? read battery voltage
  • GPS
    • :EN { OFF | ON } enable GPS
    • :EN? get GPS enabled state
    • :NUMCoords {n} set count of coordinates received (use to clear count)
    • :NUMCoords? get count of coordinates received
    • :LOngitude {n} set longitude
    • :LOngitude? get longitude
    • :LAtitude {n} set latitude
    • :LAtitude? get latitude
  • MMA MMA8451Q
    • :ID? read ID register (WHO_AM_I == 0x1a)
  • MPL MPL3115A2
    • :ID? read ID register (WHO_AM_I == 0xc4)
  • SX9500
    • :RST reset SX9500
    • :REGister {addr}, {value} write SX9500 register
    • :REGister? {addr} read SX9500 register

test_interactive.cpp

Committer:
Wayne Roberts
Date:
15 months ago
Revision:
12:60990328c884
Parent:
11:5e67cde3fc62

File content as of revision 12:60990328c884:

/*-
 * Copyright (c) 2012-2013 Jan Breuer,
 *
 * All Rights Reserved
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @file   main.c
 * @date   Thu Nov 15 10:58:45 UTC 2012
 * 
 * @brief  SCPI parser test
 * 
 * 
 */

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



Serial pc(USBTX, USBRX);

#ifdef TARGET_MOTE_L152RC
    #define LED_TIMEOUT 50000 // usec
    DigitalOut RedLed( PB_1 );     // Active Low
    DigitalOut YellowLed( PB_10 ); // Active Low
    DigitalOut UsrLed( PA_5 );     // Active High
    TimerEvent_t RedLedTimer;
    static void OnInputEvent( void );
#endif /* TARGET_MOTE_L152RC */

#ifdef TARGET_MOTE_L152RC
#endif /* TARGET_MOTE_L152RC */


char smbuffer[64];

size_t SCPI_Write(scpi_t * context, const char * data, size_t len) {
    (void) context;
    return fwrite(data, 1, len, stdout);
}

scpi_result_t SCPI_Flush(scpi_t * context) {    
    fflush(stdout);
    return SCPI_RES_OK;
}

int SCPI_Error(scpi_t * context, int_fast16_t err) {
    (void) context;

    printf("**ERROR: %d, \"%s\"\r\n", (int32_t) err, SCPI_ErrorTranslate(err));
    return 0;
}

scpi_result_t SCPI_Control(scpi_t * context, scpi_ctrl_name_t ctrl, scpi_reg_val_t val) {
    if (SCPI_CTRL_SRQ == ctrl) {
        printf("**SRQ: 0x%X (%d)\r\n", val, val);
    } else {
        printf("**CTRL %02x: 0x%X (%d)\r\n", ctrl, val, val);
    }
    return SCPI_RES_OK;
}

/**
 * Return 0 as OK and other number as error
 */
scpi_result_t SCPI_Test(scpi_t * context) {
    printf("**Test\r\n");
    return (scpi_result_t)0;
}



scpi_result_t SCPI_SystemCommTcpipControlQ(scpi_t * context) {
    return SCPI_RES_ERR;
}
/*
 * 
 */
int get_kbd_str(char* buf, int size)
{
    char c;
    int i;
    static int prev_len;
    
    for (i = 0;;) {
        if (pc.readable()) {
            c = pc.getc();
            if (c == 8) {   // backspace
                if (i > 0) {
                    pc.putc(8);
                    pc.putc(' ');
                    pc.putc(8);
                    i--;
                }
            } else if (c == '\r') {
                if (i == 0) {
                    return prev_len; // repeat previous
                } else {
                    buf[i++] = c;
                    buf[i] = 0; // null terminate
                    prev_len = i;
                    pc.putc('\r');
                    pc.putc('\n');
                    return i;
                }
            } else if (c == 3) {
                // ctrl-C abort
                //abort_key = true;
                return -1;
            } else if (i < size) {
                buf[i++] = c;
                pc.putc(c);
            }
        } else {
            /* service something */
            service_radio();
        }
    } // ...for()
}

int main(int argc, char** argv) {
    (void) argc;
    (void) argv;
    //int result;
    
    scpi_def_init();

    SCPI_Init(&scpi_context);

    printf("\r\nreset\r\n");


#ifdef TARGET_MOTE_L152RC
    RedLed = 1;
    YellowLed = 1;
    UsrLed = 1;
    TimerInit( &RedLedTimer, OnInputEvent);
#endif /* TARGET_MOTE_L152RC */



    while (1) {
         //fgets(smbuffer, 10, stdin); 

         int len = get_kbd_str(smbuffer, sizeof(smbuffer));
         if (len > 0) {      
#ifdef TARGET_MOTE_L152RC
            /* Blink Red LED on keyboard entry */
            RedLed = 0;
            TimerSetValue( &RedLedTimer, LED_TIMEOUT ); // set blink LED to 750ms
            TimerStart( &RedLedTimer );
#endif /* TARGET_MOTE_L152RC */                   
            /*result =*/ SCPI_Input(&scpi_context, smbuffer, len);
        }
    }

    //return (EXIT_SUCCESS);
}

#ifdef TARGET_MOTE_L152RC
static void OnInputEvent( void )
{
    TimerStop( &RedLedTimer);

    RedLed = 1;
}
#endif /* TARGET_MOTE_L152RC */