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