Kenji Arai / TYBLE16_mbedlized_os5_several_examples_1st

Dependencies:   nRF51_Vdd TextLCD BME280

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LoRaMacCommand.cpp Source File

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 }