got this sample program for 2+ sx1276 modules to communicate in a ping pong fashion. This program has been tested and verified to run with 915MHz Hope RFM95 modules running with MAX32620FTHR and MAX32630FTHR micro controllers.

Dependencies:   BMI160 BufferedSerial SX1276GenericLib USBDeviceHT max32630fthr

Fork of STM32L0_LoRa by Helmut Tschemernjak

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