Lora Transport Abstraction Layer for sx1272

Dependents:   lora-transceiver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LoraTransport.cpp Source File

LoraTransport.cpp

00001 #include "LoraTransport.h"
00002 #include "mbed.h"
00003 
00004 namespace LoraTransport {
00005 
00006     namespace {
00007 
00008         void onTxDone();
00009         void onTxTimeout();
00010         void onRxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr);
00011         void onRxTimeout();
00012         void onCadDone(bool);
00013         void onRxError();
00014 
00015         XRange _radio(onTxDone, onTxTimeout, onRxDone, onRxTimeout, onRxError, NULL, onCadDone );
00016         mbed::Timer _timer;
00017         int _deadline;
00018         uint16_t _addr;
00019         int16_t _rssi_value;
00020         int8_t _snr_value;
00021         State _state;
00022         State _last_error_state;
00023         uint8_t _next_packet_number;
00024         Packet _packet;
00025         Ack _ack;
00026 
00027         /*bool overNineThousand(int n){
00028             return n > 9000; // https://www.youtube.com/watch?v=LqSg9yVfzV0
00029         }*/
00030 
00031         void onCadDone(bool activityDetected){
00032             _radio.Sleep();
00033             if(activityDetected){
00034                 _radio.StartCad();
00035             }else{
00036                 wait_ms((_radio.Random()%100)*10);
00037                 if(_state == TX_MSG){
00038                     _radio.Send((uint8_t*)&_packet, _packet.payload_size+5);
00039                 }else if(_state == TX_SUCCESS_ACK || _state == TX_ERROR_ACK){
00040                     _radio.Send((uint8_t*)&_ack, sizeof(_ack));
00041                 }
00042             }
00043         }
00044 
00045         void onTxTimeout(){
00046             _radio.Sleep();
00047             //printf("tx timeout\r\n");
00048             //printf("time on air for packet: %f\r\n",_radio.TimeOnAir(MODEM_LORA,_packet.payload_size+5));
00049             if(_timer.read_us() > _deadline){
00050                 //printf("deadline reached, give up\r\n");
00051                 _timer.stop();
00052                 if(_state == TX_MSG){
00053                     //printf("tx timeout while sending message\r\n");
00054                     // timeout sending message
00055                     _last_error_state = TX_MSG_TIMEOUT;
00056                     _state = TX_ERROR;
00057                 }else if(_state == TX_SUCCESS_ACK){
00058                     //printf("tx timeout while sending success ack\r\n");
00059                     // timeout sending success ack
00060                     _last_error_state = TX_SUCCESS_ACK_TIMEOUT;
00061                     _state = RX_ERROR;
00062                 }else if(_state == TX_ERROR_ACK){
00063                     //printf("tx timeout while sending error ack\r\n");
00064                     // timeout sending error ack
00065                     _last_error_state = TX_ERROR_ACK_TIMEOUT;
00066                     _state = RX_ERROR;
00067                 }
00068             }else{
00069                 _radio.StartCad();
00070             }
00071         }
00072 
00073         void onTxDone(){
00074             _radio.Sleep();
00075             if(_state == TX_MSG){
00076                 // sending message ready, now wait for ack
00077                 _state = RX_ACK;
00078                 _radio.Rx(RX_TIMEOUT_VALUE);
00079             }else if(_state == TX_SUCCESS_ACK){
00080                 // sending success ack ready -> success!
00081                 _timer.stop();
00082                 _state = RX_SUCCESS;
00083             }else if(_state == TX_ERROR_ACK){
00084                 // sending error ack ready
00085                 if(_timer.read_us() > _deadline){
00086                     // no time for retry
00087                     //printf("error ack transmitted, give up\r\n");
00088                     _last_error_state = RX_MSG_ERROR;
00089                     _timer.stop();
00090                     _state = RX_ERROR;
00091                 }else{
00092                     // we have time for retry!
00093                     //printf("error ack transmitted, retry\r\n");
00094                     _state = RX_MSG;
00095                     _radio.Rx(RX_TIMEOUT_VALUE);
00096                 }
00097             }
00098         }
00099 
00100         void onRxTimeout(){
00101             _radio.Sleep();
00102             if(_state == RX_MSG){
00103                 if(_timer.read_us() > _deadline){
00104                     // no time for retry
00105                     //printf("rx msg timeout, give up\r\n");
00106                     _timer.stop();
00107                     _last_error_state = RX_MSG_TIMEOUT;
00108                     _state = RX_ERROR;
00109                 }else{
00110                     // we have time for retry!
00111                     //printf("rx msg timeout, retry\r\n");
00112                     _radio.Rx(RX_TIMEOUT_VALUE);
00113                 }
00114             }else if(_state == RX_ACK){
00115                 // no ack received
00116                 if(_timer.read_us() > _deadline){
00117                     // no time for retry
00118                     //printf("rx ack timeout, give up\r\n");
00119                     _timer.stop();
00120                     _last_error_state = RX_ACK_TIMEOUT;
00121                     _state = TX_ERROR;
00122                 }else{
00123                     // we have time for retry!
00124                     //printf("rx ack timeout, retry\r\n");
00125                     _state = TX_MSG;
00126                     _radio.StartCad();
00127                 }
00128             }
00129         }
00130 
00131         void onRxError(){
00132             _radio.Sleep();
00133             if(_state == RX_MSG){
00134                 if(_timer.read_us() > _deadline){
00135                     //printf("rx message error, give up\r\n");
00136                     // no time for retry
00137                     _timer.stop();
00138                     _last_error_state = RX_MSG_ERROR;
00139                     _state = RX_ERROR;
00140                 }else{
00141                     // we have time for retry -> send fail ack;
00142                     //printf("rx message error, send fail ack\r\n");
00143                     _ack.from_addr = _addr;
00144                     _ack.to_addr = 0;
00145                     _ack.success = false;
00146                     _state = TX_ERROR_ACK;
00147                     _radio.StartCad();
00148                 }
00149             }else if(_state == RX_ACK){
00150                 // no ack received
00151                 if(_timer.read_us() > _deadline){
00152                     // no time for retry
00153                     //printf("rx ack error, give up\r\n");
00154                     _timer.stop();
00155                     _last_error_state = RX_ACK_TIMEOUT;
00156                     _state = TX_ERROR;
00157                 }else{
00158                     // we have time for retry!
00159                     //printf("rx ack error, retry\r\n");
00160                     _state = TX_MSG;
00161                     _radio.StartCad();
00162                 }
00163             }
00164         }
00165 
00166         void onRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ){
00167             _radio.Sleep();
00168             _rssi_value = rssi;
00169             _snr_value = snr;
00170             if(_state == RX_MSG){
00171                 _packet.to_addr = *((uint16_t*)(payload+2));
00172                 if(_packet.to_addr != _addr && _packet.to_addr != 0){
00173                     //packet is not for us
00174                     if(_timer.read_us() > _deadline){
00175                         // no time for retry
00176                         _timer.stop();
00177                         _last_error_state = RX_MSG_TIMEOUT;
00178                         _state = RX_ERROR;
00179                     }else{
00180                         //printf("packet is not for us, retry\r\n");
00181                         _state = RX_MSG;
00182                         _radio.Rx(RX_TIMEOUT_VALUE);
00183                     }
00184                 }else{
00185                     //packet is for us
00186                     _packet.from_addr = *((uint16_t*)(payload));
00187                     _packet.packet_number = *(payload+4);
00188                     _packet.payload_size = size-5;
00189                     memcpy(_packet.payload, payload+5, _packet.payload_size);
00190                     _ack.packet_number = _packet.packet_number;
00191                     _ack.from_addr = _packet.to_addr;
00192                     _ack.to_addr = _packet.from_addr;
00193                     _ack.success = true;
00194                     _state = TX_SUCCESS_ACK;
00195                     _radio.StartCad();
00196                 }
00197             }else if(_state == RX_ACK){
00198                 _ack.to_addr = *((uint16_t*)(payload+2));
00199                 if(_ack.to_addr != _addr && _ack.to_addr != 0){
00200                     //ack is not for us
00201                     if(_timer.read_us() > _deadline){
00202                         //printf("ack is not for us, give up\r\n");
00203                         // no time for retry
00204                         _timer.stop();
00205                         _last_error_state = RX_ACK_TIMEOUT;
00206                         _state = TX_ERROR;
00207                     }else{
00208                         //printf("ack is not for us, retry\r\n");
00209                         _state = RX_ACK;
00210                         _radio.Rx(RX_TIMEOUT_VALUE);
00211                     }
00212                 }else{
00213                     //ack is for us
00214                     _ack.from_addr = *((uint16_t*)payload);
00215                     _ack.packet_number = *(payload+4);
00216                     _ack.success = *(payload+5);
00217                     if(_ack.success == true && _ack.packet_number == _packet.packet_number){
00218                         // got success ack -> transmission completed!
00219                         _timer.stop();
00220                         _state = TX_SUCCESS;
00221                     }else{
00222                         if(_timer.read_us() > _deadline){
00223                             // no time for retry
00224                             //printf("got fail ack, give up\r\n");
00225                             _timer.stop();
00226                             _last_error_state = TX_MSG_TIMEOUT;
00227                             _state = TX_ERROR;
00228                         }else{
00229                             //retry
00230                             //printf("got fail ack, retry\r\n");
00231                             _state = TX_MSG;
00232                             _radio.StartCad();
00233                         }
00234                     }
00235                 }
00236             }
00237         }
00238 
00239     }//end anonym namespace
00240 
00241 
00242     void init(){
00243         _addr = 0;
00244         _rssi_value = 0;
00245         _snr_value = 0;
00246         _state = IDLE;
00247         _last_error_state = IDLE;
00248         _next_packet_number = 0;
00249         _radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
00250                            LORA_SPREADING_FACTOR, LORA_CODINGRATE,
00251                            LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
00252                            LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP,
00253                            LORA_IQ_INVERSION_ON, TX_TIMEOUT_VALUE );
00254         _radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
00255                            LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
00256                            LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, 0,
00257                            LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP,
00258                            LORA_IQ_INVERSION_ON, true );
00259     }
00260 
00261     void setAddress(uint16_t addr){
00262         _addr = addr;
00263     }
00264 
00265     void send(uint16_t addr, uint8_t *ptr, uint8_t len, uint32_t timeout){
00266         _packet.from_addr = _addr;
00267         _packet.to_addr = addr;
00268         _packet.packet_number = _next_packet_number++;
00269         memcpy(_packet.payload, ptr, len);
00270         _packet.payload_size = len;
00271         _state = CAD_RUNNING;
00272         _deadline = timeout;
00273         _timer.stop();
00274         _timer.reset();
00275         _timer.start();
00276         _state = TX_MSG;
00277         //printf("send message with %i bytes\r\n",len);
00278         _radio.StartCad();
00279     }
00280 
00281     void recv(uint32_t timeout){
00282         _state = RX_MSG;
00283         _deadline = timeout;
00284         _timer.stop();
00285         _timer.reset();
00286         _timer.start();
00287         _state = RX_MSG;
00288         _radio.Rx(RX_TIMEOUT_VALUE);
00289     }
00290 
00291     State getState(){
00292         return _state;
00293     }
00294     State getLastErrorState(){
00295         return _last_error_state;
00296     }
00297     Packet& getPacket(){
00298         return _packet;
00299     }
00300     int16_t getRSSI(){
00301         return _rssi_value;
00302     }
00303     int8_t getSNR(){
00304         return _snr_value;
00305     }
00306 
00307     bool done(){
00308         if( _state == TX_ERROR ||
00309             _state == TX_SUCCESS ||
00310             _state == RX_ERROR ||
00311             _state == RX_SUCCESS ||
00312             _state == IDLE) {
00313             return true;
00314         }
00315         return false;
00316     }
00317 
00318     bool success(){
00319         if(_state == TX_SUCCESS || _state == RX_SUCCESS) {
00320             return true;
00321         }
00322         return false;
00323     }
00324 
00325 
00326 } // end LoraTranport namespace