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.
Dependencies: nRF51_Vdd TextLCD BME280
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 00027 #include "mbed-trace/mbed_trace.h" 00028 #define TRACE_GROUP "LMAC" 00029 00030 using namespace events; 00031 using namespace mbed; 00032 00033 /* 00034 * LoRaWAN spec 6.2: AppKey is AES-128 key 00035 */ 00036 #define APPKEY_KEY_LENGTH 128 00037 00038 /*! 00039 * Maximum length of the fOpts field 00040 */ 00041 #define LORA_MAC_COMMAND_MAX_FOPTS_LENGTH 15 00042 00043 /*! 00044 * LoRaMac duty cycle for the back-off procedure during the first hour. 00045 */ 00046 #define BACKOFF_DC_1_HOUR 100 00047 00048 /*! 00049 * LoRaMac duty cycle for the back-off procedure during the next 10 hours. 00050 */ 00051 #define BACKOFF_DC_10_HOURS 1000 00052 00053 /*! 00054 * LoRaMac duty cycle for the back-off procedure during the next 24 hours. 00055 */ 00056 #define BACKOFF_DC_24_HOURS 10000 00057 00058 /*! 00059 * The frame direction definition for uplink communications. 00060 */ 00061 #define UP_LINK 0 00062 00063 /*! 00064 * The frame direction definition for downlink communications. 00065 */ 00066 #define DOWN_LINK 1 00067 00068 LoRaMac::LoRaMac() 00069 : _lora_time(), 00070 _lora_phy(NULL), 00071 _mac_commands(), 00072 _channel_plan(), 00073 _lora_crypto(), 00074 _ev_queue(NULL), 00075 _mcps_indication(), 00076 _mcps_confirmation(), 00077 _mlme_indication(), 00078 _mlme_confirmation(), 00079 _is_nwk_joined(false), 00080 _can_cancel_tx(true), 00081 _continuous_rx2_window_open(false), 00082 _device_class(CLASS_A), 00083 _prev_qos_level(LORAWAN_DEFAULT_QOS) 00084 { 00085 memset(&_params, 0, sizeof(_params)); 00086 _params.keys.dev_eui = NULL; 00087 _params.keys.app_eui = NULL; 00088 _params.keys.app_key = NULL; 00089 00090 memset(_params.keys.nwk_skey, 0, sizeof(_params.keys.nwk_skey)); 00091 memset(_params.keys.app_skey, 0, sizeof(_params.keys.app_skey)); 00092 memset(&_ongoing_tx_msg, 0, sizeof(_ongoing_tx_msg)); 00093 memset(&_params.sys_params, 0, sizeof(_params.sys_params)); 00094 00095 _params.dev_nonce = 0; 00096 _params.net_id = 0; 00097 _params.dev_addr = 0; 00098 _params.tx_buffer_len = 0; 00099 _params.rx_buffer_len = 0; 00100 _params.ul_frame_counter = 0; 00101 _params.dl_frame_counter = 0; 00102 _params.is_ul_frame_counter_fixed = false; 00103 _params.is_rx_window_enabled = true; 00104 _params.adr_ack_counter = 0; 00105 _params.is_node_ack_requested = false; 00106 _params.is_srv_ack_requested = false; 00107 _params.ul_nb_rep_counter = 0; 00108 _params.timers.mac_init_time = 0; 00109 _params.max_ack_timeout_retries = 1; 00110 _params.ack_timeout_retry_counter = 1; 00111 _params.is_ack_retry_timeout_expired = false; 00112 _params.timers.tx_toa = 0; 00113 00114 _params.multicast_channels = NULL; 00115 00116 00117 _params.sys_params.adr_on = false; 00118 _params.sys_params.max_duty_cycle = 0; 00119 00120 reset_mcps_confirmation(); 00121 reset_mlme_confirmation(); 00122 reset_mcps_indication(); 00123 } 00124 00125 LoRaMac::~LoRaMac() 00126 { 00127 } 00128 00129 /*************************************************************************** 00130 * Radio event callbacks - delegated to Radio driver * 00131 **************************************************************************/ 00132 00133 const loramac_mcps_confirm_t *LoRaMac::get_mcps_confirmation() const 00134 { 00135 return &_mcps_confirmation; 00136 } 00137 00138 const loramac_mcps_indication_t *LoRaMac::get_mcps_indication() const 00139 { 00140 return &_mcps_indication; 00141 } 00142 00143 const loramac_mlme_confirm_t *LoRaMac::get_mlme_confirmation() const 00144 { 00145 return &_mlme_confirmation; 00146 } 00147 00148 const loramac_mlme_indication_t *LoRaMac::get_mlme_indication() const 00149 { 00150 return &_mlme_indication; 00151 } 00152 00153 void LoRaMac::post_process_mlme_request() 00154 { 00155 _mlme_confirmation.pending = false; 00156 } 00157 00158 void LoRaMac::post_process_mcps_req() 00159 { 00160 _params.is_last_tx_join_request = false; 00161 _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_OK ; 00162 if (_mcps_confirmation.req_type == MCPS_CONFIRMED ) { 00163 // An MCPS request for a CONFIRMED message has received an ack 00164 // in the downlink message 00165 if (_mcps_confirmation.ack_received) { 00166 _params.is_node_ack_requested = false; 00167 _mcps_confirmation.ack_received = false; 00168 _mcps_indication.is_ack_recvd = false; 00169 if (_params.is_ul_frame_counter_fixed == false) { 00170 _params.ul_frame_counter++; 00171 _params.adr_ack_counter++; 00172 } 00173 } else { 00174 _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR ; 00175 } 00176 } else { 00177 //UNCONFIRMED or PROPRIETARY 00178 if (_params.is_ul_frame_counter_fixed == false) { 00179 _params.ul_frame_counter++; 00180 _params.adr_ack_counter++; 00181 if (_params.sys_params.nb_trans > 1) { 00182 _mcps_confirmation.nb_retries = _params.ul_nb_rep_counter; 00183 } 00184 } 00185 } 00186 } 00187 00188 void LoRaMac::post_process_mcps_ind() 00189 { 00190 _mcps_indication.pending = false; 00191 } 00192 00193 void LoRaMac::post_process_mlme_ind() 00194 { 00195 _mlme_indication.pending = false; 00196 } 00197 00198 lorawan_time_t LoRaMac::get_current_time(void) 00199 { 00200 return _lora_time.get_current_time(); 00201 } 00202 00203 rx_slot_t LoRaMac::get_current_slot(void) 00204 { 00205 return _params.rx_slot; 00206 } 00207 00208 /** 00209 * This part handles incoming frames in response to Radio RX Interrupt 00210 */ 00211 void LoRaMac::handle_join_accept_frame(const uint8_t *payload, uint16_t size) 00212 { 00213 uint32_t mic = 0; 00214 uint32_t mic_rx = 0; 00215 00216 _mlme_confirmation.nb_retries = _params.join_request_trial_counter; 00217 00218 if (0 != _lora_crypto.decrypt_join_frame(payload + 1, size - 1, 00219 _params.keys.app_key, APPKEY_KEY_LENGTH, 00220 _params.rx_buffer + 1)) { 00221 _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL ; 00222 return; 00223 } 00224 00225 _params.rx_buffer[0] = payload[0]; 00226 00227 if (_lora_crypto.compute_join_frame_mic(_params.rx_buffer, 00228 size - LORAMAC_MFR_LEN, 00229 _params.keys.app_key, 00230 APPKEY_KEY_LENGTH, 00231 &mic) != 0) { 00232 _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL ; 00233 return; 00234 } 00235 00236 mic_rx |= (uint32_t) _params.rx_buffer[size - LORAMAC_MFR_LEN]; 00237 mic_rx |= ((uint32_t) _params.rx_buffer[size - LORAMAC_MFR_LEN + 1] << 8); 00238 mic_rx |= ((uint32_t) _params.rx_buffer[size - LORAMAC_MFR_LEN + 2] << 16); 00239 mic_rx |= ((uint32_t) _params.rx_buffer[size - LORAMAC_MFR_LEN + 3] << 24); 00240 00241 if (mic_rx == mic) { 00242 _lora_time.stop(_params.timers.rx_window2_timer); 00243 if (_lora_crypto.compute_skeys_for_join_frame(_params.keys.app_key, 00244 APPKEY_KEY_LENGTH, 00245 _params.rx_buffer + 1, 00246 _params.dev_nonce, 00247 _params.keys.nwk_skey, 00248 _params.keys.app_skey) != 0) { 00249 _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL ; 00250 return; 00251 } 00252 00253 _params.net_id = (uint32_t) _params.rx_buffer[4]; 00254 _params.net_id |= ((uint32_t) _params.rx_buffer[5] << 8); 00255 _params.net_id |= ((uint32_t) _params.rx_buffer[6] << 16); 00256 00257 _params.dev_addr = (uint32_t) _params.rx_buffer[7]; 00258 _params.dev_addr |= ((uint32_t) _params.rx_buffer[8] << 8); 00259 _params.dev_addr |= ((uint32_t) _params.rx_buffer[9] << 16); 00260 _params.dev_addr |= ((uint32_t) _params.rx_buffer[10] << 24); 00261 00262 _params.sys_params.rx1_dr_offset = (_params.rx_buffer[11] >> 4) & 0x07; 00263 _params.sys_params.rx2_channel.datarate = _params.rx_buffer[11] & 0x0F; 00264 00265 _params.sys_params.recv_delay1 = (_params.rx_buffer[12] & 0x0F); 00266 00267 if (_params.sys_params.recv_delay1 == 0) { 00268 _params.sys_params.recv_delay1 = 1; 00269 } 00270 00271 _params.sys_params.recv_delay1 *= 1000; 00272 _params.sys_params.recv_delay2 = _params.sys_params.recv_delay1 + 1000; 00273 00274 // Size of the regular payload is 12. Plus 1 byte MHDR and 4 bytes MIC 00275 _lora_phy->apply_cf_list(&_params.rx_buffer[13], size - 17); 00276 00277 _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_OK ; 00278 _is_nwk_joined = true; 00279 // Node joined successfully 00280 _params.ul_frame_counter = 0; 00281 _params.ul_nb_rep_counter = 0; 00282 _params.adr_ack_counter = 0; 00283 00284 } else { 00285 _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL ; 00286 } 00287 } 00288 00289 void LoRaMac::check_frame_size(uint16_t size) 00290 { 00291 uint8_t value = _lora_phy->get_max_payload(_mcps_indication.rx_datarate, 00292 _params.is_repeater_supported); 00293 00294 if (MAX(0, (int16_t)((int16_t)size - (int16_t)LORA_MAC_FRMPAYLOAD_OVERHEAD)) 00295 > (int32_t) value) { 00296 tr_error("Invalid frame size"); 00297 } 00298 } 00299 00300 bool LoRaMac::message_integrity_check(const uint8_t *const payload, 00301 const uint16_t size, 00302 uint8_t *const ptr_pos, 00303 uint32_t address, 00304 uint32_t *downlink_counter, 00305 const uint8_t *nwk_skey) 00306 { 00307 uint32_t mic = 0; 00308 uint32_t mic_rx = 0; 00309 00310 uint16_t sequence_counter = 0; 00311 uint16_t sequence_counter_prev = 0; 00312 uint16_t sequence_counter_diff = 0; 00313 00314 sequence_counter = (uint16_t) payload[(*ptr_pos)++]; 00315 sequence_counter |= (uint16_t) payload[(*ptr_pos)++] << 8; 00316 00317 mic_rx |= (uint32_t) payload[size - LORAMAC_MFR_LEN]; 00318 mic_rx |= ((uint32_t) payload[size - LORAMAC_MFR_LEN + 1] << 8); 00319 mic_rx |= ((uint32_t) payload[size - LORAMAC_MFR_LEN + 2] << 16); 00320 mic_rx |= ((uint32_t) payload[size - LORAMAC_MFR_LEN + 3] << 24); 00321 00322 sequence_counter_prev = (uint16_t)*downlink_counter; 00323 sequence_counter_diff = sequence_counter - sequence_counter_prev; 00324 *downlink_counter += sequence_counter_diff; 00325 if (sequence_counter < sequence_counter_prev) { 00326 *downlink_counter += 0x10000; 00327 } 00328 00329 // sizeof nws_skey must be the same as _params.keys.nwk_skey, 00330 _lora_crypto.compute_mic(payload, size - LORAMAC_MFR_LEN, 00331 nwk_skey, 00332 sizeof(_params.keys.nwk_skey) * 8, 00333 address, DOWN_LINK, *downlink_counter, &mic); 00334 00335 if (mic_rx != mic) { 00336 _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_MIC_FAIL ; 00337 return false; 00338 } 00339 00340 if (sequence_counter_diff >= _lora_phy->get_maximum_frame_counter_gap()) { 00341 _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_TOO_MANY_FRAMES_LOST ; 00342 _mcps_indication.dl_frame_counter = *downlink_counter; 00343 return false; 00344 } 00345 00346 return true; 00347 } 00348 00349 void LoRaMac::extract_data_and_mac_commands(const uint8_t *payload, 00350 uint16_t size, 00351 uint8_t fopts_len, 00352 uint8_t *nwk_skey, 00353 uint8_t *app_skey, 00354 uint32_t address, 00355 uint32_t downlink_counter, 00356 int16_t rssi, 00357 int8_t snr) 00358 { 00359 uint8_t frame_len = 0; 00360 uint8_t payload_start_index = 8 + fopts_len; 00361 uint8_t port = payload[payload_start_index++]; 00362 frame_len = (size - 4) - payload_start_index; 00363 00364 _mcps_indication.port = port; 00365 00366 // special handling of control port 0 00367 if (port == 0) { 00368 if (fopts_len == 0) { 00369 // sizeof nws_skey must be the same as _params.keys.nwk_skey, 00370 if (_lora_crypto.decrypt_payload(payload + payload_start_index, 00371 frame_len, 00372 nwk_skey, 00373 sizeof(_params.keys.nwk_skey) * 8, 00374 address, 00375 DOWN_LINK, 00376 downlink_counter, 00377 _params.rx_buffer) != 0) { 00378 _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL ; 00379 } 00380 00381 if (_mac_commands.process_mac_commands(_params.rx_buffer, 0, frame_len, 00382 snr, _mlme_confirmation, 00383 _params.sys_params, *_lora_phy) 00384 != LORAWAN_STATUS_OK) { 00385 _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_ERROR ; 00386 return; 00387 } 00388 00389 if (_mac_commands.has_sticky_mac_cmd()) { 00390 set_mlme_schedule_ul_indication(); 00391 _mac_commands.clear_sticky_mac_cmd(); 00392 } 00393 00394 return; 00395 } 00396 00397 _mcps_indication.pending = false; 00398 _mcps_confirmation.ack_received = false; 00399 _mcps_indication.is_ack_recvd = false; 00400 00401 return; 00402 } 00403 00404 // normal unicast/multicast port handling 00405 if (fopts_len > 0) { 00406 // Decode Options field MAC commands. Omit the fPort. 00407 if (_mac_commands.process_mac_commands(payload, 8, 00408 payload_start_index - 1, 00409 snr, 00410 _mlme_confirmation, 00411 _params.sys_params, 00412 *_lora_phy) != LORAWAN_STATUS_OK) { 00413 _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_ERROR ; 00414 return; 00415 } 00416 00417 if (_mac_commands.has_sticky_mac_cmd()) { 00418 set_mlme_schedule_ul_indication(); 00419 _mac_commands.clear_sticky_mac_cmd(); 00420 } 00421 } 00422 00423 // sizeof app_skey must be the same as _params.keys.app_skey 00424 if (_lora_crypto.decrypt_payload(payload + payload_start_index, 00425 frame_len, 00426 app_skey, 00427 sizeof(_params.keys.app_skey) * 8, 00428 address, 00429 DOWN_LINK, 00430 downlink_counter, 00431 _params.rx_buffer) != 0) { 00432 _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL ; 00433 } else { 00434 _mcps_indication.buffer = _params.rx_buffer; 00435 _mcps_indication.buffer_size = frame_len; 00436 _mcps_indication.is_data_recvd = true; 00437 } 00438 } 00439 00440 void LoRaMac::extract_mac_commands_only(const uint8_t *payload, 00441 int8_t snr, 00442 uint8_t fopts_len) 00443 { 00444 uint8_t payload_start_index = 8 + fopts_len; 00445 if (fopts_len > 0) { 00446 if (_mac_commands.process_mac_commands(payload, 8, payload_start_index, 00447 snr, _mlme_confirmation, 00448 _params.sys_params, *_lora_phy) 00449 != LORAWAN_STATUS_OK) { 00450 _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_ERROR ; 00451 return; 00452 } 00453 00454 if (_mac_commands.has_sticky_mac_cmd()) { 00455 set_mlme_schedule_ul_indication(); 00456 _mac_commands.clear_sticky_mac_cmd(); 00457 } 00458 } 00459 } 00460 00461 void LoRaMac::handle_data_frame(const uint8_t *const payload, 00462 const uint16_t size, 00463 uint8_t ptr_pos, 00464 uint8_t msg_type, 00465 int16_t rssi, 00466 int8_t snr) 00467 { 00468 check_frame_size(size); 00469 00470 bool is_multicast = false; 00471 loramac_frame_ctrl_t fctrl; 00472 multicast_params_t *cur_multicast_params; 00473 uint32_t address = 0; 00474 uint32_t downlink_counter = 0; 00475 uint8_t app_payload_start_index = 0; 00476 uint8_t *nwk_skey = _params.keys.nwk_skey ; 00477 uint8_t *app_skey = _params.keys.app_skey; 00478 00479 address = payload[ptr_pos++]; 00480 address |= ((uint32_t) payload[ptr_pos++] << 8); 00481 address |= ((uint32_t) payload[ptr_pos++] << 16); 00482 address |= ((uint32_t) payload[ptr_pos++] << 24); 00483 00484 if (address != _params.dev_addr) { 00485 // check if Multicast is destined for us 00486 cur_multicast_params = _params.multicast_channels; 00487 00488 while (cur_multicast_params != NULL) { 00489 if (address == cur_multicast_params->address ) { 00490 is_multicast = true; 00491 nwk_skey = cur_multicast_params->nwk_skey ; 00492 app_skey = cur_multicast_params->app_skey ; 00493 downlink_counter = cur_multicast_params->dl_frame_counter ; 00494 break; 00495 } 00496 00497 cur_multicast_params = cur_multicast_params->next ; 00498 } 00499 00500 if (!is_multicast) { 00501 // We are not the destination of this frame. 00502 _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL ; 00503 _mcps_indication.pending = false; 00504 return; 00505 } 00506 } else { 00507 is_multicast = false; 00508 nwk_skey = _params.keys.nwk_skey; 00509 app_skey = _params.keys.app_skey; 00510 downlink_counter = _params.dl_frame_counter; 00511 } 00512 00513 fctrl.value = payload[ptr_pos++]; 00514 app_payload_start_index = 8 + fctrl.bits.fopts_len ; 00515 00516 //perform MIC check 00517 if (!message_integrity_check(payload, size, &ptr_pos, address, 00518 &downlink_counter, nwk_skey)) { 00519 tr_error("MIC failed"); 00520 _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_MIC_FAIL ; 00521 _mcps_indication.pending = false; 00522 return; 00523 } 00524 00525 _mcps_confirmation.ack_received = false; 00526 _mcps_indication.is_ack_recvd = false; 00527 _mcps_indication.pending = true; 00528 _mcps_indication.is_data_recvd = false; 00529 _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_OK ; 00530 _mcps_indication.multicast = is_multicast; 00531 _mcps_indication.fpending_status = fctrl.bits.fpending ; 00532 _mcps_indication.buffer = NULL; 00533 _mcps_indication.buffer_size = 0; 00534 _mcps_indication.dl_frame_counter = downlink_counter; 00535 _mcps_indication.rssi = rssi; 00536 _mcps_indication.snr = snr; 00537 00538 _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_OK ; 00539 00540 _params.adr_ack_counter = 0; 00541 _mac_commands.clear_repeat_buffer(); 00542 _mac_commands.clear_command_buffer(); 00543 00544 if (is_multicast) { 00545 _mcps_indication.type = MCPS_MULTICAST ; 00546 00547 // Discard if its a repeated message 00548 if ((cur_multicast_params->dl_frame_counter == downlink_counter) 00549 && (cur_multicast_params->dl_frame_counter != 0)) { 00550 _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED ; 00551 _mcps_indication.dl_frame_counter = downlink_counter; 00552 _mcps_indication.pending = false; 00553 00554 return; 00555 } 00556 00557 cur_multicast_params->dl_frame_counter = downlink_counter; 00558 00559 } else { 00560 if (msg_type == FRAME_TYPE_DATA_CONFIRMED_DOWN ) { 00561 _params.is_srv_ack_requested = true; 00562 _mcps_indication.type = MCPS_CONFIRMED ; 00563 00564 if ((_params.dl_frame_counter == downlink_counter) 00565 && (_params.dl_frame_counter != 0)) { 00566 // Duplicated confirmed downlink. Skip indication. 00567 // In this case, the MAC layer shall accept the MAC commands 00568 // which are included in the downlink retransmission. 00569 // It should not provide the same frame to the application 00570 // layer again. The MAC layer accepts the acknowledgement. 00571 tr_debug("Discarding duplicate frame"); 00572 _mcps_indication.pending = false; 00573 _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED ; 00574 00575 return; 00576 } 00577 } else if (msg_type == FRAME_TYPE_DATA_UNCONFIRMED_DOWN ) { 00578 _params.is_srv_ack_requested = false; 00579 _mcps_indication.type = MCPS_UNCONFIRMED ; 00580 00581 if ((_params.dl_frame_counter == downlink_counter) 00582 && (_params.dl_frame_counter != 0)) { 00583 tr_debug("Discarding duplicate frame"); 00584 _mcps_indication.pending = false; 00585 _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED ; 00586 00587 return; 00588 } 00589 } 00590 _params.dl_frame_counter = downlink_counter; 00591 } 00592 00593 // message is intended for us and MIC have passed, stop RX2 Window 00594 // Spec: 3.3.4 Receiver Activity during the receive windows 00595 if (get_current_slot() == RX_SLOT_WIN_1 ) { 00596 _lora_time.stop(_params.timers.rx_window2_timer); 00597 } else { 00598 _lora_time.stop(_params.timers.rx_window1_timer); 00599 _lora_time.stop(_params.timers.rx_window2_timer); 00600 } 00601 00602 if (_device_class == CLASS_C) { 00603 _lora_time.stop(_rx2_closure_timer_for_class_c); 00604 } 00605 00606 if (_params.is_node_ack_requested && fctrl.bits.ack ) { 00607 _mcps_confirmation.ack_received = fctrl.bits.ack ; 00608 _mcps_indication.is_ack_recvd = fctrl.bits.ack ; 00609 } 00610 00611 uint8_t frame_len = (size - 4) - app_payload_start_index; 00612 00613 if (frame_len > 0) { 00614 extract_data_and_mac_commands(payload, size, fctrl.bits.fopts_len , 00615 nwk_skey, app_skey, address, 00616 downlink_counter, rssi, snr); 00617 } else { 00618 extract_mac_commands_only(payload, snr, fctrl.bits.fopts_len ); 00619 } 00620 00621 // Handle proprietary messages. 00622 if (msg_type == FRAME_TYPE_PROPRIETARY ) { 00623 memcpy(_params.rx_buffer, &payload[ptr_pos], size); 00624 00625 _mcps_indication.type = MCPS_PROPRIETARY ; 00626 _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_OK ; 00627 _mcps_indication.buffer = _params.rx_buffer; 00628 _mcps_indication.buffer_size = size - ptr_pos; 00629 } 00630 00631 // only stop act timer, if the ack is actually recieved 00632 if (_mcps_confirmation.ack_received) { 00633 _lora_time.stop(_params.timers.ack_timeout_timer); 00634 } 00635 } 00636 00637 void LoRaMac::set_batterylevel_callback(mbed::Callback<uint8_t(void)> battery_level) 00638 { 00639 _mac_commands.set_batterylevel_callback(battery_level); 00640 } 00641 00642 void LoRaMac::on_radio_tx_done(lorawan_time_t timestamp) 00643 { 00644 if (_device_class == CLASS_C) { 00645 // this will open a continuous RX2 window until time==RECV_DELAY1 00646 open_rx2_window(); 00647 } else { 00648 _lora_phy->put_radio_to_sleep(); 00649 } 00650 00651 if ((_mcps_confirmation.req_type == MCPS_UNCONFIRMED ) 00652 && (_params.sys_params.nb_trans > 1)) { 00653 _params.ul_nb_rep_counter++; 00654 MBED_ASSERT(_params.ul_nb_rep_counter <= _params.sys_params.nb_trans); 00655 } 00656 00657 if (_params.is_rx_window_enabled == true) { 00658 lorawan_time_t time_diff = _lora_time.get_current_time() - timestamp; 00659 // start timer after which rx1_window will get opened 00660 _lora_time.start(_params.timers.rx_window1_timer, 00661 _params.rx_window1_delay - time_diff); 00662 00663 // start timer after which rx2_window will get opened 00664 _lora_time.start(_params.timers.rx_window2_timer, 00665 _params.rx_window2_delay - time_diff); 00666 00667 // If class C and an Unconfirmed messgae is outgoing, 00668 // this will start a timer which will invoke rx2 would be 00669 // closure handler 00670 if (get_device_class() == CLASS_C) { 00671 _lora_time.start(_rx2_closure_timer_for_class_c, 00672 (_params.rx_window2_delay - time_diff) + 00673 _params.rx_window2_config.window_timeout); 00674 } 00675 00676 // start timer after which ack wait will timeout (for Confirmed messages) 00677 if (_params.is_node_ack_requested) { 00678 _lora_time.start(_params.timers.ack_timeout_timer, 00679 (_params.rx_window2_delay - time_diff) + 00680 _lora_phy->get_ack_timeout()); 00681 } 00682 } else { 00683 _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_OK ; 00684 _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT ; 00685 } 00686 00687 _params.last_channel_idx = _params.channel; 00688 00689 _lora_phy->set_last_tx_done(_params.channel, _is_nwk_joined, timestamp); 00690 00691 _params.timers.aggregated_last_tx_time = timestamp; 00692 00693 _mac_commands.clear_command_buffer(); 00694 } 00695 00696 void LoRaMac::on_radio_rx_done(const uint8_t *const payload, uint16_t size, 00697 int16_t rssi, int8_t snr) 00698 { 00699 if (_device_class == CLASS_C && !_continuous_rx2_window_open) { 00700 _lora_time.stop(_rx2_closure_timer_for_class_c); 00701 open_rx2_window(); 00702 } else if (_device_class != CLASS_C){ 00703 _lora_time.stop(_params.timers.rx_window1_timer); 00704 _lora_phy->put_radio_to_sleep(); 00705 } 00706 00707 loramac_mhdr_t mac_hdr; 00708 uint8_t pos = 0; 00709 mac_hdr.value = payload[pos++]; 00710 00711 switch (mac_hdr.bits.mtype ) { 00712 00713 case FRAME_TYPE_JOIN_ACCEPT : 00714 00715 if (nwk_joined()) { 00716 _mlme_confirmation.pending = false; 00717 return; 00718 } else { 00719 handle_join_accept_frame(payload, size); 00720 _mlme_confirmation.pending = true; 00721 } 00722 00723 break; 00724 00725 case FRAME_TYPE_DATA_UNCONFIRMED_DOWN : 00726 case FRAME_TYPE_DATA_CONFIRMED_DOWN : 00727 case FRAME_TYPE_PROPRIETARY : 00728 00729 handle_data_frame(payload, size, pos, mac_hdr.bits.mtype , rssi, snr); 00730 00731 break; 00732 00733 default: 00734 break; 00735 } 00736 } 00737 00738 void LoRaMac::on_radio_tx_timeout(void) 00739 { 00740 _lora_time.stop(_params.timers.rx_window1_timer); 00741 _lora_time.stop(_params.timers.rx_window2_timer); 00742 _lora_time.stop(_rx2_closure_timer_for_class_c); 00743 _lora_time.stop(_params.timers.ack_timeout_timer); 00744 00745 if (_device_class == CLASS_C) { 00746 open_rx2_window(); 00747 } else { 00748 _lora_phy->put_radio_to_sleep(); 00749 } 00750 00751 _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ; 00752 _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ; 00753 00754 _mac_commands.clear_command_buffer(); 00755 00756 if (_mcps_confirmation.req_type == MCPS_CONFIRMED ) { 00757 _mcps_confirmation.nb_retries = _params.ack_timeout_retry_counter; 00758 } else { 00759 _mcps_confirmation.nb_retries = _params.ul_nb_rep_counter; 00760 } 00761 00762 _mcps_confirmation.ack_received = false; 00763 _mcps_confirmation.tx_toa = 0; 00764 } 00765 00766 void LoRaMac::on_radio_rx_timeout(bool is_timeout) 00767 { 00768 if (_device_class == CLASS_A) { 00769 _lora_phy->put_radio_to_sleep(); 00770 } 00771 00772 if (_params.rx_slot == RX_SLOT_WIN_1 ) { 00773 if (_params.is_node_ack_requested == true) { 00774 _mcps_confirmation.status = is_timeout ? 00775 LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT : 00776 LORAMAC_EVENT_INFO_STATUS_RX1_ERROR ; 00777 } 00778 _mlme_confirmation.status = is_timeout ? 00779 LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT : 00780 LORAMAC_EVENT_INFO_STATUS_RX1_ERROR ; 00781 00782 if (_device_class != CLASS_C) { 00783 if (_lora_time.get_elapsed_time(_params.timers.aggregated_last_tx_time) >= _params.rx_window2_delay) { 00784 _lora_time.stop(_params.timers.rx_window2_timer); 00785 } 00786 } 00787 } else { 00788 if (_params.is_node_ack_requested == true) { 00789 _mcps_confirmation.status = is_timeout ? 00790 LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT : 00791 LORAMAC_EVENT_INFO_STATUS_RX2_ERROR ; 00792 } 00793 00794 _mlme_confirmation.status = is_timeout ? 00795 LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT : 00796 LORAMAC_EVENT_INFO_STATUS_RX2_ERROR ; 00797 } 00798 } 00799 00800 bool LoRaMac::continue_joining_process() 00801 { 00802 if (_params.join_request_trial_counter >= _params.max_join_request_trials) { 00803 return false; 00804 } 00805 00806 // Schedule a retry 00807 if (handle_retransmission() != LORAWAN_STATUS_CONNECT_IN_PROGRESS) { 00808 return false; 00809 } 00810 00811 return true; 00812 } 00813 00814 bool LoRaMac::continue_sending_process() 00815 { 00816 if (_params.ack_timeout_retry_counter > _params.max_ack_timeout_retries) { 00817 _lora_time.stop(_params.timers.ack_timeout_timer); 00818 return false; 00819 } 00820 00821 // retransmission will be handled in on_ack_timeout() whence the ACK timeout 00822 // gets fired 00823 return true; 00824 } 00825 00826 lorawan_status_t LoRaMac::send_join_request() 00827 { 00828 lorawan_status_t status = LORAWAN_STATUS_OK; 00829 loramac_mhdr_t mac_hdr; 00830 loramac_frame_ctrl_t fctrl; 00831 00832 _params.sys_params.channel_data_rate = 00833 _lora_phy->get_alternate_DR(_params.join_request_trial_counter + 1); 00834 00835 mac_hdr.value = 0; 00836 mac_hdr.bits.mtype = FRAME_TYPE_JOIN_REQ ; 00837 00838 fctrl.value = 0; 00839 fctrl.bits.adr = _params.sys_params.adr_on; 00840 _params.is_last_tx_join_request = true; 00841 00842 /* In case of join request retransmissions, the stack must prepare 00843 * the frame again, because the network server keeps track of the random 00844 * LoRaMacDevNonce values to prevent reply attacks. */ 00845 status = prepare_frame(&mac_hdr, &fctrl, 0, NULL, 0); 00846 00847 if (status == LORAWAN_STATUS_OK) { 00848 if (schedule_tx() == LORAWAN_STATUS_OK) { 00849 status = LORAWAN_STATUS_CONNECT_IN_PROGRESS; 00850 } 00851 } else { 00852 tr_error("Couldn't send a JoinRequest: error %d", status); 00853 } 00854 00855 return status; 00856 } 00857 00858 /** 00859 * This function handles retransmission of failed or unacknowledged 00860 * outgoing traffic 00861 */ 00862 lorawan_status_t LoRaMac::handle_retransmission() 00863 { 00864 if (!nwk_joined() && (_mlme_confirmation.req_type == MLME_JOIN )) { 00865 return send_join_request(); 00866 } 00867 00868 return schedule_tx(); 00869 } 00870 00871 /** 00872 * This function is called when the backoff_timer gets fired. 00873 * It is used for re-scheduling an unsent packet in the pipe. This packet 00874 * can be a Join Request or any other data packet. 00875 */ 00876 void LoRaMac::on_backoff_timer_expiry(void) 00877 { 00878 Lock lock(*this); 00879 00880 _lora_time.stop(_params.timers.backoff_timer); 00881 00882 if ((schedule_tx() != LORAWAN_STATUS_OK) && nwk_joined()) { 00883 _scheduling_failure_handler.call(); 00884 } 00885 } 00886 00887 void LoRaMac::open_rx1_window(void) 00888 { 00889 Lock lock(*this); 00890 _continuous_rx2_window_open = false; 00891 _lora_time.stop(_params.timers.rx_window1_timer); 00892 _params.rx_slot = RX_SLOT_WIN_1 ; 00893 00894 _params.rx_window1_config.channel = _params.channel; 00895 _params.rx_window1_config.dr_offset = _params.sys_params.rx1_dr_offset; 00896 _params.rx_window1_config.dl_dwell_time = _params.sys_params.downlink_dwell_time; 00897 _params.rx_window1_config.is_repeater_supported = _params.is_repeater_supported; 00898 _params.rx_window1_config.is_rx_continuous = false; 00899 _params.rx_window1_config.rx_slot = _params.rx_slot; 00900 00901 if (_device_class == CLASS_C) { 00902 _lora_phy->put_radio_to_standby(); 00903 } 00904 00905 _mcps_indication.rx_datarate = _params.rx_window1_config.datarate; 00906 00907 _lora_phy->rx_config(&_params.rx_window1_config); 00908 _lora_phy->handle_receive(); 00909 00910 tr_debug("RX1 slot open, Freq = %lu", _params.rx_window1_config.frequency); 00911 } 00912 00913 void LoRaMac::open_rx2_window() 00914 { 00915 Lock lock(*this); 00916 _continuous_rx2_window_open = true; 00917 _lora_time.stop(_params.timers.rx_window2_timer); 00918 00919 _params.rx_window2_config.channel = _params.channel; 00920 _params.rx_window2_config.frequency = _params.sys_params.rx2_channel.frequency; 00921 _params.rx_window2_config.dl_dwell_time = _params.sys_params.downlink_dwell_time; 00922 _params.rx_window2_config.is_repeater_supported = _params.is_repeater_supported; 00923 00924 if (get_device_class() == CLASS_C) { 00925 _params.rx_window2_config.is_rx_continuous = true; 00926 } else { 00927 _params.rx_window2_config.is_rx_continuous = false; 00928 } 00929 00930 _params.rx_window2_config.rx_slot = _params.rx_window2_config.is_rx_continuous ? 00931 RX_SLOT_WIN_CLASS_C : RX_SLOT_WIN_2 ; 00932 00933 _mcps_indication.rx_datarate = _params.rx_window2_config.datarate; 00934 00935 _lora_phy->rx_config(&_params.rx_window2_config); 00936 _lora_phy->handle_receive(); 00937 _params.rx_slot = _params.rx_window2_config.rx_slot; 00938 00939 tr_debug("RX2 slot open, Freq = %lu", _params.rx_window2_config.frequency); 00940 } 00941 00942 void LoRaMac::on_ack_timeout_timer_event(void) 00943 { 00944 Lock lock(*this); 00945 00946 if (_params.ack_timeout_retry_counter > _params.max_ack_timeout_retries) { 00947 return; 00948 } 00949 00950 tr_debug("ACK_TIMEOUT Elapses, Retrying ..."); 00951 _lora_time.stop(_params.timers.ack_timeout_timer); 00952 00953 // reduce data rate on every 2nd attempt if and only if the 00954 // ADR is on 00955 if ((_params.ack_timeout_retry_counter % 2) 00956 && (_params.sys_params.adr_on)) { 00957 tr_debug("Trading datarate for range"); 00958 _params.sys_params.channel_data_rate = _lora_phy->get_next_lower_tx_datarate(_params.sys_params.channel_data_rate); 00959 } 00960 00961 _mcps_confirmation.nb_retries = _params.ack_timeout_retry_counter; 00962 00963 00964 // Schedule a retry 00965 lorawan_status_t status = handle_retransmission(); 00966 00967 if (status == LORAWAN_STATUS_NO_CHANNEL_FOUND || 00968 status == LORAWAN_STATUS_NO_FREE_CHANNEL_FOUND) { 00969 // In a case when enabled channels are not found, PHY layer 00970 // resorts to default channels. Next attempt should go forward as the 00971 // default channels are always available if there is a base station in the 00972 // vicinity. Otherwise something is wrong with the stack, we should assert 00973 // here 00974 _mac_commands.clear_command_buffer(); 00975 _params.is_node_ack_requested = false; 00976 _mcps_confirmation.ack_received = false; 00977 _mcps_confirmation.nb_retries = _params.ack_timeout_retry_counter; 00978 00979 // For the next attempt we need to make sure that we do not incur length error 00980 // which would mean that the datarate changed during retransmissions and 00981 // the original packet doesn't fit into allowed payload buffer anymore. 00982 status = handle_retransmission(); 00983 00984 if (status == LORAWAN_STATUS_LENGTH_ERROR) { 00985 _scheduling_failure_handler.call(); 00986 return; 00987 } 00988 00989 // if we did not incur a length error and still the status is not OK, 00990 // it is a critical failure 00991 status = handle_retransmission(); 00992 MBED_ASSERT(status == LORAWAN_STATUS_OK); 00993 (void) status; 00994 } else if (status != LORAWAN_STATUS_OK) { 00995 _scheduling_failure_handler.call(); 00996 return; 00997 } 00998 00999 _params.ack_timeout_retry_counter++; 01000 } 01001 01002 bool LoRaMac::validate_payload_length(uint16_t length, 01003 int8_t datarate, 01004 uint8_t fopts_len) 01005 { 01006 uint16_t max_value = 0; 01007 uint16_t payloadSize = 0; 01008 01009 max_value = _lora_phy->get_max_payload(datarate, _params.is_repeater_supported); 01010 01011 // Calculate the resulting payload size 01012 payloadSize = (length + fopts_len); 01013 01014 // Validation of the application payload size 01015 if ((payloadSize <= max_value) && 01016 (payloadSize <= LORAMAC_PHY_MAXPAYLOAD)) { 01017 return true; 01018 } 01019 return false; 01020 } 01021 01022 void LoRaMac::set_mlme_schedule_ul_indication(void) 01023 { 01024 _mlme_indication.indication_type = MLME_SCHEDULE_UPLINK ; 01025 _mlme_indication.pending = true; 01026 } 01027 01028 // This is not actual transmission. It just schedules a message in response 01029 // to MCPS request 01030 lorawan_status_t LoRaMac::send(loramac_mhdr_t *machdr, const uint8_t fport, 01031 const void *fbuffer, uint16_t fbuffer_size) 01032 { 01033 loramac_frame_ctrl_t fctrl; 01034 01035 fctrl.value = 0; 01036 fctrl.bits.fopts_len = 0; 01037 fctrl.bits.fpending = 0; 01038 fctrl.bits.ack = false; 01039 fctrl.bits.adr_ack_req = false; 01040 fctrl.bits.adr = _params.sys_params.adr_on; 01041 01042 lorawan_status_t status = prepare_frame(machdr, &fctrl, fport, fbuffer, 01043 fbuffer_size); 01044 01045 if (status != LORAWAN_STATUS_OK) { 01046 return status; 01047 } 01048 01049 // Reset confirm parameters 01050 _mcps_confirmation.nb_retries = 0; 01051 _mcps_confirmation.ack_received = false; 01052 _mcps_confirmation.ul_frame_counter = _params.ul_frame_counter; 01053 01054 status = schedule_tx(); 01055 01056 return status; 01057 } 01058 01059 int LoRaMac::get_backoff_timer_event_id(void) 01060 { 01061 return _params.timers.backoff_timer.timer_id; 01062 } 01063 01064 lorawan_status_t LoRaMac::clear_tx_pipe(void) 01065 { 01066 if (!_can_cancel_tx) { 01067 return LORAWAN_STATUS_BUSY; 01068 } 01069 01070 // check if the event is not already queued 01071 const int id = get_backoff_timer_event_id(); 01072 01073 if (id == 0) { 01074 // No queued send request 01075 return LORAWAN_STATUS_NO_OP; 01076 } 01077 01078 if (_ev_queue->time_left(id) > 0) { 01079 _lora_time.stop(_params.timers.backoff_timer); 01080 _lora_time.stop(_params.timers.ack_timeout_timer); 01081 memset(_params.tx_buffer, 0, sizeof _params.tx_buffer); 01082 _params.tx_buffer_len = 0; 01083 reset_ongoing_tx(true); 01084 tr_debug("Sending Cancelled"); 01085 return LORAWAN_STATUS_OK; 01086 } else { 01087 // Event is already being dispatched so it cannot be cancelled 01088 return LORAWAN_STATUS_BUSY; 01089 } 01090 } 01091 01092 lorawan_status_t LoRaMac::schedule_tx() 01093 { 01094 channel_selection_params_t next_channel; 01095 lorawan_time_t backoff_time = 0; 01096 uint8_t fopts_len = 0; 01097 01098 if (_params.sys_params.max_duty_cycle == 255) { 01099 return LORAWAN_STATUS_DEVICE_OFF; 01100 } 01101 01102 if (_params.sys_params.max_duty_cycle == 0) { 01103 _params.timers.aggregated_timeoff = 0; 01104 } 01105 01106 if (MBED_CONF_LORA_DUTY_CYCLE_ON && _lora_phy->verify_duty_cycle(true)) { 01107 _params.is_dutycycle_on = true; 01108 } else { 01109 _params.is_dutycycle_on = false; 01110 } 01111 01112 calculate_backOff(_params.last_channel_idx); 01113 01114 next_channel.aggregate_timeoff = _params.timers.aggregated_timeoff; 01115 next_channel.current_datarate = _params.sys_params.channel_data_rate; 01116 next_channel.dc_enabled = _params.is_dutycycle_on; 01117 next_channel.joined = _is_nwk_joined; 01118 next_channel.last_aggregate_tx_time = _params.timers.aggregated_last_tx_time; 01119 01120 lorawan_status_t status = _lora_phy->set_next_channel(&next_channel, 01121 &_params.channel, 01122 &backoff_time, 01123 &_params.timers.aggregated_timeoff); 01124 01125 switch (status) { 01126 case LORAWAN_STATUS_NO_CHANNEL_FOUND: 01127 case LORAWAN_STATUS_NO_FREE_CHANNEL_FOUND: 01128 _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR ; 01129 return status; 01130 case LORAWAN_STATUS_DUTYCYCLE_RESTRICTED: 01131 if (backoff_time != 0) { 01132 tr_debug("DC enforced: Transmitting in %lu ms", backoff_time); 01133 _can_cancel_tx = true; 01134 _lora_time.start(_params.timers.backoff_timer, backoff_time); 01135 } 01136 return LORAWAN_STATUS_OK; 01137 default: 01138 break; 01139 } 01140 01141 uint8_t rx1_dr = _lora_phy->apply_DR_offset(_params.sys_params.channel_data_rate, 01142 _params.sys_params.rx1_dr_offset); 01143 01144 tr_debug("TX: Channel=%d, TX DR=%d, RX1 DR=%d", 01145 _params.channel, _params.sys_params.channel_data_rate, rx1_dr); 01146 01147 01148 _lora_phy->compute_rx_win_params(rx1_dr, MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH, 01149 MBED_CONF_LORA_MAX_SYS_RX_ERROR, 01150 &_params.rx_window1_config); 01151 01152 _lora_phy->compute_rx_win_params(_params.sys_params.rx2_channel.datarate, 01153 MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH, 01154 MBED_CONF_LORA_MAX_SYS_RX_ERROR, 01155 &_params.rx_window2_config); 01156 01157 if (!_is_nwk_joined) { 01158 _params.rx_window1_delay = _params.sys_params.join_accept_delay1 01159 + _params.rx_window1_config.window_offset; 01160 _params.rx_window2_delay = _params.sys_params.join_accept_delay2 01161 + _params.rx_window2_config.window_offset; 01162 } else { 01163 01164 // if the outgoing message is a proprietary message, it doesn't include any 01165 // standard message formatting except port and MHDR. 01166 if (_ongoing_tx_msg.type == MCPS_PROPRIETARY ) { 01167 fopts_len = 0; 01168 } else { 01169 fopts_len = _mac_commands.get_mac_cmd_length() + _mac_commands.get_repeat_commands_length(); 01170 } 01171 01172 // A check was performed for validity of FRMPayload in ::prepare_ongoing_tx() API. 01173 // However, owing to the asynch nature of the send() API, we should check the 01174 // validity again, as datarate may have changed since we last attempted to transmit. 01175 if (validate_payload_length(_ongoing_tx_msg.f_buffer_size, 01176 _params.sys_params.channel_data_rate, 01177 fopts_len) == false) { 01178 tr_error("Allowed FRMPayload = %d, FRMPayload = %d, MAC commands pending = %d", 01179 _lora_phy->get_max_payload(_params.sys_params.channel_data_rate, 01180 _params.is_repeater_supported), 01181 _ongoing_tx_msg.f_buffer_size, fopts_len); 01182 return LORAWAN_STATUS_LENGTH_ERROR; 01183 } 01184 _params.rx_window1_delay = _params.sys_params.recv_delay1 01185 + _params.rx_window1_config.window_offset; 01186 _params.rx_window2_delay = _params.sys_params.recv_delay2 01187 + _params.rx_window2_config.window_offset; 01188 } 01189 01190 // handle the ack to the server here so that if the sending was cancelled 01191 // by the user in the backoff period, we would still ack the previous frame. 01192 if (_params.is_srv_ack_requested) { 01193 _params.is_srv_ack_requested = false; 01194 } 01195 01196 _can_cancel_tx = false; 01197 return send_frame_on_channel(_params.channel); 01198 } 01199 01200 void LoRaMac::calculate_backOff(uint8_t channel) 01201 { 01202 lorawan_time_t elapsed_time = _lora_time.get_elapsed_time(_params.timers.mac_init_time); 01203 _lora_phy->calculate_backoff(_is_nwk_joined, _params.is_last_tx_join_request, _params.is_dutycycle_on, 01204 channel, elapsed_time, _params.timers.tx_toa); 01205 01206 // Update aggregated time-off. This must be an assignment and no incremental 01207 // update as we do only calculate the time-off based on the last transmission 01208 _params.timers.aggregated_timeoff = (_params.timers.tx_toa * _params.sys_params.aggregated_duty_cycle 01209 - _params.timers.tx_toa); 01210 } 01211 01212 void LoRaMac::reset_mac_parameters(void) 01213 { 01214 _is_nwk_joined = false; 01215 01216 _params.ul_frame_counter = 0; 01217 _params.dl_frame_counter = 0; 01218 _params.adr_ack_counter = 0; 01219 01220 _params.ul_nb_rep_counter = 0; 01221 01222 _params.max_ack_timeout_retries = 1; 01223 _params.ack_timeout_retry_counter = 1; 01224 _params.is_ack_retry_timeout_expired = false; 01225 01226 _params.sys_params.max_duty_cycle = 0; 01227 _params.sys_params.aggregated_duty_cycle = 1; 01228 01229 _mac_commands.clear_command_buffer(); 01230 _mac_commands.clear_repeat_buffer(); 01231 01232 _params.is_rx_window_enabled = true; 01233 01234 _lora_phy->reset_to_default_values(&_params, false); 01235 01236 _params.is_node_ack_requested = false; 01237 _params.is_srv_ack_requested = false; 01238 01239 multicast_params_t *cur = _params.multicast_channels; 01240 while (cur != NULL) { 01241 cur->dl_frame_counter = 0; 01242 cur = cur->next ; 01243 } 01244 _params.channel = 0; 01245 _params.last_channel_idx = _params.channel; 01246 } 01247 01248 uint8_t LoRaMac::get_default_tx_datarate() 01249 { 01250 return _lora_phy->get_default_tx_datarate(); 01251 } 01252 01253 void LoRaMac::enable_adaptive_datarate(bool adr_enabled) 01254 { 01255 _params.sys_params.adr_on = adr_enabled; 01256 } 01257 01258 lorawan_status_t LoRaMac::set_channel_data_rate(uint8_t data_rate) 01259 { 01260 if (_params.sys_params.adr_on) { 01261 tr_error("Cannot set data rate. Please turn off ADR first."); 01262 return LORAWAN_STATUS_PARAMETER_INVALID; 01263 } 01264 01265 if (_lora_phy->verify_tx_datarate(data_rate, false) == true) { 01266 _params.sys_params.channel_data_rate = data_rate; 01267 } else { 01268 return LORAWAN_STATUS_PARAMETER_INVALID; 01269 } 01270 01271 return LORAWAN_STATUS_OK; 01272 } 01273 01274 bool LoRaMac::tx_ongoing() 01275 { 01276 return _ongoing_tx_msg.tx_ongoing; 01277 } 01278 01279 void LoRaMac::set_tx_ongoing(bool ongoing) 01280 { 01281 _can_cancel_tx = true; 01282 _ongoing_tx_msg.tx_ongoing = ongoing; 01283 } 01284 01285 void LoRaMac::reset_ongoing_tx(bool reset_pending) 01286 { 01287 _ongoing_tx_msg.tx_ongoing = false; 01288 memset(_ongoing_tx_msg.f_buffer, 0, MBED_CONF_LORA_TX_MAX_SIZE); 01289 _ongoing_tx_msg.f_buffer_size = 0; 01290 if (reset_pending) { 01291 _ongoing_tx_msg.pending_size = 0; 01292 } 01293 } 01294 01295 int16_t LoRaMac::prepare_ongoing_tx(const uint8_t port, 01296 const uint8_t *const data, 01297 uint16_t length, 01298 uint8_t flags, 01299 uint8_t num_retries) 01300 { 01301 _ongoing_tx_msg.port = port; 01302 uint8_t max_possible_size = 0; 01303 uint8_t fopts_len = _mac_commands.get_mac_cmd_length() 01304 + _mac_commands.get_repeat_commands_length(); 01305 01306 // Handles unconfirmed messages 01307 if (flags & MSG_UNCONFIRMED_FLAG) { 01308 _ongoing_tx_msg.type = MCPS_UNCONFIRMED ; 01309 _ongoing_tx_msg.fport = port; 01310 _ongoing_tx_msg.nb_trials = 1; 01311 } 01312 01313 // Handles confirmed messages 01314 if (flags & MSG_CONFIRMED_FLAG) { 01315 _ongoing_tx_msg.type = MCPS_CONFIRMED ; 01316 _ongoing_tx_msg.fport = port; 01317 _ongoing_tx_msg.nb_trials = num_retries; 01318 } 01319 01320 // Handles proprietary messages 01321 if (flags & MSG_PROPRIETARY_FLAG) { 01322 _ongoing_tx_msg.type = MCPS_PROPRIETARY ; 01323 _ongoing_tx_msg.fport = port; 01324 _ongoing_tx_msg.nb_trials = _params.sys_params.nb_trans; 01325 // a proprietary frame only includes an MHDR field which contains MTYPE field. 01326 // Everything else is at the discretion of the implementer 01327 fopts_len = 0; 01328 } 01329 01330 max_possible_size = get_max_possible_tx_size(fopts_len); 01331 01332 if (max_possible_size > MBED_CONF_LORA_TX_MAX_SIZE) { 01333 max_possible_size = MBED_CONF_LORA_TX_MAX_SIZE; 01334 } 01335 01336 if (max_possible_size < length) { 01337 tr_info("Cannot transmit %d bytes. Possible TX Size is %d bytes", 01338 length, max_possible_size); 01339 01340 _ongoing_tx_msg.pending_size = length - max_possible_size; 01341 _ongoing_tx_msg.f_buffer_size = max_possible_size; 01342 memcpy(_ongoing_tx_msg.f_buffer, data, _ongoing_tx_msg.f_buffer_size); 01343 } else { 01344 _ongoing_tx_msg.f_buffer_size = length; 01345 _ongoing_tx_msg.pending_size = 0; 01346 if (length > 0) { 01347 memcpy(_ongoing_tx_msg.f_buffer, data, length); 01348 } 01349 } 01350 01351 tr_info("RTS = %u bytes, PEND = %u, Port: %u", 01352 _ongoing_tx_msg.f_buffer_size, _ongoing_tx_msg.pending_size, 01353 _ongoing_tx_msg.fport); 01354 01355 return _ongoing_tx_msg.f_buffer_size; 01356 } 01357 01358 lorawan_status_t LoRaMac::send_ongoing_tx() 01359 { 01360 lorawan_status_t status; 01361 _params.is_last_tx_join_request = false; 01362 int8_t datarate = _params.sys_params.channel_data_rate; 01363 01364 // This prohibits the data rate going below the minimum value. 01365 datarate = MAX(datarate, (int8_t)_lora_phy->get_minimum_tx_datarate()); 01366 01367 loramac_mhdr_t machdr; 01368 machdr.value = 0; 01369 01370 reset_mcps_confirmation(); 01371 01372 _params.ack_timeout_retry_counter = 1; 01373 _params.max_ack_timeout_retries = 1; 01374 01375 if (MCPS_UNCONFIRMED == _ongoing_tx_msg.type) { 01376 machdr.bits.mtype = FRAME_TYPE_DATA_UNCONFIRMED_UP ; 01377 } else if (_ongoing_tx_msg.type == MCPS_CONFIRMED ) { 01378 machdr.bits.mtype = FRAME_TYPE_DATA_CONFIRMED_UP ; 01379 _params.max_ack_timeout_retries = _ongoing_tx_msg.nb_trials; 01380 } else if (_ongoing_tx_msg.type == MCPS_PROPRIETARY ) { 01381 machdr.bits.mtype = FRAME_TYPE_PROPRIETARY ; 01382 } else { 01383 return LORAWAN_STATUS_SERVICE_UNKNOWN; 01384 } 01385 01386 if (_params.sys_params.adr_on == false) { 01387 if (_lora_phy->verify_tx_datarate(datarate, false) == true) { 01388 _params.sys_params.channel_data_rate = datarate; 01389 } else { 01390 return LORAWAN_STATUS_PARAMETER_INVALID; 01391 } 01392 } 01393 01394 status = send(&machdr, _ongoing_tx_msg.fport, _ongoing_tx_msg.f_buffer, 01395 _ongoing_tx_msg.f_buffer_size); 01396 if (status == LORAWAN_STATUS_OK) { 01397 _mcps_confirmation.req_type = _ongoing_tx_msg.type; 01398 } 01399 01400 return status; 01401 } 01402 01403 device_class_t LoRaMac::get_device_class() const 01404 { 01405 return _device_class; 01406 } 01407 01408 void LoRaMac::set_device_class(const device_class_t &device_class, 01409 mbed::Callback<void(void)>rx2_would_be_closure_handler) 01410 { 01411 _device_class = device_class; 01412 _rx2_would_be_closure_for_class_c = rx2_would_be_closure_handler; 01413 01414 _lora_time.init(_rx2_closure_timer_for_class_c, _rx2_would_be_closure_for_class_c); 01415 01416 if (CLASS_A == _device_class) { 01417 tr_debug("Changing device class to -> CLASS_A"); 01418 _lora_phy->put_radio_to_sleep(); 01419 } else if (CLASS_C == _device_class) { 01420 _params.is_node_ack_requested = false; 01421 _lora_phy->put_radio_to_sleep(); 01422 _lora_phy->compute_rx_win_params(_params.sys_params.rx2_channel.datarate, 01423 MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH, 01424 MBED_CONF_LORA_MAX_SYS_RX_ERROR, 01425 &_params.rx_window2_config); 01426 } 01427 01428 if (CLASS_C == _device_class) { 01429 tr_debug("Changing device class to -> CLASS_C"); 01430 open_rx2_window(); 01431 } 01432 } 01433 01434 void LoRaMac::setup_link_check_request() 01435 { 01436 reset_mlme_confirmation(); 01437 01438 _mlme_confirmation.req_type = MLME_LINK_CHECK ; 01439 _mlme_confirmation.pending = true; 01440 _mac_commands.add_link_check_req(); 01441 } 01442 01443 lorawan_status_t LoRaMac::prepare_join(const lorawan_connect_t *params, bool is_otaa) 01444 { 01445 if (params) { 01446 if (is_otaa) { 01447 if ((params->connection_u.otaa.dev_eui == NULL) 01448 || (params->connection_u.otaa.app_eui == NULL) 01449 || (params->connection_u.otaa.app_key == NULL) 01450 || (params->connection_u.otaa.nb_trials == 0)) { 01451 return LORAWAN_STATUS_PARAMETER_INVALID; 01452 } 01453 _params.keys.dev_eui = params->connection_u.otaa.dev_eui; 01454 _params.keys.app_eui = params->connection_u.otaa.app_eui; 01455 _params.keys.app_key = params->connection_u.otaa.app_key; 01456 _params.max_join_request_trials = params->connection_u.otaa.nb_trials; 01457 01458 if (!_lora_phy->verify_nb_join_trials(params->connection_u.otaa.nb_trials)) { 01459 // Value not supported, get default 01460 _params.max_join_request_trials = MBED_CONF_LORA_NB_TRIALS; 01461 } 01462 // Reset variable JoinRequestTrials 01463 _params.join_request_trial_counter = 0; 01464 01465 reset_mac_parameters(); 01466 01467 _params.sys_params.channel_data_rate = 01468 _lora_phy->get_alternate_DR(_params.join_request_trial_counter + 1); 01469 } else { 01470 if ((params->connection_u.abp.dev_addr == 0) 01471 || (params->connection_u.abp.nwk_id == 0) 01472 || (params->connection_u.abp.nwk_skey == NULL) 01473 || (params->connection_u.abp.app_skey == NULL)) { 01474 return LORAWAN_STATUS_PARAMETER_INVALID; 01475 } 01476 01477 _params.net_id = params->connection_u.abp.nwk_id; 01478 _params.dev_addr = params->connection_u.abp.dev_addr; 01479 01480 memcpy(_params.keys.nwk_skey, params->connection_u.abp.nwk_skey, 01481 sizeof(_params.keys.nwk_skey)); 01482 01483 memcpy(_params.keys.app_skey, params->connection_u.abp.app_skey, 01484 sizeof(_params.keys.app_skey)); 01485 } 01486 } else { 01487 #if MBED_CONF_LORA_OVER_THE_AIR_ACTIVATION 01488 const static uint8_t dev_eui[] = MBED_CONF_LORA_DEVICE_EUI; 01489 const static uint8_t app_eui[] = MBED_CONF_LORA_APPLICATION_EUI; 01490 const static uint8_t app_key[] = MBED_CONF_LORA_APPLICATION_KEY; 01491 01492 _params.keys.app_eui = const_cast<uint8_t *>(app_eui); 01493 _params.keys.dev_eui = const_cast<uint8_t *>(dev_eui); 01494 _params.keys.app_key = const_cast<uint8_t *>(app_key); 01495 _params.max_join_request_trials = MBED_CONF_LORA_NB_TRIALS; 01496 01497 // Reset variable JoinRequestTrials 01498 _params.join_request_trial_counter = 0; 01499 01500 reset_mac_parameters(); 01501 01502 _params.sys_params.channel_data_rate = 01503 _lora_phy->get_alternate_DR(_params.join_request_trial_counter + 1); 01504 01505 #else 01506 const static uint8_t nwk_skey[] = MBED_CONF_LORA_NWKSKEY; 01507 const static uint8_t app_skey[] = MBED_CONF_LORA_APPSKEY; 01508 01509 _params.net_id = (MBED_CONF_LORA_DEVICE_ADDRESS & LORAWAN_NETWORK_ID_MASK) >> 25; 01510 _params.dev_addr = MBED_CONF_LORA_DEVICE_ADDRESS; 01511 01512 memcpy(_params.keys.nwk_skey, nwk_skey, sizeof(_params.keys.nwk_skey)); 01513 01514 memcpy(_params.keys.app_skey, app_skey, sizeof(_params.keys.app_skey)); 01515 #endif 01516 } 01517 01518 return LORAWAN_STATUS_OK; 01519 } 01520 01521 lorawan_status_t LoRaMac::join(bool is_otaa) 01522 { 01523 if (!is_otaa) { 01524 set_nwk_joined(true); 01525 return LORAWAN_STATUS_OK; 01526 } 01527 01528 reset_mlme_confirmation(); 01529 _mlme_confirmation.req_type = MLME_JOIN ; 01530 01531 return send_join_request(); 01532 } 01533 01534 static void memcpy_convert_endianess(uint8_t *dst, 01535 const uint8_t *src, 01536 uint16_t size) 01537 { 01538 dst = dst + (size - 1); 01539 while (size--) { 01540 *dst-- = *src++; 01541 } 01542 } 01543 01544 lorawan_status_t LoRaMac::prepare_frame(loramac_mhdr_t *machdr, 01545 loramac_frame_ctrl_t *fctrl, 01546 const uint8_t fport, 01547 const void *fbuffer, 01548 uint16_t fbuffer_size) 01549 { 01550 uint16_t i; 01551 uint8_t pkt_header_len = 0; 01552 uint32_t mic = 0; 01553 const void *payload = fbuffer; 01554 uint8_t frame_port = fport; 01555 lorawan_status_t status = LORAWAN_STATUS_OK; 01556 01557 _params.tx_buffer_len = 0; 01558 01559 _params.is_node_ack_requested = false; 01560 01561 if (fbuffer == NULL) { 01562 fbuffer_size = 0; 01563 } 01564 01565 _params.tx_buffer_len = fbuffer_size; 01566 01567 _params.tx_buffer[pkt_header_len++] = machdr->value ; 01568 01569 switch (machdr->bits.mtype ) { 01570 01571 case FRAME_TYPE_JOIN_REQ : 01572 01573 _params.tx_buffer_len = pkt_header_len; 01574 memcpy_convert_endianess(_params.tx_buffer + _params.tx_buffer_len, 01575 _params.keys.app_eui, 8); 01576 _params.tx_buffer_len += 8; 01577 memcpy_convert_endianess(_params.tx_buffer + _params.tx_buffer_len, 01578 _params.keys.dev_eui, 8); 01579 _params.tx_buffer_len += 8; 01580 01581 _params.dev_nonce = _lora_phy->get_radio_rng(); 01582 01583 _params.tx_buffer[_params.tx_buffer_len++] = _params.dev_nonce & 0xFF; 01584 _params.tx_buffer[_params.tx_buffer_len++] = (_params.dev_nonce >> 8) & 0xFF; 01585 01586 if (0 != _lora_crypto.compute_join_frame_mic(_params.tx_buffer, 01587 _params.tx_buffer_len & 0xFF, 01588 _params.keys.app_key, 01589 APPKEY_KEY_LENGTH, 01590 &mic)) { 01591 return LORAWAN_STATUS_CRYPTO_FAIL; 01592 } 01593 01594 _params.tx_buffer[_params.tx_buffer_len++] = mic & 0xFF; 01595 _params.tx_buffer[_params.tx_buffer_len++] = (mic >> 8) & 0xFF; 01596 _params.tx_buffer[_params.tx_buffer_len++] = (mic >> 16) & 0xFF; 01597 _params.tx_buffer[_params.tx_buffer_len++] = (mic >> 24) & 0xFF; 01598 01599 break; 01600 case FRAME_TYPE_DATA_CONFIRMED_UP : 01601 _params.is_node_ack_requested = true; 01602 //Intentional fallthrough 01603 case FRAME_TYPE_DATA_UNCONFIRMED_UP : { 01604 if (!_is_nwk_joined) { 01605 return LORAWAN_STATUS_NO_NETWORK_JOINED; 01606 } 01607 01608 if (_params.sys_params.adr_on) { 01609 if (_lora_phy->get_next_ADR(true, 01610 _params.sys_params.channel_data_rate, 01611 _params.sys_params.channel_tx_power, 01612 _params.adr_ack_counter)) { 01613 fctrl->bits.adr_ack_req = 1; 01614 } 01615 } 01616 01617 if (_params.is_srv_ack_requested == true) { 01618 tr_debug("Acking to NS"); 01619 fctrl->bits.ack = 1; 01620 } 01621 01622 _params.tx_buffer[pkt_header_len++] = (_params.dev_addr) & 0xFF; 01623 _params.tx_buffer[pkt_header_len++] = (_params.dev_addr >> 8) & 0xFF; 01624 _params.tx_buffer[pkt_header_len++] = (_params.dev_addr >> 16) & 0xFF; 01625 _params.tx_buffer[pkt_header_len++] = (_params.dev_addr >> 24) & 0xFF; 01626 01627 _params.tx_buffer[pkt_header_len++] = fctrl->value ; 01628 01629 _params.tx_buffer[pkt_header_len++] = _params.ul_frame_counter & 0xFF; 01630 _params.tx_buffer[pkt_header_len++] = (_params.ul_frame_counter >> 8) 01631 & 0xFF; 01632 01633 _mac_commands.copy_repeat_commands_to_buffer(); 01634 01635 const uint8_t mac_commands_len = _mac_commands.get_mac_cmd_length(); 01636 01637 if ((payload != NULL) && (_params.tx_buffer_len > 0)) { 01638 if (mac_commands_len <= LORA_MAC_COMMAND_MAX_FOPTS_LENGTH) { 01639 fctrl->bits.fopts_len += mac_commands_len; 01640 01641 // Update FCtrl field with new value of OptionsLength 01642 _params.tx_buffer[0x05] = fctrl->value ; 01643 01644 const uint8_t *buffer = _mac_commands.get_mac_commands_buffer(); 01645 for (i = 0; i < mac_commands_len; i++) { 01646 _params.tx_buffer[pkt_header_len++] = buffer[i]; 01647 } 01648 } else { 01649 _params.tx_buffer_len = mac_commands_len; 01650 payload = _mac_commands.get_mac_commands_buffer(); 01651 frame_port = 0; 01652 } 01653 } else { 01654 if (mac_commands_len > 0) { 01655 _params.tx_buffer_len = mac_commands_len; 01656 payload = _mac_commands.get_mac_commands_buffer(); 01657 frame_port = 0; 01658 } 01659 } 01660 01661 _mac_commands.parse_mac_commands_to_repeat(); 01662 01663 // We always add Port Field. Spec leaves it optional. 01664 _params.tx_buffer[pkt_header_len++] = frame_port; 01665 01666 if ((payload != NULL) && (_params.tx_buffer_len > 0)) { 01667 01668 uint8_t *key = _params.keys.app_skey; 01669 uint32_t key_length = sizeof(_params.keys.app_skey) * 8; 01670 if (frame_port == 0) { 01671 key = _params.keys.nwk_skey; 01672 key_length = sizeof(_params.keys.nwk_skey) * 8; 01673 } 01674 if (0 != _lora_crypto.encrypt_payload((uint8_t *) payload, _params.tx_buffer_len, 01675 key, key_length, 01676 _params.dev_addr, UP_LINK, 01677 _params.ul_frame_counter, 01678 &_params.tx_buffer[pkt_header_len])) { 01679 status = LORAWAN_STATUS_CRYPTO_FAIL; 01680 } 01681 } 01682 01683 _params.tx_buffer_len = pkt_header_len + _params.tx_buffer_len; 01684 01685 if (0 != _lora_crypto.compute_mic(_params.tx_buffer, _params.tx_buffer_len, 01686 _params.keys.nwk_skey, sizeof(_params.keys.nwk_skey) * 8, 01687 _params.dev_addr, 01688 UP_LINK, _params.ul_frame_counter, &mic)) { 01689 status = LORAWAN_STATUS_CRYPTO_FAIL; 01690 } 01691 01692 _params.tx_buffer[_params.tx_buffer_len + 0] = mic & 0xFF; 01693 _params.tx_buffer[_params.tx_buffer_len + 1] = (mic >> 8) & 0xFF; 01694 _params.tx_buffer[_params.tx_buffer_len + 2] = (mic >> 16) & 0xFF; 01695 _params.tx_buffer[_params.tx_buffer_len + 3] = (mic >> 24) & 0xFF; 01696 01697 _params.tx_buffer_len += LORAMAC_MFR_LEN; 01698 } 01699 break; 01700 case FRAME_TYPE_PROPRIETARY : 01701 if ((fbuffer != NULL) && (_params.tx_buffer_len > 0)) { 01702 memcpy(_params.tx_buffer + pkt_header_len, (uint8_t *) fbuffer, 01703 _params.tx_buffer_len); 01704 _params.tx_buffer_len = pkt_header_len + _params.tx_buffer_len; 01705 } 01706 break; 01707 default: 01708 status = LORAWAN_STATUS_SERVICE_UNKNOWN; 01709 } 01710 01711 tr_debug("Frame prepared to send at port %u", frame_port); 01712 01713 return status; 01714 } 01715 01716 lorawan_status_t LoRaMac::send_frame_on_channel(uint8_t channel) 01717 { 01718 tx_config_params_t tx_config; 01719 int8_t tx_power = 0; 01720 01721 tx_config.channel = channel; 01722 tx_config.datarate = _params.sys_params.channel_data_rate; 01723 tx_config.tx_power = _params.sys_params.channel_tx_power; 01724 tx_config.max_eirp = _params.sys_params.max_eirp; 01725 tx_config.antenna_gain = _params.sys_params.antenna_gain; 01726 tx_config.pkt_len = _params.tx_buffer_len; 01727 01728 _lora_phy->tx_config(&tx_config, &tx_power, &_params.timers.tx_toa); 01729 01730 _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR ; 01731 01732 _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR ; 01733 _mcps_confirmation.data_rate = _params.sys_params.channel_data_rate; 01734 _mcps_confirmation.tx_power = tx_power; 01735 _mcps_confirmation.channel = channel; 01736 01737 _mcps_confirmation.tx_toa = _params.timers.tx_toa; 01738 _mlme_confirmation.tx_toa = _params.timers.tx_toa; 01739 01740 if (!_is_nwk_joined) { 01741 _params.join_request_trial_counter++; 01742 } 01743 01744 _lora_phy->handle_send(_params.tx_buffer, _params.tx_buffer_len); 01745 01746 return LORAWAN_STATUS_OK; 01747 } 01748 01749 void LoRaMac::reset_mcps_confirmation() 01750 { 01751 memset((uint8_t *) &_mcps_confirmation, 0, sizeof(_mcps_confirmation)); 01752 _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR ; 01753 } 01754 01755 void LoRaMac::reset_mlme_confirmation() 01756 { 01757 memset((uint8_t *) &_mlme_confirmation, 0, sizeof(_mlme_confirmation)); 01758 _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR ; 01759 } 01760 01761 void LoRaMac::reset_mcps_indication() 01762 { 01763 memset((uint8_t *) &_mcps_indication, 0, sizeof(_mcps_indication)); 01764 _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_ERROR ; 01765 } 01766 01767 lorawan_status_t LoRaMac::initialize(EventQueue *queue, 01768 mbed::Callback<void(void)>scheduling_failure_handler) 01769 { 01770 _lora_time.activate_timer_subsystem(queue); 01771 _lora_phy->initialize(&_lora_time); 01772 01773 _ev_queue = queue; 01774 _scheduling_failure_handler = scheduling_failure_handler; 01775 _rx2_closure_timer_for_class_c.callback = NULL; 01776 _rx2_closure_timer_for_class_c.timer_id = -1; 01777 01778 _channel_plan.activate_channelplan_subsystem(_lora_phy); 01779 01780 _device_class = CLASS_A; 01781 01782 _params.join_request_trial_counter = 0; 01783 _params.max_join_request_trials = 1; 01784 _params.is_repeater_supported = false; 01785 01786 _params.timers.aggregated_last_tx_time = 0; 01787 _params.timers.aggregated_timeoff = 0; 01788 01789 _lora_phy->reset_to_default_values(&_params, true); 01790 _params.sys_params.nb_trans = 1; 01791 01792 reset_mac_parameters(); 01793 01794 srand(_lora_phy->get_radio_rng()); 01795 01796 _params.is_nwk_public = MBED_CONF_LORA_PUBLIC_NETWORK; 01797 _lora_phy->setup_public_network_mode(_params.is_nwk_public); 01798 _lora_phy->put_radio_to_sleep(); 01799 01800 _lora_time.init(_params.timers.backoff_timer, 01801 mbed::callback(this, &LoRaMac::on_backoff_timer_expiry)); 01802 _lora_time.init(_params.timers.rx_window1_timer, 01803 mbed::callback(this, &LoRaMac::open_rx1_window)); 01804 _lora_time.init(_params.timers.rx_window2_timer, 01805 mbed::callback(this, &LoRaMac::open_rx2_window)); 01806 _lora_time.init(_params.timers.ack_timeout_timer, 01807 mbed::callback(this, &LoRaMac::on_ack_timeout_timer_event)); 01808 01809 _params.timers.mac_init_time = _lora_time.get_current_time(); 01810 01811 _params.sys_params.adr_on = MBED_CONF_LORA_ADR_ON; 01812 _params.sys_params.channel_data_rate = _lora_phy->get_default_max_tx_datarate(); 01813 01814 return LORAWAN_STATUS_OK; 01815 } 01816 01817 void LoRaMac::disconnect() 01818 { 01819 _lora_time.stop(_params.timers.backoff_timer); 01820 _lora_time.stop(_params.timers.rx_window1_timer); 01821 _lora_time.stop(_params.timers.rx_window2_timer); 01822 _lora_time.stop(_params.timers.ack_timeout_timer); 01823 01824 _lora_phy->put_radio_to_sleep(); 01825 01826 _is_nwk_joined = false; 01827 _params.is_ack_retry_timeout_expired = false; 01828 _params.is_rx_window_enabled = true; 01829 _params.is_node_ack_requested = false; 01830 _params.is_srv_ack_requested = false; 01831 01832 _mac_commands.clear_command_buffer(); 01833 _mac_commands.clear_repeat_buffer(); 01834 01835 reset_mcps_confirmation(); 01836 reset_mlme_confirmation(); 01837 reset_mcps_indication(); 01838 } 01839 01840 uint8_t LoRaMac::get_max_possible_tx_size(uint8_t fopts_len) 01841 { 01842 uint8_t max_possible_payload_size = 0; 01843 uint8_t allowed_frm_payload_size = 0; 01844 01845 int8_t datarate = _params.sys_params.channel_data_rate; 01846 int8_t tx_power = _params.sys_params.channel_tx_power; 01847 uint32_t adr_ack_counter = _params.adr_ack_counter; 01848 01849 if (_params.sys_params.adr_on) { 01850 // Just query the information. We do not want to apply them into use 01851 // at this point. 01852 _lora_phy->get_next_ADR(false, datarate, tx_power, adr_ack_counter); 01853 } 01854 01855 allowed_frm_payload_size = _lora_phy->get_max_payload(datarate, 01856 _params.is_repeater_supported); 01857 01858 if (allowed_frm_payload_size >= fopts_len) { 01859 max_possible_payload_size = allowed_frm_payload_size - fopts_len; 01860 } else { 01861 max_possible_payload_size = allowed_frm_payload_size; 01862 _mac_commands.clear_command_buffer(); 01863 _mac_commands.clear_repeat_buffer(); 01864 } 01865 01866 return max_possible_payload_size; 01867 } 01868 01869 bool LoRaMac::nwk_joined() 01870 { 01871 return _is_nwk_joined; 01872 } 01873 01874 void LoRaMac::set_nwk_joined(bool joined) 01875 { 01876 _is_nwk_joined = joined; 01877 } 01878 01879 lorawan_status_t LoRaMac::add_channel_plan(const lorawan_channelplan_t &plan) 01880 { 01881 if (tx_ongoing()) { 01882 return LORAWAN_STATUS_BUSY; 01883 } 01884 01885 return _channel_plan.set_plan(plan); 01886 } 01887 01888 lorawan_status_t LoRaMac::remove_channel_plan() 01889 { 01890 if (tx_ongoing()) { 01891 return LORAWAN_STATUS_BUSY; 01892 } 01893 01894 return _channel_plan.remove_plan(); 01895 } 01896 01897 lorawan_status_t LoRaMac::get_channel_plan(lorawan_channelplan_t &plan) 01898 { 01899 return _channel_plan.get_plan(plan, _lora_phy->get_phy_channels()); 01900 } 01901 01902 lorawan_status_t LoRaMac::remove_single_channel(uint8_t id) 01903 { 01904 if (tx_ongoing()) { 01905 return LORAWAN_STATUS_BUSY; 01906 } 01907 01908 return _channel_plan.remove_single_channel(id); 01909 } 01910 01911 lorawan_status_t LoRaMac::multicast_channel_link(multicast_params_t *channel_param) 01912 { 01913 if (channel_param == NULL) { 01914 return LORAWAN_STATUS_PARAMETER_INVALID; 01915 } 01916 if (tx_ongoing()) { 01917 return LORAWAN_STATUS_BUSY; 01918 } 01919 01920 channel_param->dl_frame_counter = 0; 01921 01922 if (_params.multicast_channels == NULL) { 01923 _params.multicast_channels = channel_param; 01924 } else { 01925 multicast_params_t *cur = _params.multicast_channels; 01926 while (cur->next != NULL) { 01927 cur = cur->next ; 01928 } 01929 cur->next = channel_param; 01930 } 01931 01932 return LORAWAN_STATUS_OK; 01933 } 01934 01935 lorawan_status_t LoRaMac::multicast_channel_unlink(multicast_params_t *channel_param) 01936 { 01937 if (channel_param == NULL) { 01938 return LORAWAN_STATUS_PARAMETER_INVALID; 01939 } 01940 01941 if (tx_ongoing()) { 01942 return LORAWAN_STATUS_BUSY; 01943 } 01944 01945 if (_params.multicast_channels != NULL) { 01946 if (_params.multicast_channels == channel_param) { 01947 _params.multicast_channels = channel_param->next ; 01948 } else { 01949 multicast_params_t *cur = _params.multicast_channels; 01950 01951 while (cur->next && cur->next != channel_param) { 01952 cur = cur->next ; 01953 } 01954 01955 if (cur->next ) { 01956 cur->next = channel_param->next ; 01957 } 01958 } 01959 channel_param->next = NULL; 01960 } 01961 01962 return LORAWAN_STATUS_OK; 01963 } 01964 01965 void LoRaMac::bind_phy(LoRaPHY &phy) 01966 { 01967 _lora_phy = &phy; 01968 } 01969 01970 uint8_t LoRaMac::get_QOS_level() 01971 { 01972 if (_prev_qos_level != _params.sys_params.nb_trans) { 01973 _prev_qos_level = _params.sys_params.nb_trans; 01974 } 01975 01976 return _params.sys_params.nb_trans; 01977 } 01978 01979 uint8_t LoRaMac::get_prev_QOS_level() 01980 { 01981 return _prev_qos_level; 01982 } 01983
Generated on Tue Jul 12 2022 15:15:48 by
