Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

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_parsed = 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_parsed);
00169 
00170                 // If nothing was consumed, we have a malformed packet at our hand
00171                 // we bin everything and return. link_adr_nb_bytes_parsed being 0 is
00172                 // a magic identifier letting us know that there are payload inconsistencies
00173                 if (link_adr_nb_bytes_parsed == 0) {
00174                     return LORAWAN_STATUS_UNSUPPORTED;
00175                 }
00176 
00177                 if ((status & 0x07) == 0x07) {
00178                     mac_sys_params.channel_data_rate  = link_adr_dr;
00179                     mac_sys_params.channel_tx_power  = link_adr_txpower;
00180                     mac_sys_params.nb_trans  = link_adr_nbtrans;
00181                 }
00182 
00183                 // Add the answers to the buffer
00184                 for (uint8_t i = 0; i < (link_adr_nb_bytes_parsed / 5); i++) {
00185                     ret_value = add_link_adr_ans(status);
00186                 }
00187                 // Update MAC index
00188                 mac_index += link_adr_nb_bytes_parsed - 1;
00189             }
00190             break;
00191             case SRV_MAC_DUTY_CYCLE_REQ :
00192                 mac_sys_params.max_duty_cycle  = payload[mac_index++];
00193                 mac_sys_params.aggregated_duty_cycle  = 1 << mac_sys_params.max_duty_cycle ;
00194                 ret_value = add_duty_cycle_ans();
00195                 break;
00196             case SRV_MAC_RX_PARAM_SETUP_REQ : {
00197                 rx_param_setup_req_t rxParamSetupReq;
00198 
00199                 rxParamSetupReq.dr_offset = (payload[mac_index] >> 4) & 0x07;
00200                 rxParamSetupReq.datarate = payload[mac_index++] & 0x0F;
00201 
00202                 rxParamSetupReq.frequency = (uint32_t) payload[mac_index++];
00203                 rxParamSetupReq.frequency |= (uint32_t) payload[mac_index++] << 8;
00204                 rxParamSetupReq.frequency |= (uint32_t) payload[mac_index++] << 16;
00205                 rxParamSetupReq.frequency *= 100;
00206 
00207                 // Perform request on region
00208                 status = lora_phy.accept_rx_param_setup_req(&rxParamSetupReq);
00209 
00210                 if ((status & 0x07) == 0x07) {
00211                     mac_sys_params.rx2_channel .datarate  = rxParamSetupReq.datarate;
00212                     mac_sys_params.rx2_channel .frequency  = rxParamSetupReq.frequency;
00213                     mac_sys_params.rx1_dr_offset  = rxParamSetupReq.dr_offset;
00214                 }
00215                 ret_value = add_rx_param_setup_ans(status);
00216             }
00217             break;
00218             case SRV_MAC_DEV_STATUS_REQ : {
00219                 uint8_t battery_level = BAT_LEVEL_NO_MEASURE ;
00220                 if (_battery_level_cb) {
00221                     battery_level = _battery_level_cb();
00222                 }
00223                 ret_value = add_dev_status_ans(battery_level, snr & 0x3F);
00224                 break;
00225             }
00226             case SRV_MAC_NEW_CHANNEL_REQ : {
00227                 channel_params_t chParam;
00228                 int8_t channel_id = payload[mac_index++];
00229 
00230                 chParam.frequency = (uint32_t) payload[mac_index++];
00231                 chParam.frequency |= (uint32_t) payload[mac_index++] << 8;
00232                 chParam.frequency |= (uint32_t) payload[mac_index++] << 16;
00233                 chParam.frequency *= 100;
00234                 chParam.rx1_frequency = 0;
00235                 chParam.dr_range.value = payload[mac_index++];
00236 
00237                 status = lora_phy.request_new_channel(channel_id, &chParam);
00238 
00239                 ret_value = add_new_channel_ans(status);
00240             }
00241             break;
00242             case SRV_MAC_RX_TIMING_SETUP_REQ : {
00243                 uint8_t delay = payload[mac_index++] & 0x0F;
00244 
00245                 if (delay == 0) {
00246                     delay++;
00247                 }
00248                 mac_sys_params.recv_delay1  = delay * 1000;
00249                 mac_sys_params.recv_delay2  = mac_sys_params.recv_delay1  + 1000;
00250                 ret_value = add_rx_timing_setup_ans();
00251             }
00252             break;
00253             case SRV_MAC_TX_PARAM_SETUP_REQ : {
00254                 uint8_t eirpDwellTime = payload[mac_index++];
00255                 uint8_t ul_dwell_time;
00256                 uint8_t dl_dwell_time;
00257                 uint8_t max_eirp;
00258 
00259                 ul_dwell_time = 0;
00260                 dl_dwell_time = 0;
00261 
00262                 if ((eirpDwellTime & 0x20) == 0x20) {
00263                     dl_dwell_time = 1;
00264                 }
00265                 if ((eirpDwellTime & 0x10) == 0x10) {
00266                     ul_dwell_time = 1;
00267                 }
00268                 max_eirp = eirpDwellTime & 0x0F;
00269 
00270                 // Check the status for correctness
00271                 if (lora_phy.accept_tx_param_setup_req(ul_dwell_time, dl_dwell_time)) {
00272                     // Accept command
00273                     mac_sys_params.uplink_dwell_time  = ul_dwell_time;
00274                     mac_sys_params.downlink_dwell_time  = dl_dwell_time;
00275                     mac_sys_params.max_eirp  = max_eirp_table[max_eirp];
00276                     // Add command response
00277                     ret_value = add_tx_param_setup_ans();
00278                 }
00279             }
00280             break;
00281             case SRV_MAC_DL_CHANNEL_REQ : {
00282                 uint8_t channel_id = payload[mac_index++];
00283                 uint32_t rx1_frequency;
00284 
00285                 rx1_frequency = (uint32_t) payload[mac_index++];
00286                 rx1_frequency |= (uint32_t) payload[mac_index++] << 8;
00287                 rx1_frequency |= (uint32_t) payload[mac_index++] << 16;
00288                 rx1_frequency *= 100;
00289                 status = lora_phy.dl_channel_request(channel_id, rx1_frequency);
00290 
00291                 ret_value = add_dl_channel_ans(status);
00292             }
00293             break;
00294             default:
00295                 // Unknown command. ABORT MAC commands processing
00296                 tr_error("Invalid MAC command (0x%X)!", payload[mac_index]);
00297                 return LORAWAN_STATUS_UNSUPPORTED;
00298         }
00299     }
00300     return ret_value;
00301 }
00302 
00303 int32_t LoRaMacCommand::cmd_buffer_remaining() const
00304 {
00305     // The maximum buffer length must take MAC commands to re-send into account.
00306     return sizeof(mac_cmd_buffer) - mac_cmd_buf_idx_to_repeat - mac_cmd_buf_idx;
00307 }
00308 
00309 void LoRaMacCommand::set_batterylevel_callback(mbed::Callback<uint8_t(void)> battery_level)
00310 {
00311     _battery_level_cb = battery_level;
00312 }
00313 
00314 lorawan_status_t LoRaMacCommand::add_link_check_req()
00315 {
00316     lorawan_status_t ret = LORAWAN_STATUS_LENGTH_ERROR;
00317     if (cmd_buffer_remaining() > 0) {
00318         mac_cmd_buffer[mac_cmd_buf_idx++] = MOTE_MAC_LINK_CHECK_REQ ;
00319         // No payload for this command
00320         ret = LORAWAN_STATUS_OK;
00321     }
00322     return ret;
00323 }
00324 
00325 lorawan_status_t LoRaMacCommand::add_link_adr_ans(uint8_t status)
00326 {
00327     lorawan_status_t ret = LORAWAN_STATUS_LENGTH_ERROR;
00328     if (cmd_buffer_remaining() > 1) {
00329         mac_cmd_buffer[mac_cmd_buf_idx++] = MOTE_MAC_LINK_ADR_ANS ;
00330         mac_cmd_buffer[mac_cmd_buf_idx++] = status;
00331         ret = LORAWAN_STATUS_OK;
00332     }
00333     return ret;
00334 }
00335 
00336 lorawan_status_t LoRaMacCommand::add_duty_cycle_ans()
00337 {
00338     lorawan_status_t ret = LORAWAN_STATUS_LENGTH_ERROR;
00339     if (cmd_buffer_remaining() > 0) {
00340         mac_cmd_buffer[mac_cmd_buf_idx++] = MOTE_MAC_DUTY_CYCLE_ANS ;
00341         // No payload for this answer
00342         ret = LORAWAN_STATUS_OK;
00343     }
00344     return ret;
00345 }
00346 
00347 lorawan_status_t LoRaMacCommand::add_rx_param_setup_ans(uint8_t status)
00348 {
00349     lorawan_status_t ret = LORAWAN_STATUS_LENGTH_ERROR;
00350     if (cmd_buffer_remaining() > 1) {
00351         mac_cmd_buffer[mac_cmd_buf_idx++] = MOTE_MAC_RX_PARAM_SETUP_ANS ;
00352         // Status: Datarate ACK, Channel ACK
00353         mac_cmd_buffer[mac_cmd_buf_idx++] = status;
00354         // This is a sticky MAC command answer. Setup indication
00355         sticky_mac_cmd = true;
00356         ret = LORAWAN_STATUS_OK;
00357     }
00358     return ret;
00359 }
00360 
00361 lorawan_status_t LoRaMacCommand::add_dev_status_ans(uint8_t battery, uint8_t margin)
00362 {
00363     lorawan_status_t ret = LORAWAN_STATUS_LENGTH_ERROR;
00364     if (cmd_buffer_remaining() > 2) {
00365         mac_cmd_buffer[mac_cmd_buf_idx++] = MOTE_MAC_DEV_STATUS_ANS ;
00366         // 1st byte Battery
00367         // 2nd byte Margin
00368         mac_cmd_buffer[mac_cmd_buf_idx++] = battery;
00369         mac_cmd_buffer[mac_cmd_buf_idx++] = margin;
00370         ret = LORAWAN_STATUS_OK;
00371     }
00372     return ret;
00373 }
00374 
00375 lorawan_status_t LoRaMacCommand::add_new_channel_ans(uint8_t status)
00376 {
00377     lorawan_status_t ret = LORAWAN_STATUS_LENGTH_ERROR;
00378     if (cmd_buffer_remaining() > 1) {
00379         mac_cmd_buffer[mac_cmd_buf_idx++] = MOTE_MAC_NEW_CHANNEL_ANS ;
00380         // Status: Datarate range OK, Channel frequency OK
00381         mac_cmd_buffer[mac_cmd_buf_idx++] = status;
00382         ret = LORAWAN_STATUS_OK;
00383     }
00384     return ret;
00385 }
00386 
00387 lorawan_status_t LoRaMacCommand::add_rx_timing_setup_ans()
00388 {
00389     lorawan_status_t ret = LORAWAN_STATUS_LENGTH_ERROR;
00390     if (cmd_buffer_remaining() > 0) {
00391         mac_cmd_buffer[mac_cmd_buf_idx++] = MOTE_MAC_RX_TIMING_SETUP_ANS ;
00392         // No payload for this answer
00393         // This is a sticky MAC command answer. Setup indication
00394         sticky_mac_cmd = true;
00395         ret = LORAWAN_STATUS_OK;
00396     }
00397     return ret;
00398 }
00399 
00400 lorawan_status_t LoRaMacCommand::add_tx_param_setup_ans()
00401 {
00402     lorawan_status_t ret = LORAWAN_STATUS_LENGTH_ERROR;
00403     if (cmd_buffer_remaining() > 0) {
00404         mac_cmd_buffer[mac_cmd_buf_idx++] = MOTE_MAC_TX_PARAM_SETUP_ANS ;
00405         // No payload for this answer
00406         ret = LORAWAN_STATUS_OK;
00407     }
00408     return ret;
00409 }
00410 
00411 lorawan_status_t LoRaMacCommand::add_dl_channel_ans(uint8_t status)
00412 {
00413     lorawan_status_t ret = LORAWAN_STATUS_LENGTH_ERROR;
00414     if (cmd_buffer_remaining() > 1) {
00415         mac_cmd_buffer[mac_cmd_buf_idx++] = MOTE_MAC_DL_CHANNEL_ANS ;
00416         // Status: Uplink frequency exists, Channel frequency OK
00417         mac_cmd_buffer[mac_cmd_buf_idx++] = status;
00418         // This is a sticky MAC command answer. Setup indication
00419         sticky_mac_cmd = true;
00420         ret = LORAWAN_STATUS_OK;
00421     }
00422     return ret;
00423 }