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