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