fota lib for mdot
Diff: mdot/Lora/Link.h
- Revision:
- 3:63d10f2375ea
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mdot/Lora/Link.h Fri Sep 14 15:39:09 2018 -0500 @@ -0,0 +1,356 @@ +/** __ ___ ____ _ ______ __ ____ __ ____ + * / |/ /_ __/ / /_(_)__/_ __/__ ____/ / / __/_ _____ / /____ __ _ ___ / _/__ ____ + * / /|_/ / // / / __/ /___// / / -_) __/ _ \ _\ \/ // (_-</ __/ -_) ' \(_-< _/ // _ \/ __/ __ + * /_/ /_/\_,_/_/\__/_/ /_/ \__/\__/_//_/ /___/\_, /___/\__/\__/_/_/_/___/ /___/_//_/\__/ /_/ + * Copyright (C) 2015 by Multi-Tech Systems /___/ + * + * + * @author Jason Reiss + * @date 10-31-2015 + * @brief lora::Link implements uses a channel plan to send and receive through an SX radio driver + * + * @details + * @copyright Copyright (C) 2015 by Multi-Tech Systems. All rights reserved. This project is released under the GNU Lesser General Public License <http://www.gnu.org/licenses/>. + * + */ + +#ifndef __LORA_LINK_H__ +#define __LORA_LINK_H__ + +#include "Lora.h" +#include "SxRadio.h" +#include "ChannelPlan.h" + +namespace lora { + + class Link: public SxRadioEvents { + + public: + /** + * Create a link object + * @param events SxRadioEvents object to pass events to + * @param radio SxRadio object for send and receive operations + * @param plan ChannelPlan to define Frequencies and Datarates used in send and receive + */ + Link(SxRadioEvents& events, SxRadio& radio, ChannelPlan* plan); + + /** + * Link destructor + */ + virtual ~Link(); + + /** + * Get current state of link + * @returns current state + */ + LinkState State(); + + // Event functions called by SxRadio class + + /** Event called by SxRadio on end of tx + */ + virtual void TxDone(void); + + /** Event called by SxRadio on tx timeout + */ + virtual void TxTimeout(void); + + /** Event called by SxRadio on end of rx + */ + virtual void RxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr); + + /** Event called by SxRadio on rx timeout + */ + virtual void RxTimeout(void); + + /** Event called by SxRadio on rx error + */ + virtual void RxError(void); + + /** Event called by Mac when bad packet recv + */ + virtual void RxNotValid(void); + + /** Event called by SxRadio on frequency hop request + */ + virtual void FhssChangeChannel(uint8_t currentChannel); + + // Link interface functions + + /** + * Send the data in buffer with provided number of attempts or repeats + * Radio is set according to current ChannelPlan + * @param buffer data to send on radio + * @param size number of bytes in buffer to send + * @param attempts number of attempts receive an ack of CONFIRMED_FRAME + * @param repeats number of times to repeat the packet, only used if attempts == 0 + * @return LORA_OK if successful + * @return LORA_NO_CHANS_ENABLED if there is not an available channel that supports the current datarate + * @return LORA_LINK_BUSY or LORA_RADIO_BUSY if not successful + */ + virtual uint8_t Send(const uint8_t* buffer, uint16_t size, uint8_t attempts = 0, uint8_t repeats = 0); + + /** + * Open receive window with provided timeout + * Radio is set according to current ChannelPlan + * @param window + * @param timeout + * @return LORA_OK if window is opened + * @return LORA_RADIO_BUSY if window cannot be opened + */ + virtual uint8_t Recv(uint8_t window, uint32_t timeout, uint32_t freq = 0, bool force_continuous=false); + + /** + * Set the delay between end of tx and start of first rx window + * Second rx window will be opened 1 second after first + * @param delay number of milliseconds + */ + virtual void SetRxDelayMs(uint32_t delay); + + /** + * Get the delay between end of tx and start of first rx window + * Second rx window will be opened 1 second after first + * @return number of milliseconds + */ + virtual uint32_t GetRxDelayMs(); + + /** + * Receive setting from Rx Timing Setup mac command + * @param payload buffer containing mac command + * @param index of mac command id in buffer + * @param size of mac command id and params + */ + virtual uint8_t HandleRxTimingSetup(const uint8_t* payload, uint8_t index, uint8_t size); + + /** + * Set the time the MCU is sleeping between tx done and rx1 window open + * This is needed to compensate timers which don't run during a stop sleep mode + * @param time in milliseconds of the sleep + */ + virtual void SetRx1SleepTime(uint32_t time); + + /** + * Get the time the MCU is sleeping between tx done and rx1 window open + * @return time in milliseconds of the sleep + */ + uint32_t GetRx1SleepTime(); + + /** + * Set the time the MCU is sleeping between rx1 window open and rx2 window open + * This is needed to compensate timers which don't run during a stop sleep mode + * @param time in milliseconds of the sleep + */ + virtual void SetRx2SleepTime(uint32_t time); + + /** + * Get the time the MCU is sleeping between rx1 window open and rx2 window open + * @return time in milliseconds of the sleep + */ + uint32_t GetRx2SleepTime(); + + // Timer callback functions and events + + /** + * Timer handler for first receive window + */ + static void OnRx1WindowTimer(void const *arg); + + /** + * Event handler to open first receive window + */ + virtual void OnRx1WindowEvent(); + + /** + * Timer handler for second receive window + */ + static void OnRx2WindowTimer(void const *arg); + + /** + * Event handler to open second receive window + */ + void OnRx2WindowEvent(); + + /** + * Timer handlers for receive window + */ + static void OnRxWindowTimer(void const *arg); + + /** + * Event handler to close receive window on timeout + */ + virtual void OnRxWindowEvent(); + + /** + * Callback for mac layer to notify link when ack has been received + */ + virtual void ReceivedAck(); + + /** + * Flag indicating if ack was received with last rx packet + * @return true if ack was received + */ + bool AckReceived(); + + /** + * Open a receive window with provided timeout + * @param timeout number of milliseconds before window will timeout, 0 == continuous + * @return LORA_OK if window is opened + * @return LORA_RADIO_BUSY if window cannot be opened + */ + virtual uint8_t OpenRxWindow(uint16_t timeout = 0, bool force_continuous=false); + + /** + * Open a receive window with provided timeout, frequency and datarate + * @param timeout number of milliseconds before window will timeout, 0 == continuous + * @param frequecy to listen for + * @param datarate to listen for + * @return LORA_OK if window is opened + * @return LORA_RADIO_BUSY if window cannot be opened + */ + virtual uint8_t OpenRxWindow(uint32_t timeout, uint32_t freq, uint8_t datarate); + + /** + * Close the receive window + */ + void CloseRxWindow(); + + /** + * Stop Rx2 Window Timer + */ + void StopRx2WindowTimer(); + + /** + * Cancel pending rx windows + */ + void CancelRxWindows(); + + /** + * Get link stats for number of up/down packets and missed acks + * @return Statistics struct + */ + Statistics& GetStats(); + + /** + * Set the current channel plan + */ + void SetChannelPlan(ChannelPlan* plan); + + /** Set the LoRaWAN class operation + * @param cls A, B or C + */ + void SetLoraClass(lora::MoteClass cls); + + /** + * Reset the internal state of the Link + */ + void ResetState(); + + /** + * Ack retries attempted during last transmission request + * @return number of ack retries attempted + */ + uint8_t TxRetries(); + + /** + * Reset link statistics + */ + void ResetStats(); + + /** + * Get the rx window we received the last packet in + * @return rx window the last packet was received in + */ + uint8_t GetLastRxWindowUsed(); + + private: + + /** + * Send data in tx buffer with current settings + * Used for resending data on missed ack or repeating packets + */ + uint8_t Send(); + + /** + * Injected SxRadioEvent object + */ + + SxRadioEvents& _events; + + /** + * Injected SxRadio object + */ + SxRadio& _radio; + + /** + * Injected ChannelPlan object used to send and receive packets + */ + ChannelPlan* _plan; + + LinkState _state; //!< Current state of Link + + // Timers + + RtosTimer _rx1WindowTimer; //!< Timer to open first rx window + RtosTimer _rx2WindowTimer; //!< Timer to open second rx window + RtosTimer _rxWindowTimer; //!< Timer to close rx window + RtosTimer _ackTimer; //!< Timer to send next attempt for confirmed frame + RtosTimer _repeatTimer; //!< Timer to send next attempt for confirmed frame + Timer _fakeRx2Timer; //!< Timer to fake rx2 window for class C + bool _ackTimerPending; //!< Flag for resend + bool _repeatTimerPending; //!< Flag for resend + + // Member variables + uint8_t _txBuffer[MAX_PHY_PACKET_SIZE]; //!< Buffer for tx packets + uint8_t _txBufferSize; //!< Size of buffer for tx packets + + uint32_t _rxDelayMs; //!< Current delay between end of tx and opening of first rx window + uint32_t _rx1SleepTime; //!< MCU sleep time before rx1 opens (in ms) + uint32_t _rx2SleepTime; //!< MCU sleep time before rx2 opens relative to rx1 open (in ms) + + uint8_t _ackAttemptsMax; //!< Number of attempts to transmit a confirmed packet + uint8_t _ackAttempts; //!< Attempt number of current packet + uint8_t _repeatsMax; //!< Number of times to repeat a packet + uint8_t _repeats; //!< Repeat number of current packet + bool _ackReceived; + + Statistics _stats; //!< Statistics for Up/Down packets and missed ACK's + + MoteClass _loraClass; + + uint8_t _lastRxWndOpened; //!< Last rx window opened + uint8_t _lastRxWnd; //!< Rx window last packet was received in + + /** + * Callback for radio thread to signal + */ + virtual void MacEvent(); + + /** + * Timer handler for ACK timeout + */ + static void OnAckTimeout(void const *arg); + + /** + * Event handler for ACK timeout + */ + void OnAckTimeoutEvent(); + + /** + * Timer handler for ACK timeout + */ + static void OnRepeatTimeout(void const *arg); + + /** + * Event handler for ACK timeout + */ + void OnRepeatTimeoutEvent(); + + /** + * Update link state + */ + void UpdateState(); + }; + +} + +#endif