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.
Dependencies: nRF51_Vdd TextLCD BME280
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 link_adr_req; 00149 int8_t link_adr_dr = DR_0; 00150 int8_t link_adr_txpower = TX_POWER_0; 00151 uint8_t link_adr_nbtrans = 0; 00152 uint8_t link_adr_nb_bytes_pasred = 0; 00153 00154 // Fill parameter structure 00155 link_adr_req.payload = &payload[mac_index - 1]; 00156 link_adr_req.payload_size = commands_size - (mac_index - 1); 00157 link_adr_req.adr_enabled = mac_sys_params.adr_on ; 00158 link_adr_req.ul_dwell_time = mac_sys_params.uplink_dwell_time ; 00159 link_adr_req.current_datarate = mac_sys_params.channel_data_rate ; 00160 link_adr_req.current_tx_power = mac_sys_params.channel_tx_power ; 00161 link_adr_req.current_nb_trans = mac_sys_params.nb_trans ; 00162 00163 // Process the ADR requests 00164 status = lora_phy.link_ADR_request(&link_adr_req, 00165 &link_adr_dr, 00166 &link_adr_txpower, 00167 &link_adr_nbtrans, 00168 &link_adr_nb_bytes_pasred); 00169 00170 if ((status & 0x07) == 0x07) { 00171 mac_sys_params.channel_data_rate = link_adr_dr; 00172 mac_sys_params.channel_tx_power = link_adr_txpower; 00173 mac_sys_params.nb_trans = link_adr_nbtrans; 00174 } 00175 00176 // Add the answers to the buffer 00177 for (uint8_t i = 0; i < (link_adr_nb_bytes_pasred / 5); i++) { 00178 ret_value = add_link_adr_ans(status); 00179 } 00180 // Update MAC index 00181 mac_index += link_adr_nb_bytes_pasred - 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 Jul 12 2022 15:15:48 by
