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