LoRaPHY project, based upon SX1276Lib, hardware with NUCLEO-F103EB/L053R8 and other boards as well as multiple Radio modules of SX1272/1276/1278. The code contains MACRO definitions and can be configured as TX/RX only, PINGPONG and consider to be a code base of RTTY.

Dependencies:   SX1276Lib mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include "main.h"
00003 #include "sx1276-hal.h"
00004 #include "debug.h"
00005 
00006 /* Set this flag to '1' to display debug messages on the console */
00007 #define DEBUG_MESSAGE   0
00008 
00009 /* Set this flag to '1' to use the LoRa modulation or to '0' to use FSK modulation */
00010 #define USE_MODEM_LORA  1
00011 #define USE_MODEM_FSK   !USE_MODEM_LORA
00012 
00013 //#define RF868  1
00014 
00015 #ifdef RF868
00016 
00017     #define RF_FREQUENCY                                    868000000 // Hz
00018     #define TX_OUTPUT_POWER                                 14        // 14 dBm
00019 
00020 #else
00021 
00022     #define RF_FREQUENCY                                    433000000 // Hz
00023     #define TX_OUTPUT_POWER                                 14        // 26 dBm
00024 
00025 #endif
00026 
00027 #if USE_MODEM_LORA == 1
00028     #define LORA_BANDWIDTH  0
00029     #define LORA_SPREADING_FACTOR   10
00030     #define LORA_CODINGRATE     2
00031 
00032     //#define LORA_BANDWIDTH                              2         // [0: 125 kHz,
00033                                                                   //  1: 250 kHz,
00034                                                                   //  2: 500 kHz,
00035                                                                   //  3: Reserved]
00036     //#define LORA_SPREADING_FACTOR                       7         // [SF7..SF12]
00037     //#define LORA_CODINGRATE                             1         // [1: 4/5,
00038                                                                   //  2: 4/6,
00039                                                                   //  3: 4/7,
00040                                                                   //  4: 4/8]
00041     #define LORA_PREAMBLE_LENGTH                        8         // Same for Tx and Rx
00042     #define LORA_SYMBOL_TIMEOUT                         5         // Symbols
00043     #define LORA_FIX_LENGTH_PAYLOAD_ON                  false
00044     #define LORA_FHSS_ENABLED                           false  
00045     #define LORA_NB_SYMB_HOP                            4     
00046     #define LORA_IQ_INVERSION_ON                        false
00047     #define LORA_CRC_ENABLED                            true
00048     
00049 #elif USE_MODEM_FSK == 1
00050 
00051     #define FSK_FDEV                                    25000     // Hz
00052     #define FSK_DATARATE                                19200     // bps
00053     #define FSK_BANDWIDTH                               50000     // Hz
00054     #define FSK_AFC_BANDWIDTH                           83333     // Hz
00055     #define FSK_PREAMBLE_LENGTH                         5         // Same for Tx and Rx
00056     #define FSK_FIX_LENGTH_PAYLOAD_ON                   false
00057     #define FSK_CRC_ENABLED                             true
00058     
00059 #else
00060     #error "Please define a modem in the compiler options."
00061 #endif
00062 
00063 #define RX_TIMEOUT_VALUE                                3500000   // in us
00064 #define BUFFER_SIZE                                     32        // Define the payload size here
00065 
00066 #if( defined ( TARGET_KL25Z ) || defined ( TARGET_LPC11U6X ) )
00067 DigitalOut led(LED2);
00068 #else
00069 //DigitalOut led(LED1);
00070 //DigitalOut led2(LED2);
00071 //DigitalOut led3(LED3);
00072 //DigitalOut led4(LED4);
00073 DigitalOut debugled(D6);
00074 DigitalOut debugled2(D7);
00075 
00076 #endif
00077 
00078 DigitalIn role(USER_BUTTON);  // PC_13 in Mini 103RC mini board
00079 Timer tx_tmr;
00080 
00081 #define UART_ENABLE
00082 
00083 #ifdef UART_ENABLE
00084 //Serial pc(USBTX, USBRX);
00085 Serial pc(SERIAL_TX, SERIAL_RX);
00086 #endif
00087 
00088 Ticker nwk_ticker;
00089 
00090 bool channelOccupied = false;
00091 
00092 #define NWK_SLEEP  0
00093 #define NWK_TX     1
00094 #define NWK_TX_NOK 2
00095 #define NWK_RX_OK  3
00096 #define NWK_RX_NOK 4   
00097 
00098 //#define PINGPONG
00099 
00100 void nwk_toggle()
00101 {
00102     debugled = !debugled;
00103     debugled2 = !debugled2;
00104 }
00105 
00106 void nwk_setmode(uint8_t mode)
00107 {
00108     switch(mode){
00109         case NWK_TX:
00110         case NWK_RX_OK:
00111             nwk_ticker.attach(&nwk_toggle, 1);
00112             break;
00113         case NWK_TX_NOK:
00114         case NWK_RX_NOK:
00115             nwk_ticker.attach(&nwk_toggle, 0.1);
00116             break;
00117         case NWK_SLEEP:
00118         default:
00119             debugled = 0;
00120             debugled2 = 0;
00121             nwk_ticker.detach();
00122             break;
00123     }
00124 }
00125 
00126 /*
00127  *  Global variables declarations
00128  */
00129 typedef enum
00130 {
00131     ST_LOWPOWER = 0,
00132     ST_IDLE,
00133     
00134     ST_RX,
00135     ST_RX_TIMEOUT,
00136     ST_RX_ERROR,
00137     
00138     ST_TX,
00139     ST_TX_TIMEOUT,
00140     
00141     ST_CAD,
00142     ST_CAD_DONE
00143 }AppStates_t;
00144 
00145 volatile AppStates_t State = ST_LOWPOWER;
00146 
00147 /*!
00148  * Radio events function pointer
00149  */
00150 static RadioEvents_t RadioEvents;
00151 
00152 /*
00153  *  Global variables declarations
00154  */
00155 SX1276MB1xAS Radio( NULL );
00156 
00157 const uint8_t PingMsg[] = "PING";
00158 const uint8_t PongMsg[] = "PONG";
00159 const uint8_t TestMsg[] = "LoRa Test";
00160 
00161 uint16_t BufferSize = BUFFER_SIZE;
00162 uint8_t Buffer[BUFFER_SIZE];
00163 
00164 //int16_t RssiValue = 0.0;
00165 //int8_t SnrValue = 0.0;
00166 
00167 int16_t RssiValue = 0;
00168 int8_t SnrValue = 0;
00169 
00170 #define REG_SIZE 0x70 // see below
00171 #define REG_IDX_SIZE 39
00172 
00173 static int my_strncmp(const char *, const char *, int);
00174 static void my_strcpy(char * , const char *);
00175 
00176 int my_strncmp(const char * s1, const char * s2, int size)
00177 {
00178     int n = size;
00179     for ( ; n > 0; s1++, s2++, --n)
00180     if (*s1 != *s2)
00181         return ((*(unsigned char *)s1 < *(unsigned char *)s2) ? -1 : +1);
00182     else if (*s1 == '\0')
00183         return 0;
00184     return 0;    
00185 }
00186 
00187 void my_strcpy(char * s1, const char * s2)
00188 {
00189     char *s = s1;
00190     while ((*s++ = *s2++) != 0)
00191     ;
00192 }
00193 
00194 void Sender ( void )
00195 {
00196     int i;
00197     my_strcpy( ( char* )Buffer, ( char* )PingMsg );
00198     for( i = 4; i < BufferSize; i++ ){
00199         Buffer[i] = i - 4;
00200     }
00201     Radio.Send( Buffer, BufferSize );
00202 }
00203 
00204 int main() 
00205 {
00206     uint8_t i;
00207     uint8_t regval;
00208     bool isMaster = true;
00209     int begin, end;
00210 
00211     uint32_t rand;
00212     debugled = 1;
00213     debugled2 = 1;
00214 
00215     isMaster = role.read();
00216     
00217     //debug( "\n\n\r     SX1276 Ping Pong Demo Application \n\n\r" );
00218 
00219     // Initialize Radio driver
00220     RadioEvents.TxDone = OnTxDone;
00221     RadioEvents.RxDone = OnRxDone;
00222     RadioEvents.RxError = OnRxError;
00223     RadioEvents.TxTimeout = OnTxTimeout;
00224     RadioEvents.RxTimeout = OnRxTimeout;
00225     Radio.Init( &RadioEvents );
00226 
00227     #ifdef UART_ENABLE
00228     regval = Radio.Read(REG_VERSION);
00229     pc.printf("%s", TestMsg);
00230     pc.printf("IC Version: %02X\r\n", regval);
00231     regval = Radio.Read(REG_OPMODE);
00232     pc.printf("OPMODE: %02X\r\n", regval);
00233     #endif
00234 
00235     debugled = 0;
00236     debugled2 = 0;
00237     
00238     // verify the connection with the board
00239     while( Radio.Read( REG_VERSION ) == 0x00  )
00240     {
00241         //debug( "Radio could not be detected!\n\r", NULL );
00242         wait( 1 );
00243     }
00244             
00245     //debug_if( ( DEBUG_MESSAGE & ( Radio.DetectBoardType( ) == SX1276MB1LAS ) ) , "\n\r > Board Type: SX1276MB1LAS < \n\r" );
00246     //debug_if( ( DEBUG_MESSAGE & ( Radio.DetectBoardType( ) == SX1276MB1MAS ) ) , "\n\r > Board Type: SX1276MB1MAS < \n\r" );
00247     
00248     Radio.SetChannel( RF_FREQUENCY ); 
00249 
00250 #if USE_MODEM_LORA == 1
00251     
00252     //debug_if( LORA_FHSS_ENABLED, "\n\n\r             > LORA FHSS Mode < \n\n\r");
00253     //debug_if( !LORA_FHSS_ENABLED, "\n\n\r             > LORA Mode < \n\n\r");
00254     
00255     Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
00256                          LORA_SPREADING_FACTOR, LORA_CODINGRATE,
00257                          LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
00258                          LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, 
00259                          LORA_IQ_INVERSION_ON, 2000000 );
00260     
00261     Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
00262                          LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
00263                          LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, 0,
00264                          LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, 
00265                          LORA_IQ_INVERSION_ON, true );
00266                          
00267 #elif USE_MODEM_FSK == 1
00268 
00269     //debug("\n\n\r              > FSK Mode < \n\n\r");
00270     Radio.SetTxConfig( MODEM_FSK, TX_OUTPUT_POWER, FSK_FDEV, 0,
00271                          FSK_DATARATE, 0,
00272                          FSK_PREAMBLE_LENGTH, FSK_FIX_LENGTH_PAYLOAD_ON,
00273                          FSK_CRC_ENABLED, 0, 0, 0, 2000000 );
00274     
00275     Radio.SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE,
00276                          0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH,
00277                          0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, FSK_CRC_ENABLED,
00278                          0, 0, false, true );
00279                          
00280 #else
00281 
00282 #error "Please define a modem in the compiler options."
00283 
00284 #endif
00285      
00286     //debug_if( DEBUG_MESSAGE, "Starting Ping-Pong loop\r\n" ); 
00287         
00288     rand = Radio.Random();
00289     rand = rand%1000;
00290     wait_ms((uint16_t)rand);
00291     
00292 #ifdef PINGPONG
00293     Radio.Rx( RX_TIMEOUT_VALUE );
00294     
00295    
00296     while( 1 )
00297     {
00298         switch( State )
00299         {
00300         case ST_RX:
00301             if( isMaster == true )
00302             {
00303                 if( BufferSize > 0 )
00304                 {
00305                     #ifdef UART_ENABLE
00306                     pc.printf("Received message:\r\n");
00307                     pc.printf("%s",Buffer);
00308                     #endif
00309                     //if( strncmp( ( const char* )Buffer, ( const char* )PongMsg, 4 ) == 0 )
00310                     if( my_strncmp( ( const char* )Buffer, ( const char* )PongMsg, 4 ) == 0 )
00311                     {
00312                         nwk_setmode(NWK_NORMAL);
00313                         //debug( "...Pong\r\n" );
00314                         // Send the next PING frame            
00315                         my_strcpy( ( char* )Buffer, ( char* )PingMsg );
00316                         //_strcpy( ( char* )Buffer, ( char* )PingMsg );
00317                         // We fill the buffer with numbers for the payload 
00318                         for( i = 4; i < BufferSize; i++ )
00319                         {
00320                             Buffer[i] = i - 4;
00321                         }
00322                         wait_ms( 10 ); 
00323                         Radio.Send( Buffer, BufferSize );
00324                     }
00325                     else if( my_strncmp( ( const char* )Buffer, ( const char* )PingMsg, 4 ) == 0 )
00326                     { // A master already exists then become a slave
00327                         debug( "...Ping\r\n" );
00328                         //nwk_setmode(NWK_NORMAL);
00329                         //led = !led;
00330                         isMaster = false;
00331                         // Send the next PONG frame            
00332                         my_strcpy( ( char* )Buffer, ( char* )PongMsg );
00333                         // We fill the buffer with numbers for the payload 
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 // valid reception but neither a PING or a PONG message
00342                     {    // Set device as master ans start again
00343                         isMaster = true;
00344                         Radio.Rx( RX_TIMEOUT_VALUE );
00345                     }    
00346                 }
00347             }
00348             else
00349             {
00350                 if( BufferSize > 0 )
00351                 {
00352                     #ifdef UART_ENABLE
00353                     pc.printf("Received message:\r\n");
00354                     pc.printf("%s",Buffer);
00355                     #endif
00356                     
00357                     if( my_strncmp( ( const char* )Buffer, ( const char* )PingMsg, 4 ) == 0 )
00358                     {
00359                         nwk_setmode(NWK_NORMAL);
00360                         //led = !led;
00361                         //debug( "...Ping\r\n" );
00362                         // Send the reply to the PING string
00363                         my_strcpy( ( char* )Buffer, ( char* )PongMsg );
00364                         // We fill the buffer with numbers for the payload 
00365                         for( i = 4; i < BufferSize; i++ )
00366                         {
00367                             Buffer[i] = i - 4;
00368                         }
00369                         wait_ms( 10 );  
00370                         Radio.Send( Buffer, BufferSize );
00371                     }
00372                     else // valid reception but not a PING as expected
00373                     {    // Set device as master and start again
00374                         isMaster = true;
00375                         Radio.Rx( RX_TIMEOUT_VALUE );
00376                     }    
00377                 }
00378             }
00379             State = ST_LOWPOWER;
00380             break;
00381         case ST_TX:    
00382             //nwk_setmode(NWK_NORMAL);
00383             //led = !led; 
00384             if( isMaster == true )  
00385             {
00386                 //debug( "Ping...\r\n" );
00387             }
00388             else
00389             {
00390                 //debug( "Pong...\r\n" );
00391             }
00392             Radio.Rx( RX_TIMEOUT_VALUE );
00393             State = ST_LOWPOWER;
00394             break;
00395         case ST_RX_TIMEOUT:
00396             //debugled = !debugled;
00397             //debugled2 = !debugled2;
00398             nwk_setmode(NWK_ERR);
00399             if( isMaster == true )
00400             {
00401                 // Send the next PING frame
00402                 my_strcpy( ( char* )Buffer, ( char* )PingMsg );
00403                 for( i = 4; i < BufferSize; i++ )
00404                 {
00405                     Buffer[i] = i - 4;
00406                 }
00407                 wait_ms( 10 ); 
00408                 Radio.Send( Buffer, BufferSize );
00409             }
00410             else
00411             {
00412                 Radio.Rx( RX_TIMEOUT_VALUE );  
00413             }             
00414             State = ST_LOWPOWER;
00415             break;
00416         case ST_RX_ERROR:
00417             // We have received a Packet with a CRC error, send reply as if packet was correct
00418             nwk_setmode(NWK_ERR);
00419             if( isMaster == true )
00420             {
00421                 // Send the next PING frame
00422                 my_strcpy( ( char* )Buffer, ( char* )PingMsg );
00423                 for( i = 4; i < BufferSize; i++ )
00424                 {
00425                     Buffer[i] = i - 4;
00426                 }
00427                 wait_ms( 10 );  
00428                 Radio.Send( Buffer, BufferSize );
00429             }
00430             else
00431             {
00432                 // Send the next PONG frame
00433                 my_strcpy( ( char* )Buffer, ( char* )PongMsg );
00434                 for( i = 4; i < BufferSize; i++ )
00435                 {
00436                     Buffer[i] = i - 4;
00437                 }
00438                 wait_ms( 10 );  
00439                 Radio.Send( Buffer, BufferSize );
00440             }
00441             State = ST_LOWPOWER;
00442             break;
00443         case ST_TX_TIMEOUT:
00444             nwk_setmode(NWK_ERR);
00445             Radio.Rx( RX_TIMEOUT_VALUE );
00446             State = ST_LOWPOWER;
00447             break;
00448         case ST_CAD:
00449             break;
00450         case ST_CAD_DONE:
00451             if(channelOccupied){
00452                 State = ST_LOWPOWER;
00453             }else{
00454                 // start to transmit here.
00455             }
00456             break;
00457         case ST_LOWPOWER:
00458             break;
00459         default:
00460             nwk_setmode(0xFF);
00461             State = ST_LOWPOWER;
00462             break;
00463         }    
00464     }
00465 
00466 #else
00467     
00468     if(isMaster == true){
00469         tx_tmr.start();
00470         begin = tx_tmr.read_ms();
00471     }else{
00472         Radio.Rx( RX_TIMEOUT_VALUE );
00473     }
00474     
00475     while(1){
00476         switch(State){
00477         case ST_RX:
00478             //nwk_setmode(NWK_RX_OK);
00479             Radio.Rx( RX_TIMEOUT_VALUE );
00480             State = ST_LOWPOWER;
00481 #ifdef UART_ENABLE
00482             //pc.printf("\r\nRX OK\tRSSI:%f  SNR:%f \r\n",float(RssiValue),float(SnrValue));
00483             pc.printf("\r\nRX OK\tRSSI:%d  SNR:%d \r\n",RssiValue,SnrValue);
00484             pc.printf("\r\nRSSI: %02X SNR: %01X\r\n", RssiValue, SnrValue);
00485 #endif      
00486             break;
00487         case ST_TX:
00488             nwk_setmode(NWK_TX);
00489             State = ST_LOWPOWER;
00490 #ifdef UART_ENABLE
00491             pc.printf("\r\nTX Done.\r\n");
00492 #endif                
00493             break;
00494         case ST_RX_TIMEOUT:
00495         case ST_RX_ERROR:
00496             //nwk_setmode(NWK_RX_NOK);
00497             Radio.Rx( RX_TIMEOUT_VALUE );
00498             State = ST_LOWPOWER;
00499 #ifdef UART_ENABLE
00500             pc.printf("\r\nRX TIMEOUT or ERROR.\r\n");
00501 #endif                
00502             break;
00503         case ST_TX_TIMEOUT:
00504             State = ST_LOWPOWER;
00505             break;
00506         case ST_LOWPOWER:
00507             if (isMaster){
00508                 end = tx_tmr.read_ms();
00509                 if ((end-begin) >= 2000){
00510                     Sender();
00511                     tx_tmr.stop();
00512                     tx_tmr.start();
00513                     begin = tx_tmr.read_ms();
00514                 }
00515             }
00516             break;
00517         default:
00518             State = ST_LOWPOWER;
00519             break;
00520         }
00521     }
00522 #endif
00523     
00524 }
00525 
00526 
00527 void OnTxDone( void )
00528 {
00529     Radio.Sleep( );
00530     State = ST_TX;    
00531     //debug_if( DEBUG_MESSAGE, "> OnTxDone\n\r" );
00532 }
00533 
00534 void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
00535 {
00536     Radio.Sleep( );
00537     BufferSize = size;
00538     memcpy( Buffer, payload, BufferSize );
00539     RssiValue = rssi;
00540     SnrValue = snr;
00541     State = ST_RX;
00542     nwk_setmode(NWK_RX_OK);
00543     //debug_if( DEBUG_MESSAGE, "> OnRxDone\n\r" );
00544 }
00545 
00546 void OnTxTimeout( void )
00547 {
00548     Radio.Sleep( );
00549     State = ST_TX_TIMEOUT;
00550     //debug_if( DEBUG_MESSAGE, "> OnTxTimeout\n\r" );
00551 }
00552 
00553 void OnRxTimeout( void )
00554 {
00555     Radio.Sleep( );
00556     Buffer[ BufferSize ] = 0;
00557     State = ST_RX_TIMEOUT;
00558     nwk_setmode(NWK_RX_NOK);
00559     //debug_if( DEBUG_MESSAGE, "> OnRxTimeout\n\r" );
00560 }
00561 
00562 void OnRxError( void )
00563 {
00564     Radio.Sleep( );
00565     State = ST_RX_ERROR;
00566     //debug_if( DEBUG_MESSAGE, "> OnRxError\n\r" );
00567 }
00568 
00569 // Added by allankliu
00570 void OnCadDone( bool channelActivityDetected )
00571 {
00572     Radio.Sleep();
00573     channelOccupied = channelActivityDetected;
00574     State = ST_CAD_DONE;
00575 }