RadioShuttle Lib for the STM32 L4 Heltec Board

Dependents:   Turtle_RadioShuttle

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers GenericPingPong.cpp Source File

GenericPingPong.cpp

00001 
00002 #include "mbed.h"
00003 #include "PinMap.h"
00004 #include "GenericPingPong.h"
00005 #if defined(DEVICE_LPTICKER) || defined(DEVICE_LOWPOWERTIMER) // LOWPOWERTIMER in older mbed versions
00006 #define MyTimeout LowPowerTimeout
00007 #else
00008 #define MyTimeout Timeout
00009 #endif
00010 #include "sx1276-mbed-hal.h"
00011 #include "main.h"
00012 
00013 #ifdef FEATURE_LORA_PING_PONG
00014 
00015 /* Set this flag to '1' to display debug messages on the console */
00016 #define DEBUG_MESSAGE   1
00017 
00018 /* Set this flag to '1' to use the LoRa modulation or to '0' to use FSK modulation */
00019 #define USE_MODEM_LORA  1
00020 #define USE_MODEM_FSK   !USE_MODEM_LORA
00021 #define RF_FREQUENCY            RF_FREQUENCY_868_1  // Hz
00022 #define TX_OUTPUT_POWER         14                  // 14 dBm
00023 
00024 #if USE_MODEM_LORA == 1
00025 
00026 #define LORA_BANDWIDTH          125000 // see LoRa bandwidth map for details  
00027 #define LORA_SPREADING_FACTOR   LORA_SF7
00028 #define LORA_CODINGRATE         LORA_ERROR_CODING_RATE_4_5
00029 
00030 #define LORA_PREAMBLE_LENGTH    8       // Same for Tx and Rx
00031 #define LORA_SYMBOL_TIMEOUT     5       // Symbols
00032 #define LORA_FIX_LENGTH_PAYLOAD_ON  false
00033 #define LORA_FHSS_ENABLED       false  
00034 #define LORA_NB_SYMB_HOP        4     
00035 #define LORA_IQ_INVERSION_ON    false
00036 #define LORA_CRC_ENABLED        true
00037     
00038 #elif USE_MODEM_FSK == 1
00039 
00040 #define FSK_FDEV                25000     // Hz
00041 #define FSK_DATARATE            19200     // bps
00042 #define FSK_BANDWIDTH           50000     // Hz
00043 #define FSK_AFC_BANDWIDTH       83333     // Hz
00044 #define FSK_PREAMBLE_LENGTH     5         // Same for Tx and Rx
00045 #define FSK_FIX_LENGTH_PAYLOAD_ON   false
00046 #define FSK_CRC_ENABLED         true
00047     
00048 #else
00049     #error "Please define a modem in the compiler options."
00050 #endif 
00051 
00052 
00053 #define RX_TIMEOUT_VALUE    3500    // in ms
00054 
00055 //#define BUFFER_SIZE       32        // Define the payload size here
00056 #define BUFFER_SIZE         64        // Define the payload size here
00057 
00058 /*
00059  *  Global variables declarations
00060  */
00061 typedef enum
00062 {
00063     LOWPOWER = 0,
00064     IDLE,
00065     
00066     RX,
00067     RX_TIMEOUT,
00068     RX_ERROR,
00069     
00070     TX,
00071     TX_TIMEOUT,
00072     
00073     CAD,
00074     CAD_DONE
00075 } AppStates_t;
00076 
00077 volatile AppStates_t State = LOWPOWER;
00078 
00079 /*!
00080  * Radio events function pointer
00081  */
00082 static RadioEvents_t RadioEvents;
00083 
00084 /*
00085  *  Global variables declarations
00086  */
00087 SX1276Generic *Radio;
00088 
00089 
00090 const uint8_t PingMsg[] = { 0xff, 0xff, 0x00, 0x00, 'P', 'I', 'N', 'G'};// "PING";
00091 const uint8_t PongMsg[] = { 0xff, 0xff, 0x00, 0x00, 'P', 'O', 'N', 'G'};// "PONG";
00092 
00093 uint16_t BufferSize = BUFFER_SIZE;
00094 uint8_t *Buffer;
00095 
00096 DigitalOut *led3;
00097 
00098 
00099 int SX1276PingPong()
00100 {
00101 #if( defined ( TARGET_KL25Z ) || defined ( TARGET_LPC11U6X ) )
00102     DigitalOut *led = new DigitalOut(LED2);
00103 #elif defined(TARGET_NUCLEO_L073RZ) || defined (TARGET_DISCO_L072CZ_LRWAN1)
00104     DigitalOut *led = new DigitalOut(LED4);   // RX red
00105     led3 = new DigitalOut(LED3);  // TX blue
00106 #else
00107     DigitalOut *led = new DigitalOut(LED1);
00108     led3 = led;
00109 #endif
00110     
00111     Buffer = new  uint8_t[BUFFER_SIZE];
00112     *led3 = 1;
00113 
00114 #ifdef TARGET_DISCO_L072CZ_LRWAN1
00115     Radio = new SX1276Generic(NULL, MURATA_SX1276,
00116             LORA_SPI_MOSI, LORA_SPI_MISO, LORA_SPI_SCLK, LORA_CS, LORA_RESET,
00117             LORA_DIO0, LORA_DIO1, LORA_DIO2, LORA_DIO3, LORA_DIO4, LORA_DIO5,
00118             LORA_ANT_RX, LORA_ANT_TX, LORA_ANT_BOOST, LORA_TCXO);
00119 #elif defined(HELTECL432_REV1)
00120     Radio = new SX1276Generic(NULL, HELTEC_L4_1276,
00121             LORA_SPI_MOSI, LORA_SPI_MISO, LORA_SPI_SCLK, LORA_CS, LORA_RESET,
00122             LORA_DIO0, LORA_DIO1, LORA_DIO2, LORA_DIO3, LORA_DIO4, LORA_DIO5,
00123             LORA_ANT_PWR);
00124 #else // RFM95
00125     Radio = new SX1276Generic(NULL, RFM95_SX1276,
00126             LORA_SPI_MOSI, LORA_SPI_MISO, LORA_SPI_SCLK, LORA_CS, LORA_RESET,
00127             LORA_DIO0, LORA_DIO1, LORA_DIO2, LORA_DIO3, LORA_DIO4, LORA_DIO5);
00128 
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     switch(Radio->DetectBoardType()) {
00158         case SX1276MB1LAS:
00159             if (DEBUG_MESSAGE)
00160                 dprintf(" > Board Type: SX1276MB1LAS <");
00161             break;
00162         case SX1276MB1MAS:
00163             if (DEBUG_MESSAGE)
00164                 dprintf(" > Board Type: SX1276MB1LAS <");
00165             break;
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             break;
00364         default:
00365             State = LOWPOWER;
00366             break;
00367         }    
00368     }
00369 }
00370 
00371 void OnTxDone(void *radio, void *userThisPtr, void *userData)
00372 {
00373     SX1276Generic *r = (SX1276Generic *)radio;
00374     r->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     SX1276Generic *r = (SX1276Generic *)radio;
00383     r->Sleep( );
00384     BufferSize = size;
00385     memcpy( Buffer, payload, BufferSize );
00386     State = RX;
00387     if (DEBUG_MESSAGE)
00388         dprintf("> OnRxDone: RssiValue=%d dBm, SnrValue=%d", rssi, snr);
00389     dump("Data:", payload, size);
00390 }
00391 
00392 void OnTxTimeout(void *radio, void *userThisPtr, void *userData)
00393 {
00394     SX1276Generic *r = (SX1276Generic *)radio;
00395     *led3 = 0;
00396     r->Sleep( );
00397     State = TX_TIMEOUT;
00398     if(DEBUG_MESSAGE)
00399         dprintf("> OnTxTimeout");
00400 }
00401 
00402 void OnRxTimeout(void *radio, void *userThisPtr, void *userData)
00403 {
00404     SX1276Generic *r = (SX1276Generic *)radio;
00405     *led3 = 0;
00406     r->Sleep( );
00407     Buffer[BufferSize-1] = 0;
00408     State = RX_TIMEOUT;
00409     if (DEBUG_MESSAGE)
00410         dprintf("> OnRxTimeout");
00411 }
00412 
00413 void OnRxError(void *radio, void *userThisPtr, void *userData)
00414 {
00415     SX1276Generic *r = (SX1276Generic *)radio;
00416     r->Sleep( );
00417     State = RX_ERROR;
00418     if (DEBUG_MESSAGE)
00419         dprintf("> OnRxError");
00420 }
00421 #endif