Lora pinpong demo (fork of https://developer.mbed.org/users/Helmut64/code/STM32L0_LoRa/ example)
Dependencies: BufferedSerial SX1276GenericLib mbed
Fork of STM32L0_LoRa by
GenericPingPong.cpp
00001 /* 00002 * This file contains a copy of the master content sx1276PingPong 00003 * with adaption for the SX1276Generic environment 00004 * (c) 2017 Helmut Tschemernjak 00005 * 30826 Garbsen (Hannover) Germany 00006 */ 00007 00008 #include "mbed.h" 00009 #include "PinMap.h" 00010 #include "GenericPingPong.h" 00011 #include "sx1276-mbed-hal.h" 00012 #include "main.h" 00013 00014 #ifdef FEATURE_LORA 00015 00016 /* Set this flag to '1' to display debug messages on the console */ 00017 #define DEBUG_MESSAGE 1 00018 00019 /* Set this flag to '1' to use the LoRa modulation or to '0' to use FSK modulation */ 00020 #define USE_MODEM_LORA 1 00021 #define USE_MODEM_FSK !USE_MODEM_LORA 00022 #define RF_FREQUENCY RF_FREQUENCY_868_1 // Hz 00023 #define TX_OUTPUT_POWER 14 // 14 dBm 00024 00025 #if USE_MODEM_LORA == 1 00026 00027 #define LORA_BANDWIDTH 125000 // LoRa default, details in SX1276::BandwidthMap 00028 #define LORA_SPREADING_FACTOR LORA_SF7 00029 #define LORA_CODINGRATE LORA_ERROR_CODING_RATE_4_5 00030 00031 #define LORA_PREAMBLE_LENGTH 8 // Same for Tx and Rx 00032 #define LORA_SYMBOL_TIMEOUT 5 // Symbols 00033 #define LORA_FIX_LENGTH_PAYLOAD_ON false 00034 #define LORA_FHSS_ENABLED false 00035 #define LORA_NB_SYMB_HOP 4 00036 #define LORA_IQ_INVERSION_ON false 00037 #define LORA_CRC_ENABLED true 00038 00039 #elif USE_MODEM_FSK == 1 00040 00041 #define FSK_FDEV 25000 // Hz 00042 #define FSK_DATARATE 19200 // bps 00043 #define FSK_BANDWIDTH 50000 // Hz 00044 #define FSK_AFC_BANDWIDTH 83333 // Hz 00045 #define FSK_PREAMBLE_LENGTH 5 // Same for Tx and Rx 00046 #define FSK_FIX_LENGTH_PAYLOAD_ON false 00047 #define FSK_CRC_ENABLED true 00048 00049 #else 00050 #error "Please define a modem in the compiler options." 00051 #endif 00052 00053 00054 #define RX_TIMEOUT_VALUE 3500 // in ms 00055 00056 //#define BUFFER_SIZE 32 // Define the payload size here 00057 #define BUFFER_SIZE 64 // Define the payload size here 00058 00059 /* 00060 * Global variables declarations 00061 */ 00062 typedef enum 00063 { 00064 LOWPOWER = 0, 00065 IDLE, 00066 00067 RX, 00068 RX_TIMEOUT, 00069 RX_ERROR, 00070 00071 TX, 00072 TX_TIMEOUT, 00073 00074 CAD, 00075 CAD_DONE 00076 } AppStates_t; 00077 00078 volatile AppStates_t State = LOWPOWER; 00079 00080 /*! 00081 * Radio events function pointer 00082 */ 00083 static RadioEvents_t RadioEvents; 00084 00085 /* 00086 * Global variables declarations 00087 */ 00088 SX1276Generic *Radio; 00089 00090 00091 const uint8_t PingMsg[] = { 0xff, 0xff, 0x00, 0x00, 'P', 'I', 'N', 'G'};// "PING"; 00092 const uint8_t PongMsg[] = { 0xff, 0xff, 0x00, 0x00, 'P', 'O', 'N', 'G'};// "PONG"; 00093 00094 uint16_t BufferSize = BUFFER_SIZE; 00095 uint8_t *Buffer; 00096 00097 DigitalOut *led3; 00098 00099 00100 int SX1276PingPong() 00101 { 00102 #if( defined ( TARGET_KL25Z ) || defined ( TARGET_LPC11U6X ) ) 00103 DigitalOut *led = new DigitalOut(LED2); 00104 #elif defined(TARGET_NUCLEO_L073RZ) || defined(TARGET_DISCO_L072CZ_LRWAN1) 00105 DigitalOut *led = new DigitalOut(LED4); // RX red 00106 led3 = new DigitalOut(LED3); // TX blue 00107 #else 00108 DigitalOut *led = new DigitalOut(LED1); 00109 led3 = led; 00110 #endif 00111 00112 Buffer = new uint8_t[BUFFER_SIZE]; 00113 *led3 = 1; 00114 00115 #ifdef B_L072Z_LRWAN1_LORA 00116 Radio = new SX1276Generic(NULL, MURATA_SX1276, 00117 LORA_SPI_MOSI, LORA_SPI_MISO, LORA_SPI_SCLK, LORA_CS, LORA_RESET, 00118 LORA_DIO0, LORA_DIO1, LORA_DIO2, LORA_DIO3, LORA_DIO4, LORA_DIO5, 00119 LORA_ANT_RX, LORA_ANT_TX, LORA_ANT_BOOST, LORA_TCXO); 00120 #else // RFM95 00121 Radio = new SX1276Generic(NULL, RFM95_SX1276, 00122 LORA_SPI_MOSI, LORA_SPI_MISO, LORA_SPI_SCLK, LORA_CS, LORA_RESET, 00123 LORA_DIO0, LORA_DIO1, LORA_DIO2, LORA_DIO3, LORA_DIO4, LORA_DIO5); 00124 00125 #endif 00126 00127 uint8_t i; 00128 bool isMaster = true; 00129 00130 dprintf("SX1276 Ping Pong Demo Application" ); 00131 dprintf("Freqency: %.1f", (double)RF_FREQUENCY/1000000.0); 00132 dprintf("TXPower: %d dBm", TX_OUTPUT_POWER); 00133 #if USE_MODEM_LORA == 1 00134 dprintf("Bandwidth: %d Hz", LORA_BANDWIDTH); 00135 dprintf("Spreading factor: SF%d", LORA_SPREADING_FACTOR); 00136 #elif USE_MODEM_FSK == 1 00137 dprintf("Bandwidth: %d kHz", FSK_BANDWIDTH); 00138 dprintf("Baudrate: %d", FSK_DATARATE); 00139 #endif 00140 // Initialize Radio driver 00141 RadioEvents.TxDone = OnTxDone; 00142 RadioEvents.RxDone = OnRxDone; 00143 RadioEvents.RxError = OnRxError; 00144 RadioEvents.TxTimeout = OnTxTimeout; 00145 RadioEvents.RxTimeout = OnRxTimeout; 00146 if (Radio->Init( &RadioEvents ) == false) { 00147 while(1) { 00148 dprintf("Radio could not be detected!"); 00149 wait( 1 ); 00150 } 00151 } 00152 00153 00154 switch(Radio->DetectBoardType()) { 00155 case SX1276MB1LAS: 00156 if (DEBUG_MESSAGE) 00157 dprintf(" > Board Type: SX1276MB1LAS <"); 00158 break; 00159 case SX1276MB1MAS: 00160 if (DEBUG_MESSAGE) 00161 dprintf(" > Board Type: SX1276MB1LAS <"); 00162 case MURATA_SX1276: 00163 if (DEBUG_MESSAGE) 00164 dprintf(" > Board Type: MURATA_SX1276_STM32L0 <"); 00165 break; 00166 case RFM95_SX1276: 00167 if (DEBUG_MESSAGE) 00168 dprintf(" > HopeRF RFM95xx <"); 00169 break; 00170 default: 00171 dprintf(" > Board Type: unknown <"); 00172 } 00173 00174 Radio->SetChannel(RF_FREQUENCY ); 00175 00176 #if USE_MODEM_LORA == 1 00177 00178 if (LORA_FHSS_ENABLED) 00179 dprintf(" > LORA FHSS Mode <"); 00180 if (!LORA_FHSS_ENABLED) 00181 dprintf(" > LORA Mode <"); 00182 00183 Radio->SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH, 00184 LORA_SPREADING_FACTOR, LORA_CODINGRATE, 00185 LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON, 00186 LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, 00187 LORA_IQ_INVERSION_ON, 2000 ); 00188 00189 Radio->SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, 00190 LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH, 00191 LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, 0, 00192 LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, 00193 LORA_IQ_INVERSION_ON, true ); 00194 00195 #elif USE_MODEM_FSK == 1 00196 00197 dprintf(" > FSK Mode <"); 00198 Radio->SetTxConfig( MODEM_FSK, TX_OUTPUT_POWER, FSK_FDEV, 0, 00199 FSK_DATARATE, 0, 00200 FSK_PREAMBLE_LENGTH, FSK_FIX_LENGTH_PAYLOAD_ON, 00201 FSK_CRC_ENABLED, 0, 0, 0, 2000 ); 00202 00203 Radio->SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE, 00204 0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH, 00205 0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, FSK_CRC_ENABLED, 00206 0, 0, false, true ); 00207 00208 #else 00209 00210 #error "Please define a modem in the compiler options." 00211 00212 #endif 00213 00214 if (DEBUG_MESSAGE) 00215 dprintf("Starting Ping-Pong loop"); 00216 00217 00218 Radio->Rx( RX_TIMEOUT_VALUE ); 00219 00220 while( 1 ) 00221 { 00222 #ifdef TARGET_STM32L4 00223 WatchDogUpdate(); 00224 #endif 00225 00226 switch( State ) 00227 { 00228 case RX: 00229 *led3 = 0; 00230 if( isMaster == true ) 00231 { 00232 if( BufferSize > 0 ) 00233 { 00234 if( memcmp(Buffer, PongMsg, sizeof(PongMsg)) == 0 ) 00235 { 00236 *led = !*led; 00237 dprintf( "...Pong" ); 00238 // Send the next PING frame 00239 memcpy(Buffer, PingMsg, sizeof(PingMsg)); 00240 // We fill the buffer with numbers for the payload 00241 for( i = sizeof(PingMsg); i < BufferSize; i++ ) 00242 { 00243 Buffer[i] = i - sizeof(PingMsg); 00244 } 00245 wait_ms( 10 ); 00246 Radio->Send( Buffer, BufferSize ); 00247 } 00248 else if( memcmp(Buffer, PingMsg, sizeof(PingMsg)) == 0 ) 00249 { // A master already exists then become a slave 00250 dprintf( "...Ping" ); 00251 *led = !*led; 00252 isMaster = false; 00253 // Send the next PONG frame 00254 memcpy(Buffer, PongMsg, sizeof(PongMsg)); 00255 // We fill the buffer with numbers for the payload 00256 for( i = sizeof(PongMsg); i < BufferSize; i++ ) 00257 { 00258 Buffer[i] = i - sizeof(PongMsg); 00259 } 00260 wait_ms( 10 ); 00261 Radio->Send( Buffer, BufferSize ); 00262 } 00263 else // valid reception but neither a PING or a PONG message 00264 { // Set device as master ans start again 00265 isMaster = true; 00266 Radio->Rx( RX_TIMEOUT_VALUE ); 00267 } 00268 } 00269 } 00270 else 00271 { 00272 if( BufferSize > 0 ) 00273 { 00274 if( memcmp(Buffer, PingMsg, sizeof(PingMsg)) == 0 ) 00275 { 00276 *led = !*led; 00277 dprintf( "...Ping" ); 00278 // Send the reply to the PING string 00279 memcpy(Buffer, PongMsg, sizeof(PongMsg)); 00280 // We fill the buffer with numbers for the payload 00281 for( i = sizeof(PongMsg); i < BufferSize; i++ ) 00282 { 00283 Buffer[i] = i - sizeof(PongMsg); 00284 } 00285 wait_ms( 10 ); 00286 Radio->Send( Buffer, BufferSize ); 00287 } 00288 else // valid reception but not a PING as expected 00289 { // Set device as master and start again 00290 isMaster = true; 00291 Radio->Rx( RX_TIMEOUT_VALUE ); 00292 } 00293 } 00294 } 00295 State = LOWPOWER; 00296 break; 00297 case TX: 00298 *led3 = 1; 00299 if( isMaster == true ) 00300 { 00301 dprintf("Ping..." ); 00302 } 00303 else 00304 { 00305 dprintf("Pong..." ); 00306 } 00307 Radio->Rx( RX_TIMEOUT_VALUE ); 00308 State = LOWPOWER; 00309 break; 00310 case RX_TIMEOUT: 00311 if( isMaster == true ) 00312 { 00313 // Send the next PING frame 00314 memcpy(Buffer, PingMsg, sizeof(PingMsg)); 00315 for( i = sizeof(PingMsg); i < BufferSize; i++ ) 00316 { 00317 Buffer[i] = i - sizeof(PingMsg); 00318 } 00319 wait_ms( 10 ); 00320 Radio->Send( Buffer, BufferSize ); 00321 } 00322 else 00323 { 00324 Radio->Rx( RX_TIMEOUT_VALUE ); 00325 } 00326 State = LOWPOWER; 00327 break; 00328 case RX_ERROR: 00329 // We have received a Packet with a CRC error, send reply as if packet was correct 00330 if( isMaster == true ) 00331 { 00332 // Send the next PING frame 00333 memcpy(Buffer, PingMsg, sizeof(PingMsg)); 00334 for( i = 4; i < BufferSize; i++ ) 00335 { 00336 Buffer[i] = i - 4; 00337 } 00338 wait_ms( 10 ); 00339 Radio->Send( Buffer, BufferSize ); 00340 } 00341 else 00342 { 00343 // Send the next PONG frame 00344 memcpy(Buffer, PongMsg, sizeof(PongMsg)); 00345 for( i = sizeof(PongMsg); i < BufferSize; i++ ) 00346 { 00347 Buffer[i] = i - sizeof(PongMsg); 00348 } 00349 wait_ms( 10 ); 00350 Radio->Send( Buffer, BufferSize ); 00351 } 00352 State = LOWPOWER; 00353 break; 00354 case TX_TIMEOUT: 00355 Radio->Rx( RX_TIMEOUT_VALUE ); 00356 State = LOWPOWER; 00357 break; 00358 case LOWPOWER: 00359 sleep(); 00360 break; 00361 default: 00362 State = LOWPOWER; 00363 break; 00364 } 00365 } 00366 } 00367 00368 void OnTxDone(void *radio, void *userThisPtr, void *userData) 00369 { 00370 Radio->Sleep( ); 00371 State = TX; 00372 if (DEBUG_MESSAGE) 00373 dprintf("> OnTxDone"); 00374 } 00375 00376 void OnRxDone(void *radio, void *userThisPtr, void *userData, uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr) 00377 { 00378 Radio->Sleep( ); 00379 BufferSize = size; 00380 memcpy( Buffer, payload, BufferSize ); 00381 State = RX; 00382 if (DEBUG_MESSAGE) 00383 dprintf("> OnRxDone: RssiValue=%d dBm, SnrValue=%d", rssi, snr); 00384 dump("Data:", payload, size); 00385 } 00386 00387 void OnTxTimeout(void *radio, void *userThisPtr, void *userData) 00388 { 00389 *led3 = 0; 00390 Radio->Sleep( ); 00391 State = TX_TIMEOUT; 00392 if(DEBUG_MESSAGE) 00393 dprintf("> OnTxTimeout"); 00394 } 00395 00396 void OnRxTimeout(void *radio, void *userThisPtr, void *userData) 00397 { 00398 *led3 = 0; 00399 Radio->Sleep( ); 00400 Buffer[BufferSize-1] = 0; 00401 State = RX_TIMEOUT; 00402 if (DEBUG_MESSAGE) 00403 dprintf("> OnRxTimeout"); 00404 } 00405 00406 void OnRxError(void *radio, void *userThisPtr, void *userData) 00407 { 00408 Radio->Sleep( ); 00409 State = RX_ERROR; 00410 if (DEBUG_MESSAGE) 00411 dprintf("> OnRxError"); 00412 } 00413 00414 #endif
Generated on Wed Jul 13 2022 19:16:22 by 1.7.2