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