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