Loïc Ringot
/
SX126X_PingPong_Demo
Ping Pong Demo with Lora Antenna and Nucleo board
Embed:
(wiki syntax)
Show/hide line numbers
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 }
Generated on Fri Jul 15 2022 02:02:18 by 1.7.2