Gleb Klochkov / Mbed OS Climatcontroll_Main

Dependencies:   esp8266-driver

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