Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
LoRaMac.cpp
00001 /** 00002 / _____) _ | | 00003 ( (____ _____ ____ _| |_ _____ ____| |__ 00004 \____ \| ___ | (_ _) ___ |/ ___) _ \ 00005 _____) ) ____| | | || |_| ____( (___| | | | 00006 (______/|_____)_|_|_| \__)_____)\____)_| |_| 00007 (C)2013 Semtech 00008 ___ _____ _ ___ _ _____ ___ ___ ___ ___ 00009 / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __| 00010 \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _| 00011 |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___| 00012 embedded.connectivity.solutions=============== 00013 00014 Description: LoRa MAC layer implementation 00015 00016 License: Revised BSD License, see LICENSE.TXT file include in the project 00017 00018 Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE ) 00019 00020 Copyright (c) 2017, Arm Limited and affiliates. 00021 00022 SPDX-License-Identifier: BSD-3-Clause 00023 */ 00024 #include <stdlib.h> 00025 #include "LoRaMac.h" 00026 #include "LoRaMacCrypto.h" 00027 00028 #if defined(FEATURE_COMMON_PAL) 00029 #include "mbed_trace.h" 00030 #define TRACE_GROUP "LMAC" 00031 #else 00032 #define tr_debug(...) (void(0)) //dummies if feature common pal is not added 00033 #define tr_info(...) (void(0)) //dummies if feature common pal is not added 00034 #define tr_error(...) (void(0)) //dummies if feature common pal is not added 00035 #endif //defined(FEATURE_COMMON_PAL) 00036 00037 using namespace events; 00038 00039 /*! 00040 * Maximum length of the fOpts field 00041 */ 00042 #define LORA_MAC_COMMAND_MAX_FOPTS_LENGTH 15 00043 00044 /*! 00045 * LoRaMac duty cycle for the back-off procedure during the first hour. 00046 */ 00047 #define BACKOFF_DC_1_HOUR 100 00048 00049 /*! 00050 * LoRaMac duty cycle for the back-off procedure during the next 10 hours. 00051 */ 00052 #define BACKOFF_DC_10_HOURS 1000 00053 00054 /*! 00055 * LoRaMac duty cycle for the back-off procedure during the next 24 hours. 00056 */ 00057 #define BACKOFF_DC_24_HOURS 10000 00058 00059 /*! 00060 * Check the MAC layer state every MAC_STATE_CHECK_TIMEOUT in ms. 00061 */ 00062 #define MAC_STATE_CHECK_TIMEOUT 1000 00063 00064 /*! 00065 * The maximum number of times the MAC layer tries to get an acknowledge. 00066 */ 00067 #define MAX_ACK_RETRIES 8 00068 00069 /*! 00070 * The frame direction definition for uplink communications. 00071 */ 00072 #define UP_LINK 0 00073 00074 /*! 00075 * The frame direction definition for downlink communications. 00076 */ 00077 #define DOWN_LINK 1 00078 00079 00080 LoRaMac::LoRaMac(LoRaWANTimeHandler &lora_time) 00081 : mac_commands(), _lora_time(lora_time) 00082 { 00083 lora_phy = NULL; 00084 //radio_events_t RadioEvents; 00085 _params.keys.dev_eui = NULL; 00086 _params.keys.app_eui = NULL; 00087 _params.keys.app_key = NULL; 00088 00089 memset(_params.keys.nwk_skey, 0, sizeof(_params.keys.nwk_skey)); 00090 memset(_params.keys.app_skey, 0, sizeof(_params.keys.app_skey)); 00091 00092 _params.dev_nonce = 0; 00093 _params.net_id = 0; 00094 _params.dev_addr = 0; 00095 _params.buffer_pkt_len = 0; 00096 _params.payload_length = 0; 00097 _params.ul_frame_counter = 0; 00098 _params.dl_frame_counter = 0; 00099 _params.is_ul_frame_counter_fixed = false; 00100 _params.is_rx_window_enabled = true; 00101 _params.is_nwk_joined = false; 00102 _params.adr_ack_counter = 0; 00103 _params.is_node_ack_requested = false; 00104 _params.is_srv_ack_requested = false; 00105 _params.ul_nb_rep_counter = 0; 00106 _params.timers.mac_init_time = 0; 00107 _params.mac_state = LORAMAC_IDLE; 00108 _params.max_ack_timeout_retries = 1; 00109 _params.ack_timeout_retry_counter = 1; 00110 _params.is_ack_retry_timeout_expired = false; 00111 _params.timers.tx_toa = 0; 00112 00113 _params.multicast_channels = NULL; 00114 00115 _params.sys_params.adr_on = false; 00116 _params.sys_params.max_duty_cycle = 0; 00117 00118 mac_primitives = NULL; 00119 ev_queue = NULL; 00120 } 00121 00122 LoRaMac::~LoRaMac() 00123 { 00124 } 00125 00126 00127 /*************************************************************************** 00128 * ISRs - Handlers * 00129 **************************************************************************/ 00130 void LoRaMac::handle_tx_done(void) 00131 { 00132 const int ret = ev_queue->call(this, &LoRaMac::on_radio_tx_done); 00133 MBED_ASSERT(ret != 0); 00134 (void)ret; 00135 } 00136 00137 void LoRaMac::handle_rx_done(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr) 00138 { 00139 const int ret = ev_queue->call(this, &LoRaMac::on_radio_rx_done, payload, size, rssi, snr); 00140 MBED_ASSERT(ret != 0); 00141 (void)ret; 00142 } 00143 00144 void LoRaMac::handle_rx_error(void) 00145 { 00146 const int ret = ev_queue->call(this, &LoRaMac::on_radio_rx_error); 00147 MBED_ASSERT(ret != 0); 00148 (void)ret; 00149 } 00150 00151 void LoRaMac::handle_rx_timeout(void) 00152 { 00153 const int ret = ev_queue->call(this, &LoRaMac::on_radio_rx_timeout); 00154 MBED_ASSERT(ret != 0); 00155 (void)ret; 00156 } 00157 00158 void LoRaMac::handle_tx_timeout(void) 00159 { 00160 const int ret = ev_queue->call(this, &LoRaMac::on_radio_tx_timeout); 00161 MBED_ASSERT(ret != 0); 00162 (void)ret; 00163 } 00164 00165 void LoRaMac::handle_cad_done(bool cad) 00166 { 00167 //TODO Not implemented yet 00168 //const int ret = ev_queue->call(this, &LoRaMac::OnRadioCadDone, cad); 00169 //MBED_ASSERT(ret != 0); 00170 //(void)ret; 00171 } 00172 00173 void LoRaMac::handle_fhss_change_channel(uint8_t cur_channel) 00174 { 00175 // TODO Not implemented yet 00176 //const int ret = ev_queue->call(this, &LoRaMac::OnRadioFHSSChangeChannel, cur_channel); 00177 //MBED_ASSERT(ret != 0); 00178 //(void)ret; 00179 } 00180 00181 void LoRaMac::handle_mac_state_check_timer_event(void) 00182 { 00183 const int ret = ev_queue->call(this, &LoRaMac::on_mac_state_check_timer_event); 00184 MBED_ASSERT(ret != 0); 00185 (void)ret; 00186 } 00187 00188 void LoRaMac::handle_delayed_tx_timer_event(void) 00189 { 00190 const int ret = ev_queue->call(this, &LoRaMac::on_tx_delayed_timer_event); 00191 MBED_ASSERT(ret != 0); 00192 (void)ret; 00193 } 00194 00195 void LoRaMac::handle_ack_timeout() 00196 { 00197 const int ret = ev_queue->call(this, &LoRaMac::on_ack_timeout_timer_event); 00198 MBED_ASSERT(ret != 0); 00199 (void)ret; 00200 } 00201 00202 void LoRaMac::handle_rx1_timer_event(void) 00203 { 00204 const int ret = ev_queue->call(this, &LoRaMac::on_rx_window1_timer_event); 00205 MBED_ASSERT(ret != 0); 00206 (void)ret; 00207 } 00208 00209 void LoRaMac::handle_rx2_timer_event(void) 00210 { 00211 const int ret = ev_queue->call(this, &LoRaMac::on_rx_window2_timer_event); 00212 MBED_ASSERT(ret != 0); 00213 (void)ret; 00214 } 00215 00216 /*************************************************************************** 00217 * Radio event callbacks - delegated to Radio driver * 00218 **************************************************************************/ 00219 void LoRaMac::on_radio_tx_done( void ) 00220 { 00221 set_band_txdone_params_t tx_done_params; 00222 lorawan_time_t cur_time = _lora_time.get_current_time( ); 00223 loramac_mlme_confirm_t mlme_confirm = mlme.get_confirmation(); 00224 00225 if (_params.dev_class != CLASS_C ) { 00226 lora_phy->put_radio_to_sleep(); 00227 } else { 00228 open_continuous_rx2_window(); 00229 } 00230 00231 // Setup timers 00232 if(_params.is_rx_window_enabled == true) { 00233 _lora_time.start(_params.timers.rx_window1_timer, _params.rx_window1_delay); 00234 00235 if (_params.dev_class != CLASS_C ) { 00236 _lora_time.start(_params.timers.rx_window2_timer, _params.rx_window2_delay); 00237 } 00238 00239 if ((_params.dev_class == CLASS_C ) || 00240 (_params.is_node_ack_requested == true)) { 00241 _lora_time.start(_params.timers.ack_timeout_timer, 00242 _params.rx_window2_delay + lora_phy->get_ack_timeout()); 00243 } 00244 } else { 00245 mcps.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_OK ; 00246 mlme_confirm.status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT ; 00247 00248 if (_params.flags.value == 0) { 00249 _params.flags.bits.mcps_req = 1; 00250 } 00251 00252 _params.flags.bits.mac_done = 1; 00253 } 00254 00255 // Verify if the last uplink was a join request 00256 if ((_params.flags.bits.mlme_req == 1) && 00257 (mlme_confirm.req_type == MLME_JOIN )) { 00258 _params.is_last_tx_join_request = true; 00259 } else { 00260 _params.is_last_tx_join_request = false; 00261 } 00262 00263 // Store last Tx channel 00264 _params.last_channel_idx = _params.channel; 00265 00266 // Update last tx done time for the current channel 00267 tx_done_params.channel = _params.channel; 00268 tx_done_params.joined = _params.is_nwk_joined; 00269 tx_done_params.last_tx_done_time = cur_time; 00270 lora_phy->set_last_tx_done(&tx_done_params); 00271 00272 // Update Aggregated last tx done time 00273 _params.timers.aggregated_last_tx_time = cur_time; 00274 00275 if (_params.is_node_ack_requested == false) { 00276 mcps.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_OK ; 00277 _params.ul_nb_rep_counter++; 00278 } 00279 } 00280 00281 void LoRaMac::prepare_rx_done_abort(void) 00282 { 00283 _params.mac_state |= LORAMAC_RX_ABORT; 00284 00285 if (_params.is_node_ack_requested) { 00286 handle_ack_timeout(); 00287 } 00288 00289 _params.flags.bits.mcps_ind = 1; 00290 _params.flags.bits.mac_done = 1; 00291 00292 // Trigger MAC state check event timer as soon as possible 00293 _lora_time.start(_params.timers.mac_state_check_timer, 1); 00294 } 00295 00296 void LoRaMac::on_radio_rx_done(uint8_t *payload, uint16_t size, int16_t rssi, 00297 int8_t snr) 00298 { 00299 loramac_mhdr_t mac_hdr; 00300 loramac_frame_ctrl_t fctrl; 00301 cflist_params_t cflist; 00302 bool skip_indication = false; 00303 00304 uint8_t pkt_header_len = 0; 00305 uint32_t address = 0; 00306 uint8_t app_payload_start_index = 0; 00307 uint8_t frame_len = 0; 00308 uint32_t mic = 0; 00309 uint32_t mic_rx = 0; 00310 00311 uint16_t sequence_counter = 0; 00312 uint16_t sequence_counter_prev = 0; 00313 uint16_t sequence_counter_diff = 0; 00314 uint32_t downlink_counter = 0; 00315 00316 multicast_params_t *cur_multicast_params = NULL; 00317 uint8_t *nwk_skey = _params.keys.nwk_skey; 00318 uint8_t *app_skey = _params.keys.app_skey; 00319 00320 uint8_t multicast = 0; 00321 00322 bool is_mic_ok = false; 00323 00324 mcps.get_confirmation().ack_received = false; 00325 mcps.get_indication().rssi = rssi; 00326 mcps.get_indication().snr = snr; 00327 mcps.get_indication().rx_slot = _params.rx_slot; 00328 mcps.get_indication().port = 0; 00329 mcps.get_indication().multicast = 0; 00330 mcps.get_indication().fpending_status = 0; 00331 mcps.get_indication().buffer = NULL; 00332 mcps.get_indication().buffer_size = 0; 00333 mcps.get_indication().is_data_recvd = false; 00334 mcps.get_indication().is_ack_recvd = false; 00335 mcps.get_indication().dl_frame_counter = 0; 00336 mcps.get_indication().type = MCPS_UNCONFIRMED ; 00337 00338 lora_phy->put_radio_to_sleep(); 00339 00340 _lora_time.stop( _params.timers.rx_window2_timer ); 00341 00342 mac_hdr.value = payload[pkt_header_len++]; 00343 00344 switch (mac_hdr.bits.mtype ) { 00345 00346 case FRAME_TYPE_JOIN_ACCEPT : 00347 if (_params.is_nwk_joined == true) { 00348 mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_ERROR ; 00349 prepare_rx_done_abort(); 00350 return; 00351 } 00352 00353 if (0 != decrypt_join_frame(payload + 1, size - 1, 00354 _params.keys.app_key, 00355 _params.payload + 1)) { 00356 mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL ; 00357 return; 00358 } 00359 00360 _params.payload[0] = mac_hdr.value ; 00361 00362 if (0 != compute_join_frame_mic(_params.payload, size - LORAMAC_MFR_LEN, 00363 _params.keys.app_key, &mic)) { 00364 mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL ; 00365 return; 00366 } 00367 00368 mic_rx |= (uint32_t) _params.payload[size - LORAMAC_MFR_LEN]; 00369 mic_rx |= ((uint32_t) _params.payload[size - LORAMAC_MFR_LEN + 1] << 8); 00370 mic_rx |= ((uint32_t) _params.payload[size - LORAMAC_MFR_LEN + 2] << 16); 00371 mic_rx |= ((uint32_t) _params.payload[size - LORAMAC_MFR_LEN + 3] << 24); 00372 00373 if (mic_rx == mic) { 00374 00375 if (0 != compute_skeys_for_join_frame(_params.keys.app_key, 00376 _params.payload + 1, 00377 _params.dev_nonce, 00378 _params.keys.nwk_skey, 00379 _params.keys.app_skey)) { 00380 mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL ; 00381 return; 00382 } 00383 00384 _params.net_id = (uint32_t) _params.payload[4]; 00385 _params.net_id |= ((uint32_t) _params.payload[5] << 8); 00386 _params.net_id |= ((uint32_t) _params.payload[6] << 16); 00387 00388 _params.dev_addr = (uint32_t) _params.payload[7]; 00389 _params.dev_addr |= ((uint32_t) _params.payload[8] << 8); 00390 _params.dev_addr |= ((uint32_t) _params.payload[9] << 16); 00391 _params.dev_addr |= ((uint32_t) _params.payload[10] << 24); 00392 00393 // DLSettings 00394 _params.sys_params.rx1_dr_offset = (_params.payload[11] >> 4) & 0x07; 00395 _params.sys_params.rx2_channel.datarate = _params.payload[11] & 0x0F; 00396 00397 // RxDelay 00398 _params.sys_params.recv_delay1 = (_params.payload[12] & 0x0F); 00399 00400 if (_params.sys_params.recv_delay1 == 0) { 00401 _params.sys_params.recv_delay1 = 1; 00402 } 00403 00404 _params.sys_params.recv_delay1 *= 1000; 00405 _params.sys_params.recv_delay2 = _params.sys_params.recv_delay1 + 1000; 00406 00407 // Apply CF list 00408 cflist.payload = &_params.payload[13]; 00409 // Size of the regular payload is 12. Plus 1 byte MHDR and 4 bytes MIC 00410 cflist.size = size - 17; 00411 00412 lora_phy->apply_cf_list(&cflist); 00413 00414 mlme.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_OK ; 00415 _params.is_nwk_joined = true; 00416 } else { 00417 mlme.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL ; 00418 } 00419 00420 break; 00421 00422 case FRAME_TYPE_DATA_CONFIRMED_DOWN : 00423 case FRAME_TYPE_DATA_UNCONFIRMED_DOWN : 00424 { 00425 uint8_t value = lora_phy->get_max_payload(mcps.get_indication().rx_datarate, _params.is_repeater_supported); 00426 00427 if (MAX(0, (int16_t) ((int16_t)size - (int16_t)LORA_MAC_FRMPAYLOAD_OVERHEAD )) > (int32_t)value) { 00428 mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_ERROR ; 00429 prepare_rx_done_abort(); 00430 return; 00431 } 00432 00433 address = payload[pkt_header_len++]; 00434 address |= ((uint32_t)payload[pkt_header_len++] << 8); 00435 address |= ((uint32_t)payload[pkt_header_len++] << 16); 00436 address |= ((uint32_t)payload[pkt_header_len++] << 24); 00437 00438 if (address != _params.dev_addr) { 00439 00440 cur_multicast_params = _params.multicast_channels; 00441 00442 while (cur_multicast_params != NULL) { 00443 00444 if (address == cur_multicast_params->address ) { 00445 multicast = 1; 00446 nwk_skey = cur_multicast_params->nwk_skey ; 00447 app_skey = cur_multicast_params->app_skey ; 00448 downlink_counter = cur_multicast_params->dl_frame_counter ; 00449 break; 00450 } 00451 00452 cur_multicast_params = cur_multicast_params->next ; 00453 } 00454 00455 if (multicast == 0) { 00456 // We are not the destination of this frame. 00457 mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL ; 00458 prepare_rx_done_abort(); 00459 return; 00460 } 00461 } else { 00462 multicast = 0; 00463 nwk_skey = _params.keys.nwk_skey; 00464 app_skey = _params.keys.app_skey; 00465 downlink_counter = _params.dl_frame_counter; 00466 } 00467 00468 fctrl.value = payload[pkt_header_len++]; 00469 00470 sequence_counter = (uint16_t )payload[pkt_header_len++]; 00471 sequence_counter |= (uint16_t)payload[pkt_header_len++] << 8; 00472 00473 app_payload_start_index = 8 + fctrl.bits.fopts_len ; 00474 00475 mic_rx |= (uint32_t)payload[size - LORAMAC_MFR_LEN]; 00476 mic_rx |= ((uint32_t)payload[size - LORAMAC_MFR_LEN + 1] << 8); 00477 mic_rx |= ((uint32_t)payload[size - LORAMAC_MFR_LEN + 2] << 16); 00478 mic_rx |= ((uint32_t)payload[size - LORAMAC_MFR_LEN + 3] << 24); 00479 00480 sequence_counter_prev = (uint16_t)downlink_counter; 00481 sequence_counter_diff = (sequence_counter - sequence_counter_prev); 00482 00483 if (sequence_counter_diff < (1 << 15)) { 00484 00485 downlink_counter += sequence_counter_diff; 00486 compute_mic(payload, size - LORAMAC_MFR_LEN, nwk_skey, 00487 address, DOWN_LINK, downlink_counter, &mic); 00488 if (mic_rx == mic) { 00489 is_mic_ok = true; 00490 } 00491 00492 } else { 00493 // check for sequence roll-over 00494 uint32_t downlink_counter_tmp = downlink_counter + 0x10000 + (int16_t)sequence_counter_diff; 00495 compute_mic(payload, size - LORAMAC_MFR_LEN, nwk_skey, 00496 address, DOWN_LINK, downlink_counter_tmp, &mic); 00497 00498 if (mic_rx == mic ) { 00499 is_mic_ok = true; 00500 downlink_counter = downlink_counter_tmp; 00501 } 00502 } 00503 00504 if (sequence_counter_diff >= lora_phy->get_maximum_frame_counter_gap()) { 00505 mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_TOO_MANY_FRAMES_LOSS ; 00506 mcps.get_indication().dl_frame_counter = downlink_counter; 00507 prepare_rx_done_abort( ); 00508 return; 00509 } 00510 00511 if (is_mic_ok == true) { 00512 mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_OK ; 00513 mcps.get_indication().multicast = multicast; 00514 mcps.get_indication().fpending_status = fctrl.bits.fpending ; 00515 mcps.get_indication().buffer = NULL; 00516 mcps.get_indication().buffer_size = 0; 00517 mcps.get_indication().dl_frame_counter = downlink_counter; 00518 00519 mcps.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_OK ; 00520 00521 _params.adr_ack_counter = 0; 00522 mac_commands.clear_repeat_buffer(); 00523 00524 // Update 32 bits downlink counter 00525 if (multicast == 1) { 00526 mcps.get_indication().type = MCPS_MULTICAST ; 00527 00528 if ((cur_multicast_params->dl_frame_counter == downlink_counter) && 00529 (cur_multicast_params->dl_frame_counter != 0)) { 00530 00531 mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED ; 00532 mcps.get_indication().dl_frame_counter = downlink_counter; 00533 prepare_rx_done_abort(); 00534 00535 return; 00536 } 00537 00538 cur_multicast_params->dl_frame_counter = downlink_counter; 00539 00540 } else { 00541 00542 if (mac_hdr.bits.mtype == FRAME_TYPE_DATA_CONFIRMED_DOWN ) { 00543 _params.is_srv_ack_requested = true; 00544 mcps.get_indication().type = MCPS_CONFIRMED ; 00545 00546 if ((_params.dl_frame_counter == downlink_counter ) && 00547 (_params.dl_frame_counter != 0)) { 00548 // Duplicated confirmed downlink. Skip indication. 00549 // In this case, the MAC layer shall accept the MAC commands 00550 // which are included in the downlink retransmission. 00551 // It should not provide the same frame to the application 00552 // layer again. 00553 skip_indication = true; 00554 } 00555 } else { 00556 _params.is_srv_ack_requested = false; 00557 mcps.get_indication().type = MCPS_UNCONFIRMED ; 00558 00559 if ((_params.dl_frame_counter == downlink_counter) && 00560 (_params.dl_frame_counter != 0)) { 00561 mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED ; 00562 mcps.get_indication().dl_frame_counter = downlink_counter; 00563 prepare_rx_done_abort(); 00564 return; 00565 } 00566 } 00567 _params.dl_frame_counter = downlink_counter; 00568 } 00569 00570 // This must be done before parsing the payload and the MAC commands. 00571 // We need to reset the MacCommandsBufferIndex here, since we need 00572 // to take retransmissions and repetitions into account. Error cases 00573 // will be handled in function OnMacStateCheckTimerEvent. 00574 if (mcps.get_confirmation().req_type == MCPS_CONFIRMED ) { 00575 if (fctrl.bits.ack == 1) { 00576 // Reset MacCommandsBufferIndex when we have received an ACK. 00577 mac_commands.clear_command_buffer(); 00578 } 00579 } else { 00580 // Reset the variable if we have received any valid frame. 00581 mac_commands.clear_command_buffer(); 00582 } 00583 00584 // Process payload and MAC commands 00585 if (((size - 4) - app_payload_start_index) > 0) { 00586 uint8_t port = payload[app_payload_start_index++]; 00587 frame_len = (size - 4) - app_payload_start_index; 00588 00589 mcps.get_indication().port = port; 00590 00591 if (port == 0) { 00592 // Only allow frames which do not have fOpts 00593 if (fctrl.bits.fopts_len == 0) { 00594 if (0 != decrypt_payload(payload + app_payload_start_index, 00595 frame_len, 00596 nwk_skey, 00597 address, 00598 DOWN_LINK, 00599 downlink_counter, 00600 _params.payload)) { 00601 mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL ; 00602 } 00603 00604 // Decode frame payload MAC commands 00605 if (LORAWAN_STATUS_OK != mac_commands.process_mac_commands( 00606 _params.payload, 0, frame_len, snr, 00607 mlme.get_confirmation(), _params.sys_params, *lora_phy)) { 00608 mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_ERROR ; 00609 } else if (mac_commands.has_sticky_mac_cmd()) { 00610 set_mlme_schedule_ul_indication(); 00611 mac_commands.clear_sticky_mac_cmd(); 00612 } 00613 } else { 00614 skip_indication = true; 00615 } 00616 } else { 00617 if (fctrl.bits.fopts_len > 0) { 00618 // Decode Options field MAC commands. Omit the fPort. 00619 if (LORAWAN_STATUS_OK != mac_commands.process_mac_commands( 00620 payload, 8, app_payload_start_index - 1, snr, 00621 mlme.get_confirmation(), _params.sys_params, *lora_phy )) { 00622 mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_ERROR ; 00623 } else if (mac_commands.has_sticky_mac_cmd()) { 00624 set_mlme_schedule_ul_indication(); 00625 mac_commands.clear_sticky_mac_cmd(); 00626 } 00627 } 00628 00629 if (0 != decrypt_payload(payload + app_payload_start_index, 00630 frame_len, 00631 app_skey, 00632 address, 00633 DOWN_LINK, 00634 downlink_counter, 00635 _params.payload)) { 00636 mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL ; 00637 } 00638 00639 if (skip_indication == false) { 00640 mcps.get_indication().buffer = _params.payload; 00641 mcps.get_indication().buffer_size = frame_len; 00642 mcps.get_indication().is_data_recvd = true; 00643 } 00644 } 00645 } else { 00646 if (fctrl.bits.fopts_len > 0) { 00647 // Decode Options field MAC commands 00648 if (LORAWAN_STATUS_OK != mac_commands.process_mac_commands( 00649 payload, 8, app_payload_start_index, snr, 00650 mlme.get_confirmation(), 00651 _params.sys_params, *lora_phy)) { 00652 mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_ERROR ; 00653 } else if (mac_commands.has_sticky_mac_cmd()) { 00654 set_mlme_schedule_ul_indication(); 00655 mac_commands.clear_sticky_mac_cmd(); 00656 } 00657 } 00658 } 00659 00660 if (skip_indication == false) { 00661 // Check if the frame is an acknowledgement 00662 if (fctrl.bits.ack == 1) { 00663 mcps.get_confirmation().ack_received = true; 00664 mcps.get_indication().is_ack_recvd = true; 00665 00666 // Stop the AckTimeout timer as no more retransmissions 00667 // are needed. 00668 _lora_time.stop(_params.timers.ack_timeout_timer); 00669 } else { 00670 mcps.get_confirmation().ack_received = false; 00671 00672 if (_params.ack_timeout_retry_counter > _params.max_ack_timeout_retries) { 00673 // Stop the AckTimeout timer as no more retransmissions 00674 // are needed. 00675 _lora_time.stop( _params.timers.ack_timeout_timer ); 00676 } 00677 } 00678 } 00679 // Provide always an indication, skip the callback to the user application, 00680 // in case of a confirmed downlink retransmission. 00681 _params.flags.bits.mcps_ind = 1; 00682 _params.flags.bits.mcps_ind_skip = skip_indication; 00683 } else { 00684 mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_MIC_FAIL ; 00685 00686 prepare_rx_done_abort( ); 00687 return; 00688 } 00689 } 00690 00691 break; 00692 00693 case FRAME_TYPE_PROPRIETARY : 00694 { 00695 memcpy(_params.payload, &payload[pkt_header_len], size); 00696 00697 mcps.get_indication().type = MCPS_PROPRIETARY ; 00698 mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_OK ; 00699 mcps.get_indication().buffer = _params.payload; 00700 mcps.get_indication().buffer_size = size - pkt_header_len; 00701 00702 _params.flags.bits.mcps_ind = 1; 00703 break; 00704 } 00705 default: 00706 mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_ERROR ; 00707 prepare_rx_done_abort(); 00708 break; 00709 } 00710 _params.flags.bits.mac_done = 1; 00711 00712 _lora_time.start(_params.timers.mac_state_check_timer, 1); 00713 } 00714 00715 void LoRaMac::on_radio_tx_timeout( void ) 00716 { 00717 if (_params.dev_class != CLASS_C ) { 00718 lora_phy->put_radio_to_sleep(); 00719 } else { 00720 open_continuous_rx2_window(); 00721 } 00722 00723 mcps.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ; 00724 00725 mlme.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ; 00726 00727 _params.flags.bits.mac_done = 1; 00728 } 00729 00730 void LoRaMac::on_radio_rx_error( void ) 00731 { 00732 if (_params.dev_class != CLASS_C ) { 00733 lora_phy->put_radio_to_sleep(); 00734 } else { 00735 open_continuous_rx2_window(); 00736 } 00737 00738 if (_params.rx_slot == RX_SLOT_WIN_1 ) { 00739 if (_params.is_node_ack_requested == true) { 00740 mcps.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_RX1_ERROR ; 00741 } 00742 00743 mlme.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_RX1_ERROR ; 00744 00745 if (_lora_time.get_elapsed_time(_params.timers.aggregated_last_tx_time) >= _params.rx_window2_delay) { 00746 _lora_time.stop(_params.timers.rx_window2_timer); 00747 _params.flags.bits.mac_done = 1; 00748 } 00749 00750 } else { 00751 00752 if (_params.is_node_ack_requested == true) { 00753 mcps.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_RX2_ERROR ; 00754 } 00755 00756 mlme.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_RX2_ERROR ; 00757 00758 _params.flags.bits.mac_done = 1; 00759 } 00760 } 00761 00762 void LoRaMac::on_radio_rx_timeout(void) 00763 { 00764 if (_params.dev_class != CLASS_C ) { 00765 lora_phy->put_radio_to_sleep(); 00766 } else { 00767 open_continuous_rx2_window(); 00768 } 00769 00770 if (_params.rx_slot == RX_SLOT_WIN_1 ) { 00771 if (_params.is_node_ack_requested == true) { 00772 mcps.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT ; 00773 } 00774 mlme.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT ; 00775 00776 if (_lora_time.get_elapsed_time(_params.timers.aggregated_last_tx_time ) >= _params.rx_window2_delay) { 00777 _lora_time.stop(_params.timers.rx_window2_timer); 00778 _params.flags.bits.mac_done = 1; 00779 } 00780 00781 } else { 00782 00783 if (_params.is_node_ack_requested == true) { 00784 mcps.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT ; 00785 } 00786 00787 mlme.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT ; 00788 00789 if (_params.dev_class != CLASS_C ) { 00790 _params.flags.bits.mac_done = 1; 00791 } 00792 } 00793 } 00794 00795 /*************************************************************************** 00796 * Timer event callbacks - deliberated locally * 00797 **************************************************************************/ 00798 void LoRaMac::on_mac_state_check_timer_event(void) 00799 { 00800 bool tx_timeout = false; 00801 00802 _lora_time.stop(_params.timers.mac_state_check_timer); 00803 00804 if (_params.flags.bits.mac_done == 1) { 00805 00806 if ((_params.mac_state & LORAMAC_RX_ABORT) == LORAMAC_RX_ABORT) { 00807 _params.mac_state &= ~LORAMAC_RX_ABORT; 00808 _params.mac_state &= ~LORAMAC_TX_RUNNING; 00809 } 00810 00811 if ((_params.flags.bits.mlme_req == 1) || (_params.flags.bits.mcps_req == 1)) { 00812 00813 if ((mcps.get_confirmation().status == LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ) || 00814 ( mlme.get_confirmation().status == LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT )) { 00815 // Stop transmit cycle due to tx timeout. 00816 _params.mac_state &= ~LORAMAC_TX_RUNNING; 00817 mac_commands.clear_command_buffer(); 00818 mcps.get_confirmation().nb_retries = _params.ack_timeout_retry_counter; 00819 mcps.get_confirmation().ack_received = false; 00820 mcps.get_confirmation().tx_toa = 0; 00821 tx_timeout = true; 00822 } 00823 } 00824 00825 if ((_params.is_node_ack_requested == false) && (tx_timeout == false)) { 00826 if ((_params.flags.bits.mlme_req == 1) || ((_params.flags.bits.mcps_req == 1))) { 00827 if ((_params.flags.bits.mlme_req == 1) && (mlme.get_confirmation().req_type == MLME_JOIN )) { 00828 // Procedure for the join request 00829 mlme.get_confirmation().nb_retries = _params.join_request_trial_counter; 00830 00831 if (mlme.get_confirmation().status == LORAMAC_EVENT_INFO_STATUS_OK ) { 00832 // Node joined successfully 00833 _params.ul_frame_counter = 0; 00834 _params.ul_nb_rep_counter = 0; 00835 _params.mac_state &= ~LORAMAC_TX_RUNNING; 00836 } else { 00837 if (_params.join_request_trial_counter >= _params.max_join_request_trials) { 00838 _params.mac_state &= ~LORAMAC_TX_RUNNING; 00839 } else { 00840 _params.flags.bits.mac_done = 0; 00841 // Sends the same frame again 00842 handle_delayed_tx_timer_event(); 00843 } 00844 } 00845 } else { 00846 // Procedure for all other frames 00847 if ((_params.ul_nb_rep_counter >= _params.sys_params.retry_num) || 00848 (_params.flags.bits.mcps_ind == 1)) { 00849 if (_params.flags.bits.mcps_ind == 0) { 00850 // Maximum repetitions without downlink. Reset MacCommandsBufferIndex. Increase ADR Ack counter. 00851 // Only process the case when the MAC did not receive a downlink. 00852 mac_commands.clear_command_buffer(); 00853 _params.adr_ack_counter++; 00854 } 00855 00856 _params.ul_nb_rep_counter = 0; 00857 00858 if (_params.is_ul_frame_counter_fixed == false) { 00859 _params.ul_frame_counter++; 00860 } 00861 00862 _params.mac_state &= ~LORAMAC_TX_RUNNING; 00863 } else { 00864 _params.flags.bits.mac_done = 0; 00865 // Sends the same frame again 00866 handle_delayed_tx_timer_event(); 00867 } 00868 } 00869 } 00870 } 00871 00872 if (_params.flags.bits.mcps_ind == 1) { 00873 // Procedure if we received a frame 00874 if ((mcps.get_confirmation().ack_received == true) || 00875 (_params.ack_timeout_retry_counter > _params.max_ack_timeout_retries)) { 00876 _params.is_ack_retry_timeout_expired = false; 00877 _params.is_node_ack_requested = false; 00878 if (_params.is_ul_frame_counter_fixed == false) { 00879 _params.ul_frame_counter++; 00880 } 00881 mcps.get_confirmation().nb_retries = _params.ack_timeout_retry_counter; 00882 00883 _params.mac_state &= ~LORAMAC_TX_RUNNING; 00884 } 00885 } 00886 00887 if ((_params.is_ack_retry_timeout_expired == true) && 00888 ((_params.mac_state & LORAMAC_TX_DELAYED) == 0)) { 00889 00890 // Retransmissions procedure for confirmed uplinks 00891 _params.is_ack_retry_timeout_expired = false; 00892 if ((_params.ack_timeout_retry_counter < _params.max_ack_timeout_retries) && 00893 (_params.ack_timeout_retry_counter <= MAX_ACK_RETRIES)) { 00894 00895 _params.ack_timeout_retry_counter++; 00896 00897 if ((_params.ack_timeout_retry_counter % 2) == 1) { 00898 _params.sys_params.channel_data_rate = lora_phy->get_next_lower_tx_datarate( 00899 _params.sys_params.channel_data_rate); 00900 } 00901 00902 // Try to send the frame again 00903 if (schedule_tx() == LORAWAN_STATUS_OK) { 00904 _params.flags.bits.mac_done = 0; 00905 } else { 00906 // The DR is not applicable for the payload size 00907 mcps.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_TX_DR_PAYLOAD_SIZE_ERROR ; 00908 00909 mac_commands.clear_command_buffer(); 00910 _params.mac_state &= ~LORAMAC_TX_RUNNING; 00911 _params.is_node_ack_requested = false; 00912 mcps.get_confirmation().ack_received = false; 00913 mcps.get_confirmation().nb_retries = _params.ack_timeout_retry_counter; 00914 mcps.get_confirmation().data_rate = _params.sys_params.channel_data_rate; 00915 00916 if (_params.is_ul_frame_counter_fixed == false) { 00917 _params.ul_frame_counter++; 00918 } 00919 } 00920 } else { 00921 lora_phy->restore_default_channels(); 00922 00923 _params.mac_state &= ~LORAMAC_TX_RUNNING; 00924 00925 mac_commands.clear_command_buffer(); 00926 _params.is_node_ack_requested = false; 00927 mcps.get_confirmation().ack_received = false; 00928 mcps.get_confirmation().nb_retries = _params.ack_timeout_retry_counter; 00929 00930 if (_params.is_ul_frame_counter_fixed == false) { 00931 _params.ul_frame_counter++; 00932 } 00933 } 00934 } 00935 } 00936 00937 // Handle reception for Class B and Class C 00938 if ((_params.mac_state & LORAMAC_RX) == LORAMAC_RX) { 00939 _params.mac_state &= ~LORAMAC_RX; 00940 } 00941 00942 if (_params.mac_state == LORAMAC_IDLE) { 00943 if (_params.flags.bits.mcps_req == 1) { 00944 _params.flags.bits.mcps_req = 0; 00945 mac_primitives->mcps_confirm(&mcps.get_confirmation()); 00946 } 00947 00948 if (_params.flags.bits.mlme_req == 1) { 00949 _params.flags.bits.mlme_req = 0; 00950 mac_primitives->mlme_confirm(&mlme.get_confirmation()); 00951 } 00952 00953 // Verify if sticky MAC commands are pending or not 00954 if (mac_commands.is_sticky_mac_command_pending() == true) { 00955 // Setup MLME indication 00956 set_mlme_schedule_ul_indication(); 00957 } 00958 00959 // Procedure done. Reset variables. 00960 _params.flags.bits.mac_done = 0; 00961 } else { 00962 // Operation not finished restart timer 00963 _lora_time.start(_params.timers.mac_state_check_timer, MAC_STATE_CHECK_TIMEOUT); 00964 } 00965 00966 // Handle MCPS indication 00967 if (_params.flags.bits.mcps_ind == 1) { 00968 _params.flags.bits.mcps_ind = 0; 00969 00970 if (_params.dev_class== CLASS_C ) { 00971 // Activate RX2 window for Class C 00972 open_continuous_rx2_window(); 00973 } 00974 00975 if (_params.flags.bits.mcps_ind_skip == 0) { 00976 mac_primitives->mcps_indication(&mcps.get_indication()); 00977 } 00978 00979 _params.flags.bits.mcps_ind_skip = 0; 00980 } 00981 00982 // Handle MLME indication 00983 if (_params.flags.bits.mlme_ind == 1) { 00984 _params.flags.bits.mlme_ind = 0; 00985 mac_primitives->mlme_indication(&mlme.get_indication()); 00986 } 00987 } 00988 00989 void LoRaMac::on_tx_delayed_timer_event(void) 00990 { 00991 loramac_mhdr_t mac_hdr; 00992 loramac_frame_ctrl_t fctrl; 00993 00994 lorawan_status_t status = LORAWAN_STATUS_OK; 00995 00996 _lora_time.stop(_params.timers.tx_delayed_timer); 00997 _params.mac_state &= ~LORAMAC_TX_DELAYED; 00998 00999 if ((_params.flags.bits.mlme_req == 1 ) && 01000 (mlme.get_confirmation().req_type == MLME_JOIN )) { 01001 01002 reset_mac_parameters(); 01003 01004 _params.sys_params.channel_data_rate = lora_phy->get_alternate_DR(_params.join_request_trial_counter + 1); 01005 01006 mac_hdr.value = 0; 01007 mac_hdr.bits.mtype = FRAME_TYPE_JOIN_REQ ; 01008 01009 fctrl.value = 0; 01010 fctrl.bits.adr = _params.sys_params.adr_on; 01011 01012 /* In case of join request retransmissions, the stack must prepare 01013 * the frame again, because the network server keeps track of the random 01014 * LoRaMacDevNonce values to prevent reply attacks. */ 01015 status = prepare_frame(&mac_hdr, &fctrl, 0, NULL, 0); 01016 } 01017 01018 if (status == LORAWAN_STATUS_OK) { 01019 schedule_tx(); 01020 } else { 01021 tr_error("Delayed TX: PrepareFrame returned error %d", status); 01022 } 01023 } 01024 01025 void LoRaMac::on_rx_window1_timer_event(void) 01026 { 01027 _lora_time.stop(_params.timers.rx_window1_timer); 01028 _params.rx_slot = RX_SLOT_WIN_1 ; 01029 01030 _params.rx_window1_config.channel = _params.channel; 01031 _params.rx_window1_config.dr_offset = _params.sys_params.rx1_dr_offset; 01032 _params.rx_window1_config.dl_dwell_time = _params.sys_params.downlink_dwell_time; 01033 _params.rx_window1_config.is_repeater_supported = _params.is_repeater_supported; 01034 _params.rx_window1_config.is_rx_continuous = false; 01035 _params.rx_window1_config.rx_slot = _params.rx_slot; 01036 01037 if (_params.dev_class == CLASS_C ) { 01038 lora_phy->put_radio_to_standby(); 01039 } 01040 01041 lora_phy->rx_config(&_params.rx_window1_config, 01042 (int8_t*) &mcps.get_indication().rx_datarate); 01043 01044 rx_window_setup(_params.rx_window1_config.is_rx_continuous, 01045 _params.sys_params.max_rx_win_time); 01046 } 01047 01048 void LoRaMac::on_rx_window2_timer_event(void) 01049 { 01050 _lora_time.stop(_params.timers.rx_window2_timer); 01051 01052 _params.rx_window2_config.channel = _params.channel; 01053 _params.rx_window2_config.frequency = _params.sys_params.rx2_channel.frequency; 01054 _params.rx_window2_config.dl_dwell_time = _params.sys_params.downlink_dwell_time; 01055 _params.rx_window2_config.is_repeater_supported = _params.is_repeater_supported; 01056 _params.rx_window2_config.rx_slot = RX_SLOT_WIN_2 ; 01057 01058 if (_params.dev_class != CLASS_C ) { 01059 _params.rx_window2_config.is_rx_continuous = false; 01060 } else { 01061 // Setup continuous listening for class c 01062 _params.rx_window2_config.is_rx_continuous = true; 01063 } 01064 01065 if (lora_phy->rx_config(&_params.rx_window2_config, 01066 (int8_t*) &mcps.get_indication().rx_datarate) == true) { 01067 01068 rx_window_setup(_params.rx_window2_config.is_rx_continuous, 01069 _params.sys_params.max_rx_win_time); 01070 01071 _params.rx_slot = RX_SLOT_WIN_2 ; 01072 } 01073 } 01074 01075 void LoRaMac::on_ack_timeout_timer_event(void) 01076 { 01077 _lora_time.stop(_params.timers.ack_timeout_timer); 01078 01079 if (_params.is_node_ack_requested == true) { 01080 _params.is_ack_retry_timeout_expired = true; 01081 _params.mac_state &= ~LORAMAC_ACK_REQ; 01082 } 01083 if (_params.dev_class == CLASS_C ) { 01084 _params.flags.bits.mac_done = 1; 01085 } 01086 } 01087 01088 void LoRaMac::rx_window_setup(bool rx_continuous, uint32_t max_rx_window_time) 01089 { 01090 lora_phy->setup_rx_window(rx_continuous, max_rx_window_time); 01091 } 01092 01093 bool LoRaMac::validate_payload_length(uint8_t length, int8_t datarate, 01094 uint8_t fopts_len) 01095 { 01096 uint16_t max_value = 0; 01097 uint16_t payloadSize = 0; 01098 01099 max_value = lora_phy->get_max_payload(datarate, _params.is_repeater_supported); 01100 01101 // Calculate the resulting payload size 01102 payloadSize = (length + fopts_len); 01103 01104 // Validation of the application payload size 01105 if ((payloadSize <= max_value) && 01106 (payloadSize <= LORAMAC_PHY_MAXPAYLOAD)) { 01107 return true; 01108 } 01109 return false; 01110 } 01111 01112 void LoRaMac::set_mlme_schedule_ul_indication(void) 01113 { 01114 mlme.get_indication().indication_type = MLME_SCHEDULE_UPLINK ; 01115 _params.flags.bits.mlme_ind = 1; 01116 } 01117 01118 // This is not actual transmission. It just schedules a message in response 01119 // to MCPS request 01120 lorawan_status_t LoRaMac::send(loramac_mhdr_t *machdr, uint8_t fport, 01121 void *fbuffer, uint16_t fbuffer_size) 01122 { 01123 loramac_frame_ctrl_t fctrl; 01124 01125 fctrl.value = 0; 01126 fctrl.bits.fopts_len = 0; 01127 fctrl.bits.fpending = 0; 01128 fctrl.bits.ack = false; 01129 fctrl.bits.adr_ack_req = false; 01130 fctrl.bits.adr = _params.sys_params.adr_on; 01131 01132 // Prepare the frame 01133 lorawan_status_t status = prepare_frame(machdr, &fctrl, fport, fbuffer, 01134 fbuffer_size); 01135 01136 // Validate status 01137 if (status != LORAWAN_STATUS_OK) { 01138 return status; 01139 } 01140 01141 // Reset confirm parameters 01142 mcps.get_confirmation().nb_retries = 0; 01143 mcps.get_confirmation().ack_received = false; 01144 mcps.get_confirmation().ul_frame_counter = _params.ul_frame_counter; 01145 01146 status = schedule_tx(); 01147 01148 return status; 01149 } 01150 01151 lorawan_status_t LoRaMac::schedule_tx(void) 01152 { 01153 lorawan_time_t dutyCycleTimeOff = 0; 01154 channel_selection_params_t nextChan; 01155 01156 // Check if the device is off 01157 if (_params.sys_params.max_duty_cycle == 255) { 01158 return LORAWAN_STATUS_DEVICE_OFF; 01159 } 01160 01161 if (_params.sys_params.max_duty_cycle == 0) { 01162 _params.timers.aggregated_timeoff = 0; 01163 } 01164 01165 // Update Backoff 01166 calculate_backOff(_params.last_channel_idx); 01167 01168 nextChan.aggregate_timeoff = _params.timers.aggregated_timeoff; 01169 nextChan.current_datarate = _params.sys_params.channel_data_rate; 01170 _params.is_dutycycle_on = MBED_CONF_LORA_DUTY_CYCLE_ON; 01171 nextChan.dc_enabled = _params.is_dutycycle_on; 01172 nextChan.joined = _params.is_nwk_joined; 01173 nextChan.last_aggregate_tx_time = _params.timers.aggregated_last_tx_time; 01174 01175 // Select channel 01176 while (lora_phy->set_next_channel(&nextChan, &_params.channel, 01177 &dutyCycleTimeOff, 01178 &_params.timers.aggregated_timeoff) == false) { 01179 _params.sys_params.channel_data_rate = lora_phy->get_default_tx_datarate(); 01180 // Update datarate in the function parameters 01181 nextChan.current_datarate = _params.sys_params.channel_data_rate; 01182 } 01183 01184 tr_debug("Next Channel Idx=%d, DR=%d", _params.channel, nextChan.current_datarate); 01185 01186 // Compute Rx1 windows parameters 01187 uint8_t dr_offset = lora_phy->apply_DR_offset(_params.sys_params.channel_data_rate, 01188 _params.sys_params.rx1_dr_offset); 01189 01190 lora_phy->compute_rx_win_params(dr_offset, _params.sys_params.min_rx_symb, 01191 _params.sys_params.max_sys_rx_error, 01192 &_params.rx_window1_config); 01193 01194 // Compute Rx2 windows parameters 01195 lora_phy->compute_rx_win_params(_params.sys_params.rx2_channel.datarate, 01196 _params.sys_params.min_rx_symb, 01197 _params.sys_params.max_sys_rx_error, 01198 &_params.rx_window2_config); 01199 01200 if (_params.is_nwk_joined == false) { 01201 _params.rx_window1_delay = _params.sys_params.join_accept_delay1 01202 + _params.rx_window1_config.window_offset; 01203 _params.rx_window2_delay = _params.sys_params.join_accept_delay2 01204 + _params.rx_window2_config.window_offset; 01205 } else { 01206 if (validate_payload_length(_params.payload_length, 01207 _params.sys_params.channel_data_rate, 01208 mac_commands.get_mac_cmd_length()) == false) { 01209 return LORAWAN_STATUS_LENGTH_ERROR; 01210 } 01211 _params.rx_window1_delay = _params.sys_params.recv_delay1 01212 + _params.rx_window1_config.window_offset; 01213 _params.rx_window2_delay = _params.sys_params.recv_delay2 01214 + _params.rx_window2_config.window_offset; 01215 } 01216 01217 // Schedule transmission of frame 01218 if (dutyCycleTimeOff == 0) { 01219 // Try to send now 01220 return send_frame_on_channel(_params.channel); 01221 } else { 01222 // Send later - prepare timer 01223 _params.mac_state |= LORAMAC_TX_DELAYED; 01224 tr_debug("Next Transmission in %lu ms", dutyCycleTimeOff); 01225 01226 _lora_time.start(_params.timers.tx_delayed_timer, dutyCycleTimeOff); 01227 01228 return LORAWAN_STATUS_OK; 01229 } 01230 } 01231 01232 void LoRaMac::calculate_backOff(uint8_t channel) 01233 { 01234 backoff_params_t backoff_params; 01235 01236 backoff_params.joined = _params.is_nwk_joined; 01237 _params.is_dutycycle_on = MBED_CONF_LORA_DUTY_CYCLE_ON; 01238 backoff_params.dc_enabled = _params.is_dutycycle_on; 01239 backoff_params.channel = channel; 01240 backoff_params.elapsed_time = _lora_time.get_elapsed_time(_params.timers.mac_init_time); 01241 backoff_params.tx_toa = _params.timers.tx_toa; 01242 backoff_params.last_tx_was_join_req = _params.is_last_tx_join_request; 01243 01244 // Update regional back-off 01245 lora_phy->calculate_backoff(&backoff_params); 01246 01247 // Update aggregated time-off 01248 _params.timers.aggregated_timeoff = _params.timers.aggregated_timeoff 01249 + (_params.timers.tx_toa * _params.sys_params.aggregated_duty_cycle 01250 - _params.timers.tx_toa); 01251 } 01252 01253 void LoRaMac::reset_mac_parameters(void) 01254 { 01255 _params.is_nwk_joined = false; 01256 01257 // Counters 01258 _params.ul_frame_counter = 0; 01259 _params.dl_frame_counter = 0; 01260 _params.adr_ack_counter = 0; 01261 01262 _params.ul_nb_rep_counter = 0; 01263 01264 _params.max_ack_timeout_retries = 1; 01265 _params.ack_timeout_retry_counter = 1; 01266 _params.is_ack_retry_timeout_expired = false; 01267 01268 _params.sys_params.max_duty_cycle = 0; 01269 _params.sys_params.aggregated_duty_cycle = 1; 01270 01271 mac_commands.clear_command_buffer(); 01272 mac_commands.clear_repeat_buffer(); 01273 mac_commands.clear_mac_commands_in_next_tx(); 01274 01275 _params.is_rx_window_enabled = true; 01276 01277 lora_phy->reset_to_default_values(&_params, false); 01278 01279 _params.is_node_ack_requested = false; 01280 _params.is_srv_ack_requested = false; 01281 01282 // Reset Multicast downlink counters 01283 multicast_params_t *cur = _params.multicast_channels; 01284 while (cur != NULL) { 01285 cur->dl_frame_counter = 0; 01286 cur = cur->next ; 01287 } 01288 01289 // Initialize channel index. 01290 _params.channel = 0; 01291 _params.last_channel_idx = _params.channel; 01292 } 01293 01294 bool LoRaMac::is_fPort_allowed (uint8_t fPort) 01295 { 01296 if ((fPort == 0) || (fPort > 224)) { 01297 return false; 01298 } 01299 return true; 01300 } 01301 01302 void LoRaMac::open_continuous_rx2_window (void) 01303 { 01304 handle_rx2_timer_event(); 01305 _params.rx_slot = RX_SLOT_WIN_CLASS_C ; 01306 } 01307 01308 static void memcpy_convert_endianess(uint8_t *dst, const uint8_t *src, 01309 uint16_t size) 01310 { 01311 dst = dst + (size - 1); 01312 while (size--) { 01313 *dst-- = *src++; 01314 } 01315 } 01316 01317 lorawan_status_t LoRaMac::prepare_frame(loramac_mhdr_t *machdr, 01318 loramac_frame_ctrl_t *fctrl, 01319 uint8_t fport, void *fbuffer, 01320 uint16_t fbuffer_size) 01321 { 01322 uint16_t i; 01323 uint8_t pkt_header_len = 0; 01324 uint32_t mic = 0; 01325 const void* payload = fbuffer; 01326 uint8_t frame_port = fport; 01327 lorawan_status_t status = LORAWAN_STATUS_OK; 01328 01329 _params.buffer_pkt_len = 0; 01330 01331 _params.is_node_ack_requested = false; 01332 01333 if (fbuffer == NULL) { 01334 fbuffer_size = 0; 01335 } 01336 01337 _params.payload_length = fbuffer_size; 01338 01339 _params.buffer[pkt_header_len++] = machdr->value ; 01340 01341 switch (machdr->bits.mtype ) { 01342 01343 case FRAME_TYPE_JOIN_REQ : 01344 01345 _params.buffer_pkt_len = pkt_header_len; 01346 memcpy_convert_endianess(_params.buffer + _params.buffer_pkt_len, 01347 _params.keys.app_eui, 8); 01348 _params.buffer_pkt_len += 8; 01349 memcpy_convert_endianess(_params.buffer + _params.buffer_pkt_len, 01350 _params.keys.dev_eui, 8); 01351 _params.buffer_pkt_len += 8; 01352 01353 _params.dev_nonce = lora_phy->get_radio_rng(); 01354 01355 _params.buffer[_params.buffer_pkt_len++] = _params.dev_nonce & 0xFF; 01356 _params.buffer[_params.buffer_pkt_len++] = (_params.dev_nonce >> 8) & 0xFF; 01357 01358 if (0 != compute_join_frame_mic(_params.buffer, 01359 _params.buffer_pkt_len & 0xFF, 01360 _params.keys.app_key, &mic)) { 01361 return LORAWAN_STATUS_CRYPTO_FAIL; 01362 } 01363 01364 _params.buffer[_params.buffer_pkt_len++] = mic & 0xFF; 01365 _params.buffer[_params.buffer_pkt_len++] = (mic >> 8) & 0xFF; 01366 _params.buffer[_params.buffer_pkt_len++] = (mic >> 16) & 0xFF; 01367 _params.buffer[_params.buffer_pkt_len++] = (mic >> 24) & 0xFF; 01368 01369 break; 01370 case FRAME_TYPE_DATA_CONFIRMED_UP : 01371 _params.is_node_ack_requested = true; 01372 //Intentional fallthrough 01373 case FRAME_TYPE_DATA_UNCONFIRMED_UP : { 01374 if (_params.is_nwk_joined == false) { 01375 // No network has been joined yet 01376 return LORAWAN_STATUS_NO_NETWORK_JOINED; 01377 } 01378 01379 if (_params.sys_params.adr_on) { 01380 if (lora_phy->get_next_ADR(true, 01381 _params.sys_params.channel_data_rate, 01382 _params.sys_params.channel_tx_power, 01383 _params.adr_ack_counter)) { 01384 fctrl->bits.adr_ack_req = 1; 01385 } 01386 } 01387 01388 if (_params.is_srv_ack_requested == true) { 01389 _params.is_srv_ack_requested = false; 01390 fctrl->bits.ack = 1; 01391 } 01392 01393 _params.buffer[pkt_header_len++] = (_params.dev_addr) & 0xFF; 01394 _params.buffer[pkt_header_len++] = (_params.dev_addr >> 8) & 0xFF; 01395 _params.buffer[pkt_header_len++] = (_params.dev_addr >> 16) & 0xFF; 01396 _params.buffer[pkt_header_len++] = (_params.dev_addr >> 24) & 0xFF; 01397 01398 _params.buffer[pkt_header_len++] = fctrl->value ; 01399 01400 _params.buffer[pkt_header_len++] = _params.ul_frame_counter & 0xFF; 01401 _params.buffer[pkt_header_len++] = (_params.ul_frame_counter >> 8) 01402 & 0xFF; 01403 01404 // Copy the MAC commands which must be re-send into the MAC command buffer 01405 mac_commands.copy_repeat_commands_to_buffer(); 01406 01407 const uint8_t mac_commands_len = mac_commands.get_mac_cmd_length(); 01408 01409 if ((payload != NULL) && (_params.payload_length > 0)) { 01410 if (mac_commands.is_mac_command_in_next_tx() == true) { 01411 if (mac_commands_len <= LORA_MAC_COMMAND_MAX_FOPTS_LENGTH) { 01412 fctrl->bits.fopts_len += mac_commands_len; 01413 01414 // Update FCtrl field with new value of OptionsLength 01415 _params.buffer[0x05] = fctrl->value ; 01416 01417 const uint8_t *buffer = 01418 mac_commands.get_mac_commands_buffer(); 01419 for (i = 0; i < mac_commands_len; i++) { 01420 _params.buffer[pkt_header_len++] = buffer[i]; 01421 } 01422 } else { 01423 _params.payload_length = mac_commands_len; 01424 payload = mac_commands.get_mac_commands_buffer(); 01425 frame_port = 0; 01426 } 01427 } 01428 } else { 01429 if ((mac_commands_len > 0) 01430 && (mac_commands.is_mac_command_in_next_tx() == true)) { 01431 _params.payload_length = mac_commands_len; 01432 payload = mac_commands.get_mac_commands_buffer(); 01433 frame_port = 0; 01434 } 01435 } 01436 01437 // Store MAC commands which must be re-send in case the device does not receive a downlink anymore 01438 mac_commands.parse_mac_commands_to_repeat(); 01439 01440 if ((payload != NULL) && (_params.payload_length > 0)) { 01441 _params.buffer[pkt_header_len++] = frame_port; 01442 01443 if (frame_port == 0) { 01444 // Reset buffer index as the mac commands are being sent on port 0 01445 mac_commands.clear_command_buffer(); 01446 if (0 != encrypt_payload((uint8_t*) payload, _params.payload_length, 01447 _params.keys.nwk_skey, _params.dev_addr, 01448 UP_LINK, 01449 _params.ul_frame_counter, 01450 &_params.buffer[pkt_header_len])) { 01451 status = LORAWAN_STATUS_CRYPTO_FAIL; 01452 } 01453 } else { 01454 if (0 != encrypt_payload((uint8_t*) payload, _params.payload_length, 01455 _params.keys.app_skey, _params.dev_addr, 01456 UP_LINK, 01457 _params.ul_frame_counter, 01458 &_params.buffer[pkt_header_len])) { 01459 status = LORAWAN_STATUS_CRYPTO_FAIL; 01460 } 01461 } 01462 } 01463 01464 _params.buffer_pkt_len = pkt_header_len + _params.payload_length; 01465 01466 if (0 != compute_mic(_params.buffer, _params.buffer_pkt_len, 01467 _params.keys.nwk_skey, 01468 _params.dev_addr, 01469 UP_LINK, 01470 _params.ul_frame_counter, &mic)) { 01471 status = LORAWAN_STATUS_CRYPTO_FAIL; 01472 } 01473 01474 _params.buffer[_params.buffer_pkt_len + 0] = mic & 0xFF; 01475 _params.buffer[_params.buffer_pkt_len + 1] = (mic >> 8) & 0xFF; 01476 _params.buffer[_params.buffer_pkt_len + 2] = (mic >> 16) & 0xFF; 01477 _params.buffer[_params.buffer_pkt_len + 3] = (mic >> 24) & 0xFF; 01478 01479 _params.buffer_pkt_len += LORAMAC_MFR_LEN; 01480 } 01481 break; 01482 case FRAME_TYPE_PROPRIETARY : 01483 if ((fbuffer != NULL) && (_params.payload_length > 0)) { 01484 memcpy(_params.buffer + pkt_header_len, (uint8_t*) fbuffer, 01485 _params.payload_length); 01486 _params.buffer_pkt_len = pkt_header_len + _params.payload_length; 01487 } 01488 break; 01489 default: 01490 status = LORAWAN_STATUS_SERVICE_UNKNOWN; 01491 } 01492 01493 return status; 01494 } 01495 01496 lorawan_status_t LoRaMac::send_frame_on_channel(uint8_t channel) 01497 { 01498 tx_config_params_t tx_config; 01499 int8_t tx_power = 0; 01500 01501 tx_config.channel = channel; 01502 tx_config.datarate = _params.sys_params.channel_data_rate; 01503 tx_config.tx_power = _params.sys_params.channel_tx_power; 01504 tx_config.max_eirp = _params.sys_params.max_eirp; 01505 tx_config.antenna_gain = _params.sys_params.antenna_gain; 01506 tx_config.pkt_len = _params.buffer_pkt_len; 01507 01508 lora_phy->tx_config(&tx_config, &tx_power, &_params.timers.tx_toa); 01509 01510 mlme.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_ERROR ; 01511 01512 mcps.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_ERROR ; 01513 mcps.get_confirmation().data_rate = _params.sys_params.channel_data_rate; 01514 mcps.get_confirmation().tx_power = tx_power; 01515 01516 // Store the time on air 01517 mcps.get_confirmation().tx_toa = _params.timers.tx_toa; 01518 mlme.get_confirmation().tx_toa = _params.timers.tx_toa; 01519 01520 // Starts the MAC layer status check timer 01521 _lora_time.start(_params.timers.mac_state_check_timer, 01522 MAC_STATE_CHECK_TIMEOUT); 01523 01524 if (_params.is_nwk_joined == false) { 01525 _params.join_request_trial_counter++; 01526 } 01527 01528 // Send now 01529 lora_phy->handle_send(_params.buffer, _params.buffer_pkt_len); 01530 01531 _params.mac_state |= LORAMAC_TX_RUNNING; 01532 01533 return LORAWAN_STATUS_OK; 01534 } 01535 01536 //lorawan_status_t LoRaMac::set_tx_continuous_wave(uint16_t timeout) 01537 //{ 01538 // cw_mode_params_t continuous_wave; 01539 01540 // continuous_wave.channel = _params.channel; 01541 // continuous_wave.datarate = _params.sys_params.channel_data_rate; 01542 // continuous_wave.tx_power = _params.sys_params.channel_tx_power; 01543 // continuous_wave.max_eirp = _params.sys_params.max_eirp; 01544 // continuous_wave.antenna_gain = _params.sys_params.antenna_gain; 01545 // continuous_wave.timeout = timeout; 01546 01547 // lora_phy->set_tx_cont_mode(&continuous_wave); 01548 01549 // // Starts the MAC layer status check timer 01550 // _lora_time.start(_params.timers.mac_state_check_timer, 01551 // MAC_STATE_CHECK_TIMEOUT); 01552 01553 // _params.mac_state |= LORAMAC_TX_RUNNING; 01554 01555 // return LORAWAN_STATUS_OK; 01556 //} 01557 01558 //lorawan_status_t LoRaMac::set_tx_continuous_wave1(uint16_t timeout, 01559 // uint32_t frequency, 01560 // uint8_t power) 01561 //{ 01562 // cw_mode_params_t continuous_wave; 01563 01564 // continuous_wave.channel = 0; 01565 // continuous_wave.datarate = 0; 01566 // continuous_wave.tx_power = power; 01567 // continuous_wave.max_eirp = 0; 01568 // continuous_wave.antenna_gain = 0; 01569 // continuous_wave.timeout = timeout; 01570 01571 // lora_phy->set_tx_cont_mode(&continuous_wave); 01572 01573 // // Starts the MAC layer status check timer 01574 // _lora_time.start(_params.timers.mac_state_check_timer, 01575 // MAC_STATE_CHECK_TIMEOUT); 01576 01577 // _params.mac_state |= LORAMAC_TX_RUNNING; 01578 01579 // return LORAWAN_STATUS_OK; 01580 //} 01581 01582 lorawan_status_t LoRaMac::initialize(loramac_primitives_t *primitives, 01583 LoRaPHY *phy, EventQueue *queue) 01584 { 01585 //store event queue pointer 01586 ev_queue = queue; 01587 01588 if (!primitives) { 01589 return LORAWAN_STATUS_PARAMETER_INVALID; 01590 } 01591 01592 lora_phy = phy; 01593 01594 // Activate MLME subsystem 01595 mlme.activate_mlme_subsystem(lora_phy); 01596 01597 // Activate MCPS subsystem 01598 mcps.activate_mcps_subsystem(); 01599 01600 // Activate MIB subsystem 01601 mib.activate_mib_subsystem(lora_phy); 01602 01603 // Activate channel planning subsystem 01604 channel_plan.activate_channelplan_subsystem(lora_phy); 01605 01606 mac_primitives = primitives; 01607 01608 _params.flags.value = 0; 01609 01610 _params.dev_class = CLASS_A ; 01611 _params.mac_state = LORAMAC_IDLE; 01612 01613 _params.join_request_trial_counter = 0; 01614 _params.max_join_request_trials = 1; 01615 _params.is_repeater_supported = false; 01616 01617 // Reset duty cycle times 01618 _params.timers.aggregated_last_tx_time = 0; 01619 _params.timers.aggregated_timeoff = 0; 01620 01621 lora_phy->reset_to_default_values(&_params, true); 01622 01623 // Init parameters which are not set in function ResetMacParameters 01624 _params.sys_params.max_sys_rx_error = 10; 01625 _params.sys_params.min_rx_symb = 6; 01626 _params.sys_params.retry_num = 1; 01627 01628 reset_mac_parameters(); 01629 01630 // Random seed initialization 01631 srand(lora_phy->get_radio_rng()); 01632 01633 _params.is_nwk_public = MBED_CONF_LORA_PUBLIC_NETWORK; 01634 lora_phy->setup_public_network_mode(_params.is_nwk_public); 01635 lora_phy->put_radio_to_sleep(); 01636 01637 // Initialize timers 01638 _lora_time.init(_params.timers.mac_state_check_timer, 01639 mbed::callback(this, &LoRaMac::handle_mac_state_check_timer_event)); 01640 _lora_time.init(_params.timers.tx_delayed_timer, 01641 mbed::callback(this, &LoRaMac::handle_delayed_tx_timer_event)); 01642 _lora_time.init(_params.timers.rx_window1_timer, 01643 mbed::callback(this, &LoRaMac::handle_rx1_timer_event)); 01644 _lora_time.init(_params.timers.rx_window2_timer, 01645 mbed::callback(this, &LoRaMac::handle_rx2_timer_event)); 01646 _lora_time.init(_params.timers.ack_timeout_timer, 01647 mbed::callback(this, &LoRaMac::handle_ack_timeout)); 01648 01649 // Store the current initialization time 01650 _params.timers.mac_init_time = _lora_time.get_current_time(); 01651 01652 return LORAWAN_STATUS_OK; 01653 } 01654 01655 void LoRaMac::disconnect() 01656 { 01657 // Cancel all timers 01658 _lora_time.stop(_params.timers.mac_state_check_timer); 01659 _lora_time.stop(_params.timers.tx_delayed_timer); 01660 _lora_time.stop(_params.timers.rx_window1_timer); 01661 _lora_time.stop(_params.timers.rx_window2_timer); 01662 _lora_time.stop(_params.timers.ack_timeout_timer); 01663 01664 // Put radio to sleep 01665 lora_phy->put_radio_to_sleep(); 01666 01667 // Reset internal state 01668 _params.is_nwk_joined = false; 01669 _params.is_ack_retry_timeout_expired = false; 01670 _params.is_rx_window_enabled = true; 01671 _params.is_node_ack_requested = false; 01672 _params.is_srv_ack_requested = false; 01673 _params.flags.value = 0; 01674 _params.mac_state = 0; 01675 01676 // Clear MAC commands 01677 mac_commands.clear_command_buffer(); 01678 mac_commands.clear_repeat_buffer(); 01679 mac_commands.clear_mac_commands_in_next_tx(); 01680 01681 // Set internal state to idle. 01682 _params.mac_state = LORAMAC_IDLE; 01683 } 01684 01685 lorawan_status_t LoRaMac::query_tx_possible(uint8_t size, 01686 loramac_tx_info_t * tx_info) 01687 { 01688 uint8_t fopt_len = mac_commands.get_mac_cmd_length() 01689 + mac_commands.get_repeat_commands_length(); 01690 01691 if (tx_info == NULL) { 01692 return LORAWAN_STATUS_PARAMETER_INVALID; 01693 } 01694 01695 // if applicaion has turned on ADR, we want to opt it out 01696 if (_params.sys_params.adr_on) { 01697 lora_phy->get_next_ADR(false, _params.sys_params.channel_data_rate, 01698 _params.sys_params.channel_tx_power, 01699 _params.adr_ack_counter); 01700 } 01701 01702 tx_info->current_payload_size = lora_phy->get_max_payload(_params.sys_params.channel_data_rate, _params.is_repeater_supported); 01703 01704 01705 // Verify if the fOpts fit into the maximum payload 01706 if (tx_info->current_payload_size >= fopt_len) { 01707 tx_info->max_possible_payload_size = tx_info->current_payload_size - fopt_len; 01708 } else { 01709 tx_info->max_possible_payload_size = tx_info->current_payload_size ; 01710 // The fOpts don't fit into the maximum payload. Omit the MAC commands to 01711 // ensure that another uplink is possible. 01712 fopt_len = 0; 01713 mac_commands.clear_command_buffer(); 01714 mac_commands.clear_repeat_buffer(); 01715 } 01716 01717 // Verify if the fOpts and the payload fit into the maximum payload 01718 if (validate_payload_length(size, _params.sys_params.channel_data_rate, 01719 fopt_len) == false) { 01720 return LORAWAN_STATUS_LENGTH_ERROR; 01721 } 01722 return LORAWAN_STATUS_OK; 01723 } 01724 01725 lorawan_status_t LoRaMac::add_channel_plan(const lorawan_channelplan_t& plan) 01726 { 01727 // Validate if the MAC is in a correct state 01728 if ((_params.mac_state & LORAMAC_TX_RUNNING) == LORAMAC_TX_RUNNING) { 01729 if ((_params.mac_state & LORAMAC_TX_CONFIG) != LORAMAC_TX_CONFIG) { 01730 return LORAWAN_STATUS_BUSY; 01731 } 01732 } 01733 01734 return channel_plan.set_plan(plan); 01735 } 01736 01737 lorawan_status_t LoRaMac::remove_channel_plan() 01738 { 01739 if ((_params.mac_state & LORAMAC_TX_RUNNING) == LORAMAC_TX_RUNNING) { 01740 if ((_params.mac_state & LORAMAC_TX_CONFIG) != LORAMAC_TX_CONFIG) { 01741 return LORAWAN_STATUS_BUSY; 01742 } 01743 } 01744 01745 return channel_plan.remove_plan(); 01746 01747 } 01748 01749 lorawan_status_t LoRaMac::get_channel_plan(lorawan_channelplan_t& plan) 01750 { 01751 // Request Mib to get channels 01752 loramac_mib_req_confirm_t mib_confirm; 01753 memset(&mib_confirm, 0, sizeof(mib_confirm)); 01754 mib_confirm.type = MIB_CHANNELS ; 01755 01756 lorawan_status_t status = mib.get_request(&mib_confirm, &_params); 01757 01758 if (status != LORAWAN_STATUS_OK) { 01759 return status; 01760 } 01761 01762 return channel_plan.get_plan(plan, &mib_confirm); 01763 } 01764 01765 lorawan_status_t LoRaMac::remove_single_channel(uint8_t id) 01766 { 01767 if ((_params.mac_state & LORAMAC_TX_RUNNING) == LORAMAC_TX_RUNNING) { 01768 if ((_params.mac_state & LORAMAC_TX_CONFIG) != LORAMAC_TX_CONFIG) { 01769 return LORAWAN_STATUS_BUSY; 01770 } 01771 } 01772 01773 return channel_plan.remove_single_channel(id); 01774 } 01775 01776 lorawan_status_t LoRaMac::multicast_channel_link(multicast_params_t *channel_param) 01777 { 01778 if (channel_param == NULL) { 01779 return LORAWAN_STATUS_PARAMETER_INVALID; 01780 } 01781 if ((_params.mac_state & LORAMAC_TX_RUNNING) == LORAMAC_TX_RUNNING) { 01782 return LORAWAN_STATUS_BUSY; 01783 } 01784 01785 // Reset downlink counter 01786 channel_param->dl_frame_counter = 0; 01787 01788 if (_params.multicast_channels == NULL) { 01789 // New node is the fist element 01790 _params.multicast_channels = channel_param; 01791 } else { 01792 multicast_params_t *cur = _params.multicast_channels; 01793 01794 // Search the last node in the list 01795 while (cur->next != NULL) { 01796 cur = cur->next ; 01797 } 01798 // This function always finds the last node 01799 cur->next = channel_param; 01800 } 01801 01802 return LORAWAN_STATUS_OK; 01803 } 01804 01805 lorawan_status_t LoRaMac::multicast_channel_unlink( 01806 multicast_params_t *channel_param) 01807 { 01808 if (channel_param == NULL) { 01809 return LORAWAN_STATUS_PARAMETER_INVALID; 01810 } 01811 if ((_params.mac_state & LORAMAC_TX_RUNNING) == LORAMAC_TX_RUNNING) { 01812 return LORAWAN_STATUS_BUSY; 01813 } 01814 01815 if (_params.multicast_channels != NULL) { 01816 if (_params.multicast_channels == channel_param) { 01817 // First element 01818 _params.multicast_channels = channel_param->next ; 01819 } else { 01820 multicast_params_t *cur = _params.multicast_channels; 01821 01822 // Search the node in the list 01823 while (cur->next && cur->next != channel_param) { 01824 cur = cur->next ; 01825 } 01826 // If we found the node, remove it 01827 if (cur->next ) { 01828 cur->next = channel_param->next ; 01829 } 01830 } 01831 channel_param->next = NULL; 01832 } 01833 01834 return LORAWAN_STATUS_OK; 01835 } 01836 01837 lorawan_status_t LoRaMac::mlme_request( loramac_mlme_req_t *mlmeRequest ) 01838 { 01839 if (LORAMAC_IDLE != _params.mac_state) { 01840 return LORAWAN_STATUS_BUSY; 01841 } 01842 01843 mlme.reset_confirmation(); 01844 01845 mlme.get_confirmation().req_type = mlmeRequest->type ; 01846 _params.flags.bits.mlme_req = 1; 01847 01848 lorawan_status_t status = LORAWAN_STATUS_SERVICE_UNKNOWN; 01849 01850 if (MLME_LINK_CHECK == mlmeRequest->type ) { 01851 status = mac_commands.add_mac_command(MOTE_MAC_LINK_CHECK_REQ , 0, 0); 01852 } else if (MLME_JOIN == mlmeRequest->type ) { 01853 if ((_params.mac_state & LORAMAC_TX_DELAYED) == LORAMAC_TX_DELAYED) { 01854 return LORAWAN_STATUS_BUSY; 01855 } 01856 01857 if ((mlmeRequest->req.join .dev_eui == NULL) 01858 || (mlmeRequest->req.join .app_eui == NULL) 01859 || (mlmeRequest->req.join .app_key == NULL) 01860 || (mlmeRequest->req.join .nb_trials == 0)) { 01861 return LORAWAN_STATUS_PARAMETER_INVALID; 01862 } 01863 _params.keys.dev_eui = mlmeRequest->req.join .dev_eui ; 01864 _params.keys.app_eui = mlmeRequest->req.join .app_eui ; 01865 _params.keys.app_key = mlmeRequest->req.join .app_key ; 01866 _params.max_join_request_trials = mlmeRequest->req.join .nb_trials ; 01867 01868 if (!lora_phy->verify_nb_join_trials(mlmeRequest->req.join .nb_trials )) { 01869 // Value not supported, get default 01870 _params.max_join_request_trials = MBED_CONF_LORA_NB_TRIALS; 01871 } 01872 // Reset variable JoinRequestTrials 01873 _params.join_request_trial_counter = 0; 01874 01875 reset_mac_parameters(); 01876 01877 _params.sys_params.channel_data_rate = 01878 lora_phy->get_alternate_DR(_params.join_request_trial_counter + 1); 01879 01880 loramac_mhdr_t machdr; 01881 machdr.value = 0; 01882 machdr.bits.mtype = FRAME_TYPE_JOIN_REQ ; 01883 status = send(&machdr, 0, NULL, 0); 01884 } else if (MLME_TXCW == mlmeRequest->type ) { 01885 mlme.set_tx_continuous_wave(_params.channel, _params.sys_params.channel_data_rate, _params.sys_params.channel_tx_power, 01886 _params.sys_params.max_eirp, _params.sys_params.antenna_gain, mlmeRequest->req.cw_tx_mode .timeout ); 01887 _lora_time.start(_params.timers.mac_state_check_timer, 01888 MAC_STATE_CHECK_TIMEOUT); 01889 01890 _params.mac_state |= LORAMAC_TX_RUNNING; 01891 status = LORAWAN_STATUS_OK; 01892 } else if (MLME_TXCW_1 == mlmeRequest->type ) { 01893 mlme.set_tx_continuous_wave(0, 0, mlmeRequest->req.cw_tx_mode .power , 0, 0, mlmeRequest->req.cw_tx_mode .timeout ); 01894 _lora_time.start(_params.timers.mac_state_check_timer, 01895 MAC_STATE_CHECK_TIMEOUT); 01896 01897 _params.mac_state |= LORAMAC_TX_RUNNING; 01898 status = LORAWAN_STATUS_OK; 01899 } 01900 01901 if (status != LORAWAN_STATUS_OK) { 01902 _params.is_node_ack_requested = false; 01903 _params.flags.bits.mlme_req = 0; 01904 } 01905 01906 01907 return status; 01908 } 01909 01910 lorawan_status_t LoRaMac::mcps_request( loramac_mcps_req_t *mcpsRequest ) 01911 { 01912 if (_params.mac_state != LORAMAC_IDLE) { 01913 return LORAWAN_STATUS_BUSY; 01914 } 01915 01916 loramac_mhdr_t machdr; 01917 int8_t datarate = mcpsRequest->data_rate ; 01918 // TODO: The comment is different than the code??? 01919 // Apply the minimum possible datarate. 01920 // Some regions have limitations for the minimum datarate. 01921 datarate = MAX(datarate, (int8_t)lora_phy->get_minimum_tx_datarate()); 01922 01923 machdr.value = 0; 01924 01925 mcps.reset_confirmation(); 01926 01927 _params.ack_timeout_retry_counter = 1; 01928 _params.max_ack_timeout_retries = 1; 01929 01930 switch (mcpsRequest->type ) { 01931 case MCPS_UNCONFIRMED : { 01932 machdr.bits.mtype = FRAME_TYPE_DATA_UNCONFIRMED_UP ; 01933 break; 01934 } 01935 case MCPS_CONFIRMED : { 01936 machdr.bits.mtype = FRAME_TYPE_DATA_CONFIRMED_UP ; 01937 _params.max_ack_timeout_retries = mcpsRequest->nb_trials ; 01938 break; 01939 } 01940 case MCPS_PROPRIETARY : { 01941 machdr.bits.mtype = FRAME_TYPE_PROPRIETARY ; 01942 break; 01943 } 01944 default: 01945 return LORAWAN_STATUS_PARAMETER_INVALID; 01946 } 01947 01948 // Filter fPorts 01949 // TODO: Does not work with PROPRIETARY messages 01950 // if( IsFPortAllowed( mcpsRequest->fport ) == false ) { 01951 // return LORAWAN_STATUS_PARAMETER_INVALID; 01952 // } 01953 01954 if (_params.sys_params.adr_on == false) { 01955 if (lora_phy->verify_tx_datarate(datarate, false) == true) { 01956 _params.sys_params.channel_data_rate = datarate; 01957 } else { 01958 return LORAWAN_STATUS_PARAMETER_INVALID; 01959 } 01960 } 01961 01962 lorawan_status_t status = send(&machdr, mcpsRequest->fport , mcpsRequest->f_buffer, 01963 mcpsRequest->f_buffer_size); 01964 if (status == LORAWAN_STATUS_OK) { 01965 mcps.get_confirmation().req_type = mcpsRequest->type ; 01966 _params.flags.bits.mcps_req = 1; 01967 } else { 01968 _params.is_node_ack_requested = false; 01969 } 01970 01971 return status; 01972 } 01973 01974 lorawan_status_t LoRaMac::mib_get_request_confirm( loramac_mib_req_confirm_t *mibGet ) 01975 { 01976 return mib.get_request(mibGet, &_params); 01977 } 01978 01979 lorawan_status_t LoRaMac::mib_set_request_confirm( loramac_mib_req_confirm_t *mibSet ) 01980 { 01981 lorawan_status_t status = mib.set_request(mibSet, &_params); 01982 if (LORAWAN_STATUS_OK == status && CLASS_C == _params.dev_class && (MIB_DEVICE_CLASS == mibSet->type || 01983 (MIB_RX2_CHANNEL == mibSet->type && _params.is_nwk_joined))) { 01984 open_continuous_rx2_window(); 01985 } 01986 return status; 01987 } 01988 01989 radio_events_t *LoRaMac::get_phy_event_handlers() 01990 { 01991 radio_events.tx_done = mbed::callback(this, &LoRaMac::handle_tx_done); 01992 radio_events.rx_done = mbed::callback(this, &LoRaMac::handle_rx_done); 01993 radio_events.rx_error = mbed::callback(this, &LoRaMac::handle_rx_error); 01994 radio_events.tx_timeout = mbed::callback(this, &LoRaMac::handle_tx_timeout); 01995 radio_events.rx_timeout = mbed::callback(this, &LoRaMac::handle_rx_timeout); 01996 01997 return &radio_events; 01998 } 01999 02000 #if defined(LORAWAN_COMPLIANCE_TEST) 02001 /*************************************************************************** 02002 * Compliance testing * 02003 **************************************************************************/ 02004 02005 lorawan_status_t LoRaMac::LoRaMacSetTxTimer( uint32_t TxDutyCycleTime ) 02006 { 02007 _lora_time.start(tx_next_packet_timer, TxDutyCycleTime); 02008 return LORAWAN_STATUS_OK; 02009 } 02010 02011 lorawan_status_t LoRaMac::LoRaMacStopTxTimer( ) 02012 { 02013 _lora_time.stop(tx_next_packet_timer); 02014 return LORAWAN_STATUS_OK; 02015 } 02016 02017 void LoRaMac::LoRaMacTestRxWindowsOn( bool enable ) 02018 { 02019 _params.is_rx_window_enabled = enable; 02020 } 02021 02022 void LoRaMac::LoRaMacTestSetMic( uint16_t txPacketCounter ) 02023 { 02024 _params.ul_frame_counter = txPacketCounter; 02025 _params.is_ul_frame_counter_fixed = true; 02026 } 02027 02028 void LoRaMac::LoRaMacTestSetDutyCycleOn( bool enable ) 02029 { 02030 if(lora_phy->verify_duty_cycle(enable) == true) 02031 { 02032 _params.is_dutycycle_on = enable; 02033 } 02034 } 02035 02036 void LoRaMac::LoRaMacTestSetChannel( uint8_t channel ) 02037 { 02038 _params.channel = channel; 02039 } 02040 #endif
Generated on Tue Jul 12 2022 11:43:35 by
