Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

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