Lora Transport Abstraction Layer for sx1272
Embed:
(wiki syntax)
Show/hide line numbers
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
Generated on Thu Jul 14 2022 14:48:44 by 1.7.2