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 Devin Alexander

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers GenericPingPong.cpp Source File

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