Lora support for the STM B_L072Z_LRWAN1 board out of the box. Also supports HopeRF RFM95, Murata CMWX1ZZABZ and Semtech SX1276MB1MAS/SX1276MB1LAS modules.
Dependencies: BufferedSerial SX1276GenericLib mbed USBDeviceHT
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 #elif defined(HELTEC_STM32L4) 00121 Radio = new SX1276Generic(NULL, HELTEC_L4_1276, 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 POWER_VEXT); 00125 #else // RFM95 00126 Radio = new SX1276Generic(NULL, RFM95_SX1276, 00127 LORA_SPI_MOSI, LORA_SPI_MISO, LORA_SPI_SCLK, LORA_CS, LORA_RESET, 00128 LORA_DIO0, LORA_DIO1, LORA_DIO2, LORA_DIO3, LORA_DIO4, LORA_DIO5); 00129 #endif 00130 00131 uint8_t i; 00132 bool isMaster = true; 00133 00134 dprintf("SX1276 Ping Pong Demo Application" ); 00135 dprintf("Freqency: %.1f", (double)RF_FREQUENCY/1000000.0); 00136 dprintf("TXPower: %d dBm", TX_OUTPUT_POWER); 00137 #if USE_MODEM_LORA == 1 00138 dprintf("Bandwidth: %d Hz", LORA_BANDWIDTH); 00139 dprintf("Spreading factor: SF%d", LORA_SPREADING_FACTOR); 00140 #elif USE_MODEM_FSK == 1 00141 dprintf("Bandwidth: %d kHz", FSK_BANDWIDTH); 00142 dprintf("Baudrate: %d", FSK_DATARATE); 00143 #endif 00144 // Initialize Radio driver 00145 RadioEvents.TxDone = OnTxDone; 00146 RadioEvents.RxDone = OnRxDone; 00147 RadioEvents.RxError = OnRxError; 00148 RadioEvents.TxTimeout = OnTxTimeout; 00149 RadioEvents.RxTimeout = OnRxTimeout; 00150 if (Radio->Init( &RadioEvents ) == false) { 00151 while(1) { 00152 dprintf("Radio could not be detected!"); 00153 wait( 1 ); 00154 } 00155 } 00156 00157 00158 switch(Radio->DetectBoardType()) { 00159 case SX1276MB1LAS: 00160 if (DEBUG_MESSAGE) 00161 dprintf(" > Board Type: SX1276MB1LAS <"); 00162 break; 00163 case SX1276MB1MAS: 00164 if (DEBUG_MESSAGE) 00165 dprintf(" > Board Type: SX1276MB1LAS <"); 00166 case MURATA_SX1276: 00167 if (DEBUG_MESSAGE) 00168 dprintf(" > Board Type: MURATA_SX1276_STM32L0 <"); 00169 break; 00170 case RFM95_SX1276: 00171 if (DEBUG_MESSAGE) 00172 dprintf(" > HopeRF RFM95xx <"); 00173 break; 00174 default: 00175 dprintf(" > Board Type: unknown <"); 00176 } 00177 00178 Radio->SetChannel(RF_FREQUENCY ); 00179 00180 #if USE_MODEM_LORA == 1 00181 00182 if (LORA_FHSS_ENABLED) 00183 dprintf(" > LORA FHSS Mode <"); 00184 if (!LORA_FHSS_ENABLED) 00185 dprintf(" > LORA Mode <"); 00186 00187 Radio->SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH, 00188 LORA_SPREADING_FACTOR, LORA_CODINGRATE, 00189 LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON, 00190 LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, 00191 LORA_IQ_INVERSION_ON, 2000 ); 00192 00193 Radio->SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, 00194 LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH, 00195 LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, 0, 00196 LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, 00197 LORA_IQ_INVERSION_ON, true ); 00198 00199 #elif USE_MODEM_FSK == 1 00200 00201 dprintf(" > FSK Mode <"); 00202 Radio->SetTxConfig( MODEM_FSK, TX_OUTPUT_POWER, FSK_FDEV, 0, 00203 FSK_DATARATE, 0, 00204 FSK_PREAMBLE_LENGTH, FSK_FIX_LENGTH_PAYLOAD_ON, 00205 FSK_CRC_ENABLED, 0, 0, 0, 2000 ); 00206 00207 Radio->SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE, 00208 0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH, 00209 0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, FSK_CRC_ENABLED, 00210 0, 0, false, true ); 00211 00212 #else 00213 00214 #error "Please define a modem in the compiler options." 00215 00216 #endif 00217 00218 if (DEBUG_MESSAGE) 00219 dprintf("Starting Ping-Pong loop"); 00220 00221 00222 Radio->Rx( RX_TIMEOUT_VALUE ); 00223 00224 while( 1 ) 00225 { 00226 #ifdef TARGET_STM32L4 00227 // WatchDogUpdate(); 00228 #endif 00229 00230 switch( State ) 00231 { 00232 case RX: 00233 *led3 = 0; 00234 if( isMaster == true ) 00235 { 00236 if( BufferSize > 0 ) 00237 { 00238 if( memcmp(Buffer, PongMsg, sizeof(PongMsg)) == 0 ) 00239 { 00240 *led = !*led; 00241 dprintf( "...Pong" ); 00242 // Send the next PING frame 00243 memcpy(Buffer, PingMsg, sizeof(PingMsg)); 00244 // We fill the buffer with numbers for the payload 00245 for( i = sizeof(PingMsg); i < BufferSize; i++ ) 00246 { 00247 Buffer[i] = i - sizeof(PingMsg); 00248 } 00249 wait_ms( 10 ); 00250 Radio->Send( Buffer, BufferSize ); 00251 } 00252 else if( memcmp(Buffer, PingMsg, sizeof(PingMsg)) == 0 ) 00253 { // A master already exists then become a slave 00254 dprintf( "...Ping" ); 00255 *led = !*led; 00256 isMaster = false; 00257 // Send the next PONG frame 00258 memcpy(Buffer, PongMsg, sizeof(PongMsg)); 00259 // We fill the buffer with numbers for the payload 00260 for( i = sizeof(PongMsg); i < BufferSize; i++ ) 00261 { 00262 Buffer[i] = i - sizeof(PongMsg); 00263 } 00264 wait_ms( 10 ); 00265 Radio->Send( Buffer, BufferSize ); 00266 } 00267 else // valid reception but neither a PING or a PONG message 00268 { // Set device as master ans start again 00269 isMaster = true; 00270 Radio->Rx( RX_TIMEOUT_VALUE ); 00271 } 00272 } 00273 } 00274 else 00275 { 00276 if( BufferSize > 0 ) 00277 { 00278 if( memcmp(Buffer, PingMsg, sizeof(PingMsg)) == 0 ) 00279 { 00280 *led = !*led; 00281 dprintf( "...Ping" ); 00282 // Send the reply to the PING string 00283 memcpy(Buffer, PongMsg, sizeof(PongMsg)); 00284 // We fill the buffer with numbers for the payload 00285 for( i = sizeof(PongMsg); i < BufferSize; i++ ) 00286 { 00287 Buffer[i] = i - sizeof(PongMsg); 00288 } 00289 wait_ms( 10 ); 00290 Radio->Send( Buffer, BufferSize ); 00291 } 00292 else // valid reception but not a PING as expected 00293 { // Set device as master and start again 00294 isMaster = true; 00295 Radio->Rx( RX_TIMEOUT_VALUE ); 00296 } 00297 } 00298 } 00299 State = LOWPOWER; 00300 break; 00301 case TX: 00302 *led3 = 1; 00303 if( isMaster == true ) 00304 { 00305 dprintf("Ping..." ); 00306 } 00307 else 00308 { 00309 dprintf("Pong..." ); 00310 } 00311 Radio->Rx( RX_TIMEOUT_VALUE ); 00312 State = LOWPOWER; 00313 break; 00314 case RX_TIMEOUT: 00315 if( isMaster == true ) 00316 { 00317 // Send the next PING frame 00318 memcpy(Buffer, PingMsg, sizeof(PingMsg)); 00319 for( i = sizeof(PingMsg); i < BufferSize; i++ ) 00320 { 00321 Buffer[i] = i - sizeof(PingMsg); 00322 } 00323 wait_ms( 10 ); 00324 Radio->Send( Buffer, BufferSize ); 00325 } 00326 else 00327 { 00328 Radio->Rx( RX_TIMEOUT_VALUE ); 00329 } 00330 State = LOWPOWER; 00331 break; 00332 case RX_ERROR: 00333 // We have received a Packet with a CRC error, send reply as if packet was correct 00334 if( isMaster == true ) 00335 { 00336 // Send the next PING frame 00337 memcpy(Buffer, PingMsg, sizeof(PingMsg)); 00338 for( i = 4; i < BufferSize; i++ ) 00339 { 00340 Buffer[i] = i - 4; 00341 } 00342 wait_ms( 10 ); 00343 Radio->Send( Buffer, BufferSize ); 00344 } 00345 else 00346 { 00347 // Send the next PONG frame 00348 memcpy(Buffer, PongMsg, sizeof(PongMsg)); 00349 for( i = sizeof(PongMsg); i < BufferSize; i++ ) 00350 { 00351 Buffer[i] = i - sizeof(PongMsg); 00352 } 00353 wait_ms( 10 ); 00354 Radio->Send( Buffer, BufferSize ); 00355 } 00356 State = LOWPOWER; 00357 break; 00358 case TX_TIMEOUT: 00359 Radio->Rx( RX_TIMEOUT_VALUE ); 00360 State = LOWPOWER; 00361 break; 00362 case LOWPOWER: 00363 sleep(); 00364 break; 00365 default: 00366 State = LOWPOWER; 00367 break; 00368 } 00369 } 00370 } 00371 00372 void OnTxDone(void *radio, void *userThisPtr, void *userData) 00373 { 00374 Radio->Sleep( ); 00375 State = TX; 00376 if (DEBUG_MESSAGE) 00377 dprintf("> OnTxDone"); 00378 } 00379 00380 void OnRxDone(void *radio, void *userThisPtr, void *userData, uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr) 00381 { 00382 Radio->Sleep( ); 00383 BufferSize = size; 00384 memcpy( Buffer, payload, BufferSize ); 00385 State = RX; 00386 if (DEBUG_MESSAGE) 00387 dprintf("> OnRxDone: RssiValue=%d dBm, SnrValue=%d", rssi, snr); 00388 dump("Data:", payload, size); 00389 } 00390 00391 void OnTxTimeout(void *radio, void *userThisPtr, void *userData) 00392 { 00393 *led3 = 0; 00394 Radio->Sleep( ); 00395 State = TX_TIMEOUT; 00396 if(DEBUG_MESSAGE) 00397 dprintf("> OnTxTimeout"); 00398 } 00399 00400 void OnRxTimeout(void *radio, void *userThisPtr, void *userData) 00401 { 00402 *led3 = 0; 00403 Radio->Sleep( ); 00404 Buffer[BufferSize-1] = 0; 00405 State = RX_TIMEOUT; 00406 if (DEBUG_MESSAGE) 00407 dprintf("> OnRxTimeout"); 00408 } 00409 00410 void OnRxError(void *radio, void *userThisPtr, void *userData) 00411 { 00412 Radio->Sleep( ); 00413 State = RX_ERROR; 00414 if (DEBUG_MESSAGE) 00415 dprintf("> OnRxError"); 00416 } 00417 00418 #endif
Generated on Fri Jul 15 2022 00:33:04 by 1.7.2