init
Embed:
(wiki syntax)
Show/hide line numbers
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:24:47 by
1.7.2