ping pong with modifiable parameters

Dependencies:   mbed SX126xLib

main.cpp

Committer:
nimita23
Date:
2019-07-10
Revision:
7:df2f595fda33
Parent:
6:e155f7cceb5b
Child:
8:2952eeb51ceb

File content as of revision 7:df2f595fda33:

#include "mbed.h"
#include "radio.h"
#include "sx126x-hal.h"

#define buffer_size 256             // incoming buffer size
#define buffer_fill buffer_size+1   // number, when buffer is ready
#define BUFFER_SIZE 16              // payload size
#define PINGPONGSIZE 4  // size of token defining message type in the payload
#define TX_TIMEOUT_VALUE                            0xFFFF // ms
#define RX_TIMEOUT_VALUE                            0xFFFF // ms

typedef enum                        //states of the application
{
    APP_LOWPOWER,
    APP_RX,
    APP_RX_TIMEOUT,
    APP_RX_ERROR,
    APP_TX,
    APP_TX_TIMEOUT,
}AppStates_t;

const uint8_t PingMsg[] = "PING";
const uint8_t PongMsg[] = "PONG";

long unsigned RF_FREQUENCY = 450000000; // Hz
RadioLoRaSpreadingFactors_t spreading_factor = LORA_SF7;
RadioLoRaBandwidths_t bandwidth = LORA_BW_500;
int TX_OUTPUT_POWER  = 10; //The range of the output power is [-18..+13] dBm
bool isMaster =  true;

Serial s( USBTX, USBRX ); // serial object for AT commands
char serial_buffer[buffer_size];    // buffer to save incoming data
int serial_buffer_index = 0;          // index array for buffer
bool serial_end_line = false;       // searching for end line

uint8_t BufferSize = BUFFER_SIZE;
uint8_t Buffer[BUFFER_SIZE];

uint16_t RxIrqMask = IRQ_RX_DONE | IRQ_CRC_ERROR | IRQ_RX_TX_TIMEOUT;
uint16_t TxIrqMask = IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT;

PacketParams_t PacketParams;
PacketStatus_t PacketStatus;

ModulationParams_t modulationParams;

/*!
 * \brief The State of the application
 */
AppStates_t AppState = APP_LOWPOWER;
void OnTxDone( void );
void OnRxDone( void );
void OnTxTimeout( void );
void OnRxTimeout( void );
void OnRxError( IrqErrorCode_t );
void parser();
void LoRa_init();


RadioCallbacks_t callbacks = {
    &OnTxDone,        // txDone
    &OnRxDone,        // rxDone
    NULL,             // rxPreambleDetect
    NULL,             // rxSyncWordDone
    NULL,             // rxHeaderDone
    &OnTxTimeout,     // txTimeout
    &OnRxTimeout,     // rxTimeout
    &OnRxError,       // rxError
    NULL,       // cadDone
};

// mosi, miso, sclk, nss, busy, dio1, dio2, dio3, rst, callbacks...

SX126xHal Radio( D11, D12, D13, D7, D3, D5, NC, NC, A0, A1, A2, D8, &callbacks );

DigitalOut ANT_SW( A3 );
DigitalOut TxLed( A4 );
DigitalOut RxLed( A5 );

/*!
 * \brief Define IO for Unused Pin
 */
DigitalOut F_CS( D6 );      // MBED description of pin
DigitalOut SD_CS( D8 );     // MBED description of pin


void serialRx()
{
    int j;
    while(s.readable()) {
        char character=s.getc();                                           
        if(( (int)character==10 || (int)character==13) && serial_end_line) {
            serial_end_line=true; 
            continue;
        } else {
            serial_end_line=false; 
        }
        if(serial_buffer_index != buffer_fill) {
            serial_buffer[serial_buffer_index++] = character;
            if(serial_buffer_index == buffer_size) {
                serial_buffer[buffer_size-1] = '\0';
                serial_buffer_index=buffer_fill;
                continue;
            }
            if(character == 13 || character == 10) {
                serial_buffer[serial_buffer_index-1] = '\0';
                serial_buffer_index = buffer_fill;
                serial_end_line = true;
            }
        } 
    }
    if(serial_buffer_index==buffer_fill && serial_end_line != true) {
        printf("Input too long to be parsed\n\r");
        serial_buffer_index = 0;
    }
    else if(serial_end_line == true) {
        serial_buffer_index = 0;
        if(sscanf (serial_buffer,"%d",&j)) {  // sscanf for searching integer
            printf("From PC:%d.\n\r" ,j);  // write to serial incoming integer
        }
        parser();
    }
    
}

/*!
 * \brief Specify serial datarate for UART debug output
 */
void baud( int baudrate )
{    
    s.baud(baudrate);
    s.attach(&serialRx,Serial::RxIrq);  
}

void LoRa_init() {
    modulationParams.PacketType                  = PACKET_TYPE_LORA;
    modulationParams.Params.LoRa.SpreadingFactor = spreading_factor;
    modulationParams.Params.LoRa.Bandwidth       = bandwidth;
    modulationParams.Params.LoRa.CodingRate      = LORA_CR_4_5;

    PacketParams.PacketType                 = PACKET_TYPE_LORA;
    PacketParams.Params.LoRa.PreambleLength = 0x08;
    PacketParams.Params.LoRa.HeaderType     = LORA_PACKET_VARIABLE_LENGTH;
    PacketParams.Params.LoRa.PayloadLength  = 15;
    PacketParams.Params.LoRa.CrcMode        = LORA_CRC_ON;
    PacketParams.Params.LoRa.InvertIQ       = LORA_IQ_INVERTED;

    

    Radio.SetStandby( STDBY_RC );
    Radio.SetPacketType( modulationParams.PacketType );
    Radio.SetModulationParams( &modulationParams );
    Radio.SetPacketParams( &PacketParams );

    Radio.SetRfFrequency( RF_FREQUENCY );
    Radio.SetBufferBaseAddresses( 0x00, 0x00 );
    Radio.SetTxParams( TX_OUTPUT_POWER, RADIO_RAMP_20_US );

    RxLed = 0;
    TxLed = 0;

    Radio.SetDioIrqParams( RxIrqMask, RxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
    Radio.SetRx( RX_TIMEOUT_VALUE );
    AppState = APP_LOWPOWER;
    isMaster = true;
    
    Radio.ProcessIrqs( );
}

int main( )
{
    baud( 115200 );

    F_CS   = 1;
    SD_CS  = 1;
    RxLed  = 1;
    TxLed  = 1;
    ANT_SW = 1;

    wait_ms( 500 ); // wait for on board DC/DC start-up time

    Radio.Init( );
    Radio.SetRegulatorMode( USE_DCDC ); // Can also be set in LDO mode but consume more power

    memset( &Buffer, 0x00, BufferSize );

    printf( "\n\n\r     SX1262 Whitespace Ping Pong Application \n\n\r");

    LoRa_init();
    printf( "\nPing Pong running in LORA mode\n\r");
    

    while( 1 )
    {
        Radio.ProcessIrqs( );
        switch( AppState )
        {
            case APP_RX:
                AppState = APP_LOWPOWER;
                RxLed = !RxLed;
                Radio.GetPayload( Buffer, &BufferSize, BUFFER_SIZE );
                printf("\n%s\n", Buffer);
                if( isMaster == true )
                {
                    if( BufferSize > 0 )
                    {
                        if( strncmp( ( const char* )Buffer, ( const char* )PongMsg, PINGPONGSIZE ) == 0 )
                        {
                            printf( "...Pong\r\n" );
                            memcpy( Buffer, PingMsg, PINGPONGSIZE );
                            Radio.SetDioIrqParams( TxIrqMask, TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
                            Radio.SendPayload( Buffer, BufferSize, (TX_TIMEOUT_VALUE));
                        }
                        else if( strncmp( ( const char* )Buffer, ( const char* )PingMsg, PINGPONGSIZE ) == 0 )
                        {
                            // A master already exists then become a slave
                            printf( "...Ping\r\n" );
                            isMaster = false;
                            memcpy( Buffer, PongMsg, PINGPONGSIZE );
                            Radio.SetDioIrqParams( TxIrqMask, TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
                            Radio.SendPayload( Buffer, BufferSize, TX_TIMEOUT_VALUE );
                        }
                        else // valid reception but neither a PING or a PONG message
                        {    // Set device as master ans start again
                            isMaster = true;
                            Radio.SetDioIrqParams( RxIrqMask, RxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
                            Radio.SetRx(RX_TIMEOUT_VALUE );
                        }
                    }
                }
                else
                {
                    if( BufferSize > 0 )
                    {
                        if( strncmp( ( const char* )Buffer, ( const char* )PingMsg, PINGPONGSIZE ) == 0 )
                        {
                            printf( "...Ping\r\n" );
                            memcpy( Buffer, PongMsg, 4 );
                            Radio.SetDioIrqParams( TxIrqMask, TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
                            Radio.SendPayload( Buffer, BufferSize, TX_TIMEOUT_VALUE );
                        }
                        else // valid reception but not a PING as expected
                        {
                            isMaster = true;
                            Radio.SetDioIrqParams( RxIrqMask, RxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
                            Radio.SetRx(RX_TIMEOUT_VALUE);
                        }
                    }
                }
                break;

            case APP_TX:
                AppState = APP_LOWPOWER;
                TxLed = !TxLed;
                if( isMaster == true )
                {
                    printf( "Ping...\r\n" );
                }
                else
                {
                    printf( "Pong...\r\n" );
                }
                Radio.SetDioIrqParams( RxIrqMask, RxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
                Radio.SetRx(RX_TIMEOUT_VALUE );
                break;

            case APP_RX_TIMEOUT:
                AppState = APP_LOWPOWER;
                if( isMaster == true )
                {
                    // Send the next PING frame
                    memcpy( Buffer, PingMsg, PINGPONGSIZE );
                    Radio.SetDioIrqParams( TxIrqMask, TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
                    Radio.SendPayload( Buffer, BufferSize, TX_TIMEOUT_VALUE );
                }
                else
                {
                    Radio.SetDioIrqParams( RxIrqMask, RxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
                    Radio.SetRx( RX_TIMEOUT_VALUE );
                }
                break;

            case APP_RX_ERROR:
                AppState = APP_LOWPOWER;
                // We have received a Packet with a CRC error, send reply as if packet was correct
                if( isMaster == true )
                {
                    // Send the next PING frame
                    memcpy( Buffer, PingMsg, PINGPONGSIZE );
                    Radio.SetDioIrqParams( TxIrqMask, TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
                    Radio.SendPayload( Buffer, BufferSize,  TX_TIMEOUT_VALUE);
                }
                else
                {
                    // Send the next PONG frame
                    memcpy( Buffer, PongMsg, PINGPONGSIZE );
                    Radio.SetDioIrqParams( TxIrqMask, TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
                    Radio.SendPayload( Buffer, BufferSize, TX_TIMEOUT_VALUE );
                }
                break;

            case APP_TX_TIMEOUT:
                AppState = APP_LOWPOWER;
                Radio.SetDioIrqParams( RxIrqMask, RxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
                Radio.SetRx( RX_TIMEOUT_VALUE  );
                break;

            case APP_LOWPOWER:
                break;

            default:
                // Set low power
                break;
        }
    }
}

void OnTxDone( void ) {
    AppState = APP_TX;
}

void OnRxDone( void ) {
    int RssiValue, SnrValue;
    AppState = APP_RX;
    PacketStatus_t packetStatus;
    Radio.GetPacketStatus(&packetStatus);
    RssiValue = packetStatus.Params.LoRa.RssiPkt;
    SnrValue = packetStatus.Params.LoRa.SnrPkt;
    printf("rssi: %d; snr: %d\n\r", RssiValue, SnrValue );
}

void OnTxTimeout( void ) {
    AppState = APP_TX_TIMEOUT;
    printf( "<>>>>>>>>TXE\r\n" );
}

void OnRxTimeout( void ) {
    AppState = APP_RX_TIMEOUT;
}

void OnRxError( IrqErrorCode_t errorCode ) {
    AppState = APP_RX_ERROR;
    printf( "RXE<>>>>>>>>\r\n" );
}

void OnCadDone( bool channelActivityDetected ) {
}


void parser() {
    printf("%s\n\r", serial_buffer);
    char command[10];
    long val;
    if(sscanf(serial_buffer, "%10s %lu", command, &val) != 2){
        printf("Invalid Input\n\r");
        return;
    }
    if(strcmp(command, "FREQ") == 0) {
        if((125000000<=val) && (val<=960000000)) {
            RF_FREQUENCY = val;
            printf("Frequency set to: %lu\n\r", val);
            LoRa_init();              
        }
    }
    else if(strcmp(command, "TX") == 0) {
        if((-22<=val) && (val<=13)) {
            TX_OUTPUT_POWER = val;
            printf("TX output power set to: %lu\n\r", val);
            LoRa_init(); 
        }
    }
    else if(strcmp(command, "S_F") == 0) {
        switch(val) {
            case 5:
                spreading_factor = LORA_SF5;
            break;
            case 6:
                spreading_factor = LORA_SF6;
            break;
            case 7:
                spreading_factor = LORA_SF7;
            break;
            case 8:
                spreading_factor = LORA_SF8;
            break;
            case 9:
                spreading_factor = LORA_SF9;
            break;
            case 10:
                spreading_factor = LORA_SF10;
            break;
            case 11:
                spreading_factor = LORA_SF11;
            break;
            case 12:
                spreading_factor = LORA_SF12;
            break;
            default:
                printf("enter spreading factor between 5 and 12\n\r");
                return;
        }
        printf("Spreading factor changed to %lu\n\r", val);
        LoRa_init();
    }
    else if(strcmp(command, "BW") == 0) {
        switch(val) {
            case 500:
                bandwidth = LORA_BW_500;
            break;
            case 250:
                bandwidth = LORA_BW_250;
            break;
            case 125:
                bandwidth = LORA_BW_125;
            break;
            case 062:
                bandwidth = LORA_BW_062;
            break;
            case 041:
                bandwidth = LORA_BW_041;
            break;
            case 031:
                bandwidth = LORA_BW_031;
            break;
            case 020:
                bandwidth = LORA_BW_020;
            break;
            case 015:
                bandwidth = LORA_BW_015;
            break;
            case 010:
                bandwidth = LORA_BW_010;
            break;
            case 007:
                bandwidth = LORA_BW_007;
            break;
            default:
                printf("Valid bandwidths: 500, 250, 125, 62, 41, 31, 20, ");
                printf("15, 10, 7\n\r");
                return;
        }
        printf("LoRa bandwidth changed to %lu\n\r", val);
        LoRa_init();
    }
    else
        printf("Invalid command\n\r");
    
        
}