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