This is example code that can get you started with building your own IR vision robot that communicates over LoRa

Dependencies:   Adafruit-MotorShield Adafruit-PWM-Servo-Driver Adafruit_GFX BufferedSerial MAX17055_EZconfig NEO-6m-GPS SX1276GenericLib USBDeviceHT max32630fthr max77650_charger_sample

Fork of MAX326xxFTHR_LoRa_Example_test 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 #include "global_buffers.h"
00014 
00015 #ifdef FEATURE_LORA
00016 
00017 /* Set this flag to '1' to display debug messages on the console */
00018 #define DEBUG_MESSAGE   0
00019 
00020 /* Set this flag to '1' to use the LoRa modulation or to '0' to use FSK modulation */
00021 #define USE_MODEM_LORA  1
00022 #define USE_MODEM_FSK   !USE_MODEM_LORA
00023 #define RF_FREQUENCY            RF_FREQUENCY_915_0  // Hz
00024 #define TX_OUTPUT_POWER         14                  // 14 dBm
00025 
00026 #if USE_MODEM_LORA == 1
00027 
00028 #define LORA_BANDWIDTH          125000  // LoRa default, details in SX1276::BandwidthMap
00029 #define LORA_SPREADING_FACTOR   LORA_SF7
00030 #define LORA_CODINGRATE         LORA_ERROR_CODING_RATE_4_5
00031 
00032 #define LORA_PREAMBLE_LENGTH    8       // Same for Tx and Rx
00033 #define LORA_SYMBOL_TIMEOUT     5       // Symbols
00034 #define LORA_FIX_LENGTH_PAYLOAD_ON  false
00035 #define LORA_FHSS_ENABLED       false  
00036 #define LORA_NB_SYMB_HOP        4     
00037 #define LORA_IQ_INVERSION_ON    false
00038 #define LORA_CRC_ENABLED        true
00039     
00040 #elif USE_MODEM_FSK == 1
00041 
00042 #define FSK_FDEV                25000     // Hz
00043 #define FSK_DATARATE            19200     // bps
00044 #define FSK_BANDWIDTH           50000     // Hz
00045 #define FSK_AFC_BANDWIDTH       83333     // Hz
00046 #define FSK_PREAMBLE_LENGTH     5         // Same for Tx and Rx
00047 #define FSK_FIX_LENGTH_PAYLOAD_ON   false
00048 #define FSK_CRC_ENABLED         true
00049     
00050 #else
00051     #error "Please define a modem in the compiler options."
00052 #endif 
00053 
00054 
00055 //#define RX_TIMEOUT_VALUE    3500  // in ms
00056 #define RX_TIMEOUT_VALUE    333  // in ms
00057 
00058 
00059 //#define BUFFER_SIZE       64        // Define the payload size here
00060 
00061 /*
00062  *  Global variables declarations
00063  */
00064 typedef enum
00065 {
00066     LOWPOWER = 0,
00067     IDLE,
00068     
00069     RX,
00070     RX_TIMEOUT,
00071     RX_ERROR,
00072     
00073     TX,
00074     TX_TIMEOUT,
00075     
00076     CAD,
00077     CAD_DONE
00078 } AppStates_t;
00079 
00080 volatile AppStates_t State = LOWPOWER;
00081 
00082 /*!
00083  * Radio events function pointer
00084  */
00085 static RadioEvents_t RadioEvents;
00086 
00087 /*
00088  *  Global variables declarations
00089  */
00090 SX1276Generic *Radio;
00091 
00092 
00093 // Aliases for the buffers that are made in the main()
00094 uint8_t *BufferTx;
00095 uint8_t *BufferRx;
00096 
00097 DigitalOut *led3;
00098 
00099 
00100 int SX1276PingPongSetup(uint8_t *BufferTxFromMain, uint8_t *BufferRxFromMain) 
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     BufferTx = BufferTxFromMain;
00114     BufferRx = BufferRxFromMain;
00115     *led3 = 1;
00116 
00117 #ifdef B_L072Z_LRWAN1_LORA
00118     Radio = new SX1276Generic(NULL, MURATA_SX1276,
00119             LORA_SPI_MOSI, LORA_SPI_MISO, LORA_SPI_SCLK, LORA_CS, LORA_RESET,
00120             LORA_DIO0, LORA_DIO1, LORA_DIO2, LORA_DIO3, LORA_DIO4, LORA_DIO5,
00121             LORA_ANT_RX, LORA_ANT_TX, LORA_ANT_BOOST, LORA_TCXO);
00122 #else // RFM95
00123     Radio = new SX1276Generic(NULL, RFM95_SX1276,
00124             LORA_SPI_MOSI, LORA_SPI_MISO, LORA_SPI_SCLK, LORA_CS, LORA_RESET,
00125             LORA_DIO0, LORA_DIO1, LORA_DIO2, LORA_DIO3, LORA_DIO4, LORA_DIO5);
00126 
00127 #endif
00128     
00129     dprintf("SX1276 Ping Pong Demo Application" );
00130     dprintf("Freqency: %.1f", (double)RF_FREQUENCY/1000000.0);
00131     dprintf("TXPower: %d dBm",  TX_OUTPUT_POWER);
00132 #if USE_MODEM_LORA == 1
00133     dprintf("Bandwidth: %d Hz", LORA_BANDWIDTH);
00134     dprintf("Spreading factor: SF%d", LORA_SPREADING_FACTOR);
00135 #elif USE_MODEM_FSK == 1
00136     dprintf("Bandwidth: %d kHz",  FSK_BANDWIDTH);
00137     dprintf("Baudrate: %d", FSK_DATARATE);
00138 #endif
00139     // Initialize Radio driver
00140     RadioEvents.TxDone = OnTxDone;
00141     RadioEvents.RxDone = OnRxDone;
00142     RadioEvents.RxError = OnRxError;
00143     RadioEvents.TxTimeout = OnTxTimeout;
00144     RadioEvents.RxTimeout = OnRxTimeout;    
00145     if (Radio->Init( &RadioEvents ) == false) {
00146         while(1) {
00147             dprintf("Radio could not be detected!");
00148             wait( 1 );
00149         }
00150     }
00151 
00152     
00153     switch(Radio->DetectBoardType()) {
00154         case SX1276MB1LAS:
00155             if (DEBUG_MESSAGE)
00156                 dprintf(" > Board Type: SX1276MB1LAS <");
00157             break;
00158         case SX1276MB1MAS:
00159             if (DEBUG_MESSAGE)
00160                 dprintf(" > Board Type: SX1276MB1LAS <");
00161         case MURATA_SX1276:
00162             if (DEBUG_MESSAGE)
00163                 dprintf(" > Board Type: MURATA_SX1276_STM32L0 <");
00164             break;
00165         case RFM95_SX1276:
00166             if (DEBUG_MESSAGE)
00167                 dprintf(" > HopeRF RFM95xx <");
00168             break;
00169         default:
00170             dprintf(" > Board Type: unknown <");
00171     }
00172 
00173     Radio->SetChannel(RF_FREQUENCY ); 
00174 
00175 #if USE_MODEM_LORA == 1
00176     
00177     if (LORA_FHSS_ENABLED)
00178         dprintf("             > LORA FHSS Mode <");
00179     if (!LORA_FHSS_ENABLED)
00180         dprintf("             > LORA Mode <");
00181     
00182     
00183     // Without this line, the default max payload length is only 64 bytes
00184     Radio->SetMaxPayloadLength(MODEM_LORA, 255);
00185 
00186     Radio->SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
00187                          LORA_SPREADING_FACTOR, LORA_CODINGRATE,
00188                          LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
00189                          LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, 
00190                          LORA_IQ_INVERSION_ON, 2000 );
00191     
00192     Radio->SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
00193                          LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
00194                          LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, 0,
00195                          LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, 
00196                          LORA_IQ_INVERSION_ON, true );
00197                          
00198 #elif USE_MODEM_FSK == 1
00199 
00200     dprintf("              > FSK Mode <");
00201     Radio->SetTxConfig( MODEM_FSK, TX_OUTPUT_POWER, FSK_FDEV, 0,
00202                          FSK_DATARATE, 0,
00203                          FSK_PREAMBLE_LENGTH, FSK_FIX_LENGTH_PAYLOAD_ON,
00204                          FSK_CRC_ENABLED, 0, 0, 0, 2000 );
00205     
00206     Radio->SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE,
00207                          0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH,
00208                          0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, FSK_CRC_ENABLED,
00209                          0, 0, false, true );
00210                          
00211 #else
00212 
00213 #error "Please define a modem in the compiler options."
00214 
00215 #endif
00216      
00217     if (DEBUG_MESSAGE)
00218         dprintf("Starting Ping-Pong loop"); 
00219 
00220         
00221     Radio->Rx( RX_TIMEOUT_VALUE );
00222 }
00223 
00224 /****************************************************************************************************************************************
00225  * 
00226  ****************************************************************************************************************************************/
00227 int SX1276PingPong(void)
00228 {
00229 #if   defined(TARGET_MAX32630FTHR) // Master Device: Bluetooth Gateway
00230     bool isMaster = true;
00231 #elif defined(TARGET_MAX32620FTHR) // Slave Device: Robot
00232     bool isMaster = false;
00233 #endif
00234     
00235     switch( State )
00236     {
00237     case RX:
00238 //          *led3 = 0;
00239         if( isMaster == true )
00240         {
00241             if( BufferSizeRx > 0 )
00242             {
00243                 /* This checks if the ID of the received transaction is matching that of
00244                  * the slave device's ID. This is Defined in the GenericPingPong.h
00245                  */
00246                 if( memcmp(&BufferRx[rx_idx_signature], PongMsg, sizeof(PongMsg)) == 0 )
00247                 {
00248 //                        *led = !*led;
00249                     if (DEBUG_MESSAGE)
00250                         dprintf( "...Pong" );
00251                     wait_ms( 10 ); 
00252                     Radio->Send( BufferTx, BufferSizeTx );
00253                 }
00254                 else // valid reception but neither a PING or a PONG message
00255                 {    // Set device as master ans start again
00256                     //isMaster = true;
00257                     Radio->Rx( RX_TIMEOUT_VALUE );
00258                 }
00259             }
00260         }
00261         else
00262         {
00263             if( BufferSizeRx > 0 )
00264             {
00265                 if( memcmp(BufferRx, PingMsg, sizeof(PingMsg)) == 0 )
00266                 {
00267 //                        *led = !*led;
00268                     if (DEBUG_MESSAGE)
00269                         dprintf( "...Ping" );
00270                     wait_ms( 10 );  
00271                     Radio->Send( BufferTx, BufferSizeTx );
00272                 }
00273                 else // valid reception but not a PING as expected
00274                 {    // Set device as master and start again
00275                     //isMaster = true;
00276                     Radio->Rx( RX_TIMEOUT_VALUE );
00277                 }    
00278             }
00279         }
00280         State = LOWPOWER;
00281         break;
00282     case TX:    
00283 //            *led3 = 1;
00284         if( isMaster == true )  
00285         {
00286             if (DEBUG_MESSAGE)
00287                 dprintf("Ping..." );
00288         }
00289         else
00290         {
00291             if (DEBUG_MESSAGE)
00292                 dprintf("Pong..." );
00293         }
00294         Radio->Rx( RX_TIMEOUT_VALUE );
00295         State = LOWPOWER;
00296         break;
00297     case RX_TIMEOUT:
00298         if( isMaster == true )
00299         {
00300             wait_ms( 10 ); 
00301             Radio->Send( BufferTx, BufferSizeTx );
00302         }
00303         else
00304         {
00305             Radio->Rx( RX_TIMEOUT_VALUE );  
00306         }             
00307         State = LOWPOWER;
00308         break;
00309     case RX_ERROR:
00310         // We have received a Packet with a CRC error, send reply as if packet was correct
00311         if( isMaster == true )
00312         {
00313             // Send the next PING frame
00314 //            memcpy(BufferTx, PingMsg, sizeof(PingMsg));
00315 /*            
00316             for( i = 4; i < BufferSizeTx; i++ )
00317             {
00318                 BufferTx[i] = i - 4;
00319             }
00320 */
00321 //          fillPayloadWithGlobalBufs(BufferTx);
00322             wait_ms( 10 );  
00323             Radio->Send( BufferTx, BufferSizeTx );
00324         }
00325         else
00326         {
00327             // Send the next PONG frame
00328 //            memcpy(BufferTx, PongMsg, sizeof(PongMsg));
00329 /*
00330             for( i = sizeof(PongMsg); i < BufferSizeTx; i++ )
00331             {
00332                 BufferTx[i] = i - sizeof(PongMsg);
00333             }
00334 */
00335             wait_ms( 10 );  
00336             Radio->Send( BufferTx, BufferSizeTx );
00337         }
00338         State = LOWPOWER;
00339         break;
00340     case TX_TIMEOUT:
00341         Radio->Rx( RX_TIMEOUT_VALUE );
00342         State = LOWPOWER;
00343         break;
00344     case LOWPOWER:
00345         sleep();
00346         break;
00347     default:
00348         State = LOWPOWER;
00349         break;
00350     }    
00351 }
00352 
00353 void OnTxDone(void *radio, void *userThisPtr, void *userData)
00354 {
00355     Radio->Sleep( );
00356     State = TX; 
00357     if (DEBUG_MESSAGE)
00358         dprintf("> OnTxDone");
00359 }
00360 
00361 void OnRxDone(void *radio, void *userThisPtr, void *userData, uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
00362 {
00363     Radio->Sleep( );
00364     
00365     if(BufferSizeRx != size)
00366         memcpy( BufferRx, payload, size );
00367     else
00368         memcpy( BufferRx, payload, BufferSizeRx );
00369     State = RX;
00370     
00371     // Reset the RxTimeoutCount 
00372     RxTimeoutCount = 0;
00373 
00374     if (DEBUG_MESSAGE) {
00375         dprintf("> OnRxDone: RssiValue=%d dBm, SnrValue=%d", rssi, snr);
00376         dump("Data:", payload, size);
00377     }
00378 }
00379 
00380 void OnTxTimeout(void *radio, void *userThisPtr, void *userData)
00381 {
00382 //    *led3 = 0;
00383     Radio->Sleep( );
00384     State = TX_TIMEOUT;
00385     if(DEBUG_MESSAGE)
00386         dprintf("> OnTxTimeout");
00387 }
00388 
00389 void OnRxTimeout(void *radio, void *userThisPtr, void *userData)
00390 {
00391 //    *led3 = 0;
00392     Radio->Sleep( );
00393     BufferRx[BufferSizeRx-1] = 0;
00394     State = RX_TIMEOUT;
00395     if (DEBUG_MESSAGE)
00396         dprintf("> OnRxTimeout");
00397         
00398     // Increment how many times a transmission times out\
00399     RxTimeoutCount = RxTimeoutCount + 1;
00400 }
00401 
00402 void OnRxError(void *radio, void *userThisPtr, void *userData)
00403 {
00404     Radio->Sleep( );
00405     State = RX_ERROR;
00406     if (DEBUG_MESSAGE)
00407         dprintf("> OnRxError");
00408         
00409     // Increment how many times a transmission times out\
00410     RxTimeoutCount = RxTimeoutCount + 1;
00411 }
00412 
00413 int numOfRxTimeouts()
00414 {
00415     return RxTimeoutCount;
00416 }
00417 
00418 #endif