create a LoRa Modem from the PingPong example

Dependencies:   SX1276Lib mbed

Fork of SX1276PingPong by Semtech

Files at this revision

API Documentation at this revision

Comitter:
donsez
Date:
Sun Mar 06 11:10:13 2016 +0000
Parent:
9:e764990e45df
Child:
16:352011886276
Commit message:
add lib

Changed in this revision

SX1276Lib.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/SX1276Lib.lib	Tue Dec 16 12:52:01 2014 +0000
+++ b/SX1276Lib.lib	Sun Mar 06 11:10:13 2016 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/GregCr/code/SX1276Lib/#618826a997e2
+https://developer.mbed.org/users/donsez/code/SX1276Lib/#452450d0b8c0
--- a/main.cpp	Tue Dec 16 12:52:01 2014 +0000
+++ b/main.cpp	Sun Mar 06 11:10:13 2016 +0000
@@ -1,25 +1,45 @@
 #include "mbed.h"
 #include "main.h"
 #include "sx1276-hal.h"
+
 #include "debug.h"
 
+/* CONFIGURATION */
+
+#define NODE_ADDR 0x411A
+
 /* Set this flag to '1' to display debug messages on the console */
-#define DEBUG_MESSAGE   0
+#define DEBUG_MESSAGE   1
+
+#define RX_MODE 1
+
+#define TX_MODE !RX_MODE
+
+/* Set the mode RX_MODE or TX_MODE */
+#define MODE RX_MODE
+
+/* Set the delay (according the duty cycle for the ISM band of the frequency RF_FREQUENCY */
+
+#define DUTY_CYCLE 0.01
+//#define DELAY_NEXT_TX_IN_MILLISEC ((int)((timeOnAirInMilli / DUTY_CYCLE)-timeOnAirInMilli))
+
+#define DELAY_NEXT_TX_IN_MILLISEC 5000
 
 /* Set this flag to '1' to use the LoRa modulation or to '0' to use FSK modulation */
 #define USE_MODEM_LORA  1
 #define USE_MODEM_FSK   !USE_MODEM_LORA
 
-#define RF_FREQUENCY                                    868000000 // Hz
+#define RF_FREQUENCY                                    868100000 // Hz
 #define TX_OUTPUT_POWER                                 14        // 14 dBm
 
+
 #if USE_MODEM_LORA == 1
 
-    #define LORA_BANDWIDTH                              2         // [0: 125 kHz,
+    #define LORA_BANDWIDTH                              0         // [0: 125 kHz,
                                                                   //  1: 250 kHz,
                                                                   //  2: 500 kHz,
                                                                   //  3: Reserved]
-    #define LORA_SPREADING_FACTOR                       7         // [SF7..SF12]
+    #define LORA_SPREADING_FACTOR                       12         // [SF7..SF12]
     #define LORA_CODINGRATE                             1         // [1: 4/5,
                                                                   //  2: 4/6,
                                                                   //  3: 4/7,
@@ -46,8 +66,11 @@
     #error "Please define a modem in the compiler options."
 #endif
 
-#define RX_TIMEOUT_VALUE                                3500000   // in us
-#define BUFFER_SIZE                                     32        // Define the payload size here
+#define RX_TIMEOUT_VALUE                                1000000000   // in us
+#define BUFFER_SIZE                                     17        // Define the payload size here
+
+
+Serial pc(USBTX,USBRX);
 
 #if( defined ( TARGET_KL25Z ) || defined ( TARGET_LPC11U6X ) )
 DigitalOut led(LED2);
@@ -61,211 +84,193 @@
 typedef RadioState States_t;
 volatile States_t State = LOWPOWER;
 
-SX1276MB1xAS Radio( OnTxDone, OnTxTimeout, OnRxDone, OnRxTimeout, OnRxError, NULL, NULL );
-
-const uint8_t PingMsg[] = "PING";
-const uint8_t PongMsg[] = "PONG";
+SX1276MB1xAS Radio( OnTxDone, OnTxTimeout, OnRxDone, OnRxTimeout, OnRxError, NULL /*OnFhssChangeChannel*/, NULL /*OnCadDone*/ );
 
 uint16_t BufferSize = BUFFER_SIZE;
 uint8_t Buffer[BUFFER_SIZE];
 
-int16_t RssiValue = 0.0;
-int8_t SnrValue = 0.0;
+int16_t RssiValue = 0;
+int8_t SnrValue = 0;
+
+ModemType Modem;
+
+uint16_t SeqNum = 0;
+
+// Address of the Source Node
+uint16_t NodeSrcAddr = NODE_ADDR;
+
+void hexprintf(Serial* pc, const uint8_t* buffer, uint16_t size)
+{
+    for(uint16_t count = 0; count < size; count++)
+    {
+        pc->printf("%02x", buffer[count]);
+    }
+}
+const uint8_t Msg[] = "TEST**##abcdefghijklmnopqrstuvwxyz#0123456789#ABCDEFGHIJKLMNOPQRSTUVWXYZ#0123456789#abcdefghijklmnopqrstuvwxyz#0123456789#ABCDEFGHIJKLMNOPQRSTUVWXYZ#0123456789#abcdefghijklmnopqrstuvwxyz#0123456789#ABCDEFGHIJKLMNOPQRSTUVWXYZ#0123456789#abcdefghijklmnopqrs#"; /* abc.. is for padding */
+
 
 int main() 
-{
-    uint8_t i;
-    bool isMaster = true;
+{    
+
+    pc.format(8, Serial::None, 1);
+    pc.baud(115200);
     
-    debug( "\n\n\r     SX1276 Ping Pong Demo Application \n\n\r" );
+    sx_debug( ">INFO RX/TX Modem \r\n\n" );
     
     // verify the connection with the board
     while( Radio.Read( REG_VERSION ) == 0x00  )
     {
-        debug( "Radio could not be detected!\n\r", NULL );
+        sx_debug( ">ERROR : Radio could not be detected!\r\n", NULL );
         wait( 1 );
     }
             
-    debug_if( ( DEBUG_MESSAGE & ( Radio.DetectBoardType( ) == SX1276MB1LAS ) ) , "\n\r > Board Type: SX1276MB1LAS < \n\r" );
-    debug_if( ( DEBUG_MESSAGE & ( Radio.DetectBoardType( ) == SX1276MB1MAS ) ) , "\n\r > Board Type: SX1276MB1MAS < \n\r" );
+    sx_debug_if( ( DEBUG_MESSAGE & ( Radio.DetectBoardType( ) == SX1276MB1LAS ) ) , ">INFO Board Type: SX1276MB1LAS\r\n" );
+    sx_debug_if( ( DEBUG_MESSAGE & ( Radio.DetectBoardType( ) == SX1276MB1MAS ) ) , ">INFO Board Type: SX1276MB1MAS\r\n" );
     
     Radio.SetChannel( RF_FREQUENCY ); 
 
+
 #if USE_MODEM_LORA == 1
     
-    debug_if( LORA_FHSS_ENABLED, "\n\n\r             > LORA FHSS Mode < \n\n\r");
-    debug_if( !LORA_FHSS_ENABLED, "\n\n\r             > LORA Mode < \n\n\r");
+    sx_debug_if( LORA_FHSS_ENABLED, ">INFO LORA FHSS Mode\r\n");
+    sx_debug_if( !LORA_FHSS_ENABLED, ">INFO LORA Mode\r\n");
 
-    Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
+    Modem = MODEM_LORA;
+
+    Radio.SetTxConfig( Modem, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
                          LORA_SPREADING_FACTOR, LORA_CODINGRATE,
                          LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
                          LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, 
                          LORA_IQ_INVERSION_ON, 2000000 );
     
-    Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
+    pc.printf(">INFO TX Parameters freq=%d bw=%d sf=%d cr=%d preamble=%d crc=%d fhss=%d hop=%d iq=%d\r\n",
+                        RF_FREQUENCY, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE,
+                        LORA_PREAMBLE_LENGTH, LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP,
+                        LORA_IQ_INVERSION_ON
+                        );
+
+    Radio.SetRxConfig( Modem, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
                          LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
                          LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, 0,
                          LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, 
                          LORA_IQ_INVERSION_ON, true );
                          
+                         
+    pc.printf(">INFO RX Parameters freq=%d bw=%d sf=%d cr=%d preamble=%d crc=%d fhss=%d hop=%d iq=%d\r\n",
+                        RF_FREQUENCY, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE,
+                        LORA_PREAMBLE_LENGTH, LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP,
+                        LORA_IQ_INVERSION_ON
+                        );
+                         
 #elif USE_MODEM_FSK == 1
 
-    debug("\n\n\r              > FSK Mode < \n\n\r");
+    sx_debug(">INFO FSK Mode\r\n");
+    
+    Modem = MODEM_FSK;
+
     Radio.SetTxConfig( MODEM_FSK, TX_OUTPUT_POWER, FSK_FDEV, 0,
                          FSK_DATARATE, 0,
                          FSK_PREAMBLE_LENGTH, FSK_FIX_LENGTH_PAYLOAD_ON,
                          FSK_CRC_ENABLED, 0, 0, 0, 2000000 );
+                         
+    pc.printf(">INFO TX Parameters freq=%d bw=%d sf=%d dr=%d\r\n",
+                        RF_FREQUENCY, FSK_BANDWIDTH, FSK_DATARATE );
     
     Radio.SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE,
                          0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH,
                          0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, FSK_CRC_ENABLED,
                          0, 0, false, true );
                          
+    pc.printf(">INFO RX Parameters freq=%d bw=%d dr=%d afc_bw=%d preamble=%d crc=%d\r\n",
+                        RF_FREQUENCY, FSK_BANDWIDTH, FSK_DATARATE, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH, FSK_CRC_ENABLED );
+
+                         
 #else
 
 #error "Please define a modem in the compiler options."
 
 #endif
-     
-    debug_if( DEBUG_MESSAGE, "Starting Ping-Pong loop\r\n" ); 
+
         
     led = 0;
-        
+#if MODE == RX_MODE
+     sx_debug_if( DEBUG_MESSAGE, ">INFO Starting RX loop\r\n" ); 
+
+    // start RX
     Radio.Rx( RX_TIMEOUT_VALUE );
+    State = LOWPOWER;
     
+#elif MODE == TX_MODE
+    sx_debug_if( DEBUG_MESSAGE, ">INFO Starting TX loop\r\n" ); 
+    State = TX;
+    
+#else
+#error "Please define a valid mode (RX_MODE, TX_MODE)."
+#endif
+
+// TODO ECHO_MODE : RX_MODE then TX_MODE
+
     while( 1 )
     {
         switch( State )
         {
         case RX:
-            if( isMaster == true )
-            {
                 if( BufferSize > 0 )
                 {
-                    if( strncmp( ( const char* )Buffer, ( const char* )PongMsg, 4 ) == 0 )
-                    {
-                        led = !led;
-                        debug( "...Pong\r\n" );
-                        // Send the next PING frame            
-                        strcpy( ( char* )Buffer, ( char* )PingMsg );
-                        // We fill the buffer with numbers for the payload 
-                        for( i = 4; i < BufferSize; i++ )
-                        {
-                            Buffer[i] = i - 4;
-                        }
-                        wait_ms( 10 ); 
-                        Radio.Send( Buffer, BufferSize );
-                    }
-                    else if( strncmp( ( const char* )Buffer, ( const char* )PingMsg, 4 ) == 0 )
-                    { // A master already exists then become a slave
-                        debug( "...Ping\r\n" );
-                        led = !led;
-                        isMaster = false;
-                        // Send the next PONG frame            
-                        strcpy( ( char* )Buffer, ( char* )PongMsg );
-                        // We fill the buffer with numbers for the payload 
-                        for( i = 4; i < BufferSize; i++ )
-                        {
-                            Buffer[i] = i - 4;
-                        }
-                        wait_ms( 10 ); 
-                        Radio.Send( Buffer, BufferSize );
-                    }
-                    else // valid reception but neither a PING or a PONG message
-                    {    // Set device as master ans start again
-                        isMaster = true;
-                        Radio.Rx( RX_TIMEOUT_VALUE );
-                    }    
+                    led = !led; // Invert LED
+
+                    
+                    // TODO ADD  tmst | number | Internal timestamp of "RX finished" event (32b unsigned)
+
+                    pc.printf(">INFO RX modem=%d size=%d rssi=%d snr=%d freq=%d bw=%d sf=%d cr=%d buffer=",
+                        Modem, BufferSize, RssiValue, SnrValue, RF_FREQUENCY, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE );
+                    hexprintf(&pc, Buffer, BufferSize);
+                    pc.printf("\r\n");
+
+                    pc.printf("RX;%d;%d;%d;%d;%d;%d;%d;%d;",
+                        Modem, BufferSize, RssiValue, SnrValue, RF_FREQUENCY, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE );
+                    hexprintf(&pc, Buffer, BufferSize);
+                    pc.printf("\r\n");
+//                        wait_ms( 10 ); 
+                    Radio.Rx( RX_TIMEOUT_VALUE );
                 }
-            }
-            else
-            {
-                if( BufferSize > 0 )
-                {
-                    if( strncmp( ( const char* )Buffer, ( const char* )PingMsg, 4 ) == 0 )
-                    {
-                        led = !led;
-                        debug( "...Ping\r\n" );
-                        // Send the reply to the PING string
-                        strcpy( ( char* )Buffer, ( char* )PongMsg );
-                        // We fill the buffer with numbers for the payload 
-                        for( i = 4; i < BufferSize; i++ )
-                        {
-                            Buffer[i] = i - 4;
-                        }
-                        wait_ms( 10 );  
-                        Radio.Send( Buffer, BufferSize );
-                    }
-                    else // valid reception but not a PING as expected
-                    {    // Set device as master and start again
-                        isMaster = true;
-                        Radio.Rx( RX_TIMEOUT_VALUE );
-                    }    
-                }
-            }
-            State = LOWPOWER;
-            break;
-        case TX:    
-            led = !led; 
-            if( isMaster == true )  
-            {
-                debug( "Ping...\r\n" );
-            }
-            else
-            {
-                debug( "Pong...\r\n" );
-            }
-            Radio.Rx( RX_TIMEOUT_VALUE );
+            
             State = LOWPOWER;
             break;
         case RX_TIMEOUT:
-            if( isMaster == true )
-            {
-                // Send the next PING frame
-                strcpy( ( char* )Buffer, ( char* )PingMsg );
-                for( i = 4; i < BufferSize; i++ )
-                {
-                    Buffer[i] = i - 4;
-                }
-                wait_ms( 10 ); 
-                Radio.Send( Buffer, BufferSize );
-            }
-            else
-            {
-                Radio.Rx( RX_TIMEOUT_VALUE );  
-            }             
+            Radio.Rx( RX_TIMEOUT_VALUE );  
             State = LOWPOWER;
             break;
         case RX_ERROR:
-            // We have received a Packet with a CRC error, send reply as if packet was correct
-            if( isMaster == true )
-            {
-                // Send the next PING frame
-                strcpy( ( char* )Buffer, ( char* )PingMsg );
-                for( i = 4; i < BufferSize; i++ )
-                {
-                    Buffer[i] = i - 4;
-                }
-                wait_ms( 10 );  
-                Radio.Send( Buffer, BufferSize );
-            }
-            else
-            {
-                // Send the next PONG frame
-                strcpy( ( char* )Buffer, ( char* )PongMsg );
-                for( i = 4; i < BufferSize; i++ )
-                {
-                    Buffer[i] = i - 4;
-                }
-                wait_ms( 10 );  
-                Radio.Send( Buffer, BufferSize );
-            }
+            // We have received a Packet with a CRC error
+            pc.printf(">INFO RX_ERROR size=%d\r\n", BufferSize); 
+            pc.printf("RX_ERROR;%d\r\n", BufferSize); 
+            Radio.Rx( RX_TIMEOUT_VALUE );  
             State = LOWPOWER;
             break;
         case TX_TIMEOUT:
-            Radio.Rx( RX_TIMEOUT_VALUE );
+            pc.printf(">TX: TIMEOUT\r\n");
+        case TX:
+            int timeOnAirInMilli = Radio.TimeOnAir(Modem,BufferSize)/1000;
+            if(DELAY_NEXT_TX_IN_MILLISEC!=0) {
+                pc.printf(">INFO: wait %.4f sec before TX\r\n", DELAY_NEXT_TX_IN_MILLISEC/1000.0);
+                wait_ms( DELAY_NEXT_TX_IN_MILLISEC );
+            }
+            led = !led; // Invert LED
+            memcpy(( char* )Buffer, ( char* ) Msg, BufferSize);
+            ++SeqNum;
+            /* refresh counters in payload (big endian, for readability) */
+            Buffer[4] = (uint8_t)(SeqNum >> 8); /* MSB */
+            Buffer[5] = (uint8_t)(SeqNum & 0x00FF); /* LSB */
+            Buffer[6] = (uint8_t)(NodeSrcAddr >> 8); /* MSB */
+            Buffer[7] = (uint8_t)(NodeSrcAddr & 0x00FF); /* LSB */
+
+            /* send packet */
+            pc.printf(">TX: src=%4x seqnum=%u size=%d timeOnAir=%.4f\r\n", NodeSrcAddr, SeqNum, BufferSize, timeOnAirInMilli/1000.0);
+            wait_ms( 10 ); 
+            Radio.Send( Buffer, BufferSize );
             State = LOWPOWER;
-            break;
+            break;            
         case LOWPOWER:
             break;
         default:
@@ -279,7 +284,7 @@
 {
     Radio.Sleep( );
     State = TX;
-    debug_if( DEBUG_MESSAGE, "> OnTxDone\n\r" );
+    sx_debug_if( DEBUG_MESSAGE, ">INFO OnTxDone\r\n" );
 }
 
 void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
@@ -290,14 +295,14 @@
     RssiValue = rssi;
     SnrValue = snr;
     State = RX;
-    debug_if( DEBUG_MESSAGE, "> OnRxDone\n\r" );
+    sx_debug_if( DEBUG_MESSAGE, ">INFO OnRxDone\r\n" );
 }
 
 void OnTxTimeout( void )
 {
     Radio.Sleep( );
     State = TX_TIMEOUT;
-    debug_if( DEBUG_MESSAGE, "> OnTxTimeout\n\r" );
+    sx_debug_if( DEBUG_MESSAGE, ">INFO OnTxTimeout\r\n" );
 }
 
 void OnRxTimeout( void )
@@ -305,13 +310,29 @@
     Radio.Sleep( );
     Buffer[ BufferSize ] = 0;
     State = RX_TIMEOUT;
-    debug_if( DEBUG_MESSAGE, "> OnRxTimeout\n\r" );
+    sx_debug_if( DEBUG_MESSAGE, ">INFO OnRxTimeout\r\n" );
 }
 
 void OnRxError( void )
 {
     Radio.Sleep( );
     State = RX_ERROR;
-    debug_if( DEBUG_MESSAGE, "> OnRxError\n\r" );
+    sx_debug_if( DEBUG_MESSAGE, ">INFO OnRxError\r\n" );
 }
 
+/*!
+ * @brief Function executed on Radio Fhss Change Channel event
+ */
+void OnFhssChangeChannel( uint8_t channelIndex )
+{
+      sx_debug_if( DEBUG_MESSAGE, ">INFO OnFhssChangeChannel\r\n" );  
+}
+
+/*!
+ * @brief Function executed on CAD Done event
+ */
+void OnCadDone( void )
+{
+    State = TX;
+    sx_debug_if( DEBUG_MESSAGE, ">INFO OnCadDone\r\n" );  
+}
\ No newline at end of file