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

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_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