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.
LoRaMacCommand.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 00025 #include "LoRaMacCommand.h" 00026 #include "LoRaMac.h" 00027 00028 #if defined(FEATURE_COMMON_PAL) 00029 #include "mbed_trace.h" 00030 #define TRACE_GROUP "LMACC" 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 /** 00038 * LoRaMAC max EIRP (dBm) table. 00039 */ 00040 static const uint8_t max_eirp_table[] = { 8, 10, 12, 13, 14, 16, 18, 20, 21, 24, 26, 27, 29, 30, 33, 36 }; 00041 00042 00043 LoRaMacCommand::LoRaMacCommand() 00044 { 00045 mac_cmd_in_next_tx = false; 00046 sticky_mac_cmd = false; 00047 mac_cmd_buf_idx = 0; 00048 mac_cmd_buf_idx_to_repeat = 0; 00049 00050 memset(mac_cmd_buffer, 0, sizeof(mac_cmd_buffer)); 00051 memset(mac_cmd_buffer_to_repeat, 0, sizeof(mac_cmd_buffer_to_repeat)); 00052 } 00053 00054 LoRaMacCommand::~LoRaMacCommand() 00055 { 00056 } 00057 00058 lorawan_status_t LoRaMacCommand::add_mac_command(uint8_t cmd, uint8_t p1, 00059 uint8_t p2) 00060 { 00061 lorawan_status_t status = LORAWAN_STATUS_BUSY; 00062 // The maximum buffer length must take MAC commands to re-send into account. 00063 const uint8_t bufLen = LORA_MAC_COMMAND_MAX_LENGTH 00064 - mac_cmd_buf_idx_to_repeat; 00065 00066 switch (cmd) { 00067 case MOTE_MAC_LINK_CHECK_REQ : 00068 if (mac_cmd_buf_idx < bufLen) { 00069 mac_cmd_buffer[mac_cmd_buf_idx++] = cmd; 00070 // No payload for this command 00071 status = LORAWAN_STATUS_OK; 00072 } 00073 break; 00074 case MOTE_MAC_LINK_ADR_ANS : 00075 if (mac_cmd_buf_idx < (bufLen - 1)) { 00076 mac_cmd_buffer[mac_cmd_buf_idx++] = cmd; 00077 // Margin 00078 mac_cmd_buffer[mac_cmd_buf_idx++] = p1; 00079 status = LORAWAN_STATUS_OK; 00080 } 00081 break; 00082 case MOTE_MAC_DUTY_CYCLE_ANS : 00083 if (mac_cmd_buf_idx < bufLen) { 00084 mac_cmd_buffer[mac_cmd_buf_idx++] = cmd; 00085 // No payload for this answer 00086 status = LORAWAN_STATUS_OK; 00087 } 00088 break; 00089 case MOTE_MAC_RX_PARAM_SETUP_ANS : 00090 if (mac_cmd_buf_idx < (bufLen - 1)) { 00091 mac_cmd_buffer[mac_cmd_buf_idx++] = cmd; 00092 // Status: Datarate ACK, Channel ACK 00093 mac_cmd_buffer[mac_cmd_buf_idx++] = p1; 00094 // This is a sticky MAC command answer. Setup indication 00095 // _lora_mac.set_mlme_schedule_ul_indication(); 00096 sticky_mac_cmd = true; 00097 status = LORAWAN_STATUS_OK; 00098 } 00099 break; 00100 case MOTE_MAC_DEV_STATUS_ANS : 00101 if (mac_cmd_buf_idx < (bufLen - 2)) { 00102 mac_cmd_buffer[mac_cmd_buf_idx++] = cmd; 00103 // 1st byte Battery 00104 // 2nd byte Margin 00105 mac_cmd_buffer[mac_cmd_buf_idx++] = p1; 00106 mac_cmd_buffer[mac_cmd_buf_idx++] = p2; 00107 status = LORAWAN_STATUS_OK; 00108 } 00109 break; 00110 case MOTE_MAC_NEW_CHANNEL_ANS : 00111 if (mac_cmd_buf_idx < (bufLen - 1)) { 00112 mac_cmd_buffer[mac_cmd_buf_idx++] = cmd; 00113 // Status: Datarate range OK, Channel frequency OK 00114 mac_cmd_buffer[mac_cmd_buf_idx++] = p1; 00115 status = LORAWAN_STATUS_OK; 00116 } 00117 break; 00118 case MOTE_MAC_RX_TIMING_SETUP_ANS : 00119 if (mac_cmd_buf_idx < bufLen) { 00120 mac_cmd_buffer[mac_cmd_buf_idx++] = cmd; 00121 // No payload for this answer 00122 // This is a sticky MAC command answer. Setup indication 00123 // _lora_mac.set_mlme_schedule_ul_indication(); 00124 sticky_mac_cmd = true; 00125 status = LORAWAN_STATUS_OK; 00126 } 00127 break; 00128 case MOTE_MAC_TX_PARAM_SETUP_ANS : 00129 if (mac_cmd_buf_idx < bufLen) { 00130 mac_cmd_buffer[mac_cmd_buf_idx++] = cmd; 00131 // No payload for this answer 00132 status = LORAWAN_STATUS_OK; 00133 } 00134 break; 00135 case MOTE_MAC_DL_CHANNEL_ANS : 00136 if (mac_cmd_buf_idx < bufLen) { 00137 mac_cmd_buffer[mac_cmd_buf_idx++] = cmd; 00138 // Status: Uplink frequency exists, Channel frequency OK 00139 mac_cmd_buffer[mac_cmd_buf_idx++] = p1; 00140 // This is a sticky MAC command answer. Setup indication 00141 // _lora_mac.set_mlme_schedule_ul_indication(); 00142 sticky_mac_cmd = true; 00143 status = LORAWAN_STATUS_OK; 00144 } 00145 break; 00146 default: 00147 return LORAWAN_STATUS_SERVICE_UNKNOWN; 00148 } 00149 if (status == LORAWAN_STATUS_OK) { 00150 mac_cmd_in_next_tx = true; 00151 } 00152 return status; 00153 } 00154 00155 void LoRaMacCommand::clear_command_buffer() 00156 { 00157 mac_cmd_buf_idx = 0; 00158 } 00159 00160 uint8_t LoRaMacCommand::get_mac_cmd_length() const 00161 { 00162 return mac_cmd_buf_idx; 00163 } 00164 00165 uint8_t *LoRaMacCommand::get_mac_commands_buffer() 00166 { 00167 return mac_cmd_buffer; 00168 } 00169 00170 void LoRaMacCommand::parse_mac_commands_to_repeat() 00171 { 00172 uint8_t i = 0; 00173 uint8_t cmd_cnt = 0; 00174 00175 for (i = 0; i < mac_cmd_buf_idx; i++) { 00176 switch (mac_cmd_buffer[i]) { 00177 // STICKY 00178 case MOTE_MAC_DL_CHANNEL_ANS : 00179 case MOTE_MAC_RX_PARAM_SETUP_ANS : { // 1 byte payload 00180 mac_cmd_buffer_to_repeat[cmd_cnt++] = mac_cmd_buffer[i++]; 00181 mac_cmd_buffer_to_repeat[cmd_cnt++] = mac_cmd_buffer[i]; 00182 break; 00183 } 00184 case MOTE_MAC_RX_TIMING_SETUP_ANS : { // 0 byte payload 00185 mac_cmd_buffer_to_repeat[cmd_cnt++] = mac_cmd_buffer[i]; 00186 break; 00187 } 00188 // NON-STICKY 00189 case MOTE_MAC_DEV_STATUS_ANS : { // 2 bytes payload 00190 i += 2; 00191 break; 00192 } 00193 case MOTE_MAC_LINK_ADR_ANS : 00194 case MOTE_MAC_NEW_CHANNEL_ANS : { // 1 byte payload 00195 i++; 00196 break; 00197 } 00198 case MOTE_MAC_TX_PARAM_SETUP_ANS : 00199 case MOTE_MAC_DUTY_CYCLE_ANS : 00200 case MOTE_MAC_LINK_CHECK_REQ : { // 0 byte payload 00201 break; 00202 } 00203 default: 00204 break; 00205 } 00206 } 00207 00208 if (cmd_cnt > 0) { 00209 mac_cmd_in_next_tx = true; 00210 } else { 00211 mac_cmd_in_next_tx = false; 00212 } 00213 mac_cmd_buf_idx_to_repeat = cmd_cnt; 00214 } 00215 00216 00217 void LoRaMacCommand::clear_repeat_buffer() 00218 { 00219 mac_cmd_buf_idx_to_repeat = 0; 00220 } 00221 00222 void LoRaMacCommand::copy_repeat_commands_to_buffer() 00223 { 00224 memcpy(&mac_cmd_buffer[mac_cmd_buf_idx], mac_cmd_buffer_to_repeat, mac_cmd_buf_idx_to_repeat); 00225 mac_cmd_buf_idx += mac_cmd_buf_idx_to_repeat; 00226 } 00227 00228 uint8_t LoRaMacCommand::get_repeat_commands_length() const 00229 { 00230 return mac_cmd_buf_idx_to_repeat; 00231 } 00232 00233 void LoRaMacCommand::clear_mac_commands_in_next_tx() 00234 { 00235 mac_cmd_in_next_tx = false; 00236 } 00237 00238 bool LoRaMacCommand::is_mac_command_in_next_tx() const 00239 { 00240 return mac_cmd_in_next_tx; 00241 } 00242 00243 void LoRaMacCommand::clear_sticky_mac_cmd() 00244 { 00245 sticky_mac_cmd = false; 00246 } 00247 00248 bool LoRaMacCommand::has_sticky_mac_cmd() const 00249 { 00250 return sticky_mac_cmd; 00251 } 00252 00253 lorawan_status_t LoRaMacCommand::process_mac_commands(uint8_t *payload, uint8_t mac_index, 00254 uint8_t commands_size, uint8_t snr, 00255 loramac_mlme_confirm_t & mlme_conf, 00256 lora_mac_system_params_t &mac_sys_params, 00257 LoRaPHY &lora_phy) 00258 { 00259 uint8_t status = 0; 00260 lorawan_status_t ret_value = LORAWAN_STATUS_OK; 00261 00262 while (mac_index < commands_size) { 00263 // Decode Frame MAC commands 00264 switch (payload[mac_index++]) { 00265 case SRV_MAC_LINK_CHECK_ANS : 00266 mlme_conf.status = LORAMAC_EVENT_INFO_STATUS_OK ; 00267 mlme_conf.demod_margin = payload[mac_index++]; 00268 mlme_conf.nb_gateways = payload[mac_index++]; 00269 break; 00270 case SRV_MAC_LINK_ADR_REQ : { 00271 adr_req_params_t linkAdrReq; 00272 int8_t linkAdrDatarate = DR_0; 00273 int8_t linkAdrTxPower = TX_POWER_0; 00274 uint8_t linkAdrNbRep = 0; 00275 uint8_t linkAdrNbBytesParsed = 0; 00276 00277 // Fill parameter structure 00278 linkAdrReq.payload = &payload[mac_index - 1]; 00279 linkAdrReq.payload_size = commands_size - (mac_index - 1); 00280 linkAdrReq.adr_enabled = mac_sys_params.adr_on ; 00281 linkAdrReq.ul_dwell_time = mac_sys_params.uplink_dwell_time ; 00282 linkAdrReq.current_datarate = mac_sys_params.channel_data_rate ; 00283 linkAdrReq.current_tx_power = mac_sys_params.channel_tx_power ; 00284 linkAdrReq.current_nb_rep = mac_sys_params.retry_num ; 00285 00286 // Process the ADR requests 00287 status = lora_phy.link_ADR_request(&linkAdrReq, 00288 &linkAdrDatarate, 00289 &linkAdrTxPower, 00290 &linkAdrNbRep, 00291 &linkAdrNbBytesParsed); 00292 00293 if ((status & 0x07) == 0x07) { 00294 mac_sys_params.channel_data_rate = linkAdrDatarate; 00295 mac_sys_params.channel_tx_power = linkAdrTxPower; 00296 mac_sys_params.retry_num = linkAdrNbRep; 00297 } 00298 00299 // Add the answers to the buffer 00300 for (uint8_t i = 0; i < (linkAdrNbBytesParsed / 5); i++) { 00301 ret_value = add_mac_command(MOTE_MAC_LINK_ADR_ANS , status, 0); 00302 } 00303 // Update MAC index 00304 mac_index += linkAdrNbBytesParsed - 1; 00305 } 00306 break; 00307 case SRV_MAC_DUTY_CYCLE_REQ : 00308 mac_sys_params.max_duty_cycle = payload[mac_index++]; 00309 mac_sys_params.aggregated_duty_cycle = 1 << mac_sys_params.max_duty_cycle ; 00310 ret_value = add_mac_command(MOTE_MAC_DUTY_CYCLE_ANS , 0, 0); 00311 break; 00312 case SRV_MAC_RX_PARAM_SETUP_REQ : { 00313 rx_param_setup_req_t rxParamSetupReq; 00314 00315 rxParamSetupReq.dr_offset = (payload[mac_index] >> 4) & 0x07; 00316 rxParamSetupReq.datarate = payload[mac_index] & 0x0F; 00317 mac_index++; 00318 00319 rxParamSetupReq.frequency = (uint32_t) payload[mac_index++]; 00320 rxParamSetupReq.frequency |= (uint32_t) payload[mac_index++] 00321 << 8; 00322 rxParamSetupReq.frequency |= (uint32_t) payload[mac_index++] 00323 << 16; 00324 rxParamSetupReq.frequency *= 100; 00325 00326 // Perform request on region 00327 status = lora_phy.accept_rx_param_setup_req(&rxParamSetupReq); 00328 00329 if ((status & 0x07) == 0x07) { 00330 mac_sys_params.rx2_channel .datarate = 00331 rxParamSetupReq.datarate; 00332 mac_sys_params.rx2_channel .frequency = 00333 rxParamSetupReq.frequency; 00334 mac_sys_params.rx1_dr_offset = rxParamSetupReq.dr_offset; 00335 } 00336 ret_value = add_mac_command(MOTE_MAC_RX_PARAM_SETUP_ANS , status, 00337 0); 00338 } 00339 break; 00340 case SRV_MAC_DEV_STATUS_REQ : { 00341 uint8_t batteryLevel = BAT_LEVEL_NO_MEASURE ; 00342 // we don't have a mechanism at the moment to measure 00343 // battery levels 00344 ret_value = add_mac_command(MOTE_MAC_DEV_STATUS_ANS , 00345 batteryLevel, snr & 0x3F); 00346 break; 00347 } 00348 case SRV_MAC_NEW_CHANNEL_REQ : { 00349 channel_params_t chParam; 00350 int8_t channel_id = payload[mac_index++]; 00351 00352 chParam.frequency = (uint32_t) payload[mac_index++]; 00353 chParam.frequency |= (uint32_t) payload[mac_index++] << 8; 00354 chParam.frequency |= (uint32_t) payload[mac_index++] << 16; 00355 chParam.frequency *= 100; 00356 chParam.rx1_frequency = 0; 00357 chParam.dr_range .value = payload[mac_index++]; 00358 00359 status = lora_phy.request_new_channel(channel_id, &chParam); 00360 00361 ret_value = add_mac_command(MOTE_MAC_NEW_CHANNEL_ANS , status, 0); 00362 } 00363 break; 00364 case SRV_MAC_RX_TIMING_SETUP_REQ : { 00365 uint8_t delay = payload[mac_index++] & 0x0F; 00366 00367 if (delay == 0) { 00368 delay++; 00369 } 00370 mac_sys_params.recv_delay1 = delay * 1000; 00371 mac_sys_params.recv_delay2 = mac_sys_params.recv_delay1 + 1000; 00372 ret_value = add_mac_command(MOTE_MAC_RX_TIMING_SETUP_ANS , 0, 0); 00373 } 00374 break; 00375 case SRV_MAC_TX_PARAM_SETUP_REQ : { 00376 uint8_t eirpDwellTime = payload[mac_index++]; 00377 uint8_t ul_dwell_time; 00378 uint8_t dl_dwell_time; 00379 uint8_t max_eirp; 00380 00381 ul_dwell_time = 0; 00382 dl_dwell_time = 0; 00383 00384 if ((eirpDwellTime & 0x20) == 0x20) { 00385 dl_dwell_time = 1; 00386 } 00387 if ((eirpDwellTime & 0x10) == 0x10) { 00388 ul_dwell_time = 1; 00389 } 00390 max_eirp = eirpDwellTime & 0x0F; 00391 00392 // Check the status for correctness 00393 if (lora_phy.accept_tx_param_setup_req(ul_dwell_time, dl_dwell_time)) { 00394 // Accept command 00395 mac_sys_params.uplink_dwell_time = 00396 ul_dwell_time; 00397 mac_sys_params.downlink_dwell_time = 00398 dl_dwell_time; 00399 mac_sys_params.max_eirp = 00400 max_eirp_table[max_eirp]; 00401 // Add command response 00402 ret_value = add_mac_command(MOTE_MAC_TX_PARAM_SETUP_ANS , 0, 0); 00403 } 00404 } 00405 break; 00406 case SRV_MAC_DL_CHANNEL_REQ : { 00407 00408 uint8_t channel_id = payload[mac_index++]; 00409 uint32_t rx1_frequency; 00410 00411 rx1_frequency = (uint32_t) payload[mac_index++]; 00412 rx1_frequency |= (uint32_t) payload[mac_index++] << 8; 00413 rx1_frequency |= (uint32_t) payload[mac_index++] << 16; 00414 rx1_frequency *= 100; 00415 00416 status = lora_phy.dl_channel_request(channel_id, rx1_frequency); 00417 00418 ret_value = add_mac_command(MOTE_MAC_DL_CHANNEL_ANS , status, 0); 00419 } 00420 break; 00421 default: 00422 // Unknown command. ABORT MAC commands processing 00423 ret_value = LORAWAN_STATUS_UNSUPPORTED; 00424 } 00425 } 00426 return ret_value; 00427 } 00428 00429 bool LoRaMacCommand::is_sticky_mac_command_pending() 00430 { 00431 if (mac_cmd_buf_idx_to_repeat > 0) { 00432 return true; 00433 } 00434 return false; 00435 }
Generated on Tue Jul 12 2022 15:17:25 by
1.7.2