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