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