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