Ping Pong Demo with Lora Antenna and Nucleo board

Dependencies:   mbed SX126xLib

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main_pingpong.cpp Source File

main_pingpong.cpp

Go to the documentation of this file.
00001 /*!
00002  * \file      main_pingpong.cpp
00003  *
00004  * \brief     Ping-Pong implementation
00005  *
00006  * \copyright Revised BSD License, see section \ref LICENSE.
00007  *
00008  * \code
00009  *                ______                              _
00010  *               / _____)             _              | |
00011  *              ( (____  _____ ____ _| |_ _____  ____| |__
00012  *               \____ \| ___ |    (_   _) ___ |/ ___)  _ \
00013  *               _____) ) ____| | | || |_| ____( (___| | | |
00014  *              (______/|_____)_|_|_| \__)_____)\____)_| |_|
00015  *              (C)2013-2018 Semtech
00016  *
00017  * \endcode
00018  *
00019  */
00020 
00021 #include "mbed.h"
00022 #include "sx126x-hal.h"
00023 #include "sx126x.h"
00024 //#include "debug.h"
00025  
00026 #define SEND_PING_BEAT_US 200000
00027 #define RX_TIMEOUT_US 200000
00028 
00029 /* Set this flag to '1' to display debug messages on the console */
00030 #define DEBUG_MESSAGE   1
00031  
00032 /* Set this flag to '1' to use the LoRa modulation or to '0' to use FSK modulation */
00033 #define USE_MODEM_LORA  1
00034 #define USE_MODEM_FSK   !USE_MODEM_LORA
00035  
00036 #define RF_FREQUENCY                                    868000000 // Hz
00037 #define TX_OUTPUT_POWER                                 14        // 14 dBm
00038  
00039 #if USE_MODEM_LORA == 1
00040  
00041     #define LORA_BANDWIDTH                              LORA_BW_500         // [0: 125 kHz,
00042                                                                   //  1: 250 kHz,
00043                                                                   //  2: 500 kHz,
00044                                                                   //  3: Reserved]
00045     #define LORA_SPREADING_FACTOR                       LORA_SF7         // [SF7..SF12]
00046     #define LORA_LOWDATARATEOPTIMIZE                    0
00047     #define LORA_CODINGRATE                             LORA_CR_4_5         // [1: 4/5,
00048                                                                   //  2: 4/6,
00049                                                                   //  3: 4/7,
00050                                                                   //  4: 4/8]
00051     #define LORA_PREAMBLE_LENGTH                        8         // Same for Tx and Rx
00052     #define LORA_SYMBOL_TIMEOUT                         5         // Symbols
00053     #define LORA_HEADER_TYPE                            LORA_PACKET_VARIABLE_LENGTH
00054     #define LORA_FHSS_ENABLED                           false  
00055     #define LORA_NB_SYMB_HOP                            4     
00056     #define LORA_IQ                                     LORA_IQ_NORMAL
00057     #define LORA_CRC_MODE                               LORA_CRC_OFF
00058  
00059 #elif USE_MODEM_FSK == 1
00060  
00061     #define FSK_FDEV                                    25000     // Hz
00062     #define FSK_DATARATE                                19200     // bps
00063     #define FSK_BANDWIDTH                               RX_BW_93800     // Hz
00064     #define FSK_MODULATION_SHAPPING                     MOD_SHAPING_G_BT_05
00065     #define FSK_PREAMBLE_LENGTH                         5         // Same for Tx and Rx
00066     #define FSK_HEADER_TYPE                             RADIO_PACKET_VARIABLE_LENGTH
00067     #define FSK_CRC_MODE                                RADIO_CRC_2_BYTES_CCIT
00068     #define FSK_ADDR_FILTERING                          RADIO_ADDRESSCOMP_FILT_NODE;
00069     #define FSK_WHITENING_MODE                          RADIO_DC_FREE_OFF
00070     #define FSK_PREAMBLE_DETECTOR_MODE                  RADIO_PREAMBLE_DETECTOR_OFF
00071     #define FSK_SYNCWORD_LENGTH                         8
00072 #else
00073     #error "Please define a modem in the compiler options."
00074 #endif
00075  
00076 #define RX_TIMEOUT_VALUE                                3500      // in ms
00077 #define BUFFER_SIZE                                     32        // Define the payload size here
00078  
00079 #if( defined ( TARGET_KL25Z ) || defined ( TARGET_LPC11U6X ) )
00080 DigitalOut led( LED2 );
00081 #else
00082 DigitalOut led( LED1 );
00083 #endif
00084  
00085  /*
00086  * Callback functions prototypes
00087  */
00088 /*!
00089  * @brief Function to be executed on Radio Tx Done event
00090  */
00091 void OnTxDone( void );
00092  
00093 /*!
00094  * @brief Function to be executed on Radio Rx Done event
00095  */
00096 void OnRxDone( void );
00097  
00098 /*!
00099  * @brief Function executed on Radio Tx Timeout event
00100  */
00101 void OnTxTimeout( void );
00102  
00103 /*!
00104  * @brief Function executed on Radio Rx Timeout event
00105  */
00106 void OnRxTimeout( void );
00107  
00108 /*!
00109  * @brief Function executed on Radio Rx Error event
00110  */
00111 void OnRxError( IrqErrorCode_t errCode );
00112  
00113 /*!
00114  * @brief Function executed on Radio Fhss Change Channel event
00115  */
00116 void OnFhssChangeChannel( uint8_t channelIndex );
00117 
00118 typedef struct{
00119     RadioPacketTypes_t packetType;
00120     int8_t txPower;
00121     RadioRampTimes_t txRampTime;
00122     ModulationParams_t modParams;
00123     PacketParams_t packetParams;
00124     uint32_t rfFrequency;
00125     uint16_t irqTx;
00126     uint16_t irqRx;
00127     uint32_t txTimeout;
00128     uint32_t rxTimeout;
00129 }RadioConfigurations_t;
00130 RadioConfigurations_t radioConfiguration;
00131  
00132 /*
00133  *  Global variables declarations
00134  */
00135 typedef enum
00136 {
00137     SEND_PACKET,
00138     WAIT_SEND_DONE,
00139     RECEIVE_PACKET,
00140     WAIT_RECEIVE_DONE,
00141     PACKET_RECEIVED,
00142 }AppStates_t;
00143 volatile AppStates_t State = SEND_PACKET;
00144 
00145 typedef struct{
00146     bool rxDone;
00147     bool rxError;
00148     bool txDone;
00149     bool rxTimeout;
00150     bool txTimeout;
00151 }RadioFlags_t;
00152 RadioFlags_t radioFlags = {
00153     .txDone = false,
00154     .rxDone = false,
00155     .rxError = false,
00156     .rxTimeout = false,
00157     .txTimeout = false,
00158 };
00159  
00160 /*!
00161  * Radio events function pointer
00162  */
00163 static RadioCallbacks_t RadioEvents  = {
00164     .txDone = &OnTxDone,
00165     .txTimeout = &OnTxTimeout,
00166     .rxDone = &OnRxDone,
00167     .rxPreambleDetect = NULL,
00168     .rxHeaderDone = NULL,
00169     .rxTimeout = &OnRxTimeout,
00170     .rxError = &OnRxError,
00171     .cadDone = NULL,
00172 };
00173 
00174 /*
00175  *  Global variables declarations
00176  */
00177 //Radio Radio( NULL );
00178 #define MESSAGE_SIZE 4
00179 typedef uint8_t Messages_t[MESSAGE_SIZE];
00180 const Messages_t PingMsg = {'P', 'I', 'N', 'G'};
00181 const Messages_t PongMsg = {'P', 'O', 'N', 'G'};
00182 const Messages_t *messageToReceive = &PongMsg;
00183 const Messages_t *messageToSend = &PingMsg;
00184  
00185 uint8_t BufferSize = BUFFER_SIZE;
00186 uint8_t Buffer[BUFFER_SIZE];
00187  
00188 int8_t RssiValue = 0;
00189 int8_t SnrValue = 0;
00190 
00191 void GetRssiSnr(int8_t *rssi, int8_t *snr);
00192 SX126xHal Radio( D11, D12, D13, D7, D3, D5, NC, NC, A0, A1, A2, D8, &RadioEvents  );
00193 
00194 void SetToMaster(void);
00195 void SetToSlave(void);
00196 void RunMasterStateMachine();
00197 void RunSlaveStateMachine();
00198 void SetConfiguration(RadioConfigurations_t *config);
00199 void ConfigureGeneralRadio(SX126xHal *radio, RadioConfigurations_t *config);
00200 void ConfigureRadioTx(SX126xHal *radio, RadioConfigurations_t *config);
00201 void ConfigureRadioRx(SX126xHal *radio, RadioConfigurations_t *config);
00202 void PrepareBuffer(SX126xHal *radio, const Messages_t *messageToSend);
00203 bool isMaster = false;
00204 bool masterCanSend = true;
00205 void MasterSendNextEvent(void){masterCanSend = true;}
00206 bool slaveCanListen = false;
00207 void SlaveListenNextEvent(void){slaveCanListen = true;}
00208 Ticker masterSendNextTicker;
00209 Ticker slaveListenNextTicker;
00210 
00211 Serial serial(USBTX, USBRX);
00212 
00213 int main( void ) 
00214 {
00215     Radio.Reset();
00216     Radio.Init();
00217     serial.baud(115200);
00218     SetToMaster();
00219     SetConfiguration(&radioConfiguration);
00220     ConfigureGeneralRadio(&Radio, &radioConfiguration);
00221     while(true){
00222         if(isMaster){
00223             RunMasterStateMachine();
00224         }
00225         else{
00226             RunSlaveStateMachine();
00227         }
00228     }
00229 }
00230 
00231 void RunMasterStateMachine(){
00232     switch(State){
00233         case SEND_PACKET:{
00234             if(masterCanSend == true){
00235                 masterCanSend = false;
00236                 masterSendNextTicker.attach_us(&MasterSendNextEvent, SEND_PING_BEAT_US);
00237                 PrepareBuffer(&Radio, messageToSend);
00238                 ConfigureRadioTx(&Radio, &radioConfiguration);
00239                 Radio.SetTx(radioConfiguration.txTimeout);
00240                 printf("Ping...\n");
00241                 State = WAIT_SEND_DONE;
00242             }
00243             break;
00244         }
00245         
00246         case WAIT_SEND_DONE:{
00247             if(radioFlags.txDone){
00248                 radioFlags.txDone = false;
00249                 State = RECEIVE_PACKET;
00250             }
00251             if(radioFlags.txTimeout){
00252                 radioFlags.txTimeout = false;
00253                 State = SEND_PACKET;
00254             }
00255             break;
00256         }
00257         
00258         case RECEIVE_PACKET:{
00259             ConfigureRadioRx(&Radio, &radioConfiguration);
00260             Radio.SetRx(radioConfiguration.rxTimeout);
00261             State = WAIT_RECEIVE_DONE;
00262             break;
00263         }
00264         
00265         case WAIT_RECEIVE_DONE:{
00266             if(radioFlags.rxDone == true){
00267                 radioFlags.rxDone = false;
00268                 State = PACKET_RECEIVED;
00269             }
00270             if(radioFlags.rxTimeout == true){
00271                 radioFlags.rxTimeout = false;
00272                 State = SEND_PACKET;
00273             }
00274             break;
00275         }
00276         
00277         case PACKET_RECEIVED:{
00278             Radio.GetPayload( Buffer, &BufferSize, BUFFER_SIZE );
00279             RssiValue = Radio.GetRssiInst();
00280             GetRssiSnr(&RssiValue, &SnrValue);
00281             if( strncmp(( const char* )Buffer, (const char*)messageToReceive, MESSAGE_SIZE ) == 0 ){
00282                 printf("...Pong\n");
00283                 State = SEND_PACKET;
00284             }
00285             else if( strncmp(( const char* )Buffer, (const char*)messageToSend, MESSAGE_SIZE ) == 0 ){
00286                 // Another Master is in the air, swith to slave
00287                 SetToSlave();
00288             }
00289             else{
00290                 printf("WRONG PAYLOAD\n");
00291                 SetToMaster();
00292             }
00293             break;
00294         }
00295     }
00296 }
00297 
00298 void RunSlaveStateMachine(){
00299     switch(State){
00300         case RECEIVE_PACKET:{
00301             if(slaveCanListen == true){
00302                 slaveCanListen = false;
00303                 ConfigureRadioRx(&Radio, &radioConfiguration);
00304                 Radio.SetRx(radioConfiguration.rxTimeout);
00305                 slaveListenNextTicker.attach_us(&SlaveListenNextEvent, SEND_PING_BEAT_US - ( RX_TIMEOUT_US>>1 ));
00306                 State = WAIT_RECEIVE_DONE;
00307             }
00308             break;
00309         }
00310         
00311         case WAIT_RECEIVE_DONE:{
00312             if(radioFlags.rxDone == true){
00313                 radioFlags.rxDone = false;
00314                 State = PACKET_RECEIVED;
00315             }
00316             if(radioFlags.rxTimeout == true){
00317                 radioFlags.rxTimeout = false;
00318                 SetToMaster();
00319             }
00320             break;
00321         }
00322         
00323         case PACKET_RECEIVED:{
00324             Radio.GetPayload( Buffer, &BufferSize, BUFFER_SIZE );
00325             RssiValue = Radio.GetRssiInst();
00326             GetRssiSnr(&RssiValue, &SnrValue);
00327             if( strncmp(( const char* )Buffer, (const char*)messageToReceive, MESSAGE_SIZE ) == 0 ){
00328                 printf("...Ping\n");
00329                 State = SEND_PACKET;
00330             }
00331             else{
00332                 SetToMaster();
00333             }
00334             break;
00335         }
00336         
00337         case SEND_PACKET:{
00338             PrepareBuffer(&Radio, messageToSend);
00339             ConfigureRadioTx(&Radio, &radioConfiguration);
00340             printf("Pong...\n");
00341             Radio.SetTx(radioConfiguration.txTimeout);
00342             State = WAIT_SEND_DONE;
00343             break;
00344         }
00345         
00346         case WAIT_SEND_DONE:{
00347             if(radioFlags.txDone){
00348                 radioFlags.txDone = false;
00349                 State = RECEIVE_PACKET;
00350             }
00351             if(radioFlags.txTimeout){
00352                 radioFlags.txTimeout = false;
00353                 SetToMaster();
00354             }
00355             break;
00356         }
00357     }
00358 }
00359 
00360 void SetToMaster(){
00361     printf("-->Master\n");
00362     isMaster = true;
00363     masterCanSend = true;
00364     State = SEND_PACKET;
00365     messageToReceive = &PongMsg;
00366     messageToSend = &PingMsg;
00367 }
00368 
00369 void SetToSlave(){
00370     slaveCanListen = false;
00371     slaveListenNextTicker.attach_us(&SlaveListenNextEvent, SEND_PING_BEAT_US - ( RX_TIMEOUT_US>>1 ));
00372     printf("--> Slave\n");
00373     isMaster = false;
00374     State = RECEIVE_PACKET;
00375     messageToReceive = &PingMsg;
00376     messageToSend = &PongMsg;
00377 }
00378  
00379 void OnTxDone( void )
00380 {
00381     radioFlags.txDone = true;
00382 }
00383  
00384 void OnRxDone( void )
00385 {
00386     radioFlags.rxDone = true;
00387 }
00388  
00389 void OnTxTimeout( void )
00390 {
00391     radioFlags.txTimeout = true;
00392     debug_if( DEBUG_MESSAGE, "> OnTxTimeout\n\r" );
00393 }
00394  
00395 void OnRxTimeout( void )
00396 {
00397     radioFlags.rxTimeout = true;
00398     debug_if( DEBUG_MESSAGE, "> OnRxTimeout\n\r" );
00399 }
00400  
00401 void OnRxError( IrqErrorCode_t errCode )
00402 {
00403     radioFlags.rxError = true;
00404     debug_if( DEBUG_MESSAGE, "> OnRxError\n\r" );
00405 }
00406 
00407 void SetConfiguration(RadioConfigurations_t *config){
00408     config->irqRx = IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT;
00409     config->irqTx = IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT;
00410     config->rfFrequency = RF_FREQUENCY;
00411     config->txTimeout = 0;
00412     config->rxTimeout = (uint32_t)(RX_TIMEOUT_US / 15.625);
00413     config->txPower = TX_OUTPUT_POWER;
00414     config->txRampTime = RADIO_RAMP_200_US;
00415     #if USE_MODEM_LORA == 1
00416         config->packetType = PACKET_TYPE_LORA;
00417         config->modParams.PacketType = PACKET_TYPE_LORA;
00418         config->modParams.Params.LoRa.Bandwidth = LORA_BANDWIDTH;
00419         config->modParams.Params.LoRa.CodingRate = LORA_CODINGRATE;
00420         config->modParams.Params.LoRa.LowDatarateOptimize = LORA_LOWDATARATEOPTIMIZE;
00421         config->modParams.Params.LoRa.SpreadingFactor = LORA_SPREADING_FACTOR;
00422         config->packetParams.PacketType = PACKET_TYPE_LORA;
00423         config->packetParams.Params.LoRa.CrcMode = LORA_CRC_MODE;
00424         config->packetParams.Params.LoRa.HeaderType = LORA_HEADER_TYPE;
00425         config->packetParams.Params.LoRa.InvertIQ = LORA_IQ;
00426         config->packetParams.Params.LoRa.PayloadLength = BUFFER_SIZE;
00427         config->packetParams.Params.LoRa.PreambleLength = LORA_PREAMBLE_LENGTH;
00428     #elif USE_MODEM_FSK == 1
00429         config->packetType = PACKET_TYPE_GFSK;
00430         config->modParams.PacketType = PACKET_TYPE_GFSK;
00431         config->modParams.Params.Gfsk.Bandwidth = FSK_BANDWIDTH;
00432         config->modParams.Params.Gfsk.BitRate = 1024000000 / FSK_DATARATE;
00433         config->modParams.Params.Gfsk.Fdev = FSK_FDEV * 1.048576;
00434         config->modParams.Params.Gfsk.ModulationShaping = FSK_MODULATION_SHAPPING;
00435         config->packetParams.PacketType = PACKET_TYPE_GFSK;
00436         config->packetParams.Params.Gfsk.AddrComp = FSK_ADDR_FILTERING;
00437         config->packetParams.Params.Gfsk.CrcLength = FSK_CRC_MODE;
00438         config->packetParams.Params.Gfsk.DcFree = FSK_WHITENING_MODE;
00439         config->packetParams.Params.Gfsk.HeaderType = FSK_HEADER_TYPE;
00440         config->packetParams.Params.Gfsk.PayloadLength = BUFFER_SIZE;
00441         config->packetParams.Params.Gfsk.PreambleLength = FSK_PREAMBLE_LENGTH;
00442         config->packetParams.Params.Gfsk.PreambleMinDetect = FSK_PREAMBLE_DETECTOR_MODE;
00443         config->packetParams.Params.Gfsk.SyncWordLength = FSK_SYNCWORD_LENGTH;
00444     #endif
00445 }
00446 
00447 void ConfigureGeneralRadio(SX126xHal *radio, RadioConfigurations_t *config){
00448     radio->SetPacketType(config->packetType);
00449     radio->SetPacketParams(&config->packetParams);
00450     radio->SetModulationParams(&config->modParams);
00451     radio->SetRfFrequency(config->rfFrequency);
00452     radio->SetTxParams(config->txPower, config->txRampTime);
00453     radio->SetInterruptMode();
00454     if(config->packetType == PACKET_TYPE_GFSK){
00455         uint8_t syncword[8] = {0xF0, 0x0F, 0x55, 0xAA, 0xF0, 0x0F, 0x55, 0xAA};
00456         radio->SetSyncWord(syncword);
00457     }
00458 }
00459 
00460 void ConfigureRadioTx(SX126xHal *radio, RadioConfigurations_t *config){
00461     radio->SetDioIrqParams(config->irqTx, config->irqTx, IRQ_RADIO_NONE, IRQ_RADIO_NONE);
00462 }
00463 
00464 void ConfigureRadioRx(SX126xHal *radio, RadioConfigurations_t *config){
00465     radio->SetDioIrqParams(config->irqRx, config->irqRx, IRQ_RADIO_NONE, IRQ_RADIO_NONE);
00466 }
00467 
00468 void PrepareBuffer(SX126xHal *radio, const Messages_t *messageToSend){
00469     radio->SetPayload((uint8_t*)messageToSend, MESSAGE_SIZE);
00470 }
00471 
00472 void GetRssiSnr(int8_t *rssi, int8_t *snr)
00473 {
00474     PacketStatus_t pkt_stat;
00475     Radio.GetPacketStatus(&pkt_stat);    
00476     #if USE_MODEM_LORA == 1
00477         *rssi = pkt_stat.Params.LoRa.RssiPkt;
00478         *snr = pkt_stat.Params.LoRa.SnrPkt;
00479     #else
00480         *rssi = pkt_stat.Params.Gfsk.RssiSync;
00481     #endif
00482 }