fota lib for mdot

Dependents:   UQ_LoraWAN

mdot/Lora/Link.h

Committer:
Jenkins@KEILDM1.dc.multitech.prv
Date:
2018-09-14
Revision:
3:63d10f2375ea

File content as of revision 3:63d10f2375ea:

/**   __  ___     ____  _    ______        __     ____         __                  ____
 *   /  |/  /_ __/ / /_(_)__/_  __/__ ____/ /    / __/_ _____ / /____ __ _  ___   /  _/__  ____
 *  / /|_/ / // / / __/ /___// / / -_) __/ _ \  _\ \/ // (_-</ __/ -_)  ' \(_-<  _/ // _ \/ __/  __
 * /_/  /_/\_,_/_/\__/_/    /_/  \__/\__/_//_/ /___/\_, /___/\__/\__/_/_/_/___/ /___/_//_/\__/  /_/
 * 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