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