Aloha implementation of LoRa technology

Dependencies:   SX1276Lib mbed

Fork of SX1276PingPong by Semtech

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 #include "Aloha.h"
00006 #include "AlohaPacket.h"
00007 
00008 /* Set this flag to '1' to display debug messages on the console */
00009 #define DEBUG_MESSAGE   1
00010 
00011 #define RF_FREQUENCY                                    868000000 // Hz
00012 #define TX_OUTPUT_POWER                                 14        // 14 dBm
00013 #define LORA_BANDWIDTH                              2         // [0: 125 kHz,
00014                                                               //  1: 250 kHz,
00015                                                               //  2: 500 kHz,
00016                                                               //  3: Reserved]
00017 #define LORA_SPREADING_FACTOR                       7         // [SF7..SF12]
00018 #define LORA_CODINGRATE                             1         // [1: 4/5,
00019                                                               //  2: 4/6,
00020                                                               //  3: 4/7,
00021                                                               //  4: 4/8]
00022 #define LORA_PREAMBLE_LENGTH                        8         // Same for Tx and Rx
00023 #define LORA_SYMBOL_TIMEOUT                         5         // Symbols
00024 #define LORA_FIX_LENGTH_PAYLOAD_ON                  false
00025 #define LORA_FHSS_ENABLED                           false  
00026 #define LORA_NB_SYMB_HOP                            4     
00027 #define LORA_IQ_INVERSION_ON                        false
00028 #define LORA_CRC_ENABLED                            true
00029 
00030 
00031 #define RX_TIMEOUT_VALUE                                3500000   // in us
00032 #define BUFFER_SIZE                                     4 // Define the payload size here
00033 
00034 DigitalOut led(LED2);
00035 
00036 uint16_t BufferSize = BUFFER_SIZE;
00037 uint8_t Buffer[BUFFER_SIZE];
00038 
00039 int16_t RssiValue = 0.0;
00040 int8_t SnrValue = 0.0;
00041 
00042 /*
00043  *  Global variables declarations
00044  */
00045 typedef enum
00046 {
00047     LOWPOWER = 0,
00048     IDLE,
00049     
00050     RX,
00051     RX_TIMEOUT,
00052     RX_ERROR,
00053     
00054     TX,
00055     TX_TIMEOUT,
00056     
00057     CAD,
00058     CAD_DONE
00059 }AppStates_t;
00060 
00061 volatile AppStates_t State = LOWPOWER;
00062 
00063 
00064 /*!
00065  * Radio events function pointer
00066  */
00067 static RadioEvents_t RadioEvents;
00068 
00069 /*
00070  *  Global variables declarations
00071  */
00072 SX1276MB1xAS Radio( NULL );
00073 
00074 // aloha protocol
00075 Aloha aloha;
00076 
00077 // user button
00078 InterruptIn UserButton(USER_BUTTON);
00079 static int seqid = 0;
00080 
00081 void sendMessage()
00082 {
00083     HeaderStruct header;
00084     DataStruct data;
00085     
00086     memset(&header, 0, sizeof(header));
00087     memset(&data, 0, sizeof(data));
00088     
00089     header.fid = 0x0;
00090     header.no = (uint8_t) seqid;
00091     data.pd0 = 0xff;
00092     data.pd1 = 0xff;
00093     
00094     uint8_t buffer[4];
00095     createAlohaPacket(buffer, &header, &data);
00096     
00097     Radio.Send(buffer, 4);
00098 }
00099 
00100 void sendAck(int id)
00101 {
00102     HeaderStruct header;
00103     DataStruct data;
00104     
00105     memset(&header, 0, sizeof(header));
00106     memset(&data, 0, sizeof(data));
00107     
00108     header.fid = 0x1;
00109     header.no = (uint8_t) id;
00110     data.pd0 = 0x00;
00111     data.pd1 = 0x00;
00112     
00113     uint8_t buffer[4];
00114     createAlohaPacket(buffer, &header, &data);
00115     
00116     Radio.Send(buffer, 4);
00117 }
00118 
00119 
00120 void setExpire()
00121 {
00122     if (aloha.attempts >= ALOHA_MAX_ATTEMPT)
00123     {
00124         aloha.state = Aloha::EXPIRED;
00125     }
00126     else
00127     {
00128         aloha.state = Aloha::RETRANSMIT;
00129     }
00130 }
00131 
00132 void userButtonHandler()
00133 {
00134     seqid += 1;
00135     sendMessage();
00136 }
00137 
00138 void RadioInit()
00139 {
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     Radio.Init( &RadioEvents );
00147     
00148     // detect radio hardware
00149     while( Radio.Read( REG_VERSION ) == 0x00  )
00150     {
00151         printf( "Radio could not be detected!\n\r" );
00152         wait( 1 );
00153     }
00154     printf("RadioRegVersion: %d\r\n", Radio.Read( REG_VERSION ));
00155     
00156     // set radio frequency channel
00157     Radio.SetChannel( RF_FREQUENCY ); 
00158     
00159     // set radio parameter
00160     Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
00161                          LORA_SPREADING_FACTOR, LORA_CODINGRATE,
00162                          LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
00163                          LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, 
00164                          LORA_IQ_INVERSION_ON, 2000000 );
00165     
00166     Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
00167                          LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
00168                          LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, 0,
00169                          LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, 
00170                          LORA_IQ_INVERSION_ON, true );
00171 }
00172 
00173 
00174 int main() 
00175 {  
00176     RadioInit();
00177     UserButton.rise(userButtonHandler);
00178     
00179     Radio.Rx( RX_TIMEOUT_VALUE );
00180     while (1)
00181     {
00182         switch( State )
00183         {
00184         case RX:
00185             // if the receive frame is an ack, then cancel the timer
00186             // otherwise process the frame
00187             HeaderStruct header;
00188             DataStruct data;
00189             
00190             memset(&header, 0, sizeof(header));
00191             memset(&data, 0, sizeof(data));
00192             
00193             // decode data
00194             dissectAlohaPacket(Buffer, &header, &data);
00195             
00196             // process packet
00197             switch (header.fid)
00198             {
00199                 case 0x0: // data packet
00200                     sendAck(header.no);
00201                     break;
00202                     
00203                 case 0x1: // ack received
00204                     aloha.AlohaAckTimeout.detach();
00205                     aloha.state = Aloha::IDLE;
00206                     break;
00207                 
00208                 default:
00209                     break;
00210             }
00211                 
00212             if (header.fid == 0x01)
00213             {
00214                 aloha.AlohaAckTimeout.detach();
00215             }
00216             
00217             // TODO: process the frame
00218             
00219             
00220             printf("RECV::fid=0x%x, seqid=0x%x, pd0=0x%x, pd1=0x%x\r\n", header.fid, header.no, data.pd0, data.pd1);
00221             
00222             // enter listening mode
00223             Radio.Rx( RX_TIMEOUT_VALUE );
00224             
00225             State = LOWPOWER;
00226             break;
00227         case TX:
00228             // transmit done
00229             // set the state to pending and attach the timer with random delay
00230             
00231             // we dont need ack for ack
00232             if (aloha.state == Aloha::ACK_RESP)
00233             {
00234                 aloha.state =  Aloha::IDLE;
00235                 break;
00236             }
00237             
00238             // set delay time
00239             if (aloha.state == Aloha::IDLE)
00240             {
00241                 aloha.delay = (Radio.Random() % 1000) / 1000.0f;
00242             }
00243             else if (aloha.state == Aloha::RETRANSMIT)
00244             {
00245                 aloha.delay *= 2;
00246             }
00247             
00248             aloha.AlohaAckTimeout.detach();
00249             aloha.AlohaAckTimeout.attach(&setExpire, aloha.delay);
00250             
00251             // increase the attempt counter
00252             aloha.attempts += 1;
00253             
00254             // enter listening mode
00255             Radio.Rx( RX_TIMEOUT_VALUE );
00256             
00257             // state transition
00258             aloha.state = Aloha::PENDING;
00259                     
00260             State = LOWPOWER;
00261             break;
00262         case RX_TIMEOUT:
00263             // enter listening mode
00264             Radio.Rx( RX_TIMEOUT_VALUE );
00265             
00266             State = LOWPOWER;
00267             break;
00268         case RX_ERROR:
00269             // we don't handle crc failed situation
00270             // enter listening mode
00271             Radio.Rx( RX_TIMEOUT_VALUE );
00272             
00273             State = LOWPOWER;
00274             break;
00275         case TX_TIMEOUT:
00276             // we don't handle hardware error
00277             // enter listening mode
00278             Radio.Rx( RX_TIMEOUT_VALUE );
00279             
00280             State = LOWPOWER;
00281             break;
00282         case LOWPOWER:
00283             break;
00284         default:
00285             State = LOWPOWER;
00286             break;
00287         }
00288         
00289         switch (aloha.state)
00290         {
00291         case Aloha::IDLE:
00292             // transmit packet if any
00293             // printf("Aloha::IDLE\r\n");
00294             break;
00295         
00296         case Aloha::PENDING:
00297             // set rx time
00298             // printf("Aloha::PENDING, delay=%f, attempt=%d\r\n", aloha.delay, aloha.attempts);
00299             break;
00300             
00301         case Aloha::RETRANSMIT:
00302             // send the packet again
00303             sendMessage();
00304             
00305             // printf("Aloha::RETRANSMIT\r\n");
00306             break;
00307         case Aloha::EXPIRED:
00308             // give up the transmission
00309             // back to idle
00310             aloha.attempts = 0;
00311             
00312             aloha.state = Aloha::IDLE;
00313             // printf("Aloha::EXPIRED\r\n");
00314             break;
00315         case Aloha::ACK_RESP:
00316             break;
00317         default:
00318             break;
00319         }
00320     }
00321 }
00322 
00323 void OnTxDone( void )
00324 {
00325     Radio.Sleep( );
00326     State = TX;
00327     printf( "> OnTxDone\n\r" );
00328 }
00329 
00330 void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
00331 {
00332     Radio.Sleep( );
00333     BufferSize = size;
00334     memcpy( Buffer, payload, BufferSize );
00335     RssiValue = rssi;
00336     SnrValue = snr;
00337     State = RX;
00338     printf( "> OnRxDone\n\r" );
00339 }
00340 
00341 void OnTxTimeout( void )
00342 {
00343     Radio.Sleep( );
00344     State = TX_TIMEOUT;
00345     printf( "> OnTxTimeout\n\r" );
00346 }
00347 
00348 void OnRxTimeout( void )
00349 {
00350     Radio.Sleep( );
00351     Buffer[ BufferSize ] = 0;
00352     State = RX_TIMEOUT;
00353     printf( "> OnRxTimeout\n\r" );
00354 }
00355 
00356 void OnRxError( void )
00357 {
00358     Radio.Sleep( );
00359     State = RX_ERROR;
00360     printf( "> OnRxError\n\r" );
00361 }