Nicolas Borla / Mbed OS BBR_1Ebene
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::on_radio_rx_done(const uint8_t* const payload, uint16_t size,
00665                                int16_t rssi, int8_t snr)
00666 {
00667     // on reception turn off queued timers
00668     _lora_time.stop(_params.timers.rx_window1_timer);
00669     _lora_time.stop(_params.timers.rx_window2_timer);
00670 
00671     if (_device_class == CLASS_C) {
00672          open_rx2_window();
00673      } else {
00674          _lora_phy.put_radio_to_sleep();
00675      }
00676 
00677     loramac_mhdr_t  mac_hdr;
00678     uint8_t pos = 0;
00679     mac_hdr.value  = payload[pos++];
00680 
00681     switch (mac_hdr.bits.mtype ) {
00682 
00683         case FRAME_TYPE_JOIN_ACCEPT :
00684 
00685             if (nwk_joined()) {
00686                 abort_rx();
00687                 _mlme_confirmation.pending = false;
00688                 return;
00689             } else {
00690                 handle_join_accept_frame(payload, size);
00691                 _mlme_confirmation.pending = true;
00692             }
00693 
00694             break;
00695 
00696         case FRAME_TYPE_DATA_UNCONFIRMED_DOWN :
00697         case FRAME_TYPE_DATA_CONFIRMED_DOWN :
00698         case FRAME_TYPE_PROPRIETARY :
00699 
00700             handle_data_frame(payload, size, pos, mac_hdr.bits.mtype , rssi, snr);
00701 
00702             break;
00703 
00704         default:
00705             break;
00706     }
00707 }
00708 
00709 void LoRaMac::on_radio_tx_timeout( void )
00710 {
00711     _lora_time.stop(_params.timers.rx_window1_timer);
00712     _lora_time.stop(_params.timers.rx_window2_timer);
00713     _lora_time.stop(_params.timers.ack_timeout_timer);
00714 
00715     if (_device_class == CLASS_C) {
00716         open_rx2_window();
00717     } else {
00718         _lora_phy.put_radio_to_sleep();
00719     }
00720 
00721     _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ;
00722     _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ;
00723 
00724     _mac_commands.clear_command_buffer();
00725 
00726     _mcps_confirmation.nb_retries = _params.ack_timeout_retry_counter;
00727     _mcps_confirmation.ack_received = false;
00728     _mcps_confirmation.tx_toa = 0;
00729 
00730     post_process_mcps_req();
00731 }
00732 
00733 rx_slot_t  LoRaMac::on_radio_rx_timeout(bool is_timeout)
00734 {
00735     if (_device_class != CLASS_C) {
00736         _lora_phy.put_radio_to_sleep();
00737     }
00738 
00739     if (_params.rx_slot == RX_SLOT_WIN_1 ) {
00740         if (_params.is_node_ack_requested == true) {
00741             _mcps_confirmation.status = is_timeout ? LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT 
00742                     : LORAMAC_EVENT_INFO_STATUS_RX1_ERROR ;
00743         }
00744         _mlme_confirmation.status = is_timeout ? LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT 
00745                 : LORAMAC_EVENT_INFO_STATUS_RX1_ERROR ;
00746 
00747         if (_device_class != CLASS_C) {
00748             if (_lora_time.get_elapsed_time(_params.timers.aggregated_last_tx_time ) >= _params.rx_window2_delay) {
00749                 _lora_time.stop(_params.timers.rx_window2_timer);
00750             }
00751         }
00752     } else {
00753         if (_params.is_node_ack_requested == true) {
00754             _mcps_confirmation.status = is_timeout ? LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT 
00755                     : LORAMAC_EVENT_INFO_STATUS_RX2_ERROR ;
00756         }
00757 
00758         _mlme_confirmation.status = is_timeout ? LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT 
00759                 : LORAMAC_EVENT_INFO_STATUS_RX2_ERROR ;
00760     }
00761 
00762     if (_device_class == CLASS_C) {
00763        open_rx2_window();
00764     }
00765 
00766     return _params.rx_slot;
00767 }
00768 
00769 bool LoRaMac::continue_joining_process()
00770 {
00771     if (_params.join_request_trial_counter >= _params.max_join_request_trials) {
00772         return false;
00773     }
00774 
00775     // Schedule a retry
00776     if (handle_retransmission() != LORAWAN_STATUS_OK) {
00777         return false;
00778     }
00779 
00780     return true;
00781 }
00782 
00783 bool LoRaMac::continue_sending_process()
00784 {
00785     if (_params.ack_timeout_retry_counter >= _params.max_ack_timeout_retries) {
00786         _mac_commands.clear_command_buffer();
00787         _params.adr_ack_counter++;
00788         return false;
00789     }
00790 
00791     // retransmission will be handled in on_ack_timeout() whence the ACK timeout
00792     // gets fired
00793     return true;
00794 }
00795 
00796 lorawan_status_t LoRaMac::send_join_request()
00797 {
00798     lorawan_status_t status = LORAWAN_STATUS_OK;
00799     loramac_mhdr_t  mac_hdr;
00800     loramac_frame_ctrl_t  fctrl;
00801 
00802     _params.sys_params.channel_data_rate = _lora_phy.get_alternate_DR(
00803             _params.join_request_trial_counter + 1);
00804 
00805     mac_hdr.value  = 0;
00806     mac_hdr.bits.mtype  = FRAME_TYPE_JOIN_REQ ;
00807 
00808     fctrl.value  = 0;
00809     fctrl.bits.adr  = _params.sys_params.adr_on;
00810     _params.is_last_tx_join_request = true;
00811 
00812     /* In case of join request retransmissions, the stack must prepare
00813      * the frame again, because the network server keeps track of the random
00814      * LoRaMacDevNonce values to prevent reply attacks. */
00815     status = prepare_frame(&mac_hdr, &fctrl, 0, NULL, 0);
00816 
00817     if (status == LORAWAN_STATUS_OK) {
00818         status = schedule_tx();
00819     } else {
00820         tr_error("Retransmission: error %d", status);
00821     }
00822 
00823     return status;
00824 }
00825 
00826 /**
00827  * This function handles retransmission of failed or unacknowledged
00828  * outgoing traffic
00829  */
00830 lorawan_status_t LoRaMac::handle_retransmission()
00831 {
00832     if (!nwk_joined() && (_mlme_confirmation.req_type == MLME_JOIN )) {
00833         return send_join_request();
00834     }
00835 
00836     return schedule_tx();
00837 }
00838 
00839 /**
00840  * This function is called when the backoff_timer gets fired.
00841  * It is used for re-scheduling an unsent packet in the pipe. This packet
00842  * can be a Join Request or any other data packet.
00843  */
00844 void LoRaMac::on_backoff_timer_expiry(void)
00845 {
00846     Lock lock(*this);
00847     lorawan_status_t status = schedule_tx();
00848     MBED_ASSERT(status==LORAWAN_STATUS_OK);
00849 }
00850 
00851 void LoRaMac::open_rx1_window(void)
00852 {
00853     Lock lock(*this);
00854     _lora_time.stop(_params.timers.rx_window1_timer);
00855     _params.rx_slot = RX_SLOT_WIN_1 ;
00856 
00857     _params.rx_window1_config.channel = _params.channel;
00858     _params.rx_window1_config.dr_offset = _params.sys_params.rx1_dr_offset;
00859     _params.rx_window1_config.dl_dwell_time = _params.sys_params.downlink_dwell_time;
00860     _params.rx_window1_config.is_repeater_supported = _params.is_repeater_supported;
00861     _params.rx_window1_config.is_rx_continuous = false;
00862     _params.rx_window1_config.rx_slot = _params.rx_slot;
00863 
00864     if (_device_class == CLASS_C) {
00865         _lora_phy.put_radio_to_standby();
00866     }
00867 
00868     _mcps_indication.rx_datarate = _params.rx_window1_config.datarate;
00869     _lora_phy.rx_config(&_params.rx_window1_config);
00870 
00871     _lora_phy.setup_rx_window(_params.rx_window1_config.is_rx_continuous,
00872                               _params.sys_params.max_rx_win_time);
00873 }
00874 
00875 void LoRaMac::open_rx2_window()
00876 {
00877     Lock lock(*this);
00878     _lora_time.stop(_params.timers.rx_window2_timer);
00879 
00880     _params.rx_window2_config.channel = _params.channel;
00881     _params.rx_window2_config.frequency = _params.sys_params.rx2_channel.frequency;
00882     _params.rx_window2_config.dl_dwell_time = _params.sys_params.downlink_dwell_time;
00883     _params.rx_window2_config.is_repeater_supported = _params.is_repeater_supported;
00884     _params.rx_window2_config.rx_slot = RX_SLOT_WIN_2 ;
00885 
00886     _params.rx_window2_config.is_rx_continuous = get_device_class()==CLASS_C ? true : false;
00887 
00888     _mcps_indication.rx_datarate = _params.rx_window2_config.datarate;
00889 
00890     if (_lora_phy.rx_config(&_params.rx_window2_config)) {
00891 
00892         _lora_phy.setup_rx_window(_params.rx_window2_config.is_rx_continuous,
00893                                   _params.sys_params.max_rx_win_time);
00894 
00895         _params.rx_slot = _params.rx_window2_config.is_rx_continuous ?
00896                           RX_SLOT_WIN_CLASS_C  : RX_SLOT_WIN_2 ;
00897     }
00898 }
00899 
00900 void LoRaMac::check_to_disable_ack_timeout(bool node_ack_requested,
00901                                            device_class_t dev_class,
00902                                            bool ack_received,
00903                                            uint8_t ack_timeout_retries_counter,
00904                                            uint8_t ack_timeout_retries)
00905 {
00906     // There are three cases where we need to stop the AckTimeoutTimer:
00907     if( node_ack_requested == false ) {
00908         if( dev_class == CLASS_C ) {
00909             // FIRST CASE
00910             // We have performed an unconfirmed uplink in class c mode
00911             // and have received a downlink in RX1 or RX2.
00912             _lora_time.stop(_params.timers.ack_timeout_timer);
00913         }
00914     } else {
00915         if( ack_received == 1 ) {
00916             // SECOND CASE
00917             // We received an ACK for previously sent confirmable message
00918             _lora_time.stop(_params.timers.ack_timeout_timer);
00919         } else {
00920             // THIRD CASE
00921             // Max number of retries exceeded for confirmable message
00922             if( ack_timeout_retries_counter > ack_timeout_retries ) {
00923                 _lora_time.stop(_params.timers.ack_timeout_timer);
00924             }
00925         }
00926     }
00927 }
00928 
00929 void LoRaMac::on_ack_timeout_timer_event(void)
00930 {
00931     Lock lock(*this);
00932     _params.ack_timeout_retry_counter++;
00933 
00934     // reduce data rate
00935     if ((_params.ack_timeout_retry_counter % 2)) {
00936         _params.sys_params.channel_data_rate = _lora_phy.get_next_lower_tx_datarate(
00937                                                _params.sys_params.channel_data_rate);
00938     }
00939 
00940     // Schedule a retry
00941     if (handle_retransmission() != LORAWAN_STATUS_OK) {
00942         // In a case when enabled channels are not found, PHY layer
00943         // resorts to default channels. Next attempt should go forward as the
00944         // default channels are always available if there is a base station in the
00945         // vicinity. Otherwise something is wrong with the stack, we should assert
00946         // here
00947         _mac_commands.clear_command_buffer();
00948         _params.is_node_ack_requested = false;
00949         _mcps_confirmation.ack_received = false;
00950         _mcps_confirmation.nb_retries = _params.ack_timeout_retry_counter;
00951 
00952         // now that is a critical failure
00953         lorawan_status_t status = handle_retransmission();
00954         MBED_ASSERT(status==LORAWAN_STATUS_OK);
00955     }
00956 }
00957 
00958 bool LoRaMac::validate_payload_length(uint16_t length,
00959                                       int8_t datarate,
00960                                       uint8_t fopts_len)
00961 {
00962     uint16_t max_value = 0;
00963     uint16_t payloadSize = 0;
00964 
00965     max_value = _lora_phy.get_max_payload(datarate, _params.is_repeater_supported);
00966 
00967     // Calculate the resulting payload size
00968     payloadSize = (length + fopts_len);
00969 
00970     // Validation of the application payload size
00971     if ((payloadSize <= max_value) &&
00972         (payloadSize <= LORAMAC_PHY_MAXPAYLOAD)) {
00973         return true;
00974     }
00975     return false;
00976 }
00977 
00978 void LoRaMac::set_mlme_schedule_ul_indication(void)
00979 {
00980     _mlme_indication.indication_type = MLME_SCHEDULE_UPLINK ;
00981     _mlme_indication.pending= true;
00982 }
00983 
00984 // This is not actual transmission. It just schedules a message in response
00985 // to MCPS request
00986 lorawan_status_t LoRaMac::send(loramac_mhdr_t  *machdr, const uint8_t fport,
00987                                const void *fbuffer, uint16_t fbuffer_size)
00988 {
00989     loramac_frame_ctrl_t  fctrl;
00990 
00991     fctrl.value  = 0;
00992     fctrl.bits.fopts_len  = 0;
00993     fctrl.bits.fpending  = 0;
00994     fctrl.bits.ack  = false;
00995     fctrl.bits.adr_ack_req  = false;
00996     fctrl.bits.adr  = _params.sys_params.adr_on;
00997 
00998     lorawan_status_t status = prepare_frame(machdr, &fctrl, fport, fbuffer,
00999                                             fbuffer_size);
01000 
01001     if (status != LORAWAN_STATUS_OK) {
01002         return status;
01003     }
01004 
01005     // Reset confirm parameters
01006     _mcps_confirmation.nb_retries = 0;
01007     _mcps_confirmation.ack_received = false;
01008     _mcps_confirmation.ul_frame_counter = _params.ul_frame_counter;
01009 
01010     status = schedule_tx();
01011 
01012     return status;
01013 }
01014 
01015 lorawan_status_t LoRaMac::schedule_tx()
01016 {
01017     channel_selection_params_t next_channel;
01018     lorawan_time_t backoff_time = 0;
01019 
01020     if (_params.sys_params.max_duty_cycle == 255) {
01021         return LORAWAN_STATUS_DEVICE_OFF;
01022     }
01023 
01024     if (_params.sys_params.max_duty_cycle == 0) {
01025         _params.timers.aggregated_timeoff = 0;
01026     }
01027 
01028     calculate_backOff(_params.last_channel_idx);
01029 
01030     next_channel.aggregate_timeoff = _params.timers.aggregated_timeoff;
01031     next_channel.current_datarate = _params.sys_params.channel_data_rate;
01032     _params.is_dutycycle_on = MBED_CONF_LORA_DUTY_CYCLE_ON;
01033     next_channel.dc_enabled = _params.is_dutycycle_on;
01034     next_channel.joined = _is_nwk_joined;
01035     next_channel.last_aggregate_tx_time = _params.timers.aggregated_last_tx_time;
01036 
01037     lorawan_status_t status = _lora_phy.set_next_channel(&next_channel,
01038                                                          &_params.channel,
01039                                                          &backoff_time,
01040                                                          &_params.timers.aggregated_timeoff);
01041 
01042     switch (status) {
01043         case LORAWAN_STATUS_NO_CHANNEL_FOUND:
01044         case LORAWAN_STATUS_NO_FREE_CHANNEL_FOUND:
01045             return status;
01046         case LORAWAN_STATUS_DUTYCYCLE_RESTRICTED:
01047             if (backoff_time != 0) {
01048                 tr_debug("Next Transmission in %lu ms", backoff_time);
01049                 _lora_time.start(_params.timers.backoff_timer, backoff_time);
01050             }
01051             return LORAWAN_STATUS_OK;
01052         default:
01053             break;
01054     }
01055 
01056     tr_debug("Next Channel Idx=%d, DR=%d", _params.channel, next_channel.current_datarate);
01057 
01058     uint8_t dr_offset = _lora_phy.apply_DR_offset(_params.sys_params.channel_data_rate,
01059                                                   _params.sys_params.rx1_dr_offset);
01060 
01061     _lora_phy.compute_rx_win_params(dr_offset, _params.sys_params.min_rx_symb,
01062                                     _params.sys_params.max_sys_rx_error,
01063                                     &_params.rx_window1_config);
01064 
01065     _lora_phy.compute_rx_win_params(_params.sys_params.rx2_channel.datarate,
01066                                     _params.sys_params.min_rx_symb,
01067                                     _params.sys_params.max_sys_rx_error,
01068                                     &_params.rx_window2_config);
01069 
01070     if (!_is_nwk_joined) {
01071         _params.rx_window1_delay = _params.sys_params.join_accept_delay1
01072                 + _params.rx_window1_config.window_offset;
01073         _params.rx_window2_delay = _params.sys_params.join_accept_delay2
01074                 + _params.rx_window2_config.window_offset;
01075     } else {
01076         if (validate_payload_length(_params.tx_buffer_len,
01077                                     _params.sys_params.channel_data_rate,
01078                                     _mac_commands.get_mac_cmd_length()) == false) {
01079             return LORAWAN_STATUS_LENGTH_ERROR;
01080         }
01081         _params.rx_window1_delay = _params.sys_params.recv_delay1
01082                 + _params.rx_window1_config.window_offset;
01083         _params.rx_window2_delay = _params.sys_params.recv_delay2
01084                 + _params.rx_window2_config.window_offset;
01085     }
01086 
01087     return send_frame_on_channel(_params.channel);
01088 }
01089 
01090 void LoRaMac::calculate_backOff(uint8_t channel)
01091 {
01092     lorawan_time_t elapsed_time = _lora_time.get_elapsed_time(_params.timers.mac_init_time);
01093 
01094     _params.is_dutycycle_on = MBED_CONF_LORA_DUTY_CYCLE_ON;
01095 
01096     _lora_phy.calculate_backoff(_is_nwk_joined, _params.is_last_tx_join_request, _params.is_dutycycle_on,
01097                                 channel, elapsed_time, _params.timers.tx_toa);
01098 
01099     // Update aggregated time-off. This must be an assignment and no incremental
01100     // update as we do only calculate the time-off based on the last transmission
01101     _params.timers.aggregated_timeoff = (_params.timers.tx_toa * _params.sys_params.aggregated_duty_cycle
01102                                          - _params.timers.tx_toa);
01103 }
01104 
01105 void LoRaMac::reset_mac_parameters(void)
01106 {
01107     _is_nwk_joined = false;
01108 
01109     _params.ul_frame_counter = 0;
01110     _params.dl_frame_counter = 0;
01111     _params.adr_ack_counter = 0;
01112 
01113     _params.ul_nb_rep_counter = 0;
01114 
01115     _params.max_ack_timeout_retries = 1;
01116     _params.ack_timeout_retry_counter = 1;
01117     _params.is_ack_retry_timeout_expired = false;
01118 
01119     _params.sys_params.max_duty_cycle = 0;
01120     _params.sys_params.aggregated_duty_cycle = 1;
01121 
01122     _mac_commands.clear_command_buffer();
01123     _mac_commands.clear_repeat_buffer();
01124     _mac_commands.clear_mac_commands_in_next_tx();
01125 
01126     _params.is_rx_window_enabled = true;
01127 
01128     _lora_phy.reset_to_default_values(&_params, false);
01129 
01130     _params.is_node_ack_requested = false;
01131     _params.is_srv_ack_requested = false;
01132 
01133     multicast_params_t  *cur = _params.multicast_channels;
01134     while (cur != NULL) {
01135         cur->dl_frame_counter  = 0;
01136         cur = cur->next ;
01137     }
01138     _params.channel = 0;
01139     _params.last_channel_idx = _params.channel;
01140 }
01141 
01142 uint8_t LoRaMac::get_default_tx_datarate()
01143 {
01144     return _lora_phy.get_default_tx_datarate();
01145 }
01146 
01147 void LoRaMac::enable_adaptive_datarate(bool adr_enabled)
01148 {
01149     _params.sys_params.adr_on = adr_enabled;
01150 }
01151 
01152 lorawan_status_t LoRaMac::set_channel_data_rate(uint8_t data_rate)
01153 {
01154     if (_params.sys_params.adr_on) {
01155         tr_error("Cannot set data rate. Please turn off ADR first.");
01156         return LORAWAN_STATUS_PARAMETER_INVALID;
01157     }
01158 
01159     if (_lora_phy.verify_tx_datarate(data_rate, false) == true) {
01160         _params.sys_params.channel_data_rate = data_rate;
01161     } else {
01162         return LORAWAN_STATUS_PARAMETER_INVALID;
01163     }
01164 
01165     return LORAWAN_STATUS_OK;
01166 }
01167 
01168 bool LoRaMac::tx_ongoing()
01169 {
01170     return _ongoing_tx_msg.tx_ongoing;
01171 }
01172 
01173 void LoRaMac::set_tx_ongoing(bool ongoing)
01174 {
01175     _ongoing_tx_msg.tx_ongoing = ongoing;
01176 }
01177 
01178 void LoRaMac::reset_ongoing_tx(bool reset_pending)
01179 {
01180     _ongoing_tx_msg.tx_ongoing = false;
01181     memset(_ongoing_tx_msg.f_buffer, 0, MBED_CONF_LORA_TX_MAX_SIZE);
01182     _ongoing_tx_msg.f_buffer_size = 0;
01183     if (reset_pending) {
01184         _ongoing_tx_msg.pending_size = 0;
01185     }
01186 }
01187 
01188 int16_t LoRaMac::prepare_ongoing_tx(const uint8_t port,
01189                                     const uint8_t* const data,
01190                                     uint16_t length,
01191                                     uint8_t flags,
01192                                     uint8_t num_retries)
01193 {
01194     _ongoing_tx_msg.port = port;
01195 
01196     uint8_t max_possible_size = get_max_possible_tx_size(length);
01197 
01198     if (max_possible_size > MBED_CONF_LORA_TX_MAX_SIZE) {
01199         max_possible_size = MBED_CONF_LORA_TX_MAX_SIZE;
01200     }
01201 
01202     if (max_possible_size < length) {
01203         tr_info("Cannot transmit %d bytes. Possible TX Size is %d bytes",
01204                 length, max_possible_size);
01205 
01206         _ongoing_tx_msg.pending_size = length - max_possible_size;
01207         _ongoing_tx_msg.f_buffer_size = max_possible_size;
01208         memcpy(_ongoing_tx_msg.f_buffer, data, _ongoing_tx_msg.f_buffer_size);
01209     } else {
01210         _ongoing_tx_msg.f_buffer_size = length;
01211         _ongoing_tx_msg.pending_size = 0;
01212         if (length > 0) {
01213             memcpy(_ongoing_tx_msg.f_buffer, data, length);
01214         }
01215     }
01216 
01217     // Handles all unconfirmed messages, including proprietary and multicast
01218     if ((flags & MSG_FLAG_MASK) == MSG_UNCONFIRMED_FLAG
01219             || (flags & MSG_FLAG_MASK) == MSG_UNCONFIRMED_MULTICAST
01220             || (flags & MSG_FLAG_MASK) == MSG_UNCONFIRMED_PROPRIETARY) {
01221 
01222          _ongoing_tx_msg.type = MCPS_UNCONFIRMED ;
01223          _ongoing_tx_msg.fport = port;
01224          _ongoing_tx_msg.nb_trials = 1;
01225     }
01226 
01227     // Handles all confirmed messages, including proprietary and multicast
01228     if ((flags & MSG_FLAG_MASK) == MSG_CONFIRMED_FLAG
01229             || (flags & MSG_FLAG_MASK) == MSG_CONFIRMED_MULTICAST
01230             || (flags & MSG_FLAG_MASK) == MSG_CONFIRMED_PROPRIETARY) {
01231 
01232         _ongoing_tx_msg.type = MCPS_CONFIRMED ;
01233         _ongoing_tx_msg.fport = port;
01234         _ongoing_tx_msg.nb_trials = num_retries;
01235     }
01236 
01237     tr_info("RTS = %u bytes, PEND = %u, Port: %u",
01238             _ongoing_tx_msg.f_buffer_size, _ongoing_tx_msg.pending_size,
01239             _ongoing_tx_msg.fport);
01240 
01241     return _ongoing_tx_msg.f_buffer_size;
01242 }
01243 
01244 lorawan_status_t LoRaMac::send_ongoing_tx()
01245 {
01246     lorawan_status_t status;
01247     _params.is_last_tx_join_request = false;
01248     int8_t datarate = _params.sys_params.channel_data_rate;
01249 
01250     // TODO: The comment is different than the code???
01251     // Apply the minimum possible datarate.
01252     // Some regions have limitations for the minimum datarate.
01253     datarate = MAX(datarate, (int8_t)_lora_phy.get_minimum_tx_datarate());
01254 
01255     loramac_mhdr_t  machdr;
01256     machdr.value  = 0;
01257 
01258     reset_mcps_confirmation();
01259 
01260     _params.ack_timeout_retry_counter = 1;
01261     _params.max_ack_timeout_retries = 1;
01262 
01263     if (MCPS_UNCONFIRMED  == _ongoing_tx_msg.type) {
01264         machdr.bits.mtype = FRAME_TYPE_DATA_UNCONFIRMED_UP ;
01265     } else if (_ongoing_tx_msg.type == MCPS_CONFIRMED ) {
01266         machdr.bits.mtype = FRAME_TYPE_DATA_CONFIRMED_UP ;
01267         _params.max_ack_timeout_retries = _ongoing_tx_msg.nb_trials;
01268     } else if (_ongoing_tx_msg.type == MCPS_PROPRIETARY ) {
01269         //TODO: Is this dead code currently??? Nobody sets this type
01270         machdr.bits.mtype = FRAME_TYPE_PROPRIETARY ;
01271     } else {
01272         return LORAWAN_STATUS_SERVICE_UNKNOWN;
01273     }
01274 
01275     if (_params.sys_params.adr_on == false) {
01276         if (_lora_phy.verify_tx_datarate(datarate, false) == true) {
01277             _params.sys_params.channel_data_rate = datarate;
01278         } else {
01279             return LORAWAN_STATUS_PARAMETER_INVALID;
01280         }
01281     }
01282 
01283     status = send(&machdr, _ongoing_tx_msg.fport, _ongoing_tx_msg.f_buffer,
01284                            _ongoing_tx_msg.f_buffer_size);
01285     if (status == LORAWAN_STATUS_OK) {
01286         _mcps_confirmation.req_type = _ongoing_tx_msg.type;
01287     }
01288 
01289     return status;
01290 }
01291 
01292 device_class_t LoRaMac::get_device_class() const
01293 {
01294     return _device_class;
01295 }
01296 
01297 void LoRaMac::set_device_class(const device_class_t& device_class)
01298 {
01299     _device_class = device_class;
01300 
01301     if (CLASS_A == _device_class) {
01302         _lora_phy.put_radio_to_sleep();
01303     } else if (CLASS_C == _device_class) {
01304         _params.is_node_ack_requested = false;
01305         _lora_phy.put_radio_to_sleep();
01306         _lora_phy.compute_rx_win_params(
01307                     _params.sys_params.rx2_channel.datarate,
01308                     _params.sys_params.min_rx_symb,
01309                     _params.sys_params.max_sys_rx_error,
01310                     &_params.rx_window2_config);
01311     }
01312     if (CLASS_C == _device_class) {
01313         open_rx2_window();
01314     }
01315 }
01316 
01317 void LoRaMac::setup_link_check_request()
01318 {
01319     reset_mlme_confirmation();
01320 
01321     _mlme_confirmation.req_type = MLME_LINK_CHECK ;
01322     _mlme_confirmation.pending = true;
01323     _mac_commands.add_link_check_req();
01324 }
01325 
01326 lorawan_status_t LoRaMac::prepare_join(const lorawan_connect_t *params, bool is_otaa)
01327 {
01328     if (params) {
01329         if (is_otaa) {
01330             if ((params->connection_u.otaa.dev_eui == NULL) ||
01331                 (params->connection_u.otaa.app_eui == NULL) ||
01332                 (params->connection_u.otaa.app_key == NULL) ||
01333                 (params->connection_u.otaa.nb_trials == 0)) {
01334                 return LORAWAN_STATUS_PARAMETER_INVALID;
01335             }
01336             _params.keys.dev_eui = params->connection_u.otaa.dev_eui;
01337             _params.keys.app_eui = params->connection_u.otaa.app_eui;
01338             _params.keys.app_key = params->connection_u.otaa.app_key;
01339             _params.max_join_request_trials = params->connection_u.otaa.nb_trials;
01340 
01341             if (!_lora_phy.verify_nb_join_trials(params->connection_u.otaa.nb_trials)) {
01342                 // Value not supported, get default
01343                 _params.max_join_request_trials = MBED_CONF_LORA_NB_TRIALS;
01344             }
01345             // Reset variable JoinRequestTrials
01346             _params.join_request_trial_counter = 0;
01347         } else {
01348             _params.net_id = params->connection_u.abp.nwk_id;
01349             _params.dev_addr = params->connection_u.abp.dev_addr;
01350 
01351             memcpy(_params.keys.nwk_skey, params->connection_u.abp.nwk_skey,
01352                    sizeof(_params.keys.nwk_skey));
01353 
01354             memcpy(_params.keys.app_skey, params->connection_u.abp.app_skey,
01355                    sizeof(_params.keys.app_skey));
01356         }
01357     } else {
01358 #if MBED_CONF_LORA_OVER_THE_AIR_ACTIVATION
01359     const static uint8_t dev_eui[] = MBED_CONF_LORA_DEVICE_EUI;
01360     const static uint8_t app_eui[] = MBED_CONF_LORA_APPLICATION_EUI;
01361     const static uint8_t app_key[] = MBED_CONF_LORA_APPLICATION_KEY;
01362 
01363     _params.keys.app_eui = const_cast<uint8_t *>(app_eui);
01364     _params.keys.dev_eui = const_cast<uint8_t *>(dev_eui);
01365     _params.keys.app_key = const_cast<uint8_t *>(app_key);
01366     _params.max_join_request_trials = MBED_CONF_LORA_NB_TRIALS;
01367 
01368     // Reset variable JoinRequestTrials
01369     _params.join_request_trial_counter = 0;
01370 
01371     reset_mac_parameters();
01372 
01373     _params.sys_params.channel_data_rate =
01374             _lora_phy.get_alternate_DR(_params.join_request_trial_counter + 1);
01375 
01376 #else
01377     const static uint8_t nwk_skey[] = MBED_CONF_LORA_NWKSKEY;
01378     const static uint8_t app_skey[] = MBED_CONF_LORA_APPSKEY;
01379 
01380     _params.net_id = (MBED_CONF_LORA_DEVICE_ADDRESS & LORAWAN_NETWORK_ID_MASK);
01381     _params.dev_addr = MBED_CONF_LORA_DEVICE_ADDRESS;
01382 
01383     memcpy(_params.keys.nwk_skey, nwk_skey,
01384            sizeof(_params.keys.nwk_skey));
01385 
01386     memcpy(_params.keys.app_skey, app_skey,
01387            sizeof(_params.keys.app_skey));
01388 #endif
01389     }
01390     return LORAWAN_STATUS_OK;
01391 }
01392 
01393 lorawan_status_t LoRaMac::join(bool is_otaa)
01394 {
01395     if (!is_otaa) {
01396         set_nwk_joined(true);
01397         return LORAWAN_STATUS_OK;
01398     }
01399 
01400     reset_mlme_confirmation();
01401     _mlme_confirmation.req_type = MLME_JOIN ;
01402 
01403     return send_join_request();
01404 }
01405 
01406 static void memcpy_convert_endianess(uint8_t *dst,
01407                                      const uint8_t *src,
01408                                      uint16_t size)
01409 {
01410     dst = dst + (size - 1);
01411     while (size--) {
01412         *dst-- = *src++;
01413     }
01414 }
01415 
01416 lorawan_status_t LoRaMac::prepare_frame(loramac_mhdr_t  *machdr,
01417                                         loramac_frame_ctrl_t  *fctrl,
01418                                         const uint8_t fport,
01419                                         const void *fbuffer,
01420                                         uint16_t fbuffer_size)
01421 {
01422     uint16_t i;
01423     uint8_t pkt_header_len = 0;
01424     uint32_t mic = 0;
01425     const void* payload = fbuffer;
01426     uint8_t frame_port = fport;
01427     lorawan_status_t status = LORAWAN_STATUS_OK;
01428 
01429     _params.tx_buffer_len = 0;
01430 
01431     _params.is_node_ack_requested = false;
01432 
01433     if (fbuffer == NULL) {
01434         fbuffer_size = 0;
01435     }
01436 
01437     _params.tx_buffer_len = fbuffer_size;
01438 
01439     _params.tx_buffer[pkt_header_len++] = machdr->value ;
01440 
01441     switch (machdr->bits.mtype ) {
01442 
01443         case FRAME_TYPE_JOIN_REQ :
01444 
01445             _params.tx_buffer_len = pkt_header_len;
01446             memcpy_convert_endianess(_params.tx_buffer + _params.tx_buffer_len,
01447                                      _params.keys.app_eui, 8);
01448             _params.tx_buffer_len += 8;
01449             memcpy_convert_endianess(_params.tx_buffer + _params.tx_buffer_len,
01450                                      _params.keys.dev_eui, 8);
01451             _params.tx_buffer_len += 8;
01452 
01453             _params.dev_nonce = _lora_phy.get_radio_rng();
01454 
01455             _params.tx_buffer[_params.tx_buffer_len++] = _params.dev_nonce & 0xFF;
01456             _params.tx_buffer[_params.tx_buffer_len++] = (_params.dev_nonce >> 8) & 0xFF;
01457 
01458             if (0 != _lora_crypto.compute_join_frame_mic(_params.tx_buffer,
01459                                                          _params.tx_buffer_len & 0xFF,
01460                                                          _params.keys.app_key,
01461                                                          APPKEY_KEY_LENGTH,
01462                                                          &mic)) {
01463                 return LORAWAN_STATUS_CRYPTO_FAIL;
01464             }
01465 
01466             _params.tx_buffer[_params.tx_buffer_len++] = mic & 0xFF;
01467             _params.tx_buffer[_params.tx_buffer_len++] = (mic >> 8) & 0xFF;
01468             _params.tx_buffer[_params.tx_buffer_len++] = (mic >> 16) & 0xFF;
01469             _params.tx_buffer[_params.tx_buffer_len++] = (mic >> 24) & 0xFF;
01470 
01471             break;
01472         case FRAME_TYPE_DATA_CONFIRMED_UP :
01473             _params.is_node_ack_requested = true;
01474             //Intentional fallthrough
01475         case FRAME_TYPE_DATA_UNCONFIRMED_UP : {
01476             if (!_is_nwk_joined) {
01477                 return LORAWAN_STATUS_NO_NETWORK_JOINED;
01478             }
01479 
01480             if (_params.sys_params.adr_on) {
01481                 if (_lora_phy.get_next_ADR(true,
01482                                            _params.sys_params.channel_data_rate,
01483                                            _params.sys_params.channel_tx_power,
01484                                            _params.adr_ack_counter)) {
01485                     fctrl->bits.adr_ack_req  = 1;
01486                 }
01487             }
01488 
01489             if (_params.is_srv_ack_requested == true) {
01490                 _params.is_srv_ack_requested = false;
01491                 fctrl->bits.ack  = 1;
01492             }
01493 
01494             _params.tx_buffer[pkt_header_len++] = (_params.dev_addr) & 0xFF;
01495             _params.tx_buffer[pkt_header_len++] = (_params.dev_addr >> 8) & 0xFF;
01496             _params.tx_buffer[pkt_header_len++] = (_params.dev_addr >> 16) & 0xFF;
01497             _params.tx_buffer[pkt_header_len++] = (_params.dev_addr >> 24) & 0xFF;
01498 
01499             _params.tx_buffer[pkt_header_len++] = fctrl->value ;
01500 
01501             _params.tx_buffer[pkt_header_len++] = _params.ul_frame_counter & 0xFF;
01502             _params.tx_buffer[pkt_header_len++] = (_params.ul_frame_counter >> 8)
01503                     & 0xFF;
01504 
01505             _mac_commands.copy_repeat_commands_to_buffer();
01506 
01507             const uint8_t mac_commands_len = _mac_commands.get_mac_cmd_length();
01508 
01509             if ((payload != NULL) && (_params.tx_buffer_len > 0)) {
01510                 if (_mac_commands.is_mac_command_in_next_tx() == true) {
01511                     if (mac_commands_len <= LORA_MAC_COMMAND_MAX_FOPTS_LENGTH) {
01512                         fctrl->bits.fopts_len  += mac_commands_len;
01513 
01514                         // Update FCtrl field with new value of OptionsLength
01515                         _params.tx_buffer[0x05] = fctrl->value ;
01516 
01517                         const uint8_t *buffer =
01518                                 _mac_commands.get_mac_commands_buffer();
01519                         for (i = 0; i < mac_commands_len; i++) {
01520                             _params.tx_buffer[pkt_header_len++] = buffer[i];
01521                         }
01522                     } else {
01523                         _params.tx_buffer_len = mac_commands_len;
01524                         payload = _mac_commands.get_mac_commands_buffer();
01525                         frame_port = 0;
01526                     }
01527                 }
01528             } else {
01529                 if ((mac_commands_len > 0)
01530                         && (_mac_commands.is_mac_command_in_next_tx() == true)) {
01531                     _params.tx_buffer_len = mac_commands_len;
01532                     payload = _mac_commands.get_mac_commands_buffer();
01533                     frame_port = 0;
01534                 }
01535             }
01536 
01537             _mac_commands.parse_mac_commands_to_repeat();
01538 
01539             if ((payload != NULL) && (_params.tx_buffer_len > 0)) {
01540                 _params.tx_buffer[pkt_header_len++] = frame_port;
01541 
01542                 uint8_t *key = _params.keys.app_skey;
01543                 uint32_t key_length = sizeof(_params.keys.app_skey)*8;
01544                 if (frame_port == 0) {
01545                     _mac_commands.clear_command_buffer();
01546                     key = _params.keys.nwk_skey;
01547                     key_length = sizeof(_params.keys.nwk_skey)*8;
01548                 }
01549                 if (0 != _lora_crypto.encrypt_payload((uint8_t*) payload, _params.tx_buffer_len,
01550                                                       key, key_length,
01551                                                       _params.dev_addr, UP_LINK,
01552                                                       _params.ul_frame_counter,
01553                                                       &_params.tx_buffer[pkt_header_len])) {
01554                     status = LORAWAN_STATUS_CRYPTO_FAIL;
01555                 }
01556             }
01557 
01558             _params.tx_buffer_len = pkt_header_len + _params.tx_buffer_len;
01559 
01560             if (0 != _lora_crypto.compute_mic(_params.tx_buffer, _params.tx_buffer_len,
01561                                               _params.keys.nwk_skey, sizeof(_params.keys.nwk_skey)*8,
01562                                               _params.dev_addr,
01563                                               UP_LINK, _params.ul_frame_counter, &mic)) {
01564                 status = LORAWAN_STATUS_CRYPTO_FAIL;
01565             }
01566 
01567             _params.tx_buffer[_params.tx_buffer_len + 0] = mic & 0xFF;
01568             _params.tx_buffer[_params.tx_buffer_len + 1] = (mic >> 8) & 0xFF;
01569             _params.tx_buffer[_params.tx_buffer_len + 2] = (mic >> 16) & 0xFF;
01570             _params.tx_buffer[_params.tx_buffer_len + 3] = (mic >> 24) & 0xFF;
01571 
01572             _params.tx_buffer_len += LORAMAC_MFR_LEN;
01573         }
01574             break;
01575         case FRAME_TYPE_PROPRIETARY :
01576             if ((fbuffer != NULL) && (_params.tx_buffer_len > 0)) {
01577                 memcpy(_params.tx_buffer + pkt_header_len, (uint8_t*) fbuffer,
01578                        _params.tx_buffer_len);
01579                 _params.tx_buffer_len = pkt_header_len + _params.tx_buffer_len;
01580             }
01581             break;
01582         default:
01583             status = LORAWAN_STATUS_SERVICE_UNKNOWN;
01584     }
01585 
01586     tr_debug("Frame prepared to send at port %u", frame_port);
01587 
01588     return status;
01589 }
01590 
01591 lorawan_status_t LoRaMac::send_frame_on_channel(uint8_t channel)
01592 {
01593     tx_config_params_t tx_config;
01594     int8_t tx_power = 0;
01595 
01596     tx_config.channel = channel;
01597     tx_config.datarate = _params.sys_params.channel_data_rate;
01598     tx_config.tx_power = _params.sys_params.channel_tx_power;
01599     tx_config.max_eirp = _params.sys_params.max_eirp;
01600     tx_config.antenna_gain = _params.sys_params.antenna_gain;
01601     tx_config.pkt_len = _params.tx_buffer_len;
01602 
01603     _lora_phy.tx_config(&tx_config, &tx_power, &_params.timers.tx_toa);
01604 
01605     _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
01606 
01607     _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
01608     _mcps_confirmation.data_rate = _params.sys_params.channel_data_rate;
01609     _mcps_confirmation.tx_power = tx_power;
01610     _mcps_confirmation.channel = channel;
01611 
01612     _mcps_confirmation.tx_toa = _params.timers.tx_toa;
01613     _mlme_confirmation.tx_toa = _params.timers.tx_toa;
01614 
01615    // _lora_time.start(_params.timers.mac_state_check_timer,
01616    //                  MAC_STATE_CHECK_TIMEOUT);
01617 
01618     if (!_is_nwk_joined) {
01619         _params.join_request_trial_counter++;
01620     }
01621 
01622     _lora_phy.handle_send(_params.tx_buffer, _params.tx_buffer_len);
01623 
01624     return LORAWAN_STATUS_OK;
01625 }
01626 
01627 void LoRaMac::reset_mcps_confirmation()
01628 {
01629     memset((uint8_t*) &_mcps_confirmation, 0, sizeof(_mcps_confirmation));
01630     _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
01631 }
01632 
01633 void LoRaMac::reset_mlme_confirmation()
01634 {
01635     memset((uint8_t*) &_mlme_confirmation, 0, sizeof(_mlme_confirmation));
01636     _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
01637 }
01638 
01639 void LoRaMac::reset_mcps_indication()
01640 {
01641     memset((uint8_t*) &_mcps_indication, 0, sizeof(_mcps_indication));
01642     _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
01643 }
01644 
01645 void LoRaMac::set_tx_continuous_wave(uint8_t channel, int8_t datarate, int8_t tx_power,
01646                                      float max_eirp, float antenna_gain, uint16_t timeout)
01647 {
01648     cw_mode_params_t  continuous_wave;
01649 
01650     continuous_wave.channel  = channel;
01651     continuous_wave.datarate  = datarate;
01652     continuous_wave.tx_power  = tx_power;
01653     continuous_wave.max_eirp  = max_eirp;
01654     continuous_wave.antenna_gain  = antenna_gain;
01655     continuous_wave.timeout  = timeout;
01656 
01657     _lora_phy.set_tx_cont_mode(&continuous_wave);
01658 }
01659 
01660 lorawan_status_t LoRaMac::initialize(EventQueue *queue)
01661 {
01662     _lora_time.activate_timer_subsystem(queue);
01663 
01664     _ev_queue = queue;
01665 
01666     _channel_plan.activate_channelplan_subsystem(&_lora_phy);
01667 
01668     _device_class = CLASS_A;
01669 
01670     _params.join_request_trial_counter = 0;
01671     _params.max_join_request_trials = 1;
01672     _params.is_repeater_supported = false;
01673 
01674     _params.timers.aggregated_last_tx_time = 0;
01675     _params.timers.aggregated_timeoff = 0;
01676 
01677     _lora_phy.reset_to_default_values(&_params, true);
01678 
01679     _params.sys_params.max_sys_rx_error = 10;
01680     _params.sys_params.min_rx_symb = 6;
01681     _params.sys_params.retry_num = 1;
01682 
01683     reset_mac_parameters();
01684 
01685     srand(_lora_phy.get_radio_rng());
01686 
01687     _params.is_nwk_public = MBED_CONF_LORA_PUBLIC_NETWORK;
01688     _lora_phy.setup_public_network_mode(_params.is_nwk_public);
01689     _lora_phy.put_radio_to_sleep();
01690 
01691     _lora_time.init(_params.timers.backoff_timer,
01692                     mbed::callback(this, &LoRaMac::on_backoff_timer_expiry));
01693     _lora_time.init(_params.timers.rx_window1_timer,
01694                     mbed::callback(this, &LoRaMac::open_rx1_window));
01695     _lora_time.init(_params.timers.rx_window2_timer,
01696                     mbed::callback(this, &LoRaMac::open_rx2_window));
01697     _lora_time.init(_params.timers.ack_timeout_timer,
01698                     mbed::callback(this, &LoRaMac::on_ack_timeout_timer_event));
01699 
01700     _params.timers.mac_init_time = _lora_time.get_current_time();
01701 
01702     _params.sys_params.adr_on = MBED_CONF_LORA_ADR_ON;
01703 
01704     _params.is_nwk_public = MBED_CONF_LORA_PUBLIC_NETWORK;
01705     _lora_phy.setup_public_network_mode(MBED_CONF_LORA_PUBLIC_NETWORK);
01706 
01707     return LORAWAN_STATUS_OK;
01708 }
01709 
01710 void LoRaMac::disconnect()
01711 {
01712     _lora_time.stop(_params.timers.backoff_timer);
01713     _lora_time.stop(_params.timers.rx_window1_timer);
01714     _lora_time.stop(_params.timers.rx_window2_timer);
01715     _lora_time.stop(_params.timers.ack_timeout_timer);
01716 
01717     _lora_phy.put_radio_to_sleep();
01718 
01719     _is_nwk_joined = false;
01720     _params.is_ack_retry_timeout_expired = false;
01721     _params.is_rx_window_enabled = true;
01722     _params.is_node_ack_requested = false;
01723     _params.is_srv_ack_requested = false;
01724 
01725     _mac_commands.clear_command_buffer();
01726     _mac_commands.clear_repeat_buffer();
01727     _mac_commands.clear_mac_commands_in_next_tx();
01728 
01729     reset_mcps_confirmation();
01730     reset_mlme_confirmation();
01731     reset_mcps_indication();
01732 }
01733 
01734 uint8_t LoRaMac::get_max_possible_tx_size(uint8_t size)
01735 {
01736     uint8_t max_possible_payload_size = 0;
01737     uint8_t current_payload_size = 0;
01738     uint8_t fopt_len = _mac_commands.get_mac_cmd_length()
01739             + _mac_commands.get_repeat_commands_length();
01740 
01741     if (_params.sys_params.adr_on) {
01742         _lora_phy.get_next_ADR(false, _params.sys_params.channel_data_rate,
01743                                _params.sys_params.channel_tx_power,
01744                                _params.adr_ack_counter);
01745     }
01746 
01747     current_payload_size = _lora_phy.get_max_payload(_params.sys_params.channel_data_rate, _params.is_repeater_supported);
01748 
01749     if (current_payload_size >= fopt_len) {
01750         max_possible_payload_size = current_payload_size - fopt_len;
01751     } else {
01752         max_possible_payload_size = current_payload_size;
01753         fopt_len = 0;
01754         _mac_commands.clear_command_buffer();
01755         _mac_commands.clear_repeat_buffer();
01756     }
01757 
01758     if (validate_payload_length(size, _params.sys_params.channel_data_rate,
01759                                 fopt_len) == false) {
01760         return max_possible_payload_size;
01761     }
01762     return current_payload_size;
01763 }
01764 
01765 bool LoRaMac::nwk_joined()
01766 {
01767     return _is_nwk_joined;
01768 }
01769 
01770 void LoRaMac::set_nwk_joined(bool joined)
01771 {
01772     _is_nwk_joined = joined;
01773 }
01774 
01775 lorawan_status_t LoRaMac::add_channel_plan(const lorawan_channelplan_t& plan)
01776 {
01777     if (tx_ongoing()) {
01778         return LORAWAN_STATUS_BUSY;
01779     }
01780 
01781     return _channel_plan.set_plan(plan);
01782 }
01783 
01784 lorawan_status_t LoRaMac::remove_channel_plan()
01785 {
01786     if (tx_ongoing()) {
01787         return LORAWAN_STATUS_BUSY;
01788     }
01789 
01790     return _channel_plan.remove_plan();
01791 }
01792 
01793 lorawan_status_t LoRaMac::get_channel_plan(lorawan_channelplan_t& plan)
01794 {
01795     return _channel_plan.get_plan(plan, _lora_phy.get_phy_channels());
01796 }
01797 
01798 lorawan_status_t LoRaMac::remove_single_channel(uint8_t id)
01799 {
01800     if (tx_ongoing()) {
01801         return LORAWAN_STATUS_BUSY;
01802     }
01803 
01804     return _channel_plan.remove_single_channel(id);
01805 }
01806 
01807 lorawan_status_t LoRaMac::multicast_channel_link(multicast_params_t  *channel_param)
01808 {
01809     if (channel_param == NULL) {
01810         return LORAWAN_STATUS_PARAMETER_INVALID;
01811     }
01812     if (tx_ongoing()) {
01813         return LORAWAN_STATUS_BUSY;
01814     }
01815 
01816     channel_param->dl_frame_counter  = 0;
01817 
01818     if (_params.multicast_channels == NULL) {
01819         _params.multicast_channels = channel_param;
01820     } else {
01821         multicast_params_t  *cur = _params.multicast_channels;
01822         while (cur->next  != NULL) {
01823             cur = cur->next ;
01824         }
01825         cur->next  = channel_param;
01826     }
01827 
01828     return LORAWAN_STATUS_OK;
01829 }
01830 
01831 lorawan_status_t LoRaMac::multicast_channel_unlink(
01832         multicast_params_t  *channel_param)
01833 {
01834     if (channel_param == NULL) {
01835         return LORAWAN_STATUS_PARAMETER_INVALID;
01836     }
01837 
01838     if (tx_ongoing()) {
01839         return LORAWAN_STATUS_BUSY;
01840     }
01841 
01842     if (_params.multicast_channels != NULL) {
01843         if (_params.multicast_channels == channel_param) {
01844             _params.multicast_channels = channel_param->next ;
01845         } else {
01846             multicast_params_t  *cur = _params.multicast_channels;
01847 
01848             while (cur->next  && cur->next  != channel_param) {
01849                 cur = cur->next ;
01850             }
01851 
01852             if (cur->next ) {
01853                 cur->next  = channel_param->next ;
01854             }
01855         }
01856         channel_param->next  = NULL;
01857     }
01858 
01859     return LORAWAN_STATUS_OK;
01860 }
01861 
01862 void LoRaMac::bind_radio_driver(LoRaRadio& radio)
01863 {
01864     _lora_phy.set_radio_instance(radio);
01865 }
01866 
01867 #if defined(LORAWAN_COMPLIANCE_TEST)
01868 /***************************************************************************
01869  * Compliance testing                                                      *
01870  **************************************************************************/
01871 
01872 
01873 lorawan_status_t LoRaMac::mlme_request( loramac_mlme_req_t *mlmeRequest )
01874 {
01875     if (LORAMAC_IDLE != _params.mac_state) {
01876         return LORAWAN_STATUS_BUSY;
01877     }
01878 
01879     reset_mlme_confirmation();
01880 
01881     _mlme_confirmation.req_type = mlmeRequest->type;
01882     _params.flags.bits.mlme_req = 1;
01883 
01884     lorawan_status_t status = LORAWAN_STATUS_SERVICE_UNKNOWN;
01885 
01886     if (MLME_TXCW  == mlmeRequest->type) {
01887         set_tx_continuous_wave(_params.channel, _params.sys_params.channel_data_rate, _params.sys_params.channel_tx_power,
01888                                     _params.sys_params.max_eirp, _params.sys_params.antenna_gain, mlmeRequest->cw_tx_mode.timeout);
01889         _lora_time.start(_params.timers.mac_state_check_timer,
01890                          MAC_STATE_CHECK_TIMEOUT);
01891 
01892         _params.mac_state |= LORAMAC_TX_RUNNING;
01893         status = LORAWAN_STATUS_OK;
01894     } else if (MLME_TXCW_1  == mlmeRequest->type) {
01895         set_tx_continuous_wave(0, 0, mlmeRequest->cw_tx_mode.power, 0, 0, mlmeRequest->cw_tx_mode.timeout);
01896         _lora_time.start(_params.timers.mac_state_check_timer,
01897                          MAC_STATE_CHECK_TIMEOUT);
01898 
01899         _params.mac_state |= LORAMAC_TX_RUNNING;
01900         status = LORAWAN_STATUS_OK;
01901     }
01902 
01903     if (status != LORAWAN_STATUS_OK) {
01904         _params.is_node_ack_requested = false;
01905         _params.flags.bits.mlme_req = 0;
01906     }
01907 
01908 
01909     return status;
01910 }
01911 
01912 lorawan_status_t LoRaMac::test_request( loramac_compliance_test_req_t *mcpsRequest )
01913 {
01914     if (_params.mac_state != LORAMAC_IDLE) {
01915         return LORAWAN_STATUS_BUSY;
01916     }
01917 
01918     loramac_mhdr_t  machdr;
01919     int8_t datarate = mcpsRequest->data_rate;
01920     // TODO: The comment is different than the code???
01921     // Apply the minimum possible datarate.
01922     // Some regions have limitations for the minimum datarate.
01923     datarate = MAX(datarate, (int8_t)_lora_phy.get_minimum_tx_datarate());
01924 
01925     machdr.value  = 0;
01926 
01927     reset_mcps_confirmation();
01928 
01929     _params.ack_timeout_retry_counter = 1;
01930     _params.max_ack_timeout_retries = 1;
01931 
01932     switch (mcpsRequest->type) {
01933         case MCPS_UNCONFIRMED : {
01934             machdr.bits.mtype  = FRAME_TYPE_DATA_UNCONFIRMED_UP ;
01935             break;
01936         }
01937         case MCPS_CONFIRMED : {
01938             machdr.bits.mtype  = FRAME_TYPE_DATA_CONFIRMED_UP ;
01939             _params.max_ack_timeout_retries = mcpsRequest->nb_trials;
01940             break;
01941         }
01942         case MCPS_PROPRIETARY : {
01943             machdr.bits.mtype  = FRAME_TYPE_PROPRIETARY ;
01944             break;
01945         }
01946         default:
01947             return LORAWAN_STATUS_PARAMETER_INVALID;
01948     }
01949 
01950 //    Filter fPorts
01951 //    TODO: Does not work with PROPRIETARY messages
01952 //    if( IsFPortAllowed( mcpsRequest->fport ) == false ) {
01953 //        return LORAWAN_STATUS_PARAMETER_INVALID;
01954 //    }
01955 
01956     if (_params.sys_params.adr_on == false) {
01957         if (_lora_phy.verify_tx_datarate(datarate, false) == true) {
01958             _params.sys_params.channel_data_rate = datarate;
01959         } else {
01960             return LORAWAN_STATUS_PARAMETER_INVALID;
01961         }
01962     }
01963 
01964     lorawan_status_t status = send(&machdr, mcpsRequest->fport, mcpsRequest->f_buffer,
01965                                    mcpsRequest->f_buffer_size);
01966     if (status == LORAWAN_STATUS_OK) {
01967         _mcps_confirmation.req_type = mcpsRequest->type;
01968         _params.flags.bits.mcps_req = 1;
01969     } else {
01970         _params.is_node_ack_requested = false;
01971     }
01972 
01973     return status;
01974 }
01975 
01976 lorawan_status_t LoRaMac::LoRaMacSetTxTimer( uint32_t TxDutyCycleTime )
01977 {
01978     _lora_time.start(tx_next_packet_timer, TxDutyCycleTime);
01979     return LORAWAN_STATUS_OK;
01980 }
01981 
01982  lorawan_status_t LoRaMac::LoRaMacStopTxTimer( )
01983 {
01984     _lora_time.stop(tx_next_packet_timer);
01985     return LORAWAN_STATUS_OK;
01986 }
01987 
01988 void LoRaMac::LoRaMacTestRxWindowsOn( bool enable )
01989 {
01990     _params.is_rx_window_enabled = enable;
01991 }
01992 
01993 void LoRaMac::LoRaMacTestSetMic( uint16_t txPacketCounter )
01994 {
01995     _params.ul_frame_counter = txPacketCounter;
01996     _params.is_ul_frame_counter_fixed = true;
01997 }
01998 
01999 void LoRaMac::LoRaMacTestSetDutyCycleOn( bool enable )
02000 {
02001     if(_lora_phy.verify_duty_cycle(enable) == true)
02002     {
02003         _params.is_dutycycle_on = enable;
02004     }
02005 }
02006 
02007 void LoRaMac::LoRaMacTestSetChannel( uint8_t channel )
02008 {
02009     _params.channel = channel;
02010 }
02011 #endif