Lora pinpong demo (fork of https://developer.mbed.org/users/Helmut64/code/STM32L0_LoRa/ example)

Dependencies:   BufferedSerial SX1276GenericLib mbed

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