Gleb Klochkov / Mbed OS Climatcontroll_Main

Dependencies:   esp8266-driver

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 #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()
00043 {
00044     mac_cmd_in_next_tx = false;
00045     sticky_mac_cmd = 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                 sticky_mac_cmd = true;
00096                 status = LORAWAN_STATUS_OK;
00097             }
00098             break;
00099         case MOTE_MAC_DEV_STATUS_ANS :
00100             if (mac_cmd_buf_idx < (bufLen - 2)) {
00101                 mac_cmd_buffer[mac_cmd_buf_idx++] = cmd;
00102                 // 1st byte Battery
00103                 // 2nd byte Margin
00104                 mac_cmd_buffer[mac_cmd_buf_idx++] = p1;
00105                 mac_cmd_buffer[mac_cmd_buf_idx++] = p2;
00106                 status = LORAWAN_STATUS_OK;
00107             }
00108             break;
00109         case MOTE_MAC_NEW_CHANNEL_ANS :
00110             if (mac_cmd_buf_idx < (bufLen - 1)) {
00111                 mac_cmd_buffer[mac_cmd_buf_idx++] = cmd;
00112                 // Status: Datarate range OK, Channel frequency OK
00113                 mac_cmd_buffer[mac_cmd_buf_idx++] = p1;
00114                 status = LORAWAN_STATUS_OK;
00115             }
00116             break;
00117         case MOTE_MAC_RX_TIMING_SETUP_ANS :
00118             if (mac_cmd_buf_idx < bufLen) {
00119                 mac_cmd_buffer[mac_cmd_buf_idx++] = cmd;
00120                 // No payload for this answer
00121                 // This is a sticky MAC command answer. Setup indication
00122 //                _lora_mac.set_mlme_schedule_ul_indication();
00123                 sticky_mac_cmd = true;
00124                 status = LORAWAN_STATUS_OK;
00125             }
00126             break;
00127         case MOTE_MAC_TX_PARAM_SETUP_ANS :
00128             if (mac_cmd_buf_idx < bufLen) {
00129                 mac_cmd_buffer[mac_cmd_buf_idx++] = cmd;
00130                 // No payload for this answer
00131                 status = LORAWAN_STATUS_OK;
00132             }
00133             break;
00134         case MOTE_MAC_DL_CHANNEL_ANS :
00135             if (mac_cmd_buf_idx < bufLen) {
00136                 mac_cmd_buffer[mac_cmd_buf_idx++] = cmd;
00137                 // Status: Uplink frequency exists, Channel frequency OK
00138                 mac_cmd_buffer[mac_cmd_buf_idx++] = p1;
00139                 // This is a sticky MAC command answer. Setup indication
00140 //                _lora_mac.set_mlme_schedule_ul_indication();
00141                 sticky_mac_cmd = true;
00142                 status = LORAWAN_STATUS_OK;
00143             }
00144             break;
00145         default:
00146             return LORAWAN_STATUS_SERVICE_UNKNOWN;
00147     }
00148     if (status == LORAWAN_STATUS_OK) {
00149         mac_cmd_in_next_tx = true;
00150     }
00151     return status;
00152 }
00153 
00154 void LoRaMacCommand::clear_command_buffer()
00155 {
00156     mac_cmd_buf_idx = 0;
00157 }
00158 
00159 uint8_t LoRaMacCommand::get_mac_cmd_length() const
00160 {
00161     return mac_cmd_buf_idx;
00162 }
00163 
00164 uint8_t *LoRaMacCommand::get_mac_commands_buffer()
00165 {
00166     return mac_cmd_buffer;
00167 }
00168 
00169 void LoRaMacCommand::parse_mac_commands_to_repeat()
00170 {
00171     uint8_t i = 0;
00172     uint8_t cmd_cnt = 0;
00173 
00174     for (i = 0; i < mac_cmd_buf_idx; i++) {
00175         switch (mac_cmd_buffer[i]) {
00176             // STICKY
00177             case MOTE_MAC_DL_CHANNEL_ANS :
00178             case MOTE_MAC_RX_PARAM_SETUP_ANS : { // 1 byte payload
00179                 mac_cmd_buffer_to_repeat[cmd_cnt++] = mac_cmd_buffer[i++];
00180                 mac_cmd_buffer_to_repeat[cmd_cnt++] = mac_cmd_buffer[i];
00181                 break;
00182             }
00183             case MOTE_MAC_RX_TIMING_SETUP_ANS : { // 0 byte payload
00184                 mac_cmd_buffer_to_repeat[cmd_cnt++] = mac_cmd_buffer[i];
00185                 break;
00186             }
00187                 // NON-STICKY
00188             case MOTE_MAC_DEV_STATUS_ANS : { // 2 bytes payload
00189                 i += 2;
00190                 break;
00191             }
00192             case MOTE_MAC_LINK_ADR_ANS :
00193             case MOTE_MAC_NEW_CHANNEL_ANS : { // 1 byte payload
00194                 i++;
00195                 break;
00196             }
00197             case MOTE_MAC_TX_PARAM_SETUP_ANS :
00198             case MOTE_MAC_DUTY_CYCLE_ANS :
00199             case MOTE_MAC_LINK_CHECK_REQ : { // 0 byte payload
00200                 break;
00201             }
00202             default:
00203                 break;
00204         }
00205     }
00206 
00207     if (cmd_cnt > 0) {
00208         mac_cmd_in_next_tx = true;
00209     } else {
00210         mac_cmd_in_next_tx = false;
00211     }
00212     mac_cmd_buf_idx_to_repeat = cmd_cnt;
00213 }
00214 
00215 
00216 void LoRaMacCommand::clear_repeat_buffer()
00217 {
00218     mac_cmd_buf_idx_to_repeat = 0;
00219 }
00220 
00221 void LoRaMacCommand::copy_repeat_commands_to_buffer()
00222 {
00223     memcpy(&mac_cmd_buffer[mac_cmd_buf_idx], mac_cmd_buffer_to_repeat, mac_cmd_buf_idx_to_repeat);
00224     mac_cmd_buf_idx += mac_cmd_buf_idx_to_repeat;
00225 }
00226 
00227 uint8_t LoRaMacCommand::get_repeat_commands_length() const
00228 {
00229     return mac_cmd_buf_idx_to_repeat;
00230 }
00231 
00232 void LoRaMacCommand::clear_mac_commands_in_next_tx()
00233 {
00234     mac_cmd_in_next_tx = false;
00235 }
00236 
00237 bool LoRaMacCommand::is_mac_command_in_next_tx() const
00238 {
00239     return mac_cmd_in_next_tx;
00240 }
00241 
00242 void LoRaMacCommand::clear_sticky_mac_cmd()
00243 {
00244     sticky_mac_cmd = false;
00245 }
00246 
00247 bool LoRaMacCommand::has_sticky_mac_cmd() const
00248 {
00249     return sticky_mac_cmd;
00250 }
00251 
00252 lorawan_status_t LoRaMacCommand::process_mac_commands(uint8_t *payload, uint8_t mac_index,
00253                                                       uint8_t commands_size, uint8_t snr,
00254                                                       loramac_mlme_confirm_t & mlme_conf,
00255                                                       lora_mac_system_params_t  &mac_sys_params,
00256                                                       LoRaPHY &lora_phy)
00257 {
00258     uint8_t status = 0;
00259     lorawan_status_t ret_value = LORAWAN_STATUS_OK;
00260 
00261     while (mac_index < commands_size) {
00262         // Decode Frame MAC commands
00263         switch (payload[mac_index++]) {
00264             case SRV_MAC_LINK_CHECK_ANS :
00265                 mlme_conf.status  = LORAMAC_EVENT_INFO_STATUS_OK ;
00266                 mlme_conf.demod_margin  = payload[mac_index++];
00267                 mlme_conf.nb_gateways  = payload[mac_index++];
00268                 break;
00269             case SRV_MAC_LINK_ADR_REQ : {
00270                 adr_req_params_t linkAdrReq;
00271                 int8_t linkAdrDatarate = DR_0;
00272                 int8_t linkAdrTxPower = TX_POWER_0;
00273                 uint8_t linkAdrNbRep = 0;
00274                 uint8_t linkAdrNbBytesParsed = 0;
00275 
00276                 // Fill parameter structure
00277                 linkAdrReq.payload  = &payload[mac_index - 1];
00278                 linkAdrReq.payload_size  = commands_size - (mac_index - 1);
00279                 linkAdrReq.adr_enabled  = mac_sys_params.adr_on ;
00280                 linkAdrReq.ul_dwell_time  = mac_sys_params.uplink_dwell_time ;
00281                 linkAdrReq.current_datarate  = mac_sys_params.channel_data_rate ;
00282                 linkAdrReq.current_tx_power  = mac_sys_params.channel_tx_power ;
00283                 linkAdrReq.current_nb_rep  = mac_sys_params.retry_num ;
00284 
00285                 // Process the ADR requests
00286                 status = lora_phy.link_ADR_request(&linkAdrReq,
00287                                                    &linkAdrDatarate,
00288                                                    &linkAdrTxPower,
00289                                                    &linkAdrNbRep,
00290                                                    &linkAdrNbBytesParsed);
00291 
00292                 if ((status & 0x07) == 0x07) {
00293                     mac_sys_params.channel_data_rate  = linkAdrDatarate;
00294                     mac_sys_params.channel_tx_power  = linkAdrTxPower;
00295                     mac_sys_params.retry_num  = linkAdrNbRep;
00296                 }
00297 
00298                 // Add the answers to the buffer
00299                 for (uint8_t i = 0; i < (linkAdrNbBytesParsed / 5); i++) {
00300                     ret_value = add_mac_command(MOTE_MAC_LINK_ADR_ANS , status, 0);
00301                 }
00302                 // Update MAC index
00303                 mac_index += linkAdrNbBytesParsed - 1;
00304             }
00305                 break;
00306             case SRV_MAC_DUTY_CYCLE_REQ :
00307                 mac_sys_params.max_duty_cycle  = payload[mac_index++];
00308                 mac_sys_params.aggregated_duty_cycle  = 1 << mac_sys_params.max_duty_cycle ;
00309                 ret_value = add_mac_command(MOTE_MAC_DUTY_CYCLE_ANS , 0, 0);
00310                 break;
00311             case SRV_MAC_RX_PARAM_SETUP_REQ : {
00312                 rx_param_setup_req_t rxParamSetupReq;
00313 
00314                 rxParamSetupReq.dr_offset = (payload[mac_index] >> 4) & 0x07;
00315                 rxParamSetupReq.datarate = payload[mac_index] & 0x0F;
00316                 mac_index++;
00317 
00318                 rxParamSetupReq.frequency = (uint32_t) payload[mac_index++];
00319                 rxParamSetupReq.frequency |= (uint32_t) payload[mac_index++]
00320                         << 8;
00321                 rxParamSetupReq.frequency |= (uint32_t) payload[mac_index++]
00322                         << 16;
00323                 rxParamSetupReq.frequency *= 100;
00324 
00325                 // Perform request on region
00326                 status = lora_phy.accept_rx_param_setup_req(&rxParamSetupReq);
00327 
00328                 if ((status & 0x07) == 0x07) {
00329                     mac_sys_params.rx2_channel .datarate  =
00330                             rxParamSetupReq.datarate;
00331                     mac_sys_params.rx2_channel .frequency  =
00332                             rxParamSetupReq.frequency;
00333                     mac_sys_params.rx1_dr_offset  = rxParamSetupReq.dr_offset;
00334                 }
00335                 ret_value = add_mac_command(MOTE_MAC_RX_PARAM_SETUP_ANS , status,
00336                                             0);
00337             }
00338                 break;
00339             case SRV_MAC_DEV_STATUS_REQ : {
00340                 uint8_t batteryLevel = BAT_LEVEL_NO_MEASURE ;
00341                 // we don't have a mechanism at the moment to measure
00342                 // battery levels
00343                 ret_value = add_mac_command(MOTE_MAC_DEV_STATUS_ANS ,
00344                                             batteryLevel, snr & 0x3F);
00345                 break;
00346             }
00347             case SRV_MAC_NEW_CHANNEL_REQ : {
00348                 channel_params_t  chParam;
00349                 int8_t channel_id = payload[mac_index++];
00350 
00351                 chParam.frequency  = (uint32_t) payload[mac_index++];
00352                 chParam.frequency  |= (uint32_t) payload[mac_index++] << 8;
00353                 chParam.frequency  |= (uint32_t) payload[mac_index++] << 16;
00354                 chParam.frequency  *= 100;
00355                 chParam.rx1_frequency  = 0;
00356                 chParam.dr_range .value  = payload[mac_index++];
00357 
00358                 status = lora_phy.request_new_channel(channel_id, &chParam);
00359 
00360                 ret_value = add_mac_command(MOTE_MAC_NEW_CHANNEL_ANS , status, 0);
00361             }
00362                 break;
00363             case SRV_MAC_RX_TIMING_SETUP_REQ : {
00364                 uint8_t delay = payload[mac_index++] & 0x0F;
00365 
00366                 if (delay == 0) {
00367                     delay++;
00368                 }
00369                 mac_sys_params.recv_delay1  = delay * 1000;
00370                 mac_sys_params.recv_delay2  = mac_sys_params.recv_delay1  + 1000;
00371                 ret_value = add_mac_command(MOTE_MAC_RX_TIMING_SETUP_ANS , 0, 0);
00372             }
00373                 break;
00374             case SRV_MAC_TX_PARAM_SETUP_REQ : {
00375                 uint8_t eirpDwellTime = payload[mac_index++];
00376                 uint8_t ul_dwell_time;
00377                 uint8_t dl_dwell_time;
00378                 uint8_t max_eirp;
00379 
00380                 ul_dwell_time = 0;
00381                 dl_dwell_time = 0;
00382 
00383                 if ((eirpDwellTime & 0x20) == 0x20) {
00384                     dl_dwell_time = 1;
00385                 }
00386                 if ((eirpDwellTime & 0x10) == 0x10) {
00387                     ul_dwell_time = 1;
00388                 }
00389                 max_eirp = eirpDwellTime & 0x0F;
00390 
00391                 // Check the status for correctness
00392                 if (lora_phy.accept_tx_param_setup_req(ul_dwell_time, dl_dwell_time)) {
00393                     // Accept command
00394                     mac_sys_params.uplink_dwell_time  =
00395                             ul_dwell_time;
00396                     mac_sys_params.downlink_dwell_time  =
00397                             dl_dwell_time;
00398                     mac_sys_params.max_eirp  =
00399                             max_eirp_table[max_eirp];
00400                     // Add command response
00401                     ret_value = add_mac_command(MOTE_MAC_TX_PARAM_SETUP_ANS , 0, 0);
00402                 }
00403             }
00404                 break;
00405             case SRV_MAC_DL_CHANNEL_REQ : {
00406 
00407                 uint8_t channel_id = payload[mac_index++];
00408                 uint32_t rx1_frequency;
00409 
00410                 rx1_frequency = (uint32_t) payload[mac_index++];
00411                 rx1_frequency |= (uint32_t) payload[mac_index++] << 8;
00412                 rx1_frequency |= (uint32_t) payload[mac_index++] << 16;
00413                 rx1_frequency *= 100;
00414 
00415                 status = lora_phy.dl_channel_request(channel_id, rx1_frequency);
00416 
00417                 ret_value = add_mac_command(MOTE_MAC_DL_CHANNEL_ANS , status, 0);
00418             }
00419                 break;
00420             default:
00421                 // Unknown command. ABORT MAC commands processing
00422                 ret_value = LORAWAN_STATUS_UNSUPPORTED;
00423         }
00424     }
00425     return ret_value;
00426 }
00427 
00428 bool LoRaMacCommand::is_sticky_mac_command_pending()
00429 {
00430     if (mac_cmd_buf_idx_to_repeat > 0) {
00431         return true;
00432     }
00433     return false;
00434 }