Knight KE / Mbed OS Game_Master
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LoRaMac.cpp Source File

LoRaMac.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 <stdlib.h>
00025 #include "LoRaMac.h"
00026 
00027 #include "mbed-trace/mbed_trace.h"
00028 #define TRACE_GROUP "LMAC"
00029 
00030 using namespace events;
00031 using namespace mbed;
00032 
00033 /*
00034  * LoRaWAN spec 6.2: AppKey is AES-128 key
00035  */
00036 #define APPKEY_KEY_LENGTH                           128
00037 
00038 /*!
00039  * Maximum length of the fOpts field
00040  */
00041 #define LORA_MAC_COMMAND_MAX_FOPTS_LENGTH           15
00042 
00043 /*!
00044  * LoRaMac duty cycle for the back-off procedure during the first hour.
00045  */
00046 #define BACKOFF_DC_1_HOUR                           100
00047 
00048 /*!
00049  * LoRaMac duty cycle for the back-off procedure during the next 10 hours.
00050  */
00051 #define BACKOFF_DC_10_HOURS                         1000
00052 
00053 /*!
00054  * LoRaMac duty cycle for the back-off procedure during the next 24 hours.
00055  */
00056 #define BACKOFF_DC_24_HOURS                         10000
00057 
00058 /*!
00059  * The frame direction definition for uplink communications.
00060  */
00061 #define UP_LINK                                     0
00062 
00063 /*!
00064  * The frame direction definition for downlink communications.
00065  */
00066 #define DOWN_LINK                                   1
00067 
00068 /**
00069  * A mask for the network ID.
00070  */
00071 #define LORAWAN_NETWORK_ID_MASK                     ( uint32_t )0xFE000000
00072 
00073 
00074 LoRaMac::LoRaMac()
00075     : _lora_time(),
00076       _lora_phy(_lora_time),
00077       _mac_commands(),
00078       _channel_plan(),
00079       _lora_crypto(),
00080       _ev_queue(NULL),
00081       _mcps_indication(),
00082       _mcps_confirmation(),
00083       _mlme_indication(),
00084       _mlme_confirmation(),
00085       _is_nwk_joined(false),
00086       _continuous_rx2_window_open(false),
00087       _device_class(CLASS_A)
00088 {
00089     _params.keys.dev_eui = NULL;
00090     _params.keys.app_eui = NULL;
00091     _params.keys.app_key = NULL;
00092 
00093     memset(_params.keys.nwk_skey, 0, sizeof(_params.keys.nwk_skey));
00094     memset(_params.keys.app_skey, 0, sizeof(_params.keys.app_skey));
00095     memset(&_ongoing_tx_msg, 0, sizeof(_ongoing_tx_msg));
00096 
00097     _params.dev_nonce = 0;
00098     _params.net_id = 0;
00099     _params.dev_addr = 0;
00100     _params.tx_buffer_len = 0;
00101     _params.rx_buffer_len = 0;
00102     _params.ul_frame_counter = 0;
00103     _params.dl_frame_counter = 0;
00104     _params.is_ul_frame_counter_fixed = false;
00105     _params.is_rx_window_enabled = true;
00106     _params.adr_ack_counter = 0;
00107     _params.is_node_ack_requested = false;
00108     _params.is_srv_ack_requested = false;
00109     _params.ul_nb_rep_counter = 0;
00110     _params.timers.mac_init_time = 0;
00111     _params.max_ack_timeout_retries = 1;
00112     _params.ack_timeout_retry_counter = 1;
00113     _params.is_ack_retry_timeout_expired = false;
00114     _params.timers.tx_toa = 0;
00115 
00116     _params.multicast_channels = NULL;
00117 
00118     _params.sys_params.adr_on = false;
00119     _params.sys_params.max_duty_cycle = 0;
00120 
00121     reset_mcps_confirmation();
00122     reset_mlme_confirmation();
00123     reset_mcps_indication();
00124 }
00125 
00126 LoRaMac::~LoRaMac()
00127 {
00128 }
00129 
00130 /***************************************************************************
00131  * Radio event callbacks - delegated to Radio driver                       *
00132  **************************************************************************/
00133 
00134 const loramac_mcps_confirm_t  *LoRaMac::get_mcps_confirmation() const
00135 {
00136     return &_mcps_confirmation;
00137 }
00138 
00139 const loramac_mcps_indication_t  *LoRaMac::get_mcps_indication() const
00140 {
00141     return &_mcps_indication;
00142 }
00143 
00144 const loramac_mlme_confirm_t  *LoRaMac::get_mlme_confirmation() const
00145 {
00146     return &_mlme_confirmation;
00147 }
00148 
00149 const loramac_mlme_indication_t  *LoRaMac::get_mlme_indication() const
00150 {
00151     return &_mlme_indication;
00152 }
00153 
00154 void LoRaMac::post_process_mlme_request()
00155 {
00156     _mlme_confirmation.pending = false;
00157 }
00158 
00159 void LoRaMac::post_process_mcps_req()
00160 {
00161     _params.is_last_tx_join_request = false;
00162     _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_OK ;
00163     if (_mcps_confirmation.req_type == MCPS_CONFIRMED ) {
00164         // An MCPS request for a CONFIRMED message has received an ack
00165         // in the downlink message
00166         if (_mcps_confirmation.ack_received) {
00167             _params.is_node_ack_requested = false;
00168             _mcps_confirmation.ack_received = false;
00169             _mcps_indication.is_ack_recvd = false;
00170             if (_params.is_ul_frame_counter_fixed == false) {
00171                 _params.ul_frame_counter++;
00172             }
00173         }
00174     } else {
00175         //UNCONFIRMED or PROPRIETARY
00176         if (_params.is_ul_frame_counter_fixed == false) {
00177             _params.ul_frame_counter++;
00178         }
00179     }
00180 }
00181 
00182 void LoRaMac::post_process_mcps_ind()
00183 {
00184     _mcps_indication.pending = false;
00185 }
00186 
00187 void LoRaMac::post_process_mlme_ind()
00188 {
00189     _mlme_indication.pending = false;
00190 }
00191 
00192 lorawan_time_t LoRaMac::get_current_time(void)
00193 {
00194     return _lora_time.get_current_time();
00195 }
00196 
00197 rx_slot_t  LoRaMac::get_current_slot(void)
00198 {
00199     return _params.rx_slot;
00200 }
00201 
00202 /**
00203  * This part handles incoming frames in response to Radio RX Interrupt
00204  */
00205 void LoRaMac::handle_join_accept_frame(const uint8_t *payload, uint16_t size)
00206 {
00207     uint32_t mic = 0;
00208     uint32_t mic_rx = 0;
00209 
00210     _mlme_confirmation.nb_retries = _params.join_request_trial_counter;
00211 
00212     if (0 != _lora_crypto.decrypt_join_frame(payload + 1, size - 1,
00213                                              _params.keys.app_key, APPKEY_KEY_LENGTH,
00214                                              _params.rx_buffer + 1)) {
00215         _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL ;
00216         return;
00217     }
00218 
00219     _params.rx_buffer[0] = payload[0];
00220 
00221     if (_lora_crypto.compute_join_frame_mic(_params.rx_buffer,
00222                                             size - LORAMAC_MFR_LEN,
00223                                             _params.keys.app_key,
00224                                             APPKEY_KEY_LENGTH,
00225                                             &mic) != 0) {
00226         _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL ;
00227         return;
00228     }
00229 
00230     mic_rx |= (uint32_t) _params.rx_buffer[size - LORAMAC_MFR_LEN];
00231     mic_rx |= ((uint32_t) _params.rx_buffer[size - LORAMAC_MFR_LEN + 1] << 8);
00232     mic_rx |= ((uint32_t) _params.rx_buffer[size - LORAMAC_MFR_LEN + 2] << 16);
00233     mic_rx |= ((uint32_t) _params.rx_buffer[size - LORAMAC_MFR_LEN + 3] << 24);
00234 
00235     if (mic_rx == mic) {
00236         _lora_time.stop(_params.timers.rx_window2_timer);
00237         if (_lora_crypto.compute_skeys_for_join_frame(_params.keys.app_key,
00238                                                       APPKEY_KEY_LENGTH,
00239                                                       _params.rx_buffer + 1,
00240                                                       _params.dev_nonce,
00241                                                       _params.keys.nwk_skey,
00242                                                       _params.keys.app_skey) != 0) {
00243             _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL ;
00244             return;
00245         }
00246 
00247         _params.net_id = (uint32_t) _params.rx_buffer[4];
00248         _params.net_id |= ((uint32_t) _params.rx_buffer[5] << 8);
00249         _params.net_id |= ((uint32_t) _params.rx_buffer[6] << 16);
00250 
00251         _params.dev_addr = (uint32_t) _params.rx_buffer[7];
00252         _params.dev_addr |= ((uint32_t) _params.rx_buffer[8] << 8);
00253         _params.dev_addr |= ((uint32_t) _params.rx_buffer[9] << 16);
00254         _params.dev_addr |= ((uint32_t) _params.rx_buffer[10] << 24);
00255 
00256         _params.sys_params.rx1_dr_offset = (_params.rx_buffer[11] >> 4) & 0x07;
00257         _params.sys_params.rx2_channel.datarate = _params.rx_buffer[11] & 0x0F;
00258 
00259         _params.sys_params.recv_delay1 = (_params.rx_buffer[12] & 0x0F);
00260 
00261         if (_params.sys_params.recv_delay1 == 0) {
00262             _params.sys_params.recv_delay1 = 1;
00263         }
00264 
00265         _params.sys_params.recv_delay1 *= 1000;
00266         _params.sys_params.recv_delay2 = _params.sys_params.recv_delay1 + 1000;
00267 
00268         // Size of the regular payload is 12. Plus 1 byte MHDR and 4 bytes MIC
00269         _lora_phy.apply_cf_list(&_params.rx_buffer[13], size - 17);
00270 
00271         _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_OK ;
00272         _is_nwk_joined = true;
00273         // Node joined successfully
00274         _params.ul_frame_counter = 0;
00275         _params.ul_nb_rep_counter = 0;
00276 
00277     } else {
00278         _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL ;
00279     }
00280 }
00281 
00282 void LoRaMac::check_frame_size(uint16_t size)
00283 {
00284     uint8_t value = _lora_phy.get_max_payload(_mcps_indication.rx_datarate,
00285                                               _params.is_repeater_supported);
00286 
00287     if (MAX(0, (int16_t)((int16_t)size - (int16_t)LORA_MAC_FRMPAYLOAD_OVERHEAD))
00288             > (int32_t) value) {
00289         tr_error("Invalid frame size");
00290     }
00291 }
00292 
00293 bool LoRaMac::message_integrity_check(const uint8_t *const payload,
00294                                       const uint16_t size,
00295                                       uint8_t *const ptr_pos,
00296                                       uint32_t address,
00297                                       uint32_t *downlink_counter,
00298                                       const uint8_t *nwk_skey)
00299 {
00300     uint32_t mic = 0;
00301     uint32_t mic_rx = 0;
00302 
00303     uint16_t sequence_counter = 0;
00304     uint16_t sequence_counter_prev = 0;
00305     uint16_t sequence_counter_diff = 0;
00306 
00307     sequence_counter = (uint16_t) payload[(*ptr_pos)++];
00308     sequence_counter |= (uint16_t) payload[(*ptr_pos)++] << 8;
00309 
00310     mic_rx |= (uint32_t) payload[size - LORAMAC_MFR_LEN];
00311     mic_rx |= ((uint32_t) payload[size - LORAMAC_MFR_LEN + 1] << 8);
00312     mic_rx |= ((uint32_t) payload[size - LORAMAC_MFR_LEN + 2] << 16);
00313     mic_rx |= ((uint32_t) payload[size - LORAMAC_MFR_LEN + 3] << 24);
00314 
00315     sequence_counter_prev = (uint16_t)*downlink_counter;
00316     sequence_counter_diff = sequence_counter - sequence_counter_prev;
00317     *downlink_counter += sequence_counter_diff;
00318     if (sequence_counter < sequence_counter_prev) {
00319         *downlink_counter += 0x10000;
00320     }
00321 
00322     // sizeof nws_skey must be the same as _params.keys.nwk_skey,
00323     _lora_crypto.compute_mic(payload, size - LORAMAC_MFR_LEN,
00324                              nwk_skey,
00325                              sizeof(_params.keys.nwk_skey) * 8,
00326                              address, DOWN_LINK, *downlink_counter, &mic);
00327 
00328     if (mic_rx != mic) {
00329         _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_MIC_FAIL ;
00330         return false;
00331     }
00332 
00333     if (sequence_counter_diff >= _lora_phy.get_maximum_frame_counter_gap()) {
00334         _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_TOO_MANY_FRAMES_LOST ;
00335         _mcps_indication.dl_frame_counter = *downlink_counter;
00336         return false;
00337     }
00338 
00339     return true;
00340 }
00341 
00342 void LoRaMac::extract_data_and_mac_commands(const uint8_t *payload,
00343                                             uint16_t size,
00344                                             uint8_t fopts_len,
00345                                             uint8_t *nwk_skey,
00346                                             uint8_t *app_skey,
00347                                             uint32_t address,
00348                                             uint32_t downlink_counter,
00349                                             int16_t rssi,
00350                                             int8_t snr)
00351 {
00352     uint8_t frame_len = 0;
00353     uint8_t payload_start_index = 8 + fopts_len;
00354     uint8_t port = payload[payload_start_index++];
00355     frame_len = (size - 4) - payload_start_index;
00356 
00357     _mcps_indication.port = port;
00358 
00359     // special handling of control port 0
00360     if (port == 0) {
00361         if (fopts_len == 0) {
00362             // sizeof nws_skey must be the same as _params.keys.nwk_skey,
00363             if (_lora_crypto.decrypt_payload(payload + payload_start_index,
00364                                              frame_len,
00365                                              nwk_skey,
00366                                              sizeof(_params.keys.nwk_skey) * 8,
00367                                              address,
00368                                              DOWN_LINK,
00369                                              downlink_counter,
00370                                              _params.rx_buffer) != 0) {
00371                 _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL ;
00372             }
00373 
00374             if (_mac_commands.process_mac_commands(_params.rx_buffer, 0, frame_len,
00375                                                    snr, _mlme_confirmation,
00376                                                    _params.sys_params, _lora_phy)
00377                     != LORAWAN_STATUS_OK) {
00378                 _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
00379                 return;
00380             }
00381 
00382             if (_mac_commands.has_sticky_mac_cmd()) {
00383                 set_mlme_schedule_ul_indication();
00384                 _mac_commands.clear_sticky_mac_cmd();
00385             }
00386 
00387             return;
00388         }
00389 
00390         _mcps_indication.pending = false;
00391         _mcps_confirmation.ack_received = false;
00392         _mcps_indication.is_ack_recvd = false;
00393 
00394         return;
00395     }
00396 
00397     // normal unicast/multicast port handling
00398     if (fopts_len > 0) {
00399         // Decode Options field MAC commands. Omit the fPort.
00400         if (_mac_commands.process_mac_commands(payload, 8,
00401                                                payload_start_index - 1,
00402                                                snr,
00403                                                _mlme_confirmation,
00404                                                _params.sys_params,
00405                                                _lora_phy) != LORAWAN_STATUS_OK) {
00406             _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
00407             return;
00408         }
00409 
00410         if (_mac_commands.has_sticky_mac_cmd()) {
00411             set_mlme_schedule_ul_indication();
00412             _mac_commands.clear_sticky_mac_cmd();
00413         }
00414     }
00415 
00416     // sizeof app_skey must be the same as _params.keys.app_skey
00417     if (_lora_crypto.decrypt_payload(payload + payload_start_index,
00418                                      frame_len,
00419                                      app_skey,
00420                                      sizeof(_params.keys.app_skey) * 8,
00421                                      address,
00422                                      DOWN_LINK,
00423                                      downlink_counter,
00424                                      _params.rx_buffer) != 0) {
00425         _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL ;
00426     } else {
00427         _mcps_indication.buffer = _params.rx_buffer;
00428         _mcps_indication.buffer_size = frame_len;
00429         _mcps_indication.is_data_recvd = true;
00430     }
00431 }
00432 
00433 void LoRaMac::extract_mac_commands_only(const uint8_t *payload,
00434                                         int8_t snr,
00435                                         uint8_t fopts_len)
00436 {
00437     uint8_t payload_start_index = 8 + fopts_len;
00438     if (fopts_len > 0) {
00439         if (_mac_commands.process_mac_commands(payload, 8, payload_start_index,
00440                                                snr, _mlme_confirmation,
00441                                                _params.sys_params, _lora_phy)
00442                 != LORAWAN_STATUS_OK) {
00443             _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
00444             return;
00445         }
00446 
00447         if (_mac_commands.has_sticky_mac_cmd()) {
00448             set_mlme_schedule_ul_indication();
00449             _mac_commands.clear_sticky_mac_cmd();
00450         }
00451     }
00452 }
00453 
00454 void LoRaMac::handle_data_frame(const uint8_t *const payload,
00455                                 const uint16_t size,
00456                                 uint8_t ptr_pos,
00457                                 uint8_t msg_type,
00458                                 int16_t rssi,
00459                                 int8_t snr)
00460 {
00461     check_frame_size(size);
00462 
00463     bool is_multicast = false;
00464     loramac_frame_ctrl_t  fctrl;
00465     multicast_params_t  *cur_multicast_params;
00466     uint32_t address = 0;
00467     uint32_t downlink_counter = 0;
00468     uint8_t app_payload_start_index = 0;
00469     uint8_t *nwk_skey = _params.keys.nwk_skey ;
00470     uint8_t *app_skey = _params.keys.app_skey;
00471 
00472     address = payload[ptr_pos++];
00473     address |= ((uint32_t) payload[ptr_pos++] << 8);
00474     address |= ((uint32_t) payload[ptr_pos++] << 16);
00475     address |= ((uint32_t) payload[ptr_pos++] << 24);
00476 
00477     if (address != _params.dev_addr) {
00478         // check if Multicast is destined for us
00479         cur_multicast_params = _params.multicast_channels;
00480 
00481         while (cur_multicast_params != NULL) {
00482             if (address == cur_multicast_params->address ) {
00483                 is_multicast = true;
00484                 nwk_skey = cur_multicast_params->nwk_skey ;
00485                 app_skey = cur_multicast_params->app_skey ;
00486                 downlink_counter = cur_multicast_params->dl_frame_counter ;
00487                 break;
00488             }
00489 
00490             cur_multicast_params = cur_multicast_params->next ;
00491         }
00492 
00493         if (!is_multicast) {
00494             // We are not the destination of this frame.
00495             _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL ;
00496             _mcps_indication.pending = false;
00497             return;
00498         }
00499     } else {
00500         is_multicast = false;
00501         nwk_skey = _params.keys.nwk_skey;
00502         app_skey = _params.keys.app_skey;
00503         downlink_counter = _params.dl_frame_counter;
00504     }
00505 
00506     fctrl.value  = payload[ptr_pos++];
00507     app_payload_start_index = 8 + fctrl.bits.fopts_len ;
00508 
00509     //perform MIC check
00510     if (!message_integrity_check(payload, size, &ptr_pos, address,
00511                                  &downlink_counter, nwk_skey)) {
00512         tr_error("MIC failed");
00513         _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_MIC_FAIL ;
00514         _mcps_indication.pending = false;
00515         return;
00516     }
00517 
00518     // message is intended for us and MIC have passed, stop RX2 Window
00519     // Spec: 3.3.4 Receiver Activity during the receive windows
00520     _lora_time.stop(_params.timers.rx_window2_timer);
00521 
00522     _mcps_confirmation.ack_received = false;
00523     _mcps_indication.is_ack_recvd = false;
00524     _mcps_indication.pending = true;
00525     _mcps_indication.is_data_recvd = false;
00526     _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_OK ;
00527     _mcps_indication.multicast = is_multicast;
00528     _mcps_indication.fpending_status = fctrl.bits.fpending ;
00529     _mcps_indication.buffer = NULL;
00530     _mcps_indication.buffer_size = 0;
00531     _mcps_indication.dl_frame_counter = downlink_counter;
00532     _mcps_indication.rssi = rssi;
00533     _mcps_indication.snr = snr;
00534 
00535     _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_OK ;
00536 
00537     _params.adr_ack_counter = 0;
00538     _mac_commands.clear_repeat_buffer();
00539 
00540     if (is_multicast) {
00541         _mcps_indication.type = MCPS_MULTICAST ;
00542 
00543         // Discard if its a repeated message
00544         if ((cur_multicast_params->dl_frame_counter  == downlink_counter)
00545                 && (cur_multicast_params->dl_frame_counter  != 0)) {
00546             _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED ;
00547             _mcps_indication.dl_frame_counter = downlink_counter;
00548             _mcps_indication.pending = false;
00549 
00550             return;
00551         }
00552 
00553         cur_multicast_params->dl_frame_counter  = downlink_counter;
00554 
00555     } else {
00556         if (msg_type == FRAME_TYPE_DATA_CONFIRMED_DOWN ) {
00557             _params.is_srv_ack_requested = true;
00558             _mcps_indication.type = MCPS_CONFIRMED ;
00559 
00560             if ((_params.dl_frame_counter == downlink_counter)
00561                     && (_params.dl_frame_counter != 0)) {
00562                 // Duplicated confirmed downlink. Skip indication.
00563                 // In this case, the MAC layer shall accept the MAC commands
00564                 // which are included in the downlink retransmission.
00565                 // It should not provide the same frame to the application
00566                 // layer again. The MAC layer accepts the acknowledgement.
00567                 tr_debug("Discarding duplicate frame");
00568                 _mcps_indication.pending = false;
00569                 _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED ;
00570             }
00571         } else if (msg_type == FRAME_TYPE_DATA_UNCONFIRMED_DOWN ) {
00572             _params.is_srv_ack_requested = false;
00573             _mcps_indication.type = MCPS_UNCONFIRMED ;
00574 
00575             if ((_params.dl_frame_counter == downlink_counter)
00576                     && (_params.dl_frame_counter != 0)) {
00577                 tr_debug("Discarding duplicate frame");
00578                 _mcps_indication.pending = false;
00579                 _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED ;
00580 
00581                 return;
00582             }
00583         }
00584         _params.dl_frame_counter = downlink_counter;
00585     }
00586 
00587     // This must be done before parsing the payload and the MAC commands.
00588     // We need to reset the MacCommandsBufferIndex here, since we need
00589     // to take retransmissions and repetitions into account. Error cases
00590     // will be handled in function OnMacStateCheckTimerEvent.
00591     if (_params.is_node_ack_requested) {
00592         if (fctrl.bits.ack ) {
00593             _mac_commands.clear_command_buffer();
00594             _mcps_confirmation.ack_received = fctrl.bits.ack ;
00595             _mcps_indication.is_ack_recvd = fctrl.bits.ack ;
00596         }
00597     } else {
00598         _mac_commands.clear_command_buffer();
00599     }
00600 
00601     uint8_t frame_len = (size - 4) - app_payload_start_index;
00602 
00603     if (frame_len > 0) {
00604         extract_data_and_mac_commands(payload, size, fctrl.bits.fopts_len ,
00605                                       nwk_skey, app_skey, address,
00606                                       downlink_counter, rssi, snr);
00607     } else {
00608         extract_mac_commands_only(payload, snr, fctrl.bits.fopts_len );
00609     }
00610 
00611     // Handle proprietary messages.
00612     if (msg_type == FRAME_TYPE_PROPRIETARY ) {
00613         memcpy(_params.rx_buffer, &payload[ptr_pos], size);
00614 
00615         _mcps_indication.type = MCPS_PROPRIETARY ;
00616         _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_OK ;
00617         _mcps_indication.buffer = _params.rx_buffer;
00618         _mcps_indication.buffer_size = size - ptr_pos;
00619     }
00620 
00621     // only stop act timer, if the ack is actually recieved
00622     if (_mcps_confirmation.ack_received) {
00623         _lora_time.stop(_params.timers.ack_timeout_timer);
00624     }
00625 }
00626 
00627 void LoRaMac::set_batterylevel_callback(mbed::Callback<uint8_t(void)> battery_level)
00628 {
00629     _mac_commands.set_batterylevel_callback(battery_level);
00630 }
00631 
00632 void LoRaMac::on_radio_tx_done(lorawan_time_t timestamp)
00633 {
00634     if (_device_class == CLASS_C) {
00635         // this will open a continuous RX2 window until time==RECV_DELAY1
00636         open_rx2_window();
00637     } else {
00638         _lora_phy.put_radio_to_sleep();
00639     }
00640 
00641     if (_params.is_rx_window_enabled == true) {
00642         lorawan_time_t time_diff = _lora_time.get_current_time() - timestamp;
00643         // start timer after which rx1_window will get opened
00644         _lora_time.start(_params.timers.rx_window1_timer,
00645                          _params.rx_window1_delay - time_diff);
00646 
00647         if (_device_class != CLASS_C) {
00648             _lora_time.start(_params.timers.rx_window2_timer,
00649                              _params.rx_window2_delay - time_diff);
00650         }
00651 
00652         if (_params.is_node_ack_requested) {
00653             _lora_time.start(_params.timers.ack_timeout_timer,
00654                              (_params.rx_window2_delay - time_diff) +
00655                              _lora_phy.get_ack_timeout());
00656         }
00657     } else {
00658         _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_OK ;
00659         _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT ;
00660     }
00661 
00662     _params.last_channel_idx = _params.channel;
00663 
00664     _lora_phy.set_last_tx_done(_params.channel, _is_nwk_joined, timestamp);
00665 
00666     _params.timers.aggregated_last_tx_time = timestamp;
00667 }
00668 
00669 void LoRaMac::on_radio_rx_done(const uint8_t *const payload, uint16_t size,
00670                                int16_t rssi, int8_t snr)
00671 {
00672     if (_device_class == CLASS_C && !_continuous_rx2_window_open) {
00673         open_rx2_window();
00674     } else {
00675         _lora_time.stop(_params.timers.rx_window1_timer);
00676         _lora_phy.put_radio_to_sleep();
00677     }
00678 
00679     loramac_mhdr_t  mac_hdr;
00680     uint8_t pos = 0;
00681     mac_hdr.value  = payload[pos++];
00682 
00683     switch (mac_hdr.bits.mtype ) {
00684 
00685         case FRAME_TYPE_JOIN_ACCEPT :
00686 
00687             if (nwk_joined()) {
00688                 _mlme_confirmation.pending = false;
00689                 return;
00690             } else {
00691                 handle_join_accept_frame(payload, size);
00692                 _mlme_confirmation.pending = true;
00693             }
00694 
00695             break;
00696 
00697         case FRAME_TYPE_DATA_UNCONFIRMED_DOWN :
00698         case FRAME_TYPE_DATA_CONFIRMED_DOWN :
00699         case FRAME_TYPE_PROPRIETARY :
00700 
00701             handle_data_frame(payload, size, pos, mac_hdr.bits.mtype , rssi, snr);
00702 
00703             break;
00704 
00705         default:
00706             break;
00707     }
00708 }
00709 
00710 void LoRaMac::on_radio_tx_timeout(void)
00711 {
00712     _lora_time.stop(_params.timers.rx_window1_timer);
00713     _lora_time.stop(_params.timers.rx_window2_timer);
00714     _lora_time.stop(_params.timers.ack_timeout_timer);
00715 
00716     if (_device_class == CLASS_C) {
00717         open_rx2_window();
00718     } else {
00719         _lora_phy.put_radio_to_sleep();
00720     }
00721 
00722     _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ;
00723     _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ;
00724 
00725     _mac_commands.clear_command_buffer();
00726 
00727     _mcps_confirmation.nb_retries = _params.ack_timeout_retry_counter;
00728     _mcps_confirmation.ack_received = false;
00729     _mcps_confirmation.tx_toa = 0;
00730 
00731     post_process_mcps_req();
00732 }
00733 
00734 void LoRaMac::on_radio_rx_timeout(bool is_timeout)
00735 {
00736     if (_device_class == CLASS_C && !_continuous_rx2_window_open) {
00737         open_rx2_window();
00738     } else {
00739         _lora_phy.put_radio_to_sleep();
00740     }
00741 
00742     if (_params.rx_slot == RX_SLOT_WIN_1 ) {
00743         if (_params.is_node_ack_requested == true) {
00744             _mcps_confirmation.status = is_timeout ?
00745                                         LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT  :
00746                                         LORAMAC_EVENT_INFO_STATUS_RX1_ERROR ;
00747         }
00748         _mlme_confirmation.status = is_timeout ?
00749                                     LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT  :
00750                                     LORAMAC_EVENT_INFO_STATUS_RX1_ERROR ;
00751 
00752         if (_device_class != CLASS_C) {
00753             if (_lora_time.get_elapsed_time(_params.timers.aggregated_last_tx_time) >= _params.rx_window2_delay) {
00754                 _lora_time.stop(_params.timers.rx_window2_timer);
00755             }
00756         }
00757     } else {
00758         if (_params.is_node_ack_requested == true) {
00759             _mcps_confirmation.status = is_timeout ?
00760                                         LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT  :
00761                                         LORAMAC_EVENT_INFO_STATUS_RX2_ERROR ;
00762         }
00763 
00764         _mlme_confirmation.status = is_timeout ?
00765                                     LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT  :
00766                                     LORAMAC_EVENT_INFO_STATUS_RX2_ERROR ;
00767     }
00768 }
00769 
00770 bool LoRaMac::continue_joining_process()
00771 {
00772     if (_params.join_request_trial_counter >= _params.max_join_request_trials) {
00773         return false;
00774     }
00775 
00776     // Schedule a retry
00777     if (handle_retransmission() != LORAWAN_STATUS_OK) {
00778         return false;
00779     }
00780 
00781     return true;
00782 }
00783 
00784 bool LoRaMac::continue_sending_process()
00785 {
00786     if (_params.ack_timeout_retry_counter > _params.max_ack_timeout_retries) {
00787         _mac_commands.clear_command_buffer();
00788         _params.adr_ack_counter++;
00789         return false;
00790     }
00791 
00792     // retransmission will be handled in on_ack_timeout() whence the ACK timeout
00793     // gets fired
00794     return true;
00795 }
00796 
00797 lorawan_status_t LoRaMac::send_join_request()
00798 {
00799     lorawan_status_t status = LORAWAN_STATUS_OK;
00800     loramac_mhdr_t  mac_hdr;
00801     loramac_frame_ctrl_t  fctrl;
00802 
00803     _params.sys_params.channel_data_rate =
00804         _lora_phy.get_alternate_DR(_params.join_request_trial_counter + 1);
00805 
00806     mac_hdr.value  = 0;
00807     mac_hdr.bits.mtype  = FRAME_TYPE_JOIN_REQ ;
00808 
00809     fctrl.value  = 0;
00810     fctrl.bits.adr  = _params.sys_params.adr_on;
00811     _params.is_last_tx_join_request = true;
00812 
00813     /* In case of join request retransmissions, the stack must prepare
00814      * the frame again, because the network server keeps track of the random
00815      * LoRaMacDevNonce values to prevent reply attacks. */
00816     status = prepare_frame(&mac_hdr, &fctrl, 0, NULL, 0);
00817 
00818     if (status == LORAWAN_STATUS_OK) {
00819         status = schedule_tx();
00820     } else {
00821         tr_error("Retransmission: error %d", status);
00822     }
00823 
00824     return status;
00825 }
00826 
00827 /**
00828  * This function handles retransmission of failed or unacknowledged
00829  * outgoing traffic
00830  */
00831 lorawan_status_t LoRaMac::handle_retransmission()
00832 {
00833     if (!nwk_joined() && (_mlme_confirmation.req_type == MLME_JOIN )) {
00834         return send_join_request();
00835     }
00836 
00837     return schedule_tx();
00838 }
00839 
00840 /**
00841  * This function is called when the backoff_timer gets fired.
00842  * It is used for re-scheduling an unsent packet in the pipe. This packet
00843  * can be a Join Request or any other data packet.
00844  */
00845 void LoRaMac::on_backoff_timer_expiry(void)
00846 {
00847     Lock lock(*this);
00848     lorawan_status_t status = schedule_tx();
00849     MBED_ASSERT(status == LORAWAN_STATUS_OK);
00850     (void) status;
00851 }
00852 
00853 void LoRaMac::open_rx1_window(void)
00854 {
00855     Lock lock(*this);
00856     _continuous_rx2_window_open = false;
00857     _lora_time.stop(_params.timers.rx_window1_timer);
00858     _params.rx_slot = RX_SLOT_WIN_1 ;
00859 
00860     _params.rx_window1_config.channel = _params.channel;
00861     _params.rx_window1_config.dr_offset = _params.sys_params.rx1_dr_offset;
00862     _params.rx_window1_config.dl_dwell_time = _params.sys_params.downlink_dwell_time;
00863     _params.rx_window1_config.is_repeater_supported = _params.is_repeater_supported;
00864     _params.rx_window1_config.is_rx_continuous = false;
00865     _params.rx_window1_config.rx_slot = _params.rx_slot;
00866 
00867     if (_device_class == CLASS_C) {
00868         _lora_phy.put_radio_to_standby();
00869     }
00870 
00871     _mcps_indication.rx_datarate = _params.rx_window1_config.datarate;
00872     _lora_phy.rx_config(&_params.rx_window1_config);
00873 
00874     _lora_phy.setup_rx_window(_params.rx_window1_config.is_rx_continuous,
00875                               _params.sys_params.max_rx_win_time);
00876 
00877     tr_debug("Opening RX1 Window");
00878 }
00879 
00880 void LoRaMac::open_rx2_window()
00881 {
00882     Lock lock(*this);
00883     _continuous_rx2_window_open = true;
00884     _lora_time.stop(_params.timers.rx_window2_timer);
00885 
00886     _params.rx_window2_config.channel = _params.channel;
00887     _params.rx_window2_config.frequency = _params.sys_params.rx2_channel.frequency;
00888     _params.rx_window2_config.dl_dwell_time = _params.sys_params.downlink_dwell_time;
00889     _params.rx_window2_config.is_repeater_supported = _params.is_repeater_supported;
00890     _params.rx_window2_config.rx_slot = _params.rx_window2_config.is_rx_continuous ?
00891                                         RX_SLOT_WIN_CLASS_C  : RX_SLOT_WIN_2 ;
00892 
00893     if (get_device_class() == CLASS_C) {
00894         _params.rx_window2_config.is_rx_continuous = true;
00895     } else {
00896         _params.rx_window2_config.is_rx_continuous = false;
00897     }
00898 
00899     _mcps_indication.rx_datarate = _params.rx_window2_config.datarate;
00900 
00901     if (_lora_phy.rx_config(&_params.rx_window2_config)) {
00902 
00903         _lora_phy.setup_rx_window(_params.rx_window2_config.is_rx_continuous,
00904                                   _params.sys_params.max_rx_win_time);
00905 
00906         _params.rx_slot = _params.rx_window2_config.rx_slot;
00907     }
00908 
00909     tr_debug("Opening RX2 Window, Frequency = %u", _params.rx_window2_config.frequency);
00910 }
00911 
00912 void LoRaMac::on_ack_timeout_timer_event(void)
00913 {
00914     Lock lock(*this);
00915 
00916     if (_params.ack_timeout_retry_counter > _params.max_ack_timeout_retries) {
00917         if (get_device_class() == CLASS_C) {
00918             // no need to use EventQueue as LoRaWANStack and LoRaMac are always
00919             // in same context
00920             _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
00921             _ack_expiry_handler_for_class_c.call();
00922         }
00923         return;
00924     }
00925 
00926     tr_debug("ACK_TIMEOUT Elapses, Retrying ...");
00927     _lora_time.stop(_params.timers.ack_timeout_timer);
00928 
00929     // reduce data rate on every 2nd attempt if and only if the
00930     // ADR is on
00931     if ((_params.ack_timeout_retry_counter % 2)
00932             && (_params.sys_params.adr_on)) {
00933         tr_debug("Trading datarate for range");
00934         _params.sys_params.channel_data_rate = _lora_phy.get_next_lower_tx_datarate(_params.sys_params.channel_data_rate);
00935     }
00936 
00937     _mcps_confirmation.nb_retries = _params.ack_timeout_retry_counter;
00938 
00939     // Schedule a retry
00940     if (handle_retransmission() != LORAWAN_STATUS_OK) {
00941         // In a case when enabled channels are not found, PHY layer
00942         // resorts to default channels. Next attempt should go forward as the
00943         // default channels are always available if there is a base station in the
00944         // vicinity. Otherwise something is wrong with the stack, we should assert
00945         // here
00946         _mac_commands.clear_command_buffer();
00947         _params.is_node_ack_requested = false;
00948         _mcps_confirmation.ack_received = false;
00949         _mcps_confirmation.nb_retries = _params.ack_timeout_retry_counter;
00950 
00951         // now that is a critical failure
00952         lorawan_status_t status = handle_retransmission();
00953         MBED_ASSERT(status == LORAWAN_STATUS_OK);
00954         (void) status;
00955     }
00956 
00957     _params.ack_timeout_retry_counter++;
00958 }
00959 
00960 bool LoRaMac::validate_payload_length(uint16_t length,
00961                                       int8_t datarate,
00962                                       uint8_t fopts_len)
00963 {
00964     uint16_t max_value = 0;
00965     uint16_t payloadSize = 0;
00966 
00967     max_value = _lora_phy.get_max_payload(datarate, _params.is_repeater_supported);
00968 
00969     // Calculate the resulting payload size
00970     payloadSize = (length + fopts_len);
00971 
00972     // Validation of the application payload size
00973     if ((payloadSize <= max_value) &&
00974             (payloadSize <= LORAMAC_PHY_MAXPAYLOAD)) {
00975         return true;
00976     }
00977     return false;
00978 }
00979 
00980 void LoRaMac::set_mlme_schedule_ul_indication(void)
00981 {
00982     _mlme_indication.indication_type = MLME_SCHEDULE_UPLINK ;
00983     _mlme_indication.pending = true;
00984 }
00985 
00986 // This is not actual transmission. It just schedules a message in response
00987 // to MCPS request
00988 lorawan_status_t LoRaMac::send(loramac_mhdr_t  *machdr, const uint8_t fport,
00989                                const void *fbuffer, uint16_t fbuffer_size)
00990 {
00991     loramac_frame_ctrl_t  fctrl;
00992 
00993     fctrl.value  = 0;
00994     fctrl.bits.fopts_len  = 0;
00995     fctrl.bits.fpending  = 0;
00996     fctrl.bits.ack  = false;
00997     fctrl.bits.adr_ack_req  = false;
00998     fctrl.bits.adr  = _params.sys_params.adr_on;
00999 
01000     lorawan_status_t status = prepare_frame(machdr, &fctrl, fport, fbuffer,
01001                                             fbuffer_size);
01002 
01003     if (status != LORAWAN_STATUS_OK) {
01004         return status;
01005     }
01006 
01007     // Reset confirm parameters
01008     _mcps_confirmation.nb_retries = 0;
01009     _mcps_confirmation.ack_received = false;
01010     _mcps_confirmation.ul_frame_counter = _params.ul_frame_counter;
01011 
01012     status = schedule_tx();
01013 
01014     return status;
01015 }
01016 
01017 int LoRaMac::get_backoff_timer_event_id(void)
01018 {
01019     return _params.timers.backoff_timer.timer_id;
01020 }
01021 
01022 lorawan_status_t LoRaMac::clear_tx_pipe(void)
01023 {
01024     // check if the event is not already queued
01025     if (_ev_queue->time_left(get_backoff_timer_event_id()) > 0) {
01026         _lora_time.stop(_params.timers.backoff_timer);
01027         _lora_time.stop(_params.timers.ack_timeout_timer);
01028         memset(_params.tx_buffer, 0, sizeof _params.tx_buffer);
01029         _params.tx_buffer_len = 0;
01030         reset_ongoing_tx(true);
01031         tr_debug("Sending Cancelled");
01032         return LORAWAN_STATUS_OK;
01033     }
01034 
01035     return LORAWAN_STATUS_BUSY;
01036 }
01037 
01038 lorawan_status_t LoRaMac::schedule_tx()
01039 {
01040     channel_selection_params_t next_channel;
01041     lorawan_time_t backoff_time = 0;
01042 
01043     if (_params.sys_params.max_duty_cycle == 255) {
01044         return LORAWAN_STATUS_DEVICE_OFF;
01045     }
01046 
01047     if (_params.sys_params.max_duty_cycle == 0) {
01048         _params.timers.aggregated_timeoff = 0;
01049     }
01050 
01051     calculate_backOff(_params.last_channel_idx);
01052 
01053     next_channel.aggregate_timeoff = _params.timers.aggregated_timeoff;
01054     next_channel.current_datarate = _params.sys_params.channel_data_rate;
01055     _params.is_dutycycle_on = MBED_CONF_LORA_DUTY_CYCLE_ON;
01056     next_channel.dc_enabled = _params.is_dutycycle_on;
01057     next_channel.joined = _is_nwk_joined;
01058     next_channel.last_aggregate_tx_time = _params.timers.aggregated_last_tx_time;
01059 
01060     lorawan_status_t status = _lora_phy.set_next_channel(&next_channel,
01061                                                          &_params.channel,
01062                                                          &backoff_time,
01063                                                          &_params.timers.aggregated_timeoff);
01064 
01065     switch (status) {
01066         case LORAWAN_STATUS_NO_CHANNEL_FOUND:
01067         case LORAWAN_STATUS_NO_FREE_CHANNEL_FOUND:
01068             return status;
01069         case LORAWAN_STATUS_DUTYCYCLE_RESTRICTED:
01070             if (backoff_time != 0) {
01071                 tr_debug("DC enforced: Transmitting in %lu ms", backoff_time);
01072                 _lora_time.start(_params.timers.backoff_timer, backoff_time);
01073             }
01074             return LORAWAN_STATUS_OK;
01075         default:
01076             break;
01077     }
01078 
01079     tr_debug("TX: Channel=%d, DR=%d", _params.channel, next_channel.current_datarate);
01080 
01081     uint8_t dr_offset = _lora_phy.apply_DR_offset(_params.sys_params.channel_data_rate,
01082                                                   _params.sys_params.rx1_dr_offset);
01083 
01084     _lora_phy.compute_rx_win_params(dr_offset, _params.sys_params.min_rx_symb,
01085                                     _params.sys_params.max_sys_rx_error,
01086                                     &_params.rx_window1_config);
01087 
01088     _lora_phy.compute_rx_win_params(_params.sys_params.rx2_channel.datarate,
01089                                     _params.sys_params.min_rx_symb,
01090                                     _params.sys_params.max_sys_rx_error,
01091                                     &_params.rx_window2_config);
01092 
01093     if (!_is_nwk_joined) {
01094         _params.rx_window1_delay = _params.sys_params.join_accept_delay1
01095                                    + _params.rx_window1_config.window_offset;
01096         _params.rx_window2_delay = _params.sys_params.join_accept_delay2
01097                                    + _params.rx_window2_config.window_offset;
01098     } else {
01099         if (validate_payload_length(_params.tx_buffer_len,
01100                                     _params.sys_params.channel_data_rate,
01101                                     _mac_commands.get_mac_cmd_length()) == false) {
01102             return LORAWAN_STATUS_LENGTH_ERROR;
01103         }
01104         _params.rx_window1_delay = _params.sys_params.recv_delay1
01105                                    + _params.rx_window1_config.window_offset;
01106         _params.rx_window2_delay = _params.sys_params.recv_delay2
01107                                    + _params.rx_window2_config.window_offset;
01108     }
01109 
01110     // handle the ack to the server here so that if the sending was cancelled
01111     // by the user in the backoff period, we would still ack the previous frame.
01112     if (_params.is_srv_ack_requested) {
01113         _params.is_srv_ack_requested = false;
01114     }
01115 
01116     return send_frame_on_channel(_params.channel);
01117 }
01118 
01119 void LoRaMac::calculate_backOff(uint8_t channel)
01120 {
01121     lorawan_time_t elapsed_time = _lora_time.get_elapsed_time(_params.timers.mac_init_time);
01122 
01123     _params.is_dutycycle_on = MBED_CONF_LORA_DUTY_CYCLE_ON;
01124 
01125     _lora_phy.calculate_backoff(_is_nwk_joined, _params.is_last_tx_join_request, _params.is_dutycycle_on,
01126                                 channel, elapsed_time, _params.timers.tx_toa);
01127 
01128     // Update aggregated time-off. This must be an assignment and no incremental
01129     // update as we do only calculate the time-off based on the last transmission
01130     _params.timers.aggregated_timeoff = (_params.timers.tx_toa * _params.sys_params.aggregated_duty_cycle
01131                                          - _params.timers.tx_toa);
01132 }
01133 
01134 void LoRaMac::reset_mac_parameters(void)
01135 {
01136     _is_nwk_joined = false;
01137 
01138     _params.ul_frame_counter = 0;
01139     _params.dl_frame_counter = 0;
01140     _params.adr_ack_counter = 0;
01141 
01142     _params.ul_nb_rep_counter = 0;
01143 
01144     _params.max_ack_timeout_retries = 1;
01145     _params.ack_timeout_retry_counter = 1;
01146     _params.is_ack_retry_timeout_expired = false;
01147 
01148     _params.sys_params.max_duty_cycle = 0;
01149     _params.sys_params.aggregated_duty_cycle = 1;
01150 
01151     _mac_commands.clear_command_buffer();
01152     _mac_commands.clear_repeat_buffer();
01153     _mac_commands.clear_mac_commands_in_next_tx();
01154 
01155     _params.is_rx_window_enabled = true;
01156 
01157     _lora_phy.reset_to_default_values(&_params, false);
01158 
01159     _params.is_node_ack_requested = false;
01160     _params.is_srv_ack_requested = false;
01161 
01162     multicast_params_t  *cur = _params.multicast_channels;
01163     while (cur != NULL) {
01164         cur->dl_frame_counter  = 0;
01165         cur = cur->next ;
01166     }
01167     _params.channel = 0;
01168     _params.last_channel_idx = _params.channel;
01169 }
01170 
01171 uint8_t LoRaMac::get_default_tx_datarate()
01172 {
01173     return _lora_phy.get_default_tx_datarate();
01174 }
01175 
01176 void LoRaMac::enable_adaptive_datarate(bool adr_enabled)
01177 {
01178     _params.sys_params.adr_on = adr_enabled;
01179 }
01180 
01181 lorawan_status_t LoRaMac::set_channel_data_rate(uint8_t data_rate)
01182 {
01183     if (_params.sys_params.adr_on) {
01184         tr_error("Cannot set data rate. Please turn off ADR first.");
01185         return LORAWAN_STATUS_PARAMETER_INVALID;
01186     }
01187 
01188     if (_lora_phy.verify_tx_datarate(data_rate, false) == true) {
01189         _params.sys_params.channel_data_rate = data_rate;
01190     } else {
01191         return LORAWAN_STATUS_PARAMETER_INVALID;
01192     }
01193 
01194     return LORAWAN_STATUS_OK;
01195 }
01196 
01197 bool LoRaMac::tx_ongoing()
01198 {
01199     return _ongoing_tx_msg.tx_ongoing;
01200 }
01201 
01202 void LoRaMac::set_tx_ongoing(bool ongoing)
01203 {
01204     _ongoing_tx_msg.tx_ongoing = ongoing;
01205 }
01206 
01207 void LoRaMac::reset_ongoing_tx(bool reset_pending)
01208 {
01209     _ongoing_tx_msg.tx_ongoing = false;
01210     memset(_ongoing_tx_msg.f_buffer, 0, MBED_CONF_LORA_TX_MAX_SIZE);
01211     _ongoing_tx_msg.f_buffer_size = 0;
01212     if (reset_pending) {
01213         _ongoing_tx_msg.pending_size = 0;
01214     }
01215 }
01216 
01217 int16_t LoRaMac::prepare_ongoing_tx(const uint8_t port,
01218                                     const uint8_t *const data,
01219                                     uint16_t length,
01220                                     uint8_t flags,
01221                                     uint8_t num_retries)
01222 {
01223     _ongoing_tx_msg.port = port;
01224 
01225     uint8_t max_possible_size = get_max_possible_tx_size(length);
01226 
01227     if (max_possible_size > MBED_CONF_LORA_TX_MAX_SIZE) {
01228         max_possible_size = MBED_CONF_LORA_TX_MAX_SIZE;
01229     }
01230 
01231     if (max_possible_size < length) {
01232         tr_info("Cannot transmit %d bytes. Possible TX Size is %d bytes",
01233                 length, max_possible_size);
01234 
01235         _ongoing_tx_msg.pending_size = length - max_possible_size;
01236         _ongoing_tx_msg.f_buffer_size = max_possible_size;
01237         memcpy(_ongoing_tx_msg.f_buffer, data, _ongoing_tx_msg.f_buffer_size);
01238     } else {
01239         _ongoing_tx_msg.f_buffer_size = length;
01240         _ongoing_tx_msg.pending_size = 0;
01241         if (length > 0) {
01242             memcpy(_ongoing_tx_msg.f_buffer, data, length);
01243         }
01244     }
01245 
01246     // Handles unconfirmed messages
01247     if (flags & MSG_UNCONFIRMED_FLAG) {
01248         _ongoing_tx_msg.type = MCPS_UNCONFIRMED ;
01249         _ongoing_tx_msg.fport = port;
01250         _ongoing_tx_msg.nb_trials = 1;
01251     }
01252 
01253     // Handles confirmed messages
01254     if (flags & MSG_CONFIRMED_FLAG) {
01255         _ongoing_tx_msg.type = MCPS_CONFIRMED ;
01256         _ongoing_tx_msg.fport = port;
01257         _ongoing_tx_msg.nb_trials = num_retries;
01258     }
01259 
01260     // Handles proprietary messages
01261     if (flags & MSG_PROPRIETARY_FLAG) {
01262         _ongoing_tx_msg.type = MCPS_PROPRIETARY ;
01263         _ongoing_tx_msg.fport = port;
01264         _ongoing_tx_msg.nb_trials = 1;
01265     }
01266 
01267     tr_info("RTS = %u bytes, PEND = %u, Port: %u",
01268             _ongoing_tx_msg.f_buffer_size, _ongoing_tx_msg.pending_size,
01269             _ongoing_tx_msg.fport);
01270 
01271     return _ongoing_tx_msg.f_buffer_size;
01272 }
01273 
01274 lorawan_status_t LoRaMac::send_ongoing_tx()
01275 {
01276     lorawan_status_t status;
01277     _params.is_last_tx_join_request = false;
01278     int8_t datarate = _params.sys_params.channel_data_rate;
01279 
01280     // This prohibits the data rate going below the minimum value.
01281     datarate = MAX(datarate, (int8_t)_lora_phy.get_minimum_tx_datarate());
01282 
01283     loramac_mhdr_t  machdr;
01284     machdr.value  = 0;
01285 
01286     reset_mcps_confirmation();
01287 
01288     _params.ack_timeout_retry_counter = 1;
01289     _params.max_ack_timeout_retries = 1;
01290 
01291     if (MCPS_UNCONFIRMED  == _ongoing_tx_msg.type) {
01292         machdr.bits.mtype = FRAME_TYPE_DATA_UNCONFIRMED_UP ;
01293     } else if (_ongoing_tx_msg.type == MCPS_CONFIRMED ) {
01294         machdr.bits.mtype = FRAME_TYPE_DATA_CONFIRMED_UP ;
01295         _params.max_ack_timeout_retries = _ongoing_tx_msg.nb_trials;
01296     } else if (_ongoing_tx_msg.type == MCPS_PROPRIETARY ) {
01297         machdr.bits.mtype = FRAME_TYPE_PROPRIETARY ;
01298     } else {
01299         return LORAWAN_STATUS_SERVICE_UNKNOWN;
01300     }
01301 
01302     if (_params.sys_params.adr_on == false) {
01303         if (_lora_phy.verify_tx_datarate(datarate, false) == true) {
01304             _params.sys_params.channel_data_rate = datarate;
01305         } else {
01306             return LORAWAN_STATUS_PARAMETER_INVALID;
01307         }
01308     }
01309 
01310     status = send(&machdr, _ongoing_tx_msg.fport, _ongoing_tx_msg.f_buffer,
01311                   _ongoing_tx_msg.f_buffer_size);
01312     if (status == LORAWAN_STATUS_OK) {
01313         _mcps_confirmation.req_type = _ongoing_tx_msg.type;
01314     }
01315 
01316     return status;
01317 }
01318 
01319 device_class_t LoRaMac::get_device_class() const
01320 {
01321     return _device_class;
01322 }
01323 
01324 void LoRaMac::set_device_class(const device_class_t &device_class,
01325                                mbed::Callback<void(void)>ack_expiry_handler)
01326 {
01327     _device_class = device_class;
01328     _ack_expiry_handler_for_class_c = ack_expiry_handler;
01329 
01330     if (CLASS_A == _device_class) {
01331         tr_debug("Changing device class to -> CLASS_A");
01332         _lora_phy.put_radio_to_sleep();
01333     } else if (CLASS_C == _device_class) {
01334         _params.is_node_ack_requested = false;
01335         _lora_phy.put_radio_to_sleep();
01336         _lora_phy.compute_rx_win_params(_params.sys_params.rx2_channel.datarate,
01337                                         _params.sys_params.min_rx_symb,
01338                                         _params.sys_params.max_sys_rx_error,
01339                                         &_params.rx_window2_config);
01340     }
01341 
01342     if (CLASS_C == _device_class) {
01343         tr_debug("Changing device class to -> CLASS_C");
01344         open_rx2_window();
01345     }
01346 }
01347 
01348 void LoRaMac::setup_link_check_request()
01349 {
01350     reset_mlme_confirmation();
01351 
01352     _mlme_confirmation.req_type = MLME_LINK_CHECK ;
01353     _mlme_confirmation.pending = true;
01354     _mac_commands.add_link_check_req();
01355 }
01356 
01357 lorawan_status_t LoRaMac::prepare_join(const lorawan_connect_t *params, bool is_otaa)
01358 {
01359     if (params) {
01360         if (is_otaa) {
01361             if ((params->connection_u.otaa.dev_eui == NULL)
01362                     || (params->connection_u.otaa.app_eui == NULL)
01363                     || (params->connection_u.otaa.app_key == NULL)
01364                     || (params->connection_u.otaa.nb_trials == 0)) {
01365                 return LORAWAN_STATUS_PARAMETER_INVALID;
01366             }
01367             _params.keys.dev_eui = params->connection_u.otaa.dev_eui;
01368             _params.keys.app_eui = params->connection_u.otaa.app_eui;
01369             _params.keys.app_key = params->connection_u.otaa.app_key;
01370             _params.max_join_request_trials = params->connection_u.otaa.nb_trials;
01371 
01372             if (!_lora_phy.verify_nb_join_trials(params->connection_u.otaa.nb_trials)) {
01373                 // Value not supported, get default
01374                 _params.max_join_request_trials = MBED_CONF_LORA_NB_TRIALS;
01375             }
01376             // Reset variable JoinRequestTrials
01377             _params.join_request_trial_counter = 0;
01378         } else {
01379             if ((params->connection_u.abp.dev_addr == 0)
01380                     || (params->connection_u.abp.nwk_id == 0)
01381                     || (params->connection_u.abp.nwk_skey == NULL)
01382                     || (params->connection_u.abp.app_skey == NULL)) {
01383                 return LORAWAN_STATUS_PARAMETER_INVALID;
01384             }
01385 
01386             _params.net_id = params->connection_u.abp.nwk_id;
01387             _params.dev_addr = params->connection_u.abp.dev_addr;
01388 
01389             memcpy(_params.keys.nwk_skey, params->connection_u.abp.nwk_skey,
01390                    sizeof(_params.keys.nwk_skey));
01391 
01392             memcpy(_params.keys.app_skey, params->connection_u.abp.app_skey,
01393                    sizeof(_params.keys.app_skey));
01394         }
01395     } else {
01396 #if MBED_CONF_LORA_OVER_THE_AIR_ACTIVATION
01397         const static uint8_t dev_eui[] = MBED_CONF_LORA_DEVICE_EUI;
01398         const static uint8_t app_eui[] = MBED_CONF_LORA_APPLICATION_EUI;
01399         const static uint8_t app_key[] = MBED_CONF_LORA_APPLICATION_KEY;
01400 
01401         _params.keys.app_eui = const_cast<uint8_t *>(app_eui);
01402         _params.keys.dev_eui = const_cast<uint8_t *>(dev_eui);
01403         _params.keys.app_key = const_cast<uint8_t *>(app_key);
01404         _params.max_join_request_trials = MBED_CONF_LORA_NB_TRIALS;
01405 
01406         // Reset variable JoinRequestTrials
01407         _params.join_request_trial_counter = 0;
01408 
01409         reset_mac_parameters();
01410 
01411         _params.sys_params.channel_data_rate =
01412             _lora_phy.get_alternate_DR(_params.join_request_trial_counter + 1);
01413 
01414 #else
01415         const static uint8_t nwk_skey[] = MBED_CONF_LORA_NWKSKEY;
01416         const static uint8_t app_skey[] = MBED_CONF_LORA_APPSKEY;
01417 
01418         _params.net_id = (MBED_CONF_LORA_DEVICE_ADDRESS & LORAWAN_NETWORK_ID_MASK);
01419         _params.dev_addr = MBED_CONF_LORA_DEVICE_ADDRESS;
01420 
01421         memcpy(_params.keys.nwk_skey, nwk_skey, sizeof(_params.keys.nwk_skey));
01422 
01423         memcpy(_params.keys.app_skey, app_skey, sizeof(_params.keys.app_skey));
01424 #endif
01425     }
01426 
01427     return LORAWAN_STATUS_OK;
01428 }
01429 
01430 lorawan_status_t LoRaMac::join(bool is_otaa)
01431 {
01432     if (!is_otaa) {
01433         set_nwk_joined(true);
01434         return LORAWAN_STATUS_OK;
01435     }
01436 
01437     reset_mlme_confirmation();
01438     _mlme_confirmation.req_type = MLME_JOIN ;
01439 
01440     return send_join_request();
01441 }
01442 
01443 static void memcpy_convert_endianess(uint8_t *dst,
01444                                      const uint8_t *src,
01445                                      uint16_t size)
01446 {
01447     dst = dst + (size - 1);
01448     while (size--) {
01449         *dst-- = *src++;
01450     }
01451 }
01452 
01453 lorawan_status_t LoRaMac::prepare_frame(loramac_mhdr_t  *machdr,
01454                                         loramac_frame_ctrl_t  *fctrl,
01455                                         const uint8_t fport,
01456                                         const void *fbuffer,
01457                                         uint16_t fbuffer_size)
01458 {
01459     uint16_t i;
01460     uint8_t pkt_header_len = 0;
01461     uint32_t mic = 0;
01462     const void *payload = fbuffer;
01463     uint8_t frame_port = fport;
01464     lorawan_status_t status = LORAWAN_STATUS_OK;
01465 
01466     _params.tx_buffer_len = 0;
01467 
01468     _params.is_node_ack_requested = false;
01469 
01470     if (fbuffer == NULL) {
01471         fbuffer_size = 0;
01472     }
01473 
01474     _params.tx_buffer_len = fbuffer_size;
01475 
01476     _params.tx_buffer[pkt_header_len++] = machdr->value ;
01477 
01478     switch (machdr->bits.mtype ) {
01479 
01480         case FRAME_TYPE_JOIN_REQ :
01481 
01482             _params.tx_buffer_len = pkt_header_len;
01483             memcpy_convert_endianess(_params.tx_buffer + _params.tx_buffer_len,
01484                                      _params.keys.app_eui, 8);
01485             _params.tx_buffer_len += 8;
01486             memcpy_convert_endianess(_params.tx_buffer + _params.tx_buffer_len,
01487                                      _params.keys.dev_eui, 8);
01488             _params.tx_buffer_len += 8;
01489 
01490             _params.dev_nonce = _lora_phy.get_radio_rng();
01491 
01492             _params.tx_buffer[_params.tx_buffer_len++] = _params.dev_nonce & 0xFF;
01493             _params.tx_buffer[_params.tx_buffer_len++] = (_params.dev_nonce >> 8) & 0xFF;
01494 
01495             if (0 != _lora_crypto.compute_join_frame_mic(_params.tx_buffer,
01496                                                          _params.tx_buffer_len & 0xFF,
01497                                                          _params.keys.app_key,
01498                                                          APPKEY_KEY_LENGTH,
01499                                                          &mic)) {
01500                 return LORAWAN_STATUS_CRYPTO_FAIL;
01501             }
01502 
01503             _params.tx_buffer[_params.tx_buffer_len++] = mic & 0xFF;
01504             _params.tx_buffer[_params.tx_buffer_len++] = (mic >> 8) & 0xFF;
01505             _params.tx_buffer[_params.tx_buffer_len++] = (mic >> 16) & 0xFF;
01506             _params.tx_buffer[_params.tx_buffer_len++] = (mic >> 24) & 0xFF;
01507 
01508             break;
01509         case FRAME_TYPE_DATA_CONFIRMED_UP :
01510             _params.is_node_ack_requested = true;
01511         //Intentional fallthrough
01512         case FRAME_TYPE_DATA_UNCONFIRMED_UP : {
01513             if (!_is_nwk_joined) {
01514                 return LORAWAN_STATUS_NO_NETWORK_JOINED;
01515             }
01516 
01517             if (_params.sys_params.adr_on) {
01518                 if (_lora_phy.get_next_ADR(true,
01519                                            _params.sys_params.channel_data_rate,
01520                                            _params.sys_params.channel_tx_power,
01521                                            _params.adr_ack_counter)) {
01522                     fctrl->bits.adr_ack_req  = 1;
01523                 }
01524             }
01525 
01526             if (_params.is_srv_ack_requested == true) {
01527                 tr_debug("Acking to NS");
01528                 fctrl->bits.ack  = 1;
01529             }
01530 
01531             _params.tx_buffer[pkt_header_len++] = (_params.dev_addr) & 0xFF;
01532             _params.tx_buffer[pkt_header_len++] = (_params.dev_addr >> 8) & 0xFF;
01533             _params.tx_buffer[pkt_header_len++] = (_params.dev_addr >> 16) & 0xFF;
01534             _params.tx_buffer[pkt_header_len++] = (_params.dev_addr >> 24) & 0xFF;
01535 
01536             _params.tx_buffer[pkt_header_len++] = fctrl->value ;
01537 
01538             _params.tx_buffer[pkt_header_len++] = _params.ul_frame_counter & 0xFF;
01539             _params.tx_buffer[pkt_header_len++] = (_params.ul_frame_counter >> 8)
01540                                                   & 0xFF;
01541 
01542             _mac_commands.copy_repeat_commands_to_buffer();
01543 
01544             const uint8_t mac_commands_len = _mac_commands.get_mac_cmd_length();
01545 
01546             if ((payload != NULL) && (_params.tx_buffer_len > 0)) {
01547                 if (_mac_commands.is_mac_command_in_next_tx() == true) {
01548                     if (mac_commands_len <= LORA_MAC_COMMAND_MAX_FOPTS_LENGTH) {
01549                         fctrl->bits.fopts_len  += mac_commands_len;
01550 
01551                         // Update FCtrl field with new value of OptionsLength
01552                         _params.tx_buffer[0x05] = fctrl->value ;
01553 
01554                         const uint8_t *buffer = _mac_commands.get_mac_commands_buffer();
01555                         for (i = 0; i < mac_commands_len; i++) {
01556                             _params.tx_buffer[pkt_header_len++] = buffer[i];
01557                         }
01558                     } else {
01559                         _params.tx_buffer_len = mac_commands_len;
01560                         payload = _mac_commands.get_mac_commands_buffer();
01561                         frame_port = 0;
01562                     }
01563                 }
01564             } else {
01565                 if ((mac_commands_len > 0)
01566                         && (_mac_commands.is_mac_command_in_next_tx() == true)) {
01567                     _params.tx_buffer_len = mac_commands_len;
01568                     payload = _mac_commands.get_mac_commands_buffer();
01569                     frame_port = 0;
01570                 }
01571             }
01572 
01573             _mac_commands.parse_mac_commands_to_repeat();
01574 
01575             if ((payload != NULL) && (_params.tx_buffer_len > 0)) {
01576                 _params.tx_buffer[pkt_header_len++] = frame_port;
01577 
01578                 uint8_t *key = _params.keys.app_skey;
01579                 uint32_t key_length = sizeof(_params.keys.app_skey) * 8;
01580                 if (frame_port == 0) {
01581                     _mac_commands.clear_command_buffer();
01582                     key = _params.keys.nwk_skey;
01583                     key_length = sizeof(_params.keys.nwk_skey) * 8;
01584                 }
01585                 if (0 != _lora_crypto.encrypt_payload((uint8_t *) payload, _params.tx_buffer_len,
01586                                                       key, key_length,
01587                                                       _params.dev_addr, UP_LINK,
01588                                                       _params.ul_frame_counter,
01589                                                       &_params.tx_buffer[pkt_header_len])) {
01590                     status = LORAWAN_STATUS_CRYPTO_FAIL;
01591                 }
01592             }
01593 
01594             _params.tx_buffer_len = pkt_header_len + _params.tx_buffer_len;
01595 
01596             if (0 != _lora_crypto.compute_mic(_params.tx_buffer, _params.tx_buffer_len,
01597                                               _params.keys.nwk_skey, sizeof(_params.keys.nwk_skey) * 8,
01598                                               _params.dev_addr,
01599                                               UP_LINK, _params.ul_frame_counter, &mic)) {
01600                 status = LORAWAN_STATUS_CRYPTO_FAIL;
01601             }
01602 
01603             _params.tx_buffer[_params.tx_buffer_len + 0] = mic & 0xFF;
01604             _params.tx_buffer[_params.tx_buffer_len + 1] = (mic >> 8) & 0xFF;
01605             _params.tx_buffer[_params.tx_buffer_len + 2] = (mic >> 16) & 0xFF;
01606             _params.tx_buffer[_params.tx_buffer_len + 3] = (mic >> 24) & 0xFF;
01607 
01608             _params.tx_buffer_len += LORAMAC_MFR_LEN;
01609         }
01610             break;
01611         case FRAME_TYPE_PROPRIETARY :
01612             if ((fbuffer != NULL) && (_params.tx_buffer_len > 0)) {
01613                 memcpy(_params.tx_buffer + pkt_header_len, (uint8_t *) fbuffer,
01614                        _params.tx_buffer_len);
01615                 _params.tx_buffer_len = pkt_header_len + _params.tx_buffer_len;
01616             }
01617             break;
01618         default:
01619             status = LORAWAN_STATUS_SERVICE_UNKNOWN;
01620     }
01621 
01622     tr_debug("Frame prepared to send at port %u", frame_port);
01623 
01624     return status;
01625 }
01626 
01627 lorawan_status_t LoRaMac::send_frame_on_channel(uint8_t channel)
01628 {
01629     tx_config_params_t tx_config;
01630     int8_t tx_power = 0;
01631 
01632     tx_config.channel = channel;
01633     tx_config.datarate = _params.sys_params.channel_data_rate;
01634     tx_config.tx_power = _params.sys_params.channel_tx_power;
01635     tx_config.max_eirp = _params.sys_params.max_eirp;
01636     tx_config.antenna_gain = _params.sys_params.antenna_gain;
01637     tx_config.pkt_len = _params.tx_buffer_len;
01638 
01639     _lora_phy.tx_config(&tx_config, &tx_power, &_params.timers.tx_toa);
01640 
01641     _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
01642 
01643     _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
01644     _mcps_confirmation.data_rate = _params.sys_params.channel_data_rate;
01645     _mcps_confirmation.tx_power = tx_power;
01646     _mcps_confirmation.channel = channel;
01647 
01648     _mcps_confirmation.tx_toa = _params.timers.tx_toa;
01649     _mlme_confirmation.tx_toa = _params.timers.tx_toa;
01650 
01651     if (!_is_nwk_joined) {
01652         _params.join_request_trial_counter++;
01653     }
01654 
01655     _lora_phy.handle_send(_params.tx_buffer, _params.tx_buffer_len);
01656 
01657     return LORAWAN_STATUS_OK;
01658 }
01659 
01660 void LoRaMac::reset_mcps_confirmation()
01661 {
01662     memset((uint8_t *) &_mcps_confirmation, 0, sizeof(_mcps_confirmation));
01663     _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
01664 }
01665 
01666 void LoRaMac::reset_mlme_confirmation()
01667 {
01668     memset((uint8_t *) &_mlme_confirmation, 0, sizeof(_mlme_confirmation));
01669     _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
01670 }
01671 
01672 void LoRaMac::reset_mcps_indication()
01673 {
01674     memset((uint8_t *) &_mcps_indication, 0, sizeof(_mcps_indication));
01675     _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
01676 }
01677 
01678 void LoRaMac::set_tx_continuous_wave(uint8_t channel, int8_t datarate, int8_t tx_power,
01679                                      float max_eirp, float antenna_gain, uint16_t timeout)
01680 {
01681     cw_mode_params_t  continuous_wave;
01682 
01683     continuous_wave.channel  = channel;
01684     continuous_wave.datarate  = datarate;
01685     continuous_wave.tx_power  = tx_power;
01686     continuous_wave.max_eirp  = max_eirp;
01687     continuous_wave.antenna_gain  = antenna_gain;
01688     continuous_wave.timeout  = timeout;
01689 
01690     _lora_phy.set_tx_cont_mode(&continuous_wave);
01691 }
01692 
01693 lorawan_status_t LoRaMac::initialize(EventQueue *queue)
01694 {
01695     _lora_time.activate_timer_subsystem(queue);
01696 
01697     _ev_queue = queue;
01698 
01699     _channel_plan.activate_channelplan_subsystem(&_lora_phy);
01700 
01701     _device_class = CLASS_A;
01702 
01703     _params.join_request_trial_counter = 0;
01704     _params.max_join_request_trials = 1;
01705     _params.is_repeater_supported = false;
01706 
01707     _params.timers.aggregated_last_tx_time = 0;
01708     _params.timers.aggregated_timeoff = 0;
01709 
01710     _lora_phy.reset_to_default_values(&_params, true);
01711 
01712     _params.sys_params.max_sys_rx_error = 10;
01713     _params.sys_params.min_rx_symb = 6;
01714     _params.sys_params.retry_num = 1;
01715 
01716     reset_mac_parameters();
01717 
01718     srand(_lora_phy.get_radio_rng());
01719 
01720     _params.is_nwk_public = MBED_CONF_LORA_PUBLIC_NETWORK;
01721     _lora_phy.setup_public_network_mode(_params.is_nwk_public);
01722     _lora_phy.put_radio_to_sleep();
01723 
01724     _lora_time.init(_params.timers.backoff_timer,
01725                     mbed::callback(this, &LoRaMac::on_backoff_timer_expiry));
01726     _lora_time.init(_params.timers.rx_window1_timer,
01727                     mbed::callback(this, &LoRaMac::open_rx1_window));
01728     _lora_time.init(_params.timers.rx_window2_timer,
01729                     mbed::callback(this, &LoRaMac::open_rx2_window));
01730     _lora_time.init(_params.timers.ack_timeout_timer,
01731                     mbed::callback(this, &LoRaMac::on_ack_timeout_timer_event));
01732 
01733     _params.timers.mac_init_time = _lora_time.get_current_time();
01734 
01735     _params.sys_params.adr_on = MBED_CONF_LORA_ADR_ON;
01736 
01737     _params.is_nwk_public = MBED_CONF_LORA_PUBLIC_NETWORK;
01738     _lora_phy.setup_public_network_mode(MBED_CONF_LORA_PUBLIC_NETWORK);
01739 
01740     return LORAWAN_STATUS_OK;
01741 }
01742 
01743 void LoRaMac::disconnect()
01744 {
01745     _lora_time.stop(_params.timers.backoff_timer);
01746     _lora_time.stop(_params.timers.rx_window1_timer);
01747     _lora_time.stop(_params.timers.rx_window2_timer);
01748     _lora_time.stop(_params.timers.ack_timeout_timer);
01749 
01750     _lora_phy.put_radio_to_sleep();
01751 
01752     _is_nwk_joined = false;
01753     _params.is_ack_retry_timeout_expired = false;
01754     _params.is_rx_window_enabled = true;
01755     _params.is_node_ack_requested = false;
01756     _params.is_srv_ack_requested = false;
01757 
01758     _mac_commands.clear_command_buffer();
01759     _mac_commands.clear_repeat_buffer();
01760     _mac_commands.clear_mac_commands_in_next_tx();
01761 
01762     reset_mcps_confirmation();
01763     reset_mlme_confirmation();
01764     reset_mcps_indication();
01765 }
01766 
01767 uint8_t LoRaMac::get_max_possible_tx_size(uint8_t size)
01768 {
01769     uint8_t max_possible_payload_size = 0;
01770     uint8_t current_payload_size = 0;
01771     uint8_t fopt_len = _mac_commands.get_mac_cmd_length()
01772                        + _mac_commands.get_repeat_commands_length();
01773 
01774     if (_params.sys_params.adr_on) {
01775         _lora_phy.get_next_ADR(false, _params.sys_params.channel_data_rate,
01776                                _params.sys_params.channel_tx_power,
01777                                _params.adr_ack_counter);
01778     }
01779 
01780     current_payload_size = _lora_phy.get_max_payload(_params.sys_params.channel_data_rate, _params.is_repeater_supported);
01781 
01782     if (current_payload_size >= fopt_len) {
01783         max_possible_payload_size = current_payload_size - fopt_len;
01784     } else {
01785         max_possible_payload_size = current_payload_size;
01786         fopt_len = 0;
01787         _mac_commands.clear_command_buffer();
01788         _mac_commands.clear_repeat_buffer();
01789     }
01790 
01791     if (validate_payload_length(size, _params.sys_params.channel_data_rate,
01792                                 fopt_len) == false) {
01793         return max_possible_payload_size;
01794     }
01795     return current_payload_size;
01796 }
01797 
01798 bool LoRaMac::nwk_joined()
01799 {
01800     return _is_nwk_joined;
01801 }
01802 
01803 void LoRaMac::set_nwk_joined(bool joined)
01804 {
01805     _is_nwk_joined = joined;
01806 }
01807 
01808 lorawan_status_t LoRaMac::add_channel_plan(const lorawan_channelplan_t &plan)
01809 {
01810     if (tx_ongoing()) {
01811         return LORAWAN_STATUS_BUSY;
01812     }
01813 
01814     return _channel_plan.set_plan(plan);
01815 }
01816 
01817 lorawan_status_t LoRaMac::remove_channel_plan()
01818 {
01819     if (tx_ongoing()) {
01820         return LORAWAN_STATUS_BUSY;
01821     }
01822 
01823     return _channel_plan.remove_plan();
01824 }
01825 
01826 lorawan_status_t LoRaMac::get_channel_plan(lorawan_channelplan_t &plan)
01827 {
01828     return _channel_plan.get_plan(plan, _lora_phy.get_phy_channels());
01829 }
01830 
01831 lorawan_status_t LoRaMac::remove_single_channel(uint8_t id)
01832 {
01833     if (tx_ongoing()) {
01834         return LORAWAN_STATUS_BUSY;
01835     }
01836 
01837     return _channel_plan.remove_single_channel(id);
01838 }
01839 
01840 lorawan_status_t LoRaMac::multicast_channel_link(multicast_params_t  *channel_param)
01841 {
01842     if (channel_param == NULL) {
01843         return LORAWAN_STATUS_PARAMETER_INVALID;
01844     }
01845     if (tx_ongoing()) {
01846         return LORAWAN_STATUS_BUSY;
01847     }
01848 
01849     channel_param->dl_frame_counter  = 0;
01850 
01851     if (_params.multicast_channels == NULL) {
01852         _params.multicast_channels = channel_param;
01853     } else {
01854         multicast_params_t  *cur = _params.multicast_channels;
01855         while (cur->next  != NULL) {
01856             cur = cur->next ;
01857         }
01858         cur->next  = channel_param;
01859     }
01860 
01861     return LORAWAN_STATUS_OK;
01862 }
01863 
01864 lorawan_status_t LoRaMac::multicast_channel_unlink(multicast_params_t  *channel_param)
01865 {
01866     if (channel_param == NULL) {
01867         return LORAWAN_STATUS_PARAMETER_INVALID;
01868     }
01869 
01870     if (tx_ongoing()) {
01871         return LORAWAN_STATUS_BUSY;
01872     }
01873 
01874     if (_params.multicast_channels != NULL) {
01875         if (_params.multicast_channels == channel_param) {
01876             _params.multicast_channels = channel_param->next ;
01877         } else {
01878             multicast_params_t  *cur = _params.multicast_channels;
01879 
01880             while (cur->next  && cur->next  != channel_param) {
01881                 cur = cur->next ;
01882             }
01883 
01884             if (cur->next ) {
01885                 cur->next  = channel_param->next ;
01886             }
01887         }
01888         channel_param->next  = NULL;
01889     }
01890 
01891     return LORAWAN_STATUS_OK;
01892 }
01893 
01894 void LoRaMac::bind_radio_driver(LoRaRadio &radio)
01895 {
01896     _lora_phy.set_radio_instance(radio);
01897 }
01898 
01899 #if defined(LORAWAN_COMPLIANCE_TEST)
01900 /***************************************************************************
01901  * Compliance testing                                                      *
01902  **************************************************************************/
01903 
01904 
01905 lorawan_status_t LoRaMac::mlme_request(loramac_mlme_req_t *mlmeRequest)
01906 {
01907     if (LORAMAC_IDLE != _params.mac_state) {
01908         return LORAWAN_STATUS_BUSY;
01909     }
01910 
01911     reset_mlme_confirmation();
01912 
01913     _mlme_confirmation.req_type = mlmeRequest->type;
01914     _params.flags.bits.mlme_req = 1;
01915 
01916     lorawan_status_t status = LORAWAN_STATUS_SERVICE_UNKNOWN;
01917 
01918     if (MLME_TXCW  == mlmeRequest->type) {
01919         set_tx_continuous_wave(_params.channel, _params.sys_params.channel_data_rate, _params.sys_params.channel_tx_power,
01920                                _params.sys_params.max_eirp, _params.sys_params.antenna_gain, mlmeRequest->cw_tx_mode.timeout);
01921         _lora_time.start(_params.timers.mac_state_check_timer,
01922                          MAC_STATE_CHECK_TIMEOUT);
01923 
01924         _params.mac_state |= LORAMAC_TX_RUNNING;
01925         status = LORAWAN_STATUS_OK;
01926     } else if (MLME_TXCW_1  == mlmeRequest->type) {
01927         set_tx_continuous_wave(0, 0, mlmeRequest->cw_tx_mode.power, 0, 0, mlmeRequest->cw_tx_mode.timeout);
01928         _lora_time.start(_params.timers.mac_state_check_timer,
01929                          MAC_STATE_CHECK_TIMEOUT);
01930 
01931         _params.mac_state |= LORAMAC_TX_RUNNING;
01932         status = LORAWAN_STATUS_OK;
01933     }
01934 
01935     if (status != LORAWAN_STATUS_OK) {
01936         _params.is_node_ack_requested = false;
01937         _params.flags.bits.mlme_req = 0;
01938     }
01939 
01940     return status;
01941 }
01942 
01943 lorawan_status_t LoRaMac::test_request(loramac_compliance_test_req_t *mcpsRequest)
01944 {
01945     if (_params.mac_state != LORAMAC_IDLE) {
01946         return LORAWAN_STATUS_BUSY;
01947     }
01948 
01949     loramac_mhdr_t  machdr;
01950     int8_t datarate = mcpsRequest->data_rate;
01951     // TODO: The comment is different than the code???
01952     // Apply the minimum possible datarate.
01953     // Some regions have limitations for the minimum datarate.
01954     datarate = MAX(datarate, (int8_t)_lora_phy.get_minimum_tx_datarate());
01955 
01956     machdr.value  = 0;
01957 
01958     reset_mcps_confirmation();
01959 
01960     _params.ack_timeout_retry_counter = 1;
01961     _params.max_ack_timeout_retries = 1;
01962 
01963     switch (mcpsRequest->type) {
01964         case MCPS_UNCONFIRMED : {
01965             machdr.bits.mtype  = FRAME_TYPE_DATA_UNCONFIRMED_UP ;
01966             break;
01967         }
01968         case MCPS_CONFIRMED : {
01969             machdr.bits.mtype  = FRAME_TYPE_DATA_CONFIRMED_UP ;
01970             _params.max_ack_timeout_retries = mcpsRequest->nb_trials;
01971             break;
01972         }
01973         case MCPS_PROPRIETARY : {
01974             machdr.bits.mtype  = FRAME_TYPE_PROPRIETARY ;
01975             break;
01976         }
01977         default:
01978             return LORAWAN_STATUS_PARAMETER_INVALID;
01979     }
01980 
01981 //    Filter fPorts
01982 //    TODO: Does not work with PROPRIETARY messages
01983 //    if( IsFPortAllowed( mcpsRequest->fport ) == false ) {
01984 //        return LORAWAN_STATUS_PARAMETER_INVALID;
01985 //    }
01986 
01987     if (_params.sys_params.adr_on == false) {
01988         if (_lora_phy.verify_tx_datarate(datarate, false) == true) {
01989             _params.sys_params.channel_data_rate = datarate;
01990         } else {
01991             return LORAWAN_STATUS_PARAMETER_INVALID;
01992         }
01993     }
01994 
01995     lorawan_status_t status = send(&machdr, mcpsRequest->fport, mcpsRequest->f_buffer,
01996                                    mcpsRequest->f_buffer_size);
01997     if (status == LORAWAN_STATUS_OK) {
01998         _mcps_confirmation.req_type = mcpsRequest->type;
01999         _params.flags.bits.mcps_req = 1;
02000     } else {
02001         _params.is_node_ack_requested = false;
02002     }
02003 
02004     return status;
02005 }
02006 
02007 lorawan_status_t LoRaMac::LoRaMacSetTxTimer(uint32_t TxDutyCycleTime)
02008 {
02009     _lora_time.start(tx_next_packet_timer, TxDutyCycleTime);
02010     return LORAWAN_STATUS_OK;
02011 }
02012 
02013 lorawan_status_t LoRaMac::LoRaMacStopTxTimer()
02014 {
02015     _lora_time.stop(tx_next_packet_timer);
02016     return LORAWAN_STATUS_OK;
02017 }
02018 
02019 void LoRaMac::LoRaMacTestRxWindowsOn(bool enable)
02020 {
02021     _params.is_rx_window_enabled = enable;
02022 }
02023 
02024 void LoRaMac::LoRaMacTestSetMic(uint16_t txPacketCounter)
02025 {
02026     _params.ul_frame_counter = txPacketCounter;
02027     _params.is_ul_frame_counter_fixed = true;
02028 }
02029 
02030 void LoRaMac::LoRaMacTestSetDutyCycleOn(bool enable)
02031 {
02032     if (_lora_phy.verify_duty_cycle(enable) == true) {
02033         _params.is_dutycycle_on = enable;
02034     }
02035 }
02036 
02037 void LoRaMac::LoRaMacTestSetChannel(uint8_t channel)
02038 {
02039     _params.channel = channel;
02040 }
02041 #endif