Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
LoRaMac.h
00001 /** 00002 * \file LoRaMac.h 00003 * 00004 * \brief LoRa MAC layer implementation 00005 * 00006 * \copyright Revised BSD License, see LICENSE.TXT file include in the project 00007 * 00008 * \code 00009 * ______ _ 00010 * / _____) _ | | 00011 * ( (____ _____ ____ _| |_ _____ ____| |__ 00012 * \____ \| ___ | (_ _) ___ |/ ___) _ \ 00013 * _____) ) ____| | | || |_| ____( (___| | | | 00014 * (______/|_____)_|_|_| \__)_____)\____)_| |_| 00015 * (C)2013 Semtech 00016 * 00017 * ___ _____ _ ___ _ _____ ___ ___ ___ ___ 00018 * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __| 00019 * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _| 00020 * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___| 00021 * embedded.connectivity.solutions=============== 00022 * 00023 * \endcode 00024 * 00025 * \author Miguel Luis ( Semtech ) 00026 * 00027 * \author Gregory Cristian ( Semtech ) 00028 * 00029 * \author Daniel Jaeckle ( STACKFORCE ) 00030 * 00031 * \defgroup LORAMAC LoRa MAC layer implementation 00032 * This module specifies the API implementation of the LoRaMAC layer. 00033 * This is a placeholder for a detailed description of the LoRaMac 00034 * layer and the supported features. 00035 * 00036 * Copyright (c) 2017, Arm Limited and affiliates. 00037 * SPDX-License-Identifier: BSD-3-Clause 00038 * 00039 */ 00040 #ifndef MBED_LORAWAN_MAC_H__ 00041 #define MBED_LORAWAN_MAC_H__ 00042 00043 #include "events/EventQueue.h" 00044 00045 #include "lorastack/phy/LoRaPHY.h" 00046 00047 #include "system/LoRaWANTimer.h" 00048 #include "system/lorawan_data_structures.h" 00049 00050 #include "LoRaMacChannelPlan.h" 00051 #include "LoRaMacCommand.h" 00052 #include "LoRaMacCrypto.h" 00053 #if MBED_CONF_RTOS_PRESENT 00054 #include "rtos/Mutex.h" 00055 #endif 00056 00057 #include "platform/ScopedLock.h" 00058 00059 class LoRaMac { 00060 00061 public: 00062 00063 /** 00064 * Constructor 00065 */ 00066 LoRaMac(); 00067 00068 /** 00069 * Destructor 00070 */ 00071 ~LoRaMac(); 00072 00073 /** 00074 * @brief LoRaMAC layer initialization 00075 * 00076 * @details Initializes the LoRaMAC layer, 00077 * 00078 * 00079 * @param queue [in] A pointer to the application provided EventQueue. 00080 * 00081 * @param scheduling_failure_handler A callback to inform upper layer if a deferred 00082 * transmission (after backoff or retry) fails to schedule. 00083 * 00084 * @return `lorawan_status_t` The status of the operation. The possible values are: 00085 * \ref LORAWAN_STATUS_OK 00086 * \ref LORAWAN_STATUS_PARAMETER_INVALID 00087 */ 00088 lorawan_status_t initialize(events::EventQueue *queue, 00089 mbed::Callback<void(void)>scheduling_failure_handler); 00090 00091 /** 00092 * @brief Disconnect LoRaMac layer 00093 * 00094 * @details Cancels all outstanding requests and sets LoRaMac's 00095 * internal state to idle. 00096 */ 00097 void disconnect(void); 00098 00099 /** 00100 * @brief nwk_joined Checks if device has joined to network 00101 * @return True if joined to network, false otherwise 00102 */ 00103 bool nwk_joined(); 00104 00105 /** 00106 * @brief Adds a channel plan to the system. 00107 * 00108 * @details Adds a whole channel plan or a single new channel if the plan 00109 * contains only one channel and 'plan.nb_channels' is set to 1. 00110 * Please note that this functionality is not available in all regions. 00111 * Information on the allowed ranges is available at the 00112 * LoRaWAN Regional Parameters V1.0.2rB. 00113 * 00114 * @param plan [in] A reference to application provided channel plan. 00115 * 00116 * @return `lorawan_status_t` The status of the operation. The possible values are: 00117 * \ref LORAWAN_STATUS_OK 00118 * \ref LORAWAN_STATUS_BUSY 00119 * \ref LORAWAN_STATUS_PARAMETER_INVALID 00120 */ 00121 lorawan_status_t add_channel_plan(const lorawan_channelplan_t &plan); 00122 00123 /** 00124 * @brief Removes a channel plan from the system. 00125 * 00126 * @details Removes the whole active channel plan except the 'Default Channels'. 00127 * Please note that this functionality is not available in all regions. 00128 * Information on the allowed ranges is available at the 00129 * LoRaWAN Regional Parameters V1.0.2rB. 00130 * 00131 * @return `lorawan_status_t` The status of the operation. The possible values are: 00132 * \ref LORAWAN_STATUS_OK 00133 * \ref LORAWAN_STATUS_BUSY 00134 * \ref LORAWAN_STATUS_PARAMETER_INVALID 00135 */ 00136 lorawan_status_t remove_channel_plan(); 00137 00138 /** 00139 * @brief Access active channel plan. 00140 * 00141 * @details Provides access to the current active channel plan. 00142 * 00143 * @param plan [out] A reference to application provided channel plan data 00144 * structure which will be filled in with active channel 00145 * plan. 00146 * 00147 * @return `lorawan_status_t` The status of the operation. The possible values are: 00148 * \ref LORAWAN_STATUS_OK 00149 * \ref LORAWAN_STATUS_BUSY 00150 * \ref LORAWAN_STATUS_PARAMETER_INVALID 00151 */ 00152 lorawan_status_t get_channel_plan(lorawan_channelplan_t &plan); 00153 00154 /** 00155 * @brief Remove a given channel from the active plan. 00156 * 00157 * @details Deactivates the given channel. 00158 * 00159 * @param id Id of the channel. 00160 * 00161 * @return `lorawan_status_t` The status of the operation. The possible values are: 00162 * \ref LORAWAN_STATUS_OK 00163 * \ref LORAWAN_STATUS_BUSY 00164 * \ref LORAWAN_STATUS_PARAMETER_INVALID 00165 */ 00166 lorawan_status_t remove_single_channel(uint8_t id); 00167 00168 /** 00169 * @brief LoRaMAC multicast channel link service. 00170 * 00171 * @details Links a multicast channel into the linked list. 00172 * 00173 * @param [in] channel_param The multicast channel parameters to link. 00174 * 00175 * @return `lorawan_status_t` The status of the operation. The possible values are: 00176 * \ref LORAWAN_STATUS_OK 00177 * \ref LORAWAN_STATUS_BUSY 00178 * \ref LORAWAN_STATUS_PARAMETER_INVALID 00179 */ 00180 lorawan_status_t multicast_channel_link(multicast_params_t *channel_param); 00181 00182 /** 00183 * @brief LoRaMAC multicast channel unlink service. 00184 * 00185 * @details Unlinks a multicast channel from the linked list. 00186 * 00187 * @param [in] channel_param The multicast channel parameters to unlink. 00188 * 00189 * @return `lorawan_status_t` The status of the operation. The possible values are: 00190 * \ref LORAWAN_STATUS_OK 00191 * \ref LORAWAN_STATUS_BUSY 00192 * \ref LORAWAN_STATUS_PARAMETER_INVALID 00193 */ 00194 lorawan_status_t multicast_channel_unlink(multicast_params_t *channel_param); 00195 00196 /** Binds phy layer to MAC. 00197 * 00198 * @param phy LoRaPHY object 00199 */ 00200 void bind_phy(LoRaPHY &phy); 00201 00202 /** 00203 * @brief Schedules the frame for sending. 00204 * 00205 * @details Prepares a full MAC frame and schedules it for physical 00206 * transmission. 00207 * 00208 * @param [in] mac_hdr MAC frame header field 00209 * @param [in] fport Payload port 00210 * @param [in] fbuffer MAC frame data buffer to be sent 00211 * @param [in] fbuffer_size MAC frame data buffer size 00212 * 00213 * @return status Status of the operation. LORAWAN_STATUS_OK in case 00214 * of success and a negative error code in case of 00215 * failure. 00216 */ 00217 lorawan_status_t send(loramac_mhdr_t *mac_hdr, const uint8_t fport, 00218 const void *fbuffer, uint16_t fbuffer_size); 00219 00220 /** 00221 * @brief get_default_tx_datarate Gets the default TX datarate 00222 * @return default TX datarate. 00223 */ 00224 uint8_t get_default_tx_datarate(); 00225 00226 /** 00227 * @brief enable_adaptive_datarate Enables or disables adaptive datarate. 00228 * @param adr_enabled Flag indicating is adr enabled or disabled. 00229 */ 00230 void enable_adaptive_datarate(bool adr_enabled); 00231 00232 /** Sets up the data rate. 00233 * 00234 * `set_datarate()` first verifies whether the data rate given is valid or not. 00235 * If it is valid, the system sets the given data rate to the channel. 00236 * 00237 * @param data_rate The intended data rate, for example DR_0 or DR_1. 00238 * Note that the macro DR_* can mean different 00239 * things in different regions. 00240 * 00241 * @return LORAWAN_STATUS_OK if everything goes well, otherwise 00242 * a negative error code. 00243 */ 00244 lorawan_status_t set_channel_data_rate(uint8_t data_rate); 00245 00246 /** 00247 * @brief tx_ongoing Check whether a prepare is done or not. 00248 * @return True if prepare_ongoing_tx is called, false otherwise. 00249 */ 00250 bool tx_ongoing(); 00251 00252 /** 00253 * @brief set_tx_ongoing Changes the ongoing status for prepared message. 00254 * @param ongoing The value indicating the status. 00255 */ 00256 void set_tx_ongoing(bool ongoing); 00257 00258 /** 00259 * @brief reset_ongoing_tx Resets _ongoing_tx_msg. 00260 * @param reset_pending If true resets pending size also. 00261 */ 00262 void reset_ongoing_tx(bool reset_pending = false); 00263 00264 /** 00265 * @brief prepare_ongoing_tx This will prepare (and override) ongoing_tx_msg. 00266 * @param port The application port number. 00267 * 00268 * @param data A pointer to the data being sent. The ownership of the 00269 * buffer is not transferred. 00270 * 00271 * @param length The size of data in bytes. 00272 * 00273 * @param flags A flag used to determine what type of 00274 * message is being sent. 00275 * 00276 * @param num_retries Number of retries for a confirmed type message 00277 * 00278 * @return The number of bytes prepared for sending. 00279 */ 00280 int16_t prepare_ongoing_tx(const uint8_t port, const uint8_t *data, 00281 uint16_t length, uint8_t flags, uint8_t num_retries); 00282 00283 /** 00284 * @brief send_ongoing_tx Sends the ongoing_tx_msg 00285 * @return LORAWAN_STATUS_OK or a negative error code on failure. 00286 */ 00287 lorawan_status_t send_ongoing_tx(void); 00288 00289 /** 00290 * @brief device_class Returns active device class 00291 * @return Device class in use. 00292 */ 00293 device_class_t get_device_class() const; 00294 00295 /** 00296 * @brief set_device_class Sets active device class. 00297 * @param device_class Device class to use. 00298 * @param ack_expiry_handler callback function to inform about ack expiry 00299 */ 00300 void set_device_class(const device_class_t &device_class, 00301 mbed::Callback<void(void)>ack_expiry_handler); 00302 00303 /** 00304 * @brief setup_link_check_request Adds link check request command 00305 * to be put on next outgoing message (when it fits) 00306 */ 00307 void setup_link_check_request(); 00308 00309 /** 00310 * @brief prepare_join prepares arguments to be ready for join() call. 00311 * @param params Join parameters to use, if NULL, the default will be used. 00312 * @param is_otaa True if joining is to be done using OTAA, false for ABP. 00313 * 00314 * @return LORAWAN_STATUS_OK or a negative error code on failure. 00315 */ 00316 lorawan_status_t prepare_join(const lorawan_connect_t *params, bool is_otaa); 00317 00318 /** 00319 * @brief join Joins the network. 00320 * @param is_otaa True if joining is to be done using OTAA, false for ABP. 00321 * @return LORAWAN_STATUS_OK or a negative error code on failure. 00322 */ 00323 lorawan_status_t join(bool is_otaa); 00324 00325 /** 00326 * MAC operations upon successful transmission 00327 */ 00328 void on_radio_tx_done(lorawan_time_t timestamp); 00329 00330 /** 00331 * MAC operations upon reception 00332 */ 00333 void on_radio_rx_done(const uint8_t *const payload, uint16_t size, 00334 int16_t rssi, int8_t snr); 00335 00336 /** 00337 * MAC operations upon transmission timeout 00338 */ 00339 void on_radio_tx_timeout(void); 00340 00341 /** 00342 * MAC operations upon empty reception slots 00343 * 00344 * @param is_timeout false when radio encountered an error 00345 * true when the an RX slot went empty 00346 * 00347 * @return current RX slot 00348 */ 00349 void on_radio_rx_timeout(bool is_timeout); 00350 00351 /** 00352 * Handles retransmissions of Join requests if an Accept 00353 * was not received. 00354 * 00355 * @returns true if a retry will be made 00356 */ 00357 bool continue_joining_process(void); 00358 00359 /** 00360 * Checks if the CONFIRMED data can be sent again or not. 00361 */ 00362 bool continue_sending_process(void); 00363 00364 /** 00365 * Read-only access to MAC primitive blocks 00366 */ 00367 const loramac_mcps_confirm_t *get_mcps_confirmation() const; 00368 const loramac_mcps_indication_t *get_mcps_indication() const; 00369 const loramac_mlme_confirm_t *get_mlme_confirmation() const; 00370 const loramac_mlme_indication_t *get_mlme_indication() const; 00371 00372 /** 00373 * Post processing steps in response to actions carried out 00374 * by controller layer and Mac 00375 */ 00376 void post_process_mcps_req(void); 00377 void post_process_mcps_ind(void); 00378 void post_process_mlme_request(void); 00379 void post_process_mlme_ind(void); 00380 00381 /** 00382 * Set battery level query callback 00383 */ 00384 void set_batterylevel_callback(mbed::Callback<uint8_t(void)> battery_level); 00385 00386 /** 00387 * Returns the event ID of backoff timer. 00388 */ 00389 int get_backoff_timer_event_id(void); 00390 00391 /** 00392 * Clears out the TX pipe by discarding any outgoing message if the backoff 00393 * timer is still running. 00394 */ 00395 lorawan_status_t clear_tx_pipe(void); 00396 00397 /** 00398 * Gets the current time 00399 */ 00400 lorawan_time_t get_current_time(void); 00401 00402 /** 00403 * Gets the current receive slot 00404 */ 00405 rx_slot_t get_current_slot(void); 00406 00407 /** 00408 * These locks trample through to the upper layers and make 00409 * the stack thread safe. 00410 */ 00411 #if MBED_CONF_RTOS_PRESENT 00412 void lock(void) 00413 { 00414 _mutex.lock(); 00415 } 00416 void unlock(void) 00417 { 00418 _mutex.unlock(); 00419 } 00420 #else 00421 void lock(void) { } 00422 void unlock(void) { } 00423 #endif 00424 00425 private: 00426 /** 00427 * @brief Queries the LoRaMAC the maximum possible FRMPayload size to send. 00428 * The LoRaMAC takes the scheduled MAC commands into account and returns 00429 * corresponding value. 00430 * 00431 * @param fopts_len [in] Number of mac commands in the queue pending. 00432 * 00433 * @return Size of the biggest packet that can be sent. 00434 * Please note that if the size of the MAC commands in the queue do 00435 * not fit into the payload size on the related datarate, the LoRaMAC will 00436 * omit the MAC commands. 00437 */ 00438 uint8_t get_max_possible_tx_size(uint8_t fopts_len); 00439 00440 /** 00441 * @brief set_nwk_joined This is used for ABP mode for which real joining does not happen 00442 * @param joined True if device has joined in network, false otherwise 00443 */ 00444 void set_nwk_joined(bool joined); 00445 00446 /** 00447 * @brief Configures the events to trigger an MLME-Indication with 00448 * a MLME type of MLME_SCHEDULE_UPLINK. 00449 */ 00450 void set_mlme_schedule_ul_indication(void); 00451 00452 /** 00453 * @brief Resets MAC specific parameters to default 00454 */ 00455 void reset_mac_parameters(void); 00456 00457 /** 00458 * Handles a Join Accept frame 00459 */ 00460 void handle_join_accept_frame(const uint8_t *payload, uint16_t size); 00461 00462 /** 00463 * Handles data frames 00464 */ 00465 void handle_data_frame(const uint8_t *payload, uint16_t size, uint8_t ptr_pos, 00466 uint8_t msg_type, int16_t rssi, int8_t snr); 00467 00468 /** 00469 * Send a Join Request 00470 */ 00471 lorawan_status_t send_join_request(); 00472 00473 /** 00474 * Handles retransmissions 00475 */ 00476 lorawan_status_t handle_retransmission(); 00477 00478 /** 00479 * Checks if the frame is valid 00480 */ 00481 void check_frame_size(uint16_t size); 00482 00483 /** 00484 * Performs MIC 00485 */ 00486 bool message_integrity_check(const uint8_t *payload, uint16_t size, 00487 uint8_t *ptr_pos, uint32_t address, 00488 uint32_t *downlink_counter, const uint8_t *nwk_skey); 00489 00490 /** 00491 * Decrypts and extracts data and MAC commands from the received encrypted 00492 * payload 00493 */ 00494 void extract_data_and_mac_commands(const uint8_t *payload, uint16_t size, 00495 uint8_t fopts_len, uint8_t *nwk_skey, 00496 uint8_t *app_skey, uint32_t address, 00497 uint32_t downlink_frame_counter, 00498 int16_t rssi, int8_t snr); 00499 /** 00500 * Decrypts and extracts MAC commands from the received encrypted 00501 * payload if there is no data 00502 */ 00503 void extract_mac_commands_only(const uint8_t *payload, int8_t snr, uint8_t fopts_len); 00504 00505 /** 00506 * Callback function to be executed when the DC backoff timer expires 00507 */ 00508 void on_backoff_timer_expiry(void); 00509 00510 /** 00511 * At the end of an RX1 window timer, an RX1 window is opened using this method. 00512 */ 00513 void open_rx1_window(void); 00514 00515 /** 00516 * At the end of an RX2 window timer, an RX2 window is opened using this method. 00517 */ 00518 void open_rx2_window(void); 00519 00520 /** 00521 * A method to retry a CONFIRMED message after a particular time period 00522 * (ACK_TIMEOUT = TIME_IN_MS) if the ack was not received 00523 */ 00524 void on_ack_timeout_timer_event(void); 00525 00526 /*! 00527 * \brief Check if the OnAckTimeoutTimer has do be disabled. If so, the 00528 * function disables it. 00529 * 00530 * \param [in] node_ack_requested Set to true, if the node has requested an ACK 00531 * \param [in] dev_class The device class 00532 * \param [in] ack_received Set to true, if the node has received an ACK 00533 * \param [in] ack_timeout_retries_counter Retries counter for confirmed uplinks 00534 * \param [in] ack_timeout_retries Maximum retries for confirmed uplinks 00535 */ 00536 void check_to_disable_ack_timeout(bool node_ack_requested, 00537 device_class_t dev_class, 00538 bool ack_received, 00539 uint8_t ack_timeout_retries_counter, 00540 uint8_t ack_timeout_retries); 00541 00542 /** 00543 * Validates if the payload fits into the frame, taking the datarate 00544 * into account. 00545 * 00546 * Please Refer to chapter 4.3.2 of the LoRaWAN specification, v1.0.2 00547 */ 00548 bool validate_payload_length(uint16_t length, int8_t datarate, uint8_t fopts_len); 00549 00550 /** 00551 * Prepares MAC frame on the behest of send() API. 00552 */ 00553 lorawan_status_t prepare_frame(loramac_mhdr_t *mac_hdr, 00554 loramac_frame_ctrl_t *fctrl, const uint8_t fport, 00555 const void *fbuffer, uint16_t fbuffer_size); 00556 00557 /** 00558 * Schedules a transmission on the behest of send() API. 00559 */ 00560 lorawan_status_t schedule_tx(); 00561 00562 /** 00563 * Calculates the back-off time for the band of a channel. 00564 * Takes in the last used channel id as a parameter. 00565 */ 00566 void calculate_backOff(uint8_t channel_id); 00567 00568 /** 00569 * Hands over the MAC frame to PHY layer. 00570 */ 00571 lorawan_status_t send_frame_on_channel(uint8_t channel); 00572 00573 /** 00574 * Resets MAC primitive blocks 00575 */ 00576 void reset_mcps_confirmation(void); 00577 void reset_mlme_confirmation(void); 00578 void reset_mcps_indication(void); 00579 00580 /** 00581 * @brief set_tx_continuous_wave Puts the system in continuous transmission mode 00582 * @param [in] channel A Channel to use 00583 * @param [in] datarate A datarate to use 00584 * @param [in] tx_power A RF output power to use 00585 * @param [in] max_eirp A maximum possible EIRP to use 00586 * @param [in] antenna_gain Antenna gain to use 00587 * @param [in] timeout Time in seconds while the radio is kept in continuous wave mode 00588 */ 00589 void set_tx_continuous_wave(uint8_t channel, int8_t datarate, int8_t tx_power, 00590 float max_eirp, float antenna_gain, uint16_t timeout); 00591 00592 private: 00593 typedef mbed::ScopedLock<LoRaMac> Lock; 00594 #if MBED_CONF_RTOS_PRESENT 00595 rtos::Mutex _mutex; 00596 #endif 00597 00598 /** 00599 * Timer subsystem handle 00600 */ 00601 LoRaWANTimeHandler _lora_time; 00602 00603 /** 00604 * LoRa PHY layer object storage 00605 */ 00606 LoRaPHY *_lora_phy; 00607 00608 /** 00609 * MAC command handle 00610 */ 00611 LoRaMacCommand _mac_commands; 00612 00613 /** 00614 * Channel planning subsystem 00615 */ 00616 LoRaMacChannelPlan _channel_plan; 00617 00618 /** 00619 * Crypto handling subsystem 00620 */ 00621 LoRaMacCrypto _lora_crypto; 00622 00623 /** 00624 * Central MAC layer data storage 00625 */ 00626 loramac_protocol_params _params; 00627 00628 /** 00629 * EventQueue object storage 00630 */ 00631 events::EventQueue *_ev_queue; 00632 00633 /** 00634 * Class C doesn't timeout in RX2 window as it is a continuous window. 00635 * We use this callback to inform the LoRaWANStack controller that the 00636 * system cannot do more retries. 00637 */ 00638 mbed::Callback<void(void)> _ack_expiry_handler_for_class_c; 00639 00640 /** 00641 * Transmission is async, i.e., a call to schedule_tx() may be deferred to 00642 * a time after a certain back off. We use this callback to inform the 00643 * controller layer that a specific TX transaction failed to schedule after 00644 * backoff or retry. 00645 */ 00646 mbed::Callback<void(void)> _scheduling_failure_handler; 00647 00648 /** 00649 * Structure to hold MCPS indication data. 00650 */ 00651 loramac_mcps_indication_t _mcps_indication; 00652 00653 /** 00654 * Structure to hold MCPS confirm data. 00655 */ 00656 loramac_mcps_confirm_t _mcps_confirmation; 00657 00658 /** 00659 * Structure to hold MLME indication data. 00660 */ 00661 loramac_mlme_indication_t _mlme_indication; 00662 00663 /** 00664 * Structure to hold MLME confirm data. 00665 */ 00666 loramac_mlme_confirm_t _mlme_confirmation; 00667 00668 loramac_tx_message_t _ongoing_tx_msg; 00669 00670 bool _is_nwk_joined; 00671 00672 bool _continuous_rx2_window_open; 00673 00674 device_class_t _device_class; 00675 }; 00676 00677 #endif // MBED_LORAWAN_MAC_H__
Generated on Tue Aug 9 2022 00:37:09 by
1.7.2