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::on_radio_rx_done(const uint8_t* const payload, uint16_t size, 00665 int16_t rssi, int8_t snr) 00666 { 00667 // on reception turn off queued timers 00668 _lora_time.stop(_params.timers.rx_window1_timer); 00669 _lora_time.stop(_params.timers.rx_window2_timer); 00670 00671 if (_device_class == CLASS_C) { 00672 open_rx2_window(); 00673 } else { 00674 _lora_phy.put_radio_to_sleep(); 00675 } 00676 00677 loramac_mhdr_t mac_hdr; 00678 uint8_t pos = 0; 00679 mac_hdr.value = payload[pos++]; 00680 00681 switch (mac_hdr.bits.mtype ) { 00682 00683 case FRAME_TYPE_JOIN_ACCEPT : 00684 00685 if (nwk_joined()) { 00686 abort_rx(); 00687 _mlme_confirmation.pending = false; 00688 return; 00689 } else { 00690 handle_join_accept_frame(payload, size); 00691 _mlme_confirmation.pending = true; 00692 } 00693 00694 break; 00695 00696 case FRAME_TYPE_DATA_UNCONFIRMED_DOWN : 00697 case FRAME_TYPE_DATA_CONFIRMED_DOWN : 00698 case FRAME_TYPE_PROPRIETARY : 00699 00700 handle_data_frame(payload, size, pos, mac_hdr.bits.mtype , rssi, snr); 00701 00702 break; 00703 00704 default: 00705 break; 00706 } 00707 } 00708 00709 void LoRaMac::on_radio_tx_timeout( void ) 00710 { 00711 _lora_time.stop(_params.timers.rx_window1_timer); 00712 _lora_time.stop(_params.timers.rx_window2_timer); 00713 _lora_time.stop(_params.timers.ack_timeout_timer); 00714 00715 if (_device_class == CLASS_C) { 00716 open_rx2_window(); 00717 } else { 00718 _lora_phy.put_radio_to_sleep(); 00719 } 00720 00721 _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ; 00722 _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ; 00723 00724 _mac_commands.clear_command_buffer(); 00725 00726 _mcps_confirmation.nb_retries = _params.ack_timeout_retry_counter; 00727 _mcps_confirmation.ack_received = false; 00728 _mcps_confirmation.tx_toa = 0; 00729 00730 post_process_mcps_req(); 00731 } 00732 00733 rx_slot_t LoRaMac::on_radio_rx_timeout(bool is_timeout) 00734 { 00735 if (_device_class != CLASS_C) { 00736 _lora_phy.put_radio_to_sleep(); 00737 } 00738 00739 if (_params.rx_slot == RX_SLOT_WIN_1 ) { 00740 if (_params.is_node_ack_requested == true) { 00741 _mcps_confirmation.status = is_timeout ? LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT 00742 : LORAMAC_EVENT_INFO_STATUS_RX1_ERROR ; 00743 } 00744 _mlme_confirmation.status = is_timeout ? LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT 00745 : LORAMAC_EVENT_INFO_STATUS_RX1_ERROR ; 00746 00747 if (_device_class != CLASS_C) { 00748 if (_lora_time.get_elapsed_time(_params.timers.aggregated_last_tx_time ) >= _params.rx_window2_delay) { 00749 _lora_time.stop(_params.timers.rx_window2_timer); 00750 } 00751 } 00752 } else { 00753 if (_params.is_node_ack_requested == true) { 00754 _mcps_confirmation.status = is_timeout ? LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT 00755 : LORAMAC_EVENT_INFO_STATUS_RX2_ERROR ; 00756 } 00757 00758 _mlme_confirmation.status = is_timeout ? LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT 00759 : LORAMAC_EVENT_INFO_STATUS_RX2_ERROR ; 00760 } 00761 00762 if (_device_class == CLASS_C) { 00763 open_rx2_window(); 00764 } 00765 00766 return _params.rx_slot; 00767 } 00768 00769 bool LoRaMac::continue_joining_process() 00770 { 00771 if (_params.join_request_trial_counter >= _params.max_join_request_trials) { 00772 return false; 00773 } 00774 00775 // Schedule a retry 00776 if (handle_retransmission() != LORAWAN_STATUS_OK) { 00777 return false; 00778 } 00779 00780 return true; 00781 } 00782 00783 bool LoRaMac::continue_sending_process() 00784 { 00785 if (_params.ack_timeout_retry_counter >= _params.max_ack_timeout_retries) { 00786 _mac_commands.clear_command_buffer(); 00787 _params.adr_ack_counter++; 00788 return false; 00789 } 00790 00791 // retransmission will be handled in on_ack_timeout() whence the ACK timeout 00792 // gets fired 00793 return true; 00794 } 00795 00796 lorawan_status_t LoRaMac::send_join_request() 00797 { 00798 lorawan_status_t status = LORAWAN_STATUS_OK; 00799 loramac_mhdr_t mac_hdr; 00800 loramac_frame_ctrl_t fctrl; 00801 00802 _params.sys_params.channel_data_rate = _lora_phy.get_alternate_DR( 00803 _params.join_request_trial_counter + 1); 00804 00805 mac_hdr.value = 0; 00806 mac_hdr.bits.mtype = FRAME_TYPE_JOIN_REQ ; 00807 00808 fctrl.value = 0; 00809 fctrl.bits.adr = _params.sys_params.adr_on; 00810 _params.is_last_tx_join_request = true; 00811 00812 /* In case of join request retransmissions, the stack must prepare 00813 * the frame again, because the network server keeps track of the random 00814 * LoRaMacDevNonce values to prevent reply attacks. */ 00815 status = prepare_frame(&mac_hdr, &fctrl, 0, NULL, 0); 00816 00817 if (status == LORAWAN_STATUS_OK) { 00818 status = schedule_tx(); 00819 } else { 00820 tr_error("Retransmission: error %d", status); 00821 } 00822 00823 return status; 00824 } 00825 00826 /** 00827 * This function handles retransmission of failed or unacknowledged 00828 * outgoing traffic 00829 */ 00830 lorawan_status_t LoRaMac::handle_retransmission() 00831 { 00832 if (!nwk_joined() && (_mlme_confirmation.req_type == MLME_JOIN )) { 00833 return send_join_request(); 00834 } 00835 00836 return schedule_tx(); 00837 } 00838 00839 /** 00840 * This function is called when the backoff_timer gets fired. 00841 * It is used for re-scheduling an unsent packet in the pipe. This packet 00842 * can be a Join Request or any other data packet. 00843 */ 00844 void LoRaMac::on_backoff_timer_expiry(void) 00845 { 00846 Lock lock(*this); 00847 lorawan_status_t status = schedule_tx(); 00848 MBED_ASSERT(status==LORAWAN_STATUS_OK); 00849 } 00850 00851 void LoRaMac::open_rx1_window(void) 00852 { 00853 Lock lock(*this); 00854 _lora_time.stop(_params.timers.rx_window1_timer); 00855 _params.rx_slot = RX_SLOT_WIN_1 ; 00856 00857 _params.rx_window1_config.channel = _params.channel; 00858 _params.rx_window1_config.dr_offset = _params.sys_params.rx1_dr_offset; 00859 _params.rx_window1_config.dl_dwell_time = _params.sys_params.downlink_dwell_time; 00860 _params.rx_window1_config.is_repeater_supported = _params.is_repeater_supported; 00861 _params.rx_window1_config.is_rx_continuous = false; 00862 _params.rx_window1_config.rx_slot = _params.rx_slot; 00863 00864 if (_device_class == CLASS_C) { 00865 _lora_phy.put_radio_to_standby(); 00866 } 00867 00868 _mcps_indication.rx_datarate = _params.rx_window1_config.datarate; 00869 _lora_phy.rx_config(&_params.rx_window1_config); 00870 00871 _lora_phy.setup_rx_window(_params.rx_window1_config.is_rx_continuous, 00872 _params.sys_params.max_rx_win_time); 00873 } 00874 00875 void LoRaMac::open_rx2_window() 00876 { 00877 Lock lock(*this); 00878 _lora_time.stop(_params.timers.rx_window2_timer); 00879 00880 _params.rx_window2_config.channel = _params.channel; 00881 _params.rx_window2_config.frequency = _params.sys_params.rx2_channel.frequency; 00882 _params.rx_window2_config.dl_dwell_time = _params.sys_params.downlink_dwell_time; 00883 _params.rx_window2_config.is_repeater_supported = _params.is_repeater_supported; 00884 _params.rx_window2_config.rx_slot = RX_SLOT_WIN_2 ; 00885 00886 _params.rx_window2_config.is_rx_continuous = get_device_class()==CLASS_C ? true : false; 00887 00888 _mcps_indication.rx_datarate = _params.rx_window2_config.datarate; 00889 00890 if (_lora_phy.rx_config(&_params.rx_window2_config)) { 00891 00892 _lora_phy.setup_rx_window(_params.rx_window2_config.is_rx_continuous, 00893 _params.sys_params.max_rx_win_time); 00894 00895 _params.rx_slot = _params.rx_window2_config.is_rx_continuous ? 00896 RX_SLOT_WIN_CLASS_C : RX_SLOT_WIN_2 ; 00897 } 00898 } 00899 00900 void LoRaMac::check_to_disable_ack_timeout(bool node_ack_requested, 00901 device_class_t dev_class, 00902 bool ack_received, 00903 uint8_t ack_timeout_retries_counter, 00904 uint8_t ack_timeout_retries) 00905 { 00906 // There are three cases where we need to stop the AckTimeoutTimer: 00907 if( node_ack_requested == false ) { 00908 if( dev_class == CLASS_C ) { 00909 // FIRST CASE 00910 // We have performed an unconfirmed uplink in class c mode 00911 // and have received a downlink in RX1 or RX2. 00912 _lora_time.stop(_params.timers.ack_timeout_timer); 00913 } 00914 } else { 00915 if( ack_received == 1 ) { 00916 // SECOND CASE 00917 // We received an ACK for previously sent confirmable message 00918 _lora_time.stop(_params.timers.ack_timeout_timer); 00919 } else { 00920 // THIRD CASE 00921 // Max number of retries exceeded for confirmable message 00922 if( ack_timeout_retries_counter > ack_timeout_retries ) { 00923 _lora_time.stop(_params.timers.ack_timeout_timer); 00924 } 00925 } 00926 } 00927 } 00928 00929 void LoRaMac::on_ack_timeout_timer_event(void) 00930 { 00931 Lock lock(*this); 00932 _params.ack_timeout_retry_counter++; 00933 00934 // reduce data rate 00935 if ((_params.ack_timeout_retry_counter % 2)) { 00936 _params.sys_params.channel_data_rate = _lora_phy.get_next_lower_tx_datarate( 00937 _params.sys_params.channel_data_rate); 00938 } 00939 00940 // Schedule a retry 00941 if (handle_retransmission() != LORAWAN_STATUS_OK) { 00942 // In a case when enabled channels are not found, PHY layer 00943 // resorts to default channels. Next attempt should go forward as the 00944 // default channels are always available if there is a base station in the 00945 // vicinity. Otherwise something is wrong with the stack, we should assert 00946 // here 00947 _mac_commands.clear_command_buffer(); 00948 _params.is_node_ack_requested = false; 00949 _mcps_confirmation.ack_received = false; 00950 _mcps_confirmation.nb_retries = _params.ack_timeout_retry_counter; 00951 00952 // now that is a critical failure 00953 lorawan_status_t status = handle_retransmission(); 00954 MBED_ASSERT(status==LORAWAN_STATUS_OK); 00955 } 00956 } 00957 00958 bool LoRaMac::validate_payload_length(uint16_t length, 00959 int8_t datarate, 00960 uint8_t fopts_len) 00961 { 00962 uint16_t max_value = 0; 00963 uint16_t payloadSize = 0; 00964 00965 max_value = _lora_phy.get_max_payload(datarate, _params.is_repeater_supported); 00966 00967 // Calculate the resulting payload size 00968 payloadSize = (length + fopts_len); 00969 00970 // Validation of the application payload size 00971 if ((payloadSize <= max_value) && 00972 (payloadSize <= LORAMAC_PHY_MAXPAYLOAD)) { 00973 return true; 00974 } 00975 return false; 00976 } 00977 00978 void LoRaMac::set_mlme_schedule_ul_indication(void) 00979 { 00980 _mlme_indication.indication_type = MLME_SCHEDULE_UPLINK ; 00981 _mlme_indication.pending= true; 00982 } 00983 00984 // This is not actual transmission. It just schedules a message in response 00985 // to MCPS request 00986 lorawan_status_t LoRaMac::send(loramac_mhdr_t *machdr, const uint8_t fport, 00987 const void *fbuffer, uint16_t fbuffer_size) 00988 { 00989 loramac_frame_ctrl_t fctrl; 00990 00991 fctrl.value = 0; 00992 fctrl.bits.fopts_len = 0; 00993 fctrl.bits.fpending = 0; 00994 fctrl.bits.ack = false; 00995 fctrl.bits.adr_ack_req = false; 00996 fctrl.bits.adr = _params.sys_params.adr_on; 00997 00998 lorawan_status_t status = prepare_frame(machdr, &fctrl, fport, fbuffer, 00999 fbuffer_size); 01000 01001 if (status != LORAWAN_STATUS_OK) { 01002 return status; 01003 } 01004 01005 // Reset confirm parameters 01006 _mcps_confirmation.nb_retries = 0; 01007 _mcps_confirmation.ack_received = false; 01008 _mcps_confirmation.ul_frame_counter = _params.ul_frame_counter; 01009 01010 status = schedule_tx(); 01011 01012 return status; 01013 } 01014 01015 lorawan_status_t LoRaMac::schedule_tx() 01016 { 01017 channel_selection_params_t next_channel; 01018 lorawan_time_t backoff_time = 0; 01019 01020 if (_params.sys_params.max_duty_cycle == 255) { 01021 return LORAWAN_STATUS_DEVICE_OFF; 01022 } 01023 01024 if (_params.sys_params.max_duty_cycle == 0) { 01025 _params.timers.aggregated_timeoff = 0; 01026 } 01027 01028 calculate_backOff(_params.last_channel_idx); 01029 01030 next_channel.aggregate_timeoff = _params.timers.aggregated_timeoff; 01031 next_channel.current_datarate = _params.sys_params.channel_data_rate; 01032 _params.is_dutycycle_on = MBED_CONF_LORA_DUTY_CYCLE_ON; 01033 next_channel.dc_enabled = _params.is_dutycycle_on; 01034 next_channel.joined = _is_nwk_joined; 01035 next_channel.last_aggregate_tx_time = _params.timers.aggregated_last_tx_time; 01036 01037 lorawan_status_t status = _lora_phy.set_next_channel(&next_channel, 01038 &_params.channel, 01039 &backoff_time, 01040 &_params.timers.aggregated_timeoff); 01041 01042 switch (status) { 01043 case LORAWAN_STATUS_NO_CHANNEL_FOUND: 01044 case LORAWAN_STATUS_NO_FREE_CHANNEL_FOUND: 01045 return status; 01046 case LORAWAN_STATUS_DUTYCYCLE_RESTRICTED: 01047 if (backoff_time != 0) { 01048 tr_debug("Next Transmission in %lu ms", backoff_time); 01049 _lora_time.start(_params.timers.backoff_timer, backoff_time); 01050 } 01051 return LORAWAN_STATUS_OK; 01052 default: 01053 break; 01054 } 01055 01056 tr_debug("Next Channel Idx=%d, DR=%d", _params.channel, next_channel.current_datarate); 01057 01058 uint8_t dr_offset = _lora_phy.apply_DR_offset(_params.sys_params.channel_data_rate, 01059 _params.sys_params.rx1_dr_offset); 01060 01061 _lora_phy.compute_rx_win_params(dr_offset, _params.sys_params.min_rx_symb, 01062 _params.sys_params.max_sys_rx_error, 01063 &_params.rx_window1_config); 01064 01065 _lora_phy.compute_rx_win_params(_params.sys_params.rx2_channel.datarate, 01066 _params.sys_params.min_rx_symb, 01067 _params.sys_params.max_sys_rx_error, 01068 &_params.rx_window2_config); 01069 01070 if (!_is_nwk_joined) { 01071 _params.rx_window1_delay = _params.sys_params.join_accept_delay1 01072 + _params.rx_window1_config.window_offset; 01073 _params.rx_window2_delay = _params.sys_params.join_accept_delay2 01074 + _params.rx_window2_config.window_offset; 01075 } else { 01076 if (validate_payload_length(_params.tx_buffer_len, 01077 _params.sys_params.channel_data_rate, 01078 _mac_commands.get_mac_cmd_length()) == false) { 01079 return LORAWAN_STATUS_LENGTH_ERROR; 01080 } 01081 _params.rx_window1_delay = _params.sys_params.recv_delay1 01082 + _params.rx_window1_config.window_offset; 01083 _params.rx_window2_delay = _params.sys_params.recv_delay2 01084 + _params.rx_window2_config.window_offset; 01085 } 01086 01087 return send_frame_on_channel(_params.channel); 01088 } 01089 01090 void LoRaMac::calculate_backOff(uint8_t channel) 01091 { 01092 lorawan_time_t elapsed_time = _lora_time.get_elapsed_time(_params.timers.mac_init_time); 01093 01094 _params.is_dutycycle_on = MBED_CONF_LORA_DUTY_CYCLE_ON; 01095 01096 _lora_phy.calculate_backoff(_is_nwk_joined, _params.is_last_tx_join_request, _params.is_dutycycle_on, 01097 channel, elapsed_time, _params.timers.tx_toa); 01098 01099 // Update aggregated time-off. This must be an assignment and no incremental 01100 // update as we do only calculate the time-off based on the last transmission 01101 _params.timers.aggregated_timeoff = (_params.timers.tx_toa * _params.sys_params.aggregated_duty_cycle 01102 - _params.timers.tx_toa); 01103 } 01104 01105 void LoRaMac::reset_mac_parameters(void) 01106 { 01107 _is_nwk_joined = false; 01108 01109 _params.ul_frame_counter = 0; 01110 _params.dl_frame_counter = 0; 01111 _params.adr_ack_counter = 0; 01112 01113 _params.ul_nb_rep_counter = 0; 01114 01115 _params.max_ack_timeout_retries = 1; 01116 _params.ack_timeout_retry_counter = 1; 01117 _params.is_ack_retry_timeout_expired = false; 01118 01119 _params.sys_params.max_duty_cycle = 0; 01120 _params.sys_params.aggregated_duty_cycle = 1; 01121 01122 _mac_commands.clear_command_buffer(); 01123 _mac_commands.clear_repeat_buffer(); 01124 _mac_commands.clear_mac_commands_in_next_tx(); 01125 01126 _params.is_rx_window_enabled = true; 01127 01128 _lora_phy.reset_to_default_values(&_params, false); 01129 01130 _params.is_node_ack_requested = false; 01131 _params.is_srv_ack_requested = false; 01132 01133 multicast_params_t *cur = _params.multicast_channels; 01134 while (cur != NULL) { 01135 cur->dl_frame_counter = 0; 01136 cur = cur->next ; 01137 } 01138 _params.channel = 0; 01139 _params.last_channel_idx = _params.channel; 01140 } 01141 01142 uint8_t LoRaMac::get_default_tx_datarate() 01143 { 01144 return _lora_phy.get_default_tx_datarate(); 01145 } 01146 01147 void LoRaMac::enable_adaptive_datarate(bool adr_enabled) 01148 { 01149 _params.sys_params.adr_on = adr_enabled; 01150 } 01151 01152 lorawan_status_t LoRaMac::set_channel_data_rate(uint8_t data_rate) 01153 { 01154 if (_params.sys_params.adr_on) { 01155 tr_error("Cannot set data rate. Please turn off ADR first."); 01156 return LORAWAN_STATUS_PARAMETER_INVALID; 01157 } 01158 01159 if (_lora_phy.verify_tx_datarate(data_rate, false) == true) { 01160 _params.sys_params.channel_data_rate = data_rate; 01161 } else { 01162 return LORAWAN_STATUS_PARAMETER_INVALID; 01163 } 01164 01165 return LORAWAN_STATUS_OK; 01166 } 01167 01168 bool LoRaMac::tx_ongoing() 01169 { 01170 return _ongoing_tx_msg.tx_ongoing; 01171 } 01172 01173 void LoRaMac::set_tx_ongoing(bool ongoing) 01174 { 01175 _ongoing_tx_msg.tx_ongoing = ongoing; 01176 } 01177 01178 void LoRaMac::reset_ongoing_tx(bool reset_pending) 01179 { 01180 _ongoing_tx_msg.tx_ongoing = false; 01181 memset(_ongoing_tx_msg.f_buffer, 0, MBED_CONF_LORA_TX_MAX_SIZE); 01182 _ongoing_tx_msg.f_buffer_size = 0; 01183 if (reset_pending) { 01184 _ongoing_tx_msg.pending_size = 0; 01185 } 01186 } 01187 01188 int16_t LoRaMac::prepare_ongoing_tx(const uint8_t port, 01189 const uint8_t* const data, 01190 uint16_t length, 01191 uint8_t flags, 01192 uint8_t num_retries) 01193 { 01194 _ongoing_tx_msg.port = port; 01195 01196 uint8_t max_possible_size = get_max_possible_tx_size(length); 01197 01198 if (max_possible_size > MBED_CONF_LORA_TX_MAX_SIZE) { 01199 max_possible_size = MBED_CONF_LORA_TX_MAX_SIZE; 01200 } 01201 01202 if (max_possible_size < length) { 01203 tr_info("Cannot transmit %d bytes. Possible TX Size is %d bytes", 01204 length, max_possible_size); 01205 01206 _ongoing_tx_msg.pending_size = length - max_possible_size; 01207 _ongoing_tx_msg.f_buffer_size = max_possible_size; 01208 memcpy(_ongoing_tx_msg.f_buffer, data, _ongoing_tx_msg.f_buffer_size); 01209 } else { 01210 _ongoing_tx_msg.f_buffer_size = length; 01211 _ongoing_tx_msg.pending_size = 0; 01212 if (length > 0) { 01213 memcpy(_ongoing_tx_msg.f_buffer, data, length); 01214 } 01215 } 01216 01217 // Handles all unconfirmed messages, including proprietary and multicast 01218 if ((flags & MSG_FLAG_MASK) == MSG_UNCONFIRMED_FLAG 01219 || (flags & MSG_FLAG_MASK) == MSG_UNCONFIRMED_MULTICAST 01220 || (flags & MSG_FLAG_MASK) == MSG_UNCONFIRMED_PROPRIETARY) { 01221 01222 _ongoing_tx_msg.type = MCPS_UNCONFIRMED ; 01223 _ongoing_tx_msg.fport = port; 01224 _ongoing_tx_msg.nb_trials = 1; 01225 } 01226 01227 // Handles all confirmed messages, including proprietary and multicast 01228 if ((flags & MSG_FLAG_MASK) == MSG_CONFIRMED_FLAG 01229 || (flags & MSG_FLAG_MASK) == MSG_CONFIRMED_MULTICAST 01230 || (flags & MSG_FLAG_MASK) == MSG_CONFIRMED_PROPRIETARY) { 01231 01232 _ongoing_tx_msg.type = MCPS_CONFIRMED ; 01233 _ongoing_tx_msg.fport = port; 01234 _ongoing_tx_msg.nb_trials = num_retries; 01235 } 01236 01237 tr_info("RTS = %u bytes, PEND = %u, Port: %u", 01238 _ongoing_tx_msg.f_buffer_size, _ongoing_tx_msg.pending_size, 01239 _ongoing_tx_msg.fport); 01240 01241 return _ongoing_tx_msg.f_buffer_size; 01242 } 01243 01244 lorawan_status_t LoRaMac::send_ongoing_tx() 01245 { 01246 lorawan_status_t status; 01247 _params.is_last_tx_join_request = false; 01248 int8_t datarate = _params.sys_params.channel_data_rate; 01249 01250 // TODO: The comment is different than the code??? 01251 // Apply the minimum possible datarate. 01252 // Some regions have limitations for the minimum datarate. 01253 datarate = MAX(datarate, (int8_t)_lora_phy.get_minimum_tx_datarate()); 01254 01255 loramac_mhdr_t machdr; 01256 machdr.value = 0; 01257 01258 reset_mcps_confirmation(); 01259 01260 _params.ack_timeout_retry_counter = 1; 01261 _params.max_ack_timeout_retries = 1; 01262 01263 if (MCPS_UNCONFIRMED == _ongoing_tx_msg.type) { 01264 machdr.bits.mtype = FRAME_TYPE_DATA_UNCONFIRMED_UP ; 01265 } else if (_ongoing_tx_msg.type == MCPS_CONFIRMED ) { 01266 machdr.bits.mtype = FRAME_TYPE_DATA_CONFIRMED_UP ; 01267 _params.max_ack_timeout_retries = _ongoing_tx_msg.nb_trials; 01268 } else if (_ongoing_tx_msg.type == MCPS_PROPRIETARY ) { 01269 //TODO: Is this dead code currently??? Nobody sets this type 01270 machdr.bits.mtype = FRAME_TYPE_PROPRIETARY ; 01271 } else { 01272 return LORAWAN_STATUS_SERVICE_UNKNOWN; 01273 } 01274 01275 if (_params.sys_params.adr_on == false) { 01276 if (_lora_phy.verify_tx_datarate(datarate, false) == true) { 01277 _params.sys_params.channel_data_rate = datarate; 01278 } else { 01279 return LORAWAN_STATUS_PARAMETER_INVALID; 01280 } 01281 } 01282 01283 status = send(&machdr, _ongoing_tx_msg.fport, _ongoing_tx_msg.f_buffer, 01284 _ongoing_tx_msg.f_buffer_size); 01285 if (status == LORAWAN_STATUS_OK) { 01286 _mcps_confirmation.req_type = _ongoing_tx_msg.type; 01287 } 01288 01289 return status; 01290 } 01291 01292 device_class_t LoRaMac::get_device_class() const 01293 { 01294 return _device_class; 01295 } 01296 01297 void LoRaMac::set_device_class(const device_class_t& device_class) 01298 { 01299 _device_class = device_class; 01300 01301 if (CLASS_A == _device_class) { 01302 _lora_phy.put_radio_to_sleep(); 01303 } else if (CLASS_C == _device_class) { 01304 _params.is_node_ack_requested = false; 01305 _lora_phy.put_radio_to_sleep(); 01306 _lora_phy.compute_rx_win_params( 01307 _params.sys_params.rx2_channel.datarate, 01308 _params.sys_params.min_rx_symb, 01309 _params.sys_params.max_sys_rx_error, 01310 &_params.rx_window2_config); 01311 } 01312 if (CLASS_C == _device_class) { 01313 open_rx2_window(); 01314 } 01315 } 01316 01317 void LoRaMac::setup_link_check_request() 01318 { 01319 reset_mlme_confirmation(); 01320 01321 _mlme_confirmation.req_type = MLME_LINK_CHECK ; 01322 _mlme_confirmation.pending = true; 01323 _mac_commands.add_link_check_req(); 01324 } 01325 01326 lorawan_status_t LoRaMac::prepare_join(const lorawan_connect_t *params, bool is_otaa) 01327 { 01328 if (params) { 01329 if (is_otaa) { 01330 if ((params->connection_u.otaa.dev_eui == NULL) || 01331 (params->connection_u.otaa.app_eui == NULL) || 01332 (params->connection_u.otaa.app_key == NULL) || 01333 (params->connection_u.otaa.nb_trials == 0)) { 01334 return LORAWAN_STATUS_PARAMETER_INVALID; 01335 } 01336 _params.keys.dev_eui = params->connection_u.otaa.dev_eui; 01337 _params.keys.app_eui = params->connection_u.otaa.app_eui; 01338 _params.keys.app_key = params->connection_u.otaa.app_key; 01339 _params.max_join_request_trials = params->connection_u.otaa.nb_trials; 01340 01341 if (!_lora_phy.verify_nb_join_trials(params->connection_u.otaa.nb_trials)) { 01342 // Value not supported, get default 01343 _params.max_join_request_trials = MBED_CONF_LORA_NB_TRIALS; 01344 } 01345 // Reset variable JoinRequestTrials 01346 _params.join_request_trial_counter = 0; 01347 } else { 01348 _params.net_id = params->connection_u.abp.nwk_id; 01349 _params.dev_addr = params->connection_u.abp.dev_addr; 01350 01351 memcpy(_params.keys.nwk_skey, params->connection_u.abp.nwk_skey, 01352 sizeof(_params.keys.nwk_skey)); 01353 01354 memcpy(_params.keys.app_skey, params->connection_u.abp.app_skey, 01355 sizeof(_params.keys.app_skey)); 01356 } 01357 } else { 01358 #if MBED_CONF_LORA_OVER_THE_AIR_ACTIVATION 01359 const static uint8_t dev_eui[] = MBED_CONF_LORA_DEVICE_EUI; 01360 const static uint8_t app_eui[] = MBED_CONF_LORA_APPLICATION_EUI; 01361 const static uint8_t app_key[] = MBED_CONF_LORA_APPLICATION_KEY; 01362 01363 _params.keys.app_eui = const_cast<uint8_t *>(app_eui); 01364 _params.keys.dev_eui = const_cast<uint8_t *>(dev_eui); 01365 _params.keys.app_key = const_cast<uint8_t *>(app_key); 01366 _params.max_join_request_trials = MBED_CONF_LORA_NB_TRIALS; 01367 01368 // Reset variable JoinRequestTrials 01369 _params.join_request_trial_counter = 0; 01370 01371 reset_mac_parameters(); 01372 01373 _params.sys_params.channel_data_rate = 01374 _lora_phy.get_alternate_DR(_params.join_request_trial_counter + 1); 01375 01376 #else 01377 const static uint8_t nwk_skey[] = MBED_CONF_LORA_NWKSKEY; 01378 const static uint8_t app_skey[] = MBED_CONF_LORA_APPSKEY; 01379 01380 _params.net_id = (MBED_CONF_LORA_DEVICE_ADDRESS & LORAWAN_NETWORK_ID_MASK); 01381 _params.dev_addr = MBED_CONF_LORA_DEVICE_ADDRESS; 01382 01383 memcpy(_params.keys.nwk_skey, nwk_skey, 01384 sizeof(_params.keys.nwk_skey)); 01385 01386 memcpy(_params.keys.app_skey, app_skey, 01387 sizeof(_params.keys.app_skey)); 01388 #endif 01389 } 01390 return LORAWAN_STATUS_OK; 01391 } 01392 01393 lorawan_status_t LoRaMac::join(bool is_otaa) 01394 { 01395 if (!is_otaa) { 01396 set_nwk_joined(true); 01397 return LORAWAN_STATUS_OK; 01398 } 01399 01400 reset_mlme_confirmation(); 01401 _mlme_confirmation.req_type = MLME_JOIN ; 01402 01403 return send_join_request(); 01404 } 01405 01406 static void memcpy_convert_endianess(uint8_t *dst, 01407 const uint8_t *src, 01408 uint16_t size) 01409 { 01410 dst = dst + (size - 1); 01411 while (size--) { 01412 *dst-- = *src++; 01413 } 01414 } 01415 01416 lorawan_status_t LoRaMac::prepare_frame(loramac_mhdr_t *machdr, 01417 loramac_frame_ctrl_t *fctrl, 01418 const uint8_t fport, 01419 const void *fbuffer, 01420 uint16_t fbuffer_size) 01421 { 01422 uint16_t i; 01423 uint8_t pkt_header_len = 0; 01424 uint32_t mic = 0; 01425 const void* payload = fbuffer; 01426 uint8_t frame_port = fport; 01427 lorawan_status_t status = LORAWAN_STATUS_OK; 01428 01429 _params.tx_buffer_len = 0; 01430 01431 _params.is_node_ack_requested = false; 01432 01433 if (fbuffer == NULL) { 01434 fbuffer_size = 0; 01435 } 01436 01437 _params.tx_buffer_len = fbuffer_size; 01438 01439 _params.tx_buffer[pkt_header_len++] = machdr->value ; 01440 01441 switch (machdr->bits.mtype ) { 01442 01443 case FRAME_TYPE_JOIN_REQ : 01444 01445 _params.tx_buffer_len = pkt_header_len; 01446 memcpy_convert_endianess(_params.tx_buffer + _params.tx_buffer_len, 01447 _params.keys.app_eui, 8); 01448 _params.tx_buffer_len += 8; 01449 memcpy_convert_endianess(_params.tx_buffer + _params.tx_buffer_len, 01450 _params.keys.dev_eui, 8); 01451 _params.tx_buffer_len += 8; 01452 01453 _params.dev_nonce = _lora_phy.get_radio_rng(); 01454 01455 _params.tx_buffer[_params.tx_buffer_len++] = _params.dev_nonce & 0xFF; 01456 _params.tx_buffer[_params.tx_buffer_len++] = (_params.dev_nonce >> 8) & 0xFF; 01457 01458 if (0 != _lora_crypto.compute_join_frame_mic(_params.tx_buffer, 01459 _params.tx_buffer_len & 0xFF, 01460 _params.keys.app_key, 01461 APPKEY_KEY_LENGTH, 01462 &mic)) { 01463 return LORAWAN_STATUS_CRYPTO_FAIL; 01464 } 01465 01466 _params.tx_buffer[_params.tx_buffer_len++] = mic & 0xFF; 01467 _params.tx_buffer[_params.tx_buffer_len++] = (mic >> 8) & 0xFF; 01468 _params.tx_buffer[_params.tx_buffer_len++] = (mic >> 16) & 0xFF; 01469 _params.tx_buffer[_params.tx_buffer_len++] = (mic >> 24) & 0xFF; 01470 01471 break; 01472 case FRAME_TYPE_DATA_CONFIRMED_UP : 01473 _params.is_node_ack_requested = true; 01474 //Intentional fallthrough 01475 case FRAME_TYPE_DATA_UNCONFIRMED_UP : { 01476 if (!_is_nwk_joined) { 01477 return LORAWAN_STATUS_NO_NETWORK_JOINED; 01478 } 01479 01480 if (_params.sys_params.adr_on) { 01481 if (_lora_phy.get_next_ADR(true, 01482 _params.sys_params.channel_data_rate, 01483 _params.sys_params.channel_tx_power, 01484 _params.adr_ack_counter)) { 01485 fctrl->bits.adr_ack_req = 1; 01486 } 01487 } 01488 01489 if (_params.is_srv_ack_requested == true) { 01490 _params.is_srv_ack_requested = false; 01491 fctrl->bits.ack = 1; 01492 } 01493 01494 _params.tx_buffer[pkt_header_len++] = (_params.dev_addr) & 0xFF; 01495 _params.tx_buffer[pkt_header_len++] = (_params.dev_addr >> 8) & 0xFF; 01496 _params.tx_buffer[pkt_header_len++] = (_params.dev_addr >> 16) & 0xFF; 01497 _params.tx_buffer[pkt_header_len++] = (_params.dev_addr >> 24) & 0xFF; 01498 01499 _params.tx_buffer[pkt_header_len++] = fctrl->value ; 01500 01501 _params.tx_buffer[pkt_header_len++] = _params.ul_frame_counter & 0xFF; 01502 _params.tx_buffer[pkt_header_len++] = (_params.ul_frame_counter >> 8) 01503 & 0xFF; 01504 01505 _mac_commands.copy_repeat_commands_to_buffer(); 01506 01507 const uint8_t mac_commands_len = _mac_commands.get_mac_cmd_length(); 01508 01509 if ((payload != NULL) && (_params.tx_buffer_len > 0)) { 01510 if (_mac_commands.is_mac_command_in_next_tx() == true) { 01511 if (mac_commands_len <= LORA_MAC_COMMAND_MAX_FOPTS_LENGTH) { 01512 fctrl->bits.fopts_len += mac_commands_len; 01513 01514 // Update FCtrl field with new value of OptionsLength 01515 _params.tx_buffer[0x05] = fctrl->value ; 01516 01517 const uint8_t *buffer = 01518 _mac_commands.get_mac_commands_buffer(); 01519 for (i = 0; i < mac_commands_len; i++) { 01520 _params.tx_buffer[pkt_header_len++] = buffer[i]; 01521 } 01522 } else { 01523 _params.tx_buffer_len = mac_commands_len; 01524 payload = _mac_commands.get_mac_commands_buffer(); 01525 frame_port = 0; 01526 } 01527 } 01528 } else { 01529 if ((mac_commands_len > 0) 01530 && (_mac_commands.is_mac_command_in_next_tx() == true)) { 01531 _params.tx_buffer_len = mac_commands_len; 01532 payload = _mac_commands.get_mac_commands_buffer(); 01533 frame_port = 0; 01534 } 01535 } 01536 01537 _mac_commands.parse_mac_commands_to_repeat(); 01538 01539 if ((payload != NULL) && (_params.tx_buffer_len > 0)) { 01540 _params.tx_buffer[pkt_header_len++] = frame_port; 01541 01542 uint8_t *key = _params.keys.app_skey; 01543 uint32_t key_length = sizeof(_params.keys.app_skey)*8; 01544 if (frame_port == 0) { 01545 _mac_commands.clear_command_buffer(); 01546 key = _params.keys.nwk_skey; 01547 key_length = sizeof(_params.keys.nwk_skey)*8; 01548 } 01549 if (0 != _lora_crypto.encrypt_payload((uint8_t*) payload, _params.tx_buffer_len, 01550 key, key_length, 01551 _params.dev_addr, UP_LINK, 01552 _params.ul_frame_counter, 01553 &_params.tx_buffer[pkt_header_len])) { 01554 status = LORAWAN_STATUS_CRYPTO_FAIL; 01555 } 01556 } 01557 01558 _params.tx_buffer_len = pkt_header_len + _params.tx_buffer_len; 01559 01560 if (0 != _lora_crypto.compute_mic(_params.tx_buffer, _params.tx_buffer_len, 01561 _params.keys.nwk_skey, sizeof(_params.keys.nwk_skey)*8, 01562 _params.dev_addr, 01563 UP_LINK, _params.ul_frame_counter, &mic)) { 01564 status = LORAWAN_STATUS_CRYPTO_FAIL; 01565 } 01566 01567 _params.tx_buffer[_params.tx_buffer_len + 0] = mic & 0xFF; 01568 _params.tx_buffer[_params.tx_buffer_len + 1] = (mic >> 8) & 0xFF; 01569 _params.tx_buffer[_params.tx_buffer_len + 2] = (mic >> 16) & 0xFF; 01570 _params.tx_buffer[_params.tx_buffer_len + 3] = (mic >> 24) & 0xFF; 01571 01572 _params.tx_buffer_len += LORAMAC_MFR_LEN; 01573 } 01574 break; 01575 case FRAME_TYPE_PROPRIETARY : 01576 if ((fbuffer != NULL) && (_params.tx_buffer_len > 0)) { 01577 memcpy(_params.tx_buffer + pkt_header_len, (uint8_t*) fbuffer, 01578 _params.tx_buffer_len); 01579 _params.tx_buffer_len = pkt_header_len + _params.tx_buffer_len; 01580 } 01581 break; 01582 default: 01583 status = LORAWAN_STATUS_SERVICE_UNKNOWN; 01584 } 01585 01586 tr_debug("Frame prepared to send at port %u", frame_port); 01587 01588 return status; 01589 } 01590 01591 lorawan_status_t LoRaMac::send_frame_on_channel(uint8_t channel) 01592 { 01593 tx_config_params_t tx_config; 01594 int8_t tx_power = 0; 01595 01596 tx_config.channel = channel; 01597 tx_config.datarate = _params.sys_params.channel_data_rate; 01598 tx_config.tx_power = _params.sys_params.channel_tx_power; 01599 tx_config.max_eirp = _params.sys_params.max_eirp; 01600 tx_config.antenna_gain = _params.sys_params.antenna_gain; 01601 tx_config.pkt_len = _params.tx_buffer_len; 01602 01603 _lora_phy.tx_config(&tx_config, &tx_power, &_params.timers.tx_toa); 01604 01605 _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR ; 01606 01607 _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR ; 01608 _mcps_confirmation.data_rate = _params.sys_params.channel_data_rate; 01609 _mcps_confirmation.tx_power = tx_power; 01610 _mcps_confirmation.channel = channel; 01611 01612 _mcps_confirmation.tx_toa = _params.timers.tx_toa; 01613 _mlme_confirmation.tx_toa = _params.timers.tx_toa; 01614 01615 // _lora_time.start(_params.timers.mac_state_check_timer, 01616 // MAC_STATE_CHECK_TIMEOUT); 01617 01618 if (!_is_nwk_joined) { 01619 _params.join_request_trial_counter++; 01620 } 01621 01622 _lora_phy.handle_send(_params.tx_buffer, _params.tx_buffer_len); 01623 01624 return LORAWAN_STATUS_OK; 01625 } 01626 01627 void LoRaMac::reset_mcps_confirmation() 01628 { 01629 memset((uint8_t*) &_mcps_confirmation, 0, sizeof(_mcps_confirmation)); 01630 _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR ; 01631 } 01632 01633 void LoRaMac::reset_mlme_confirmation() 01634 { 01635 memset((uint8_t*) &_mlme_confirmation, 0, sizeof(_mlme_confirmation)); 01636 _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR ; 01637 } 01638 01639 void LoRaMac::reset_mcps_indication() 01640 { 01641 memset((uint8_t*) &_mcps_indication, 0, sizeof(_mcps_indication)); 01642 _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_ERROR ; 01643 } 01644 01645 void LoRaMac::set_tx_continuous_wave(uint8_t channel, int8_t datarate, int8_t tx_power, 01646 float max_eirp, float antenna_gain, uint16_t timeout) 01647 { 01648 cw_mode_params_t continuous_wave; 01649 01650 continuous_wave.channel = channel; 01651 continuous_wave.datarate = datarate; 01652 continuous_wave.tx_power = tx_power; 01653 continuous_wave.max_eirp = max_eirp; 01654 continuous_wave.antenna_gain = antenna_gain; 01655 continuous_wave.timeout = timeout; 01656 01657 _lora_phy.set_tx_cont_mode(&continuous_wave); 01658 } 01659 01660 lorawan_status_t LoRaMac::initialize(EventQueue *queue) 01661 { 01662 _lora_time.activate_timer_subsystem(queue); 01663 01664 _ev_queue = queue; 01665 01666 _channel_plan.activate_channelplan_subsystem(&_lora_phy); 01667 01668 _device_class = CLASS_A; 01669 01670 _params.join_request_trial_counter = 0; 01671 _params.max_join_request_trials = 1; 01672 _params.is_repeater_supported = false; 01673 01674 _params.timers.aggregated_last_tx_time = 0; 01675 _params.timers.aggregated_timeoff = 0; 01676 01677 _lora_phy.reset_to_default_values(&_params, true); 01678 01679 _params.sys_params.max_sys_rx_error = 10; 01680 _params.sys_params.min_rx_symb = 6; 01681 _params.sys_params.retry_num = 1; 01682 01683 reset_mac_parameters(); 01684 01685 srand(_lora_phy.get_radio_rng()); 01686 01687 _params.is_nwk_public = MBED_CONF_LORA_PUBLIC_NETWORK; 01688 _lora_phy.setup_public_network_mode(_params.is_nwk_public); 01689 _lora_phy.put_radio_to_sleep(); 01690 01691 _lora_time.init(_params.timers.backoff_timer, 01692 mbed::callback(this, &LoRaMac::on_backoff_timer_expiry)); 01693 _lora_time.init(_params.timers.rx_window1_timer, 01694 mbed::callback(this, &LoRaMac::open_rx1_window)); 01695 _lora_time.init(_params.timers.rx_window2_timer, 01696 mbed::callback(this, &LoRaMac::open_rx2_window)); 01697 _lora_time.init(_params.timers.ack_timeout_timer, 01698 mbed::callback(this, &LoRaMac::on_ack_timeout_timer_event)); 01699 01700 _params.timers.mac_init_time = _lora_time.get_current_time(); 01701 01702 _params.sys_params.adr_on = MBED_CONF_LORA_ADR_ON; 01703 01704 _params.is_nwk_public = MBED_CONF_LORA_PUBLIC_NETWORK; 01705 _lora_phy.setup_public_network_mode(MBED_CONF_LORA_PUBLIC_NETWORK); 01706 01707 return LORAWAN_STATUS_OK; 01708 } 01709 01710 void LoRaMac::disconnect() 01711 { 01712 _lora_time.stop(_params.timers.backoff_timer); 01713 _lora_time.stop(_params.timers.rx_window1_timer); 01714 _lora_time.stop(_params.timers.rx_window2_timer); 01715 _lora_time.stop(_params.timers.ack_timeout_timer); 01716 01717 _lora_phy.put_radio_to_sleep(); 01718 01719 _is_nwk_joined = false; 01720 _params.is_ack_retry_timeout_expired = false; 01721 _params.is_rx_window_enabled = true; 01722 _params.is_node_ack_requested = false; 01723 _params.is_srv_ack_requested = false; 01724 01725 _mac_commands.clear_command_buffer(); 01726 _mac_commands.clear_repeat_buffer(); 01727 _mac_commands.clear_mac_commands_in_next_tx(); 01728 01729 reset_mcps_confirmation(); 01730 reset_mlme_confirmation(); 01731 reset_mcps_indication(); 01732 } 01733 01734 uint8_t LoRaMac::get_max_possible_tx_size(uint8_t size) 01735 { 01736 uint8_t max_possible_payload_size = 0; 01737 uint8_t current_payload_size = 0; 01738 uint8_t fopt_len = _mac_commands.get_mac_cmd_length() 01739 + _mac_commands.get_repeat_commands_length(); 01740 01741 if (_params.sys_params.adr_on) { 01742 _lora_phy.get_next_ADR(false, _params.sys_params.channel_data_rate, 01743 _params.sys_params.channel_tx_power, 01744 _params.adr_ack_counter); 01745 } 01746 01747 current_payload_size = _lora_phy.get_max_payload(_params.sys_params.channel_data_rate, _params.is_repeater_supported); 01748 01749 if (current_payload_size >= fopt_len) { 01750 max_possible_payload_size = current_payload_size - fopt_len; 01751 } else { 01752 max_possible_payload_size = current_payload_size; 01753 fopt_len = 0; 01754 _mac_commands.clear_command_buffer(); 01755 _mac_commands.clear_repeat_buffer(); 01756 } 01757 01758 if (validate_payload_length(size, _params.sys_params.channel_data_rate, 01759 fopt_len) == false) { 01760 return max_possible_payload_size; 01761 } 01762 return current_payload_size; 01763 } 01764 01765 bool LoRaMac::nwk_joined() 01766 { 01767 return _is_nwk_joined; 01768 } 01769 01770 void LoRaMac::set_nwk_joined(bool joined) 01771 { 01772 _is_nwk_joined = joined; 01773 } 01774 01775 lorawan_status_t LoRaMac::add_channel_plan(const lorawan_channelplan_t& plan) 01776 { 01777 if (tx_ongoing()) { 01778 return LORAWAN_STATUS_BUSY; 01779 } 01780 01781 return _channel_plan.set_plan(plan); 01782 } 01783 01784 lorawan_status_t LoRaMac::remove_channel_plan() 01785 { 01786 if (tx_ongoing()) { 01787 return LORAWAN_STATUS_BUSY; 01788 } 01789 01790 return _channel_plan.remove_plan(); 01791 } 01792 01793 lorawan_status_t LoRaMac::get_channel_plan(lorawan_channelplan_t& plan) 01794 { 01795 return _channel_plan.get_plan(plan, _lora_phy.get_phy_channels()); 01796 } 01797 01798 lorawan_status_t LoRaMac::remove_single_channel(uint8_t id) 01799 { 01800 if (tx_ongoing()) { 01801 return LORAWAN_STATUS_BUSY; 01802 } 01803 01804 return _channel_plan.remove_single_channel(id); 01805 } 01806 01807 lorawan_status_t LoRaMac::multicast_channel_link(multicast_params_t *channel_param) 01808 { 01809 if (channel_param == NULL) { 01810 return LORAWAN_STATUS_PARAMETER_INVALID; 01811 } 01812 if (tx_ongoing()) { 01813 return LORAWAN_STATUS_BUSY; 01814 } 01815 01816 channel_param->dl_frame_counter = 0; 01817 01818 if (_params.multicast_channels == NULL) { 01819 _params.multicast_channels = channel_param; 01820 } else { 01821 multicast_params_t *cur = _params.multicast_channels; 01822 while (cur->next != NULL) { 01823 cur = cur->next ; 01824 } 01825 cur->next = channel_param; 01826 } 01827 01828 return LORAWAN_STATUS_OK; 01829 } 01830 01831 lorawan_status_t LoRaMac::multicast_channel_unlink( 01832 multicast_params_t *channel_param) 01833 { 01834 if (channel_param == NULL) { 01835 return LORAWAN_STATUS_PARAMETER_INVALID; 01836 } 01837 01838 if (tx_ongoing()) { 01839 return LORAWAN_STATUS_BUSY; 01840 } 01841 01842 if (_params.multicast_channels != NULL) { 01843 if (_params.multicast_channels == channel_param) { 01844 _params.multicast_channels = channel_param->next ; 01845 } else { 01846 multicast_params_t *cur = _params.multicast_channels; 01847 01848 while (cur->next && cur->next != channel_param) { 01849 cur = cur->next ; 01850 } 01851 01852 if (cur->next ) { 01853 cur->next = channel_param->next ; 01854 } 01855 } 01856 channel_param->next = NULL; 01857 } 01858 01859 return LORAWAN_STATUS_OK; 01860 } 01861 01862 void LoRaMac::bind_radio_driver(LoRaRadio& radio) 01863 { 01864 _lora_phy.set_radio_instance(radio); 01865 } 01866 01867 #if defined(LORAWAN_COMPLIANCE_TEST) 01868 /*************************************************************************** 01869 * Compliance testing * 01870 **************************************************************************/ 01871 01872 01873 lorawan_status_t LoRaMac::mlme_request( loramac_mlme_req_t *mlmeRequest ) 01874 { 01875 if (LORAMAC_IDLE != _params.mac_state) { 01876 return LORAWAN_STATUS_BUSY; 01877 } 01878 01879 reset_mlme_confirmation(); 01880 01881 _mlme_confirmation.req_type = mlmeRequest->type; 01882 _params.flags.bits.mlme_req = 1; 01883 01884 lorawan_status_t status = LORAWAN_STATUS_SERVICE_UNKNOWN; 01885 01886 if (MLME_TXCW == mlmeRequest->type) { 01887 set_tx_continuous_wave(_params.channel, _params.sys_params.channel_data_rate, _params.sys_params.channel_tx_power, 01888 _params.sys_params.max_eirp, _params.sys_params.antenna_gain, mlmeRequest->cw_tx_mode.timeout); 01889 _lora_time.start(_params.timers.mac_state_check_timer, 01890 MAC_STATE_CHECK_TIMEOUT); 01891 01892 _params.mac_state |= LORAMAC_TX_RUNNING; 01893 status = LORAWAN_STATUS_OK; 01894 } else if (MLME_TXCW_1 == mlmeRequest->type) { 01895 set_tx_continuous_wave(0, 0, mlmeRequest->cw_tx_mode.power, 0, 0, mlmeRequest->cw_tx_mode.timeout); 01896 _lora_time.start(_params.timers.mac_state_check_timer, 01897 MAC_STATE_CHECK_TIMEOUT); 01898 01899 _params.mac_state |= LORAMAC_TX_RUNNING; 01900 status = LORAWAN_STATUS_OK; 01901 } 01902 01903 if (status != LORAWAN_STATUS_OK) { 01904 _params.is_node_ack_requested = false; 01905 _params.flags.bits.mlme_req = 0; 01906 } 01907 01908 01909 return status; 01910 } 01911 01912 lorawan_status_t LoRaMac::test_request( loramac_compliance_test_req_t *mcpsRequest ) 01913 { 01914 if (_params.mac_state != LORAMAC_IDLE) { 01915 return LORAWAN_STATUS_BUSY; 01916 } 01917 01918 loramac_mhdr_t machdr; 01919 int8_t datarate = mcpsRequest->data_rate; 01920 // TODO: The comment is different than the code??? 01921 // Apply the minimum possible datarate. 01922 // Some regions have limitations for the minimum datarate. 01923 datarate = MAX(datarate, (int8_t)_lora_phy.get_minimum_tx_datarate()); 01924 01925 machdr.value = 0; 01926 01927 reset_mcps_confirmation(); 01928 01929 _params.ack_timeout_retry_counter = 1; 01930 _params.max_ack_timeout_retries = 1; 01931 01932 switch (mcpsRequest->type) { 01933 case MCPS_UNCONFIRMED : { 01934 machdr.bits.mtype = FRAME_TYPE_DATA_UNCONFIRMED_UP ; 01935 break; 01936 } 01937 case MCPS_CONFIRMED : { 01938 machdr.bits.mtype = FRAME_TYPE_DATA_CONFIRMED_UP ; 01939 _params.max_ack_timeout_retries = mcpsRequest->nb_trials; 01940 break; 01941 } 01942 case MCPS_PROPRIETARY : { 01943 machdr.bits.mtype = FRAME_TYPE_PROPRIETARY ; 01944 break; 01945 } 01946 default: 01947 return LORAWAN_STATUS_PARAMETER_INVALID; 01948 } 01949 01950 // Filter fPorts 01951 // TODO: Does not work with PROPRIETARY messages 01952 // if( IsFPortAllowed( mcpsRequest->fport ) == false ) { 01953 // return LORAWAN_STATUS_PARAMETER_INVALID; 01954 // } 01955 01956 if (_params.sys_params.adr_on == false) { 01957 if (_lora_phy.verify_tx_datarate(datarate, false) == true) { 01958 _params.sys_params.channel_data_rate = datarate; 01959 } else { 01960 return LORAWAN_STATUS_PARAMETER_INVALID; 01961 } 01962 } 01963 01964 lorawan_status_t status = send(&machdr, mcpsRequest->fport, mcpsRequest->f_buffer, 01965 mcpsRequest->f_buffer_size); 01966 if (status == LORAWAN_STATUS_OK) { 01967 _mcps_confirmation.req_type = mcpsRequest->type; 01968 _params.flags.bits.mcps_req = 1; 01969 } else { 01970 _params.is_node_ack_requested = false; 01971 } 01972 01973 return status; 01974 } 01975 01976 lorawan_status_t LoRaMac::LoRaMacSetTxTimer( uint32_t TxDutyCycleTime ) 01977 { 01978 _lora_time.start(tx_next_packet_timer, TxDutyCycleTime); 01979 return LORAWAN_STATUS_OK; 01980 } 01981 01982 lorawan_status_t LoRaMac::LoRaMacStopTxTimer( ) 01983 { 01984 _lora_time.stop(tx_next_packet_timer); 01985 return LORAWAN_STATUS_OK; 01986 } 01987 01988 void LoRaMac::LoRaMacTestRxWindowsOn( bool enable ) 01989 { 01990 _params.is_rx_window_enabled = enable; 01991 } 01992 01993 void LoRaMac::LoRaMacTestSetMic( uint16_t txPacketCounter ) 01994 { 01995 _params.ul_frame_counter = txPacketCounter; 01996 _params.is_ul_frame_counter_fixed = true; 01997 } 01998 01999 void LoRaMac::LoRaMacTestSetDutyCycleOn( bool enable ) 02000 { 02001 if(_lora_phy.verify_duty_cycle(enable) == true) 02002 { 02003 _params.is_dutycycle_on = enable; 02004 } 02005 } 02006 02007 void LoRaMac::LoRaMacTestSetChannel( uint8_t channel ) 02008 { 02009 _params.channel = channel; 02010 } 02011 #endif
Generated on Tue Jul 12 2022 18:18:37 by
1.7.2