takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

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