ping pong with modifiable parameters

Dependencies:   mbed SX126xLib

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include "radio.h"
00003 #include "sx126x-hal.h"
00004 
00005 #define buffer_size 256             // incoming buffer size
00006 #define buffer_fill buffer_size+1   // number, when buffer is ready
00007 #define BUFFER_SIZE 16              // payload size
00008 #define PINGPONGSIZE 4  // size of token defining message type in the payload
00009 #define TX_TIMEOUT_VALUE                            0xFFFF // ms
00010 #define RX_TIMEOUT_VALUE                            0xFFFF // ms
00011 
00012 typedef enum                        //states of the application
00013 {
00014     APP_LOWPOWER,
00015     APP_RX,
00016     APP_RX_TIMEOUT,
00017     APP_RX_ERROR,
00018     APP_TX,
00019     APP_TX_TIMEOUT,
00020 }AppStates_t;
00021 
00022 const uint8_t PingMsg[] = "PING";
00023 const uint8_t PongMsg[] = "PONG";
00024 
00025 long unsigned RF_FREQUENCY = 500000000; // Hz
00026 RadioLoRaSpreadingFactors_t spreading_factor = LORA_SF7;
00027 RadioLoRaBandwidths_t bandwidth = LORA_BW_500;
00028 RadioLoRaCodingRates_t coding_rate = LORA_CR_4_5;
00029 int TX_OUTPUT_POWER  = 10; //The range of the output power is [-18..+13] dBm
00030 bool isMaster =  true;
00031 
00032 Serial s( USBTX, USBRX ); // serial object for AT commands
00033 char serial_buffer[buffer_size];    // buffer to save incoming data
00034 char serial_buffer2[buffer_size];   // second buffer to save incoming data
00035 int serial_buffer_where=0;          // index array for buffer
00036 int serial_buffer2_where=0;         // index array for second buffer
00037 bool serial_end_line = false;       // searching for end line
00038 
00039 
00040 uint8_t BufferSize = BUFFER_SIZE;
00041 uint8_t Buffer[BUFFER_SIZE];
00042 
00043 uint16_t RxIrqMask = IRQ_RX_DONE | IRQ_CRC_ERROR | IRQ_RX_TX_TIMEOUT;
00044 uint16_t TxIrqMask = IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT;
00045 
00046 PacketParams_t PacketParams;
00047 PacketStatus_t PacketStatus;
00048 
00049 ModulationParams_t modulationParams;
00050 
00051 /*!
00052  * \brief The State of the application
00053  */
00054 AppStates_t AppState = APP_LOWPOWER;
00055 void OnTxDone( void );
00056 void OnRxDone( void );
00057 void OnTxTimeout( void );
00058 void OnRxTimeout( void );
00059 void OnRxError( IrqErrorCode_t );
00060 void parser(char*);
00061 void LoRa_init();
00062 
00063 
00064 RadioCallbacks_t callbacks = {
00065     &OnTxDone,        // txDone
00066     &OnRxDone,        // rxDone
00067     NULL,             // rxPreambleDetect
00068     NULL,             // rxSyncWordDone
00069     NULL,             // rxHeaderDone
00070     &OnTxTimeout,     // txTimeout
00071     &OnRxTimeout,     // rxTimeout
00072     &OnRxError,       // rxError
00073     NULL,       // cadDone
00074 };
00075 
00076 // mosi, miso, sclk, nss, busy, dio1, dio2, dio3, rst, callbacks...
00077 
00078 SX126xHal Radio( D11, D12, D13, D7, D3, D5, NC, NC, A0, A1, A2, D8, &callbacks );
00079 
00080 DigitalOut ANT_SW( A3 );
00081 DigitalOut TxLed( A4 );
00082 DigitalOut RxLed( A5 );
00083 
00084 /*!
00085  * \brief Define IO for Unused Pin
00086  */
00087 DigitalOut F_CS( D6 );      // MBED description of pin
00088 DigitalOut SD_CS( D8 );     // MBED description of pin
00089 
00090 
00091 void serialRx()
00092 {
00093     
00094     while(s.readable()) {                                                  // read all data from serial
00095         char character=s.getc();                                           // get a char form serial
00096         if(((int)character==10 || (int)character==13) && serial_end_line) { // search for end line /r or /n
00097             serial_end_line=true;                                           // end was find in the previous charascter, skip
00098             continue;
00099         } else {
00100             serial_end_line=false;                                          // clear serial_end_line flag
00101         }
00102         if(serial_buffer_where!=buffer_fill && !(serial_buffer2_where != 0 && serial_buffer2_where!=buffer_fill)) {
00103             serial_buffer[serial_buffer_where++]=character;
00104             if(serial_buffer_where==buffer_size) {                          // check if incoming data are smaller than buffer size
00105                 serial_buffer[buffer_size-1]='\0';                          // posibility to lost data, if the incoming data are too big
00106                 serial_buffer_where=buffer_fill;                            // set index array to indicate buffer fill
00107                 continue;
00108             }
00109             if(character==13 || character==10) {                            // if end of line (\r \n) is indicated, prepare the buffer to serialGetBuffer
00110                 serial_buffer[serial_buffer_where-1]='\0';                  // set end of buffer with 0
00111                 serial_buffer_where=buffer_fill;                            // set index array to indicate buffer fill
00112                 serial_end_line=true;                                       // end of line was find, set serial_end_line flag
00113             }
00114         } else if(serial_buffer2_where!=buffer_fill) {                      // same for second buffer
00115             serial_buffer2[serial_buffer2_where++]=character;
00116             if(serial_buffer2_where==buffer_size) {
00117                 serial_buffer2[buffer_size-1]='\0';
00118                 serial_buffer2_where=buffer_fill;
00119                 continue;
00120             }
00121             if(character==13 || character==10) {
00122                 serial_buffer2[serial_buffer2_where-1]='\0';
00123                 serial_buffer2_where=buffer_fill;
00124                 serial_end_line=true;
00125             }
00126         } 
00127     }
00128 }
00129 
00130 int serialGetBuffer(char * & data)
00131 {
00132     if(serial_buffer_where==buffer_fill && serial_buffer2_where==buffer_fill) {
00133         data=serial_buffer;
00134         //memcpy(data, serial_buffer, strlen(serial_buffer)+1);
00135         serial_buffer_where=0;
00136         return 2;
00137     } else if(serial_buffer2_where==buffer_fill) {
00138         data=serial_buffer2;
00139         //memcpy(data, serial_buffer2, strlen(serial_buffer2)+1);
00140         serial_buffer2_where=0;
00141         return 1;
00142     } else if(serial_buffer_where==buffer_fill) {
00143         data=serial_buffer;
00144         //memcpy(data, serial_buffer, strlen(serial_buffer)+1);
00145         serial_buffer_where=0;
00146         return 1;
00147     } else {
00148         data = NULL;
00149         return 0;
00150     }
00151 }
00152 
00153 /*!
00154  * \brief Specify serial datarate for UART debug output
00155  */
00156 void baud( int baudrate )
00157 {    
00158     s.baud(baudrate);
00159     s.attach(&serialRx,Serial::RxIrq);  
00160 }
00161 
00162 void LoRa_init() {
00163     modulationParams.PacketType                  = PACKET_TYPE_LORA;
00164     modulationParams.Params.LoRa.SpreadingFactor = spreading_factor;
00165     modulationParams.Params.LoRa.Bandwidth       = bandwidth;
00166     modulationParams.Params.LoRa.CodingRate      = coding_rate;
00167 
00168     PacketParams.PacketType                 = PACKET_TYPE_LORA;
00169     PacketParams.Params.LoRa.PreambleLength = 0x08;
00170     PacketParams.Params.LoRa.HeaderType     = LORA_PACKET_VARIABLE_LENGTH;
00171     PacketParams.Params.LoRa.PayloadLength  = 15;
00172     PacketParams.Params.LoRa.CrcMode        = LORA_CRC_ON;
00173     PacketParams.Params.LoRa.InvertIQ       = LORA_IQ_INVERTED;
00174 
00175     
00176 
00177     Radio.SetStandby( STDBY_RC );
00178     Radio.SetPacketType( modulationParams.PacketType );
00179     Radio.SetModulationParams( &modulationParams );
00180     Radio.SetPacketParams( &PacketParams );
00181 
00182     Radio.SetRfFrequency( RF_FREQUENCY );
00183     Radio.SetBufferBaseAddresses( 0x00, 0x00 );
00184     Radio.SetTxParams( TX_OUTPUT_POWER, RADIO_RAMP_20_US );
00185 
00186     RxLed = 0;
00187     TxLed = 0;
00188 
00189     Radio.SetDioIrqParams( RxIrqMask, RxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
00190     Radio.SetRx( RX_TIMEOUT_VALUE );
00191     AppState = APP_LOWPOWER;
00192     isMaster = true;
00193     
00194     Radio.ProcessIrqs( );
00195 }
00196 
00197 int main( )
00198 {
00199     baud( 115200 );
00200 
00201     F_CS   = 1;
00202     SD_CS  = 1;
00203     RxLed  = 1;
00204     TxLed  = 1;
00205     ANT_SW = 1;
00206 
00207     wait_ms( 500 ); // wait for on board DC/DC start-up time
00208 
00209     Radio.Init( );
00210     Radio.SetRegulatorMode( USE_DCDC ); // Can also be set in LDO mode but consume more power
00211 
00212     memset( &Buffer, 0x00, BufferSize );
00213 
00214     printf( "\n\n\r     SX1262 Whitespace Ping Pong Application \n\n\r");
00215 
00216     LoRa_init();
00217     printf( "\nPing Pong running in LORA mode\n\r");
00218     
00219 
00220     while( 1 )
00221     {
00222         Radio.ProcessIrqs( );
00223         char *data;
00224         serialGetBuffer(data);
00225         if(data)
00226             parser(data);
00227         switch( AppState )
00228         {
00229             case APP_RX:
00230                 AppState = APP_LOWPOWER;
00231                 RxLed = !RxLed;
00232                 Radio.GetPayload( Buffer, &BufferSize, BUFFER_SIZE );
00233                 printf("\n%s\n", Buffer);
00234                 if( isMaster == true )
00235                 {
00236                     if( BufferSize > 0 )
00237                     {
00238                         if( strncmp( ( const char* )Buffer, ( const char* )PongMsg, PINGPONGSIZE ) == 0 )
00239                         {
00240                             printf( "...Pong\r\n" );
00241                             memcpy( Buffer, PingMsg, PINGPONGSIZE );
00242                             Radio.SetDioIrqParams( TxIrqMask, TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
00243                             Radio.SendPayload( Buffer, BufferSize, (TX_TIMEOUT_VALUE));
00244                         }
00245                         else if( strncmp( ( const char* )Buffer, ( const char* )PingMsg, PINGPONGSIZE ) == 0 )
00246                         {
00247                             // A master already exists then become a slave
00248                             printf( "...Ping\r\n" );
00249                             isMaster = false;
00250                             memcpy( Buffer, PongMsg, PINGPONGSIZE );
00251                             Radio.SetDioIrqParams( TxIrqMask, TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
00252                             Radio.SendPayload( Buffer, BufferSize, TX_TIMEOUT_VALUE );
00253                         }
00254                         else // valid reception but neither a PING or a PONG message
00255                         {    // Set device as master ans start again
00256                             isMaster = true;
00257                             Radio.SetDioIrqParams( RxIrqMask, RxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
00258                             Radio.SetRx(RX_TIMEOUT_VALUE );
00259                         }
00260                     }
00261                 }
00262                 else
00263                 {
00264                     if( BufferSize > 0 )
00265                     {
00266                         if( strncmp( ( const char* )Buffer, ( const char* )PingMsg, PINGPONGSIZE ) == 0 )
00267                         {
00268                             printf( "...Ping\r\n" );
00269                             memcpy( Buffer, PongMsg, 4 );
00270                             Radio.SetDioIrqParams( TxIrqMask, TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
00271                             Radio.SendPayload( Buffer, BufferSize, TX_TIMEOUT_VALUE );
00272                         }
00273                         else // valid reception but not a PING as expected
00274                         {
00275                             isMaster = true;
00276                             Radio.SetDioIrqParams( RxIrqMask, RxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
00277                             Radio.SetRx(RX_TIMEOUT_VALUE);
00278                         }
00279                     }
00280                 }
00281                 break;
00282 
00283             case APP_TX:
00284                 AppState = APP_LOWPOWER;
00285                 TxLed = !TxLed;
00286                 if( isMaster == true )
00287                 {
00288                     printf( "Ping...\r\n" );
00289                 }
00290                 else
00291                 {
00292                     printf( "Pong...\r\n" );
00293                 }
00294                 Radio.SetDioIrqParams( RxIrqMask, RxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
00295                 Radio.SetRx(RX_TIMEOUT_VALUE );
00296                 break;
00297 
00298             case APP_RX_TIMEOUT:
00299                 AppState = APP_LOWPOWER;
00300                 if( isMaster == true )
00301                 {
00302                     // Send the next PING frame
00303                     memcpy( Buffer, PingMsg, PINGPONGSIZE );
00304                     Radio.SetDioIrqParams( TxIrqMask, TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
00305                     Radio.SendPayload( Buffer, BufferSize, TX_TIMEOUT_VALUE );
00306                 }
00307                 else
00308                 {
00309                     Radio.SetDioIrqParams( RxIrqMask, RxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
00310                     Radio.SetRx( RX_TIMEOUT_VALUE );
00311                 }
00312                 break;
00313 
00314             case APP_RX_ERROR:
00315                 AppState = APP_LOWPOWER;
00316                 // We have received a Packet with a CRC error, send reply as if packet was correct
00317                 if( isMaster == true )
00318                 {
00319                     // Send the next PING frame
00320                     memcpy( Buffer, PingMsg, PINGPONGSIZE );
00321                     Radio.SetDioIrqParams( TxIrqMask, TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
00322                     Radio.SendPayload( Buffer, BufferSize,  TX_TIMEOUT_VALUE);
00323                 }
00324                 else
00325                 {
00326                     // Send the next PONG frame
00327                     memcpy( Buffer, PongMsg, PINGPONGSIZE );
00328                     Radio.SetDioIrqParams( TxIrqMask, TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
00329                     Radio.SendPayload( Buffer, BufferSize, TX_TIMEOUT_VALUE );
00330                 }
00331                 break;
00332 
00333             case APP_TX_TIMEOUT:
00334                 AppState = APP_LOWPOWER;
00335                 Radio.SetDioIrqParams( RxIrqMask, RxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
00336                 Radio.SetRx( RX_TIMEOUT_VALUE  );
00337                 break;
00338 
00339             case APP_LOWPOWER:
00340                 break;
00341 
00342             default:
00343                 // Set low power
00344                 break;
00345         }
00346     }
00347 }
00348 
00349 void OnTxDone( void ) {
00350     AppState = APP_TX;
00351 }
00352 
00353 void OnRxDone( void ) {
00354     int RssiValue, SnrValue;
00355     AppState = APP_RX;
00356     PacketStatus_t packetStatus;
00357     Radio.GetPacketStatus(&packetStatus);
00358     RssiValue = packetStatus.Params.LoRa.RssiPkt;
00359     SnrValue = packetStatus.Params.LoRa.SnrPkt;
00360     printf("rssi: %d; snr: %d\n\r", RssiValue, SnrValue );
00361 }
00362 
00363 void OnTxTimeout( void ) {
00364     AppState = APP_TX_TIMEOUT;
00365     printf( "<>>>>>>>>TXE\r\n" );
00366 }
00367 
00368 void OnRxTimeout( void ) {
00369     AppState = APP_RX_TIMEOUT;
00370 }
00371 
00372 void OnRxError( IrqErrorCode_t errorCode ) {
00373     AppState = APP_RX_ERROR;
00374     printf( "RXE<>>>>>>>>\r\n" );
00375 }
00376 
00377 void OnCadDone( bool channelActivityDetected ) {
00378 }
00379 
00380 
00381 void parser(char* serial_in) {
00382     printf("%s\n\r", serial_in);
00383     char command[10];
00384     long val;
00385     if(sscanf(serial_in, "%10s %lu", command, &val) != 2){
00386         printf("Invalid Input\n\r");
00387         return;
00388     }
00389     if(strcmp(command, "FREQ") == 0) {
00390         if((125000000<=val) && (val<=960000000)) {
00391             RF_FREQUENCY = val;
00392             printf("Frequency set to: %lu\n\r", val);
00393             LoRa_init();              
00394         }
00395     }
00396     else if(strcmp(command, "TX") == 0) {
00397         if((-22<=val) && (val<=13)) {
00398             TX_OUTPUT_POWER = val;
00399             printf("TX output power set to: %lu\n\r", val);
00400             LoRa_init(); 
00401         }
00402     }
00403     else if(strcmp(command, "S_F") == 0) {
00404         switch(val) {
00405             case 5:
00406                 spreading_factor = LORA_SF5;
00407             break;
00408             case 6:
00409                 spreading_factor = LORA_SF6;
00410             break;
00411             case 7:
00412                 spreading_factor = LORA_SF7;
00413             break;
00414             case 8:
00415                 spreading_factor = LORA_SF8;
00416             break;
00417             case 9:
00418                 spreading_factor = LORA_SF9;
00419             break;
00420             case 10:
00421                 spreading_factor = LORA_SF10;
00422             break;
00423             case 11:
00424                 spreading_factor = LORA_SF11;
00425             break;
00426             case 12:
00427                 spreading_factor = LORA_SF12;
00428             break;
00429             default:
00430                 printf("enter spreading factor between 5 and 12\n\r");
00431                 return;
00432         }
00433     }
00434     else if(strcmp(command, "CR") == 0) {
00435         switch(val) {
00436             case 45:
00437                 coding_rate = LORA_CR_4_5;
00438             break;
00439             case 46:
00440                 coding_rate = LORA_CR_4_6;
00441             break;
00442             case 47:
00443                 coding_rate = LORA_CR_4_7;
00444             break;
00445             case 48:
00446                 coding_rate = LORA_CR_4_8;
00447             break;
00448             default:
00449                 printf("enter valid coding rate\n\r");
00450                 return;
00451         }
00452         printf("Spreading factor changed to %lu\n\r", val);
00453         LoRa_init();
00454     }
00455     else if(strcmp(command, "BW") == 0) {
00456         switch(val) {
00457             case 500:
00458                 bandwidth = LORA_BW_500;
00459             break;
00460             case 250:
00461                 bandwidth = LORA_BW_250;
00462             break;
00463             case 125:
00464                 bandwidth = LORA_BW_125;
00465             break;
00466             case 62:
00467                 bandwidth = LORA_BW_062;
00468             break;
00469             case 41:
00470                 bandwidth = LORA_BW_041;
00471             break;
00472             case 31:
00473                 bandwidth = LORA_BW_031;
00474             break;
00475             case 20:
00476                 bandwidth = LORA_BW_020;
00477             break;
00478             case 15:
00479                 bandwidth = LORA_BW_015;
00480             break;
00481             case 10:
00482                 bandwidth = LORA_BW_010;
00483             break;
00484             case 7:
00485                 bandwidth = LORA_BW_007;
00486             break;
00487             default:
00488                 printf("Valid bandwidths: 500, 250, 125, 62, 41, 31, 20, ");
00489                 printf("15, 10, 7\n\r");
00490                 return;
00491         }
00492         
00493         
00494         // TODO separate master slave
00495         // TODO make a separate lorawan compatible
00496         // TODO view current settings
00497         // TODO stop display
00498         // ncurses
00499         printf("LoRa bandwidth changed to %lu\n\r", val);
00500         LoRa_init();
00501     }
00502     else
00503         printf("Invalid command\n\r");
00504     
00505         
00506 }