fota lib for mdot

Files at this revision

API Documentation at this revision

Comitter:
Jenkins@KEILDM1.dc.multitech.prv
Date:
Fri Sep 14 15:39:09 2018 -0500
Parent:
2:c0473f0113b4
Child:
4:3046dd3928b0
Commit message:
fota lib updates

Changed in this revision

mdot/LoRaConfig.h Show annotated file Show diff for this revision Revisions of this file
mdot/Lora/ChannelPlan.h Show annotated file Show diff for this revision Revisions of this file
mdot/Lora/ChannelPlans/ChannelPlan_AS923.h Show annotated file Show diff for this revision Revisions of this file
mdot/Lora/ChannelPlans/ChannelPlan_AS923_Japan.h Show annotated file Show diff for this revision Revisions of this file
mdot/Lora/ChannelPlans/ChannelPlan_AU915.h Show annotated file Show diff for this revision Revisions of this file
mdot/Lora/ChannelPlans/ChannelPlan_EU868.h Show annotated file Show diff for this revision Revisions of this file
mdot/Lora/ChannelPlans/ChannelPlan_IN865.h Show annotated file Show diff for this revision Revisions of this file
mdot/Lora/ChannelPlans/ChannelPlan_KR920.h Show annotated file Show diff for this revision Revisions of this file
mdot/Lora/ChannelPlans/ChannelPlan_US915.h Show annotated file Show diff for this revision Revisions of this file
mdot/Lora/ChannelPlans/ChannelPlans.h Show annotated file Show diff for this revision Revisions of this file
mdot/Lora/Crypto.h Show annotated file Show diff for this revision Revisions of this file
mdot/Lora/Link.h Show annotated file Show diff for this revision Revisions of this file
mdot/Lora/Lora.h Show annotated file Show diff for this revision Revisions of this file
mdot/Lora/Mac.h Show annotated file Show diff for this revision Revisions of this file
mdot/Lora/MacEvents.h Show annotated file Show diff for this revision Revisions of this file
mdot/Lora/Mote.h Show annotated file Show diff for this revision Revisions of this file
mdot/Lora/Radio/SxRadio.h Show annotated file Show diff for this revision Revisions of this file
mdot/Lora/Radio/SxRadio1272.h Show annotated file Show diff for this revision Revisions of this file
mdot/Lora/Radio/SxRadio1272Regs-Fsk.h Show annotated file Show diff for this revision Revisions of this file
mdot/Lora/Radio/SxRadio1272Regs-LoRa.h Show annotated file Show diff for this revision Revisions of this file
mdot/Lora/Radio/SxRadioEvents.h Show annotated file Show diff for this revision Revisions of this file
mdot/Lora/Utils/MTSCircularBuffer.h Show annotated file Show diff for this revision Revisions of this file
mdot/Lora/Utils/MTSLog.h Show annotated file Show diff for this revision Revisions of this file
mdot/Lora/Utils/MTSText.h Show annotated file Show diff for this revision Revisions of this file
mdot/Lora/Utils/Utils.h Show annotated file Show diff for this revision Revisions of this file
mdot/Lora/Utils/aes.h Show annotated file Show diff for this revision Revisions of this file
mdot/Lora/Utils/cmac.h Show annotated file Show diff for this revision Revisions of this file
mdot/Lora/Utils/library_version.h Show annotated file Show diff for this revision Revisions of this file
mdot/SpiFlash25.h Show annotated file Show diff for this revision Revisions of this file
mdot/WakeUp.h Show annotated file Show diff for this revision Revisions of this file
mdot/fota.ar Show annotated file Show diff for this revision Revisions of this file
mdot/libfota.a Show annotated file Show diff for this revision Revisions of this file
mdot/mDot.h Show annotated file Show diff for this revision Revisions of this file
mdot/mDotEvent.h Show annotated file Show diff for this revision Revisions of this file
mdot/spiffs.h Show annotated file Show diff for this revision Revisions of this file
mdot/spiffs_config.h Show annotated file Show diff for this revision Revisions of this file
mdot/spiffs_nucleus.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/LoRaConfig.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,678 @@
+#include "mbed.h"
+#if defined (TARGET_MTS_MDOT_F411RE)
+#include "spiffs.h"
+#include "SpiFlash25.h"
+#else
+#include "xdot_eeprom.h"
+#endif /* TARGET_MTS_MDOT_F411RE */
+#include "mDot.h"
+#include "ChannelPlan.h"
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+#ifndef __LORA_CONFIG_H__
+#define __LORA_CONFIG_H__
+
+#if defined (TARGET_MTS_MDOT_F411RE)
+// this value represents the number of files you can have open at the same time
+// adjust it according to your requirements
+#define MAX_CONCURRENT_FDS      5
+
+#define PAGE_SIZE               256
+#define SECTOR_SIZE             64*1024
+#define MEM_SIZE                2*1024*1024
+#else
+#define SETTINGS_ADDR       0x0000      // configuration is 1024 bytes (0x000-0x3FF)
+#define PROTECTED_ADDR      0x0400      // protected configuration is 256 bytes (0x400-0x4FF)
+#define SESSION_ADDR        0x0500      // session is 256 bytes (0x500-0x5FF)
+#define USER_ADDR           0x0800      // user space is 6*1024 bytes (0x800 - 0x1FFF)
+#endif /* TARGET_MTS_MDOT_F411RE */
+
+#define MULTICAST_SESSIONS 3
+#define EUI_LENGTH 8
+#define KEY_LENGTH 16
+#define PASSPHRASE_LENGTH 128
+
+// DON'T CHANGE THIS UNLESS YOU REALLY WANT TO
+#define PROTECTED_RFU_SIZE 223
+
+// PROTECTED SETTINGS SHOULD ALWAYS HAVE SIZE OF 256 BYTES
+typedef struct {
+        uint8_t FrequencyBand;
+        uint8_t DeviceEUI[EUI_LENGTH];
+        uint8_t AppEUI[EUI_LENGTH];
+        uint8_t AppKey[KEY_LENGTH];
+        uint8_t RFU[PROTECTED_RFU_SIZE];
+} ProtectedSettings_t;
+
+// DON'T CHANGE THIS UNLESS YOU REALLY WANT TO
+#define CONFIG_RFU_SIZE 361
+
+// SETTINGS SHOULD ALWAYS HAVE SIZE OF 1024 BYTES
+typedef struct {
+        uint8_t ConfigVersion;
+
+        uint32_t SerialBaudRate;
+        uint32_t DebugBaudRate;
+        uint8_t StartUpMode;
+
+        /* Network Settings */
+        uint8_t NetworkEUI[EUI_LENGTH];
+        uint8_t NetworkEUIPassphrase[PASSPHRASE_LENGTH];
+        uint8_t NetworkKey[KEY_LENGTH];
+        uint8_t NetworkKeyPassphrase[PASSPHRASE_LENGTH];
+
+        uint32_t NetworkAddress;
+        uint8_t NetworkSessionKey[KEY_LENGTH];
+        uint8_t DataSessionKey[KEY_LENGTH];
+
+        uint8_t JoinMode;
+        uint8_t JoinRetries;
+
+        /* Radio Settings */
+
+        uint8_t ForwardErrorCorrection;
+        uint8_t ACKAttempts;
+        bool EnableEncryption;
+        bool EnableCRC;
+        bool EnableADR;
+        bool EnableEcho;
+        bool EnableVerbose;
+
+        uint32_t TxFrequency;
+        uint8_t TxDataRate;
+        bool TxInverted;
+        uint8_t TxPower;
+        bool TxWait;
+        uint8_t FrequencySubBand;
+
+        uint32_t RxFrequency;
+        uint8_t RxDataRate;
+        bool RxInverted;
+        uint8_t RxOutput;
+
+        /* Serial Settings */
+        uint32_t WakeInterval;
+        uint16_t WakeTimeout;
+        uint32_t WakeDelay;
+
+        uint8_t PublicNetwork;
+        uint8_t LinkCheckCount;
+        uint8_t LinkCheckThreshold;
+
+        uint8_t LogLevel;
+        uint8_t JoinByteOrder;
+
+        uint8_t WakePin;
+        uint8_t WakeMode;
+
+        uint8_t PreserveSessionOverReset;
+
+        uint8_t JoinDelay;
+        uint8_t RxDelay;
+        uint8_t Port;
+
+        uint8_t Class;
+        int8_t AntennaGain;
+
+        bool FlowControl;
+        uint8_t Repeat;
+
+        bool SerialClearOnError;
+        uint8_t Rx2Datarate;
+        uint8_t JoinRx1DatarateOffset;  //!< Offset for datarate for first window
+        uint8_t JoinRx2DatarateIndex;   //!< Datarate for second window
+
+        uint32_t Channels[16];
+        uint8_t ChannelRanges[16];
+
+        uint32_t JoinRx2Frequency;      //!< Frequency used in second window
+
+        uint8_t MaxEIRP;
+        uint8_t UlDwellTime;
+        uint8_t DlDwellTime;
+
+        uint8_t padding;
+
+        uint32_t DlChannels[16];
+
+        uint8_t LastPlan;               //!< Channel plan from last saved configuration
+
+        int8_t lbtThreshold;            //!< Listen before talk threshold
+        uint16_t lbtTimeUs;             //!< Listen before talk time
+
+        // Multicast session address and keys
+        uint32_t MulticastAddress[MULTICAST_SESSIONS];
+        uint8_t MulticastNetSessionKey[MULTICAST_SESSIONS][KEY_LENGTH];
+        uint8_t MulticastAppSessionKey[MULTICAST_SESSIONS][KEY_LENGTH];
+
+        uint8_t AutoSleep;
+
+        uint8_t RFU[CONFIG_RFU_SIZE];
+} LoRaSettings_t;
+
+// DON'T CHANGE THIS UNLESS YOU REALLY WANT TO
+#define SESSION_RFU_SIZE 2
+
+// SESSION SETTINGS SHOULD ALWAYS HAVE SIZE OF 256 BYTES
+typedef struct {
+        bool Joined;
+        uint8_t Rx1DatarateOffset;
+        uint8_t Rx2Datarate;
+        uint8_t ChannelMask500k;
+
+        uint32_t NetworkAddress;
+
+        uint8_t NetworkKey[KEY_LENGTH];
+        uint8_t DataKey[KEY_LENGTH];
+
+        uint64_t ChannelMask;
+
+        uint32_t Channels[16];
+        uint8_t ChannelRanges[16];
+
+        uint32_t UplinkCounter;
+
+        uint8_t Rx1Delay;
+        uint8_t Datarate;
+        uint8_t TxPower;
+        uint8_t Repeat;
+
+        uint32_t Rx2Frequency;
+
+        uint32_t DownlinkCounter;
+
+        uint8_t MaxDutyCycle;
+        uint8_t AdrAckCounter;
+        uint8_t LinkFailCount;
+        uint8_t FrequencySubBand;
+
+        uint32_t NetworkId;
+
+        bool ServerAckRequested;
+        uint8_t DeviceClass;
+
+        uint8_t CommandBufferIndex;
+
+        uint8_t CommandBuffer[15];
+
+        uint8_t UlDwellTime;
+        uint8_t DlDwellTime;
+
+        uint32_t DlChannels[16];
+
+        uint8_t MaxEIRP;
+
+        // Multicast session counter values
+        uint32_t MulticastCounters[MULTICAST_SESSIONS];
+
+        uint8_t RFU[SESSION_RFU_SIZE];
+
+        uint8_t LastPlan;               //!< Channel plan from last saved session
+
+} NetworkSession_t;
+
+class LoRaConfig {
+
+    public:
+
+        static const uint8_t EuiLength = EUI_LENGTH;
+        static const uint8_t KeyLength = KEY_LENGTH;
+        static const uint8_t PassPhraseLength = PASSPHRASE_LENGTH;
+
+        enum JoinMode {
+            MANUAL,
+            OTA,
+            AUTO_OTA,
+            PEER_TO_PEER
+        };
+
+        enum Mode {
+            COMMAND_MODE,
+            SERIAL_MODE
+        };
+
+        enum RX_Output {
+            HEXADECIMAL,
+            BINARY
+        };
+
+        enum DataRates {
+            DR0,
+            DR1,
+            DR2,
+            DR3,
+            DR4,
+            DR5,
+            DR6,
+            DR7,
+            DR8,
+            DR9,
+            DR10,
+            DR11,
+            DR12,
+            DR13,
+            DR14,
+            DR15
+        };
+
+        enum FrequencySubBands {
+            FSB_ALL,
+            FSB_1,
+            FSB_2,
+            FSB_3,
+            FSB_4,
+            FSB_5,
+            FSB_6,
+            FSB_7,
+            FSB_8
+        };
+
+        enum JoinByteOrder {
+            LSB,
+            MSB
+        };
+
+        static const uint32_t BaudRates[];
+        static const std::string DRS[];
+        static const uint32_t DefaultBaudRate;
+
+        uint32_t ValidateBaudRate(uint32_t rate);
+
+        LoRaConfig(lora::ChannelPlan *plan);
+        ~LoRaConfig();
+
+        bool Save();
+        bool SaveSession();
+        bool SaveProtected();
+
+#if defined (TARGET_MTS_MDOT_F411RE)
+        void EnablePVD();
+        bool PVDO();
+#endif /* TARGET_MTS_MDOT_F411RE */
+
+        void Mount();
+        void Load();
+        void Default();
+        void DefaultSession();
+        void DefaultProtected();
+
+        uint8_t PublicNetwork();
+        void PublicNetwork(uint8_t val);
+
+        uint8_t* DeviceEUI();
+        void DeviceEUI(uint8_t* devEUI);
+
+        const uint8_t* AppEUI();
+        void AppEUI(const uint8_t* appEUI);
+
+        const uint8_t* AppKey();
+        void AppKey(const uint8_t* appKey);
+
+        uint8_t* NetworkEUI();
+        void NetworkEUI(const uint8_t* networkEUI);
+
+        uint8_t* NetworkEUIPassphrase();
+        void NetworkEUIPassphrase(uint8_t* networkEUIPassphrase, uint8_t length);
+
+        uint8_t* NetworkKey();
+        void NetworkKey(const uint8_t* networkKey);
+
+        uint8_t* NetworkKeyPassphrase();
+        void NetworkKeyPassphrase(uint8_t* networkKeyPassphrase, uint8_t length);
+
+        uint32_t NetworkAddress();
+        void NetworkAddress(uint32_t addr);
+
+        uint8_t* NetworkSessionKey();
+        void NetworkSessionKey(uint8_t* networkSessionKey);
+
+        uint8_t* DataSessionKey();
+        void DataSessionKey(uint8_t* dataSessionKey);
+
+        uint8_t JoinMode();
+        void JoinMode(uint8_t mode);
+
+        uint8_t JoinRetries();
+        void JoinRetries(uint8_t retries);
+
+        uint8_t LinkCheckCount();
+        void LinkCheckCount(uint8_t count);
+
+        uint8_t LinkCheckThreshold();
+        void LinkCheckThreshold(uint8_t count);
+
+        uint8_t ForwardErrorCorrection();
+        void ForwardErrorCorrection(uint8_t bytes);
+
+        uint8_t ACKAttempts();
+        void ACKAttempts(uint8_t attempts);
+
+        bool EnableEncryption();
+        void EnableEncryption(uint8_t enable);
+
+        bool EnableCRC();
+        void EnableCRC(uint8_t enable);
+
+        bool EnableADR();
+        void EnableADR(uint8_t enable);
+
+        bool EnableEcho();
+        void EnableEcho(uint8_t enable);
+
+        bool EnableVerbose();
+        void EnableVerbose(uint8_t enable);
+
+        uint8_t TxDataRate();
+        void TxDataRate(uint8_t rate);
+
+        uint8_t TxPower();
+        void TxPower(uint8_t power);
+
+        uint8_t FrequencyBand();
+        void FrequencyBand(uint8_t band);
+
+        uint8_t FrequencySubBand();
+        void FrequencySubBand(uint8_t band);
+
+        uint32_t TxFrequency();
+        void TxFrequency(uint32_t freq);
+
+        bool TxInverted();
+        void TxInverted(bool enable);
+
+        bool TxWait();
+        void TxWait(bool timeout);
+
+        uint32_t RxFrequency();
+        void RxFrequency(uint32_t freq);
+
+        bool RxInverted();
+        void RxInverted(bool enable);
+
+        uint8_t RxOutput();
+        void RxOutput(uint8_t type);
+
+        uint8_t RxDataRate();
+        void RxDataRate(uint8_t rate);
+
+        uint8_t Rx2DataRate();
+        void Rx2DataRate(uint8_t rate);
+
+        uint8_t StartUpMode();
+        void StartUpMode(uint8_t mode);
+
+        /* Serial Settings */
+        uint32_t SerialBaudRate();
+        void SerialBaudRate(uint32_t rate);
+
+        uint32_t WakeInterval();
+        void WakeInterval(uint32_t interval);
+
+        uint32_t WakeDelay();
+        void WakeDelay(uint32_t delay);
+
+        uint16_t WakeTimeout();
+        void WakeTimeout(uint16_t timeout);
+
+        uint8_t WakePin();
+        void WakePin(uint8_t pin);
+
+        uint8_t WakeMode();
+        void WakeMode(uint8_t mode);
+
+        uint32_t DebugBaudRate();
+        void DebugBaudRate(uint32_t baud);
+
+        bool Joined();
+        void Joined(bool val);
+
+        uint32_t* Channels();
+
+        uint32_t* DownlinkChannels();
+
+        uint8_t* ChannelRanges();
+
+        uint8_t* SessionDataKey();
+        void SessionDataKey(uint8_t* key);
+
+        uint8_t* SessionNetworkKey();
+        void SessionNetworkKey(uint8_t* key);
+
+        uint32_t SessionNetworkAddress();
+        void SessionNetworkAddress(uint32_t addr);
+
+        uint8_t SessionDatarate();
+        void SessionDatarate(uint8_t datarate);
+
+        uint8_t SessionTxPower();
+        void SessionTxPower(uint8_t power);
+
+        uint8_t SessionRepeat();
+        void SessionRepeat(uint8_t repeat);
+
+        uint8_t SessionRxDelay();
+        void SessionRxDelay(uint8_t delay);
+
+        uint8_t SessionRx1DatarateOffset();
+        void SessionRx1DatarateOffset(uint8_t offset);
+
+        uint8_t SessionRx2Datarate();
+        void SessionRx2Datarate(uint8_t datarate);
+
+        uint32_t SessionRx2Frequency();
+        void SessionRx2Frequency(uint32_t frequency);
+
+        uint64_t SessionChannelMask();
+        void SessionChannelMask(uint64_t mask);
+
+        uint8_t Session500kMask();
+        void Session500kMask(uint8_t mask);
+
+        uint32_t* SessionChannels();
+
+        uint32_t* SessionDownlinkChannels();
+
+        uint8_t* SessionChannelRanges();
+
+        uint32_t SessionUplinkCounter();
+        void SessionUplinkCounter(uint32_t count);
+
+        uint32_t SessionDownlinkCounter();
+        void SessionDownlinkCounter(uint32_t count);
+
+        uint8_t SessionAdrAckCounter();
+        void SessionAdrAckCounter(uint8_t count);
+
+        uint8_t SessionLinkFailCount();
+        void SessionLinkFailCount(uint8_t count);
+
+        uint8_t SessionFrequencySubBand();
+        void SessionFrequencySubBand(uint8_t band);
+
+        bool SessionServerAckRequested();
+        void SessionServerAckRequested(bool val);
+
+        uint32_t SessionNetworkId();
+        void SessionNetworkId(uint32_t id);
+
+        uint8_t SessionDeviceClass();
+        void SessionDeviceClass(uint8_t cls);
+
+        uint8_t* SessionCommandBuffer();
+        void SessionCommandBuffer(uint8_t* buffer);
+
+        uint8_t SessionCommandBufferIndex();
+        void SessionCommandBufferIndex(uint8_t index);
+
+        uint8_t SessionMaxDutyCycle();
+        void SessionMaxDutyCycle(uint8_t duty);
+
+        uint8_t SessionUplinkDwelltime();
+        void SessionUplinkDwelltime(uint8_t dwell);
+
+        uint8_t SessionDownlinkDwelltime();
+        void SessionDownlinkDwelltime(uint8_t dwell);
+
+        uint8_t SessionMaxEIRP();
+        void SessionMaxEIRP(uint8_t pow);
+
+        uint8_t LogLevel();
+        void LogLevel(uint8_t level);
+
+        uint8_t JoinByteOrder();
+        void JoinByteOrder(uint8_t order);
+
+        uint8_t PreserveSessionOverReset();
+        void PreserveSessionOverReset(uint8_t);
+
+        uint8_t JoinDelay();
+        void JoinDelay(uint8_t delay);
+
+        uint8_t JoinRx1DatarateOffset();
+        void JoinRx1DatarateOffset(uint8_t offset);
+
+        uint8_t JoinRx2DatarateIndex();
+        void JoinRx2DatarateIndex(uint8_t datarate);
+
+        uint32_t JoinRx2Frequency();
+        void JoinRx2Frequency(uint32_t freq);
+
+        uint8_t RxDelay();
+        void RxDelay(uint8_t delay);
+
+        uint8_t Port();
+        void Port(uint8_t port);
+
+        uint8_t Class();
+        void Class(uint8_t cls);
+
+        int8_t AntennaGain();
+        void AntennaGain(int8_t gain);
+
+        bool FlowControl();
+        void FlowControl(bool enable);
+
+        uint8_t Repeat();
+        void Repeat(uint8_t repeat);
+
+        bool SerialClearOnError();
+        void SerialClearOnError(bool val);
+
+        uint8_t LastPlan();
+        uint8_t SessionLastPlan();
+
+        void LbtTimeUs(uint16_t us);
+        uint16_t LbtTimeUs();
+        void LbtThreshold(int8_t rssi);
+        int8_t LbtThreshold();
+
+        uint32_t GetMulticastAddress(int i);
+        uint8_t* GetMulticastNetSessionKey(int i);
+        uint8_t* GetMulticastAppSessionKey(int i);
+        uint32_t GetMulticastCounter(int i);
+
+
+        void SetMulticastAddress(int i, uint32_t addr);
+        void SetMulticastNetSessionKey(int i, const uint8_t* key);
+        void SetMulticastAppSessionKey(int i, const uint8_t* key);
+        void SetMulticastCounter(int i, uint32_t count);
+
+        void AutoSleep(uint8_t enable);
+        uint8_t AutoSleep();
+
+        /*!
+         * AES encryption/decryption cipher network app ieee eui
+         */
+        static const uint8_t defaultNetworkEUI[EUI_LENGTH];
+        /*!
+         * AES encryption/decryption cipher application key
+         */
+        static const uint8_t defaultNetworkKey[KEY_LENGTH];
+
+        /*!
+         * AES encryption/decryption cipher network session key
+         */
+        static const uint8_t defaultNetworkSessionKey[KEY_LENGTH];
+
+        /*!
+         * AES encryption/decryption cipher application session key
+         */
+        static const uint8_t defaultDataSessionKey[KEY_LENGTH];
+
+        void Sleep();
+        void Wakeup();
+
+        void SetChannelPlan(lora::ChannelPlan *plan);
+
+#if defined (TARGET_MTS_MDOT_F411RE)
+        mDot::mdot_file OpenUserFile(const char* file, int mode);
+        bool SeekUserFile(mDot::mdot_file& file, size_t offset, int whence);
+        int ReadUserFile(mDot::mdot_file& file, void* data, size_t length);
+        int WriteUserFile(mDot::mdot_file& file, void* data, size_t length);
+        bool CloseUserFile(mDot::mdot_file& file);
+        bool MoveUserFile(mDot::mdot_file& file, const char* new_name);
+
+        bool MoveUserFile(const char* file, const char* new_name);
+        bool SaveUserFile(const char* file, void* data, uint32_t size);
+        bool AppendUserFile(const char* file, void* data, uint32_t size);
+        bool ReadUserFile(const char* file, void* data, uint32_t size);
+        bool DeleteUserFile(const char* file);
+        bool DeleteFile(const char* file);
+
+        bool MoveUserFileToFirwareUpgrade(const char* file);
+
+        std::vector<mDot::mdot_file> ListUserFiles();
+#endif /* TARGET_MTS_MDOT_F411RE */
+
+    private:
+        LoRaSettings_t _settings;
+        ProtectedSettings_t _protected;
+        NetworkSession_t _session;
+        bool _dirty_settings;
+
+        uint32_t _frequencyMin;
+        uint32_t _frequencyMax;
+
+        lora::ChannelPlan *_plan;
+
+#if defined (TARGET_MTS_MDOT_F411RE)
+        // SpiFlash25 flash(MOSI, MISO, SCK, CS, W, HOLD);
+        static SpiFlash25 _flash;
+
+        mDot::mdot_file OpenFile(spiffs *fs, const char* file, int mode);
+        bool SeekFile(spiffs *fs, mDot::mdot_file& file, size_t offset, int whence);
+
+        int ReadFile(spiffs *fs, mDot::mdot_file& file, void* data, size_t length);
+        int WriteFile(spiffs *fs, mDot::mdot_file& file, void* data, size_t length);
+        int MoveFile(spiffs* fs, mDot::mdot_file& file, const char* new_name);
+        bool CloseFile(spiffs *fs, mDot::mdot_file& file);
+
+        bool AppendFile(spiffs *fs, const char* file, void* data, uint32_t size);
+        bool SaveFile(spiffs *fs, const char* file, void* data, uint32_t size);
+        bool ReadFile(spiffs *fs, const char* file, void* dest, uint32_t size);
+        bool MoveFile(spiffs *fs, const char* file, const char* new_name);
+
+        // glue code between SPI driver and filesystem
+        static int spi_read(unsigned int addr, unsigned int size, unsigned char* data);
+        static int spi_write(unsigned int addr, unsigned int size, unsigned char* data);
+        static int spi_erase(unsigned int addr, unsigned int size);
+
+        static u8_t spiffs_work_buf[PAGE_SIZE * 2];
+        static u8_t spiffs_fds[32 * MAX_CONCURRENT_FDS];
+        static u8_t spiffs_cache_buf[(PAGE_SIZE + 32) * 4];
+
+        u8_t _openFds;
+
+        static spiffs _fs;
+
+        static char file[];
+        static char protected_file[];
+        static char session_file[];
+        static char user_dir[];
+#endif /* TARGET_MTS_MDOT_F411RE */
+
+};
+
+#endif // __LORA_CONFIG_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/Lora/ChannelPlan.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,631 @@
+/**   __  ___     ____  _    ______        __     ____         __                  ____
+ *   /  |/  /_ __/ / /_(_)__/_  __/__ ____/ /    / __/_ _____ / /____ __ _  ___   /  _/__  ____
+ *  / /|_/ / // / / __/ /___// / / -_) __/ _ \  _\ \/ // (_-</ __/ -_)  ' \(_-<  _/ // _ \/ __/ __
+ * /_/  /_/\_,_/_/\__/_/    /_/  \__/\__/_//_/ /___/\_, /___/\__/\__/_/_/_/___/ /___/_//_/\__/ /_/
+ * Copyright (C) 2015 by Multi-Tech Systems        /___/
+ *
+ *
+ * @author Jason Reiss
+ * @date   10-31-2015
+ * @brief  lora::ChannelPlan provides an interface for LoRaWAN channel schemes
+ *
+ * @details
+ *
+ */
+
+#ifndef __CHANNEL_STRATEGY_H__
+#define __CHANNEL_STRATEGY_H__
+
+#include "Lora.h"
+#include "SxRadio.h"
+#include <vector>
+
+namespace lora {
+
+    class ChannelPlan {
+        public:
+
+            /**
+             * Descriptions for channel plans & region information.
+             * Bits 0-2 represent the plan type (fixed or dynamic)
+             *   0b000              cannot be used as plans may line up with old definitions and cause much badness
+             *   0b001              fixed channel plans
+             *   0b010              dynamic channel plans
+             *   0b011 - 0b111      RFU
+             * Bits 3-7 represent the specific channel plan/region within the plan type
+             */
+            enum PlanType {
+                FIXED = 0x20,
+                DYNAMIC = 0x40,
+            };
+
+            enum Plan {
+                EU868_OLD = 0x00,
+                US915_OLD = 0x01,
+                AU915_OLD = 0x02,
+
+                FB_EU868 = 0x00,
+                FB_US915 = 0x01,
+                FB_AU915 = 0x02,
+
+                FB_868 = 0x00,
+                FB_915 = 0x01,
+
+                US915 = FIXED | 0x00,
+                AU915 = FIXED | 0x01,
+
+                EU868 = DYNAMIC | 0x00,
+                IN865 = DYNAMIC | 0x01,
+                AS923 = DYNAMIC | 0x02,
+                KR920 = DYNAMIC | 0x03,
+                AS923_JAPAN = DYNAMIC | 0x04,
+
+                NONE = 0xFF,
+            };
+
+            /**
+             * ChannelPlan constructor
+             * @param radio SxRadio object used to set Tx/Rx config
+             * @param settings Settings object
+             */
+            ChannelPlan(SxRadio* radio, Settings* settings);
+
+            /**
+             * ChannelPlan destructor
+             */
+            virtual ~ChannelPlan();
+            
+            /**
+             * Checks that at least one channel exist for the data rate
+             */
+            virtual uint8_t ValidateAdrDatarate(uint8_t status);
+
+            /**
+             * Initialize channels, datarates and duty cycle bands according to current channel plan in settings
+             */
+            virtual void Init() = 0;
+
+            /**
+             * Set SxRadio object to be used to set Tx/Rx config
+             */
+            virtual void SetRadio(SxRadio* radio);
+
+            /**
+             * Set Settings object
+             */
+            virtual void SetSettings(Settings* settings);
+
+            /**
+             * Get the next channel to use to transmit
+             * @return LORA_OK if channel was found
+             * @return LORA_NO_CHANS_ENABLED
+             */
+            virtual uint8_t GetNextChannel() = 0;
+
+            /**
+             * Set the number of channels in the plan
+             */
+            virtual void SetNumberOfChannels(uint8_t channels, bool resize = true);
+
+            /**
+             * Get the number of channels in the plan
+             */
+            virtual uint8_t GetNumberOfChannels();
+
+            /**
+             * Check if channel is enabled
+             * @return true if enabled
+             */
+            virtual bool IsChannelEnabled(uint8_t channel);
+
+            /**
+             * Set a 16 bit channel mask with offset
+             * @param index of mask to set 0:0-15, 1:16-31 ...
+             * @param mask 16 bit mask of enabled channels
+             * @return true
+             */
+            virtual bool SetChannelMask(uint8_t index, uint16_t mask);
+
+            /**
+             * Get the channel mask of currently enabled channels
+             * @return vector containing channel bit masks
+             */
+            virtual std::vector<uint16_t> GetChannelMask();
+
+            /**
+             * Add a channel to the ChannelPlan
+             * @param index of channel, use -1 to add to end
+             * @param channel settings to add
+             */
+            virtual uint8_t AddChannel(int8_t index, Channel channel) = 0;
+
+            /**
+             * Get channel at index
+             * @return Channel
+             */
+            virtual Channel GetChannel(int8_t index) = 0;
+
+            /**
+             * Add a downlink channel to the ChannelPlan
+             * Set to 0 to use the default uplink channel frequency
+             * @param index of channel, use -1 to add to end
+             * @param channel settings to add
+             */
+            virtual uint8_t AddDownlinkChannel(int8_t index, Channel channel);
+
+            /**
+             * Get channel at index
+             * @return Channel
+             */
+            virtual Channel GetDownlinkChannel(uint8_t index);
+
+            /**
+             * Set number of datarates in ChannelPlan
+             * @param datarates
+             */
+            virtual void SetNumberOfDatarates(uint8_t datarates);
+
+            /**
+             * Add a datarate to the ChannelPlan
+             * @param index of datarate, use -1 to add to end
+             * @param datarate settings to add
+             */
+            virtual uint8_t AddDatarate(int8_t index, Datarate datarate);
+
+            /**
+             * Get datarate at index
+             * @return Datarate
+             */
+            virtual Datarate GetDatarate(int8_t index);
+
+            /**
+             * Get max payload size for current datarate
+             * @return size in bytes
+             */
+            virtual uint8_t GetMaxPayloadSize();
+
+            /**
+             * Get rx window settings for requested window
+             * RX_1, RX_2, RX_BEACON, RX_SLOT
+             * @param window
+             * @return RxWindow
+             */
+            virtual RxWindow GetRxWindow(uint8_t window) = 0;
+
+            /**
+             * Get current channel to use for transmitting
+             * @param channel index of channel
+             * @return LORA_OK
+             */
+            virtual uint8_t SetTxChannel(uint8_t channel);
+
+            /**
+             * Get datarate to use on the join request
+             * @return datarate index
+             */
+            virtual uint8_t GetJoinDatarate() = 0;
+
+            /**
+             * Calculate the next time a join request is possible
+             * @param size of join frame
+             * @returns LORA_OK
+             */
+            virtual uint8_t CalculateJoinBackoff(uint8_t size) = 0;
+
+            /**
+             * Get the current datarate
+             * @return Datarate
+             */
+            virtual Datarate GetTxDatarate();
+
+            /**
+             * Set the current datarate
+             * @param index of datarate
+             * @return LORA_OK
+             */
+            virtual uint8_t SetTxDatarate(uint8_t index);
+
+            /**
+             * Set the datarate offset used for first receive window
+             * @param offset
+             * @return LORA_OK
+             */
+            virtual uint8_t SetRx1Offset(uint8_t offset);
+
+            /**
+             * Set the frequency for second receive window
+             * @param freq
+             * @return LORA_OK
+             */
+            virtual uint8_t SetRx2Frequency(uint32_t freq);
+
+            /**
+             * Set the datarate index used for second receive window
+             * @param index
+             * @return LORA_OK
+             */
+            virtual uint8_t SetRx2DatarateIndex(uint8_t index);
+
+            /**
+             * Get next channel and set the SxRadio tx config with current settings
+             * @return LORA_OK
+             */
+            virtual uint8_t SetTxConfig() = 0;
+
+            /**
+             * Set the SxRadio rx config provided window
+             * @param window to be opened
+             * @param continuous keep window open
+             * @return LORA_OK
+             */
+            virtual uint8_t SetRxConfig(uint8_t window, bool continuous) = 0;
+
+            /**
+             * Set frequency sub band if supported by plan
+             * @param sub_band
+             * @return LORA_OK
+             */
+            virtual uint8_t SetFrequencySubBand(uint8_t group) = 0;
+
+            /**
+             * Get frequency sub band if supported by plan
+             * @return sub band 0-8 or 0 if not supported
+             */
+            virtual uint8_t GetFrequencySubBand();
+
+            /**
+             * Reset the ack counter used to lower datarate if ACK's are missed
+             */
+            virtual void ResetAckCounter();
+
+            /**
+             * Callback for radio to request channel change when frequency hopping
+             * @param currentChannel
+             */
+            virtual void FhssChangeChannel(uint8_t currentChannel);
+
+            /**
+             * Callback for ACK timeout event
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleAckTimeout();
+
+            /**
+             * Callback for Join Accept packet to load optional channels
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleJoinAccept(const uint8_t* buffer, uint8_t size) = 0;
+
+            /**
+             * Callback to for rx parameter setup ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleRxParamSetup(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status) = 0;
+
+            /**
+             * Callback to for new channel ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleNewChannel(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status) = 0;
+
+            /**
+             * Callback to for downlink channel request ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleDownlinkChannelReq(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Callback to for ping slot channel request ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandlePingSlotChannelReq(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status) = 0;
+
+            /**
+             * Callback to for beacon frequency request ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleBeaconFrequencyReq(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status) = 0;
+
+            /**
+             * Callback to for adaptive datarate ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleAdrCommand(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status) = 0;
+
+            /**
+             * Validate the configuration after multiple ADR commands have been applied
+             * @return status to be returned in MoteCommand answer
+             */
+            virtual uint8_t ValidateAdrConfiguration() = 0;
+
+            /**
+             * Check that Rf Frequency is within channel plan range
+             * @param freq frequency in Hz
+             * @return true if valid frequency
+             */
+            virtual bool CheckRfFrequency(uint32_t freq);
+
+            /**
+             * Flag for ADR
+             * @return true if ADR is enable in settings
+             */
+            virtual bool IsAdrEnabled();
+
+            /**
+             * Flag if ADR ACK should be sent in next packet
+             * @return true when flag should be set
+             */
+            virtual bool AdrAckReq();
+
+            /**
+             * Increment the ADR counter to track when ADR ACK request should be sent
+             * @return current value
+             */
+            virtual uint8_t IncAdrCounter();
+
+            /**
+             * Reset the ADR counter when valid downlink is received from network server
+             */
+            virtual void ResetAdrCounter();
+
+            /**
+             * Get the time the radio must be off air to comply with regulations
+             * Time to wait may be dependent on duty-cycle restrictions per channel
+             * Or duty-cycle of join requests if OTAA is being attempted
+             * @return ms of time to wait for next tx opportunity
+             */
+            virtual uint32_t GetTimeOffAir() = 0;
+
+            /**
+             * Get the channels in use by current channel plan
+             * @return channel frequencies
+             */
+            virtual std::vector<uint32_t> GetChannels() = 0;
+
+            /**
+             * Get the downlink channels in use by current channel plan
+             * @return channel frequencies
+             */
+            virtual std::vector<uint32_t> GetDownlinkChannels();
+
+            /**
+             * Get the channel datarate ranges in use by current channel plan
+             * @return channel datarate ranges
+             */
+            virtual std::vector<uint8_t> GetChannelRanges() = 0;
+
+            /**
+             * Set the time off air for the given duty band
+             * @param band index
+             * @param time off air in ms
+             */
+            virtual void SetDutyBandTimeOff(uint8_t band, uint32_t timeoff);
+
+            /**
+             * Get the time off air for the given duty band
+             * @param band index
+             * @return time off air in ms
+             */
+            virtual uint32_t GetDutyBandTimeOff(uint8_t band);
+
+            /**
+             * Get the number of duty bands in the current channel plan
+             * @return number of bands
+             */
+            virtual uint8_t GetNumDutyBands();
+
+            /**
+             * Get the duty band index for the given frequency
+             * @param freq frequency in Hz
+             * @return index of duty band
+             */
+            virtual int8_t GetDutyBand(uint32_t freq);
+
+            /**
+             * Add duty band
+             * @param index of duty band or -1 to append
+             * @param band DutyBand definition
+             * @return LORA_OK
+             */
+            virtual uint8_t AddDutyBand(int8_t index, DutyBand band);
+
+            /**
+             * Update duty cycle with current settings
+             */
+            void UpdateDutyCycle(uint8_t bytes);
+
+            /**
+             * Update duty cycle with at given frequency and time on air
+             * @param freq frequency
+             * @param time_on_air_ms tx time on air
+             */
+            virtual void UpdateDutyCycle(uint32_t freq, uint32_t time_on_air_ms);
+
+            /**
+             * Get time on air with current settings
+             * @param bytes number of bytes to be sent
+             */
+            virtual uint32_t GetTimeOnAir(uint8_t bytes);
+
+            /**
+             * Reset the duty timers with the current time off air
+             */
+            virtual void ResetDutyCycleTimer();
+
+            /**
+             * Print log message for given rx window
+             * @param wnd 1 or 2
+             */
+            virtual void LogRxWindow(uint8_t wnd) = 0;
+
+            /**
+             * Indicator of P2P mode
+             * @return true if enabled
+             */
+            virtual bool P2PEnabled();
+
+            /**
+             * Ack timeout for P2P mode
+             * @return timeout in ms
+             */
+            virtual uint16_t P2PTimeout();
+
+            /**
+             * Ack backoff for P2P mode
+             * @return backoff in ms
+             */
+            virtual uint16_t P2PBackoff();
+
+            /**
+             * Enable the default channels of the channel plan
+             */
+            virtual void EnableDefaultChannels() = 0;
+
+            /**
+             *  Callback for radio thread to signal
+             */
+            virtual void MacEvent();
+
+            /**
+             * Called when MAC layer doesn't know about a command.
+             * Use to add custom or new mac command handling
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleMacCommand(uint8_t* payload, uint8_t& index);
+
+            virtual void DecrementDatarate();
+            virtual void IncrementDatarate();
+
+            virtual std::string GetPlanName();
+            virtual uint8_t GetPlan();
+            virtual bool IsPlanFixed();
+            virtual bool IsPlanDynamic();
+            static bool IsPlanFixed(uint8_t plan);
+            static bool IsPlanDynamic(uint8_t plan);
+            virtual uint32_t GetMinFrequency();
+            virtual uint32_t GetMaxFrequency();
+
+            virtual uint8_t GetMinDatarate();
+            virtual uint8_t GetMaxDatarate();
+            virtual uint8_t GetMinDatarateOffset();
+            virtual uint8_t GetMaxDatarateOffset();
+
+            virtual uint8_t GetMinRx2Datarate();
+            virtual uint8_t GetMaxRx2Datarate();
+            virtual uint8_t GetMaxTxPower();
+            virtual uint8_t GetMinTxPower();
+
+            virtual uint16_t GetLBT_TimeUs();
+            virtual void SetLBT_TimeUs(uint16_t us);
+
+            virtual int8_t GetLBT_Threshold();
+            virtual void SetLBT_Threshold(int8_t rssi);
+
+            /**
+             * Set LBT time and threshold to defaults
+             */
+            virtual void DefaultLBT();
+
+            virtual bool ListenBeforeTalk();
+        
+            /**
+             * use to clear downlink channels on join
+             */
+            virtual void ClearChannels();
+    
+        protected:
+
+            SxRadio* GetRadio();                //!< Get pointer to the SxRadio object or assert if it is null
+            Settings* GetSettings();            //!< Get pointer to the settings object or assert if it is null
+
+            uint8_t _txChannel;                 //!< Current channel for transmit
+            uint8_t _txFrequencySubBand;        //!< Current frequency sub band for hybrid operation
+
+            std::vector<Datarate> _datarates;   //!< List of datarates
+
+            std::vector<Channel> _channels;     //!< List of channels for transmit
+            std::vector<Channel> _dlChannels;   //!< List of channels for receive if changed from default
+
+            std::vector<DutyBand> _dutyBands;   //!< List of duty bands to limit radio time on air
+
+            uint8_t _maxTxPower;                //!< Max Tx power for channel Plan
+            uint8_t _minTxPower;
+
+            uint32_t _minFrequency;             //!< Minimum Frequency
+            uint32_t _maxFrequency;             //!< Maximum Frequency
+
+            Channel _beaconChannel;             //!< Beacon window settings
+            Channel _beaconRxChannel;           //!< Beacon slot rx window settings
+
+            uint8_t _minDatarate;               //!< Minimum datarate to accept in ADR request
+            uint8_t _maxDatarate;               //!< Maximum datarate to accept in ADR request
+
+            uint8_t _minRx2Datarate;            //!< Minimum datarate to accept in for Rx2
+            uint8_t _maxRx2Datarate;            //!< Maximum datarate to accept in for Rx2
+            uint8_t _minDatarateOffset;         //!< Minimum datarate offset to accept
+            uint8_t _maxDatarateOffset;         //!< Maximum datarate offset to accept
+
+            uint32_t _freqUBase125k;            //!< Start of 125K uplink channels
+            uint32_t _freqUStep125k;            //!< Step between 125K uplink channels
+            uint32_t _freqUBase500k;            //!< Start of 500K uplink channels
+            uint32_t _freqUStep500k;            //!< Step between 500K uplink channels
+            uint32_t _freqDBase500k;            //!< Start of 500K downlink channels
+            uint32_t _freqDStep500k;            //!< Step between 500K downlink channels
+
+            uint8_t _numChans;                  //!< Number of total channels in plan
+            uint8_t _numChans125k;              //!< Number of 125K  channels in plan
+            uint8_t _numChans500k;              //!< Number of 500K channels in plan
+
+            uint16_t _LBT_TimeUs;               //!< Sample time in us for LBT
+            int8_t _LBT_Threshold;              //!< Threshold in dBm for LBT
+
+            std::vector<uint16_t> _channelMask; //!< Bit mask for currently enabled channels
+
+            Timer _dutyCycleTimer;              //!< Timer for tracking time-off-air
+            RtosTimer _txDutyTimer;             //!< Event timer for expiration of time-off-air
+
+            bool _txDutyCyclePending;           //!< Flag for pending duty cycle event
+
+            static void OnTxDutyCycleEvent(const void* arg);    //!< Rtos callback for duty cycle event
+            void OnTxDutyCycleEventBottom();                    //!< Callback for duty cycle event
+
+            static const uint8_t* TX_POWERS;                    //!< List of available tx powers
+            static const uint8_t* RADIO_POWERS;                    //!< List of available tx powers
+            static const uint8_t* MAX_PAYLOAD_SIZE;             //!< List of max payload sizes for each datarate
+            static const uint8_t* MAX_PAYLOAD_SIZE_REPEATER;    //!< List of repeater compatible max payload sizes for each datarate
+
+            uint8_t _plan;
+            std::string _planName;
+
+        private:
+
+            SxRadio* _radio;                    //!< Injected SxRadio dependency
+            Settings* _settings;                //!< Current settings
+    };
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/Lora/ChannelPlans/ChannelPlan_AS923.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,244 @@
+/**   __  ___     ____  _    ______        __     ____         __                  ____
+ *   /  |/  /_ __/ / /_(_)__/_  __/__ ____/ /    / __/_ _____ / /____ __ _  ___   /  _/__  ____
+ *  / /|_/ / // / / __/ /___// / / -_) __/ _ \  _\ \/ // (_-</ __/ -_)  ' \(_-<  _/ // _ \/ __/ __
+ * /_/  /_/\_,_/_/\__/_/    /_/  \__/\__/_//_/ /___/\_, /___/\__/\__/_/_/_/___/ /___/_//_/\__/ /_/
+ * Copyright (C) 2015 by Multi-Tech Systems        /___/
+ *
+ *
+ * @author Jason Reiss
+ * @date   10-31-2015
+ * @brief  lora::ChannelPlan provides an interface for LoRaWAN channel schemes
+ *
+ * @details
+ *
+ */
+
+#ifndef __CHANNEL_PLAN_AS923_H__
+#define __CHANNEL_PLAN_AS923_H__
+
+#include "Lora.h"
+#include "SxRadio.h"
+#include <vector>
+#include "ChannelPlan.h"
+
+namespace lora {
+
+    class ChannelPlan_AS923: public lora::ChannelPlan {
+        public:
+            /**
+             * ChannelPlan constructor
+             * @param radio SxRadio object used to set Tx/Rx config
+             * @param settings Settings object
+             */
+            ChannelPlan_AS923();
+            ChannelPlan_AS923(Settings* settings);
+            ChannelPlan_AS923(SxRadio* radio, Settings* settings);
+
+            /**
+             * ChannelPlan destructor
+             */
+            virtual ~ChannelPlan_AS923();
+
+            /**
+             * Initialize channels, datarates and duty cycle bands according to current channel plan in settings
+             */
+            virtual void Init();
+
+            /**
+             * Get the next channel to use to transmit
+             * @return LORA_OK if channel was found
+             * @return LORA_NO_CHANS_ENABLED
+             */
+            virtual uint8_t GetNextChannel();
+
+            /**
+             * Add a channel to the ChannelPlan
+             * @param index of channel, use -1 to add to end
+             * @param channel settings to add
+             */
+            virtual uint8_t AddChannel(int8_t index, Channel channel);
+
+            /**
+             * Get channel at index
+             * @return Channel
+             */
+            virtual Channel GetChannel(int8_t index);
+
+            /**
+             * Get rx window settings for requested window
+             * RX_1, RX_2, RX_BEACON, RX_SLOT
+             * @param window
+             * @return RxWindow
+             */
+            virtual RxWindow GetRxWindow(uint8_t window);
+
+            /**
+             * Get datarate to use on the join request
+             * @return datarate index
+             */
+            virtual uint8_t GetJoinDatarate();
+
+            /**
+             * Calculate the next time a join request is possible
+             * @param size of join frame
+             * @returns LORA_OK
+             */
+            virtual uint8_t CalculateJoinBackoff(uint8_t size);
+
+            /**
+             * Get next channel and set the SxRadio tx config with current settings
+             * @return LORA_OK
+             */
+            virtual uint8_t SetTxConfig();
+
+            /**
+             * Set the SxRadio rx config provided window
+             * @param window to be opened
+             * @param continuous keep window open
+             * @return LORA_OK
+             */
+            virtual uint8_t SetRxConfig(uint8_t window, bool continuous);
+
+            /**
+             * Set frequency sub band if supported by plan
+             * @param sub_band
+             * @return LORA_OK
+             */
+            virtual uint8_t SetFrequencySubBand(uint8_t sub_band);
+
+            /**
+             * Callback for ACK timeout event
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleAckTimeout();
+
+            /**
+             * Callback for Join Accept packet to load optional channels
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleJoinAccept(const uint8_t* buffer, uint8_t size);
+
+            /**
+             * Callback to for rx parameter setup ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleRxParamSetup(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Callback to for new channel ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleNewChannel(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Callback to for ping slot channel request ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandlePingSlotChannelReq(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Callback to for beacon frequency request ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleBeaconFrequencyReq(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Callback to for adaptive datarate ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleAdrCommand(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Validate the configuration after multiple ADR commands have been applied
+             * @return status to be returned in MoteCommand answer
+             */
+            virtual uint8_t ValidateAdrConfiguration();
+
+            /**
+             * Update duty cycle with at given frequency and time on air
+             * @param freq frequency
+             * @param time_on_air_ms tx time on air
+             */
+            virtual void UpdateDutyCycle(uint32_t freq, uint32_t time_on_air_ms);
+
+            /**
+             * Get the time the radio must be off air to comply with regulations
+             * Time to wait may be dependent on duty-cycle restrictions per channel
+             * Or duty-cycle of join requests if OTAA is being attempted
+             * @return ms of time to wait for next tx opportunity
+             */
+            virtual uint32_t GetTimeOffAir();
+
+            /**
+             * Get the channels in use by current channel plan
+             * @return channel frequencies
+             */
+            virtual std::vector<uint32_t> GetChannels();
+
+            /**
+             * Get the channel datarate ranges in use by current channel plan
+             * @return channel datarate ranges
+             */
+            virtual std::vector<uint8_t> GetChannelRanges();
+
+            /**
+             * Print log message for given rx window
+             * @param wnd 1 or 2
+             */
+            virtual void LogRxWindow(uint8_t wnd);
+
+            /**
+             * Enable the default channels of the channel plan
+             */
+            virtual void EnableDefaultChannels();
+
+            /**
+             * Called when MAC layer doesn't know about a command.
+             * Use to add custom or new mac command handling
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleMacCommand(uint8_t* payload, uint8_t& index);
+
+            /**
+             * Get max payload size for current datarate
+             * @return size in bytes
+             */
+            virtual uint8_t GetMaxPayloadSize();
+
+            /**
+             * Decrements the datarate based on TxDwellTime
+             */
+            virtual void DecrementDatarate();
+
+        protected:
+
+            static const uint8_t AS923_TX_POWERS[8];                    //!< List of available tx powers
+            static const uint8_t AS923_RADIO_POWERS[21];                 //!< List of calibrated tx powers
+            static const uint8_t AS923_MAX_PAYLOAD_SIZE[];              //!< List of max payload sizes for each datarate
+            static const uint8_t AS923_MAX_PAYLOAD_SIZE_400[];              //!< List of max payload sizes for each datarate
+            static const uint8_t AS923_MAX_PAYLOAD_SIZE_REPEATER[];     //!< List of repeater compatible max payload sizes for each datarate
+            static const uint8_t AS923_MAX_PAYLOAD_SIZE_REPEATER_400[];     //!< List of repeater compatible max payload sizes for each datarate
+    };
+}
+
+#endif //__CHANNEL_PLAN_AS923_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/Lora/ChannelPlans/ChannelPlan_AS923_Japan.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,51 @@
+/**   __  ___     ____  _    ______        __     ____         __                  ____
+ *   /  |/  /_ __/ / /_(_)__/_  __/__ ____/ /    / __/_ _____ / /____ __ _  ___   /  _/__  ____
+ *  / /|_/ / // / / __/ /___// / / -_) __/ _ \  _\ \/ // (_-</ __/ -_)  ' \(_-<  _/ // _ \/ __/ __
+ * /_/  /_/\_,_/_/\__/_/    /_/  \__/\__/_//_/ /___/\_, /___/\__/\__/_/_/_/___/ /___/_//_/\__/ /_/
+ * Copyright (C) 2015 by Multi-Tech Systems        /___/
+ *
+ *
+ * @author Mike Fiore
+ * @date   5-16-2017
+ * @brief  lora::ChannelPlan provides an interface for LoRaWAN channel schemes
+ *
+ * @details
+ *
+ */
+
+#ifndef __CHANNEL_PLAN_AS923_JAPAN_H__
+#define __CHANNEL_PLAN_AS923_JAPAN_H__
+
+#include "ChannelPlan_AS923.h"
+
+namespace lora {
+
+    class ChannelPlan_AS923_Japan: public lora::ChannelPlan_AS923 {
+        public:
+            /**
+             * ChannelPlan constructor
+             * @param radio SxRadio object used to set Tx/Rx config
+             * @param settings Settings object
+             */
+            ChannelPlan_AS923_Japan();
+            ChannelPlan_AS923_Japan(Settings* settings);
+            ChannelPlan_AS923_Japan(SxRadio* radio, Settings* settings);
+
+            /**
+             * ChannelPlan destructor
+             */
+            virtual ~ChannelPlan_AS923_Japan();
+
+            /**
+             * Initialize channels, datarates and duty cycle bands according to current channel plan in settings
+             */
+            virtual void Init();
+
+            /**
+             * Set LBT time and threshold to defaults
+             */
+            virtual void DefaultLBT();
+    };
+}
+
+#endif //__CHANNEL_PLAN_AS923JAPAN_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/Lora/ChannelPlans/ChannelPlan_AU915.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,261 @@
+/**   __  ___     ____  _    ______        __     ____         __                  ____
+ *   /  |/  /_ __/ / /_(_)__/_  __/__ ____/ /    / __/_ _____ / /____ __ _  ___   /  _/__  ____
+ *  / /|_/ / // / / __/ /___// / / -_) __/ _ \  _\ \/ // (_-</ __/ -_)  ' \(_-<  _/ // _ \/ __/ __
+ * /_/  /_/\_,_/_/\__/_/    /_/  \__/\__/_//_/ /___/\_, /___/\__/\__/_/_/_/___/ /___/_//_/\__/ /_/
+ * Copyright (C) 2015 by Multi-Tech Systems        /___/
+ *
+ *
+ * @author Jason Reiss
+ * @date   10-31-2015
+ * @brief  lora::ChannelPlan provides an interface for LoRaWAN channel schemes
+ *
+ * @details
+ *
+ */
+
+#ifndef __CHANNEL_PLAN_AU915_H__
+#define __CHANNEL_PLAN_AU915_H__
+
+#include "Lora.h"
+#include "SxRadio.h"
+#include "ChannelPlan.h"
+#include <vector>
+
+namespace lora {
+
+    class ChannelPlan_AU915 : public lora::ChannelPlan {
+        public:
+
+            /**
+             * ChannelPlan constructor
+             * @param radio SxRadio object used to set Tx/Rx config
+             * @param settings Settings object
+             */
+            ChannelPlan_AU915();
+            ChannelPlan_AU915(Settings* settings);
+            ChannelPlan_AU915(SxRadio* radio, Settings* settings);
+
+            /**
+             * ChannelPlan destructor
+             */
+            virtual ~ChannelPlan_AU915();
+
+            /**
+             * Initialize channels, datarates and duty cycle bands according to current channel plan in settings
+             */
+            virtual void Init();
+
+            /**
+             * Get the next channel to use to transmit
+             * @return LORA_OK if channel was found
+             * @return LORA_NO_CHANS_ENABLED
+             */
+            virtual uint8_t GetNextChannel();
+
+            /**
+             * Set the number of channels in the plan
+             */
+            virtual void SetNumberOfChannels(uint8_t channels, bool resize = true);
+
+            /**
+             * Check if channel is enabled
+             * @return true if enabled
+             */
+            virtual bool IsChannelEnabled(uint8_t channel);
+
+
+            /**
+             * Add a channel to the ChannelPlan
+             * @param index of channel, use -1 to add to end
+             * @param channel settings to add
+             */
+            virtual uint8_t AddChannel(int8_t index, Channel channel);
+
+            /**
+             * Get channel at index
+             * @return Channel
+             */
+            virtual Channel GetChannel(int8_t index);
+
+            /**
+             * Get rx window settings for requested window
+             * RX_1, RX_2, RX_BEACON, RX_SLOT
+             * @param window
+             * @return RxWindow
+             */
+            virtual RxWindow GetRxWindow(uint8_t window);
+
+            /**
+             * Get datarate to use on the join request
+             * @return datarate index
+             */
+            virtual uint8_t GetJoinDatarate();
+
+            /**
+             * Calculate the next time a join request is possible
+             * @param size of join frame
+             * @returns LORA_OK
+             */
+            virtual uint8_t CalculateJoinBackoff(uint8_t size);
+
+            /**
+             * Set the datarate offset used for first receive window
+             * @param offset
+             * @return LORA_OK
+             */
+            virtual uint8_t SetRx1Offset(uint8_t offset);
+
+            /**
+             * Set the frequency for second receive window
+             * @param freq
+             * @return LORA_OK
+             */
+            virtual uint8_t SetRx2Frequency(uint32_t freq);
+
+            /**
+             * Set the datarate index used for second receive window
+             * @param index
+             * @return LORA_OK
+             */
+            virtual uint8_t SetRx2DatarateIndex(uint8_t index);
+
+            /**
+             * Get next channel and set the SxRadio tx config with current settings
+             * @return LORA_OK
+             */
+            virtual uint8_t SetTxConfig();
+
+            /**
+             * Set the SxRadio rx config provided window
+             * @param window to be opened
+             * @param continuous keep window open
+             * @return LORA_OK
+             */
+            virtual uint8_t SetRxConfig(uint8_t window, bool continuous);
+
+            /**
+             * Set frequency sub band if supported by plan
+             * @param sub_band
+             * @return LORA_OK
+             */
+            virtual uint8_t SetFrequencySubBand(uint8_t sub_band);
+
+            /**
+             * Callback for Join Accept packet to load optional channels
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleJoinAccept(const uint8_t* buffer, uint8_t size);
+
+            /**
+             * Callback to for rx parameter setup ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleRxParamSetup(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Callback to for new channel ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleNewChannel(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Callback to for downlink channel request ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleDownlinkChannelReq(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Callback to for ping slot channel request ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandlePingSlotChannelReq(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Callback to for beacon frequency request ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleBeaconFrequencyReq(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Callback to for adaptive datarate ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleAdrCommand(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Validate the configuration after multiple ADR commands have been applied
+             * @return status to be returned in MoteCommand answer
+             */
+            virtual uint8_t ValidateAdrConfiguration();
+
+            /**
+             * Get the time the radio must be off air to comply with regulations
+             * Time to wait may be dependent on duty-cycle restrictions per channel
+             * Or duty-cycle of join requests if OTAA is being attempted
+             * @return ms of time to wait for next tx opportunity
+             */
+            virtual uint32_t GetTimeOffAir();
+
+            /**
+             * Get the channels in use by current channel plan
+             * @return channel frequencies
+             */
+            virtual std::vector<uint32_t> GetChannels();
+
+            /**
+             * Get the channel datarate ranges in use by current channel plan
+             * @return channel datarate ranges
+             */
+            virtual std::vector<uint8_t> GetChannelRanges();
+
+
+            /**
+             * Print log message for given rx window
+             * @param wnd 1 or 2
+             */
+            virtual void LogRxWindow(uint8_t wnd);
+
+            /**
+             * Enable the default channels of the channel plan
+             */
+            virtual void EnableDefaultChannels();
+
+            virtual uint8_t GetMinDatarate();
+
+            virtual uint8_t GetMaxDatarate();
+
+        protected:
+
+            static const uint8_t AU915_TX_POWERS[11];                   //!< List of available tx powers
+            static const uint8_t AU915_RADIO_POWERS[21];                //!< List of calibrated tx powers
+            static const uint8_t AU915_MAX_PAYLOAD_SIZE[];              //!< List of max payload sizes for each datarate
+            static const uint8_t AU915_MAX_PAYLOAD_SIZE_REPEATER[];     //!< List of repeater compatible max payload sizes for each datarate
+
+    };
+}
+
+#endif // __CHANNEL_PLAN_AU915_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/Lora/ChannelPlans/ChannelPlan_EU868.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,230 @@
+/**   __  ___     ____  _    ______        __     ____         __                  ____
+ *   /  |/  /_ __/ / /_(_)__/_  __/__ ____/ /    / __/_ _____ / /____ __ _  ___   /  _/__  ____
+ *  / /|_/ / // / / __/ /___// / / -_) __/ _ \  _\ \/ // (_-</ __/ -_)  ' \(_-<  _/ // _ \/ __/ __
+ * /_/  /_/\_,_/_/\__/_/    /_/  \__/\__/_//_/ /___/\_, /___/\__/\__/_/_/_/___/ /___/_//_/\__/ /_/
+ * Copyright (C) 2015 by Multi-Tech Systems        /___/
+ *
+ *
+ * @author Jason Reiss
+ * @date   10-31-2015
+ * @brief  lora::ChannelPlan provides an interface for LoRaWAN channel schemes
+ *
+ * @details
+ *
+ */
+
+#ifndef __CHANNEL_PLAN_EU868_H__
+#define __CHANNEL_PLAN_EU868_H__
+
+#include "Lora.h"
+#include "SxRadio.h"
+#include <vector>
+#include "ChannelPlan.h"
+
+namespace lora {
+
+    class ChannelPlan_EU868 : public lora::ChannelPlan {
+        public:
+            /**
+             * ChannelPlan constructor
+             * @param radio SxRadio object used to set Tx/Rx config
+             * @param settings Settings object
+             */
+            ChannelPlan_EU868();
+            ChannelPlan_EU868(Settings* settings);
+            ChannelPlan_EU868(SxRadio* radio, Settings* settings);
+
+            /**
+             * ChannelPlan destructor
+             */
+            virtual ~ChannelPlan_EU868();
+
+            /**
+             * Initialize channels, datarates and duty cycle bands according to current channel plan in settings
+             */
+            virtual void Init();
+
+            /**
+             * Get the next channel to use to transmit
+             * @return LORA_OK if channel was found
+             * @return LORA_NO_CHANS_ENABLED
+             */
+            virtual uint8_t GetNextChannel();
+
+            /**
+             * Add a channel to the ChannelPlan
+             * @param index of channel, use -1 to add to end
+             * @param channel settings to add
+             */
+            virtual uint8_t AddChannel(int8_t index, Channel channel);
+
+            /**
+             * Get channel at index
+             * @return Channel
+             */
+            virtual Channel GetChannel(int8_t index);
+
+            /**
+             * Get rx window settings for requested window
+             * RX_1, RX_2, RX_BEACON, RX_SLOT
+             * @param window
+             * @return RxWindow
+             */
+            virtual RxWindow GetRxWindow(uint8_t window);
+
+            /**
+             * Get datarate to use on the join request
+             * @return datarate index
+             */
+            virtual uint8_t GetJoinDatarate();
+
+            /**
+             * Calculate the next time a join request is possible
+             * @param size of join frame
+             * @returns LORA_OK
+             */
+            virtual uint8_t CalculateJoinBackoff(uint8_t size);
+
+            /**
+             * Get next channel and set the SxRadio tx config with current settings
+             * @return LORA_OK
+             */
+            virtual uint8_t SetTxConfig();
+
+            /**
+             * Set the SxRadio rx config provided window
+             * @param window to be opened
+             * @param continuous keep window open
+             * @return LORA_OK
+             */
+            virtual uint8_t SetRxConfig(uint8_t window, bool continuous);
+
+            /**
+             * Set frequency sub band if supported by plan
+             * @param sub_band
+             * @return LORA_OK
+             */
+            virtual uint8_t SetFrequencySubBand(uint8_t sub_band);
+
+            /**
+             * Get time on air with current settings
+             * @param bytes number of bytes to be sent
+             */
+            virtual uint32_t GetTimeOnAir(uint8_t bytes);
+
+            /**
+             * Callback for ACK timeout event
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleAckTimeout();
+
+            /**
+             * Callback for Join Accept packet to load optional channels
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleJoinAccept(const uint8_t* buffer, uint8_t size);
+
+            /**
+             * Callback to for rx parameter setup ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleRxParamSetup(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Callback to for new channel ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleNewChannel(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Callback to for ping slot channel request ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandlePingSlotChannelReq(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Callback to for beacon frequency request ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleBeaconFrequencyReq(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Callback to for adaptive datarate ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleAdrCommand(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Validate the configuration after multiple ADR commands have been applied
+             * @return status to be returned in MoteCommand answer
+             */
+            virtual uint8_t ValidateAdrConfiguration();
+
+            /**
+             * Update duty cycle with at given frequency and time on air
+             * @param freq frequency
+             * @param time_on_air_ms tx time on air
+             */
+            virtual void UpdateDutyCycle(uint32_t freq, uint32_t time_on_air_ms);
+
+            /**
+             * Get the time the radio must be off air to comply with regulations
+             * Time to wait may be dependent on duty-cycle restrictions per channel
+             * Or duty-cycle of join requests if OTAA is being attempted
+             * @return ms of time to wait for next tx opportunity
+             */
+            virtual uint32_t GetTimeOffAir();
+
+            /**
+             * Get the channels in use by current channel plan
+             * @return channel frequencies
+             */
+            virtual std::vector<uint32_t> GetChannels();
+
+            /**
+             * Get the channel datarate ranges in use by current channel plan
+             * @return channel datarate ranges
+             */
+            virtual std::vector<uint8_t> GetChannelRanges();
+
+            /**
+             * Print log message for given rx window
+             * @param wnd 1 or 2
+             */
+            virtual void LogRxWindow(uint8_t wnd);
+
+            /**
+             * Enable the default channels of the channel plan
+             */
+            virtual void EnableDefaultChannels();
+
+        protected:
+
+            static const uint8_t EU868_TX_POWERS[8];                    //!< List of available tx powers
+            static const uint8_t EU868_RADIO_POWERS[21];                 //!< List of calibrated tx powers
+            static const uint8_t EU868_MAX_PAYLOAD_SIZE[];              //!< List of max payload sizes for each datarate
+            static const uint8_t EU868_MAX_PAYLOAD_SIZE_REPEATER[];     //!< List of repeater compatible max payload sizes for each datarate
+    };
+}
+
+#endif //__CHANNEL_PLAN_EU868_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/Lora/ChannelPlans/ChannelPlan_IN865.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,241 @@
+/**   __  ___     ____  _    ______        __     ____         __                  ____
+ *   /  |/  /_ __/ / /_(_)__/_  __/__ ____/ /    / __/_ _____ / /____ __ _  ___   /  _/__  ____
+ *  / /|_/ / // / / __/ /___// / / -_) __/ _ \  _\ \/ // (_-</ __/ -_)  ' \(_-<  _/ // _ \/ __/ __
+ * /_/  /_/\_,_/_/\__/_/    /_/  \__/\__/_//_/ /___/\_, /___/\__/\__/_/_/_/___/ /___/_//_/\__/ /_/
+ * Copyright (C) 2015 by Multi-Tech Systems        /___/
+ *
+ *
+ * @author Jason Reiss
+ * @date   10-31-2015
+ * @brief  lora::ChannelPlan provides an interface for LoRaWAN channel schemes
+ *
+ * @details
+ *
+ */
+
+#ifndef __CHANNEL_PLAN_IN865_H__
+#define __CHANNEL_PLAN_IN865_H__
+
+#include "Lora.h"
+#include "SxRadio.h"
+#include <vector>
+#include "ChannelPlan.h"
+
+namespace lora {
+
+    class ChannelPlan_IN865 : public lora::ChannelPlan {
+        public:
+            /**
+             * ChannelPlan constructor
+             * @param radio SxRadio object used to set Tx/Rx config
+             * @param settings Settings object
+             */
+            ChannelPlan_IN865();
+            ChannelPlan_IN865(Settings* settings);
+            ChannelPlan_IN865(SxRadio* radio, Settings* settings);
+
+            /**
+             * ChannelPlan destructor
+             */
+            virtual ~ChannelPlan_IN865();
+
+            /**
+             * Initialize channels, datarates and duty cycle bands according to current channel plan in settings
+             */
+            virtual void Init();
+
+            /**
+             * Get the next channel to use to transmit
+             * @return LORA_OK if channel was found
+             * @return LORA_NO_CHANS_ENABLED
+             */
+            virtual uint8_t GetNextChannel();
+
+            /**
+             * Add a channel to the ChannelPlan
+             * @param index of channel, use -1 to add to end
+             * @param channel settings to add
+             */
+            virtual uint8_t AddChannel(int8_t index, Channel channel);
+
+            /**
+             * Get channel at index
+             * @return Channel
+             */
+            virtual Channel GetChannel(int8_t index);
+
+            /**
+             * Get rx window settings for requested window
+             * RX_1, RX_2, RX_BEACON, RX_SLOT
+             * @param window
+             * @return RxWindow
+             */
+            virtual RxWindow GetRxWindow(uint8_t window);
+
+            /**
+             * Get datarate to use on the join request
+             * @return datarate index
+             */
+            virtual uint8_t GetJoinDatarate();
+
+            /**
+             * Calculate the next time a join request is possible
+             * @param size of join frame
+             * @returns LORA_OK
+             */
+            virtual uint8_t CalculateJoinBackoff(uint8_t size);
+
+            /**
+             * Get next channel and set the SxRadio tx config with current settings
+             * @return LORA_OK
+             */
+            virtual uint8_t SetTxConfig();
+
+            /**
+             * Set the SxRadio rx config provided window
+             * @param window to be opened
+             * @param continuous keep window open
+             * @return LORA_OK
+             */
+            virtual uint8_t SetRxConfig(uint8_t window, bool continuous);
+
+            /**
+             * Set frequency sub band if supported by plan
+             * @param sub_band
+             * @return LORA_OK
+             */
+            virtual uint8_t SetFrequencySubBand(uint8_t sub_band);
+
+            /**
+             * Callback for ACK timeout event
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleAckTimeout();
+
+            /**
+             * Callback for Join Accept packet to load optional channels
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleJoinAccept(const uint8_t* buffer, uint8_t size);
+
+            /**
+             * Callback to for rx parameter setup ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleRxParamSetup(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Callback to for new channel ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleNewChannel(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Callback to for ping slot channel request ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandlePingSlotChannelReq(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Callback to for beacon frequency request ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleBeaconFrequencyReq(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Callback to for adaptive datarate ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleAdrCommand(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Validate the configuration after multiple ADR commands have been applied
+             * @return status to be returned in MoteCommand answer
+             */
+            virtual uint8_t ValidateAdrConfiguration();
+
+            /**
+             * Update duty cycle with at given frequency and time on air
+             * @param freq frequency
+             * @param time_on_air_ms tx time on air
+             */
+            virtual void UpdateDutyCycle(uint32_t freq, uint32_t time_on_air_ms);
+
+            /**
+             * Get the time the radio must be off air to comply with regulations
+             * Time to wait may be dependent on duty-cycle restrictions per channel
+             * Or duty-cycle of join requests if OTAA is being attempted
+             * @return ms of time to wait for next tx opportunity
+             */
+            virtual uint32_t GetTimeOffAir();
+
+            /**
+             * Get the channels in use by current channel plan
+             * @return channel frequencies
+             */
+            virtual std::vector<uint32_t> GetChannels();
+
+            /**
+             * Get the channel datarate ranges in use by current channel plan
+             * @return channel datarate ranges
+             */
+            virtual std::vector<uint8_t> GetChannelRanges();
+
+            /**
+             * Print log message for given rx window
+             * @param wnd 1 or 2
+             */
+            virtual void LogRxWindow(uint8_t wnd);
+
+            /**
+             * Enable the default channels of the channel plan
+             */
+            virtual void EnableDefaultChannels();
+
+            /**
+             * Called when MAC layer doesn't know about a command.
+             * Use to add custom or new mac command handling
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleMacCommand(uint8_t* payload, uint8_t& index);
+
+            /**
+             *Decrements the datarate based on TxDwellTime
+             */
+            virtual void DecrementDatarate();
+
+            /**
+             *Decrements the datarate based on TxDwellTime
+             */
+            virtual void IncrementDatarate();
+
+        protected:
+
+            static const uint8_t IN865_TX_POWERS[11];                    //!< List of available tx powers
+            static const uint8_t IN865_RADIO_POWERS[21];                 //!< List of calibrated tx powers
+            static const uint8_t IN865_MAX_PAYLOAD_SIZE[];              //!< List of max payload sizes for each datarate
+            static const uint8_t IN865_MAX_PAYLOAD_SIZE_REPEATER[];     //!< List of repeater compatible max payload sizes for each datarate
+    };
+}
+
+#endif //__CHANNEL_PLAN_IN865_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/Lora/ChannelPlans/ChannelPlan_KR920.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,236 @@
+/**   __  ___     ____  _    ______        __     ____         __                  ____
+ *   /  |/  /_ __/ / /_(_)__/_  __/__ ____/ /    / __/_ _____ / /____ __ _  ___   /  _/__  ____
+ *  / /|_/ / // / / __/ /___// / / -_) __/ _ \  _\ \/ // (_-</ __/ -_)  ' \(_-<  _/ // _ \/ __/ __
+ * /_/  /_/\_,_/_/\__/_/    /_/  \__/\__/_//_/ /___/\_, /___/\__/\__/_/_/_/___/ /___/_//_/\__/ /_/
+ * Copyright (C) 2015 by Multi-Tech Systems        /___/
+ *
+ *
+ * @author Jason Reiss
+ * @date   10-31-2015
+ * @brief  lora::ChannelPlan provides an interface for LoRaWAN channel schemes
+ *
+ * @details
+ *
+ */
+
+#ifndef __CHANNEL_PLAN_KR920_H__
+#define __CHANNEL_PLAN_KR920_H__
+
+#include "Lora.h"
+#include "SxRadio.h"
+#include <vector>
+#include "ChannelPlan.h"
+
+namespace lora {
+
+    class ChannelPlan_KR920 : public lora::ChannelPlan {
+        public:
+            /**
+             * ChannelPlan constructor
+             * @param radio SxRadio object used to set Tx/Rx config
+             * @param settings Settings object
+             */
+            ChannelPlan_KR920();
+            ChannelPlan_KR920(Settings* settings);
+            ChannelPlan_KR920(SxRadio* radio, Settings* settings);
+
+            /**
+             * ChannelPlan destructor
+             */
+            virtual ~ChannelPlan_KR920();
+
+            /**
+             * Initialize channels, datarates and duty cycle bands according to current channel plan in settings
+             */
+            virtual void Init();
+
+            /**
+             * Get the next channel to use to transmit
+             * @return LORA_OK if channel was found
+             * @return LORA_NO_CHANS_ENABLED
+             */
+            virtual uint8_t GetNextChannel();
+
+            /**
+             * Add a channel to the ChannelPlan
+             * @param index of channel, use -1 to add to end
+             * @param channel settings to add
+             */
+            virtual uint8_t AddChannel(int8_t index, Channel channel);
+
+            /**
+             * Get channel at index
+             * @return Channel
+             */
+            virtual Channel GetChannel(int8_t index);
+
+            /**
+             * Get rx window settings for requested window
+             * RX_1, RX_2, RX_BEACON, RX_SLOT
+             * @param window
+             * @return RxWindow
+             */
+            virtual RxWindow GetRxWindow(uint8_t window);
+
+            /**
+             * Get datarate to use on the join request
+             * @return datarate index
+             */
+            virtual uint8_t GetJoinDatarate();
+
+            /**
+             * Calculate the next time a join request is possible
+             * @param size of join frame
+             * @returns LORA_OK
+             */
+            virtual uint8_t CalculateJoinBackoff(uint8_t size);
+
+            /**
+             * Get next channel and set the SxRadio tx config with current settings
+             * @return LORA_OK
+             */
+            virtual uint8_t SetTxConfig();
+
+            /**
+             * Set the SxRadio rx config provided window
+             * @param window to be opened
+             * @param continuous keep window open
+             * @return LORA_OK
+             */
+            virtual uint8_t SetRxConfig(uint8_t window, bool continuous);
+
+            /**
+             * Set frequency sub band if supported by plan
+             * @param sub_band
+             * @return LORA_OK
+             */
+            virtual uint8_t SetFrequencySubBand(uint8_t sub_band);
+
+            /**
+             * Callback for ACK timeout event
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleAckTimeout();
+
+            /**
+             * Callback for Join Accept packet to load optional channels
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleJoinAccept(const uint8_t* buffer, uint8_t size);
+
+            /**
+             * Callback to for rx parameter setup ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleRxParamSetup(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Callback to for new channel ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleNewChannel(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Callback to for ping slot channel request ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandlePingSlotChannelReq(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Callback to for beacon frequency request ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleBeaconFrequencyReq(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Callback to for adaptive datarate ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleAdrCommand(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Validate the configuration after multiple ADR commands have been applied
+             * @return status to be returned in MoteCommand answer
+             */
+            virtual uint8_t ValidateAdrConfiguration();
+
+            /**
+             * Update duty cycle with at given frequency and time on air
+             * @param freq frequency
+             * @param time_on_air_ms tx time on air
+             */
+            virtual void UpdateDutyCycle(uint32_t freq, uint32_t time_on_air_ms);
+
+            /**
+             * Get the time the radio must be off air to comply with regulations
+             * Time to wait may be dependent on duty-cycle restrictions per channel
+             * Or duty-cycle of join requests if OTAA is being attempted
+             * @return ms of time to wait for next tx opportunity
+             */
+            virtual uint32_t GetTimeOffAir();
+
+            /**
+             * Get the channels in use by current channel plan
+             * @return channel frequencies
+             */
+            virtual std::vector<uint32_t> GetChannels();
+
+            /**
+             * Get the channel datarate ranges in use by current channel plan
+             * @return channel datarate ranges
+             */
+            virtual std::vector<uint8_t> GetChannelRanges();
+
+            /**
+             * Print log message for given rx window
+             * @param wnd 1 or 2
+             */
+            virtual void LogRxWindow(uint8_t wnd);
+
+            /**
+             * Enable the default channels of the channel plan
+             */
+            virtual void EnableDefaultChannels();
+
+            /**
+             * Called when MAC layer doesn't know about a command.
+             * Use to add custom or new mac command handling
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleMacCommand(uint8_t* payload, uint8_t& index);
+
+            /**
+             * Set LBT time and threshold to defaults
+             */
+            virtual void DefaultLBT();
+
+        protected:
+
+            static const uint8_t KR920_TX_POWERS[8];                    //!< List of available tx powers
+            static const uint8_t KR920_RADIO_POWERS[21];                 //!< List of calibrated tx powers
+            static const uint8_t KR920_MAX_PAYLOAD_SIZE[];              //!< List of max payload sizes for each datarate
+            static const uint8_t KR920_MAX_PAYLOAD_SIZE_REPEATER[];     //!< List of repeater compatible max payload sizes for each datarate
+    };
+}
+
+#endif //__CHANNEL_PLAN_KR920_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/Lora/ChannelPlans/ChannelPlan_US915.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,261 @@
+/**   __  ___     ____  _    ______        __     ____         __                  ____
+ *   /  |/  /_ __/ / /_(_)__/_  __/__ ____/ /    / __/_ _____ / /____ __ _  ___   /  _/__  ____
+ *  / /|_/ / // / / __/ /___// / / -_) __/ _ \  _\ \/ // (_-</ __/ -_)  ' \(_-<  _/ // _ \/ __/ __
+ * /_/  /_/\_,_/_/\__/_/    /_/  \__/\__/_//_/ /___/\_, /___/\__/\__/_/_/_/___/ /___/_//_/\__/ /_/
+ * Copyright (C) 2015 by Multi-Tech Systems        /___/
+ *
+ *
+ * @author Jason Reiss
+ * @date   10-31-2015
+ * @brief  lora::ChannelPlan provides an interface for LoRaWAN channel schemes
+ *
+ * @details
+ *
+ */
+
+#ifndef __CHANNEL_PLAN_US915_H__
+#define __CHANNEL_PLAN_US915_H__
+
+#include "Lora.h"
+#include "SxRadio.h"
+#include "ChannelPlan.h"
+#include <vector>
+
+namespace lora {
+
+    class ChannelPlan_US915 : public lora::ChannelPlan {
+        public:
+
+            /**
+             * ChannelPlan constructor
+             * @param radio SxRadio object used to set Tx/Rx config
+             * @param settings Settings object
+             */
+            ChannelPlan_US915();
+            ChannelPlan_US915(Settings* settings);
+            ChannelPlan_US915(SxRadio* radio, Settings* settings);
+
+            /**
+             * ChannelPlan destructor
+             */
+            virtual ~ChannelPlan_US915();
+
+            /**
+             * Initialize channels, datarates and duty cycle bands according to current channel plan in settings
+             */
+            virtual void Init();
+
+            /**
+             * Get the next channel to use to transmit
+             * @return LORA_OK if channel was found
+             * @return LORA_NO_CHANS_ENABLED
+             */
+            virtual uint8_t GetNextChannel();
+
+            /**
+             * Set the number of channels in the plan
+             */
+            virtual void SetNumberOfChannels(uint8_t channels, bool resize = true);
+
+            /**
+             * Check if channel is enabled
+             * @return true if enabled
+             */
+            virtual bool IsChannelEnabled(uint8_t channel);
+
+
+            /**
+             * Add a channel to the ChannelPlan
+             * @param index of channel, use -1 to add to end
+             * @param channel settings to add
+             */
+            virtual uint8_t AddChannel(int8_t index, Channel channel);
+
+            /**
+             * Get channel at index
+             * @return Channel
+             */
+            virtual Channel GetChannel(int8_t index);
+
+            /**
+             * Get rx window settings for requested window
+             * RX_1, RX_2, RX_BEACON, RX_SLOT
+             * @param window
+             * @return RxWindow
+             */
+            virtual RxWindow GetRxWindow(uint8_t window);
+
+            /**
+             * Get datarate to use on the join request
+             * @return datarate index
+             */
+            virtual uint8_t GetJoinDatarate();
+
+            /**
+             * Calculate the next time a join request is possible
+             * @param size of join frame
+             * @returns LORA_OK
+             */
+            virtual uint8_t CalculateJoinBackoff(uint8_t size);
+
+            /**
+             * Set the datarate offset used for first receive window
+             * @param offset
+             * @return LORA_OK
+             */
+            virtual uint8_t SetRx1Offset(uint8_t offset);
+
+            /**
+             * Set the frequency for second receive window
+             * @param freq
+             * @return LORA_OK
+             */
+            virtual uint8_t SetRx2Frequency(uint32_t freq);
+
+            /**
+             * Set the datarate index used for second receive window
+             * @param index
+             * @return LORA_OK
+             */
+            virtual uint8_t SetRx2DatarateIndex(uint8_t index);
+
+            /**
+             * Get next channel and set the SxRadio tx config with current settings
+             * @return LORA_OK
+             */
+            virtual uint8_t SetTxConfig();
+
+            /**
+             * Set the SxRadio rx config provided window
+             * @param window to be opened
+             * @param continuous keep window open
+             * @return LORA_OK
+             */
+            virtual uint8_t SetRxConfig(uint8_t window, bool continuous);
+
+            /**
+             * Set frequency sub band if supported by plan
+             * @param sub_band
+             * @return LORA_OK
+             */
+            virtual uint8_t SetFrequencySubBand(uint8_t sub_band);
+
+            /**
+             * Callback for Join Accept packet to load optional channels
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleJoinAccept(const uint8_t* buffer, uint8_t size);
+
+            /**
+             * Callback to for rx parameter setup ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleRxParamSetup(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Callback to for new channel ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleNewChannel(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Callback to for downlink channel request ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleDownlinkChannelReq(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Callback to for ping slot channel request ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandlePingSlotChannelReq(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Callback to for beacon frequency request ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleBeaconFrequencyReq(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Callback to for adaptive datarate ServerCommand
+             * @param payload packet data
+             * @param index of start of command buffer
+             * @param size number of bytes in command buffer
+             * @param[out] status to be returned in MoteCommand answer
+             * @return LORA_OK
+             */
+            virtual uint8_t HandleAdrCommand(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status);
+
+            /**
+             * Validate the configuration after multiple ADR commands have been applied
+             * @return status to be returned in MoteCommand answer
+             */
+            virtual uint8_t ValidateAdrConfiguration();
+
+            /**
+             * Get the time the radio must be off air to comply with regulations
+             * Time to wait may be dependent on duty-cycle restrictions per channel
+             * Or duty-cycle of join requests if OTAA is being attempted
+             * @return ms of time to wait for next tx opportunity
+             */
+            virtual uint32_t GetTimeOffAir();
+
+            /**
+             * Get the channels in use by current channel plan
+             * @return channel frequencies
+             */
+            virtual std::vector<uint32_t> GetChannels();
+
+            /**
+             * Get the channel datarate ranges in use by current channel plan
+             * @return channel datarate ranges
+             */
+            virtual std::vector<uint8_t> GetChannelRanges();
+
+
+            /**
+             * Print log message for given rx window
+             * @param wnd 1 or 2
+             */
+            virtual void LogRxWindow(uint8_t wnd);
+
+            /**
+             * Enable the default channels of the channel plan
+             */
+            virtual void EnableDefaultChannels();
+
+            virtual uint8_t GetMinDatarate();
+
+            virtual uint8_t GetMaxDatarate();
+
+        protected:
+
+            static const uint8_t US915_TX_POWERS[11];                   //!< List of available tx powers
+            static const uint8_t US915_RADIO_POWERS[21];                //!< List of calibrated tx powers
+            static const uint8_t US915_MAX_PAYLOAD_SIZE[];              //!< List of max payload sizes for each datarate
+            static const uint8_t US915_MAX_PAYLOAD_SIZE_REPEATER[];     //!< List of repeater compatible max payload sizes for each datarate
+
+    };
+}
+
+#endif // __CHANNEL_PLAN_US915_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/Lora/ChannelPlans/ChannelPlans.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,16 @@
+#include "ChannelPlan_AS923.h"
+#include "ChannelPlan_AU915.h"
+#include "ChannelPlan_US915.h"
+#include "ChannelPlan_EU868.h"
+#include "ChannelPlan_KR920.h"
+#include "ChannelPlan_IN865.h"
+#include "ChannelPlan_AS923_Japan.h"
+
+
+#define CP_AS923 1
+#define CP_AU915 2
+#define CP_US915 3
+#define CP_EU868 4
+#define CP_KR920 5
+#define CP_IN865 6
+#define CP_AS923_JAPAN 7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/Lora/Crypto.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,153 @@
+/* ______                              _
+  / _____)             _              | |
+ ( (____  _____ ____ _| |_ _____  ____| |__
+  \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+  _____) ) ____| | | || |_| ____( (___| | | |
+ (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ (C)2013 Semtech
+
+ Description: LoRa MAC layer implementation
+
+ License: Revised BSD License, see LICENSE.TXT file include in the project
+
+ Maintainer: Miguel Luis and Gregory Cristian
+ */
+#ifndef __LORA_CRYPTO_H__
+#define __LORA_CRYPTO_H__
+
+#include "casado/aes.h"
+#include "gladman/cmac.h"
+#include <cstring>
+#include <inttypes.h>
+
+namespace lora {
+
+    class Crypto
+    {
+        public:
+            Crypto(void);
+
+            /*!
+             * Computes the LoRaMAC frame MIC field
+             *
+             * \param [IN]  buffer          Data buffer
+             * \param [IN]  size            Data buffer size
+             * \param [IN]  key             AES key to be used
+             * \param [IN]  address         Frame address
+             * \param [IN]  dir             Frame direction [0: uplink, 1: downlink, 2:peer]
+             * \param [IN]  sequenceCounter Frame sequence counter
+             * \param [OUT] mic             Computed MIC field
+             */
+            void ComputeMic(uint8_t *buffer, uint16_t size, uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint32_t *mic);
+
+            /*!
+             * Computes the LoRaMAC payload encryption
+             *
+             * \param [IN]  buffer          Data buffer
+             * \param [IN]  size            Data buffer size
+             * \param [IN]  key             AES key to be used
+             * \param [IN]  address         Frame address
+             * \param [IN]  dir             Frame direction [0: uplink, 1: downlink, 2:peer]
+             * \param [IN]  sequenceCounter Frame sequence counter
+             * \param [OUT] encBuffer       Encrypted buffer
+             */
+            void PayloadEncrypt(const uint8_t *buffer, uint16_t size, uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *encBuffer);
+
+            /*!
+             * Computes the LoRaMAC payload decryption
+             *
+             * \param [IN]  buffer          Data buffer
+             * \param [IN]  size            Data buffer size
+             * \param [IN]  key             AES key to be used
+             * \param [IN]  address         Frame address
+             * \param [IN]  dir             Frame direction [0: uplink, 1: downlink, 2:peer]
+             * \param [IN]  sequenceCounter Frame sequence counter
+             * \param [OUT] decBuffer       Decrypted buffer
+             */
+            void PayloadDecrypt(uint8_t *buffer, uint16_t size, uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *decBuffer);
+
+            /*!
+             * Computes the LoRaMAC Join Request frame MIC field
+             *
+             * \param [IN]  buffer          Data buffer
+             * \param [IN]  size            Data buffer size
+             * \param [IN]  key             AES key to be used
+             * \param [OUT] mic             Computed MIC field
+             */
+            void JoinComputeMic(const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t *mic);
+
+            /*!
+             * Computes the LoRaMAC join frame decryption
+             *
+             * \param [IN]  buffer          Data buffer
+             * \param [IN]  size            Data buffer size
+             * \param [IN]  key             AES key to be used
+             * \param [OUT] decBuffer       Decrypted buffer
+             */
+            void JoinDecrypt(uint8_t *buffer, uint16_t size, uint8_t *key, uint8_t *decBuffer);
+
+            /*!
+             * Computes the LoRaMAC join frame decryption
+             *
+             * \param [IN]  key             AES key to be used
+             * \param [IN]  appNonce        Application nonce
+             * \param [IN]  devNonce        Device nonce
+             * \param [OUT] nwkSKey         Network session key
+             * \param [OUT] appSKey         Application session key
+             */
+            void DeriveSessionKeys(uint8_t *key, uint8_t *appNonce, uint8_t *netID, uint16_t devNonce, uint8_t *nwkSKey, uint8_t *appSKey);
+
+            /*!
+             * Compute ping slot for current beacon frame
+             * \param [IN]  beaconTime     Time of current beacon
+             * \param [IN]  devAddr        Device Address
+             * \param [IN]  period         Period of downlink
+             * \return current pinslot
+             */
+            uint32_t ComputePingSlot(uint32_t beaconTime, uint32_t devAddr, uint32_t period);
+
+            /*!
+             * Helper to copy mic bytes onto buffer
+             * \param [IN]  mic         integer mic value
+             * \param [IN]  buff        location to copy to
+             */
+            void CopyMicToArray(uint32_t mic, uint8_t* buff);
+
+            void DeriveMcKEKey(uint8_t *mcKEKey, uint8_t *appKey, uint8_t *EUI);
+            
+            void DeriveMcKey(uint8_t *mcKey, uint8_t *mcKeyEncrypt, uint8_t *mcKEKey);
+
+            void DeriveMcSessionKeys(uint8_t *mcAppKey, uint8_t *mcNetKey, uint8_t *mcKey, uint8_t *mcAddr);
+
+        private:
+            /*!
+             * MIC field computation initial data
+             */
+            uint8_t MicBlockB0[16];
+
+            /*!
+             * Contains the computed MIC field.
+             *
+             * \remark Only the 4 first bytes are used
+             */
+            uint8_t Mic[16];
+
+            /*!
+             * Encryption aBlock and sBlock
+             */
+            uint8_t aBlock[16];
+            uint8_t sBlock[16];
+
+            /*!
+             * AES computation context variable
+             */
+            aes_context AesContext;
+
+            /*!
+             * CMAC computation context variable
+             */
+            AES_CMAC_CTX AesCmacCtx[1];
+    };
+
+}
+#endif // __LORAMAC_CRYPTO_H__
--- /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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/Lora/Lora.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,739 @@
+/**   __  ___     ____  _    ______        __     ____         __                  ____
+ *   /  |/  /_ __/ / /_(_)__/_  __/__ ____/ /    / __/_ _____ / /____ __ _  ___   /  _/__  ____
+ *  / /|_/ / // / / __/ /___// / / -_) __/ _ \  _\ \/ // (_-</ __/ -_)  ' \(_-<  _/ // _ \/ __/  __
+ * /_/  /_/\_,_/_/\__/_/    /_/  \__/\__/_//_/ /___/\_, /___/\__/\__/_/_/_/___/ /___/_//_/\__/  /_/
+ * Copyright (C) 2015 by Multi-Tech Systems        /___/
+ *
+ *
+ * @author Jason Reiss
+ * @date   10-31-2015
+ * @brief  lora namespace defines global settings, structures and enums for the lora library
+ *
+ * @details
+ *
+ *
+ *
+ */
+
+#ifndef __LORA_H__
+#define __LORA_H__
+
+#include "mbed.h"
+#include <assert.h>
+#include "MTSLog.h"
+//#include <cstring>
+#include <inttypes.h>
+
+namespace lora {
+
+    /**
+     * Frequency bandwidth of a Datarate, higher bandwidth gives higher datarate
+     */
+    enum Bandwidth {
+        BW_125,
+        BW_250,
+        BW_500,
+        BW_FSK = 50
+    };
+
+    /**
+     * Spreading factor of a Datarate, lower spreading factor gives higher datarate
+     */
+    enum SpreadingFactors {
+        SF_6 = 6,
+        SF_7,
+        SF_8,
+        SF_9,
+        SF_10,
+        SF_11,
+        SF_12,
+        SF_FSK,
+        SF_INVALID
+    };
+
+    /**
+     * Datarates for use with ChannelPlan
+     */
+    enum Datarates {
+        DR_0 = 0,
+        DR_1,
+        DR_2,
+        DR_3,
+        DR_4,
+        DR_5,
+        DR_6,
+        DR_7,
+        DR_8,
+        DR_9,
+        DR_10,
+        DR_11,
+        DR_12,
+        DR_13,
+        DR_14,
+        DR_15
+    };
+
+    const uint8_t MIN_DATARATE = (uint8_t) DR_0;             //!< Minimum datarate
+
+
+    const uint8_t MAX_PHY_PACKET_SIZE = 255;                    //!< Maximum size for a packet
+    const uint8_t MAX_APPS = 8;                                 //!< Maximum number of apps sessions to save
+    const uint8_t MAX_MULTICAST_SESSIONS = 8;                   //!< Maximum number of multicast sessions to save
+    const uint8_t EUI_SIZE = 8;                                 //!< Number of bytes in an EUI
+    const uint8_t KEY_SIZE = 16;                                //!< Number of bytes in an AES key
+
+    const uint8_t DEFAULT_NUM_CHANNELS = 16;                    //!< Default number of channels in a plan
+    const uint8_t DEFAULT_RX1_DR_OFFSET = 0;                    //!< Default datarate offset for first rx window
+    const uint8_t DEFAULT_RX2_DATARATE = 0;                     //!< Default datarate for second rx window
+    const uint8_t DEFAULT_TX_POWER = 14;                        //!< Default transmit power
+    const uint8_t DEFAULT_CODE_RATE = 1;                        //!< Default coding rate 1:4/5, 2:4/6, 3:4/7, 4:4/8
+    const uint8_t DEFAULT_PREAMBLE_LEN = 8;                     //!< Default preamble length
+
+    const int32_t MAX_FCNT_GAP = 16384;                         //!< Maximum allowed gap in sequence numbers before roll-over
+
+    const uint16_t PRIVATE_JOIN_DELAY = 1000;                   //!< Default join delay used for private network
+    const uint16_t PUBLIC_JOIN_DELAY = 5000;                    //!< Default join delay used for public network
+    const uint16_t DEFAULT_JOIN_DELAY = PRIVATE_JOIN_DELAY;     //!< Default join delay1
+    const uint16_t DEFAULT_RX_DELAY = 1000;                     //!< Default delay for first receive window
+    const uint16_t DEFAULT_RX_TIMEOUT = 3000;                   //!< Default timeout for receive windows
+
+    const uint8_t HI_DR_SYMBOL_TIMEOUT = 12;                    //!< Symbol timeout for receive at datarate with SF < 11
+    const uint8_t LO_DR_SYMBOL_TIMEOUT = 8;                     //!< Symbol timeout for receive at datarate with SF > 10
+
+    const uint16_t RX2_DELAY_OFFSET = 1000;                     //!< Delay between first and second window
+    const uint16_t RXC_OFFSET = 50;                             //!< Time between end of RXC after TX and RX1
+
+    const uint8_t US915_125K_NUM_CHANS = 64;                    //!< Number of 125k channels in US915 channel plan
+    const uint8_t US915_500K_NUM_CHANS = 8;                     //!< Number of 500k channels in US915 channel plan
+
+    const uint32_t US915_125K_FREQ_BASE = 902300000;            //!< Frequency base for 125k US915 uplink channels
+    const uint32_t US915_125K_FREQ_STEP = 200000;               //!< Frequency step for 125k US915 uplink channels
+
+    const uint32_t US915_500K_FREQ_BASE = 903000000;            //!< Frequency base for 500k US915 uplink channels
+    const uint32_t US915_500K_FREQ_STEP = 1600000;              //!< Frequency step for 500k US915 uplink channels
+
+    const uint32_t US915_500K_DBASE = 923300000;                //!< Frequency base for 500k US915 downlink channels
+    const uint32_t US915_500K_DSTEP = 600000;                   //!< Frequency step for 500k US915 downlink channels
+
+    const uint32_t US915_FREQ_MIN = 902000000;
+    const uint32_t US915_FREQ_MAX = 928000000;
+
+    const uint8_t US915_MIN_DATARATE = (uint8_t) DR_0;       //!< Minimum transmit datarate for US915
+    const uint8_t US915_MAX_DATARATE = (uint8_t) DR_4;       //!< Maximum transmit datarate for US915
+
+    const uint8_t US915_MIN_DATARATE_OFFSET = (uint8_t) 0;       //!< Minimum transmit datarate for US915
+    const uint8_t US915_MAX_DATARATE_OFFSET = (uint8_t) 3;       //!< Maximum transmit datarate for US915
+
+    const uint8_t AU915_125K_NUM_CHANS = 64;                    //!< Number of 125k channels in AU915 channel plan
+    const uint8_t AU915_500K_NUM_CHANS = 8;                     //!< Number of 500k channels in AU915 channel plan
+
+    const uint32_t AU915_125K_FREQ_BASE = 915200000;            //!< Frequency base for 125k AU915 uplink channels
+    const uint32_t AU915_125K_FREQ_STEP = 200000;               //!< Frequency step for 125k AU915 uplink channels
+
+    const uint32_t AU915_500K_FREQ_BASE = 915900000;            //!< Frequency base for 500k AU915 uplink channels
+    const uint32_t AU915_500K_FREQ_STEP = 1600000;              //!< Frequency step for 500k AU915 uplink channels
+
+    const uint32_t AU915_500K_DBASE = 923300000;                //!< Frequency base for 500k AU915 downlink channels
+    const uint32_t AU915_500K_DSTEP = 600000;                   //!< Frequency step for 500k AU915 downlink channels
+
+    const uint32_t AU915_FREQ_MIN = 915000000;
+    const uint32_t AU915_FREQ_MAX = 928000000;
+
+    const uint8_t AU915_MIN_DATARATE = (uint8_t) DR_0;       //!< Minimum transmit datarate for AU915
+    const uint8_t AU915_MAX_DATARATE = (uint8_t) DR_6;       //!< Maximum transmit datarate for AU915
+
+    const uint8_t AU915_MIN_DATARATE_OFFSET = (uint8_t) 0;       //!< Minimum transmit datarate for AU915
+    const uint8_t AU915_MAX_DATARATE_OFFSET = (uint8_t) 5;       //!< Maximum transmit datarate for AU915
+
+    const uint8_t EU868_125K_NUM_CHANS = 16;                    //!< Number of 125k channels in EU868 channel plan
+    const uint8_t EU868_DEFAULT_NUM_CHANS = 3;                  //!< Number of default channels in EU868 channel plan
+    const uint32_t EU868_125K_FREQ_BASE = 868100000;            //!< Frequency base for 125k EU868 uplink channels
+    const uint32_t EU868_125K_FREQ_STEP = 200000;               //!< Frequency step for 125k EU868 uplink channels
+    const uint32_t EU868_RX2_FREQ = 869525000;                  //!< Frequency default for second rx window in EU868
+
+    const uint8_t EU868_TX_POWER_MAX = 14;                      //!< Max power for EU868 channel plan
+
+    const uint8_t KR920_125K_NUM_CHANS = 16;                    //!< Number of 125k channels in KR920 channel plan
+    const uint8_t KR920_DEFAULT_NUM_CHANS = 3;                  //!< Number of default channels in KR920 channel plan
+    const uint32_t KR920_125K_FREQ_BASE = 868100000;            //!< Frequency base for 125k KR920 uplink channels
+    const uint32_t KR920_125K_FREQ_STEP = 200000;               //!< Frequency step for 125k KR920 uplink channels
+    const uint32_t KR920_RX2_FREQ = 869525000;                  //!< Frequency default for second rx window in KR920
+
+    const uint8_t KR920_TX_POWER_MAX = 14;                      //!< Max power for KR920 channel plan
+
+    const uint8_t AS923_125K_NUM_CHANS = 16;                    //!< Number of 125k channels in AS923 channel plan
+    const uint8_t AS923_DEFAULT_NUM_CHANS = 2;                  //!< Number of default channels in AS923 channel plan
+    const uint32_t AS923_125K_FREQ_BASE = 868100000;            //!< Frequency base for 125k AS923 uplink channels
+    const uint32_t AS923_125K_FREQ_STEP = 200000;               //!< Frequency step for 125k AS923 uplink channels
+    const uint32_t AS923_RX2_FREQ = 869525000;                  //!< Frequency default for second rx window in AS923
+
+    const uint8_t AS923_TX_POWER_MAX = 14;                      //!< Max power for AS923 channel plan
+
+    const uint8_t IN865_125K_NUM_CHANS = 16;                    //!< Number of 125k channels in IN865 channel plan
+    const uint8_t IN865_DEFAULT_NUM_CHANS = 3;                  //!< Number of default channels in IN865 channel plan
+    const uint32_t IN865_125K_DEF_FREQ_1 = 865062500;
+    const uint32_t IN865_125K_DEF_FREQ_2 = 865402500;
+    const uint32_t IN865_125K_DEF_FREQ_3 = 865985000;
+    const uint32_t IN865_RX2_FREQ = 866550000;                  //!< Frequency default for second rx window in IN865
+
+    const uint8_t IN865_TX_POWER_MAX = 30;                      //!< Max power for IN865 channel plan
+
+    // 0.1% duty cycle 863-868
+    // Limiting to 865-868 allows for 1% duty cycle
+    const uint32_t EU868_MILLI_FREQ_MIN = 865000000;
+    const uint32_t EU868_MILLI_FREQ_MAX = 868000000;
+
+    const uint32_t EU868_MILLI_1_FREQ_MIN = 868700000;
+    const uint32_t EU868_MILLI_1_FREQ_MAX = 869200000;
+
+    // 1% duty cycle
+    const uint32_t EU868_CENTI_FREQ_MIN = 868000000;
+    const uint32_t EU868_CENTI_FREQ_MAX = 868600000;
+
+    // 10% duty cycle
+    const uint32_t EU868_DECI_FREQ_MIN = 869400000;
+    const uint32_t EU868_DECI_FREQ_MAX = 869650000;
+
+    // Below 7dBm there is no duty cycle for these frequencies
+    // Up to 14dBm there is 1% duty cycle
+    const uint32_t EU868_VAR_FREQ_MIN = 869700000;
+    const uint32_t EU868_VAR_FREQ_MAX = 870000000;
+
+    const uint32_t EU868_FREQ_MIN = 863000000;
+    const uint32_t EU868_FREQ_MAX = 870000000;
+
+    const uint8_t EU868_MIN_DATARATE = (uint8_t) DR_0;       //!< Minimum transmit datarate for EU868
+    const uint8_t EU868_MAX_DATARATE = (uint8_t) DR_7;       //!< Maximum transmit datarate for EU868
+
+    const uint8_t EU868_MIN_DATARATE_OFFSET = (uint8_t) 0;       //!< Minimum transmit datarate for US915
+    const uint8_t EU868_MAX_DATARATE_OFFSET = (uint8_t) 5;       //!< Maximum transmit datarate for US915
+
+    const int16_t DEFAULT_FREE_CHAN_RSSI_THRESHOLD = -90;       //!< Threshold for channel activity detection (CAD) dBm
+
+    const uint8_t CHAN_MASK_SIZE = 16;                          //!< Number of bits in a channel mask
+    const uint8_t COMMANDS_BUFFER_SIZE = 15;                    //!< Size of Mac Command buffer
+
+    const uint8_t PKT_HEADER = 0;                               //!< Index to packet mHdr field
+    const uint8_t PKT_ADDRESS = 1;                              //!< Index to first byte of packet address field
+    const uint8_t PKT_FRAME_CONTROL = PKT_ADDRESS + 4;          //!< Index to packet fCtrl field @see UplinkControl
+    const uint8_t PKT_FRAME_COUNTER = PKT_FRAME_CONTROL + 1;    //!< Index to packet frame counter field
+    const uint8_t PKT_OPTIONS_START = PKT_FRAME_COUNTER + 2;    //!< Index to start of optional mac commands
+
+    const uint8_t PKT_JOIN_APP_NONCE = 1;                       //!< Index to application nonce in Join Accept message
+    const uint8_t PKT_JOIN_NETWORK_ID = 4;                      //!< Index to network id in Join Accept message
+    const uint8_t PKT_JOIN_NETWORK_ADDRESS = 7;                 //!< Index to network address in Join Accept message
+    const uint8_t PKT_JOIN_DL_SETTINGS = 11;                    //!< Index to downlink settings in Join Accept message
+    const uint8_t PKT_JOIN_RX_DELAY = 12;                       //!< Index to rx delay in Join Accept message
+
+    const uint8_t ADR_ACK_LIMIT = 64;                           //!< Number of packets without ADR ACK Request
+    const uint8_t ADR_ACK_DELAY = 32;                           //!< Number of packets to expect ADR ACK Response within
+
+    const uint16_t ACK_TIMEOUT = 2000;                          //!< Base millisecond timeout to resend after missed ACK
+    const uint16_t ACK_TIMEOUT_RND = 1000;                      //!< Random millisecond adjustment to resend after missed ACK
+
+    const uint8_t FRAME_OVERHEAD = 13;                          //!< Bytes of network info overhead in a frame
+
+    const uint16_t MAX_OFF_AIR_WAIT = 5000U;                    //!< Max time in ms to block for a duty cycle restriction to expire before erroring out
+    /**
+     * Settings for type of network
+     *
+     * PRIVATE_MTS - Sync Word 0x12, US/AU Downlink frequencies per Frequency Sub Band
+     * PUBLIC_LORAWAN - Sync Word 0x34
+     * PRIVATE_LORAWAN - Sync Word 0x12
+     * PEER_TO_PEER - Sync Word 0x56 used for Dot to Dot communication
+     *
+     * Join Delay window settings are independent of Network Type setting
+     */
+    enum NetworkType {
+        PRIVATE_MTS = 0,
+        PUBLIC_LORAWAN = 1,
+        PRIVATE_LORAWAN = 2,
+        PEER_TO_PEER = 4
+    };
+
+    /**
+     * Enum for on/off settings
+     */
+    enum Enabled {
+        OFF = 0,
+        ON = 1
+    };
+
+    /**
+     * Return status of mac functions
+     */
+    enum MacStatus {
+        LORA_OK = 0,
+        LORA_ERROR = 1,
+        LORA_JOIN_ERROR = 2,
+        LORA_SEND_ERROR = 3,
+        LORA_MIC_ERROR = 4,
+        LORA_ADDRESS_ERROR = 5,
+        LORA_NO_CHANS_ENABLED = 6,
+        LORA_COMMAND_BUFFER_FULL = 7,
+        LORA_UNKNOWN_MAC_COMMAND = 8,
+        LORA_ADR_OFF = 9,
+        LORA_BUSY = 10,
+        LORA_LINK_BUSY = 11,
+        LORA_RADIO_BUSY = 12,
+        LORA_BUFFER_FULL = 13,
+        LORA_JOIN_BACKOFF = 14,
+        LORA_NO_FREE_CHAN = 15,
+        LORA_AGGREGATED_DUTY_CYCLE = 16,
+        LORA_MAC_COMMAND_ERROR = 17,
+        LORA_MAX_PAYLOAD_EXCEEDED = 18,
+        LORA_LBT_CHANNEL_BUSY = 19
+    };
+
+    /**
+     * State for Link
+     */
+    enum LinkState {
+        LINK_IDLE = 0,  //!< Link ready to send or receive
+        LINK_TX,        //!< Link is busy sending
+        LINK_ACK_TX,    //!< Link is busy resending after missed ACK
+        LINK_REP_TX,    //!< Link is busy repeating
+        LINK_RX,        //!< Link has receive window open
+        LINK_RX1,       //!< Link has first received window open
+        LINK_RX2,       //!< Link has second received window open
+        LINK_RXC,       //!< Link has class C received window open
+        LINK_P2P,       //!< Link is busy sending
+    };
+
+    /**
+     * State for MAC
+     */
+    enum MacState {
+        MAC_IDLE,
+        MAC_RX1,
+        MAC_RX2,
+        MAC_RXC,
+        MAC_TX,
+        MAC_JOIN
+    };
+
+    /**
+     * Operation class for device
+     */
+    enum MoteClass {
+        CLASS_A = 0x00, //!< Device can only receive in windows opened after a transmit
+        CLASS_B = 0x01, //!< Device can receive in windows sychronized with gateway beacon
+        CLASS_C = 0x02  //!< Device can receive any time when not transmitting
+    };
+
+    /**
+     * Direction of a packet
+     */
+    enum Direction {
+        DIR_UP = 0,     //!< Packet is sent from mote to gateway
+        DIR_DOWN = 1,   //!< Packet was received from gateway
+        DIR_PEER = 2    //!< Packet was received from peer
+    };
+
+
+    /**
+     * Received window used by Link
+     */
+    enum ReceiveWindows {
+        RX_1 = 1,           //!< First receive window
+        RX_2,               //!< Second receive window
+        RX_BEACON,          //!< Beacon receive window
+        RX_SLOT,            //!< Ping Slot receive window
+        RXC,                //!< Class C continuous window
+        RX_TEST
+    };
+
+    /**
+     * Datarate range for a Channel
+     */
+    typedef union {
+            int8_t Value;
+            struct {
+                    int8_t Min :4;
+                    int8_t Max :4;
+            } Fields;
+    } DatarateRange;
+
+    /**
+     * Datarate used for transmitting and receiving
+     */
+    typedef struct Datarate {
+            uint8_t Index;
+            uint8_t Bandwidth;
+            uint8_t Coderate;
+            uint8_t PreambleLength;
+            uint8_t SpreadingFactor;
+            uint8_t Crc;
+            uint8_t TxIQ;
+            uint8_t RxIQ;
+            uint8_t SymbolTimeout();
+            Datarate();
+    } Datarate;
+
+    /**
+     * Channel used for transmitting
+     */
+    typedef struct {
+            uint8_t Index;
+            uint32_t Frequency;
+            DatarateRange DrRange;
+    } Channel;
+
+    /**
+     * Receive window
+     */
+    typedef struct {
+            uint8_t Index;
+            uint32_t Frequency;
+            uint8_t DatarateIndex;
+    } RxWindow;
+
+    /**
+     * Duty band for limiting time-on-air for regional regulations
+     */
+    typedef struct {
+            uint8_t Index;
+            uint32_t FrequencyMin;
+            uint32_t FrequencyMax;
+            uint8_t PowerMax;
+            uint16_t DutyCycle;          //!< Multiplier of time on air, 0:100%, 1:50%, 2:33%, 10:10%, 100:1%, 1000,0.1%
+            uint32_t TimeOffEnd;         //!< Timestamp when this band will be available
+    } DutyBand;
+
+    /**
+     * Device configuration
+     */
+    typedef struct {
+            uint8_t FrequencyBand;      //!< Used to choose ChannelPlan
+            uint8_t EUI[8];             //!< Unique identifier assigned to device
+    } DeviceConfig;
+
+    /**
+     * Network configuration
+     */
+    typedef struct {
+            uint8_t Mode;               //!< PUBLIC, PRIVATE or PEER_TO_PEER network mode
+            uint8_t Class;              //!< Operating class of device
+            uint8_t EUI[8];             //!< Network ID or AppEUI
+            uint8_t Key[16];            //!< Network Key or AppKey
+            uint8_t JoinDelay;          //!< Number of seconds to wait before 1st RX Window
+            uint8_t RxDelay;            //!< Number of seconds to wait before 1st RX Window
+            uint8_t FrequencySubBand;   //!< FrequencySubBand used for US915 hybrid operation 0:72 channels, 1:1-8 channels ...
+            uint8_t AckAttempts;        //!< Number of attempts to send packet and receive an ACK from server
+            uint8_t Retries;            //!< Number of times to resend a packet without receiving an ACK, redundancy
+            uint8_t ADREnabled;         //!< Enable adaptive datarate
+            uint8_t CADEnabled;         //!< Enable listen before talk/channel activity detection
+            uint8_t RepeaterMode;       //!< Limit payloads to repeater compatible sizes
+            uint8_t TxPower;            //!< Default radio output power in dBm
+            uint8_t TxPowerMax;         //!< Max transmit power
+            uint8_t TxDatarate;         //!< Datarate for P2P transmit
+            uint32_t TxFrequency;       //!< Frequency for P2P transmit
+            int8_t AntennaGain;         //!< Antenna Gain
+            uint8_t DisableEncryption;  //!< Disable Encryption
+            uint8_t DisableCRC;        //!< Disable CRC on uplink packets
+            uint16_t P2PACKTimeout;
+            uint16_t P2PACKBackoff;
+            uint8_t JoinRx1DatarateOffset;  //!< Offset for datarate for first window
+            uint32_t JoinRx2Frequency;      //!< Frequency used in second window
+            uint8_t JoinRx2DatarateIndex;   //!< Datarate for second window
+    } NetworkConfig;
+
+    /**
+     * Network session info
+     * Some settings are acquired in join message and others may be changed through Mac Commands from server
+     */
+    typedef struct {
+            uint8_t Joined;                     //!< State of session
+            uint8_t Rx1DatarateOffset;          //!< Offset for datarate for first window
+            uint32_t Rx2Frequency;              //!< Frequency used in second window
+            uint8_t Rx2DatarateIndex;           //!< Datarate for second window
+            uint8_t TxPower;                    //!< Current total radiated output power in dBm
+            uint8_t TxDatarate;                 //!< Current datarate can be changed when ADR is enabled
+            uint32_t Address;                   //!< Network address
+            uint32_t NetworkID;                 //!< Network ID 24-bits
+            uint8_t NetworkSessionKey[16];      //!< Network session key
+            uint8_t ApplicationSessionKey[16];  //!< Data session key
+            uint16_t ChannelMask[4];            //!< Current channel mask
+            uint16_t ChannelMask500k;           //!< Current channel mask for 500k channels
+            uint32_t DownlinkCounter;           //!< Downlink counter of last packet received from server
+            uint32_t UplinkCounter;             //!< Uplink counter of last packet received from server
+            uint8_t Redundancy;                 //!< Number of time to repeat an uplink
+            uint8_t MaxDutyCycle;               //!< Current Max Duty Cycle value
+            uint32_t JoinTimeOnAir;              //!< Balance of time on air used during join attempts
+            uint32_t JoinTimeOffEnd;            //!< RTC time of next join attempt
+            uint32_t JoinFirstAttempt;          //!< RTC time of first failed join attempt
+            uint32_t AggregatedTimeOffEnd;      //!< Time off air expiration for aggregate duty cycle
+            uint16_t AggregateDutyCycle;        //!< Used for enforcing time-on-air
+            uint8_t AckCounter;                 //!< Current number of packets sent without ACK from server
+            uint8_t AdrCounter;                 //!< Current number of packets received without downlink from server
+            uint8_t RxDelay;                    //!< Number of seconds to wait before 1st RX Window
+            uint8_t CommandBuffer[COMMANDS_BUFFER_SIZE]; //!< Buffer to hold Mac Commands and parameters to be sent in next packet
+            uint8_t CommandBufferIndex;         //!< Index to place next Mac Command, also current size of Command Buffer
+            bool SrvRequestedAck;               //!< Indicator of ACK requested by server in last packet received
+            bool DataPending;                   //!< Indicator of data pending at server
+            uint8_t RxTimingSetupReqReceived;   //!< Indicator that RxTimingSetupAns should be included in uplink
+            uint8_t RxParamSetupReqAnswer;      //!< Indicator that RxParamSetupAns should be included in uplink
+            uint8_t DlChannelReqAnswer;         //!< Indicator that DlChannelAns should be included in uplink
+            uint8_t DownlinkDwelltime;          //!< On air dwell time for downlink packets 0:NONE,1:400ms
+            uint8_t UplinkDwelltime;            //!< On air dwell time for uplink packets 0:NONE,1:400ms
+            uint8_t Max_EIRP;                   //!< Maximum allowed EIRP for uplink
+    } NetworkSession;
+
+    /**
+     * Multicast session info
+     */
+    typedef struct {
+            uint32_t Address;               //!< Network address
+            uint8_t NetworkSessionKey[16];  //!< Network session key
+            uint8_t DataSessionKey[16];     //!< Data session key
+            uint32_t DownlinkCounter;       //!< Downlink counter of last packet received from server
+    } MulticastSession;
+
+    /**
+     * Application configuration
+     */
+    typedef struct {
+            uint8_t Port;                   //!< Port used by application
+            uint8_t AppEUI;                 //!< Application ID
+            uint8_t AppKey[16];             //!< Application Key
+    } ApplicationConfig;
+
+    /**
+     * Statistics of current network session
+     */
+    typedef struct Statistics {
+            uint32_t Up;                    //!< Number of uplink packets sent
+            uint32_t Down;                  //!< Number of downlink packets received
+            uint32_t Joins;                 //!< Number of join requests sent
+            uint32_t JoinFails;             //!< Number of join requests without response or invalid response
+            uint32_t MissedAcks;            //!< Number of missed acknowledgement attempts of confirmed packets
+            uint32_t CRCErrors;             //!< Number of CRC errors in received packets
+            int32_t AvgCount;              //!< Number of packets used to compute rolling average of RSSI and SNR
+            int16_t Rssi;                   //!< RSSI of last packet received
+            int16_t RssiMin;                //!< Minimum RSSI of last AvgCount packets
+            int16_t RssiMax;                //!< Maximum RSSI of last AvgCount packets
+            int16_t RssiAvg;                //!< Rolling average RSSI of last AvgCount packets
+            int16_t Snr;                     //!< SNR of last packet received
+            int16_t SnrMin;                  //!< Minimum SNR of last AvgCount packets
+            int16_t SnrMax;                  //!< Maximum SNR of last AvgCount packets
+            int16_t SnrAvg;                  //!< Rolling average SNR of last AvgCount packets
+    } Statistics;
+
+    /**
+     *  Testing settings
+     */
+    typedef struct {
+            uint8_t TestMode;
+            uint8_t SkipMICCheck;
+            uint8_t DisableDutyCycle;
+            uint8_t DisableRx1;
+            uint8_t DisableRx2;
+            uint8_t FixedUplinkCounter;
+            uint8_t DisableRandomJoinDatarate;
+    } Testing;
+
+    /**
+     * Combination of device, network, testing settings and statistics
+     */
+    typedef struct {
+            DeviceConfig Device;
+            NetworkConfig Network;
+            NetworkSession Session;
+            ApplicationConfig Applications[MAX_APPS];
+            MulticastSession Multicast[MAX_MULTICAST_SESSIONS];
+            Statistics Stats;
+            Testing Test;
+    } Settings;
+
+    /**
+     * Downlink settings sent in Join Accept message
+     */
+    typedef union {
+            uint8_t Value;
+            struct {
+                    uint8_t Rx2Datarate :4;
+                    uint8_t Rx1Offset :3;
+                    uint8_t RFU :1;
+            };
+    } DownlinkSettings;
+
+    /**
+     * Frame structure for Join Request
+     */
+    typedef struct {
+            uint8_t Type;
+            uint8_t AppEUI[8];
+            uint8_t DevEUI[8];
+            uint8_t Nonce[2];
+            uint8_t MIC[4];
+    } JoinRequestFrame;
+
+    /**
+     * Mac header of uplink and downlink packets
+     */
+    typedef union {
+            uint8_t Value;
+            struct {
+                    uint8_t Major :2;
+                    uint8_t RFU :3;
+                    uint8_t MType :3;
+            } Bits;
+    } MacHeader;
+
+    /**
+     * Frame control field of uplink packets
+     */
+    typedef union {
+            uint8_t Value;
+            struct {
+                    uint8_t OptionsLength :4;
+                    uint8_t ClassB :1;
+                    uint8_t Ack :1;
+                    uint8_t AdrAckReq :1;
+                    uint8_t Adr :1;
+            } Bits;
+    } UplinkControl;
+
+    /**
+     * Frame control field of downlink packets
+     */
+    typedef union {
+            uint8_t Value;
+            struct {
+                    uint8_t OptionsLength :4;
+                    uint8_t FPending :1;
+                    uint8_t Ack :1;
+                    uint8_t RFU :1;
+                    uint8_t Adr :1;
+            } Bits;
+    } DownlinkControl;
+
+    /**
+     * Frame type of packet
+     */
+    typedef enum {
+        FRAME_TYPE_JOIN_REQ = 0x00,
+        FRAME_TYPE_JOIN_ACCEPT = 0x01,
+        FRAME_TYPE_DATA_UNCONFIRMED_UP = 0x02,
+        FRAME_TYPE_DATA_UNCONFIRMED_DOWN = 0x03,
+        FRAME_TYPE_DATA_CONFIRMED_UP = 0x04,
+        FRAME_TYPE_DATA_CONFIRMED_DOWN = 0x05,
+        FRAME_TYPE_RFU = 0x06,
+        FRAME_TYPE_PROPRIETARY = 0x07,
+    } FrameType;
+
+    /**
+     * LoRaWAN mote MAC commands
+     */
+    typedef enum {
+        /* Class A */
+        MOTE_MAC_LINK_CHECK_REQ = 0x02,
+        MOTE_MAC_LINK_ADR_ANS = 0x03,
+        MOTE_MAC_DUTY_CYCLE_ANS = 0x04,
+        MOTE_MAC_RX_PARAM_SETUP_ANS = 0x05,
+        MOTE_MAC_DEV_STATUS_ANS = 0x06,
+        MOTE_MAC_NEW_CHANNEL_ANS = 0x07,
+        MOTE_MAC_RX_TIMING_SETUP_ANS = 0x08,
+        MOTE_MAC_TX_PARAM_SETUP_ANS = 0x09,
+        MOTE_MAC_DL_CHANNEL_ANS = 0x0A,
+
+        /* Class B */
+        MOTE_MAC_PING_SLOT_INFO_REQ = 0x0B,
+        MOTE_MAC_PING_SLOT_FREQ_ANS = 0x0C,
+        MOTE_MAC_PING_SLOT_CHANNEL_ANS = 0x0D,
+        MOTE_MAC_BEACON_TIMING_REQ = 0x0E,
+        MOTE_MAC_BEACON_FREQ_ANS = 0x0F,
+
+        /* Multitech */
+        MOTE_MAC_PING_REQ = 0x80,
+        MOTE_MAC_CHANGE_CLASS = 0x81,
+        MOTE_MAC_MULTIPART_START_REQ = 0x82,
+        MOTE_MAC_MULTIPART_START_ANS = 0x83,
+        MOTE_MAC_MULTIPART_CHUNK = 0x84,
+        MOTE_MAC_MULTIPART_END_REQ = 0x85,
+        MOTE_MAC_MULTIPART_END_ANS = 0x86
+    } MoteCommand;
+
+    /*!
+     * LoRaWAN server MAC commands
+     */
+    typedef enum {
+        /* Class A */
+        SRV_MAC_LINK_CHECK_ANS = 0x02,
+        SRV_MAC_LINK_ADR_REQ = 0x03,
+        SRV_MAC_DUTY_CYCLE_REQ = 0x04,
+        SRV_MAC_RX_PARAM_SETUP_REQ = 0x05,
+        SRV_MAC_DEV_STATUS_REQ = 0x06,
+        SRV_MAC_NEW_CHANNEL_REQ = 0x07,
+        SRV_MAC_RX_TIMING_SETUP_REQ = 0x08,
+        SRV_MAC_TX_PARAM_SETUP_REQ = 0x09,
+        SRV_MAC_DL_CHANNEL_REQ = 0x0A,
+
+        /* Class B */
+        SRV_MAC_PING_SLOT_INFO_ANS = 0x0B,
+        SRV_MAC_PING_SLOT_FREQ_REQ = 0x0C,
+        SRV_MAC_PING_SLOT_CHANNEL_REQ = 0x0D,
+        SRV_MAC_BEACON_TIMING_ANS = 0x0E,
+        SRV_MAC_BEACON_FREQ_REQ = 0x0F,
+
+        /* Multitech */
+        SRV_MAC_PING_ANS = 0x80,
+        SRV_MAC_CHANGE_CLASS = 0x81,
+        SRV_MAC_MULTIPART_START_REQ = 0x82,
+        SRV_MAC_MULTIPART_START_ANS = 0x83,
+        SRV_MAC_MULTIPART_CHUNK = 0x84,
+        SRV_MAC_MULTIPART_END_REQ = 0x85,
+        SRV_MAC_MULTIPART_END_ANS = 0x86
+    } ServerCommand;
+
+    /**
+     * Random seed for software RNG
+     */
+    void srand(uint32_t seed);
+
+    /**
+     * Software RNG for consistent results across differing hardware
+     */
+    int rand(void);
+
+    /**
+     * Generate random number bounded by min and max
+     */
+    int32_t rand_r(int32_t min, int32_t max);
+
+    uint8_t CountBits(uint16_t mask);
+
+    /**
+     * Copy 3-bytes network order from array into LSB of integer value
+     */
+    void CopyNetIDtoInt(const uint8_t* arr, uint32_t& val);
+
+    /**
+     * Copy LSB 3-bytes from integer value into array network order
+     */
+    void CopyNetIDtoArray(uint32_t val, uint8_t* arr);
+
+    /**
+     * Copy 4-bytes network order from array in to integer value
+     */
+    void CopyAddrtoInt(const uint8_t* arr, uint32_t& val);
+
+    /**
+     * Copy 4-bytes from integer in to array network order
+     */
+    void CopyAddrtoArray(uint32_t val, uint8_t* arr);
+
+    /**
+     * Copy 3-bytes network order from array into integer value and multiply by 100
+     */
+    void CopyFreqtoInt(const uint8_t* arr, uint32_t& freq);
+
+    /**
+     * Reverse memory copy
+     */
+    void memcpy_r(uint8_t *dst, const uint8_t *src, size_t n);
+
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/Lora/Mac.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,495 @@
+/**   __  ___     ____  _    ______        __     ____         __                  ____
+ *   /  |/  /_ __/ / /_(_)__/_  __/__ ____/ /    / __/_ _____ / /____ __ _  ___   /  _/__  ____
+ *  / /|_/ / // / / __/ /___// / / -_) __/ _ \  _\ \/ // (_-</ __/ -_)  ' \(_-<  _/ // _ \/ __/  __
+ * /_/  /_/\_,_/_/\__/_/    /_/  \__/\__/_//_/ /___/\_, /___/\__/\__/_/_/_/___/ /___/_//_/\__/  /_/
+ * Copyright (C) 2015 by Multi-Tech Systems        /___/
+ *
+ *
+ * @author Jason Reiss
+ * @date   10-31-2015
+ * @brief  lora::Mac implements the Mac layer providing mote addressing and packet encryption
+ *
+ * @details
+ *
+ */
+
+#ifndef __LORA_MAC_H__
+#define __LORA_MAC_H__
+
+#include "Lora.h"
+#include "ChannelPlan.h"
+#include "SxRadio.h"
+#include "SxRadio1272.h"
+#include "SxRadioEvents.h"
+#include "MacEvents.h"
+#include "Crypto.h"
+#include "Link.h"
+
+namespace lora {
+
+    class Mac: public SxRadioEvents, public Crypto {
+        public:
+
+            virtual ~Mac();
+
+            Mac(SxRadio& radio, MacEvents* events, ChannelPlan* plan, Settings& settings);
+
+            /**
+             * Send a Join Request packet
+             * @param devEUI
+             * @param appEUI
+             * @param appKey
+             * @return LORA_OK if successful
+             * @return LORA_LINK_BUSY
+             * @return LORA_RADIO_BUSY
+             */
+            uint8_t Join(const uint8_t* devEUI, const uint8_t* appEUI, const uint8_t* appKey);
+
+            /**
+             * Send a packet
+             * @param port app port to send with payload
+             * @param payload data to send
+             * @param size of payload
+             * @param attempts number of attempts to receive an ACK
+             * @param repeats number of times to repeat packet
+             * @return LORA_OK if successful
+             * @return LORA_MAX_PAYLOAD_EXCEEDED if payload size exceeds datarate maximum
+             * @return LORA_NO_CHANS_ENABLED if there is not an available channel that supports the current datarate
+             * @return LORA_LINK_BUSY if link was busy
+             * @return LORA_RADIO_BUSY if radio was busy
+             * @return LORA_BUFFER_FULL if mac commands filled the packet, client should resend the packet
+             */
+            uint8_t Send(uint8_t port, const uint8_t* payload, uint16_t size, uint8_t attempts = 0, uint8_t repeats = 0);
+
+            /**
+             * Prepare frame to be sent over link
+             * @param port to send data to
+             * @param payload to send
+             * @param size of payload
+             * @param attempts 0:Unconfirmed, 1-8:Confirmed
+             * @return LORA_OK
+             */
+            uint8_t PrepareFrame(uint8_t port, const uint8_t* payload, uint8_t size, uint8_t attempts);
+
+            /**
+             * Reset the mac commands buffer
+             */
+            void ResetMacCommands();
+
+            /**
+             * Add a mac command to be sent with next packet
+             * @param cmd id of command
+             * @param pc number of parameters
+             * @param pv array of parameters
+             * @return LORA_OK if successful
+             * @return LORA_COMMAND_BUFFER_FULL
+             * @return LORA_UNKNOWN_MAC_COMMAND
+             */
+            uint8_t AddMacCommand(uint8_t cmd, uint8_t pc, uint8_t* pv);
+
+            /**
+             * Handle mac command received from server
+             * @param payload received on radio
+             * @param index of mac command id
+             * @param size of mac command list
+             */
+            uint8_t HandleMacCommands(uint8_t* payload, uint8_t index, uint8_t size);
+
+            /**
+             * Handle Join Accept packet
+             * @param payload received
+             * @param size of payload
+             * @return LORA_OK if successful
+             * @return LORA_JOIN_ERROR if already joined or MIC fails
+             */
+            uint8_t HandleJoinAccept(uint8_t* payload, uint8_t size);
+
+            /**
+             * Handle Packet receipt
+             * Verifies Address and MIC, checks the Frame Control bits for ACK
+             * Then decrypts the payload and handles any Mac Commands
+             * @param payload received
+             * @param size of payload
+             * @param[out] port data was received on
+             * @param[out] length of user data in payload
+             */
+            uint8_t HandleDownlinkPacket(uint8_t* payload, uint8_t size, uint8_t& port, uint8_t& length);
+
+            /**
+             * Check for ACK from server in received packet and notifies Link if present
+             * @param fCtrl frame control byte of packet
+             * @return LORA_OK
+             */
+            uint8_t CheckFrameControl(DownlinkControl fCtrl);
+
+            /**
+             * Verify that packet address is intended for mote or in list of multicast addresses
+             * @param payload received
+             * @param size of payload
+             * @param[out] address found in header of packet
+             * @param[out] networkSessionKey associated with address
+             * @param[out] dataSessionKey associated with address
+             * @return LORA_OK if successful
+             * @return LORA_ADDRESS_ERROR if address is not found
+             */
+            uint8_t VerifyAddress(uint8_t* payload, uint8_t size, uint32_t& address, uint8_t* networkSessionKey, uint8_t* dataSessionKey);
+
+            /**
+             * Verify that MIC can be computed with network session key
+             * Frame counter is checked for reset and rollover
+             * @param payload received
+             * @param size of payload
+             * @param address found in header of packet
+             * @param networkSessionKey
+             * @return LORA_OK if successful
+             * @return LORA_MIC_ERROR
+             */
+            uint8_t VerifyMIC(uint8_t* payload, uint8_t size, uint32_t address, uint8_t* networkSessionKey);
+
+            /**
+             * Event called by Link on start of any tx
+             */
+            virtual void TxStart(void);
+
+            /**
+             * Event called by Link on tx done
+             */
+            virtual void TxDone(void);
+
+            /**
+             * Event called by Link on tx timeout
+             */
+            virtual void TxTimeout(void);
+
+            /**
+             * Event called by Link on rx done
+             * @param payload of received packet
+             * @param size of received packet in bytes
+             * @param rssi of received packet in dBm
+             * @param snr of received packet two's complement in 1/4 dB
+             */
+            virtual void RxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr);
+
+            /**
+             * Event called by Link on rx timeout
+             */
+            virtual void RxTimeout(void);
+
+            /**
+             * Event called by Link on rx error
+             */
+            virtual void RxError(void);
+
+            virtual void LinkIdle(void);
+
+            /**
+             * Current join status
+             * @return true if joined to lora network
+             * @return false if not joined
+             */
+            bool IsJoined();
+
+            /**
+             * Set the dev nonce
+             * The dev nonce is used for deriving session keys and part of the data send on a join request
+             */
+            void SetDeviceNonce(uint16_t nonce);
+
+            /**
+             * Get the dev nonce
+             * The dev nonce is used for deriving session keys and part of the data send on a join request
+             */
+            uint16_t GetDeviceNonce();
+
+            void SetLoraClass(MoteClass cls);
+
+            /**
+             * Get the current device MoteClass
+             */
+            MoteClass GetLoraClass();
+
+            /**
+             * Get the SNR of the last received packet
+             * @returns snr in dB
+             */
+            int8_t GetSNR();
+
+            /**
+             * Get the RSSI of the last received packet
+             * @returns rssi in dB
+             */
+            int16_t GetRSSI();
+
+            /**
+             * Update the statistics with the last received RSSI and SNR
+             * The avg, min and max RSSI and SNR will also be updated
+             */
+            void UpdateStats(int16_t rssi, int16_t snr);
+
+            /**
+             * Get the number of mac command bytes ready to be sent in the next packet
+             * @return size of buffer in bytes
+             */
+            uint8_t GetMacCommandBufferSize();
+
+            /**
+             * Get the buffer for mac command bytes ready to be sent in the next packet
+             * @return pointer to command buffer
+             */
+            const uint8_t* GetMacCommandBuffer();
+
+            /**
+             * Clear the buffer for mac command bytes to be sent in the next packet
+             */
+            void ClearMacCommandBuffer();
+
+            /**
+             * Get the size of the bytes ready to be sent in the next packet
+             * @returns size of buffer in bytes
+             */
+            uint8_t GetTxBufferSize();
+
+            /**
+             * Get the buffer of bytes  ready to be sent in the next packet
+             * @return pointer to buffer
+             */
+            const uint8_t* GetTxBuffer();
+
+            /**
+             * Get the max duty cycle currently set for device
+             * Aggregated duty cycle = 1 / 2 ^ MaxDutyCycle
+             * Value of 255 should silence device
+             * @return duty cycle 0-15 or 255
+             */
+            uint8_t GetMaxDutyCycle();
+
+            /**
+             * Get the Rx delay value currently used by the Link
+             * @return rxDelay in seconds
+             */
+            uint8_t GetRxDelay();
+
+            /**
+             * Get the MCU sleep time between tx done and the Rx1 window opening
+             * @return Time MCU sleeps between tx done and rx1 open in milliseconds
+             */
+            uint32_t GetRx1SleepTime();
+
+            /**
+             * Get the MCU sleep time between Rx1 window opening and the Rx2 window opening
+             * @return Time MCU sleeps between rx1 open and rx2 open in milliseconds
+             */
+            uint32_t GetRx2SleepTime();
+
+            /**
+             * Get pong received indicator
+             * @return true if pong was received
+             */
+            bool GetPongReceived();
+
+            /**
+             * Get the RSSI of the last received pong
+             * The RSSI will be the strength of the signal received at the gateway
+             * @return rssi in dB
+             */
+            int16_t GetPongRssi();
+
+            /**
+             * Get the SNR of the last received pong
+             * The SNR will be the strength of the signal received at the gateway
+             * @return snr in dB
+             */
+            int16_t GetPongSnr();
+
+            /**
+             * Get the current statistics for the device
+             * @return Statistics
+             */
+            Statistics& GetStats();
+
+            /**
+             * Reset the current statistics for the device
+             */
+            void ResetStats();
+
+            /**
+             * Set the current channel plan
+             */
+            void SetChannelPlan(ChannelPlan* plan);
+
+            /**
+             * Set the delay for Rx1 window
+             * @param sec time to delay after end of tx, minimum 1 second
+             */
+            uint8_t SetRxDelay(uint8_t sec);
+
+            /**
+             * Set the MCU sleep time between tx done and the Rx1 window opening
+             * @param ms time MCU sleeps between tx done and rx1 open
+             */
+            void SetRx1SleepTime(uint32_t ms);
+
+            /**
+             * Set the MCU sleep time between Rx1 window opening and the Rx2 window opening
+             * @param ms time MCU sleeps between rx1 open and rx2 open
+             */
+            void SetRx2SleepTime(uint32_t ms);
+
+            /**
+             * Set the network mode
+             * @param mode PRIVATE, PUBLIC or PEER_TO_PEER
+             */
+            uint8_t SetNetworkMode(uint8_t mode);
+
+            /**
+             * Get the current state of the MAC layer
+             * @return MAC_IDLE, MAC_TX, MAC_RX
+             */
+            MacState GetState();
+
+            /**
+             * Get the time off air for the current datarate
+             * @return time off air before next TX in ms
+             */
+            uint32_t GetTimeOffAir();
+
+            /**
+             * Open an RX Window
+             * @param timeout time in ms to hold window open, 0 for continuous
+             * @param freq frequency to listen on
+             * @param datarate to listen for
+             * @return LORA_OK
+             */
+            uint8_t OpenRxWindow(uint32_t timeout, uint32_t freq, uint8_t datarate);
+            uint8_t OpenRxWindow(uint32_t timeout, bool continuous);
+
+            /**
+             * Close the open window
+             * @return LORA_OK
+             */
+            uint8_t CloseRxWindow();
+
+            /**
+             * Cancel pending rx windows
+             * @return LORA_OK
+             */
+            uint8_t CancelRxWindows();
+
+            /**
+             * Get datarate properties of given index for current channel plan
+             * @param index of datarate
+             */
+            Datarate GetDatarate(uint8_t index);
+
+            /**
+             * Get the max payload size available of current datarate for channel plan
+             * @return bytes that can be sent
+             */
+            uint8_t GetMaxPayloadSize();
+
+            /**
+             * Call to wakeup mac layer
+             */
+            void Wakeup();
+
+            /**
+             * Set the event object to report to
+             * @param events object inheriting from MacEvents
+             */
+            void SetEventHandler(MacEvents* events);
+
+            /**
+             * Get the channels in use by current channel plan
+             * @return channel frequencies
+             */
+            std::vector<uint32_t> GetChannels();
+
+            /**
+             * Get the downlink channels in use by current channel plan
+             * @return channel frequencies
+             */
+            std::vector<uint32_t> GetDownlinkChannels();
+
+            /**
+             * Get the channel datarate ranges in use by current channel plan
+             * @return channel datarate ranges
+             */
+            std::vector<uint8_t> GetChannelRanges();
+
+            /**
+             * Enable the default channels of the channel plan
+             */
+            void EnableDefaultChannels();
+
+            /**
+             * Get the number of duty bands in the current channel plan
+             * @return number of bands
+             */
+            uint8_t GetNumDutyBands();
+
+            /**
+             * Get the time off air for the given duty band
+             * @param band index
+             * @return time off air in ms
+             */
+            uint32_t GetDutyBandTimeOff(uint8_t band);
+
+            /**
+             * Set the time off air for the given duty band
+             * @param band index
+             * @param time off air in ms
+             */
+            void SetDutyBandTimeOff(uint8_t band, uint32_t timeoff);
+
+            /**
+             * Reset internal mac state if timeout or unforeseen error occurs
+             */
+            void ResetState();
+
+            /**
+             * Enable TX CW
+             * return LORA_OK
+             */
+            uint8_t SendContinuous(bool enable);
+
+        private:
+            /**
+             * Helper for clearing MAC commands which can be cleared upon successful uplink
+             */
+            void PostTxMacPrune();
+
+            Link _link;                                 //!< Link used to manage radio
+            ChannelPlan* _plan;                         //!< Injected ChannelPlan used by Link to define parameters for tx/rx of packets
+            SxRadio& _radio;                            //!< Injected SxRadio object
+            MacEvents* _events;                         //!< Injected MaxEvents object for event notification to client
+            Settings& _settings;                        //!< Settings used to configure the Mac
+
+            bool _isMulticastPacket;                    //!< Indicator of multicast packet recieved
+            uint8_t _multicastIndex;                    //!< Index of multicast session associated with last received packet
+
+            uint8_t _rxBuffer[MAX_PHY_PACKET_SIZE];     //!< Buffer of last packet received
+            uint8_t _rxBufferSize;                      //!< Size of the last packet received
+            uint8_t _txBuffer[MAX_PHY_PACKET_SIZE];     //!< Buffer of packet to send
+            uint8_t _txBufferSize;                      //!< Size of buffer to send
+            bool _txBufferFull;                         //!< Indicates that buffer was filled with mac commands
+
+            uint16_t _joinNonce;                        //!< Random nonce value used for Join Request and to derive session keys
+
+            int16_t _rssi;                              //!< RSSI value of last received packet in dB
+            int16_t _snr;                               //!< SNR value of last received packet in cB
+
+            bool _pongReceived;                         //!< Indicator of pong received
+            int16_t _pongRssi;                          //!< RSSI value of last received pong
+            int16_t _pongSnr;                           //!< SNR value of last received pong
+
+            MacState _state;                            //!< Current mac state
+
+            uint32_t _downlinkCounter;                  //!< Temporary downlink counter
+            bool _duplicateReceived;                    //!< Indication of duplicate packet received due to missed ack
+
+            DownlinkControl _downlinkCtrl;              //!< Downlink ctrl status of last rx packet
+    };
+
+}
+
+#endif // __LORA_MAC_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/Lora/MacEvents.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,54 @@
+/**   __  ___     ____  _    ______        __     ____         __                  ____
+ *   /  |/  /_ __/ / /_(_)__/_  __/__ ____/ /    / __/_ _____ / /____ __ _  ___   /  _/__  ____
+ *  / /|_/ / // / / __/ /___// / / -_) __/ _ \  _\ \/ // (_-</ __/ -_)  ' \(_-<  _/ // _ \/ __/ __
+ * /_/  /_/\_,_/_/\__/_/    /_/  \__/\__/_//_/ /___/\_, /___/\__/\__/_/_/_/___/ /___/_//_/\__/ /_/
+ * Copyright (C) 2015 by Multi-Tech Systems        /___/
+ *
+ *
+ * @author Jason Reiss
+ * @date   10-31-2015
+ * @brief  lora::MacEvents provides an interface for events from the Mac layer
+ *
+ * @details
+ *
+ */
+
+#ifndef __LORA_MAC_EVENTS_H__
+#define __LORA_MAC_EVENTS_H__
+
+#include "Lora.h"
+
+namespace lora {
+
+    class MacEvents {
+
+        public:
+            virtual ~MacEvents() {};
+
+            virtual void TxStart(void) = 0;
+            virtual void TxDone(uint8_t dr) = 0;
+            virtual void TxTimeout(void) = 0;
+
+            virtual void JoinAccept(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr) = 0;
+            virtual void JoinFailed(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr) = 0;
+            virtual void PacketRx(uint8_t port, uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr, lora::DownlinkControl ctrl, uint8_t slot, uint8_t retries=0, uint32_t address=0, bool dupRx=false) = 0;
+            virtual void RxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr, lora::DownlinkControl ctrl, uint8_t slot) = 0;
+
+            virtual void Pong(int16_t m_rssi, int8_t m_snr, int16_t s_rssi, int8_t s_snr) = 0;
+            virtual void NetworkLinkCheck(int16_t m_rssi, int8_t m_snr, int8_t s_snr, uint8_t s_gateways) = 0;
+
+            virtual void RxTimeout(uint8_t slot) = 0;
+            virtual void RxError(uint8_t slot) = 0;
+
+            virtual void MissedAck(uint8_t retries) = 0;
+
+            virtual uint8_t MeasureBattery() = 0;
+
+        private:
+
+
+    };
+
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/Lora/Mote.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,299 @@
+/**   __  ___     ____  _    ______        __     ____         __                  ____
+ *   /  |/  /_ __/ / /_(_)__/_  __/__ ____/ /    / __/_ _____ / /____ __ _  ___   /  _/__  ____
+ *  / /|_/ / // / / __/ /___// / / -_) __/ _ \  _\ \/ // (_-</ __/ -_)  ' \(_-<  _/ // _ \/ __/ __
+ * /_/  /_/\_,_/_/\__/_/    /_/  \__/\__/_//_/ /___/\_, /___/\__/\__/_/_/_/___/ /___/_//_/\__/ /_/
+ * Copyright (C) 2015 by Multi-Tech Systems        /___/
+ *
+ *
+ * @author Jason Reiss
+ * @date   10-31-2015
+ * @brief  lora::Mote provides a user level class that abstracts the complexity of the Mac layer
+ *
+ * @details
+ *
+ */
+
+#ifndef __LORA_MOTE_H__
+#define __LORA_MOTE_H__
+
+#include "rtos.h"
+#include "MacEvents.h"
+#include <vector>
+
+class SxRadio;
+class SxRadio1272;
+
+namespace lora {
+
+    class Mac;
+    class ChannelPlan;
+
+    class MoteEvents: public MacEvents {
+
+            /**
+             * Fired at start of TX
+             */
+            virtual void TxStart(void);
+
+            /**
+             * Fired at end of TX
+             * @param dr datarate used for TX
+             */
+            virtual void TxDone(uint8_t dr);
+
+            /**
+             * Fired if TX timed out
+             */
+            virtual void TxTimeout(void);
+
+            /**
+             * Fired when JoinAccept message is received and MIC is validated
+             * @param payload received bytes
+             * @param size number of received bytes
+             * @param rssi of received packet
+             * @param snr of received packet
+             */
+            virtual void JoinAccept(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr);
+
+            /**
+             * Fired when JoinAccept message is received and MIC is not valid
+             * @param payload received bytes
+             * @param size number of received bytes
+             * @param rssi of received packet
+             * @param snr of received packet
+             */
+            virtual void JoinFailed(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr);
+
+            /**
+             * Fired when packet is received and MIC is valid
+             * @param port of packet
+             * @param payload received bytes
+             * @param size number of received bytes
+             * @param rssi of received packet
+             * @param snr of received packet
+             * @param ctrl Downlink control field of packet
+             * @param slot rx window packet was received
+             * @param retries number of attempts before ack was received
+             * @param address of the end device
+             * @param dupRx set if this packet has already been received
+             */
+            virtual void PacketRx(uint8_t port, uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr, lora::DownlinkControl ctrl, uint8_t slot, uint8_t retries = 0, uint32_t address = 0, bool dupRx=false);
+
+            /**
+             * Fired when radio has received a packet, packet is not validated
+             * @param payload received bytes
+             * @param size number of received bytes
+             * @param rssi of received packet
+             * @param snr of received packet
+             * @param ctrl Downlink control field of packet
+             * @param slot rx window packet was received
+             */
+            virtual void RxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr, lora::DownlinkControl ctrl, uint8_t slot);
+
+            /**
+             * Fired if rx window times out
+             * @param slot rx window that timed out
+             */
+            virtual void RxTimeout(uint8_t slot);
+
+            /**
+             * Fired if rx CRC error
+             * @param slot rx window that errored
+             */
+            virtual void RxError(uint8_t slot);
+
+            /**
+             * Fired if pong packet is received
+             * @param m_rssi of received packet at mote
+             * @param m_snr of received packet at mote
+             * @param s_rssi of received packet at server
+             * @param s_snr of received packet at server
+             */
+            virtual void Pong(int16_t m_rssi, int8_t m_snr, int16_t s_rssi, int8_t s_snr);
+
+            /**
+             * Fired if network link check answer is received
+             * @param m_rssi of received packet at mote
+             * @param m_snr of received packet at mote
+             * @param s_snr margin of received packet at server
+             * @param s_gateways number of gateways reporting the packet
+             */
+            virtual void NetworkLinkCheck(int16_t m_rssi, int8_t m_snr, int8_t s_snr, uint8_t s_gateways);
+
+            /**
+             * Callback to for device to measure the battery level and report to server
+             * @return battery level 0-255, 0 - external power, 1-254 level min-max, 255 device unable to measure battery
+             */
+            virtual uint8_t MeasureBattery();
+
+            /**
+             * Fired when ack attempts are exhausted and RxTimeout or RxError occur
+             * @param retries number of attempts to resend the packet
+             */
+            virtual void MissedAck(uint8_t retries);
+    };
+
+    class Mote {
+        public:
+            Mote(Settings* settings, ChannelPlan* plan);
+            virtual ~Mote();
+
+            /**
+             * MTS LoRa version
+             * @return string containing version information
+             */
+            const char* getId();
+
+            /**
+             * Indicator for network session join status
+             * @return true if joined to network
+             */
+            bool Joined();
+
+            /**
+             * Send join request
+             * @return LORA_OK if request was sent
+             */
+            uint8_t Join();
+
+            /**
+             * Send a packet
+             * @param port to send packet
+             * @param payload of packet
+             * @param size in bytes
+             * @return LORA_OK if successful
+             * @return LORA_MAX_PAYLOAD_EXCEEDED if payload size exceeds datarate maximum
+             * @return LORA_NO_CHANS_ENABLED if there is not an available channel that supports the current datarate
+             * @return LORA_LINK_BUSY if link was busy
+             * @return LORA_RADIO_BUSY if radio was busy
+             * @return LORA_BUFFER_FULL if mac commands filled the packet, client should resend the packet
+             */
+            uint8_t Send(uint8_t port, const uint8_t* payload, uint8_t size);
+
+            /**
+             * Configure the channel plan
+             * @param plan pointer to ChannelPlan object
+             * @return LORA_OK
+             */
+            uint8_t SetChannelPlan(ChannelPlan* plan);
+
+
+            Settings* GetSettings();
+
+            /**
+             * Get the channel mask of currently enabled channels
+             * @return vector containing channel bit masks
+             */
+            std::vector<uint16_t> GetChannelMask();
+
+            /**
+             * Set a 16 bit channel mask with index
+             * @param index of mask to set 0:0-15, 1:16-31 ...
+             * @param mask 16 bit mask of enabled channels
+             * @return true
+             */
+            virtual uint8_t SetChannelMask(uint8_t index, uint16_t mask);
+
+            /**
+             * Set the current frequency sub band for hybrid operation 1-8 else 0 for 64 channel operation
+             * @param sub_band 0-8
+             */
+            uint8_t SetFrequencySubBand(uint8_t sub_band);
+
+            /**
+             * Get the current frequency sub band
+             * @return sub band 0-8
+             */
+            uint8_t GetFrequencySubBand();
+
+            /**
+             * Add a channel to the channel plan
+             * EU868, AS923 and KR920 allows additional channels to be added
+             * Channels 0-2 are fixed default channels
+             *
+             * @param index of the channel
+             * @param frequency of the channel or 0 to remove channel
+             * @param range of datarates allowed by the channel
+             * @return LORA_OK if channel was added
+             */
+            uint8_t AddChannel(uint8_t index, uint32_t frequency, lora::DatarateRange range);
+
+            /**
+             * Add a downlink channel to the channel plan
+             * EU868, AS923 and KR920 allows downlink channels to be added
+             *
+             * @param index of the channel
+             * @param frequency of the channel or 0 to remove channel
+             * @return LORA_OK if channel was added
+             */
+            uint8_t AddDownlinkChannel(uint8_t index, uint32_t frequency);
+
+            /**
+             * Set network mode
+             * Choose Public LoRaWAN mode or Private Multitech mode
+             *
+             * Public mode uses 0x34 sync word with 5/6 second join windows
+             * Private mode uses 0x12 sync word with 1/2 second join windows
+             *  US915/AU915 Rx1 and Rx2 are fixed per frequency sub band setting
+             *
+             * @param mode public or private
+             * @return LORA_OK
+             */
+            uint8_t SetNetworkMode(uint8_t mode);
+
+            /**
+             * Get a pointer to the mac layer
+             * @return Mac mac
+             */
+            Mac* GetMac();
+
+            /**
+             * Get a pointer to the radio
+             * Can be used to read radio registers or get a random value based on RSSI
+             *
+             * @return SxRadio pointer
+             */
+            SxRadio* GetRadio();
+
+            /**
+             * Get the current statistics for the device
+             * @return Statistics
+             */
+            Statistics& GetStats();
+
+            /**
+             * Reset the current statistics for the device
+             */
+            void ResetStats();
+
+            /**
+             * Get time on air with current settings for provided payload bytes
+             * 13 overhead bytes will be added to payload
+             * @param bytes of payload data
+             * @return time-on-air in ms
+             */
+            uint32_t GetTimeOnAir(uint8_t bytes);
+
+            /**
+             * Get time off air required to adhere to duty-cycle limitations
+             * @return time-off-air in ms
+             */
+            uint32_t GetTimeOffAir();
+
+            /**
+             * Call before setting device in sleep mode to place radio in sleep
+             */
+            void Sleep();
+
+        protected:
+            SxRadio1272* _radio;
+            Settings* _settings;
+            Mac* _mac;
+
+        private:
+            ChannelPlan* _plan;
+            MoteEvents _events;
+    };
+
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/Lora/Radio/SxRadio.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,294 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2013 Semtech
+
+Description: Generic radio driver definition
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Miguel Luis and Gregory Cristian
+*/
+#ifndef __SXRADIO_H__
+#define __SXRADIO_H__
+
+#include <stdint.h>
+#include "rtos.h"
+#include "SxRadioEvents.h"
+
+/*!
+ * \brief Radio driver definition
+ */
+class SxRadio
+{
+public:
+    /*!
+     * Radio driver supported modems
+     */
+    typedef enum
+    {
+        MODEM_FSK = 0,
+        MODEM_LORA,
+    }RadioModems_t;
+
+    /*!
+     * Radio driver internal state machine states definition
+     */
+    typedef enum
+    {
+        RF_IDLE = 0,
+        RF_RX_RUNNING,
+        RF_TX_RUNNING,
+        RF_CAD,
+    }RadioState_t;
+
+    SxRadio(uint32_t WakeupTime) : WakeupTime(WakeupTime), State(RF_IDLE), Modem(MODEM_LORA) { }
+    virtual ~SxRadio() {};
+
+    /*!
+     * \brief Initializes the radio
+     *
+     * \param [IN] events Structure containing the driver callback functions
+     */
+    virtual void Init( SxRadioEvents *events ) = 0;
+    /*!
+     * \brief Prepares the radio for destruction
+     */
+    virtual void Terminate( void ) = 0;
+    /*!
+     * Return current radio status
+     *
+     * \param status Radio status.[RF_IDLE, RF_RX_RUNNING, RF_TX_RUNNING]
+     */
+    virtual RadioState_t Status( void ) { return State; }
+    /*!
+     * \brief Configures the radio with the given modem
+     *
+     * \param [IN] modem Modem to be used [0: FSK, 1: LoRa] 
+     */
+    virtual void SetModem( RadioModems_t modem ) = 0;
+    /*!
+     * \brief Sets the channel frequency
+     *
+     * \param [IN] freq         Channel RF frequency
+     */
+    virtual void SetChannel( uint32_t freq ) = 0;
+    /*!
+     * \brief Sets the channels configuration
+     *
+     * \param [IN] modem      Radio modem to be used [0: FSK, 1: LoRa]
+     * \param [IN] freq       Channel RF frequency
+     * \param [IN] rssiThresh RSSI threshold
+     * \param [IN] rssiVal    pointer to variable to hold RSSI value if desired - ignored if NULL
+     *
+     * \retval isFree         [true: Channel is free, false: Channel is not free]
+     */
+    virtual bool IsChannelFree( RadioModems_t modem, uint32_t freq, uint8_t datarate, int16_t rssiThresh, uint8_t bandwidth, uint32_t timeout = 5000, int16_t *rssiVal = NULL ) = 0;
+    /*!
+     * \brief Generates a 32 bits random value based on the RSSI readings
+     *
+     * \remark This function sets the radio in LoRa modem mode and disables 
+     *         all interrupts.
+     *         After calling this function either Radio.SetRxConfig or
+     *         Radio.SetTxConfig functions must be called.
+     *
+     * \retval randomValue    32 bits random value
+     */
+    virtual uint32_t Random( void ) = 0;
+    /*!
+     * \brief Sets the reception parameters
+     *
+     * \param [IN] modem        Radio modem to be used [0: FSK, 1: LoRa]
+     * \param [IN] bandwidth    Sets the bandwidth
+     *                          FSK : >= 2600 and <= 250000 Hz
+     *                          LoRa: [0: 125 kHz, 1: 250 kHz,
+     *                                 2: 500 kHz, 3: Reserved] 
+     * \param [IN] datarate     Sets the Datarate
+     *                          FSK : 600..300000 bits/s
+     *                          LoRa: [6: 64, 7: 128, 8: 256, 9: 512,
+     *                                10: 1024, 11: 2048, 12: 4096  chips]
+     * \param [IN] coderate     Sets the coding rate (LoRa only)
+     *                          FSK : N/A ( set to 0 )
+     *                          LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8] 
+     * \param [IN] bandwidthAfc Sets the AFC Bandwidth (FSK only) 
+     *                          FSK : >= 2600 and <= 250000 Hz
+     *                          LoRa: N/A ( set to 0 ) 
+     * \param [IN] preambleLen  Sets the Preamble length
+     *                          FSK : Number of bytes 
+     *                          LoRa: Length in symbols (the hardware adds 4 more symbols)
+     * \param [IN] symbTimeout  Sets the RxSingle timeout value (LoRa only) 
+     *                          FSK : N/A ( set to 0 ) 
+     *                          LoRa: timeout in symbols
+     * \param [IN] fixLen       Fixed length packets [0: variable, 1: fixed]
+     * \param [IN] payloadLen   Sets payload length when fixed length is used
+     * \param [IN] crcOn        Enables/Disables the CRC [0: OFF, 1: ON]
+     * \param [IN] FreqHopOn    Enables disables the intra-packet frequency hopping
+     *                          FSK : N/A ( set to 0 )
+     *                          LoRa: [0: OFF, 1: ON]
+     * \param [IN] HopPeriod    Number of symbols bewteen each hop
+     *                          FSK : N/A ( set to 0 )
+     *                          LoRa: Number of symbols
+     * \param [IN] iqInverted   Inverts IQ signals (LoRa only)
+     *                          FSK : N/A ( set to 0 )
+     *                          LoRa: [0: not inverted, 1: inverted]
+     * \param [IN] rxContinuous Sets the reception in continuous mode
+     *                          [false: single mode, true: continuous mode]
+     */
+    virtual void SetRxConfig( RadioModems_t modem, uint32_t bandwidth,
+                              uint32_t datarate, uint8_t coderate,
+                              uint32_t bandwidthAfc, uint16_t preambleLen,
+                              uint16_t symbTimeout, bool fixLen,
+                              uint8_t payloadLen,
+                              bool crcOn, bool FreqHopOn, uint8_t HopPeriod,
+                              bool iqInverted, bool rxContinuous ) = 0;
+    /*!
+     * \brief Sets the transmission parameters
+     *
+     * \param [IN] modem        Radio modem to be used [0: FSK, 1: LoRa] 
+     * \param [IN] power        Sets the output power [dBm]
+     * \param [IN] fdev         Sets the frequency deviation (FSK only)
+     *                          FSK : [Hz]
+     *                          LoRa: 0
+     * \param [IN] bandwidth    Sets the bandwidth (LoRa only)
+     *                          FSK : 0
+     *                          LoRa: [0: 125 kHz, 1: 250 kHz,
+     *                                 2: 500 kHz, 3: Reserved] 
+     * \param [IN] datarate     Sets the Datarate
+     *                          FSK : 600..300000 bits/s
+     *                          LoRa: [6: 64, 7: 128, 8: 256, 9: 512,
+     *                                10: 1024, 11: 2048, 12: 4096  chips]
+     * \param [IN] coderate     Sets the coding rate (LoRa only)
+     *                          FSK : N/A ( set to 0 )
+     *                          LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8] 
+     * \param [IN] preambleLen  Sets the preamble length
+     *                          FSK : Number of bytes 
+     *                          LoRa: Length in symbols (the hardware adds 4 more symbols)
+     * \param [IN] fixLen       Fixed length packets [0: variable, 1: fixed]
+     * \param [IN] crcOn        Enables disables the CRC [0: OFF, 1: ON]
+     * \param [IN] FreqHopOn    Enables disables the intra-packet frequency hopping
+     *                          FSK : N/A ( set to 0 )
+     *                          LoRa: [0: OFF, 1: ON]
+     * \param [IN] HopPeriod    Number of symbols bewteen each hop
+     *                          FSK : N/A ( set to 0 )
+     *                          LoRa: Number of symbols
+     * \param [IN] iqInverted   Inverts IQ signals (LoRa only)
+     *                          FSK : N/A ( set to 0 )
+     *                          LoRa: [0: not inverted, 1: inverted]
+     * \param [IN] timeout      Transmission timeout [us]
+     */
+    virtual void SetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev, 
+                              uint32_t bandwidth, uint32_t datarate,
+                              uint8_t coderate, uint16_t preambleLen,
+                              bool fixLen, bool crcOn, bool FreqHopOn,
+                              uint8_t HopPeriod, bool iqInverted, uint32_t timeout ) = 0;
+
+    virtual void SetTxContinuous(bool enable) = 0;
+
+    /*!
+     * \brief Checks if the given RF frequency is supported by the hardware
+     *
+     * \param [IN] frequency RF frequency to be checked
+     * \retval isSupported [true: supported, false: unsupported]
+     */
+    virtual bool CheckRfFrequency( uint32_t frequency ) { return true; }
+    /*!
+     * \brief Computes the packet time on air for the given payload
+     *
+     * \Remark Can only be called once SetRxConfig or SetTxConfig have been called
+     *
+     * \param [IN] modem      Radio modem to be used [0: FSK, 1: LoRa]
+     * \param [IN] pktLen     Packet payload length
+     *
+     * \retval airTime        Computed airTime for the given packet payload length
+     */
+    virtual double TimeOnAir( RadioModems_t modem, uint8_t pktLen ) = 0;
+    /*!
+     * \brief Sends the buffer of size. Prepares the packet to be sent and sets
+     *        the radio in transmission
+     *
+     * \param [IN]: buffer     Buffer pointer
+     * \param [IN]: size       Buffer size
+     */
+    virtual void Send( const uint8_t *buffer, uint8_t size ) = 0;
+    /*!
+     * \brief Sets the radio in sleep mode
+     */
+    virtual void Sleep( void ) = 0;
+    /*!
+     * \brief Sets the radio in standby mode
+     */
+    virtual void Standby( void ) = 0;
+    /*!
+     * \brief Sets the radio in reception mode for the given time
+     * \param [IN] timeout Reception timeout [us]
+     *                     [0: continuous, others timeout]
+     */
+    virtual void Rx( uint32_t timeout ) = 0;
+    /*!
+     * \brief Start a Channel Activity Detection
+     */
+    virtual void StartCad( void ) = 0;
+    /*!
+     * \brief Reads the current RSSI value
+     *
+     * \retval rssiValue Current RSSI value in [dBm]
+     */
+    virtual int16_t Rssi( RadioModems_t modem ) = 0;
+    /*!
+     * \brief Writes the radio register at the specified address
+     *
+     * \param [IN]: addr Register address
+     * \param [IN]: data New register value
+     */
+    virtual void Write( uint8_t addr, uint8_t data ) = 0;
+    /*!
+     * \brief Reads the radio register at the specified address
+     *
+     * \param [IN]: addr Register address
+     * \retval data Register value
+     */
+    virtual uint8_t Read ( uint8_t addr ) = 0;
+    /*!
+     * \brief Writes multiple radio registers starting at address
+     *
+     * \param [IN] addr   First Radio register address
+     * \param [IN] buffer Buffer containing the new register's values
+     * \param [IN] size   Number of registers to be written
+     */
+    virtual void WriteBuffer( uint8_t addr, const uint8_t *buffer, uint8_t size ) = 0;
+    /*!
+     * \brief Reads multiple radio registers starting at address
+     *
+     * \param [IN] addr First Radio register address
+     * \param [OUT] buffer Buffer where to copy the registers data
+     * \param [IN] size Number of registers to be read
+     */
+    virtual void ReadBuffer( uint8_t addr, uint8_t *buffer, uint8_t size ) = 0;
+
+    virtual void SignalMacEvent(void) {};
+
+    virtual void ResetRadio(void) {};
+
+    virtual uint32_t GetTimeOnAir(void) = 0;
+
+    void GrabMutex(void) { mutex.lock(); }
+    void ReleaseMutex(void) { mutex.unlock(); }
+
+    const uint32_t WakeupTime;
+
+protected:
+    RadioState_t State;
+
+    RadioModems_t Modem;
+
+    /*!
+     * Access protection
+     */
+    Mutex mutex;
+};
+
+#endif // __SXRADIO_H__
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/Lora/Radio/SxRadio1272.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,499 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2013 Semtech
+
+Description: Generic SX1272 driver implementation
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Miguel Luis and Gregory Cristian
+*/
+#ifndef __SXRADIO1272_H__
+#define __SXRADIO1272_H__
+
+#include "SxRadio.h"
+#include "SxRadio1272Regs-Fsk.h"
+#include "SxRadio1272Regs-LoRa.h"
+
+/*!
+ * Radio wakeup time from SLEEP mode
+ */
+#if defined(TARGET_XDOT_L151CC)
+#define RADIO_WAKEUP_TIME                           4 // [ms]
+#else
+#define RADIO_WAKEUP_TIME                           2 // [ms]
+#endif
+
+/*!
+ * SX1272 definitions
+ */
+#define XTAL_FREQ                                   32000000
+#define FREQ_STEP                                   61.03515625
+
+#define RX_BUFFER_SIZE                              256
+
+/*!
+ * ============================================================================
+ * Public functions prototypes
+ * ============================================================================
+ */
+
+class SxRadio1272 : public SxRadio
+{
+public:
+    enum Bandwidth {
+        BW_125, BW_250, BW_500
+    };
+
+    SxRadio1272(PinName reset, PinName DIO0, PinName DIO1, PinName DIO2,
+                PinName DIO3, PinName DIO4, PinName mosi, PinName miso,
+                PinName sclk, PinName nss, osPriority priority = osPriorityAboveNormal);
+    virtual ~SxRadio1272() {}
+
+    /*!
+     * \brief Initializes the radio
+     *
+     * \param [IN] events Structure containing the driver callback functions
+     */
+    virtual void Init( SxRadioEvents *events );
+    /*!
+     * \brief Prepares the radio for destruction
+     */
+    virtual void Terminate( void );
+    /*!
+     * \brief Configures the radio with the given modem
+     *
+     * \param [IN] modem Modem to be used [0: FSK, 1: LoRa] 
+     */
+    virtual void SetModem( RadioModems_t modem );
+    /*!
+     * \brief Sets the channel frequency
+     *
+     * \param [IN] freq         Channel RF frequency
+     */
+    virtual void SetChannel( uint32_t freq );
+    /*!
+     * \brief Detect channel free using CAD
+     *
+     * \param [IN] modem      Radio modem to be used [0: FSK, 1: LoRa]
+     * \param [IN] freq       Channel RF frequency
+     * \param [IN] rssiThresh RSSI threshold
+     * \param [IN] bandwidth 0:125k, 1:250k, 2:500k
+     * \param [IN] rssiVal    pointer to variable to hold RSSI value if desired - ignored if NULL
+     *
+     * \retval isFree         [true: Channel is free, false: Channel is not free]
+     */
+    virtual bool IsChannelFree( RadioModems_t modem, uint32_t freq, uint8_t datarate, int16_t rssiThresh, uint8_t bandwidth, uint32_t timeout = 5000, int16_t *rssiVal = NULL );
+    /*!
+     * \brief Generates a 32 bits random value based on the RSSI readings
+     *
+     * \remark This function sets the radio in LoRa modem mode and disables 
+     *         all interrupts.
+     *         After calling this function either Radio.SetRxConfig or
+     *         Radio.SetTxConfig functions must be called.
+     *
+     * \retval randomValue    32 bits random value
+     */
+    virtual uint32_t Random( void );
+    /*!
+     * \brief Sets the reception parameters
+     *
+     * \param [IN] modem        Radio modem to be used [0: FSK, 1: LoRa]
+     * \param [IN] bandwidth    Sets the bandwidth
+     *                          FSK : >= 2600 and <= 250000 Hz
+     *                          LoRa: [0: 125 kHz, 1: 250 kHz,
+     *                                 2: 500 kHz, 3: Reserved] 
+     * \param [IN] datarate     Sets the Datarate
+     *                          FSK : 600..300000 bits/s
+     *                          LoRa: [6: 64, 7: 128, 8: 256, 9: 512,
+     *                                10: 1024, 11: 2048, 12: 4096  chips]
+     * \param [IN] coderate     Sets the coding rate (LoRa only)
+     *                          FSK : N/A ( set to 0 )
+     *                          LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8] 
+     * \param [IN] bandwidthAfc Sets the AFC Bandwidth (FSK only) 
+     *                          FSK : >= 2600 and <= 250000 Hz
+     *                          LoRa: N/A ( set to 0 ) 
+     * \param [IN] preambleLen  Sets the Preamble length
+     *                          FSK : Number of bytes 
+     *                          LoRa: Length in symbols (the hardware adds 4 more symbols)
+     * \param [IN] symbTimeout  Sets the RxSingle timeout value (LoRa only) 
+     *                          FSK : N/A ( set to 0 ) 
+     *                          LoRa: timeout in symbols
+     * \param [IN] fixLen       Fixed length packets [0: variable, 1: fixed]
+     * \param [IN] payloadLen   Sets payload length when fixed length is used
+     * \param [IN] crcOn        Enables/Disables the CRC [0: OFF, 1: ON]
+     * \param [IN] FreqHopOn    Enables disables the intra-packet frequency hopping
+     *                          FSK : N/A ( set to 0 )
+     *                          LoRa: [0: OFF, 1: ON]
+     * \param [IN] HopPeriod    Number of symbols bewteen each hop
+     *                          FSK : N/A ( set to 0 )
+     *                          LoRa: Number of symbols
+     * \param [IN] iqInverted   Inverts IQ signals (LoRa only)
+     *                          FSK : N/A ( set to 0 )
+     *                          LoRa: [0: not inverted, 1: inverted]
+     * \param [IN] rxContinuous Sets the reception in continuous mode
+     *                          [false: single mode, true: continuous mode]
+     */
+    virtual void SetRxConfig( RadioModems_t modem, uint32_t bandwidth,
+                              uint32_t datarate, uint8_t coderate,
+                              uint32_t bandwidthAfc, uint16_t preambleLen,
+                              uint16_t symbTimeout, bool fixLen,
+                              uint8_t payloadLen,
+                              bool crcOn, bool FreqHopOn, uint8_t HopPeriod,
+                              bool iqInverted, bool rxContinuous );
+    /*!
+     * \brief Sets the transmission parameters
+     *
+     * \param [IN] modem        Radio modem to be used [0: FSK, 1: LoRa] 
+     * \param [IN] power        Sets the output power [dBm]
+     * \param [IN] fdev         Sets the frequency deviation (FSK only)
+     *                          FSK : [Hz]
+     *                          LoRa: 0
+     * \param [IN] bandwidth    Sets the bandwidth (LoRa only)
+     *                          FSK : 0
+     *                          LoRa: [0: 125 kHz, 1: 250 kHz,
+     *                                 2: 500 kHz, 3: Reserved] 
+     * \param [IN] datarate     Sets the Datarate
+     *                          FSK : 600..300000 bits/s
+     *                          LoRa: [6: 64, 7: 128, 8: 256, 9: 512,
+     *                                10: 1024, 11: 2048, 12: 4096  chips]
+     * \param [IN] coderate     Sets the coding rate (LoRa only)
+     *                          FSK : N/A ( set to 0 )
+     *                          LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8] 
+     * \param [IN] preambleLen  Sets the preamble length
+     *                          FSK : Number of bytes 
+     *                          LoRa: Length in symbols (the hardware adds 4 more symbols)
+     * \param [IN] fixLen       Fixed length packets [0: variable, 1: fixed]
+     * \param [IN] crcOn        Enables disables the CRC [0: OFF, 1: ON]
+     * \param [IN] FreqHopOn    Enables disables the intra-packet frequency hopping
+     *                          FSK : N/A ( set to 0 )
+     *                          LoRa: [0: OFF, 1: ON]
+     * \param [IN] HopPeriod    Number of symbols bewteen each hop
+     *                          FSK : N/A ( set to 0 )
+     *                          LoRa: Number of symbols
+     * \param [IN] iqInverted   Inverts IQ signals (LoRa only)
+     *                          FSK : N/A ( set to 0 )
+     *                          LoRa: [0: not inverted, 1: inverted]
+     * \param [IN] timeout      Transmission timeout [us]
+     */
+    virtual void SetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev, 
+                              uint32_t bandwidth, uint32_t datarate,
+                              uint8_t coderate, uint16_t preambleLen,
+                              bool fixLen, bool crcOn, bool FreqHopOn,
+                              uint8_t HopPeriod, bool iqInverted, uint32_t timeout );
+
+    /**
+     * Generate CW with current TX config
+     */
+    virtual void SetTxContinuous(bool enable);
+
+    /*!
+     * \brief Computes the packet time on air for the given payload
+     *
+     * \Remark Can only be called once SetRxConfig or SetTxConfig have been called
+     *
+     * \param [IN] modem      Radio modem to be used [0: FSK, 1: LoRa]
+     * \param [IN] pktLen     Packet payload length
+     *
+     * \retval airTime        Computed airTime for the given packet payload length
+     */
+    virtual double TimeOnAir( RadioModems_t modem, uint8_t pktLen );
+    /*!
+     * \brief Sends the buffer of size. Prepares the packet to be sent and sets
+     *        the radio in transmission
+     *
+     * \param [IN]: buffer     Buffer pointer
+     * \param [IN]: size       Buffer size
+     */
+    virtual void Send( const uint8_t *buffer, uint8_t size );
+    /*!
+     * \brief Sets the radio in sleep mode
+     */
+    virtual void Sleep( void );
+    /*!
+     * \brief Sets the radio in standby mode
+     */
+    virtual void Standby( void );
+    /*!
+     * \brief Sets the radio in reception mode for the given time
+     * \param [IN] timeout Reception timeout [ms]
+     *                     [0: continuous, others timeout]
+     */
+    virtual void Rx( uint32_t timeout );
+    /*!
+     * \brief Start a Channel Activity Detection
+     */
+    virtual void StartCad( void );
+    /*!
+     * \brief Reads the current RSSI value
+     *
+     * \retval rssiValue Current RSSI value in [dBm]
+     */
+    virtual int16_t Rssi( RadioModems_t modem );
+    /*!
+     * \brief Writes the radio register at the specified address
+     *
+     * \param [IN]: addr Register address
+     * \param [IN]: data New register value
+     */
+    virtual void Write( uint8_t addr, uint8_t data );
+    /*!
+     * \brief Reads the radio register at the specified address
+     *
+     * \param [IN]: addr Register address
+     * \retval data Register value
+     */
+    virtual uint8_t Read ( uint8_t addr );
+    /*!
+     * \brief Writes multiple radio registers starting at address
+     *
+     * \param [IN] addr   First Radio register address
+     * \param [IN] buffer Buffer containing the new register's values
+     * \param [IN] size   Number of registers to be written
+     */
+    virtual void WriteBuffer( uint8_t addr, const uint8_t *buffer, uint8_t size );
+    /*!
+     * \brief Reads multiple radio registers starting at address
+     *
+     * \param [IN] addr First Radio register address
+     * \param [OUT] buffer Buffer where to copy the registers data
+     * \param [IN] size Number of registers to be read
+     */
+    virtual void ReadBuffer( uint8_t addr, uint8_t *buffer, uint8_t size );
+
+    virtual void SignalMacEvent(void);
+
+    virtual void CheckForReset(void);
+    
+    virtual void ResetRadio();
+
+    virtual uint32_t GetTimeOnAir();
+protected:
+    /*!
+     * \brief Set antenna switch to low power
+     *
+     * \param [IN] status [true: Antenna in low power, false: Antenna active]
+     */
+    virtual void SetAntSwLowPower( bool status ) { }
+
+    /*!
+     * \brief Set antenna direction
+     *
+     * \param [IN] rxTx [1: transmitter, 0: receiver]
+     */
+    virtual void SetAntSw( uint8_t rxTx ) { }
+
+    /*!
+     * \brief Get power amp setting
+     *
+     * \param [IN] channel Channel RF frequency
+     *
+     * \retval Power amp setting
+     */
+    virtual uint8_t GetPaSelect( uint32_t channel )
+    {
+        return RF_PACONFIG_PASELECT_PABOOST;
+    }
+
+private:
+    /*!
+     * Radio registers definition
+     */
+    typedef struct
+    {
+        RadioModems_t Modem;
+        uint8_t       Addr;
+        uint8_t       Value;
+    }RadioRegisters_t;
+
+    /*!
+     * Radio FSK modem parameters
+     */
+    typedef struct
+    {
+        int8_t   Power;
+        uint32_t Fdev;
+        uint32_t Bandwidth;
+        uint32_t BandwidthAfc;
+        uint32_t Datarate;
+        uint16_t PreambleLen;
+        bool     FixLen;
+        uint8_t  PayloadLen;
+        bool     CrcOn;
+        bool     IqInverted;
+        bool     RxContinuous;
+        uint32_t TxTimeout;
+    }RadioFskSettings_t;
+
+    /*!
+     * Radio FSK packet handler state
+     */
+    typedef struct
+    {
+        bool  SyncWordDetected;
+        int8_t   RssiValue;
+        int32_t  AfcValue;
+        uint8_t  RxGain;
+        uint16_t Size;
+        uint16_t NbBytes;
+        uint8_t  FifoThresh;
+        uint8_t  ChunkSize;
+    }RadioFskPacketHandler_t;
+
+    /*!
+     * Radio LoRa modem parameters
+     */
+    typedef struct
+    {
+        int8_t   Power;
+        uint32_t Bandwidth;
+        uint32_t Datarate;
+        bool     LowDatarateOptimize;
+        uint8_t  Coderate;
+        uint16_t PreambleLen;
+        bool     FixLen;
+        uint8_t  PayloadLen;
+        bool     CrcOn;
+        bool     FreqHopOn;
+        uint8_t  HopPeriod;
+        bool     IqInverted;
+        bool     RxContinuous;
+        uint32_t TxTimeout;
+    }RadioLoRaSettings_t;
+
+    /*!
+     * Radio LoRa packet handler state
+     */
+    typedef struct
+    {
+        int8_t SnrValue;
+        int16_t RssiValue;
+        uint8_t Size;
+    }RadioLoRaPacketHandler_t;
+
+    /*!
+     * Radio Settings
+     */
+    typedef struct
+    {
+        uint32_t                 Channel;
+        RadioFskSettings_t       Fsk;
+        RadioFskPacketHandler_t  FskPacketHandler;
+        RadioLoRaSettings_t      LoRa;
+        RadioLoRaPacketHandler_t LoRaPacketHandler;
+    }RadioSettings_t;
+
+    /*!
+     * \brief Resets the SX1272
+     */
+    void Reset( void );
+
+    /*!
+     * \brief Sets the SX1272 operating mode
+     *
+     * \param [IN] opMode New operating mode
+     */
+    void SetOpMode( uint8_t opMode );
+
+    /*!
+     * \brief Sets the SX1272 in transmission mode for the given time
+     * \param [IN] timeout Transmission timeout [ms] [0: continuous, others timeout]
+     */
+    void SetTx( uint32_t timeout );
+
+    /*!
+     * \brief Writes the buffer contents to the SX1272 FIFO
+     *
+     * \param [IN] buffer Buffer containing data to be put on the FIFO.
+     * \param [IN] size Number of bytes to be written to the FIFO
+     */
+    void WriteFifo( const uint8_t *buffer, uint8_t size );
+
+    /*!
+     * \brief Reads the contents of the SX1272 FIFO
+     *
+     * \param [OUT] buffer Buffer where to copy the FIFO read data.
+     * \param [IN] size Number of bytes to be read from the FIFO
+     */
+    void ReadFifo( uint8_t *buffer, uint8_t size );
+
+    static void OnRxTxTimeoutIrq( void const *arg );
+    static void OnSyncTimeoutIrq( void const *arg );
+    void OnTimeoutIrqBottom( void );
+    void SX1272OnDioIrq( void );
+    void SX1272OnDio3Irq( void );
+    void SX1272OnDio1Irq( void );
+
+    void SX1272IrqTxDone();
+    void SX1272IrqFskRxDone(uint8_t irqFlags2);
+    void SX1272IrqFskFifoLevel(void);
+    void SX1272IrqFskFifoEmpty(void);
+    void SX1272IrqFskSyncMatch(void);
+    void SX1272IrqFsk(void);
+    void SX1272IrqLoraRxDone(uint8_t irqFlags);
+    void SX1272IrqLoraRxTimeout();
+    void SX1272IrqLoraCadDone(uint8_t irqFlags);
+    void SX1272IrqLoraFhss(void);
+    void SX1272IrqLora(void);
+    void SX1272Irq(void);
+
+    static void RadioThread(void const *args);
+
+    /*!
+     * Interrupt thread
+     */
+    Thread thread;
+    uint64_t Stack[2560/8];        // 2.5kB stack for the radio thread
+				   //align stack fix for ARM mbed 5.5.* custom stack error
+
+    /*!
+     * Reset IO line
+     */
+    DigitalInOut reset;
+
+    InterruptIn DIO3;
+    InterruptIn DIO4;
+    InterruptIn DIO0;
+    InterruptIn DIO1;
+    InterruptIn DIO2;
+
+
+    SPI spi;
+    /*!
+     * SPI slave select
+     */
+    DigitalOut nss;
+
+    /*!
+     * Event callback handler
+     */
+    SxRadioEvents *RadioEvents;
+
+    /*!
+     * Reception buffer
+     */
+    uint8_t RxTxBuffer[RX_BUFFER_SIZE];
+
+    /*!
+     * Radio hardware and global parameters
+     */
+    RadioSettings_t settings;
+
+    RtosTimer TxTimeoutTimer;
+    RtosTimer RxTimeoutTimer;
+    RtosTimer RxTimeoutSyncWord;
+
+    bool RxTxTimeoutPending;
+    bool SyncTimeoutPending;
+
+    uint8_t opMode;
+    uint32_t timeOnAir;
+    
+    static const RadioRegisters_t RadioRegsInit[];
+};
+
+#endif // __SXRADIO1272_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/Lora/Radio/SxRadio1272Regs-Fsk.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,1135 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2013 Semtech
+
+Description: SX1272 FSK modem registers and bits definitions
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Miguel Luis and Gregory Cristian
+*/
+#ifndef __SX1272_REGS_FSK_H__
+#define __SX1272_REGS_FSK_H__
+
+/*!
+ * ============================================================================
+ * SX1272 Internal registers Address
+ * ============================================================================
+ */
+#define REG_FIFO                                    0x00
+// Common settings
+#define REG_OPMODE                                  0x01
+#define REG_BITRATEMSB                              0x02
+#define REG_BITRATELSB                              0x03
+#define REG_FDEVMSB                                 0x04 
+#define REG_FDEVLSB                                 0x05
+#define REG_FRFMSB                                  0x06
+#define REG_FRFMID                                  0x07
+#define REG_FRFLSB                                  0x08
+// Tx settings
+#define REG_PACONFIG                                0x09
+#define REG_PARAMP                                  0x0A
+#define REG_OCP                                     0x0B 
+// Rx settings
+#define REG_LNA                                     0x0C
+#define REG_RXCONFIG                                0x0D
+#define REG_RSSICONFIG                              0x0E
+#define REG_RSSICOLLISION                           0x0F
+#define REG_RSSITHRESH                              0x10
+#define REG_RSSIVALUE                               0x11
+#define REG_RXBW                                    0x12 
+#define REG_AFCBW                                   0x13
+#define REG_OOKPEAK                                 0x14
+#define REG_OOKFIX                                  0x15
+#define REG_OOKAVG                                  0x16
+#define REG_RES17                                   0x17
+#define REG_RES18                                   0x18
+#define REG_RES19                                   0x19
+#define REG_AFCFEI                                  0x1A
+#define REG_AFCMSB                                  0x1B
+#define REG_AFCLSB                                  0x1C
+#define REG_FEIMSB                                  0x1D
+#define REG_FEILSB                                  0x1E
+#define REG_PREAMBLEDETECT                          0x1F
+#define REG_RXTIMEOUT1                              0x20
+#define REG_RXTIMEOUT2                              0x21
+#define REG_RXTIMEOUT3                              0x22
+#define REG_RXDELAY                                 0x23
+// Oscillator settings
+#define REG_OSC                                     0x24
+// Packet handler settings
+#define REG_PREAMBLEMSB                             0x25
+#define REG_PREAMBLELSB                             0x26
+#define REG_SYNCCONFIG                              0x27
+#define REG_SYNCVALUE1                              0x28
+#define REG_SYNCVALUE2                              0x29
+#define REG_SYNCVALUE3                              0x2A
+#define REG_SYNCVALUE4                              0x2B
+#define REG_SYNCVALUE5                              0x2C
+#define REG_SYNCVALUE6                              0x2D
+#define REG_SYNCVALUE7                              0x2E
+#define REG_SYNCVALUE8                              0x2F
+#define REG_PACKETCONFIG1                           0x30
+#define REG_PACKETCONFIG2                           0x31
+#define REG_PAYLOADLENGTH                           0x32
+#define REG_NODEADRS                                0x33
+#define REG_BROADCASTADRS                           0x34
+#define REG_FIFOTHRESH                              0x35
+// SM settings
+#define REG_SEQCONFIG1                              0x36
+#define REG_SEQCONFIG2                              0x37
+#define REG_TIMERRESOL                              0x38
+#define REG_TIMER1COEF                              0x39
+#define REG_TIMER2COEF                              0x3A
+// Service settings
+#define REG_IMAGECAL                                0x3B
+#define REG_TEMP                                    0x3C
+#define REG_LOWBAT                                  0x3D
+// Status
+#define REG_IRQFLAGS1                               0x3E
+#define REG_IRQFLAGS2                               0x3F
+// I/O settings
+#define REG_DIOMAPPING1                             0x40
+#define REG_DIOMAPPING2                             0x41
+// Version
+#define REG_VERSION                                 0x42
+// Additional settings
+#define REG_AGCREF                                  0x43
+#define REG_AGCTHRESH1                              0x44
+#define REG_AGCTHRESH2                              0x45
+#define REG_AGCTHRESH3                              0x46
+#define REG_PLLHOP                                  0x4B
+#define REG_TCXO                                    0x58
+#define REG_PADAC                                   0x5A
+#define REG_PLL                                     0x5C
+#define REG_PLLLOWPN                                0x5E
+#define REG_FORMERTEMP                              0x6C
+#define REG_BITRATEFRAC                             0x70
+
+/*!
+ * ============================================================================
+ * SX1272 FSK bits control definition
+ * ============================================================================
+ */
+
+/*!
+ * RegFifo
+ */
+
+/*!
+ * RegOpMode
+ */
+#define RF_OPMODE_LONGRANGEMODE_MASK                0x7F
+#define RF_OPMODE_LONGRANGEMODE_OFF                 0x00
+#define RF_OPMODE_LONGRANGEMODE_ON                  0x80
+
+#define RF_OPMODE_MODULATIONTYPE_MASK               0x9F
+#define RF_OPMODE_MODULATIONTYPE_FSK                0x00  // Default
+#define RF_OPMODE_MODULATIONTYPE_OOK                0x20
+
+#define RF_OPMODE_MODULATIONSHAPING_MASK            0xE7
+#define RF_OPMODE_MODULATIONSHAPING_00              0x00  // Default
+#define RF_OPMODE_MODULATIONSHAPING_01              0x08
+#define RF_OPMODE_MODULATIONSHAPING_10              0x10
+#define RF_OPMODE_MODULATIONSHAPING_11              0x18
+
+#define RF_OPMODE_MASK                              0xF8
+#define RF_OPMODE_SLEEP                             0x00
+#define RF_OPMODE_STANDBY                           0x01  // Default
+#define RF_OPMODE_SYNTHESIZER_TX                    0x02
+#define RF_OPMODE_TRANSMITTER                       0x03
+#define RF_OPMODE_SYNTHESIZER_RX                    0x04
+#define RF_OPMODE_RECEIVER                          0x05
+
+/*!
+ * RegBitRate (bits/sec)
+ */
+#define RF_BITRATEMSB_1200_BPS                      0x68
+#define RF_BITRATELSB_1200_BPS                      0x2B
+#define RF_BITRATEMSB_2400_BPS                      0x34
+#define RF_BITRATELSB_2400_BPS                      0x15
+#define RF_BITRATEMSB_4800_BPS                      0x1A  // Default
+#define RF_BITRATELSB_4800_BPS                      0x0B  // Default
+#define RF_BITRATEMSB_9600_BPS                      0x0D
+#define RF_BITRATELSB_9600_BPS                      0x05
+#define RF_BITRATEMSB_15000_BPS                     0x08
+#define RF_BITRATELSB_15000_BPS                     0x55
+#define RF_BITRATEMSB_19200_BPS                     0x06
+#define RF_BITRATELSB_19200_BPS                     0x83
+#define RF_BITRATEMSB_38400_BPS                     0x03
+#define RF_BITRATELSB_38400_BPS                     0x41
+#define RF_BITRATEMSB_76800_BPS                     0x01
+#define RF_BITRATELSB_76800_BPS                     0xA1
+#define RF_BITRATEMSB_153600_BPS                    0x00
+#define RF_BITRATELSB_153600_BPS                    0xD0
+#define RF_BITRATEMSB_57600_BPS                     0x02
+#define RF_BITRATELSB_57600_BPS                     0x2C
+#define RF_BITRATEMSB_115200_BPS                    0x01
+#define RF_BITRATELSB_115200_BPS                    0x16
+#define RF_BITRATEMSB_12500_BPS                     0x0A
+#define RF_BITRATELSB_12500_BPS                     0x00
+#define RF_BITRATEMSB_25000_BPS                     0x05
+#define RF_BITRATELSB_25000_BPS                     0x00
+#define RF_BITRATEMSB_50000_BPS                     0x02
+#define RF_BITRATELSB_50000_BPS                     0x80
+#define RF_BITRATEMSB_100000_BPS                    0x01
+#define RF_BITRATELSB_100000_BPS                    0x40
+#define RF_BITRATEMSB_150000_BPS                    0x00
+#define RF_BITRATELSB_150000_BPS                    0xD5
+#define RF_BITRATEMSB_200000_BPS                    0x00
+#define RF_BITRATELSB_200000_BPS                    0xA0
+#define RF_BITRATEMSB_250000_BPS                    0x00
+#define RF_BITRATELSB_250000_BPS                    0x80
+#define RF_BITRATEMSB_32768_BPS                     0x03
+#define RF_BITRATELSB_32768_BPS                     0xD1
+
+/*!
+ * RegFdev (Hz)
+ */
+#define RF_FDEVMSB_2000_HZ                          0x00
+#define RF_FDEVLSB_2000_HZ                          0x21
+#define RF_FDEVMSB_5000_HZ                          0x00  // Default
+#define RF_FDEVLSB_5000_HZ                          0x52  // Default
+#define RF_FDEVMSB_10000_HZ                         0x00
+#define RF_FDEVLSB_10000_HZ                         0xA4
+#define RF_FDEVMSB_15000_HZ                         0x00
+#define RF_FDEVLSB_15000_HZ                         0xF6
+#define RF_FDEVMSB_20000_HZ                         0x01
+#define RF_FDEVLSB_20000_HZ                         0x48
+#define RF_FDEVMSB_25000_HZ                         0x01
+#define RF_FDEVLSB_25000_HZ                         0x9A
+#define RF_FDEVMSB_30000_HZ                         0x01
+#define RF_FDEVLSB_30000_HZ                         0xEC
+#define RF_FDEVMSB_35000_HZ                         0x02
+#define RF_FDEVLSB_35000_HZ                         0x3D
+#define RF_FDEVMSB_40000_HZ                         0x02
+#define RF_FDEVLSB_40000_HZ                         0x8F
+#define RF_FDEVMSB_45000_HZ                         0x02
+#define RF_FDEVLSB_45000_HZ                         0xE1
+#define RF_FDEVMSB_50000_HZ                         0x03
+#define RF_FDEVLSB_50000_HZ                         0x33
+#define RF_FDEVMSB_55000_HZ                         0x03
+#define RF_FDEVLSB_55000_HZ                         0x85
+#define RF_FDEVMSB_60000_HZ                         0x03
+#define RF_FDEVLSB_60000_HZ                         0xD7
+#define RF_FDEVMSB_65000_HZ                         0x04
+#define RF_FDEVLSB_65000_HZ                         0x29
+#define RF_FDEVMSB_70000_HZ                         0x04
+#define RF_FDEVLSB_70000_HZ                         0x7B
+#define RF_FDEVMSB_75000_HZ                         0x04
+#define RF_FDEVLSB_75000_HZ                         0xCD
+#define RF_FDEVMSB_80000_HZ                         0x05
+#define RF_FDEVLSB_80000_HZ                         0x1F
+#define RF_FDEVMSB_85000_HZ                         0x05
+#define RF_FDEVLSB_85000_HZ                         0x71
+#define RF_FDEVMSB_90000_HZ                         0x05
+#define RF_FDEVLSB_90000_HZ                         0xC3
+#define RF_FDEVMSB_95000_HZ                         0x06
+#define RF_FDEVLSB_95000_HZ                         0x14
+#define RF_FDEVMSB_100000_HZ                        0x06
+#define RF_FDEVLSB_100000_HZ                        0x66
+#define RF_FDEVMSB_110000_HZ                        0x07
+#define RF_FDEVLSB_110000_HZ                        0x0A
+#define RF_FDEVMSB_120000_HZ                        0x07
+#define RF_FDEVLSB_120000_HZ                        0xAE
+#define RF_FDEVMSB_130000_HZ                        0x08
+#define RF_FDEVLSB_130000_HZ                        0x52
+#define RF_FDEVMSB_140000_HZ                        0x08
+#define RF_FDEVLSB_140000_HZ                        0xF6
+#define RF_FDEVMSB_150000_HZ                        0x09
+#define RF_FDEVLSB_150000_HZ                        0x9A
+#define RF_FDEVMSB_160000_HZ                        0x0A
+#define RF_FDEVLSB_160000_HZ                        0x3D
+#define RF_FDEVMSB_170000_HZ                        0x0A
+#define RF_FDEVLSB_170000_HZ                        0xE1
+#define RF_FDEVMSB_180000_HZ                        0x0B
+#define RF_FDEVLSB_180000_HZ                        0x85
+#define RF_FDEVMSB_190000_HZ                        0x0C
+#define RF_FDEVLSB_190000_HZ                        0x29
+#define RF_FDEVMSB_200000_HZ                        0x0C
+#define RF_FDEVLSB_200000_HZ                        0xCD
+
+/*!
+ * RegFrf (MHz)
+ */
+#define RF_FRFMSB_863_MHZ                           0xD7
+#define RF_FRFMID_863_MHZ                           0xC0
+#define RF_FRFLSB_863_MHZ                           0x00
+#define RF_FRFMSB_864_MHZ                           0xD8
+#define RF_FRFMID_864_MHZ                           0x00
+#define RF_FRFLSB_864_MHZ                           0x00
+#define RF_FRFMSB_865_MHZ                           0xD8
+#define RF_FRFMID_865_MHZ                           0x40
+#define RF_FRFLSB_865_MHZ                           0x00
+#define RF_FRFMSB_866_MHZ                           0xD8
+#define RF_FRFMID_866_MHZ                           0x80
+#define RF_FRFLSB_866_MHZ                           0x00
+#define RF_FRFMSB_867_MHZ                           0xD8
+#define RF_FRFMID_867_MHZ                           0xC0
+#define RF_FRFLSB_867_MHZ                           0x00
+#define RF_FRFMSB_868_MHZ                           0xD9
+#define RF_FRFMID_868_MHZ                           0x00
+#define RF_FRFLSB_868_MHZ                           0x00
+#define RF_FRFMSB_869_MHZ                           0xD9
+#define RF_FRFMID_869_MHZ                           0x40
+#define RF_FRFLSB_869_MHZ                           0x00
+#define RF_FRFMSB_870_MHZ                           0xD9
+#define RF_FRFMID_870_MHZ                           0x80
+#define RF_FRFLSB_870_MHZ                           0x00
+
+#define RF_FRFMSB_902_MHZ                           0xE1
+#define RF_FRFMID_902_MHZ                           0x80
+#define RF_FRFLSB_902_MHZ                           0x00
+#define RF_FRFMSB_903_MHZ                           0xE1
+#define RF_FRFMID_903_MHZ                           0xC0
+#define RF_FRFLSB_903_MHZ                           0x00
+#define RF_FRFMSB_904_MHZ                           0xE2
+#define RF_FRFMID_904_MHZ                           0x00
+#define RF_FRFLSB_904_MHZ                           0x00
+#define RF_FRFMSB_905_MHZ                           0xE2
+#define RF_FRFMID_905_MHZ                           0x40
+#define RF_FRFLSB_905_MHZ                           0x00
+#define RF_FRFMSB_906_MHZ                           0xE2
+#define RF_FRFMID_906_MHZ                           0x80
+#define RF_FRFLSB_906_MHZ                           0x00
+#define RF_FRFMSB_907_MHZ                           0xE2
+#define RF_FRFMID_907_MHZ                           0xC0
+#define RF_FRFLSB_907_MHZ                           0x00
+#define RF_FRFMSB_908_MHZ                           0xE3
+#define RF_FRFMID_908_MHZ                           0x00
+#define RF_FRFLSB_908_MHZ                           0x00
+#define RF_FRFMSB_909_MHZ                           0xE3
+#define RF_FRFMID_909_MHZ                           0x40
+#define RF_FRFLSB_909_MHZ                           0x00
+#define RF_FRFMSB_910_MHZ                           0xE3
+#define RF_FRFMID_910_MHZ                           0x80
+#define RF_FRFLSB_910_MHZ                           0x00
+#define RF_FRFMSB_911_MHZ                           0xE3
+#define RF_FRFMID_911_MHZ                           0xC0
+#define RF_FRFLSB_911_MHZ                           0x00
+#define RF_FRFMSB_912_MHZ                           0xE4
+#define RF_FRFMID_912_MHZ                           0x00
+#define RF_FRFLSB_912_MHZ                           0x00
+#define RF_FRFMSB_913_MHZ                           0xE4
+#define RF_FRFMID_913_MHZ                           0x40
+#define RF_FRFLSB_913_MHZ                           0x00
+#define RF_FRFMSB_914_MHZ                           0xE4
+#define RF_FRFMID_914_MHZ                           0x80
+#define RF_FRFLSB_914_MHZ                           0x00
+#define RF_FRFMSB_915_MHZ                           0xE4  // Default
+#define RF_FRFMID_915_MHZ                           0xC0  // Default
+#define RF_FRFLSB_915_MHZ                           0x00  // Default
+#define RF_FRFMSB_916_MHZ                           0xE5
+#define RF_FRFMID_916_MHZ                           0x00
+#define RF_FRFLSB_916_MHZ                           0x00
+#define RF_FRFMSB_917_MHZ                           0xE5
+#define RF_FRFMID_917_MHZ                           0x40
+#define RF_FRFLSB_917_MHZ                           0x00
+#define RF_FRFMSB_918_MHZ                           0xE5
+#define RF_FRFMID_918_MHZ                           0x80
+#define RF_FRFLSB_918_MHZ                           0x00
+#define RF_FRFMSB_919_MHZ                           0xE5
+#define RF_FRFMID_919_MHZ                           0xC0
+#define RF_FRFLSB_919_MHZ                           0x00
+#define RF_FRFMSB_920_MHZ                           0xE6
+#define RF_FRFMID_920_MHZ                           0x00
+#define RF_FRFLSB_920_MHZ                           0x00
+#define RF_FRFMSB_921_MHZ                           0xE6
+#define RF_FRFMID_921_MHZ                           0x40
+#define RF_FRFLSB_921_MHZ                           0x00
+#define RF_FRFMSB_922_MHZ                           0xE6
+#define RF_FRFMID_922_MHZ                           0x80
+#define RF_FRFLSB_922_MHZ                           0x00
+#define RF_FRFMSB_923_MHZ                           0xE6
+#define RF_FRFMID_923_MHZ                           0xC0
+#define RF_FRFLSB_923_MHZ                           0x00
+#define RF_FRFMSB_924_MHZ                           0xE7
+#define RF_FRFMID_924_MHZ                           0x00
+#define RF_FRFLSB_924_MHZ                           0x00
+#define RF_FRFMSB_925_MHZ                           0xE7
+#define RF_FRFMID_925_MHZ                           0x40
+#define RF_FRFLSB_925_MHZ                           0x00
+#define RF_FRFMSB_926_MHZ                           0xE7
+#define RF_FRFMID_926_MHZ                           0x80
+#define RF_FRFLSB_926_MHZ                           0x00
+#define RF_FRFMSB_927_MHZ                           0xE7
+#define RF_FRFMID_927_MHZ                           0xC0
+#define RF_FRFLSB_927_MHZ                           0x00
+#define RF_FRFMSB_928_MHZ                           0xE8
+#define RF_FRFMID_928_MHZ                           0x00
+#define RF_FRFLSB_928_MHZ                           0x00
+
+/*!
+ * RegPaConfig
+ */
+#define RF_PACONFIG_PASELECT_MASK                   0x7F
+#define RF_PACONFIG_PASELECT_PABOOST                0x80
+#define RF_PACONFIG_PASELECT_RFO                    0x00 // Default
+
+#define RF_PACONFIG_OUTPUTPOWER_MASK                0xF0
+ 
+/*!
+ * RegPaRamp
+ */
+#define RF_PARAMP_LOWPNTXPLL_MASK                   0xE0
+#define RF_PARAMP_LOWPNTXPLL_OFF                    0x10  // Default
+#define RF_PARAMP_LOWPNTXPLL_ON                     0x00
+
+#define RF_PARAMP_MASK                              0xF0
+#define RF_PARAMP_3400_US                           0x00
+#define RF_PARAMP_2000_US                           0x01
+#define RF_PARAMP_1000_US                           0x02
+#define RF_PARAMP_0500_US                           0x03
+#define RF_PARAMP_0250_US                           0x04
+#define RF_PARAMP_0125_US                           0x05
+#define RF_PARAMP_0100_US                           0x06
+#define RF_PARAMP_0062_US                           0x07
+#define RF_PARAMP_0050_US                           0x08
+#define RF_PARAMP_0040_US                           0x09  // Default
+#define RF_PARAMP_0031_US                           0x0A
+#define RF_PARAMP_0025_US                           0x0B
+#define RF_PARAMP_0020_US                           0x0C
+#define RF_PARAMP_0015_US                           0x0D
+#define RF_PARAMP_0012_US                           0x0E
+#define RF_PARAMP_0010_US                           0x0F
+
+/*!
+ * RegOcp
+ */
+#define RF_OCP_MASK                                 0xDF
+#define RF_OCP_ON                                   0x20  // Default
+#define RF_OCP_OFF                                  0x00  
+
+#define RF_OCP_TRIM_MASK                            0xE0
+#define RF_OCP_TRIM_045_MA                          0x00
+#define RF_OCP_TRIM_050_MA                          0x01   
+#define RF_OCP_TRIM_055_MA                          0x02 
+#define RF_OCP_TRIM_060_MA                          0x03 
+#define RF_OCP_TRIM_065_MA                          0x04 
+#define RF_OCP_TRIM_070_MA                          0x05 
+#define RF_OCP_TRIM_075_MA                          0x06 
+#define RF_OCP_TRIM_080_MA                          0x07  
+#define RF_OCP_TRIM_085_MA                          0x08
+#define RF_OCP_TRIM_090_MA                          0x09 
+#define RF_OCP_TRIM_095_MA                          0x0A 
+#define RF_OCP_TRIM_100_MA                          0x0B  // Default
+#define RF_OCP_TRIM_105_MA                          0x0C 
+#define RF_OCP_TRIM_110_MA                          0x0D 
+#define RF_OCP_TRIM_115_MA                          0x0E 
+#define RF_OCP_TRIM_120_MA                          0x0F 
+#define RF_OCP_TRIM_130_MA                          0x10
+#define RF_OCP_TRIM_140_MA                          0x11   
+#define RF_OCP_TRIM_150_MA                          0x12 
+#define RF_OCP_TRIM_160_MA                          0x13 
+#define RF_OCP_TRIM_170_MA                          0x14 
+#define RF_OCP_TRIM_180_MA                          0x15 
+#define RF_OCP_TRIM_190_MA                          0x16 
+#define RF_OCP_TRIM_200_MA                          0x17  
+#define RF_OCP_TRIM_210_MA                          0x18
+#define RF_OCP_TRIM_220_MA                          0x19 
+#define RF_OCP_TRIM_230_MA                          0x1A 
+#define RF_OCP_TRIM_240_MA                          0x1B
+
+/*!
+ * RegLna
+ */
+#define RF_LNA_GAIN_MASK                            0x1F
+#define RF_LNA_GAIN_G1                              0x20  // Default
+#define RF_LNA_GAIN_G2                              0x40
+#define RF_LNA_GAIN_G3                              0x60
+#define RF_LNA_GAIN_G4                              0x80
+#define RF_LNA_GAIN_G5                              0xA0
+#define RF_LNA_GAIN_G6                              0xC0
+
+#define RF_LNA_BOOST_MASK                           0xFC
+#define RF_LNA_BOOST_OFF                            0x00 // Default
+#define RF_LNA_BOOST_ON                             0x03
+
+/*!
+ * RegRxConfig
+ */
+#define RF_RXCONFIG_RESTARTRXONCOLLISION_MASK       0x7F
+#define RF_RXCONFIG_RESTARTRXONCOLLISION_ON         0x80
+#define RF_RXCONFIG_RESTARTRXONCOLLISION_OFF        0x00 // Default
+
+#define RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK         0x40 // Write only
+
+#define RF_RXCONFIG_RESTARTRXWITHPLLLOCK            0x20 // Write only
+
+#define RF_RXCONFIG_AFCAUTO_MASK                    0xEF
+#define RF_RXCONFIG_AFCAUTO_ON                      0x10
+#define RF_RXCONFIG_AFCAUTO_OFF                     0x00 // Default 
+
+#define RF_RXCONFIG_AGCAUTO_MASK                    0xF7
+#define RF_RXCONFIG_AGCAUTO_ON                      0x08 // Default
+#define RF_RXCONFIG_AGCAUTO_OFF                     0x00
+
+#define RF_RXCONFIG_RXTRIGER_MASK                   0xF8
+#define RF_RXCONFIG_RXTRIGER_OFF                    0x00
+#define RF_RXCONFIG_RXTRIGER_RSSI                   0x01
+#define RF_RXCONFIG_RXTRIGER_PREAMBLEDETECT         0x06 // Default
+#define RF_RXCONFIG_RXTRIGER_RSSI_PREAMBLEDETECT    0x07
+
+/*!
+ * RegRssiConfig
+ */
+#define RF_RSSICONFIG_OFFSET_MASK                   0x07
+#define RF_RSSICONFIG_OFFSET_P_00_DB                0x00  // Default
+#define RF_RSSICONFIG_OFFSET_P_01_DB                0x08
+#define RF_RSSICONFIG_OFFSET_P_02_DB                0x10
+#define RF_RSSICONFIG_OFFSET_P_03_DB                0x18
+#define RF_RSSICONFIG_OFFSET_P_04_DB                0x20
+#define RF_RSSICONFIG_OFFSET_P_05_DB                0x28
+#define RF_RSSICONFIG_OFFSET_P_06_DB                0x30
+#define RF_RSSICONFIG_OFFSET_P_07_DB                0x38
+#define RF_RSSICONFIG_OFFSET_P_08_DB                0x40
+#define RF_RSSICONFIG_OFFSET_P_09_DB                0x48
+#define RF_RSSICONFIG_OFFSET_P_10_DB                0x50
+#define RF_RSSICONFIG_OFFSET_P_11_DB                0x58
+#define RF_RSSICONFIG_OFFSET_P_12_DB                0x60
+#define RF_RSSICONFIG_OFFSET_P_13_DB                0x68
+#define RF_RSSICONFIG_OFFSET_P_14_DB                0x70
+#define RF_RSSICONFIG_OFFSET_P_15_DB                0x78
+#define RF_RSSICONFIG_OFFSET_M_16_DB                0x80
+#define RF_RSSICONFIG_OFFSET_M_15_DB                0x88
+#define RF_RSSICONFIG_OFFSET_M_14_DB                0x90
+#define RF_RSSICONFIG_OFFSET_M_13_DB                0x98
+#define RF_RSSICONFIG_OFFSET_M_12_DB                0xA0
+#define RF_RSSICONFIG_OFFSET_M_11_DB                0xA8
+#define RF_RSSICONFIG_OFFSET_M_10_DB                0xB0
+#define RF_RSSICONFIG_OFFSET_M_09_DB                0xB8
+#define RF_RSSICONFIG_OFFSET_M_08_DB                0xC0
+#define RF_RSSICONFIG_OFFSET_M_07_DB                0xC8
+#define RF_RSSICONFIG_OFFSET_M_06_DB                0xD0
+#define RF_RSSICONFIG_OFFSET_M_05_DB                0xD8
+#define RF_RSSICONFIG_OFFSET_M_04_DB                0xE0
+#define RF_RSSICONFIG_OFFSET_M_03_DB                0xE8
+#define RF_RSSICONFIG_OFFSET_M_02_DB                0xF0
+#define RF_RSSICONFIG_OFFSET_M_01_DB                0xF8
+
+#define RF_RSSICONFIG_SMOOTHING_MASK                0xF8
+#define RF_RSSICONFIG_SMOOTHING_2                   0x00
+#define RF_RSSICONFIG_SMOOTHING_4                   0x01
+#define RF_RSSICONFIG_SMOOTHING_8                   0x02  // Default
+#define RF_RSSICONFIG_SMOOTHING_16                  0x03
+#define RF_RSSICONFIG_SMOOTHING_32                  0x04
+#define RF_RSSICONFIG_SMOOTHING_64                  0x05
+#define RF_RSSICONFIG_SMOOTHING_128                 0x06
+#define RF_RSSICONFIG_SMOOTHING_256                 0x07
+
+/*!
+ * RegRssiCollision
+ */
+#define RF_RSSICOLISION_THRESHOLD                   0x0A  // Default
+
+/*!
+ * RegRssiThresh
+ */
+#define RF_RSSITHRESH_THRESHOLD                     0xFF  // Default
+
+/*!
+ * RegRssiValue (Read Only)
+ */
+
+/*!
+ * RegRxBw
+ */
+#define RF_RXBW_MANT_MASK                           0xE7
+#define RF_RXBW_MANT_16                             0x00  
+#define RF_RXBW_MANT_20                             0x08  
+#define RF_RXBW_MANT_24                             0x10  // Default 
+
+#define RF_RXBW_EXP_MASK                            0xF8 
+#define RF_RXBW_EXP_0                               0x00 
+#define RF_RXBW_EXP_1                               0x01 
+#define RF_RXBW_EXP_2                               0x02 
+#define RF_RXBW_EXP_3                               0x03 
+#define RF_RXBW_EXP_4                               0x04 
+#define RF_RXBW_EXP_5                               0x05  // Default
+#define RF_RXBW_EXP_6                               0x06  
+#define RF_RXBW_EXP_7                               0x07 
+
+/*!
+ * RegAfcBw
+ */
+#define RF_AFCBW_MANTAFC_MASK                       0xE7
+#define RF_AFCBW_MANTAFC_16                         0x00
+#define RF_AFCBW_MANTAFC_20                         0x08  // Default
+#define RF_AFCBW_MANTAFC_24                         0x10  
+
+#define RF_AFCBW_EXPAFC_MASK                        0xF8
+#define RF_AFCBW_EXPAFC_0                           0x00 
+#define RF_AFCBW_EXPAFC_1                           0x01 
+#define RF_AFCBW_EXPAFC_2                           0x02  
+#define RF_AFCBW_EXPAFC_3                           0x03  // Default
+#define RF_AFCBW_EXPAFC_4                           0x04 
+#define RF_AFCBW_EXPAFC_5                           0x05 
+#define RF_AFCBW_EXPAFC_6                           0x06  
+#define RF_AFCBW_EXPAFC_7                           0x07 
+
+/*!
+ * RegOokPeak
+ */
+#define RF_OOKPEAK_BITSYNC_MASK                     0xDF  // Default
+#define RF_OOKPEAK_BITSYNC_ON                       0x20  // Default
+#define RF_OOKPEAK_BITSYNC_OFF                      0x00
+
+#define RF_OOKPEAK_OOKTHRESHTYPE_MASK               0xE7
+#define RF_OOKPEAK_OOKTHRESHTYPE_FIXED              0x00
+#define RF_OOKPEAK_OOKTHRESHTYPE_PEAK               0x08  // Default
+#define RF_OOKPEAK_OOKTHRESHTYPE_AVERAGE            0x10
+
+#define RF_OOKPEAK_OOKPEAKTHRESHSTEP_MASK           0xF8
+#define RF_OOKPEAK_OOKPEAKTHRESHSTEP_0_5_DB         0x00  // Default
+#define RF_OOKPEAK_OOKPEAKTHRESHSTEP_1_0_DB         0x01
+#define RF_OOKPEAK_OOKPEAKTHRESHSTEP_1_5_DB         0x02
+#define RF_OOKPEAK_OOKPEAKTHRESHSTEP_2_0_DB         0x03
+#define RF_OOKPEAK_OOKPEAKTHRESHSTEP_3_0_DB         0x04
+#define RF_OOKPEAK_OOKPEAKTHRESHSTEP_4_0_DB         0x05
+#define RF_OOKPEAK_OOKPEAKTHRESHSTEP_5_0_DB         0x06
+#define RF_OOKPEAK_OOKPEAKTHRESHSTEP_6_0_DB         0x07
+
+/*!
+ * RegOokFix
+ */
+#define RF_OOKFIX_OOKFIXEDTHRESHOLD                 0x0C  // Default
+
+/*!
+ * RegOokAvg
+ */
+#define RF_OOKAVG_OOKPEAKTHRESHDEC_MASK             0x1F
+#define RF_OOKAVG_OOKPEAKTHRESHDEC_000              0x00  // Default
+#define RF_OOKAVG_OOKPEAKTHRESHDEC_001              0x20
+#define RF_OOKAVG_OOKPEAKTHRESHDEC_010              0x40
+#define RF_OOKAVG_OOKPEAKTHRESHDEC_011              0x60
+#define RF_OOKAVG_OOKPEAKTHRESHDEC_100              0x80
+#define RF_OOKAVG_OOKPEAKTHRESHDEC_101              0xA0
+#define RF_OOKAVG_OOKPEAKTHRESHDEC_110              0xC0
+#define RF_OOKAVG_OOKPEAKTHRESHDEC_111              0xE0
+
+#define RF_OOKAVG_AVERAGEOFFSET_MASK                0xF3
+#define RF_OOKAVG_AVERAGEOFFSET_0_DB                0x00  // Default
+#define RF_OOKAVG_AVERAGEOFFSET_2_DB                0x04
+#define RF_OOKAVG_AVERAGEOFFSET_4_DB                0x08
+#define RF_OOKAVG_AVERAGEOFFSET_6_DB                0x0C
+
+#define RF_OOKAVG_OOKAVERAGETHRESHFILT_MASK         0xFC
+#define RF_OOKAVG_OOKAVERAGETHRESHFILT_00           0x00
+#define RF_OOKAVG_OOKAVERAGETHRESHFILT_01           0x01
+#define RF_OOKAVG_OOKAVERAGETHRESHFILT_10           0x02  // Default
+#define RF_OOKAVG_OOKAVERAGETHRESHFILT_11           0x03
+
+/*!
+ * RegAfcFei
+ */
+#define RF_AFCFEI_AGCSTART                          0x10
+
+#define RF_AFCFEI_AFCCLEAR                          0x02
+
+#define RF_AFCFEI_AFCAUTOCLEAR_MASK                 0xFE
+#define RF_AFCFEI_AFCAUTOCLEAR_ON                   0x01
+#define RF_AFCFEI_AFCAUTOCLEAR_OFF                  0x00  // Default
+
+/*!
+ * RegAfcMsb (Read Only)
+ */
+ 
+/*!
+ * RegAfcLsb (Read Only)
+ */
+
+/*!
+ * RegFeiMsb (Read Only)
+ */
+
+/*!
+ * RegFeiLsb (Read Only)
+ */
+
+/*!
+ * RegPreambleDetect
+ */
+#define RF_PREAMBLEDETECT_DETECTOR_MASK             0x7F
+#define RF_PREAMBLEDETECT_DETECTOR_ON               0x80  // Default
+#define RF_PREAMBLEDETECT_DETECTOR_OFF              0x00
+
+#define RF_PREAMBLEDETECT_DETECTORSIZE_MASK         0x9F
+#define RF_PREAMBLEDETECT_DETECTORSIZE_1            0x00
+#define RF_PREAMBLEDETECT_DETECTORSIZE_2            0x20  // Default
+#define RF_PREAMBLEDETECT_DETECTORSIZE_3            0x40
+#define RF_PREAMBLEDETECT_DETECTORSIZE_4            0x60
+
+#define RF_PREAMBLEDETECT_DETECTORTOL_MASK          0xE0
+#define RF_PREAMBLEDETECT_DETECTORTOL_0             0x00
+#define RF_PREAMBLEDETECT_DETECTORTOL_1             0x01
+#define RF_PREAMBLEDETECT_DETECTORTOL_2             0x02
+#define RF_PREAMBLEDETECT_DETECTORTOL_3             0x03
+#define RF_PREAMBLEDETECT_DETECTORTOL_4             0x04
+#define RF_PREAMBLEDETECT_DETECTORTOL_5             0x05
+#define RF_PREAMBLEDETECT_DETECTORTOL_6             0x06
+#define RF_PREAMBLEDETECT_DETECTORTOL_7             0x07
+#define RF_PREAMBLEDETECT_DETECTORTOL_8             0x08
+#define RF_PREAMBLEDETECT_DETECTORTOL_9             0x09
+#define RF_PREAMBLEDETECT_DETECTORTOL_10            0x0A  // Default
+#define RF_PREAMBLEDETECT_DETECTORTOL_11            0x0B
+#define RF_PREAMBLEDETECT_DETECTORTOL_12            0x0C
+#define RF_PREAMBLEDETECT_DETECTORTOL_13            0x0D
+#define RF_PREAMBLEDETECT_DETECTORTOL_14            0x0E
+#define RF_PREAMBLEDETECT_DETECTORTOL_15            0x0F
+#define RF_PREAMBLEDETECT_DETECTORTOL_16            0x10
+#define RF_PREAMBLEDETECT_DETECTORTOL_17            0x11
+#define RF_PREAMBLEDETECT_DETECTORTOL_18            0x12
+#define RF_PREAMBLEDETECT_DETECTORTOL_19            0x13
+#define RF_PREAMBLEDETECT_DETECTORTOL_20            0x14
+#define RF_PREAMBLEDETECT_DETECTORTOL_21            0x15
+#define RF_PREAMBLEDETECT_DETECTORTOL_22            0x16
+#define RF_PREAMBLEDETECT_DETECTORTOL_23            0x17
+#define RF_PREAMBLEDETECT_DETECTORTOL_24            0x18
+#define RF_PREAMBLEDETECT_DETECTORTOL_25            0x19
+#define RF_PREAMBLEDETECT_DETECTORTOL_26            0x1A
+#define RF_PREAMBLEDETECT_DETECTORTOL_27            0x1B
+#define RF_PREAMBLEDETECT_DETECTORTOL_28            0x1C
+#define RF_PREAMBLEDETECT_DETECTORTOL_29            0x1D
+#define RF_PREAMBLEDETECT_DETECTORTOL_30            0x1E
+#define RF_PREAMBLEDETECT_DETECTORTOL_31            0x1F
+
+/*!
+ * RegRxTimeout1
+ */
+#define RF_RXTIMEOUT1_TIMEOUTRXRSSI                 0x00  // Default
+
+/*!
+ * RegRxTimeout2
+ */
+#define RF_RXTIMEOUT2_TIMEOUTRXPREAMBLE             0x00  // Default
+
+/*!
+ * RegRxTimeout3
+ */
+#define RF_RXTIMEOUT3_TIMEOUTSIGNALSYNC             0x00  // Default
+
+/*!
+ * RegRxDelay
+ */
+#define RF_RXDELAY_INTERPACKETRXDELAY               0x00  // Default
+
+/*!
+ * RegOsc
+ */
+#define RF_OSC_RCCALSTART                           0x08
+
+#define RF_OSC_CLKOUT_MASK                          0xF8
+#define RF_OSC_CLKOUT_32_MHZ                        0x00
+#define RF_OSC_CLKOUT_16_MHZ                        0x01
+#define RF_OSC_CLKOUT_8_MHZ                         0x02
+#define RF_OSC_CLKOUT_4_MHZ                         0x03
+#define RF_OSC_CLKOUT_2_MHZ                         0x04
+#define RF_OSC_CLKOUT_1_MHZ                         0x05  
+#define RF_OSC_CLKOUT_RC                            0x06
+#define RF_OSC_CLKOUT_OFF                           0x07  // Default
+
+/*!
+ * RegPreambleMsb/RegPreambleLsb
+ */
+#define RF_PREAMBLEMSB_SIZE                         0x00  // Default
+#define RF_PREAMBLELSB_SIZE                         0x03  // Default
+
+/*!
+ * RegSyncConfig
+ */
+#define RF_SYNCCONFIG_AUTORESTARTRXMODE_MASK        0x3F
+#define RF_SYNCCONFIG_AUTORESTARTRXMODE_WAITPLL_ON  0x80  // Default
+#define RF_SYNCCONFIG_AUTORESTARTRXMODE_WAITPLL_OFF 0x40
+#define RF_SYNCCONFIG_AUTORESTARTRXMODE_OFF         0x00
+
+
+#define RF_SYNCCONFIG_PREAMBLEPOLARITY_MASK         0xDF
+#define RF_SYNCCONFIG_PREAMBLEPOLARITY_55           0x20
+#define RF_SYNCCONFIG_PREAMBLEPOLARITY_AA           0x00  // Default
+
+#define RF_SYNCCONFIG_SYNC_MASK                     0xEF
+#define RF_SYNCCONFIG_SYNC_ON                       0x10  // Default
+#define RF_SYNCCONFIG_SYNC_OFF                      0x00
+
+#define RF_SYNCCONFIG_FIFOFILLCONDITION_MASK        0xF7
+#define RF_SYNCCONFIG_FIFOFILLCONDITION_AUTO        0x00  // Default
+#define RF_SYNCCONFIG_FIFOFILLCONDITION_MANUAL      0x08
+
+#define RF_SYNCCONFIG_SYNCSIZE_MASK                 0xF8
+#define RF_SYNCCONFIG_SYNCSIZE_1                    0x00
+#define RF_SYNCCONFIG_SYNCSIZE_2                    0x01
+#define RF_SYNCCONFIG_SYNCSIZE_3                    0x02  
+#define RF_SYNCCONFIG_SYNCSIZE_4                    0x03  // Default
+#define RF_SYNCCONFIG_SYNCSIZE_5                    0x04
+#define RF_SYNCCONFIG_SYNCSIZE_6                    0x05
+#define RF_SYNCCONFIG_SYNCSIZE_7                    0x06
+#define RF_SYNCCONFIG_SYNCSIZE_8                    0x07
+
+/*!
+ * RegSyncValue1-8
+ */
+#define RF_SYNCVALUE1_SYNCVALUE                     0x01  // Default
+#define RF_SYNCVALUE2_SYNCVALUE                     0x01  // Default
+#define RF_SYNCVALUE3_SYNCVALUE                     0x01  // Default
+#define RF_SYNCVALUE4_SYNCVALUE                     0x01  // Default
+#define RF_SYNCVALUE5_SYNCVALUE                     0x01  // Default
+#define RF_SYNCVALUE6_SYNCVALUE                     0x01  // Default
+#define RF_SYNCVALUE7_SYNCVALUE                     0x01  // Default
+#define RF_SYNCVALUE8_SYNCVALUE                     0x01  // Default
+
+/*!
+ * RegPacketConfig1
+ */
+#define RF_PACKETCONFIG1_PACKETFORMAT_MASK          0x7F
+#define RF_PACKETCONFIG1_PACKETFORMAT_FIXED         0x00
+#define RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE      0x80  // Default
+
+#define RF_PACKETCONFIG1_DCFREE_MASK                0x9F
+#define RF_PACKETCONFIG1_DCFREE_OFF                 0x00  // Default
+#define RF_PACKETCONFIG1_DCFREE_MANCHESTER          0x20
+#define RF_PACKETCONFIG1_DCFREE_WHITENING           0x40
+
+#define RF_PACKETCONFIG1_CRC_MASK                   0xEF
+#define RF_PACKETCONFIG1_CRC_ON                     0x10  // Default
+#define RF_PACKETCONFIG1_CRC_OFF                    0x00
+
+#define RF_PACKETCONFIG1_CRCAUTOCLEAR_MASK          0xF7
+#define RF_PACKETCONFIG1_CRCAUTOCLEAR_ON            0x00  // Default
+#define RF_PACKETCONFIG1_CRCAUTOCLEAR_OFF           0x08
+
+#define RF_PACKETCONFIG1_ADDRSFILTERING_MASK         0xF9
+#define RF_PACKETCONFIG1_ADDRSFILTERING_OFF          0x00  // Default
+#define RF_PACKETCONFIG1_ADDRSFILTERING_NODE         0x02
+#define RF_PACKETCONFIG1_ADDRSFILTERING_NODEBROADCAST 0x04
+
+#define RF_PACKETCONFIG1_CRCWHITENINGTYPE_MASK      0xFE
+#define RF_PACKETCONFIG1_CRCWHITENINGTYPE_CCITT     0x00  // Default
+#define RF_PACKETCONFIG1_CRCWHITENINGTYPE_IBM       0x01
+
+/*!
+ * RegPacketConfig2
+ */
+#define RF_PACKETCONFIG2_DATAMODE_MASK              0xBF
+#define RF_PACKETCONFIG2_DATAMODE_CONTINUOUS        0x00
+#define RF_PACKETCONFIG2_DATAMODE_PACKET            0x40  // Default
+
+#define RF_PACKETCONFIG2_IOHOME_MASK                0xDF
+#define RF_PACKETCONFIG2_IOHOME_ON                  0x20
+#define RF_PACKETCONFIG2_IOHOME_OFF                 0x00  // Default
+
+#define RF_PACKETCONFIG2_BEACON_MASK                0xF7
+#define RF_PACKETCONFIG2_BEACON_ON                  0x08
+#define RF_PACKETCONFIG2_BEACON_OFF                 0x00  // Default
+
+#define RF_PACKETCONFIG2_PAYLOADLENGTH_MSB_MASK     0xF8
+
+/*!
+ * RegPayloadLength
+ */
+#define RF_PAYLOADLENGTH_LENGTH                     0x40  // Default
+
+/*!
+ * RegNodeAdrs
+ */
+#define RF_NODEADDRESS_ADDRESS                      0x00
+
+/*!
+ * RegBroadcastAdrs
+ */
+#define RF_BROADCASTADDRESS_ADDRESS                 0x00
+
+/*!
+ * RegFifoThresh
+ */
+#define RF_FIFOTHRESH_TXSTARTCONDITION_MASK         0x7F
+#define RF_FIFOTHRESH_TXSTARTCONDITION_FIFOTHRESH   0x00  
+#define RF_FIFOTHRESH_TXSTARTCONDITION_FIFONOTEMPTY 0x80  // Default
+
+#define RF_FIFOTHRESH_FIFOTHRESHOLD_MASK            0xC0
+#define RF_FIFOTHRESH_FIFOTHRESHOLD_THRESHOLD       0x0F  // Default
+
+/*!
+ * RegSeqConfig1
+ */
+#define RF_SEQCONFIG1_SEQUENCER_START               0x80
+
+#define RF_SEQCONFIG1_SEQUENCER_STOP                0x40
+
+#define RF_SEQCONFIG1_IDLEMODE_MASK                 0xDF
+#define RF_SEQCONFIG1_IDLEMODE_SLEEP                0x20
+#define RF_SEQCONFIG1_IDLEMODE_STANDBY              0x00  // Default
+
+#define RF_SEQCONFIG1_FROMSTART_MASK                0xE7
+#define RF_SEQCONFIG1_FROMSTART_TOLPS               0x00  // Default
+#define RF_SEQCONFIG1_FROMSTART_TORX                0x08
+#define RF_SEQCONFIG1_FROMSTART_TOTX                0x10
+#define RF_SEQCONFIG1_FROMSTART_TOTX_ONFIFOLEVEL    0x18
+
+#define RF_SEQCONFIG1_LPS_MASK                      0xFB
+#define RF_SEQCONFIG1_LPS_SEQUENCER_OFF             0x00  // Default
+#define RF_SEQCONFIG1_LPS_IDLE                      0x04
+
+#define RF_SEQCONFIG1_FROMIDLE_MASK                 0xFD
+#define RF_SEQCONFIG1_FROMIDLE_TOTX                 0x00  // Default
+#define RF_SEQCONFIG1_FROMIDLE_TORX                 0x02
+
+#define RF_SEQCONFIG1_FROMTX_MASK                   0xFE
+#define RF_SEQCONFIG1_FROMTX_TOLPS                  0x00  // Default
+#define RF_SEQCONFIG1_FROMTX_TORX                   0x01
+
+/*!
+ * RegSeqConfig2
+ */
+#define RF_SEQCONFIG2_FROMRX_MASK                   0x1F
+#define RF_SEQCONFIG2_FROMRX_TOUNUSED_000           0x00  // Default
+#define RF_SEQCONFIG2_FROMRX_TORXPKT_ONPLDRDY       0x20
+#define RF_SEQCONFIG2_FROMRX_TOLPS_ONPLDRDY         0x40
+#define RF_SEQCONFIG2_FROMRX_TORXPKT_ONCRCOK        0x60
+#define RF_SEQCONFIG2_FROMRX_TOSEQUENCEROFF_ONRSSI  0x80
+#define RF_SEQCONFIG2_FROMRX_TOSEQUENCEROFF_ONSYNC  0xA0
+#define RF_SEQCONFIG2_FROMRX_TOSEQUENCEROFF_ONPREAMBLE 0xC0
+#define RF_SEQCONFIG2_FROMRX_TOUNUSED_111           0xE0
+
+#define RF_SEQCONFIG2_FROMRXTIMEOUT_MASK            0xE7
+#define RF_SEQCONFIG2_FROMRXTIMEOUT_TORXRESTART     0x00  // Default
+#define RF_SEQCONFIG2_FROMRXTIMEOUT_TOTX            0x08
+#define RF_SEQCONFIG2_FROMRXTIMEOUT_TOLPS           0x10
+#define RF_SEQCONFIG2_FROMRXTIMEOUT_TOSEQUENCEROFF  0x18
+
+#define RF_SEQCONFIG2_FROMRXPKT_MASK                0xF8
+#define RF_SEQCONFIG2_FROMRXPKT_TOSEQUENCEROFF      0x00  // Default
+#define RF_SEQCONFIG2_FROMRXPKT_TOTX_ONFIFOEMPTY    0x01
+#define RF_SEQCONFIG2_FROMRXPKT_TOLPS               0x02
+#define RF_SEQCONFIG2_FROMRXPKT_TOSYNTHESIZERRX     0x03
+#define RF_SEQCONFIG2_FROMRXPKT_TORX                0x04
+
+/*!
+ * RegTimerResol
+ */
+#define RF_TIMERRESOL_TIMER1RESOL_MASK              0xF3
+#define RF_TIMERRESOL_TIMER1RESOL_OFF               0x00  // Default
+#define RF_TIMERRESOL_TIMER1RESOL_000064_US         0x04
+#define RF_TIMERRESOL_TIMER1RESOL_004100_US         0x08
+#define RF_TIMERRESOL_TIMER1RESOL_262000_US         0x0C
+
+#define RF_TIMERRESOL_TIMER2RESOL_MASK              0xFC
+#define RF_TIMERRESOL_TIMER2RESOL_OFF               0x00  // Default
+#define RF_TIMERRESOL_TIMER2RESOL_000064_US         0x01
+#define RF_TIMERRESOL_TIMER2RESOL_004100_US         0x02
+#define RF_TIMERRESOL_TIMER2RESOL_262000_US         0x03
+
+/*!
+ * RegTimer1Coef
+ */
+#define RF_TIMER1COEF_TIMER1COEFFICIENT             0xF5  // Default
+
+/*!
+ * RegTimer2Coef
+ */
+#define RF_TIMER2COEF_TIMER2COEFFICIENT             0x20  // Default
+
+/*!
+ * RegImageCal
+ */
+#define RF_IMAGECAL_AUTOIMAGECAL_MASK               0x7F
+#define RF_IMAGECAL_AUTOIMAGECAL_ON                 0x80
+#define RF_IMAGECAL_AUTOIMAGECAL_OFF                0x00  // Default
+
+#define RF_IMAGECAL_IMAGECAL_MASK                   0xBF
+#define RF_IMAGECAL_IMAGECAL_START                  0x40
+
+#define RF_IMAGECAL_IMAGECAL_RUNNING                0x20
+#define RF_IMAGECAL_IMAGECAL_DONE                   0x00  // Default
+
+#define RF_IMAGECAL_TEMPCHANGE_HIGHER               0x08
+#define RF_IMAGECAL_TEMPCHANGE_LOWER                0x00
+
+#define RF_IMAGECAL_TEMPTHRESHOLD_MASK              0xF9
+#define RF_IMAGECAL_TEMPTHRESHOLD_05                0x00
+#define RF_IMAGECAL_TEMPTHRESHOLD_10                0x02  // Default
+#define RF_IMAGECAL_TEMPTHRESHOLD_15                0x04
+#define RF_IMAGECAL_TEMPTHRESHOLD_20                0x06
+
+#define RF_IMAGECAL_TEMPMONITOR_MASK                0xFE
+#define RF_IMAGECAL_TEMPMONITOR_ON                  0x00 // Default
+#define RF_IMAGECAL_TEMPMONITOR_OFF                 0x01
+
+/*!
+ * RegTemp (Read Only)
+ */
+
+/*!
+ * RegLowBat
+ */
+#define RF_LOWBAT_MASK                              0xF7
+#define RF_LOWBAT_ON                                0x08
+#define RF_LOWBAT_OFF                               0x00  // Default
+
+#define RF_LOWBAT_TRIM_MASK                         0xF8
+#define RF_LOWBAT_TRIM_1695                         0x00
+#define RF_LOWBAT_TRIM_1764                         0x01
+#define RF_LOWBAT_TRIM_1835                         0x02  // Default
+#define RF_LOWBAT_TRIM_1905                         0x03
+#define RF_LOWBAT_TRIM_1976                         0x04
+#define RF_LOWBAT_TRIM_2045                         0x05
+#define RF_LOWBAT_TRIM_2116                         0x06
+#define RF_LOWBAT_TRIM_2185                         0x07
+
+/*!
+ * RegIrqFlags1
+ */
+#define RF_IRQFLAGS1_MODEREADY                      0x80
+
+#define RF_IRQFLAGS1_RXREADY                        0x40
+
+#define RF_IRQFLAGS1_TXREADY                        0x20
+
+#define RF_IRQFLAGS1_PLLLOCK                        0x10
+
+#define RF_IRQFLAGS1_RSSI                           0x08
+
+#define RF_IRQFLAGS1_TIMEOUT                        0x04
+
+#define RF_IRQFLAGS1_PREAMBLEDETECT                 0x02
+
+#define RF_IRQFLAGS1_SYNCADDRESSMATCH               0x01
+
+/*!
+ * RegIrqFlags2
+ */
+#define RF_IRQFLAGS2_FIFOFULL                       0x80
+
+#define RF_IRQFLAGS2_FIFOEMPTY                      0x40
+
+#define RF_IRQFLAGS2_FIFOLEVEL                      0x20
+
+#define RF_IRQFLAGS2_FIFOOVERRUN                    0x10
+
+#define RF_IRQFLAGS2_PACKETSENT                     0x08
+
+#define RF_IRQFLAGS2_PAYLOADREADY                   0x04
+
+#define RF_IRQFLAGS2_CRCOK                          0x02
+
+#define RF_IRQFLAGS2_LOWBAT                         0x01
+
+/*!
+ * RegDioMapping1
+ */
+#define RF_DIOMAPPING1_DIO0_MASK                    0x3F
+#define RF_DIOMAPPING1_DIO0_00                      0x00  // Default
+#define RF_DIOMAPPING1_DIO0_01                      0x40
+#define RF_DIOMAPPING1_DIO0_10                      0x80
+#define RF_DIOMAPPING1_DIO0_11                      0xC0
+
+#define RF_DIOMAPPING1_DIO1_MASK                    0xCF
+#define RF_DIOMAPPING1_DIO1_00                      0x00  // Default
+#define RF_DIOMAPPING1_DIO1_01                      0x10
+#define RF_DIOMAPPING1_DIO1_10                      0x20
+#define RF_DIOMAPPING1_DIO1_11                      0x30
+
+#define RF_DIOMAPPING1_DIO2_MASK                    0xF3
+#define RF_DIOMAPPING1_DIO2_00                      0x00  // Default
+#define RF_DIOMAPPING1_DIO2_01                      0x04
+#define RF_DIOMAPPING1_DIO2_10                      0x08
+#define RF_DIOMAPPING1_DIO2_11                      0x0C
+
+#define RF_DIOMAPPING1_DIO3_MASK                    0xFC
+#define RF_DIOMAPPING1_DIO3_00                      0x00  // Default
+#define RF_DIOMAPPING1_DIO3_01                      0x01
+#define RF_DIOMAPPING1_DIO3_10                      0x02
+#define RF_DIOMAPPING1_DIO3_11                      0x03
+
+/*!
+ * RegDioMapping2
+ */
+#define RF_DIOMAPPING2_DIO4_MASK                    0x3F
+#define RF_DIOMAPPING2_DIO4_00                      0x00  // Default
+#define RF_DIOMAPPING2_DIO4_01                      0x40
+#define RF_DIOMAPPING2_DIO4_10                      0x80
+#define RF_DIOMAPPING2_DIO4_11                      0xC0
+
+#define RF_DIOMAPPING2_DIO5_MASK                    0xCF
+#define RF_DIOMAPPING2_DIO5_00                      0x00  // Default
+#define RF_DIOMAPPING2_DIO5_01                      0x10
+#define RF_DIOMAPPING2_DIO5_10                      0x20
+#define RF_DIOMAPPING2_DIO5_11                      0x30
+
+#define RF_DIOMAPPING2_MAP_MASK                     0xFE
+#define RF_DIOMAPPING2_MAP_PREAMBLEDETECT           0x01
+#define RF_DIOMAPPING2_MAP_RSSI                     0x00  // Default
+
+/*!
+ * RegVersion (Read Only)
+ */
+
+/*!
+ * RegAgcRef
+ */
+
+/*!
+ * RegAgcThresh1
+ */
+
+/*!
+ * RegAgcThresh2
+ */
+
+/*!
+ * RegAgcThresh3
+ */
+
+/*!
+ * RegPllHop
+ */
+#define RF_PLLHOP_FASTHOP_MASK                      0x7F
+#define RF_PLLHOP_FASTHOP_ON                        0x80
+#define RF_PLLHOP_FASTHOP_OFF                       0x00 // Default
+
+/*!
+ * RegTcxo
+ */
+#define RF_TCXO_TCXOINPUT_MASK                      0xEF
+#define RF_TCXO_TCXOINPUT_ON                        0x10
+#define RF_TCXO_TCXOINPUT_OFF                       0x00  // Default
+
+/*!
+ * RegPaDac
+ */
+#define RF_PADAC_20DBM_MASK                         0xF8
+#define RF_PADAC_20DBM_ON                           0x07
+#define RF_PADAC_20DBM_OFF                          0x04  // Default
+
+/*!
+ * RegPll
+ */
+#define RF_PLL_BANDWIDTH_MASK                       0x3F
+#define RF_PLL_BANDWIDTH_75                         0x00
+#define RF_PLL_BANDWIDTH_150                        0x40
+#define RF_PLL_BANDWIDTH_225                        0x80
+#define RF_PLL_BANDWIDTH_300                        0xC0  // Default
+
+/*!
+ * RegPllLowPn
+ */
+#define RF_PLLLOWPN_BANDWIDTH_MASK                  0x3F
+#define RF_PLLLOWPN_BANDWIDTH_75                    0x00
+#define RF_PLLLOWPN_BANDWIDTH_150                   0x40
+#define RF_PLLLOWPN_BANDWIDTH_225                   0x80
+#define RF_PLLLOWPN_BANDWIDTH_300                   0xC0  // Default
+
+/*!
+ * RegFormerTemp
+ */
+
+/*!
+ * RegBitrateFrac
+ */
+#define RF_BITRATEFRAC_MASK                         0xF0
+
+#endif // __SX1272_REGS_FSK_H__
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/Lora/Radio/SxRadio1272Regs-LoRa.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,548 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2013 Semtech
+
+Description: SX1272 LoRa modem registers and bits definitions
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Miguel Luis and Gregory Cristian
+*/
+#ifndef __SX1272_REGS_LORA_H__
+#define __SX1272_REGS_LORA_H__
+
+/*!
+ * ============================================================================
+ * SX1272 Internal registers Address
+ * ============================================================================
+ */
+#define REG_LR_FIFO                                 0x00 
+// Common settings
+#define REG_LR_OPMODE                               0x01 
+#define REG_LR_FRFMSB                               0x06 
+#define REG_LR_FRFMID                               0x07
+#define REG_LR_FRFLSB                               0x08 
+// Tx settings
+#define REG_LR_PACONFIG                             0x09 
+#define REG_LR_PARAMP                               0x0A 
+#define REG_LR_OCP                                  0x0B 
+// Rx settings
+#define REG_LR_LNA                                  0x0C 
+// LoRa registers
+#define REG_LR_FIFOADDRPTR                          0x0D 
+#define REG_LR_FIFOTXBASEADDR                       0x0E 
+#define REG_LR_FIFORXBASEADDR                       0x0F 
+#define REG_LR_FIFORXCURRENTADDR                    0x10 
+#define REG_LR_IRQFLAGSMASK                         0x11 
+#define REG_LR_IRQFLAGS                             0x12 
+#define REG_LR_RXNBBYTES                            0x13 
+#define REG_LR_RXHEADERCNTVALUEMSB                  0x14 
+#define REG_LR_RXHEADERCNTVALUELSB                  0x15 
+#define REG_LR_RXPACKETCNTVALUEMSB                  0x16 
+#define REG_LR_RXPACKETCNTVALUELSB                  0x17 
+#define REG_LR_MODEMSTAT                            0x18 
+#define REG_LR_PKTSNRVALUE                          0x19 
+#define REG_LR_PKTRSSIVALUE                         0x1A 
+#define REG_LR_RSSIVALUE                            0x1B 
+#define REG_LR_HOPCHANNEL                           0x1C 
+#define REG_LR_MODEMCONFIG1                         0x1D 
+#define REG_LR_MODEMCONFIG2                         0x1E 
+#define REG_LR_SYMBTIMEOUTLSB                       0x1F 
+#define REG_LR_PREAMBLEMSB                          0x20 
+#define REG_LR_PREAMBLELSB                          0x21 
+#define REG_LR_PAYLOADLENGTH                        0x22 
+#define REG_LR_PAYLOADMAXLENGTH                     0x23 
+#define REG_LR_HOPPERIOD                            0x24 
+#define REG_LR_FIFORXBYTEADDR                       0x25
+#define REG_LR_FEIMSB                               0x28
+#define REG_LR_FEIMID                               0x29
+#define REG_LR_FEILSB                               0x2A
+#define REG_LR_RSSIWIDEBAND                         0x2C
+#define REG_LR_DETECTOPTIMIZE                       0x31
+#define REG_LR_INVERTIQ                             0x33
+#define REG_LR_DETECTIONTHRESHOLD                   0x37
+
+#define REG_LR_IMAGE_CAL                            0x3B
+
+// end of documented register in datasheet
+// I/O settings
+#define REG_LR_DIOMAPPING1                          0x40
+#define REG_LR_DIOMAPPING2                          0x41
+// Version
+#define REG_LR_VERSION                              0x42
+// Additional settings
+#define REG_LR_AGCREF                               0x43
+#define REG_LR_AGCTHRESH1                           0x44
+#define REG_LR_AGCTHRESH2                           0x45
+#define REG_LR_AGCTHRESH3                           0x46
+#define REG_LR_PLLHOP                               0x4B
+#define REG_LR_TCXO                                 0x58
+#define REG_LR_PADAC                                0x5A
+#define REG_LR_PLL                                  0x5C
+#define REG_LR_PLLLOWPN                             0x5E
+#define REG_LR_FORMERTEMP                           0x6C
+
+/*!
+ * ============================================================================
+ * SX1272 LoRa bits control definition
+ * ============================================================================
+ */
+
+/*!
+ * RegFifo
+ */
+
+/*!
+ * RegOpMode
+ */
+#define RFLR_OPMODE_LONGRANGEMODE_MASK              0x7F 
+#define RFLR_OPMODE_LONGRANGEMODE_OFF               0x00 // Default
+#define RFLR_OPMODE_LONGRANGEMODE_ON                0x80 
+
+#define RFLR_OPMODE_ACCESSSHAREDREG_MASK            0xBF 
+#define RFLR_OPMODE_ACCESSSHAREDREG_ENABLE          0x40 
+#define RFLR_OPMODE_ACCESSSHAREDREG_DISABLE         0x00 // Default
+
+#define RFLR_OPMODE_MASK                            0xF8 
+#define RFLR_OPMODE_SLEEP                           0x00 
+#define RFLR_OPMODE_STANDBY                         0x01 // Default
+#define RFLR_OPMODE_SYNTHESIZER_TX                  0x02 
+#define RFLR_OPMODE_TRANSMITTER                     0x03 
+#define RFLR_OPMODE_SYNTHESIZER_RX                  0x04 
+#define RFLR_OPMODE_RECEIVER                        0x05 
+// LoRa specific modes
+#define RFLR_OPMODE_RECEIVER_SINGLE                 0x06 
+#define RFLR_OPMODE_CAD                             0x07 
+
+/*!
+ * RegFrf (MHz)
+ */
+#define RFLR_FRFMSB_915_MHZ                         0xE4  // Default
+#define RFLR_FRFMID_915_MHZ                         0xC0  // Default
+#define RFLR_FRFLSB_915_MHZ                         0x00  // Default
+
+/*!
+ * RegPaConfig
+ */
+#define RFLR_PACONFIG_PASELECT_MASK                 0x7F 
+#define RFLR_PACONFIG_PASELECT_PABOOST              0x80 
+#define RFLR_PACONFIG_PASELECT_RFO                  0x00 // Default
+
+#define RFLR_PACONFIG_OUTPUTPOWER_MASK              0xF0 
+ 
+/*!
+ * RegPaRamp
+ */
+#define RFLR_PARAMP_LOWPNTXPLL_MASK                 0xE0 
+#define RFLR_PARAMP_LOWPNTXPLL_OFF                  0x10 // Default
+#define RFLR_PARAMP_LOWPNTXPLL_ON                   0x00 
+
+#define RFLR_PARAMP_MASK                            0xF0 
+#define RFLR_PARAMP_3400_US                         0x00 
+#define RFLR_PARAMP_2000_US                         0x01 
+#define RFLR_PARAMP_1000_US                         0x02
+#define RFLR_PARAMP_0500_US                         0x03 
+#define RFLR_PARAMP_0250_US                         0x04 
+#define RFLR_PARAMP_0125_US                         0x05 
+#define RFLR_PARAMP_0100_US                         0x06 
+#define RFLR_PARAMP_0062_US                         0x07 
+#define RFLR_PARAMP_0050_US                         0x08 
+#define RFLR_PARAMP_0040_US                         0x09 // Default
+#define RFLR_PARAMP_0031_US                         0x0A 
+#define RFLR_PARAMP_0025_US                         0x0B 
+#define RFLR_PARAMP_0020_US                         0x0C 
+#define RFLR_PARAMP_0015_US                         0x0D 
+#define RFLR_PARAMP_0012_US                         0x0E 
+#define RFLR_PARAMP_0010_US                         0x0F 
+
+/*!
+ * RegOcp
+ */
+#define RFLR_OCP_MASK                               0xDF 
+#define RFLR_OCP_ON                                 0x20 // Default
+#define RFLR_OCP_OFF                                0x00   
+
+#define RFLR_OCP_TRIM_MASK                          0xE0
+#define RFLR_OCP_TRIM_045_MA                        0x00
+#define RFLR_OCP_TRIM_050_MA                        0x01   
+#define RFLR_OCP_TRIM_055_MA                        0x02 
+#define RFLR_OCP_TRIM_060_MA                        0x03 
+#define RFLR_OCP_TRIM_065_MA                        0x04 
+#define RFLR_OCP_TRIM_070_MA                        0x05 
+#define RFLR_OCP_TRIM_075_MA                        0x06 
+#define RFLR_OCP_TRIM_080_MA                        0x07  
+#define RFLR_OCP_TRIM_085_MA                        0x08
+#define RFLR_OCP_TRIM_090_MA                        0x09 
+#define RFLR_OCP_TRIM_095_MA                        0x0A 
+#define RFLR_OCP_TRIM_100_MA                        0x0B  // Default
+#define RFLR_OCP_TRIM_105_MA                        0x0C 
+#define RFLR_OCP_TRIM_110_MA                        0x0D 
+#define RFLR_OCP_TRIM_115_MA                        0x0E 
+#define RFLR_OCP_TRIM_120_MA                        0x0F 
+#define RFLR_OCP_TRIM_130_MA                        0x10
+#define RFLR_OCP_TRIM_140_MA                        0x11   
+#define RFLR_OCP_TRIM_150_MA                        0x12 
+#define RFLR_OCP_TRIM_160_MA                        0x13 
+#define RFLR_OCP_TRIM_170_MA                        0x14 
+#define RFLR_OCP_TRIM_180_MA                        0x15 
+#define RFLR_OCP_TRIM_190_MA                        0x16 
+#define RFLR_OCP_TRIM_200_MA                        0x17  
+#define RFLR_OCP_TRIM_210_MA                        0x18
+#define RFLR_OCP_TRIM_220_MA                        0x19 
+#define RFLR_OCP_TRIM_230_MA                        0x1A 
+#define RFLR_OCP_TRIM_240_MA                        0x1B
+
+/*!
+ * RegLna
+ */
+#define RFLR_LNA_GAIN_MASK                          0x1F 
+#define RFLR_LNA_GAIN_G1                            0x20 // Default
+#define RFLR_LNA_GAIN_G2                            0x40 
+#define RFLR_LNA_GAIN_G3                            0x60 
+#define RFLR_LNA_GAIN_G4                            0x80 
+#define RFLR_LNA_GAIN_G5                            0xA0 
+#define RFLR_LNA_GAIN_G6                            0xC0 
+
+#define RFLR_LNA_BOOST_MASK                         0xFC 
+#define RFLR_LNA_BOOST_OFF                          0x00 // Default
+#define RFLR_LNA_BOOST_ON                           0x03 
+
+/*!
+ * RegFifoAddrPtr
+ */
+#define RFLR_FIFOADDRPTR                            0x00 // Default
+
+/*!
+ * RegFifoTxBaseAddr
+ */
+#define RFLR_FIFOTXBASEADDR                         0x80 // Default
+
+/*!
+ * RegFifoTxBaseAddr
+ */
+#define RFLR_FIFORXBASEADDR                         0x00 // Default
+
+/*!
+ * RegFifoRxCurrentAddr (Read Only)
+ */
+
+/*!
+ * RegIrqFlagsMask
+ */
+#define RFLR_IRQFLAGS_RXTIMEOUT_MASK                0x80 
+#define RFLR_IRQFLAGS_RXDONE_MASK                   0x40 
+#define RFLR_IRQFLAGS_PAYLOADCRCERROR_MASK          0x20 
+#define RFLR_IRQFLAGS_VALIDHEADER_MASK              0x10 
+#define RFLR_IRQFLAGS_TXDONE_MASK                   0x08 
+#define RFLR_IRQFLAGS_CADDONE_MASK                  0x04 
+#define RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL_MASK       0x02 
+#define RFLR_IRQFLAGS_CADDETECTED_MASK              0x01 
+
+/*!
+ * RegIrqFlags
+ */
+#define RFLR_IRQFLAGS_RXTIMEOUT                     0x80 
+#define RFLR_IRQFLAGS_RXDONE                        0x40 
+#define RFLR_IRQFLAGS_PAYLOADCRCERROR               0x20 
+#define RFLR_IRQFLAGS_VALIDHEADER                   0x10 
+#define RFLR_IRQFLAGS_TXDONE                        0x08 
+#define RFLR_IRQFLAGS_CADDONE                       0x04 
+#define RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL            0x02 
+#define RFLR_IRQFLAGS_CADDETECTED                   0x01 
+
+/*!
+ * RegFifoRxNbBytes (Read Only)
+ */
+
+/*!
+ * RegRxHeaderCntValueMsb (Read Only)
+ */
+
+/*!
+ * RegRxHeaderCntValueLsb (Read Only)
+ */
+
+/*!
+ * RegRxPacketCntValueMsb (Read Only)
+ */
+
+/*!
+ * RegRxPacketCntValueLsb (Read Only)
+ */
+
+/*!
+ * RegModemStat (Read Only)
+ */
+#define RFLR_MODEMSTAT_RX_CR_MASK                   0x1F 
+#define RFLR_MODEMSTAT_MODEM_STATUS_MASK            0xE0 
+ 
+/*!
+ * RegPktSnrValue (Read Only)
+ */
+
+/*!
+ * RegPktRssiValue (Read Only)
+ */
+
+/*!
+ * RegRssiValue (Read Only)
+ */
+
+/*!
+ * RegHopChannel (Read Only)
+ */
+#define RFLR_HOPCHANNEL_PLL_LOCK_TIMEOUT_MASK       0x7F 
+#define RFLR_HOPCHANNEL_PLL_LOCK_FAIL               0x80 
+#define RFLR_HOPCHANNEL_PLL_LOCK_SUCCEED            0x00 // Default
+                                                    
+#define RFLR_HOPCHANNEL_CRCONPAYLOAD_MASK           0xBF
+#define RFLR_HOPCHANNEL_CRCONPAYLOAD_ON             0x40
+#define RFLR_HOPCHANNEL_CRCONPAYLOAD_OFF            0x00 // Default
+
+#define RFLR_HOPCHANNEL_CHANNEL_MASK                0x3F 
+
+/*!
+ * RegModemConfig1
+ */
+#define RFLR_MODEMCONFIG1_BW_MASK                   0x3F 
+#define RFLR_MODEMCONFIG1_BW_125_KHZ                0x00 // Default
+#define RFLR_MODEMCONFIG1_BW_250_KHZ                0x40 
+#define RFLR_MODEMCONFIG1_BW_500_KHZ                0x80 
+                                                    
+#define RFLR_MODEMCONFIG1_CODINGRATE_MASK           0xC7 
+#define RFLR_MODEMCONFIG1_CODINGRATE_4_5            0x08
+#define RFLR_MODEMCONFIG1_CODINGRATE_4_6            0x10 // Default
+#define RFLR_MODEMCONFIG1_CODINGRATE_4_7            0x18 
+#define RFLR_MODEMCONFIG1_CODINGRATE_4_8            0x20 
+                                                    
+#define RFLR_MODEMCONFIG1_IMPLICITHEADER_MASK       0xFB 
+#define RFLR_MODEMCONFIG1_IMPLICITHEADER_ON         0x04 
+#define RFLR_MODEMCONFIG1_IMPLICITHEADER_OFF        0x00 // Default
+                                                    
+#define RFLR_MODEMCONFIG1_RXPAYLOADCRC_MASK         0xFD 
+#define RFLR_MODEMCONFIG1_RXPAYLOADCRC_ON           0x02 
+#define RFLR_MODEMCONFIG1_RXPAYLOADCRC_OFF          0x00 // Default
+                                                    
+#define RFLR_MODEMCONFIG1_LOWDATARATEOPTIMIZE_MASK  0xFE 
+#define RFLR_MODEMCONFIG1_LOWDATARATEOPTIMIZE_ON    0x01 
+#define RFLR_MODEMCONFIG1_LOWDATARATEOPTIMIZE_OFF   0x00 // Default
+
+/*!
+ * RegModemConfig2
+ */
+#define RFLR_MODEMCONFIG2_SF_MASK                   0x0F 
+#define RFLR_MODEMCONFIG2_SF_6                      0x60 
+#define RFLR_MODEMCONFIG2_SF_7                      0x70 // Default
+#define RFLR_MODEMCONFIG2_SF_8                      0x80 
+#define RFLR_MODEMCONFIG2_SF_9                      0x90 
+#define RFLR_MODEMCONFIG2_SF_10                     0xA0 
+#define RFLR_MODEMCONFIG2_SF_11                     0xB0 
+#define RFLR_MODEMCONFIG2_SF_12                     0xC0 
+
+#define RFLR_MODEMCONFIG2_TXCONTINUOUSMODE_MASK     0xF7 
+#define RFLR_MODEMCONFIG2_TXCONTINUOUSMODE_ON       0x08 
+#define RFLR_MODEMCONFIG2_TXCONTINUOUSMODE_OFF      0x00 
+
+#define RFLR_MODEMCONFIG2_AGCAUTO_MASK              0xFB 
+#define RFLR_MODEMCONFIG2_AGCAUTO_ON                0x04 // Default 
+#define RFLR_MODEMCONFIG2_AGCAUTO_OFF               0x00 
+ 
+#define RFLR_MODEMCONFIG2_SYMBTIMEOUTMSB_MASK       0xFC 
+#define RFLR_MODEMCONFIG2_SYMBTIMEOUTMSB            0x00 // Default
+
+/*!
+ * RegSymbTimeoutLsb
+ */
+#define RFLR_SYMBTIMEOUTLSB_SYMBTIMEOUT             0x64 // Default
+
+/*!
+ * RegPreambleLengthMsb
+ */
+#define RFLR_PREAMBLELENGTHMSB                      0x00 // Default
+
+/*!
+ * RegPreambleLengthLsb
+ */
+#define RFLR_PREAMBLELENGTHLSB                      0x08 // Default
+
+/*!
+ * RegPayloadLength
+ */
+#define RFLR_PAYLOADLENGTH                          0x0E // Default
+
+/*!
+ * RegPayloadMaxLength
+ */
+#define RFLR_PAYLOADMAXLENGTH                       0xFF // Default
+
+/*!
+ * RegHopPeriod
+ */
+#define RFLR_HOPPERIOD_FREQFOPPINGPERIOD            0x00 // Default
+
+/*!
+ * RegFifoRxByteAddr (Read Only)
+ */
+
+/*!
+ * RegFeiMsb (Read Only)
+ */
+
+/*!
+ * RegFeiMid (Read Only)
+ */
+
+/*!
+ * RegFeiLsb (Read Only)
+ */
+
+/*!
+ * RegRssiWideband (Read Only)
+ */
+
+/*!
+ * RegDetectOptimize
+ */
+#define RFLR_DETECTIONOPTIMIZE_MASK                 0xF8
+#define RFLR_DETECTIONOPTIMIZE_SF7_TO_SF12          0x03 // Default
+#define RFLR_DETECTIONOPTIMIZE_SF6                  0x05
+
+/*!
+ * RegInvertIQ
+ */
+#define RFLR_INVERTIQ_RX_MASK                       0xBF
+#define RFLR_INVERTIQ_RX_OFF                        0x00
+#define RFLR_INVERTIQ_RX_ON                         0x40
+#define RFLR_INVERTIQ_TX_MASK                       0xFE
+#define RFLR_INVERTIQ_TX_OFF                        0x01
+#define RFLR_INVERTIQ_TX_ON                         0x00
+
+/*!
+ * RegDetectionThreshold
+ */
+#define RFLR_DETECTIONTHRESH_SF7_TO_SF12            0x0A // Default
+#define RFLR_DETECTIONTHRESH_SF6                    0x0C
+
+/*!
+ * RegDioMapping1
+ */
+#define RFLR_DIOMAPPING1_DIO0_MASK                  0x3F
+#define RFLR_DIOMAPPING1_DIO0_00                    0x00  // Default
+#define RFLR_DIOMAPPING1_DIO0_01                    0x40
+#define RFLR_DIOMAPPING1_DIO0_10                    0x80
+#define RFLR_DIOMAPPING1_DIO0_11                    0xC0
+
+#define RFLR_DIOMAPPING1_DIO1_MASK                  0xCF
+#define RFLR_DIOMAPPING1_DIO1_00                    0x00  // Default
+#define RFLR_DIOMAPPING1_DIO1_01                    0x10
+#define RFLR_DIOMAPPING1_DIO1_10                    0x20
+#define RFLR_DIOMAPPING1_DIO1_11                    0x30
+
+#define RFLR_DIOMAPPING1_DIO2_MASK                  0xF3
+#define RFLR_DIOMAPPING1_DIO2_00                    0x00  // Default
+#define RFLR_DIOMAPPING1_DIO2_01                    0x04
+#define RFLR_DIOMAPPING1_DIO2_10                    0x08
+#define RFLR_DIOMAPPING1_DIO2_11                    0x0C
+
+#define RFLR_DIOMAPPING1_DIO3_MASK                  0xFC
+#define RFLR_DIOMAPPING1_DIO3_00                    0x00  // Default
+#define RFLR_DIOMAPPING1_DIO3_01                    0x01
+#define RFLR_DIOMAPPING1_DIO3_10                    0x02
+#define RFLR_DIOMAPPING1_DIO3_11                    0x03
+
+/*!
+ * RegDioMapping2
+ */
+#define RFLR_DIOMAPPING2_DIO4_MASK                  0x3F
+#define RFLR_DIOMAPPING2_DIO4_00                    0x00  // Default
+#define RFLR_DIOMAPPING2_DIO4_01                    0x40
+#define RFLR_DIOMAPPING2_DIO4_10                    0x80
+#define RFLR_DIOMAPPING2_DIO4_11                    0xC0
+
+#define RFLR_DIOMAPPING2_DIO5_MASK                  0xCF
+#define RFLR_DIOMAPPING2_DIO5_00                    0x00  // Default
+#define RFLR_DIOMAPPING2_DIO5_01                    0x10
+#define RFLR_DIOMAPPING2_DIO5_10                    0x20
+#define RFLR_DIOMAPPING2_DIO5_11                    0x30
+
+#define RFLR_DIOMAPPING2_MAP_MASK                   0xFE
+#define RFLR_DIOMAPPING2_MAP_PREAMBLEDETECT         0x01
+#define RFLR_DIOMAPPING2_MAP_RSSI                   0x00  // Default
+
+/*!
+ * RegVersion (Read Only)
+ */
+
+/*!
+ * RegAgcRef
+ */
+
+/*!
+ * RegAgcThresh1
+ */
+
+/*!
+ * RegAgcThresh2
+ */
+
+/*!
+ * RegAgcThresh3
+ */
+ 
+/*!
+ * RegPllHop
+ */
+#define RFLR_PLLHOP_FASTHOP_MASK                    0x7F
+#define RFLR_PLLHOP_FASTHOP_ON                      0x80
+#define RFLR_PLLHOP_FASTHOP_OFF                     0x00 // Default
+
+/*!
+ * RegTcxo
+ */
+#define RFLR_TCXO_TCXOINPUT_MASK                    0xEF
+#define RFLR_TCXO_TCXOINPUT_ON                      0x10
+#define RFLR_TCXO_TCXOINPUT_OFF                     0x00  // Default
+
+/*!
+ * RegPaDac
+ */
+#define RFLR_PADAC_20DBM_MASK                       0xF8
+#define RFLR_PADAC_20DBM_ON                         0x07
+#define RFLR_PADAC_20DBM_OFF                        0x04  // Default
+
+/*!
+ * RegPll
+ */
+#define RFLR_PLL_BANDWIDTH_MASK                     0x3F
+#define RFLR_PLL_BANDWIDTH_75                       0x00
+#define RFLR_PLL_BANDWIDTH_150                      0x40
+#define RFLR_PLL_BANDWIDTH_225                      0x80
+#define RFLR_PLL_BANDWIDTH_300                      0xC0  // Default
+
+/*!
+ * RegPllLowPn
+ */
+#define RFLR_PLLLOWPN_BANDWIDTH_MASK                0x3F
+#define RFLR_PLLLOWPN_BANDWIDTH_75                  0x00
+#define RFLR_PLLLOWPN_BANDWIDTH_150                 0x40
+#define RFLR_PLLLOWPN_BANDWIDTH_225                 0x80
+#define RFLR_PLLLOWPN_BANDWIDTH_300                 0xC0  // Default
+
+/*!
+ * RegFormerTemp
+ */
+
+
+
+
+#define SX1272_REG_SYNC_WORD 0x39
+#define SX1272_SYNC_WORD_PEER_TO_PEER 0x56
+#define SX1272_SYNC_WORD_PUBLIC 0x34
+#define SX1272_SYNC_WORD_PRIVATE 0x12
+
+#endif // __SX1272_REGS_LORA_H__
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/Lora/Radio/SxRadioEvents.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,76 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2013 Semtech
+
+Description: Generic radio driver definition
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Miguel Luis and Gregory Cristian
+*/
+#ifndef __SXRADIOEVENTS_H__
+#define __SXRADIOEVENTS_H__
+
+/*!
+ * \brief Radio driver callback functions
+ */
+class SxRadioEvents
+{
+public:
+    /*!
+     * \brief  Tx Start callback prototype.
+     */
+    virtual void TxStart( void ) {}
+    /*!
+     * \brief  Tx Done callback prototype.
+     */
+    virtual void TxDone( void ) {}
+    /*!
+     * \brief  Tx Timeout callback prototype.
+     */
+    virtual void TxTimeout( void ) {}
+    /*!
+     * \brief Rx Done callback prototype.
+     *
+     * \param [IN] payload Received buffer pointer
+     * \param [IN] size    Received buffer size
+     * \param [IN] rssi    RSSI value computed while receiving the frame [dBm]
+     * \param [IN] snr     Raw SNR value given by the radio hardware
+     *                     FSK : N/A ( set to 0 )
+     *                     LoRa: SNR value is two's complement in 1/4 dB
+     */
+    virtual void RxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ) {}
+    /*!
+     * \brief  Rx Timeout callback prototype.
+     */
+    virtual void RxTimeout( void ) {}
+    /*!
+     * \brief Rx Error callback prototype.
+     */
+    virtual void RxError( void ) {}
+    /*!
+     * \brief  FHSS Change Channel callback prototype.
+     *
+     * \param [IN] currentChannel   Index number of the current channel
+     */
+    virtual void FhssChangeChannel( uint8_t currentChannel ) {}
+    /*!
+     * \brief CAD Done callback prototype.
+     *
+     * \param [IN] channelActivityDetected  Channel Activity detected during the CAD
+     */
+    virtual void CadDone( bool channelActivityDetected ) {}
+    /*!
+     * \brief Mac Event callback prototype.
+     */
+    virtual void MacEvent( void ) {}
+
+    virtual void LinkIdle(void) {}
+};
+
+#endif // __SXRADIOEVENTS_H__
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/Lora/Utils/MTSCircularBuffer.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,160 @@
+#ifndef MTSCIRCULARBUFFER_H
+#define MTSCIRCULARBUFFER_H
+
+#include <Callback.h>
+
+#include "Utils.h"
+
+namespace mts
+{
+
+/** This class provides a circular byte buffer meant for temporary storage
+* during IO transactions.  It contains many of the common methods you
+* would expect from a circular buffer like read, write, and various
+* methods for checking the size or status.  It should be noted that
+* this class does not include any special code for thread safety like
+* a lock.  In most cases this is not problematic, but is something
+* to be aware of.
+*/
+class MTSCircularBuffer
+{
+public:
+    /** Creates an MTSCircularBuffer object with the specified static size.
+    *
+    * @prarm bufferSize size of the buffer in bytes.
+    */
+    MTSCircularBuffer(int bufferSize);
+
+    /** Destructs an MTSCircularBuffer object and frees all related resources.
+    */
+    ~MTSCircularBuffer();
+
+    /** This method enables bulk reads from the buffer.  If more data is
+    * requested then available it simply returns all remaining data within the
+    * buffer.
+    *
+    * @param data the buffer where data read will be added to.
+    * @param length the amount of data in bytes to be read into the buffer.
+    * @returns the total number of bytes that were read.
+    */
+    int read(char* data, int length);
+
+    /** This method reads a single byte from the buffer.
+    *
+    * @param data char where the read byte will be stored.
+    * @returns 1 if byte is read or 0 if no bytes available.
+    */
+    int read(char& data);
+
+    /** This method enables bulk writes to the buffer. If more data
+    * is requested to be written then space available the method writes
+    * as much data as possible and returns the actual amount written.
+    *
+    * @param data the byte array to be written.
+    * @param length the length of data to be written from the data paramter.
+    * @returns the number of bytes written to the buffer, which is 0 if
+    * the buffer is full.
+    */
+    int write(const char* data, int length);
+
+    /** This method writes a signle byte as a char to the buffer.
+    *
+    * @param data the byte to be written as a char.
+    * @returns 1 if the byte was written or 0 if the buffer was full.
+    */
+    int write(char data);
+
+    /** This method is used to setup a callback funtion when the buffer reaches
+    * a certain threshold. The threshold condition is checked after every read
+    * and write call is completed. The condition is made up of both a threshold
+    * value and operator. An example that would trigger a callback is if the
+    * threshold was 10, the operator GREATER, and there were 12 bytes added to an
+    * empty buffer.
+    *
+    * @param tptr a pointer to the object to be called when the condition is met.
+    * @param mptr a pointer to the function within the object to be called when
+    * the condition is met.
+    * @param threshold the value in bytes to be used as part of the condition.
+    * @param op the operator to be used in conjunction with the threshold
+    * as part of the condition.
+    */
+    template<typename T>
+    void attach(T *tptr, void( T::*mptr)(void), int threshold, RelationalOperator op) {
+        _threshold = threshold;
+        _op = op;
+        notify.attach(tptr, mptr);
+    }
+
+    /** This method is used to setup a callback funtion when the buffer reaches
+    * a certain threshold. The threshold condition is checked after every read
+    * and write call is completed. The condition is made up of both a threshold
+    * value and operator. An example that would trigger a callback is if the
+    * threshold was 10, the operator GREATER, and there were 12 bytes added to an
+    * empty buffer.
+    *
+    * @param fptr a pointer to the static function to be called when the condition
+    * is met.
+    * @param threshold the value in bytes to be used as part of the condition.
+    * @param op the operator to be used in conjunction with the threshold
+    * as part of the condition.
+    */
+    void attach(void(*fptr)(void), int threshold, RelationalOperator op) {
+        _threshold = threshold;
+        _op = op;
+        notify = fptr;
+    }
+
+    /** This method returns the size of the storage space currently allocated for
+    * the buffer. This value is equivalent to the one passed into the constructor.
+    * This value is equal or greater than the size() of the buffer.
+    *
+    * @returns the allocated size of the buffer in bytes.
+    */
+    int capacity();
+
+    /** This method returns the amount of space left for writing.
+    *
+    * @returns numbers of unused bytes in buffer.
+    */
+    int remaining();
+
+    /** This method returns the number of bytes available for reading.
+    *
+    * @returns number of bytes currently in buffer.
+    */
+    int size();
+
+    /** This method returns whether the buffer is full.
+    *
+    * @returns true if full, otherwise false.
+    */
+    bool isFull();
+
+    /** This method returns whether the buffer is empty.
+    *
+    * @returns true if empty, otherwise false.
+    */
+    bool isEmpty();
+
+    /** This method clears the buffer. This is done through
+    * setting the internal read and write indexes to the same
+    * value and is therefore not an expensive operation.
+    */
+    void clear();
+
+
+private:
+    int bufferSize; // total size of the buffer
+    char* buffer; // internal byte buffer as a character buffer
+    int readIndex; // read index for circular buffer
+    int writeIndex; // write index for circular buffer
+    int bytes; // available data
+    Callback<void()> notify; // Internal callback notification
+    int _threshold; // threshold for the notification
+    RelationalOperator _op; // operator that determines the direction of the threshold
+    void checkThreshold(); // private function that checks thresholds and processes notifications
+};
+
+}
+
+#endif /* MTSCIRCULARBUFFER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/Lora/Utils/MTSLog.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,108 @@
+#ifndef MTSLOG_H
+#define MTSLOG_H
+
+#include <string>
+
+inline const char* className(const std::string& prettyFunction)
+{
+    size_t colons = prettyFunction.find_last_of("::");
+    if (colons == std::string::npos)
+        return "";
+    size_t begin = prettyFunction.substr(0,colons).rfind(" ") + 1;
+    size_t end = colons - begin;
+
+    return prettyFunction.substr(begin,end).c_str();
+}
+
+#define __CLASSNAME__ className(__PRETTY_FUNCTION__)
+
+
+#ifdef MTS_DEBUG
+#define logFatal(format, ...) \
+    mts::MTSLog::printMessage(mts::MTSLog::FATAL_LEVEL, "%s:%s:%d| [%s] " format "\r\n", __CLASSNAME__, __func__, __LINE__, mts::MTSLog::FATAL_LABEL, ##__VA_ARGS__)
+#define logError(format, ...) \
+    mts::MTSLog::printMessage(mts::MTSLog::ERROR_LEVEL, "%s:%s:%d| [%s] " format "\r\n", __CLASSNAME__, __func__, __LINE__, mts::MTSLog::ERROR_LABEL, ##__VA_ARGS__)
+#define logWarning(format, ...) \
+    mts::MTSLog::printMessage(mts::MTSLog::WARNING_LEVEL, "%s:%s:%d| [%s] " format "\r\n", __CLASSNAME__, __func__, __LINE__, mts::MTSLog::WARNING_LABEL, ##__VA_ARGS__)
+#define logInfo(format, ...) \
+    mts::MTSLog::printMessage(mts::MTSLog::INFO_LEVEL, "%s:%s:%d| [%s] " format "\r\n", __CLASSNAME__, __func__, __LINE__, mts::MTSLog::INFO_LABEL, ##__VA_ARGS__)
+#define logDebug(format, ...) \
+    mts::MTSLog::printMessage(mts::MTSLog::DEBUG_LEVEL, "%s:%s:%d| [%s] " format "\r\n", __CLASSNAME__, __func__, __LINE__, mts::MTSLog::DEBUG_LABEL, ##__VA_ARGS__)
+#define logTrace(format, ...) \
+    mts::MTSLog::printMessage(mts::MTSLog::TRACE_LEVEL, "%s:%s:%d| [%s] " format "\r\n", __CLASSNAME__, __func__, __LINE__, mts::MTSLog::TRACE_LABEL, ##__VA_ARGS__)
+#else
+#define logFatal(format, ...) \
+    mts::MTSLog::printMessage(mts::MTSLog::FATAL_LEVEL, "[%s] " format "\r\n", mts::MTSLog::FATAL_LABEL, ##__VA_ARGS__)
+#define logError(format, ...) \
+    mts::MTSLog::printMessage(mts::MTSLog::ERROR_LEVEL, "[%s] " format "\r\n", mts::MTSLog::ERROR_LABEL, ##__VA_ARGS__)
+#define logWarning(format, ...) \
+    mts::MTSLog::printMessage(mts::MTSLog::WARNING_LEVEL, "[%s] " format "\r\n", mts::MTSLog::WARNING_LABEL, ##__VA_ARGS__)
+#define logInfo(format, ...) \
+    mts::MTSLog::printMessage(mts::MTSLog::INFO_LEVEL, "[%s] " format "\r\n", mts::MTSLog::INFO_LABEL, ##__VA_ARGS__)
+#define logDebug(format, ...) \
+    mts::MTSLog::printMessage(mts::MTSLog::DEBUG_LEVEL, "[%s] " format "\r\n", mts::MTSLog::DEBUG_LABEL, ##__VA_ARGS__)
+#define logTrace(format, ...) \
+    mts::MTSLog::printMessage(mts::MTSLog::TRACE_LEVEL, "[%s] " format "\r\n", mts::MTSLog::TRACE_LABEL, ##__VA_ARGS__)
+#endif
+
+namespace mts {
+
+class MTSLog
+{
+public:
+
+    /** Enum of log levels.
+     */
+    enum logLevel {
+        NONE_LEVEL = 0,
+        FATAL_LEVEL = 1,
+        ERROR_LEVEL = 2,
+        WARNING_LEVEL = 3,
+        INFO_LEVEL = 4,
+        DEBUG_LEVEL = 5,
+        TRACE_LEVEL = 6
+    };
+
+    /** Print log message.
+     */
+    static void printMessage(int level, const char* format, ...);
+
+    /** Determine if the given level is currently printable.
+     */
+    static bool printable(int level);
+
+    /** Set log level
+     * Messages with lower priority than the current level will not be printed.
+     * If the level is set to NONE, no messages will print.
+     */
+    static void setLogLevel(int level);
+
+    /** Get the current log level.
+     */
+    static int getLogLevel();
+
+    /** Get string representation of the current log level.
+     */
+    static const char* getLogLevelString();
+
+    static const char* NONE_LABEL;
+    static const char* FATAL_LABEL;
+    static const char* ERROR_LABEL;
+    static const char* WARNING_LABEL;
+    static const char* INFO_LABEL;
+    static const char* DEBUG_LABEL;
+    static const char* TRACE_LABEL;
+
+private:
+
+    /** Constructor
+     */
+    MTSLog();
+
+    static int currentLevel;
+
+};
+
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/Lora/Utils/MTSText.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,83 @@
+#ifndef MTSTEXT_H
+#define MTSTEXT_H
+
+#include <string>
+#include <vector>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+namespace mts
+{
+
+/** This class contains a number of static methods for manipulating strings and other
+* text data.
+*/
+class Text
+{
+public:
+    /** This static method can be used to pull out a string at the next line break. A
+    * break can either be a newline '\n', carriage return '\r' or both.
+    *
+    * @param source the source string to look for the line break on.
+    * @param start the start postion within the string to begin looking for the line
+    * break.
+    * @param cursor this value will be updated with the index for the next available character
+    * after the line break. If a line break is not found returns -1.
+    * @returns the string beginning with the start index up to including the line breaks.
+    */
+    static std::string getLine(const std::string& source, const size_t& start, size_t& cursor);
+
+    /** This is a static method for splitting strings using a delimeter value.
+    *
+    * @param str the string to try and split.
+    * @param delimiter the delimeter value to split on as a character.
+    * @param limit the maximum number of splits. If equal to 0 it splits as amny times as possible.
+    * The default is 0.
+    * @returns an ordered vector of strings conatining the splits of the original string.
+    */
+    static std::vector<std::string> split(const std::string& str, char delimiter, int limit = 0);
+
+    /** This is a static method for splitting strings using a delimeter value.
+    *
+    * @param str the string to try and split.
+    * @param delimiter the delimeter value to split on as a string.
+    * @param limit the maximum number of splits. If equal to 0 it splits as amny times as possible.
+    * The default is 0.
+    * @returns an ordered vector of strings conatining the splits of the original string.
+    */
+    static std::vector<std::string> split(const std::string& str, const std::string& delimiter, int limit = 0);
+    
+    static std::string readString(char* index, int length);
+
+    static std::string toUpper(const std::string str);
+
+    static std::string float2String(double val, int precision);
+
+    static std::string bin2hexString(const std::vector<uint8_t>& data, const char* delim = "", bool leadingZeros = false, bool bytePadding = true);
+
+    static std::string bin2hexString(const uint8_t* data, const uint32_t len, const char* delim = "", bool leadingZeros = false, bool bytePadding = true);
+
+    static std::string bin2base64(const std::vector<uint8_t>& data);
+
+    static std::string bin2base64(const uint8_t* data, size_t size);
+
+    static bool base642bin(const std::string in, std::vector<uint8_t>& out);
+
+    static void ltrim(std::string& str, const char* args);
+
+    static void rtrim(std::string& str, const char* args);
+
+    static void trim(std::string& str, const char* args);
+
+private:
+    // Safety for class with only static methods
+    Text();
+    Text(const Text& other);
+    Text& operator=(const Text& other);
+};
+
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/Lora/Utils/Utils.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,41 @@
+#ifndef UTILS_H
+#define UTILS_H
+
+#include <string>
+
+//Defines a max function that can be used.
+inline int mts_max(int a, int b) { return a > b ? a : b; }
+
+//Defines a min function that can be used.
+inline int mts_min(int a, int b) { return a < b ? a : b; }
+
+///An enumeration for relational operators
+enum RelationalOperator {
+    GREATER, LESS, EQUAL, GREATER_EQUAL, LESS_EQUAL
+};
+
+/** A static method for getting a string representation for the RelationalOperator
+* enumeration.
+*
+* @param relationalOperator a RelationalOperator enumeration.
+* @returns the enumeration name as a string.
+*/
+static inline std::string getRelationalOperatorNames(RelationalOperator relationalOperator)
+{
+    switch(relationalOperator) {
+        case GREATER:
+            return "GREATER";
+        case LESS:
+            return "LESS";
+        case EQUAL:
+            return "EQUAL";
+        case GREATER_EQUAL:
+            return "GREATER_EQUAL";
+        case LESS_EQUAL:
+            return "LESS_EQUAL";
+        default:
+            return "UNKNOWN ENUM";
+    }
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/Lora/Utils/aes.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,171 @@
+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
+
+ LICENSE TERMS
+
+ The redistribution and use of this software (with or without changes)
+ is allowed without the payment of fees or royalties provided that:
+
+  1. source code distributions include the above copyright notice, this
+     list of conditions and the following disclaimer;
+
+  2. binary distributions include the above copyright notice, this list
+     of conditions and the following disclaimer in their documentation;
+
+  3. the name of the copyright holder is not used to endorse products
+     built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue 09/09/2006
+
+ This is an AES implementation that uses only 8-bit byte operations on the
+ cipher state.
+ */
+
+#ifndef AES_H
+#define AES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if 1
+#  define AES_ENC_PREKEYED  /* AES encryption with a precomputed key schedule  */
+#endif
+#if 1
+#  define AES_DEC_PREKEYED  /* AES decryption with a precomputed key schedule  */
+#endif
+#if 0
+#  define AES_ENC_128_OTFK  /* AES encryption with 'on the fly' 128 bit keying */
+#endif
+#if 0
+#  define AES_DEC_128_OTFK  /* AES decryption with 'on the fly' 128 bit keying */
+#endif
+#if 0
+#  define AES_ENC_256_OTFK  /* AES encryption with 'on the fly' 256 bit keying */
+#endif
+#if 0
+#  define AES_DEC_256_OTFK  /* AES decryption with 'on the fly' 256 bit keying */
+#endif
+
+#define N_ROW                   4
+#define N_COL                   4
+#define N_BLOCK   (N_ROW * N_COL)
+#define N_MAX_ROUNDS           14
+
+typedef unsigned char uint_8t;
+
+typedef uint_8t return_type;
+
+/*  Warning: The key length for 256 bit keys overflows a byte
+    (see comment below)
+*/
+
+typedef uint_8t length_type;
+
+typedef struct
+{   uint_8t ksch[(N_MAX_ROUNDS + 1) * N_BLOCK];
+    uint_8t rnd;
+} aes_context;
+
+/*  The following calls are for a precomputed key schedule
+
+    NOTE: If the length_type used for the key length is an
+    unsigned 8-bit character, a key length of 256 bits must
+    be entered as a length in bytes (valid inputs are hence
+    128, 192, 16, 24 and 32).
+*/
+
+#if defined( AES_ENC_PREKEYED ) || defined( AES_DEC_PREKEYED )
+
+return_type aes_set_key( const unsigned char key[],
+                         length_type keylen,
+                         aes_context ctx[1] );
+#endif
+
+#if defined( AES_ENC_PREKEYED )
+
+return_type aes_encrypt( const unsigned char in[N_BLOCK],
+                         unsigned char out[N_BLOCK],
+                         const aes_context ctx[1] );
+
+return_type aes_cbc_encrypt( const unsigned char *in,
+                         unsigned char *out,
+                         int n_block,
+                         unsigned char iv[N_BLOCK],
+                         const aes_context ctx[1] );
+#endif
+
+#if defined( AES_DEC_PREKEYED )
+
+return_type aes_decrypt( const unsigned char in[N_BLOCK],
+                         unsigned char out[N_BLOCK],
+                         const aes_context ctx[1] );
+
+return_type aes_cbc_decrypt( const unsigned char *in,
+                         unsigned char *out,
+                         int n_block,
+                         unsigned char iv[N_BLOCK],
+                         const aes_context ctx[1] );
+#endif
+
+/*  The following calls are for 'on the fly' keying.  In this case the
+    encryption and decryption keys are different.
+
+    The encryption subroutines take a key in an array of bytes in
+    key[L] where L is 16, 24 or 32 bytes for key lengths of 128,
+    192, and 256 bits respectively.  They then encrypts the input
+    data, in[] with this key and put the reult in the output array
+    out[].  In addition, the second key array, o_key[L], is used
+    to output the key that is needed by the decryption subroutine
+    to reverse the encryption operation.  The two key arrays can
+    be the same array but in this case the original key will be
+    overwritten.
+
+    In the same way, the decryption subroutines output keys that
+    can be used to reverse their effect when used for encryption.
+
+    Only 128 and 256 bit keys are supported in these 'on the fly'
+    modes.
+*/
+
+#if defined( AES_ENC_128_OTFK )
+void aes_encrypt_128( const unsigned char in[N_BLOCK],
+                      unsigned char out[N_BLOCK],
+                      const unsigned char key[N_BLOCK],
+                      uint_8t o_key[N_BLOCK] );
+#endif
+
+#if defined( AES_DEC_128_OTFK )
+void aes_decrypt_128( const unsigned char in[N_BLOCK],
+                      unsigned char out[N_BLOCK],
+                      const unsigned char key[N_BLOCK],
+                      unsigned char o_key[N_BLOCK] );
+#endif
+
+#if defined( AES_ENC_256_OTFK )
+void aes_encrypt_256( const unsigned char in[N_BLOCK],
+                      unsigned char out[N_BLOCK],
+                      const unsigned char key[2 * N_BLOCK],
+                      unsigned char o_key[2 * N_BLOCK] );
+#endif
+
+#if defined( AES_DEC_256_OTFK )
+void aes_decrypt_256( const unsigned char in[N_BLOCK],
+                      unsigned char out[N_BLOCK],
+                      const unsigned char key[2 * N_BLOCK],
+                      unsigned char o_key[2 * N_BLOCK] );
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/Lora/Utils/cmac.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,75 @@
+/**************************************************************************
+Copyright (C) 2009 Lander Casado, Philippas Tsigas
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files 
+(the "Software"), to deal with the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish, 
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions: 
+
+Redistributions of source code must retain the above copyright notice, 
+this list of conditions and the following disclaimers. Redistributions in
+binary form must reproduce the above copyright notice, this list of
+conditions and the following disclaimers in the documentation and/or 
+other materials provided with the distribution.
+
+In no event shall the authors or copyright holders be liable for any special,
+incidental, indirect or consequential damages of any kind, or any damages 
+whatsoever resulting from loss of use, data or profits, whether or not 
+advised of the possibility of damage, and on any theory of liability, 
+arising out of or in connection with the use or performance of this software.
+ 
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+DEALINGS WITH THE SOFTWARE
+
+*****************************************************************************/
+
+#ifndef _CMAC_H_
+#define _CMAC_H_
+
+#include "casado/aes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+  
+#define AES_CMAC_KEY_LENGTH     16
+#define AES_CMAC_DIGEST_LENGTH  16
+ 
+
+typedef unsigned char  u_int8_t;
+typedef unsigned int u_int;
+typedef struct _AES_CMAC_CTX {
+            aes_context    rijndael;
+            u_int8_t        X[16];
+            u_int8_t        M_last[16];
+            u_int           M_n;
+    } AES_CMAC_CTX;
+   
+//#include <sys/cdefs.h>
+    
+//__BEGIN_DECLS
+void     AES_CMAC_Init(AES_CMAC_CTX * ctx);
+void     AES_CMAC_SetKey(AES_CMAC_CTX * ctx, const u_int8_t key[AES_CMAC_KEY_LENGTH]);
+void     AES_CMAC_Update(AES_CMAC_CTX * ctx, const u_int8_t * data, u_int len);
+          //          __attribute__((__bounded__(__string__,2,3)));
+void     AES_CMAC_Final(u_int8_t digest[AES_CMAC_DIGEST_LENGTH], AES_CMAC_CTX  * ctx);
+            //     __attribute__((__bounded__(__minbytes__,1,AES_CMAC_DIGEST_LENGTH)));
+//__END_DECLS
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _CMAC_H_ */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/Lora/Utils/library_version.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,6 @@
+#ifndef __LIBRARY_VERSION_H__
+#define __LIBRARY_VERSION_H__
+
+#define MDOT_VERSION "3.1.0-9-g2c3ce5b"
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/SpiFlash25.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,108 @@
+/* Library for SPI flash 25* devices.
+ * Copyright (c) 2014 Multi-Tech Systems
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef SPIFLASH25_H
+#define SPIFLASH25_H
+
+#include "mbed.h"
+
+class SpiFlash25 {
+    public:
+        SpiFlash25(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName W = NC, PinName HOLD = NC, int page_size = 256, int mem_size = 2097152);
+
+        /* Set the page size (default 256) */
+        void set_page_size(int size);
+
+        /* Set up the internal SPI object */
+        void format(int bits, int mode);
+        void frequency(int hz);
+
+        /* Reads and writes can be across page boundaries */
+        bool read(int addr, int len, char* data);
+        bool write(int addr, int len, const char* data);
+
+        /* Read ID and status registers */
+        char* read_id();
+		void write_status(char data);
+        char read_status();
+
+        /* Erase methods */
+        void clear_sector(int addr);
+        void clear_mem();
+
+        void deep_power_down();
+        void wakeup();
+
+    private:
+        enum {
+            WRITE_ENABLE                = 0x06,
+            WRITE_DISABLE               = 0x04,
+            READ_IDENTIFICATION         = 0x9F,
+            READ_STATUS                 = 0x05,
+            WRITE_STATUS                = 0x01,
+            READ_DATA                   = 0x03,
+            READ_DATA_FAST              = 0x0B,
+            PAGE_PROGRAM                = 0x02,
+            SECTOR_ERASE                = 0xD8,
+            BULK_ERASE                  = 0xC7,
+            DEEP_POWER_DOWN             = 0xB9,
+            DEEP_POWER_DOWN_RELEASE     = 0xAB,
+        };
+
+        enum {
+            STATUS_SRWD                 = 0x80,     // 0b 1000 0000
+            STATUS_BP2                  = 0x10,     // 0b 0001 0000
+            STATUS_BP1                  = 0x08,     // 0b 0000 1000
+            STATUS_BP0                  = 0x04,     // 0b 0000 0100
+            STATUS_WEL                  = 0x02,     // 0b 0000 0010
+            STATUS_WIP                  = 0x01,     // 0b 0000 0001
+        };
+
+        enum {
+            ID_MANUFACTURER             = 0,
+            ID_MEM_TYPE                 = 1,
+            ID_MEM_SIZE                 = 2,
+        };
+
+        bool write_page(int addr, int len, const char* data);
+        void enable_write();
+        void wait_for_write();
+
+        static inline char high_byte(int addr) {
+            return ((addr & 0xff0000) >> 16);
+        }
+        static inline char mid_byte(int addr) {
+            return ((addr & 0xff00) >> 8);
+        }
+        static inline char low_byte(int addr) {
+            return (addr & 0xff);
+        }
+
+        SPI _spi;
+        DigitalOut _cs;
+        DigitalOut* _w;
+        DigitalOut* _hold;
+        int _mem_size;
+        int _page_size;
+        char _id[3];
+};
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/WakeUp.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,98 @@
+#include "mbed.h"
+
+/**
+ * Class to make wake up a microcontroller from deepsleep using a low-power timer. 
+ *
+ * @code
+ * // Depending on the LED connections either the LED is off the 2 seconds
+ * // the target spends in deepsleep(), and on for the other second. Or it is inverted 
+ * 
+ * #include "mbed.h"
+ * #include "WakeUp.h"
+ * 
+ * DigitalOut myled(LED1);
+ * 
+ * int main() {
+ *     wait(5);
+ *
+ *     //The low-power oscillator can be quite inaccurate on some targets
+ *     //this function calibrates it against the main clock
+ *     WakeUp::calibrate();
+ *    
+ *     while(1) {
+ *         //Set LED to zero
+ *         myled = 0;
+ *         
+ *         //Set wakeup time for 2 seconds
+ *         WakeUp::set_ms(2000);
+ *         
+ *         //Enter deepsleep, the program won't go beyond this point until it is woken up
+ *         deepsleep();
+ *         
+ *         //Set LED for 1 second to one
+ *         myled = 1;
+ *         wait(1);
+ *     }
+ * }
+ * @endcode
+ */
+class WakeUp
+{
+public:
+    /**
+    * Set the timeout
+    *
+    * @param s required time in seconds
+    */
+    static void set(uint32_t s) {
+        set_ms(1000 * s);
+    }
+    
+    /**
+    * Set the timeout
+    *
+    * @param ms required time in milliseconds
+    */
+    static void set_ms(uint32_t ms);
+    
+    /**
+    * Attach a function to be called after timeout
+    *
+    * This is optional, if you just want to wake up you 
+    * do not need to attach a function.
+    *
+    * Important: Many targets will run the wake-up routine
+    * at reduced clock speed, afterwards clock speed is restored.
+    * This means that clock speed dependent functions, such as printf
+    * might end up distorted.
+    *
+    * Also supports normal way to attach member functions
+    * (not documented for simplicity)
+    *
+    * @param *function function to call
+    */
+    static void attach(void (*function)(void)) {
+        callback.attach(function);
+    }
+
+    template<typename T>
+    static void attach(T *object, void (T::*member)(void)) {
+        callback.attach(object, member);
+    }
+    
+    /**
+    * Calibrate the timer
+    *
+    * Some of the low-power timers have very bad accuracy.
+    * This function calibrates it against the main timer.
+    *
+    * Warning: Blocks for 100ms!
+    */
+    static void calibrate(void);
+
+
+private:
+    static FunctionPointer callback;
+    static void irq_handler(void);
+    static float cycles_per_ms;
+};
\ No newline at end of file
Binary file mdot/fota.ar has changed
Binary file mdot/libfota.a has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/mDot.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,1720 @@
+// TODO: add license header
+
+#ifndef MDOT_H
+#define MDOT_H
+
+#include "mbed.h"
+#include "rtos.h"
+#include "Mote.h"
+#include <vector>
+#include <map>
+#include <string>
+
+class mDotEvent;
+class LoRaConfig;
+
+
+class mDot {
+        friend class mDotEvent;
+
+    private:
+
+        mDot(lora::ChannelPlan* plan);
+        ~mDot();
+
+        void initLora();
+
+        void setLastError(const std::string& str);
+
+        static bool validateBaudRate(const uint32_t& baud);
+        static bool validateFrequencySubBand(const uint8_t& band);
+        bool validateDataRate(const uint8_t& dr);
+
+        int32_t joinBase(const uint32_t& retries);
+        int32_t sendBase(const std::vector<uint8_t>& data, const bool& confirmed = false, const bool& blocking = true, const bool& highBw = false);
+        void waitForPacket();
+        void waitForLinkCheck();
+
+        void setActivityLedState(const uint8_t& state);
+        uint8_t getActivityLedState();
+
+        void blinkActivityLed(void) {
+            if (_activity_led) {
+                int val = _activity_led->read();
+                _activity_led->write(!val);
+            }
+        }
+
+        mDot(const mDot&);
+        mDot& operator=(const mDot&);
+
+        uint32_t RTC_ReadBackupRegister(uint32_t RTC_BKP_DR);
+        void RTC_WriteBackupRegister(uint32_t RTC_BKP_DR, uint32_t Data);
+
+        void enterStopMode(const uint32_t& interval, const uint8_t& wakeup_mode = RTC_ALARM);
+        void enterStandbyMode(const uint32_t& interval, const uint8_t& wakeup_mode = RTC_ALARM);
+
+        static mDot* _instance;
+
+        lora::Mote* _mote;
+        LoRaConfig* _config;
+        lora::Settings _settings;
+        mDotEvent* _events;
+
+        std::string _last_error;
+        static const uint32_t _baud_rates[];
+        uint8_t _activity_led_state;
+        Ticker _tick;
+        DigitalOut* _activity_led;
+        bool _activity_led_enable;
+        PinName _activity_led_pin;
+        bool _activity_led_external;
+        uint8_t _linkFailCount;
+        uint8_t _class;
+        InterruptIn* _wakeup;
+        PinName _wakeup_pin;
+
+        typedef enum {
+            OFF,
+            ON,
+            BLINK,
+        } state;
+
+    public:
+
+#if defined(TARGET_MTS_MDOT_F411RE)
+        typedef enum {
+            FM_APPEND = (1 << 0),
+            FM_TRUNC = (1 << 1),
+            FM_CREAT = (1 << 2),
+            FM_RDONLY = (1 << 3),
+            FM_WRONLY = (1 << 4),
+            FM_RDWR = (FM_RDONLY | FM_WRONLY),
+            FM_DIRECT = (1 << 5)
+        } FileMode;
+#endif /* TARGET_MTS_MDOT_F411RE */
+
+        typedef enum {
+            MDOT_OK = 0,
+            MDOT_INVALID_PARAM = -1,
+            MDOT_TX_ERROR = -2,
+            MDOT_RX_ERROR = -3,
+            MDOT_JOIN_ERROR = -4,
+            MDOT_TIMEOUT = -5,
+            MDOT_NOT_JOINED = -6,
+            MDOT_ENCRYPTION_DISABLED = -7,
+            MDOT_NO_FREE_CHAN = -8,
+            MDOT_TEST_MODE = -9,
+            MDOT_NO_ENABLED_CHAN = -10,
+            MDOT_AGGREGATED_DUTY_CYCLE = -11,
+            MDOT_MAX_PAYLOAD_EXCEEDED = -12,
+            MDOT_LBT_CHANNEL_BUSY = -13,
+            MDOT_NOT_IDLE = -14,
+            MDOT_ERROR = -1024,
+        } mdot_ret_code;
+
+        enum JoinMode {
+            MANUAL = 0,
+            OTA,
+            AUTO_OTA,
+            PEER_TO_PEER
+        };
+
+        enum Mode {
+            COMMAND_MODE,
+            SERIAL_MODE
+        };
+
+        enum RX_Output {
+            HEXADECIMAL,
+            BINARY
+        };
+
+        enum DataRates {
+            DR0,
+            DR1,
+            DR2,
+            DR3,
+            DR4,
+            DR5,
+            DR6,
+            DR7,
+            DR8,
+            DR9,
+            DR10,
+            DR11,
+            DR12,
+            DR13,
+            DR14,
+            DR15
+        };
+
+        enum FrequencySubBands {
+            FSB_ALL,
+            FSB_1,
+            FSB_2,
+            FSB_3,
+            FSB_4,
+            FSB_5,
+            FSB_6,
+            FSB_7,
+            FSB_8
+        };
+
+        enum JoinByteOrder {
+            LSB,
+            MSB
+        };
+
+        enum wakeup_mode {
+            RTC_ALARM,
+            INTERRUPT,
+            RTC_ALARM_OR_INTERRUPT
+        };
+
+        enum UserBackupRegs {
+            UBR0,
+            UBR1,
+            UBR2,
+            UBR3,
+            UBR4,
+            UBR5,
+            UBR6,
+            UBR7,
+            UBR8,
+            UBR9
+#if defined (TARGET_XDOT_L151CC)
+           ,UBR10,
+            UBR11,
+            UBR12,
+            UBR13,
+            UBR14,
+            UBR15,
+            UBR16,
+            UBR17,
+            UBR18,
+            UBR19,
+            UBR20,
+            UBR21
+#endif /* TARGET_XDOT_L151CC */
+        };
+
+#if defined(TARGET_MTS_MDOT_F411RE)
+        typedef struct {
+                int16_t fd;
+                char name[33];
+                uint32_t size;
+        } mdot_file;
+#endif /* TARGET_MTS_MDOT_F411RE */
+
+        typedef struct {
+                uint32_t Up;
+                uint32_t Down;
+                uint32_t Joins;
+                uint32_t JoinFails;
+                uint32_t MissedAcks;
+                uint32_t CRCErrors;
+        } mdot_stats;
+
+        typedef struct {
+                int16_t last;
+                int16_t min;
+                int16_t max;
+                int16_t avg;
+        } rssi_stats;
+
+        typedef struct {
+                int16_t last;
+                int16_t min;
+                int16_t max;
+                int16_t avg;
+        } snr_stats;
+
+        typedef struct {
+                bool status;
+                uint8_t dBm;
+                uint32_t gateways;
+                std::vector<uint8_t> payload;
+        } link_check;
+
+        typedef struct {
+                int32_t status;
+                int16_t rssi;
+                int16_t snr;
+        } ping_response;
+
+        static std::string JoinModeStr(uint8_t mode);
+        static std::string ModeStr(uint8_t mode);
+        static std::string RxOutputStr(uint8_t format);
+        static std::string DataRateStr(uint8_t rate);
+        static std::string FrequencyBandStr(uint8_t band);
+        static std::string FrequencySubBandStr(uint8_t band);
+
+#if defined(TARGET_MTS_MDOT_F411RE)
+        uint32_t UserRegisters[10];
+#else
+        uint32_t UserRegisters[22];
+#endif /* TARGET_MTS_MDOT_F411RE */
+
+        /**
+         *  Get a handle to the singleton object
+         * @param plan the channel plan to use
+         * @returns pointer to mDot object
+         */
+        static mDot* getInstance(lora::ChannelPlan* plan);
+
+        /**
+	 * Can only be used after a dot has 
+         * configured with a plan
+         * @returns pointer to mDot object
+         */
+        static mDot* getInstance();
+
+        void setEvents(mDotEvent* events);
+
+        /**
+         *
+         * Get library version information
+         * @returns string containing library version information
+         */
+        std::string getId();
+
+        /**
+         * Get MTS LoRa version information
+         * @returns string containing MTS LoRa version information
+         */
+        std::string getMtsLoraId();
+
+        /**
+         * Perform a soft reset of the system
+         */
+        void resetCpu();
+
+        /**
+         * Reset config to factory default
+         */
+        void resetConfig();
+
+        /**
+         * Save config data to non volatile memory
+         * @returns true if success, false if failure
+         */
+        bool saveConfig();
+
+        /**
+         * Set the log level for the library
+         * options are:
+         *  NONE_LEVEL - logging is off at this level
+         *  FATAL_LEVEL - only critical errors will be reported
+         *  ERROR_LEVEL
+         *  WARNING_LEVEL
+         *  INFO_LEVEL
+         *  DEBUG_LEVEL
+         *  TRACE_LEVEL - every detail will be reported
+         * @param level the level to log at
+         * @returns MDOT_OK if success
+         */
+        int32_t setLogLevel(const uint8_t& level);
+
+        /**
+         * Get the current log level for the library
+         * @returns current log level
+         */
+        uint8_t getLogLevel();
+
+        /**
+         * Seed pseudo RNG in LoRaMac layer, uses random value from radio RSSI reading by default
+         * @param seed for RNG
+         */
+        void seedRandom(uint32_t seed);
+
+
+        uint8_t setChannelPlan(lora::ChannelPlan* plan);
+
+        lora::Settings* getSettings();
+
+        /**
+         * Enable or disable the activity LED.
+         * @param enable true to enable the LED, false to disable
+         */
+        void setActivityLedEnable(const bool& enable);
+
+        /**
+         * Find out if the activity LED is enabled
+         * @returns true if activity LED is enabled, false if disabled
+         */
+        bool getActivityLedEnable();
+
+        /**
+         * Use a different pin for the activity LED.
+         * The default is XBEE_RSSI.
+         * @param pin the new pin to use
+         */
+        void setActivityLedPin(const PinName& pin);
+
+        /**
+         * Use an external DigitalOut object for the activity LED.
+         * The pointer must stay valid!
+         * @param pin the DigitalOut object to use
+         */
+        void setActivityLedPin(DigitalOut* pin);
+
+        /**
+         * Find out what pin the activity LED is on
+         * @returns the pin the activity LED is using
+         */
+        PinName getActivityLedPin();
+
+        /**
+         * Returns boolean indicative of start-up from standby mode
+         * @returns true if dot woke from standby
+         */
+        bool getStandbyFlag();
+
+        std::vector<uint16_t> getChannelMask();
+
+        int32_t setChannelMask(uint8_t offset, uint16_t mask);
+
+        /**
+         * Add a channel
+         * @returns MDOT_OK
+         */
+        int32_t addChannel(uint8_t index, uint32_t frequency, uint8_t datarateRange);
+
+        /**
+         * Add a downlink channel
+         * @returns MDOT_OK
+         */
+        int32_t addDownlinkChannel(uint8_t index, uint32_t frequency);
+
+        /**
+         * Get list of channel frequencies currently in use
+         * @returns vector of channels currently in use
+         */
+        std::vector<uint32_t> getChannels();
+
+        /**
+         * Get list of downlink channel frequencies currently in use
+         * @returns vector of channels currently in use
+         */
+        std::vector<uint32_t> getDownlinkChannels();
+
+        /**
+         * Get list of channel datarate ranges currently in use
+         * @returns vector of datarate ranges currently in use
+         */
+        std::vector<uint8_t> getChannelRanges();
+
+        /**
+         * Get list of channel frequencies in config file to be used as session defaults
+         * @returns vector of channels in config file
+         */
+        std::vector<uint32_t> getConfigChannels();
+
+        /**
+         * Get list of channel datarate ranges in config file to be used as session defaults
+         * @returns vector of datarate ranges in config file
+         */
+        std::vector<uint8_t> getConfigChannelRanges();
+
+        /**
+         * Get default frequency band
+         * @returns frequency band the device was manufactured for
+         */
+        uint8_t getDefaultFrequencyBand();
+
+        /**
+         * Set frequency sub band
+         * only applicable if frequency band is set for United States (FB_915)
+         * sub band 0 will allow the radio to use all 64 channels
+         * sub band 1 - 8 will allow the radio to use the 8 channels in that sub band
+         * for use with Conduit gateway and MTAC_LORA, use sub bands 1 - 8, not sub band 0
+         * @param band the sub band to use (0 - 8)
+         * @returns MDOT_OK if success
+         */
+        int32_t setFrequencySubBand(const uint8_t& band);
+
+        /**
+         * Get frequency sub band
+         * @returns frequency sub band currently in use
+         */
+        uint8_t getFrequencySubBand();
+
+        /**
+         * Get frequency band
+         * @returns frequency band (channel plan) currently in use
+         */
+        uint8_t getFrequencyBand();
+
+        /**
+         * Get channel plan name
+         * @returns name of channel plan currently in use
+         */
+        std::string getChannelPlanName();
+
+        /**
+         * Get the datarate currently in use within the MAC layer
+         * returns 0-15
+         */
+        uint8_t getSessionDataRate();
+
+
+        /**
+         * Get the current max EIRP used in the channel plan
+         * May be changed by the network server
+         * returns 0-36
+         */
+        uint8_t getSessionMaxEIRP();
+
+        /**
+         * Set the current max EIRP used in the channel plan
+         * May be changed by the network server
+         * accepts 0-36
+         */
+        void setSessionMaxEIRP(uint8_t max);
+
+        /**
+         * Get the current downlink dwell time used in the channel plan
+         * May be changed by the network server
+         * returns 0-1
+         */
+        uint8_t getSessionDownlinkDwelltime();
+
+        /**
+         * Set the current downlink dwell time used in the channel plan
+         * May be changed by the network server
+         * accepts 0-1
+         */
+        void setSessionDownlinkDwelltime(uint8_t dwell);
+
+        /**
+         * Get the current uplink dwell time used in the channel plan
+         * May be changed by the network server
+         * returns 0-1
+         */
+        uint8_t getSessionUplinkDwelltime();
+
+        /**
+         * Set the current uplink dwell time used in the channel plan
+         * May be changed by the network server
+         * accepts 0-1
+         */
+        void setSessionUplinkDwelltime(uint8_t dwell);
+
+        /**
+         * Set the current downlink dwell time used in the channel plan
+         * May be changed by the network server
+         * accepts 0-1
+         */
+        uint32_t getListenBeforeTalkTime(uint8_t ms);
+
+        /**
+         * Set the current downlink dwell time used in the channel plan
+         * May be changed by the network server
+         * accepts 0-1
+         */
+        void setListenBeforeTalkTime(uint32_t ms);
+
+        /**
+         * Set public network mode
+         * 0:PRIVATE_MTS, 1:PUBLIC_LORAWAN, 2:PRIVATE_LORAWAN
+         * PRIVATE_MTS - Sync Word 0x12, US/AU Downlink frequencies per Frequency Sub Band
+         * PUBLIC_LORAWAN - Sync Word 0x34
+         * PRIVATE_LORAWAN - Sync Word 0x12
+         *
+         * The default Join Delay is 5 seconds
+         * The default Join Delay for PRIVATE_MTS was 1 second in the previous release
+         * The Join Delay must be changed independently of Public Network setting
+         *
+         * @see lora::NetworkType
+         * @returns MDOT_OK if success
+         */
+        int32_t setPublicNetwork(const uint8_t& val);
+
+        /**
+         * Get public network mode
+         *
+         * The default Join Delay is 5 seconds
+         * The default Join Delay for PRIVATE_MTS was 1 second in the previous release
+         * The Join Delay must be changed independently of Public Network setting
+         *
+         * @see lora:NetworkType
+         * @returns 0:PRIVATE_MTS, 1:PUBLIC_LORAWAN, 2:PRIVATE_LORAWAN
+         */
+        uint8_t getPublicNetwork();
+
+        /**
+         * Get the device ID
+         * @returns vector containing the device ID (size 8)
+         */
+        std::vector<uint8_t> getDeviceId();
+
+        /**
+         * Get the device port to be used for lora application data (1-223)
+         *  @returns port
+         */
+        uint8_t getAppPort();
+
+        /**
+         * Set the device port to be used for lora application data (1-223)
+         *  @returns MDOT_OK if success
+         */
+        int32_t setAppPort(uint8_t port);
+
+        /**
+         * Set the device class A, B or C
+         *  @returns MDOT_OK if success
+         */
+        int32_t setClass(std::string newClass);
+
+        /**
+         * Get the device class A, B or C
+         *  @returns MDOT_OK if success
+         */
+        std::string getClass();
+
+        /**
+         * Get the max packet length with current settings
+         * @returns max packet length
+         */
+        uint8_t getMaxPacketLength();
+
+        /**
+         * Set network address
+         * for use with MANUAL network join mode, will be assigned in OTA & AUTO_OTA modes
+         * @param addr a vector of 4 bytes
+         * @returns MDOT_OK if success
+         */
+        int32_t setNetworkAddress(const std::vector<uint8_t>& addr);
+
+        /**
+         * Get network address
+         * @returns vector containing network address (size 4)
+         */
+        std::vector<uint8_t> getNetworkAddress();
+
+        /**
+         * Set network session key
+         * for use with MANUAL network join mode, will be assigned in OTA & AUTO_OTA modes
+         * @param key a vector of 16 bytes
+         * @returns MDOT_OK if success
+         */
+        int32_t setNetworkSessionKey(const std::vector<uint8_t>& key);
+
+        /**
+         * Get network session key
+         * @returns vector containing network session key (size 16)
+         */
+        std::vector<uint8_t> getNetworkSessionKey();
+
+        /**
+         * Set data session key
+         * for use with MANUAL network join mode, will be assigned in OTA & AUTO_OTA modes
+         * @param key a vector of 16 bytes
+         * @returns MDOT_OK if success
+         */
+        int32_t setDataSessionKey(const std::vector<uint8_t>& key);
+
+        /**
+         * Get data session key
+         * @returns vector containing data session key (size 16)
+         */
+        std::vector<uint8_t> getDataSessionKey();
+
+        /**
+         * Set network name
+         * for use with OTA & AUTO_OTA network join modes
+         * generates network ID (crc64 of name) automatically
+         * @param name a string of of at least 8 bytes and no more than 128 bytes
+         * @return MDOT_OK if success
+         */
+        int32_t setNetworkName(const std::string& name);
+
+        /**
+         * Get network name
+         * @return string containing network name (size 8 to 128)
+         */
+        std::string getNetworkName();
+
+        /**
+         * Set network ID
+         * for use with OTA & AUTO_OTA network join modes
+         * setting network ID via this function sets network name to empty
+         * @param id a vector of 8 bytes
+         * @returns MDOT_OK if success
+         */
+        int32_t setNetworkId(const std::vector<uint8_t>& id);
+
+        /**
+         * Get network ID
+         * @returns vector containing network ID (size 8)
+         */
+        std::vector<uint8_t> getNetworkId();
+
+        /**
+         * Set network passphrase
+         * for use with OTA & AUTO_OTA network join modes
+         * generates network key (cmac of passphrase) automatically
+         * @param name a string of of at least 8 bytes and no more than 128 bytes
+         * @return MDOT_OK if success
+         */
+        int32_t setNetworkPassphrase(const std::string& passphrase);
+
+        /**
+         * Get network passphrase
+         * @return string containing network passphrase (size 8 to 128)
+         */
+        std::string getNetworkPassphrase();
+
+        /**
+         * Set network key
+         * for use with OTA & AUTO_OTA network join modes
+         * setting network key via this function sets network passphrase to empty
+         * @param id a vector of 16 bytes
+         * @returns MDOT_OK if success
+         */
+        int32_t setNetworkKey(const std::vector<uint8_t>& id);
+
+        /**
+         * Get network key
+         * @returns a vector containing network key (size 16)
+         */
+        std::vector<uint8_t> getNetworkKey();
+
+        /**
+         * Set lorawan application EUI
+         * equivalent to setNetworkId
+         * @param eui application EUI (size 8)
+         */
+        int32_t setAppEUI(const uint8_t* eui);
+
+        /**
+         * Get lorawan application EUI
+         * equivalent to getNetworkId
+         * @returns vector containing application EUI (size 8)
+         */
+        const uint8_t* getAppEUI();
+
+        /**
+         * Set lorawan application key
+         * equivalent to setNetworkKey
+         * @param eui application key (size 16)
+         */
+        int32_t setAppKey(const uint8_t* key);
+
+        /**
+         * Set lorawan application key
+         * equivalent to getNetworkKey
+         * @returns eui application key (size 16)
+         */
+        const uint8_t* getAppKey();
+
+        /**
+         * Add a multicast session address and keys
+         * Downlink counter is set to 0
+         * Up to 3 MULTICAST_SESSIONS can be set
+         */
+        int32_t setMulticastSession(uint8_t index, uint32_t addr, const uint8_t* nsk, const uint8_t* dsk);
+
+        /**
+         * Set a multicast session counter
+         * Up to 3 MULTICAST_SESSIONS can be set
+         */
+        int32_t setMulticastDownlinkCounter(uint8_t index, uint32_t count);
+
+        /**
+         * Set join byte order
+         * @param order 0:LSB 1:MSB
+         */
+        uint32_t setJoinByteOrder(uint8_t order);
+
+        /**
+         * Get join byte order
+         * @returns byte order to use in joins 0:LSB 1:MSB
+         */
+        uint8_t getJoinByteOrder();
+
+        /**
+         * Attempt to join network
+         * each attempt will be made with a random datarate up to the configured datarate
+         * JoinRequest backoff between tries is enforced to 1% for 1st hour, 0.1% for 1-10 hours and 0.01% after 10 hours
+         * Check getNextTxMs() for time until next join attempt can be made
+         * @returns MDOT_OK if success
+         */
+        int32_t joinNetwork();
+
+        /**
+         * Attempts to join network once
+         * @returns MDOT_OK if success
+         */
+        int32_t joinNetworkOnce();
+
+        /**
+         * Resets current network session, essentially disconnecting from the network
+         * has no effect for MANUAL network join mode
+         */
+        void resetNetworkSession();
+
+        /**
+         * Restore saved network session from flash
+         * has no effect for MANUAL network join mode
+         */
+        void restoreNetworkSession();
+
+        /**
+         * Save current network session to flash
+         * has no effect for MANUAL network join mode
+         */
+        void saveNetworkSession();
+
+        /**
+         * Set number of times joining will retry each sub-band before changing
+         * to the next subband in US915 and AU915
+         * @param retries must be between 0 - 255
+         * @returns MDOT_OK if success
+         */
+        int32_t setJoinRetries(const uint8_t& retries);
+
+        /**
+         * Get number of times joining will retry each sub-band
+         * @returns join retries (0 - 255)
+         */
+        uint8_t getJoinRetries();
+
+        /**
+         * Set network join mode
+         * MANUAL: set network address and session keys manually
+         * OTA: User sets network name and passphrase, then attempts to join
+         * AUTO_OTA: same as OTA, but network sessions can be saved and restored
+         * @param mode MANUAL, OTA, or AUTO_OTA
+         * @returns MDOT_OK if success
+         */
+        int32_t setJoinMode(const uint8_t& mode);
+
+        /**
+         * Get network join mode
+         * @returns MANUAL, OTA, or AUTO_OTA
+         */
+        uint8_t getJoinMode();
+
+        /**
+         * Get network join status
+         * @returns true if currently joined to network
+         */
+        bool getNetworkJoinStatus();
+
+        /**
+         * Do a network link check
+         * application data may be returned in response to a network link check command
+         * @returns link_check structure containing success, dBm above noise floor, gateways in range, and packet payload
+         */
+        link_check networkLinkCheck();
+
+        /**
+         * Set network link check count to perform automatic link checks every count packets
+         * only applicable if ACKs are disabled
+         * @param count must be between 0 - 255
+         * @returns MDOT_OK if success
+         */
+        int32_t setLinkCheckCount(const uint8_t& count);
+
+        /**
+         * Get network link check count
+         * @returns count (0 - 255)
+         */
+        uint8_t getLinkCheckCount();
+
+        /**
+         * Set network link check threshold, number of link check failures or missed acks to tolerate
+         * before considering network connection lost
+         * @pararm count must be between 0 - 255
+         * @returns MDOT_OK if success
+         */
+        int32_t setLinkCheckThreshold(const uint8_t& count);
+
+        /**
+         * Get network link check threshold
+         * @returns threshold (0 - 255)
+         */
+        uint8_t getLinkCheckThreshold();
+
+        /**
+         * Get/set number of failed link checks in the current session
+         * @returns count (0 - 255)
+         */
+        uint8_t getLinkFailCount();
+        int32_t setLinkFailCount(uint8_t count);
+
+        /**
+         * Set UpLinkCounter number of packets sent to the gateway during this network session (sequence number)
+         * @returns MDOT_OK
+         */
+        int32_t setUpLinkCounter(uint32_t count);
+
+        /**
+         * Get UpLinkCounter
+         * @returns number of packets sent to the gateway during this network session (sequence number)
+         */
+        uint32_t getUpLinkCounter();
+
+        /**
+         * Set UpLinkCounter number of packets sent by the gateway during this network session (sequence number)
+         * @returns MDOT_OK
+         */
+        int32_t setDownLinkCounter(uint32_t count);
+
+        /**
+         * Get DownLinkCounter
+         * @returns number of packets sent by the gateway during this network session (sequence number)
+         */
+        uint32_t getDownLinkCounter();
+
+        /**
+         * Enable/disable AES encryption
+         * AES encryption must be enabled for use with Conduit gateway and MTAC_LORA card
+         * @param on true for AES encryption to be enabled
+         * @returns MDOT_OK if success
+         */
+        int32_t setAesEncryption(const bool& on);
+
+        /**
+         * Get AES encryption
+         * @returns true if AES encryption is enabled
+         */
+        bool getAesEncryption();
+
+        /**
+         * Get RSSI stats
+         * @returns rssi_stats struct containing last, min, max, and avg RSSI in dB
+         */
+        rssi_stats getRssiStats();
+
+        /**
+         * Get SNR stats
+         * @returns snr_stats struct containing last, min, max, and avg SNR in cB
+         */
+        snr_stats getSnrStats();
+
+        /**
+         * Get ms until next free channel
+         * only applicable for European models, US models return 0
+         * @returns time (ms) until a channel is free to use for transmitting
+         */
+        uint32_t getNextTxMs();
+
+        /**
+         * Get join delay in seconds
+         *  Defaults to 5 seconds
+         *  Must match join delay setting of the network server
+         *
+         * The default Join Delay is 5 seconds
+         * The default Join Delay for PRIVATE_MTS was 1 second in the previous release
+         *
+         *  @returns number of seconds before join accept message is expected
+         */
+        uint8_t getJoinDelay();
+
+        /**
+         * Set join delay in seconds
+         *  Defaults to 5 seconds
+         *  Must match join delay setting of the network server
+         *
+         * The default Join Delay is 5 seconds
+         * The default Join Delay for PRIVATE_MTS was 1 second in the previous release
+         *
+         *  @param delay number of seconds before join accept message is expected
+         *  @return MDOT_OK if success
+         */
+        uint32_t setJoinDelay(uint8_t delay);
+
+        /**
+         * Get join Rx1 datarate offset
+         *  defaults to 0
+         *  @returns offset
+         */
+        uint8_t getJoinRx1DataRateOffset();
+
+        /**
+         * Set join Rx1 datarate offset
+         *  @param offset for datarate
+         *  @return MDOT_OK if success
+         */
+        uint32_t setJoinRx1DataRateOffset(uint8_t offset);
+
+        /**
+         * Get join Rx2 datarate
+         *  defaults to US:DR8, AU:DR8, EU:DR0
+         *  @returns datarate
+         */
+        uint8_t getJoinRx2DataRate();
+
+        /**
+         * Set join Rx2 datarate
+         *  @param datarate
+         *  @return MDOT_OK if success
+         */
+        uint32_t setJoinRx2DataRate(uint8_t datarate);
+
+        /**
+         * Get join Rx2 frequency
+         *  defaults US:923.3, AU:923.3, EU:869.525
+         *  @returns frequency
+         */
+        uint32_t getJoinRx2Frequency();
+
+        /**
+         * Set join Rx2 frequency
+         *  @param frequency
+         *  @return MDOT_OK if success
+         */
+        uint32_t setJoinRx2Frequency(uint32_t frequency);
+
+        /**
+         * Get rx delay in seconds
+         *  Defaults to 1 second
+         *  @returns number of seconds before response message is expected
+         */
+        uint8_t getRxDelay();
+
+        /**
+         * Set rx delay in seconds
+         *  Defaults to 1 second
+         *  @param delay number of seconds before response message is expected
+         *  @return MDOT_OK if success
+         */
+        uint32_t setRxDelay(uint8_t delay);
+
+        /**
+         * Get  preserve session to save network session info through reset or power down in AUTO_OTA mode
+         *  Defaults to off
+         *  @returns true if enabled
+         */
+        bool getPreserveSession();
+
+        /**
+         * Set preserve session to save network session info through reset or power down in AUTO_OTA mode
+         *  Defaults to off
+         *  @param enable
+         *  @return MDOT_OK if success
+         */
+        uint32_t setPreserveSession(bool enable);
+
+        /**
+         * Get data pending
+         * only valid after sending data to the gateway
+         * @returns true if server has available packet(s)
+         */
+        bool getDataPending();
+
+        /**
+         * Get ack requested
+         * only valid after sending data to the gateway
+         * @returns true if server has requested ack
+         */
+        bool getAckRequested();
+
+        /**
+         * Get is transmitting indicator
+         * @returns true if currently transmitting
+         */
+        bool getIsTransmitting();
+
+        /**
+         * Get is idle indicator
+         * @returns true if not currently transmitting, waiting or receiving
+         */
+        bool getIsIdle();
+
+        /**
+         * Set TX data rate
+         * data rates affect maximum payload size
+         * @param dr DR0-DR7 for Europe, DR0-DR4 for United States
+         * @returns MDOT_OK if success
+         */
+        int32_t setTxDataRate(const uint8_t& dr);
+
+        /**
+         * Get TX data rate
+         * @returns current TX data rate (DR0-DR15)
+         */
+        uint8_t getTxDataRate();
+
+        /**
+         * Get a random value from the radio based on RSSI
+         *  @returns randome value
+         */
+        uint32_t getRadioRandom();
+
+        /**
+         * Get data rate spreading factor and bandwidth
+         * EU868 Datarates
+         * ---------------
+         * DR0 - SF12BW125
+         * DR1 - SF11BW125
+         * DR2 - SF10BW125
+         * DR3 - SF9BW125
+         * DR4 - SF8BW125
+         * DR5 - SF7BW125
+         * DR6 - SF7BW250
+         * DR7 - FSK
+         *
+         * US915 Datarates
+         * ---------------
+         * DR0 - SF10BW125
+         * DR1 - SF9BW125
+         * DR2 - SF8BW125
+         * DR3 - SF7BW125
+         * DR4 - SF8BW500
+         *
+         * AU915 Datarates
+         * ---------------
+         * DR0 - SF10BW125
+         * DR1 - SF9BW125
+         * DR2 - SF8BW125
+         * DR3 - SF7BW125
+         * DR4 - SF8BW500
+         *
+         * @returns spreading factor and bandwidth
+         */
+        std::string getDataRateDetails(uint8_t rate);
+        std::string getDateRateDetails(uint8_t rate);
+
+
+        /**
+         * Set TX power output of radio before antenna gain, default: 14 dBm
+         * actual output power may be limited by local regulations for the chosen frequency
+         * power affects maximum range
+         * @param power 2 dBm - 20 dBm
+         * @returns MDOT_OK if success
+         */
+        int32_t setTxPower(const uint32_t& power);
+
+        /**
+         * Get TX power
+         * @returns TX power (2 dBm - 20 dBm)
+         */
+        uint32_t getTxPower();
+
+        /**
+         * Get configured gain of installed antenna, default: +3 dBi
+         * @returns gain of antenna in dBi
+         */
+        int8_t getAntennaGain();
+
+        /**
+         * Set configured gain of installed antenna, default: +3 dBi
+         * @param gain -127 dBi - 128 dBi
+         * @returns MDOT_OK if success
+         */
+        int32_t setAntennaGain(int8_t gain);
+
+        /**
+         * Enable/disable TX waiting for rx windows
+         * when enabled, send calls will block until a packet is received or RX timeout
+         * @param enable set to true if expecting responses to transmitted packets
+         * @returns MDOT_OK if success
+         */
+        int32_t setTxWait(const bool& enable);
+
+        /**
+         * Get TX wait
+         * @returns true if TX wait is enabled
+         */
+        bool getTxWait();
+
+        /**
+         * Cancel pending rx windows
+         */
+        void cancelRxWindow();
+
+        /**
+         * Get time on air
+         * @returns the amount of time (in ms) it would take to send bytes bytes based on current configuration
+         */
+        uint32_t getTimeOnAir(uint8_t bytes);
+
+        /**
+         * Get min frequency
+         * @returns minimum frequency based on current channel plan
+         */
+        uint32_t getMinFrequency();
+
+        /**
+         * Get max frequency
+         * @returns maximum frequency based on current channel plan
+         */
+        uint32_t getMaxFrequency();
+
+        /**
+         * Get min datarate
+         * @returns minimum datarate based on current channel plan
+         */
+        uint8_t getMinDatarate();
+
+        /**
+         * Get max datarate
+         * @returns maximum datarate based on current channel plan
+         */
+        uint8_t getMaxDatarate();
+
+        /**
+         * Get min datarate offset
+         * @returns minimum datarate offset based on current channel plan
+         */
+        uint8_t getMinDatarateOffset();
+
+        /**
+         * Get max datarate offset
+         * @returns maximum datarate based on current channel plan
+         */
+        uint8_t getMaxDatarateOffset();
+
+        /**
+         * Get min datarate
+         * @returns minimum datarate based on current channel plan
+         */
+        uint8_t getMinRx2Datarate();
+
+        /**
+         * Get max rx2 datarate
+         * @returns maximum rx2 datarate based on current channel plan
+         */
+        uint8_t getMaxRx2Datarate();
+
+        /**
+         * Get max tx power
+         * @returns maximum tx power based on current channel plan
+         */
+        uint8_t getMaxTxPower();
+
+        /**
+         * Get min tx power
+         * @returns minimum tx power based on current channel plan
+         */
+        uint8_t getMinTxPower();
+
+        /**
+         *
+         * get/set adaptive data rate
+         * configure data rates and power levels based on signal to noise of packets received at gateway
+         * true == adaptive data rate is on
+         * set function returns MDOT_OK if success
+         */
+        int32_t setAdr(const bool& on);
+        bool getAdr();
+
+        /**
+         * Set forward error correction bytes
+         * @param bytes 1 - 4 bytes
+         * @returns MDOT_OK if success
+         */
+        int32_t setFec(const uint8_t& bytes);
+
+        /**
+         * Get forward error correction bytes
+         * @returns bytes (1 - 4)
+         */
+        uint8_t getFec();
+
+        /**
+         * Enable/disable CRC checking of packets
+         * CRC checking must be enabled for use with Conduit gateway and MTAC_LORA card
+         * @param on set to true to enable CRC checking
+         * @returns MDOT_OK if success
+         */
+        int32_t setCrc(const bool& on);
+
+        /**
+         * Get CRC checking
+         * @returns true if CRC checking is enabled
+         */
+        bool getCrc();
+
+        /**
+         * Set ack
+         * @param retries 0 to disable acks, otherwise 1 - 8
+         * @returns MDOT_OK if success
+         */
+        int32_t setAck(const uint8_t& retries);
+
+        /**
+         * Get ack
+         * @returns 0 if acks are disabled, otherwise retries (1 - 8)
+         */
+        uint8_t getAck();
+
+        /**
+         * Set number of packet repeats for unconfirmed frames
+         * @param repeat 0 or 1 for no repeats, otherwise 2-15
+         * @returns MDOT_OK if success
+         */
+        int32_t setRepeat(const uint8_t& repeat);
+
+        /**
+         * Get number of packet repeats for unconfirmed frames
+         * @returns 0 or 1 if no repeats, otherwise 2-15
+         */
+        uint8_t getRepeat();
+
+        /**
+         * Send data to the gateway
+         * validates data size (based on spreading factor)
+         * @param data a vector of up to 242 bytes (may be less based on spreading factor)
+         * @returns MDOT_OK if packet was sent successfully (ACKs disabled), or if an ACK was received (ACKs enabled)
+         */
+        int32_t send(const std::vector<uint8_t>& data, const bool& blocking = true, const bool& highBw = false);
+
+        /**
+         * Inject mac command
+         * @param data a vector containing mac commands
+         * @returns MDOT_OK
+         */
+        int32_t injectMacCommand(const std::vector<uint8_t>& data);
+
+        /**
+         * Clear MAC command buffer to be sent in next uplink
+         * @returns MDOT_OK
+         */
+        int32_t clearMacCommands();
+
+        /**
+         * Get MAC command buffer to be sent in next uplink
+         * @returns command bytes
+         */
+        std::vector<uint8_t> getMacCommands();
+
+        /**
+         * Fetch data received from the gateway
+         * this function only checks to see if a packet has been received - it does not open a receive window
+         * send() must be called before recv()
+         * @param data a vector to put the received data into
+         * @returns MDOT_OK if packet was successfully received
+         */
+        int32_t recv(std::vector<uint8_t>& data);
+
+        /**
+         * Ping
+         * status will be MDOT_OK if ping succeeded
+         * @returns ping_response struct containing status, RSSI, and SNR
+         */
+        ping_response ping();
+
+        /**
+         * Get return code string
+         * @returns string containing a description of the given error code
+         */
+        static std::string getReturnCodeString(const int32_t& code);
+
+        /**
+         * Get last error
+         * @returns string explaining the last error that occured
+         */
+        std::string getLastError();
+
+        /**
+         * Go to sleep
+         * @param interval the number of seconds to sleep before waking up if wakeup_mode == RTC_ALARM or RTC_ALARM_OR_INTERRUPT, else ignored
+         * @param wakeup_mode RTC_ALARM, INTERRUPT, RTC_ALARM_OR_INTERRUPT
+         *      if RTC_ALARM the real time clock is configured to wake the device up after the specified interval
+         *      if INTERRUPT the device will wake up on the rising edge of the interrupt pin
+         *      if RTC_ALARM_OR_INTERRUPT the device will wake on the first event to occur
+         * @param deepsleep if true go into deep sleep mode (lowest power, all memory and registers are lost, peripherals turned off)
+         *                  else go into sleep mode (low power, memory and registers are maintained, peripherals stay on)
+         *
+         * For the MDOT
+         *      in sleep mode, the device can be woken up on an XBEE_DI (2-8) pin or by the RTC alarm
+         *      in deepsleep mode, the device can only be woken up using the WKUP pin (PA0, XBEE_DIO7) or by the RTC alarm
+         * For the XDOT
+         *      in sleep mode, the device can be woken up on GPIO (0-3), UART1_RX, WAKE or by the RTC alarm
+         *      in deepsleep mode, the device can only be woken up using the WKUP pin (PA0, WAKE) or by the RTC alarm
+         * @returns MDOT_OK on success
+         */
+        int32_t sleep(const uint32_t& interval, const uint8_t& wakeup_mode = RTC_ALARM, const bool& deepsleep = true);
+
+        /**
+         * Set auto sleep mode
+         * Auto sleep mode will automatically put the MCU to sleep after tx and in between receive windows
+         * Note: The MCU will go into a stop mode sleep in between rx windows.  This means that
+         *       peripherals such as timers will not function during the sleep intervals.
+         * @param enable - Flag to enable auto sleep mode
+         */
+        void setAutoSleep(bool enable);
+
+        /**
+         * Get auto sleep mode
+         * @returns 0 if sleep mode is disabled, 1 if it is enabled
+         */
+        uint8_t getAutoSleep();
+
+        /**
+         * Set wake pin
+         * @param pin the pin to use to wake the device from sleep mode
+         *      For MDOT, XBEE_DI (2-8)
+         *      For XDOT, GPIO (0-3), UART1_RX, or WAKE
+         */
+        void setWakePin(const PinName& pin);
+
+        /**
+         * Get wake pin
+         * @returns the pin to use to wake the device from sleep mode
+         *      For MDOT, XBEE_DI (2-8)
+         *      For XDOT, GPIO (0-3), UART1_RX, or WAKE
+         */
+        PinName getWakePin();
+
+        /**
+         * Write data in a user backup register
+         * @param register one of UBR0 through UBR9 for MDOT, one of UBR0 through UBR21 for XDOT
+         * @param data user data to back up
+         * @returns true if success
+         */
+        bool writeUserBackupRegister(uint32_t reg, uint32_t data);
+
+        /**
+         * Read data in a user backup register
+         * @param register one of UBR0 through UBR9 for MDOT, one of UBR0 through UBR21 for XDOT
+         * @param data gets set to content of register
+         * @returns true if success
+         */
+        bool readUserBackupRegister(uint32_t reg, uint32_t& data);
+
+        /**
+         * Set LBT time in us
+         * @param ms time in us
+         * @returns true if success
+         */
+        bool setLbtTimeUs(uint16_t us);
+
+        /**
+         * Get LBT time in us
+         * @returns LBT time in us
+         */
+        uint16_t getLbtTimeUs();
+
+        /**
+         * Set LBT threshold in dBm
+         * @param rssi threshold in dBm
+         * @returns true if success
+         */
+        bool setLbtThreshold(int8_t rssi);
+
+        /**
+         * Get LBT threshold in dBm
+         * @returns LBT threshold in dBm
+         */
+        int8_t getLbtThreshold();
+
+#if defined(TARGET_MTS_MDOT_F411RE)
+        ///////////////////////////////////////////////////////////////////
+        // Filesystem (Non Volatile Memory) Operation Functions for mDot //
+        ///////////////////////////////////////////////////////////////////
+
+        // Save user file data to flash
+        // file - name of file max 30 chars
+        // data - data of file
+        // size - size of file
+        // returns true if successful
+        bool saveUserFile(const char* file, void* data, uint32_t size);
+
+        // Append user file data to flash
+        // file - name of file max 30 chars
+        // data - data of file
+        // size - size of file
+        // returns true if successful
+        bool appendUserFile(const char* file, void* data, uint32_t size);
+
+        // Read user file data from flash
+        // file - name of file max 30 chars
+        // data - data of file
+        // size - size of file
+        // returns true if successful
+        bool readUserFile(const char* file, void* data, uint32_t size);
+
+        // Move a user file in flash
+        // file     - name of file
+        // new_name - new name of file
+        // returns true if successful
+        bool moveUserFile(const char* file, const char* new_name);
+
+        // Delete user file data from flash
+        // file - name of file max 30 chars
+        // returns true if successful
+        bool deleteUserFile(const char* file);
+
+        // Open user file in flash, max of 4 files open concurrently
+        // file - name of file max 30 chars
+        // mode - combination of FM_APPEND | FM_TRUNC | FM_CREAT |
+        //                       FM_RDONLY | FM_WRONLY | FM_RDWR | FM_DIRECT
+        // returns - mdot_file struct, fd field will be a negative value if file could not be opened
+        mDot::mdot_file openUserFile(const char* file, int mode);
+
+        // Seek an open file
+        // file - mdot file struct
+        // offset - offset in bytes
+        // whence - where offset is based SEEK_SET, SEEK_CUR, SEEK_END
+        // returns true if successful
+        bool seekUserFile(mDot::mdot_file& file, size_t offset, int whence);
+
+        // Read bytes from open file
+        // file - mdot file struct
+        // data - mem location to store data
+        // length - number of bytes to read
+        // returns - number of bytes read, negative if error
+        int readUserFile(mDot::mdot_file& file, void* data, size_t length);
+
+        // Write bytes to open file
+        // file - mdot file struct
+        // data - data to write
+        // length - number of bytes to write
+        // returns - number of bytes written, negative if error
+        int writeUserFile(mDot::mdot_file& file, void* data, size_t length);
+
+        // Close open file
+        // file - mdot file struct
+        // returns true if successful
+        bool closeUserFile(mDot::mdot_file& file);
+
+        // List user files stored in flash
+        std::vector<mDot::mdot_file> listUserFiles();
+
+        // Move file into the firmware upgrade path to be flashed on next boot
+        // file - name of file
+        // returns true if successful
+        bool moveUserFileToFirmwareUpgrade(const char* file);
+#else
+        ///////////////////////////////////////////////////////////////
+        // EEPROM (Non Volatile Memory) Operation Functions for xDot //
+        ///////////////////////////////////////////////////////////////
+        
+        // Write to EEPROM
+        // addr - address to write to (0 - 0x17FF)
+        // data - data to write
+        // size - size of data
+        // returns true if successful
+        bool nvmWrite(uint16_t addr, void* data, uint16_t size);
+
+        // Read from EEPROM
+        // addr - address to read from (0 - 0x17FF)
+        // data - buffer for data
+        // size - size of buffer
+        // returns true if successful
+        bool nvmRead(uint16_t addr, void* data, uint16_t size);
+#endif /* TARGET_MTS_MDOT_F411RE */
+
+        // get current statistics
+        // Join Attempts, Join Fails, Up Packets, Down Packets, Missed Acks
+        mdot_stats getStats();
+
+        // reset statistics
+        // Join Attempts, Join Fails, Up Packets, Down Packets, Missed Acks
+        void resetStats();
+
+        // Convert pin number 2-8 to pin name DIO2-DI8
+        static PinName pinNum2Name(uint8_t num);
+
+        // Convert pin name DIO2-DI8 to pin number 2-8
+        static uint8_t pinName2Num(PinName name);
+
+        // Convert pin name DIO2-DI8 to string
+        static std::string pinName2Str(PinName name);
+
+        uint64_t crc64(uint64_t crc, const unsigned char *s, uint64_t l);
+
+        /*************************************************************************
+         * The following functions are only used by the AT command application and
+         * should not be used by standard applications consuming the mDot library
+         ************************************************************************/
+
+        // set/get configured baud rate for command port
+        // only for use in conjunction with AT interface
+        // set function returns MDOT_OK if success
+        int32_t setBaud(const uint32_t& baud);
+        uint32_t getBaud();
+
+        // set/get baud rate for debug port
+        // set function returns MDOT_OK if success
+        int32_t setDebugBaud(const uint32_t& baud);
+        uint32_t getDebugBaud();
+
+        // set/get command terminal echo
+        // set function returns MDOT_OK if success
+        int32_t setEcho(const bool& on);
+        bool getEcho();
+
+        // set/get command terminal verbose mode
+        // set function returns MDOT_OK if success
+        int32_t setVerbose(const bool& on);
+        bool getVerbose();
+
+        // set/get startup mode
+        // COMMAND_MODE (default), starts up ready to accept AT commands
+        // SERIAL_MODE, read serial data and send it as LoRa packets
+        // set function returns MDOT_OK if success
+        int32_t setStartUpMode(const uint8_t& mode);
+        uint8_t getStartUpMode();
+
+        int32_t setRxDataRate(const uint8_t& dr);
+        uint8_t getRxDataRate();
+
+        // get/set TX/RX frequency
+        // if frequency band == FB_868 (Europe), must be between 863000000 - 870000000
+        // if frequency band == FB_915 (United States), must be between 902000000-928000000
+        // if set to 0, device will hop frequencies
+        // set function returns MDOT_OK if success
+        int32_t setTxFrequency(const uint32_t& freq);
+        uint32_t getTxFrequency();
+        int32_t setRxFrequency(const uint32_t& freq);
+        uint32_t getRxFrequency();
+
+        // get/set TX/RX inverted
+        // true == signal is inverted
+        // set function returns MDOT_OK if success
+        int32_t setTxInverted(const bool& on);
+        bool getTxInverted();
+        int32_t setRxInverted(const bool& on);
+        bool getRxInverted();
+
+        // get/set RX output mode
+        // valid options are HEXADECIMAL and BINARY
+        // set function returns MDOT_OK if success
+        int32_t setRxOutput(const uint8_t& mode);
+        uint8_t getRxOutput();
+
+        // get/set serial wake interval
+        // valid values are 2 s - INT_MAX (2147483647) s
+        // set function returns MDOT_OK if success
+        int32_t setWakeInterval(const uint32_t& interval);
+        uint32_t getWakeInterval();
+
+        // get/set serial wake delay
+        // valid values are 2 ms - INT_MAX (2147483647) ms
+        // set function returns MDOT_OK if success
+        int32_t setWakeDelay(const uint32_t& delay);
+        uint32_t getWakeDelay();
+
+        // get/set serial receive timeout
+        // valid values are 0 ms - 65000 ms
+        // set function returns MDOT_OK if success
+        int32_t setWakeTimeout(const uint16_t& timeout);
+        uint16_t getWakeTimeout();
+
+        // get/set serial wake mode
+        // valid values are INTERRUPT or RTC_ALARM
+        // set function returns MDOT_OK if success
+        int32_t setWakeMode(const uint8_t& delay);
+        uint8_t getWakeMode();
+
+        // get/set serial flow control enabled
+        // set function returns MDOT_OK if success
+        int32_t setFlowControl(const bool& on);
+        bool getFlowControl();
+
+        // get/set serial clear on error
+        // if enabled the data read from the serial port will be discarded if it cannot be sent or if the send fails
+        // set function returns MDOT_OK if success
+        int32_t setSerialClearOnError(const bool& on);
+        bool getSerialClearOnError();
+
+        // MTS_RADIO_DEBUG_COMMANDS
+
+        /**
+         * Disable Duty cycle
+         * enables or disables the duty cycle limitations
+         * **** ONLY TO BE USED FOR TESTINGS PURPOSES ****
+         * **** ALL DEPLOYABLE CODE MUST ADHERE TO LOCAL REGULATIONS ****
+         * **** THIS SETTING WILL NOT BE SAVED TO CONFIGURATION *****
+         * @param val true to disable duty-cycle (default:false)
+         */
+        int32_t setDisableDutyCycle(bool val);
+
+        /**
+         * Disable Duty cycle
+         * **** ONLY TO BE USED FOR TESTINGS PURPOSES ****
+         * **** ALL DEPLOYABLE CODE MUST ADHERE TO LOCAL REGULATIONS ****
+         * **** THIS SETTING WILL NOT BE SAVED TO CONFIGURATION *****
+         * @return true if duty-cycle is disabled (default:false)
+         */
+        uint8_t getDisableDutyCycle();
+
+        /**
+         * LBT RSSI
+         * @return the current RSSI on the configured frequency (SetTxFrequency) using configured LBT Time
+         */
+        int16_t lbtRssi();
+
+        void openRxWindow(uint32_t timeout, uint8_t bandwidth = 0);
+        void closeRxWindow();
+        void sendContinuous(bool enable=true);
+        int32_t setDeviceId(const std::vector<uint8_t>& id);
+        int32_t setProtectedAppEUI(const std::vector<uint8_t>& appEUI);
+        int32_t setProtectedAppKey(const std::vector<uint8_t>& appKey);
+        int32_t setDefaultFrequencyBand(const uint8_t& band);
+        bool saveProtectedConfig();
+        // resets the radio/mac/link 
+        void resetRadio();
+        int32_t setRadioMode(const uint8_t& mode);
+        std::map<uint8_t, uint8_t> dumpRegisters();
+        void eraseFlash();
+
+        // deprecated - use setWakeInterval
+        int32_t setSerialWakeInterval(const uint32_t& interval);
+        // deprecated - use getWakeInterval
+        uint32_t getSerialWakeInterval();
+
+        // deprecated - use setWakeDelay
+        int32_t setSerialWakeDelay(const uint32_t& delay);
+        // deprecated - use setWakeDelay
+        uint32_t getSerialWakeDelay();
+
+        // deprecated - use setWakeTimeout
+        int32_t setSerialReceiveTimeout(const uint16_t& timeout);
+        // deprecated - use getWakeTimeout
+        uint16_t getSerialReceiveTimeout();
+
+        void setWakeupCallback(void (*function)(void));
+
+        template<typename T>
+        void setWakeupCallback(T *object, void (T::*member)(void)) {
+            _wakeup_callback.attach(object, member);
+        }
+        
+        lora::ChannelPlan* getChannelPlan(void);  
+
+        uint32_t setRx2DataRate(uint8_t dr);
+        uint8_t getRx2DataRate();
+
+        void mcGroupKeys(uint8_t *mcKeyEncrypt, uint32_t addr, uint8_t groupId, uint32_t frame_count);  
+    private:
+        typedef enum {
+            AUTO_SLEEP_EVT_CFG,
+            AUTO_SLEEP_EVT_TXDONE,
+            AUTO_SLEEP_EVT_RX1_TIMEOUT,
+            AUTO_SLEEP_EVT_CLEANUP
+        } AutoSleepEvent_t;
+
+        typedef enum {
+            USER_SLEEP,
+            AUTO_SLEEP
+        } SleepClient_t;
+
+        void sleep_ms(uint32_t interval,
+                      uint8_t wakeup_mode = RTC_ALARM,
+                      bool deepsleep = true,
+                      SleepClient_t sleep_client = USER_SLEEP);
+
+        void auto_sleep(AutoSleepEvent_t evt);
+
+        void wakeup(SleepClient_t sleep_client);
+
+        mdot_stats _stats;
+
+        FunctionPointer _wakeup_callback;
+
+        bool _standbyFlag;
+        bool _testMode;
+        uint8_t _savedPort;
+        void handleTestModePacket();
+        lora::ChannelPlan* _plan;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/mDotEvent.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,355 @@
+#ifndef MDOT_EVENT_H
+#define MDOT_EVENT_H
+
+#include "mbed.h"
+#include "mDot.h"
+#include "MacEvents.h"
+#include "MTSLog.h"
+#include "MTSText.h"
+
+typedef union {
+        uint8_t Value;
+        struct {
+                uint8_t :1;
+                uint8_t Tx :1;
+                uint8_t Rx :1;
+                uint8_t RxData :1;
+                uint8_t RxSlot :2;
+                uint8_t LinkCheck :1;
+                uint8_t JoinAccept :1;
+        } Bits;
+} LoRaMacEventFlags;
+
+typedef enum {
+    LORAMAC_EVENT_INFO_STATUS_OK = 0,
+    LORAMAC_EVENT_INFO_STATUS_ERROR,
+    LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT,
+    LORAMAC_EVENT_INFO_STATUS_RX_TIMEOUT,
+    LORAMAC_EVENT_INFO_STATUS_RX_ERROR,
+    LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL,
+    LORAMAC_EVENT_INFO_STATUS_DOWNLINK_FAIL,
+    LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL,
+    LORAMAC_EVENT_INFO_STATUS_MIC_FAIL,
+} LoRaMacEventInfoStatus;
+
+/*!
+ * LoRaMAC event information
+ */
+typedef struct {
+        LoRaMacEventInfoStatus Status;
+        lora::DownlinkControl Ctrl;
+        bool TxAckReceived;
+        bool DuplicateRx;
+        uint8_t TxNbRetries;
+        uint8_t TxDatarate;
+        uint8_t RxPort;
+        uint8_t *RxBuffer;
+        uint8_t RxBufferSize;
+        int16_t RxRssi;
+        uint8_t RxSnr;
+        uint16_t Energy;
+        uint8_t DemodMargin;
+        uint8_t NbGateways;
+} LoRaMacEventInfo;
+
+class mDotEvent: public lora::MacEvents {
+    public:
+
+        mDotEvent()
+        :
+          LinkCheckAnsReceived(false),
+          DemodMargin(0),
+          NbGateways(0),
+          PacketReceived(false),
+          RxPort(0),
+          RxPayloadSize(0),
+          PongReceived(false),
+          PongRssi(0),
+          PongSnr(0),
+          AckReceived(false),
+          DuplicateRx(false),
+          TxNbRetries(0),
+          _sleep_cb(NULL)
+        {
+            memset(&_flags, 0, sizeof(LoRaMacEventFlags));
+            memset(&_info, 0, sizeof(LoRaMacEventInfo));
+        }
+
+        virtual ~mDotEvent() {
+        }
+
+        virtual void MacEvent(LoRaMacEventFlags *flags, LoRaMacEventInfo *info) {
+            if (mts::MTSLog::getLogLevel() == mts::MTSLog::TRACE_LEVEL) {
+                std::string msg = "OK";
+                switch (info->Status) {
+                    case LORAMAC_EVENT_INFO_STATUS_ERROR:
+                        msg = "ERROR";
+                        break;
+                    case LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT:
+                        msg = "TX_TIMEOUT";
+                        break;
+                    case LORAMAC_EVENT_INFO_STATUS_RX_TIMEOUT:
+                        msg = "RX_TIMEOUT";
+                        break;
+                    case LORAMAC_EVENT_INFO_STATUS_RX_ERROR:
+                        msg = "RX_ERROR";
+                        break;
+                    case LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL:
+                        msg = "JOIN_FAIL";
+                        break;
+                    case LORAMAC_EVENT_INFO_STATUS_DOWNLINK_FAIL:
+                        msg = "DOWNLINK_FAIL";
+                        break;
+                    case LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL:
+                        msg = "ADDRESS_FAIL";
+                        break;
+                    case LORAMAC_EVENT_INFO_STATUS_MIC_FAIL:
+                        msg = "MIC_FAIL";
+                        break;
+                    default:
+                        break;
+                }
+                logTrace("Event: %s", msg.c_str());
+
+                logTrace("Flags Tx: %d Rx: %d RxData: %d RxSlot: %d LinkCheck: %d JoinAccept: %d",
+                         flags->Bits.Tx, flags->Bits.Rx, flags->Bits.RxData, flags->Bits.RxSlot, flags->Bits.LinkCheck, flags->Bits.JoinAccept);
+                logTrace("Info: Status: %d ACK: %d Retries: %d TxDR: %d RxPort: %d RxSize: %d RSSI: %d SNR: %d Energy: %d Margin: %d Gateways: %d",
+                         info->Status, info->TxAckReceived, info->TxNbRetries, info->TxDatarate, info->RxPort, info->RxBufferSize,
+                         info->RxRssi, info->RxSnr, info->Energy, info->DemodMargin, info->NbGateways);
+            }
+        }
+
+        virtual void TxStart() {
+            logDebug("mDotEvent - TxStart");
+
+            // Fire auto sleep cfg event if enabled
+            if (_sleep_cb)
+                _sleep_cb(mDot::AUTO_SLEEP_EVT_CFG);
+        }
+
+        virtual void TxDone(uint8_t dr) {
+            RxPayloadSize = 0;
+            LinkCheckAnsReceived = false;
+            PacketReceived = false;
+            AckReceived = false;
+            DuplicateRx = false;
+            PongReceived = false;
+            TxNbRetries = 0;
+
+            logDebug("mDotEvent - TxDone");
+            memset(&_flags, 0, sizeof(LoRaMacEventFlags));
+            memset(&_info, 0, sizeof(LoRaMacEventInfo));
+
+            _flags.Bits.Tx = 1;
+            _info.TxDatarate = dr;
+            _info.Status = LORAMAC_EVENT_INFO_STATUS_OK;
+            Notify();
+
+            // If configured, we can sleep until the rx window opens
+            if (_sleep_cb)
+                _sleep_cb(mDot::AUTO_SLEEP_EVT_TXDONE);
+        }
+
+        void Notify() {
+            MacEvent(&_flags, &_info);
+        }
+
+        virtual void TxTimeout(void) {
+            logDebug("mDotEvent - TxTimeout");
+
+            _flags.Bits.Tx = 1;
+            _info.Status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT;
+            Notify();
+        }
+
+        virtual void JoinAccept(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr) {
+            logDebug("mDotEvent - JoinAccept");
+
+            _flags.Bits.Tx = 0;
+            _flags.Bits.JoinAccept = 1;
+            _info.Status = LORAMAC_EVENT_INFO_STATUS_OK;
+            Notify();
+
+            if (_sleep_cb)
+                _sleep_cb(mDot::AUTO_SLEEP_EVT_CLEANUP);
+        }
+
+        virtual void JoinFailed(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr) {
+            logDebug("mDotEvent - JoinFailed");
+
+            _flags.Bits.Tx = 0;
+            _flags.Bits.JoinAccept = 1;
+            _info.Status = LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL;
+            Notify();
+
+            if (_sleep_cb)
+                _sleep_cb(mDot::AUTO_SLEEP_EVT_CLEANUP);
+        }
+
+        virtual void MissedAck(uint8_t retries) {
+            logDebug("mDotEvent - MissedAck : retries %u", retries);
+            TxNbRetries = retries;
+            _info.TxNbRetries = retries;
+        }
+
+        virtual void PacketRx(uint8_t port, uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr, lora::DownlinkControl ctrl, uint8_t slot, uint8_t retries, uint32_t address, bool dupRx) {
+            logDebug("mDotEvent - PacketRx ADDR: %08x", address);
+            RxPort = port;
+            PacketReceived = true;
+
+            memcpy(RxPayload, payload, size);
+            RxPayloadSize = size;
+
+            if (ctrl.Bits.Ack) {
+                AckReceived = true;
+            }
+
+            DuplicateRx = dupRx;
+
+            if (mts::MTSLog::getLogLevel() == mts::MTSLog::TRACE_LEVEL) {
+                std::string packet = mts::Text::bin2hexString(RxPayload, size);
+                logTrace("Payload: %s", packet.c_str());
+            }
+
+            _flags.Bits.Tx = 0;
+            _flags.Bits.Rx = 1;
+            _flags.Bits.RxData = size > 0;
+            _flags.Bits.RxSlot = slot;
+            _info.RxBuffer = payload;
+            _info.RxBufferSize = size;
+            _info.RxPort = port;
+            _info.RxRssi = rssi;
+            _info.RxSnr = snr;
+            _info.TxAckReceived = AckReceived;
+            _info.DuplicateRx = DuplicateRx;
+            _info.TxNbRetries = retries;
+            _info.Status = LORAMAC_EVENT_INFO_STATUS_OK;
+            Notify();
+        }
+
+        virtual void RxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr, lora::DownlinkControl ctrl, uint8_t slot) {
+            logDebug("mDotEvent - RxDone");
+
+            if (_sleep_cb)
+                _sleep_cb(mDot::AUTO_SLEEP_EVT_CLEANUP);
+        }
+
+        virtual void Pong(int16_t m_rssi, int8_t m_snr, int16_t s_rssi, int8_t s_snr) {
+            logDebug("mDotEvent - Pong");
+            PongReceived = true;
+            PongRssi = s_rssi;
+            PongSnr = s_snr;
+        }
+
+        virtual void NetworkLinkCheck(int16_t m_rssi, int8_t m_snr, int8_t s_snr, uint8_t s_gateways) {
+            logDebug("mDotEvent - NetworkLinkCheck");
+            LinkCheckAnsReceived = true;
+            DemodMargin = s_snr;
+            NbGateways = s_gateways;
+
+            _flags.Bits.Tx = 0;
+            _flags.Bits.LinkCheck = 1;
+            _info.RxRssi = m_rssi;
+            _info.RxSnr = m_snr;
+            _info.DemodMargin = s_snr;
+            _info.NbGateways = s_gateways;
+            _info.Status = LORAMAC_EVENT_INFO_STATUS_OK;
+            Notify();
+        }
+
+        virtual void RxTimeout(uint8_t slot) {
+            logDebug("mDotEvent - RxTimeout on Slot %d", slot);
+
+            _flags.Bits.Tx = 0;
+            _flags.Bits.RxSlot = slot;
+            _info.Status = LORAMAC_EVENT_INFO_STATUS_RX_TIMEOUT;
+            Notify();
+
+            if (_sleep_cb) {
+                // If this is the first rx window we can sleep until the next one
+                if (slot == 1)
+                    _sleep_cb(mDot::AUTO_SLEEP_EVT_RX1_TIMEOUT);
+                else
+                    _sleep_cb(mDot::AUTO_SLEEP_EVT_CLEANUP);
+            }
+        }
+
+        virtual void RxError(uint8_t slot) {
+            logDebug("mDotEvent - RxError");
+
+            memset(&_flags, 0, sizeof(LoRaMacEventFlags));
+            memset(&_info, 0, sizeof(LoRaMacEventInfo));
+
+            _flags.Bits.RxSlot = slot;
+            _info.Status = LORAMAC_EVENT_INFO_STATUS_RX_ERROR;
+            Notify();
+
+            if (_sleep_cb)
+                _sleep_cb(mDot::AUTO_SLEEP_EVT_CLEANUP);
+        }
+
+        virtual uint8_t MeasureBattery(void) {
+            return 255;
+        }
+
+        void AttachSleepCallback(Callback<void(mDot::AutoSleepEvent_t)> cb) {
+            _sleep_cb = cb;
+        }
+
+        void DetachSleepCallback() {
+            _sleep_cb = NULL;
+        }
+
+        bool LinkCheckAnsReceived;
+        uint8_t DemodMargin;
+        uint8_t NbGateways;
+
+        bool PacketReceived;
+        uint8_t RxPort;
+        uint8_t RxPayload[255];
+        uint8_t RxPayloadSize;
+
+        bool PongReceived;
+        int16_t PongRssi;
+        int16_t PongSnr;
+
+        bool AckReceived;
+        bool DuplicateRx;
+        uint8_t TxNbRetries;
+
+        LoRaMacEventFlags& Flags() {
+            return _flags;
+        }
+        LoRaMacEventInfo& Info() {
+            return _info;
+        }
+
+    private:
+        /* Hook to inject a sleep method in between receive windows */
+        Callback<void(mDot::AutoSleepEvent_t)> _sleep_cb;
+
+        LoRaMacEventFlags _flags;
+        LoRaMacEventInfo _info;
+
+//
+//        /*!
+//         * MAC layer event callback prototype.
+//         *
+//         * \param [IN] flags Bit field indicating the MAC events occurred
+//         * \param [IN] info  Details about MAC events occurred
+//         */
+//        virtual void MacEvent(LoRaMacEventFlags *flags, LoRaMacEventInfo *info) {
+//            logDebug("mDotEvent");
+//
+//            if (flags->Bits.Rx) {
+//                logDebug("Rx");
+//
+//                // Event Object must delete RxBuffer
+//                delete[] info->RxBuffer;
+//            }
+//        }
+//
+
+};
+
+#endif // __MDOT_EVENT_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/spiffs.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,437 @@
+/*
+ * spiffs.h
+ *
+ *  Created on: May 26, 2013
+ *      Author: petera
+ */
+
+
+
+#ifndef SPIFFS_H_
+#define SPIFFS_H_
+
+#include "spiffs_config.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define SPIFFS_OK                       0
+#define SPIFFS_ERR_NOT_MOUNTED          -10000
+#define SPIFFS_ERR_FULL                 -10001
+#define SPIFFS_ERR_NOT_FOUND            -10002
+#define SPIFFS_ERR_END_OF_OBJECT        -10003
+#define SPIFFS_ERR_DELETED              -10004
+#define SPIFFS_ERR_NOT_FINALIZED        -10005
+#define SPIFFS_ERR_NOT_INDEX            -10006
+#define SPIFFS_ERR_OUT_OF_FILE_DESCS    -10007
+#define SPIFFS_ERR_FILE_CLOSED          -10008
+#define SPIFFS_ERR_FILE_DELETED         -10009
+#define SPIFFS_ERR_BAD_DESCRIPTOR       -10010
+#define SPIFFS_ERR_IS_INDEX             -10011
+#define SPIFFS_ERR_IS_FREE              -10012
+#define SPIFFS_ERR_INDEX_SPAN_MISMATCH  -10013
+#define SPIFFS_ERR_DATA_SPAN_MISMATCH   -10014
+#define SPIFFS_ERR_INDEX_REF_FREE       -10015
+#define SPIFFS_ERR_INDEX_REF_LU         -10016
+#define SPIFFS_ERR_INDEX_REF_INVALID    -10017
+#define SPIFFS_ERR_INDEX_FREE           -10018
+#define SPIFFS_ERR_INDEX_LU             -10019
+#define SPIFFS_ERR_INDEX_INVALID        -10020
+#define SPIFFS_ERR_NOT_WRITABLE         -10021
+#define SPIFFS_ERR_NOT_READABLE         -10022
+
+#define SPIFFS_ERR_INTERNAL             -10050
+
+#define SPIFFS_ERR_TEST                 -10100
+
+
+// spiffs file descriptor index type. must be signed
+typedef s16_t spiffs_file;
+// spiffs file descriptor flags
+typedef u16_t spiffs_flags;
+// spiffs file mode
+typedef u16_t spiffs_mode;
+// object type
+typedef u8_t spiffs_obj_type;
+
+/* spi read call function type */
+typedef s32_t (*spiffs_read)(u32_t addr, u32_t size, u8_t *dst);
+/* spi write call function type */
+typedef s32_t (*spiffs_write)(u32_t addr, u32_t size, u8_t *src);
+/* spi erase call function type */
+typedef s32_t (*spiffs_erase)(u32_t addr, u32_t size);
+
+/* file system check callback report operation */
+typedef enum {
+  SPIFFS_CHECK_LOOKUP = 0,
+  SPIFFS_CHECK_INDEX,
+  SPIFFS_CHECK_PAGE
+} spiffs_check_type;
+
+/* file system check callback report type */
+typedef enum {
+  SPIFFS_CHECK_PROGRESS = 0,
+  SPIFFS_CHECK_ERROR,
+  SPIFFS_CHECK_FIX_INDEX,
+  SPIFFS_CHECK_FIX_LOOKUP,
+  SPIFFS_CHECK_DELETE_ORPHANED_INDEX,
+  SPIFFS_CHECK_DELETE_PAGE,
+  SPIFFS_CHECK_DELETE_BAD_FILE,
+} spiffs_check_report;
+
+/* file system check callback function */
+typedef void (*spiffs_check_callback)(spiffs_check_type type, spiffs_check_report report,
+    u32_t arg1, u32_t arg2);
+
+#ifndef SPIFFS_DBG
+#define SPIFFS_DBG(...) \
+    print(__VA_ARGS__)
+#endif
+#ifndef SPIFFS_GC_DBG
+#define SPIFFS_GC_DBG(...) printf(__VA_ARGS__)
+#endif
+#ifndef SPIFFS_CACHE_DBG
+#define SPIFFS_CACHE_DBG(...) printf(__VA_ARGS__)
+#endif
+#ifndef SPIFFS_CHECK_DBG
+#define SPIFFS_CHECK_DBG(...) printf(__VA_ARGS__)
+#endif
+
+/* Any write to the filehandle is appended to end of the file */
+#define SPIFFS_APPEND                   (1<<0)
+/* If the opened file exists, it will be truncated to zero length before opened */
+#define SPIFFS_TRUNC                    (1<<1)
+/* If the opened file does not exist, it will be created before opened */
+#define SPIFFS_CREAT                    (1<<2)
+/* The opened file may only be read */
+#define SPIFFS_RDONLY                   (1<<3)
+/* The opened file may only be writted */
+#define SPIFFS_WRONLY                   (1<<4)
+/* The opened file may be both read and writted */
+#define SPIFFS_RDWR                     (SPIFFS_RDONLY | SPIFFS_WRONLY)
+/* Any writes to the filehandle will never be cached */
+#define SPIFFS_DIRECT                   (1<<5)
+
+#define SPIFFS_SEEK_SET                 (0)
+#define SPIFFS_SEEK_CUR                 (1)
+#define SPIFFS_SEEK_END                 (2)
+
+#define SPIFFS_TYPE_FILE                (1)
+#define SPIFFS_TYPE_DIR                 (2)
+#define SPIFFS_TYPE_HARD_LINK           (3)
+#define SPIFFS_TYPE_SOFT_LINK           (4)
+
+#ifndef SPIFFS_LOCK
+#define SPIFFS_LOCK(fs)
+#endif
+
+#ifndef SPIFFS_UNLOCK
+#define SPIFFS_UNLOCK(fs)
+#endif
+
+// phys structs
+
+// spiffs spi configuration struct
+typedef struct {
+  // physical read function
+  spiffs_read hal_read_f;
+  // physical write function
+  spiffs_write hal_write_f;
+  // physical erase function
+  spiffs_erase hal_erase_f;
+#if SPIFFS_SINGLETON == 0
+  // physical size of the spi flash
+  u32_t phys_size;
+  // physical offset in spi flash used for spiffs,
+  // must be on block boundary
+  u32_t phys_addr;
+  // physical size when erasing a block
+  u32_t phys_erase_block;
+
+  // logical size of a block, must be on physical
+  // block size boundary and must never be less than
+  // a physical block
+  u32_t log_block_size;
+  // logical size of a page, must be at least
+  // log_block_size / 8
+  u32_t log_page_size;
+#endif
+} spiffs_config;
+
+typedef struct {
+  // file system configuration
+  spiffs_config cfg;
+  // number of logical blocks
+  u32_t block_count;
+
+  // cursor for free blocks, block index
+  spiffs_block_ix free_cursor_block_ix;
+  // cursor for free blocks, entry index
+  int free_cursor_obj_lu_entry;
+  // cursor when searching, block index
+  spiffs_block_ix cursor_block_ix;
+  // cursor when searching, entry index
+  int cursor_obj_lu_entry;
+
+  // primary work buffer, size of a logical page
+  u8_t *lu_work;
+  // secondary work buffer, size of a logical page
+  u8_t *work;
+  // file descriptor memory area
+  u8_t *fd_space;
+  // available file descriptors
+  u32_t fd_count;
+
+  // last error
+  s32_t err_code;
+
+  // current number of free blocks
+  u32_t free_blocks;
+  // current number of busy pages
+  u32_t stats_p_allocated;
+  // current number of deleted pages
+  u32_t stats_p_deleted;
+  // flag indicating that garbage collector is cleaning
+  u8_t cleaning;
+  // max erase count amongst all blocks
+  spiffs_obj_id max_erase_count;
+
+#if SPIFFS_GC_STATS
+  u32_t stats_gc_runs;
+#endif
+
+#if SPIFFS_CACHE
+  // cache memory
+  u8_t *cache;
+  // cache size
+  u32_t cache_size;
+#if SPIFFS_CACHE_STATS
+  u32_t cache_hits;
+  u32_t cache_misses;
+#endif
+#endif
+
+  // check callback function
+  spiffs_check_callback check_cb_f;
+} spiffs;
+
+/* spiffs file status struct */
+typedef struct {
+  spiffs_obj_id obj_id;
+  u32_t size;
+  spiffs_obj_type type;
+  u8_t name[SPIFFS_OBJ_NAME_LEN];
+} spiffs_stat;
+
+struct spiffs_dirent {
+  spiffs_obj_id obj_id;
+  u8_t name[SPIFFS_OBJ_NAME_LEN];
+  spiffs_obj_type type;
+  u32_t size;
+};
+
+typedef struct {
+  spiffs *fs;
+  spiffs_block_ix block;
+  int entry;
+} spiffs_DIR;
+
+// functions
+
+/**
+ * Initializes the file system dynamic parameters and mounts the filesystem
+ * @param fs            the file system struct
+ * @param config        the physical and logical configuration of the file system
+ * @param work          a memory work buffer comprising 2*config->log_page_size
+ *                      bytes used throughout all file system operations
+ * @param fd_space      memory for file descriptors
+ * @param fd_space_size memory size of file descriptors
+ * @param cache         memory for cache, may be null
+ * @param cache_size    memory size of cache
+ * @param check_cb_f    callback function for reporting during consistency checks
+ */
+s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
+    u8_t *fd_space, u32_t fd_space_size,
+    u8_t *cache, u32_t cache_size,
+    spiffs_check_callback check_cb_f);
+
+/**
+ * Unmounts the file system. All file handles will be flushed of any
+ * cached writes and closed.
+ * @param fs            the file system struct
+ */
+void SPIFFS_unmount(spiffs *fs);
+
+/**
+ * Creates a new file.
+ * @param fs            the file system struct
+ * @param path          the path of the new file
+ * @param mode          ignored, for posix compliance
+ */
+s32_t SPIFFS_creat(spiffs *fs, const char *path, spiffs_mode mode);
+
+/**
+ * Opens/creates a file.
+ * @param fs            the file system struct
+ * @param path          the path of the new file
+ * @param flags         the flags for the open command, can be combinations of
+ *                      SPIFFS_APPEND, SPIFFS_TRUNC, SPIFFS_CREAT, SPIFFS_RD_ONLY,
+ *                      SPIFFS_WR_ONLY, SPIFFS_RDWR, SPIFFS_DIRECT
+ * @param mode          ignored, for posix compliance
+ */
+spiffs_file SPIFFS_open(spiffs *fs, const char *path, spiffs_flags flags, spiffs_mode mode);
+
+/**
+ * Reads from given filehandle.
+ * @param fs            the file system struct
+ * @param fh            the filehandle
+ * @param buf           where to put read data
+ * @param len           how much to read
+ * @returns number of bytes read, or -1 if error
+ */
+s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, s32_t len);
+
+/**
+ * Writes to given filehandle.
+ * @param fs            the file system struct
+ * @param fh            the filehandle
+ * @param buf           the data to write
+ * @param len           how much to write
+ * @returns number of bytes written, or -1 if error
+ */
+s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len);
+
+/**
+ * Moves the read/write file offset
+ * @param fs            the file system struct
+ * @param fh            the filehandle
+ * @param offs          how much/where to move the offset
+ * @param whence        if SPIFFS_SEEK_SET, the file offset shall be set to offset bytes
+ *                      if SPIFFS_SEEK_CUR, the file offset shall be set to its current location plus offset
+ *                      if SPIFFS_SEEK_END, the file offset shall be set to the size of the file plus offset
+ */
+s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence);
+
+/**
+ * Removes a file by path
+ * @param fs            the file system struct
+ * @param path          the path of the file to remove
+ */
+s32_t SPIFFS_remove(spiffs *fs, const char *path);
+
+/**
+ * Removes a file by path
+ * @param fs            the file system struct
+ * @param path          the path of the file to move
+ * @param new_path          the path of the file to move
+ */
+s32_t SPIFFS_move(spiffs *fs, const char *path, const char *new_path);
+
+/**
+ * Removes a file by filehandle
+ * @param fs            the file system struct
+ * @param fh            the filehandle of the file to remove
+ */
+s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh);
+
+/**
+ * Gets file status by path
+ * @param fs            the file system struct
+ * @param path          the path of the file to stat
+ * @param s             the stat struct to populate
+ */
+s32_t SPIFFS_stat(spiffs *fs, const char *path, spiffs_stat *s);
+
+/**
+ * Gets file status by filehandle
+ * @param fs            the file system struct
+ * @param fh            the filehandle of the file to stat
+ * @param s             the stat struct to populate
+ */
+s32_t SPIFFS_fstat(spiffs *fs, spiffs_file fh, spiffs_stat *s);
+
+/**
+ * Flushes all pending write operations from cache for given file
+ * @param fs            the file system struct
+ * @param fh            the filehandle of the file to flush
+ */
+s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh);
+
+/**
+ * Closes a filehandle. If there are pending write operations, these are finalized before closing.
+ * @param fs            the file system struct
+ * @param fh            the filehandle of the file to close
+ */
+void SPIFFS_close(spiffs *fs, spiffs_file fh);
+
+/**
+ * Returns last error of last file operation.
+ * @param fs            the file system struct
+ */
+s32_t SPIFFS_errno(spiffs *fs);
+
+/**
+ * Opens a directory stream corresponding to the given name.
+ * The stream is positioned at the first entry in the directory.
+ * On hydrogen builds the name argument is ignored as hydrogen builds always correspond
+ * to a flat file structure - no directories.
+ * @param fs            the file system struct
+ * @param name          the name of the directory
+ * @param d             pointer the directory stream to be populated
+ */
+spiffs_DIR *SPIFFS_opendir(spiffs *fs, const char *name, spiffs_DIR *d);
+
+/**
+ * Closes a directory stream
+ * @param d             the directory stream to close
+ */
+s32_t SPIFFS_closedir(spiffs_DIR *d);
+
+/**
+ * Reads a directory into given spifs_dirent struct.
+ * @param d             pointer to the directory stream
+ * @param e             the dirent struct to be populated
+ * @returns null if error or end of stream, else given dirent is returned
+ */
+struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e);
+
+/**
+ * Runs a consistency check on given filesystem.
+ * @param fs            the file system struct
+ */
+s32_t SPIFFS_check(spiffs *fs);
+
+#if SPIFFS_TEST_VISUALISATION
+/**
+ * Prints out a visualization of the filesystem.
+ * @param fs            the file system struct
+ */
+s32_t SPIFFS_vis(spiffs *fs);
+#endif
+
+#if SPIFFS_BUFFER_HELP
+/**
+ * Returns number of bytes needed for the filedescriptor buffer given
+ * amount of file descriptors.
+ */
+u32_t SPIFFS_buffer_bytes_for_filedescs(spiffs *fs, u32_t num_descs);
+
+#if SPIFFS_CACHE
+/**
+ * Returns number of bytes needed for the cache buffer given
+ * amount of cache pages.
+ */
+u32_t SPIFFS_buffer_bytes_for_cache(spiffs *fs, u32_t num_pages);
+#endif
+#endif
+
+#if SPIFFS_CHACHE
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SPIFFS_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/spiffs_config.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,208 @@
+/*
+ * spiffs_config.h
+ *
+ *  Created on: Jul 3, 2013
+ *      Author: petera
+ */
+
+#ifndef SPIFFS_CONFIG_H_
+#define SPIFFS_CONFIG_H_
+
+// ----------- 8< ------------
+// Following includes are for the linux test build of spiffs
+// These may/should/must be removed/altered/replaced in your target
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stddef.h>
+// ----------- >8 ------------
+
+typedef signed int          s32_t;
+typedef unsigned int        u32_t;
+typedef signed short        s16_t;
+typedef unsigned short      u16_t;
+typedef signed char         s8_t;;
+typedef unsigned char       u8_t;
+
+// compile time switches
+
+// Set generic spiffs debug output call.
+#ifndef SPIFFS_DGB
+#define SPIFFS_DBG(...)
+#endif
+// Set spiffs debug output call for garbage collecting.
+#ifndef SPIFFS_GC_DGB
+#define SPIFFS_GC_DBG(...)
+#endif
+// Set spiffs debug output call for caching.
+#ifndef SPIFFS_CACHE_DGB
+#define SPIFFS_CACHE_DBG(...)
+#endif
+// Set spiffs debug output call for system consistency checks.
+#ifndef SPIFFS_CHECK_DGB
+#define SPIFFS_CHECK_DBG(...)
+#endif
+
+// Enable/disable API functions to determine exact number of bytes
+// for filedescriptor and cache buffers. Once decided for a configuration,
+// this can be disabled to reduce flash.
+#ifndef SPIFFS_BUFFER_HELP
+#define SPIFFS_BUFFER_HELP              0
+#endif
+
+// Enables/disable memory read caching of nucleus file system operations.
+// If enabled, memory area must be provided for cache in SPIFFS_mount.
+#ifndef  SPIFFS_CACHE
+#define SPIFFS_CACHE                    1
+#endif
+#if SPIFFS_CACHE
+// Enables memory write caching for file descriptors in hydrogen
+#ifndef  SPIFFS_CACHE_WR
+#define SPIFFS_CACHE_WR                 1
+#endif
+
+// Enable/disable statistics on caching. Debug/test purpose only.
+#ifndef  SPIFFS_CACHE_STATS
+#define SPIFFS_CACHE_STATS              0
+#endif
+#endif
+
+// Always check header of each accessed page to ensure consistent state.
+// If enabled it will increase number of reads, will increase flash.
+#ifndef SPIFFS_PAGE_CHECK
+#define SPIFFS_PAGE_CHECK               1
+#endif
+
+// Define maximum number of gc runs to perform to reach desired free pages.
+#ifndef SPIFFS_GC_MAX_RUNS
+#define SPIFFS_GC_MAX_RUNS              3
+#endif
+
+// Enable/disable statistics on gc. Debug/test purpose only.
+#ifndef SPIFFS_GC_STATS
+#define SPIFFS_GC_STATS                 0
+#endif
+
+// Garbage collecting examines all pages in a block which and sums up
+// to a block score. Deleted pages normally gives positive score and
+// used pages normally gives a negative score (as these must be moved).
+// To have a fair wear-leveling, the erase age is also included in score,
+// whose factor normally is the most positive.
+// The larger the score, the more likely it is that the block will
+// picked for garbage collection.
+
+// Garbage collecting heuristics - weight used for deleted pages.
+#ifndef SPIFFS_GC_HEUR_W_DELET
+#define SPIFFS_GC_HEUR_W_DELET          (5)
+#endif
+// Garbage collecting heuristics - weight used for used pages.
+#ifndef SPIFFS_GC_HEUR_W_USED
+#define SPIFFS_GC_HEUR_W_USED           (-1)
+#endif
+// Garbage collecting heuristics - weight used for time between
+// last erased and erase of this block.
+#ifndef SPIFFS_GC_HEUR_W_ERASE_AGE
+#define SPIFFS_GC_HEUR_W_ERASE_AGE      (50)
+#endif
+
+// Object name maximum length.
+#ifndef SPIFFS_OBJ_NAME_LEN
+#define SPIFFS_OBJ_NAME_LEN             (32)
+#endif
+
+// Size of buffer allocated on stack used when copying data.
+// Lower value generates more read/writes. No meaning having it bigger
+// than logical page size.
+#ifndef SPIFFS_COPY_BUFFER_STACK
+#define SPIFFS_COPY_BUFFER_STACK        (64)
+#endif
+
+// SPIFFS_LOCK and SPIFFS_UNLOCK protects spiffs from reentrancy on api level
+// These should be defined on a multithreaded system
+
+// define this to entering a mutex if you're running on a multithreaded system
+#ifndef SPIFFS_LOCK
+#define SPIFFS_LOCK(fs)
+#endif
+// define this to exiting a mutex if you're running on a multithreaded system
+#ifndef SPIFFS_UNLOCK
+#define SPIFFS_UNLOCK(fs)
+#endif
+
+
+// Enable if only one spiffs instance with constant configuration will exist
+// on the target. This will reduce calculations, flash and memory accesses.
+// Parts of configuration must be defined below instead of at time of mount.
+#ifndef SPIFFS_SINGLETON
+#define SPIFFS_SINGLETON 0
+#endif
+
+#if SPIFFS_SINGLETON
+// Instead of giving parameters in config struct, singleton build must
+// give parameters in defines below.
+#ifndef SPIFFS_CFG_PHYS_SZ
+#define SPIFFS_CFG_PHYS_SZ(ignore)        (1024*1024*2)
+#endif
+#ifndef SPIFFS_CFG_PHYS_ERASE_SZ
+#define SPIFFS_CFG_PHYS_ERASE_SZ(ignore)  (65536)
+#endif
+#ifndef SPIFFS_CFG_PHYS_ADDR
+#define SPIFFS_CFG_PHYS_ADDR(ignore)      (0)
+#endif
+#ifndef SPIFFS_CFG_LOG_PAGE_SZ
+#define SPIFFS_CFG_LOG_PAGE_SZ(ignore)    (256)
+#endif
+#ifndef SPIFFS_CFG_LOG_BLOCK_SZ
+#define SPIFFS_CFG_LOG_BLOCK_SZ(ignore)   (65536)
+#endif
+#endif
+
+// Set SPFIFS_TEST_VISUALISATION to non-zero to enable SPIFFS_vis function
+// in the api. This function will visualize all filesystem using given printf
+// function.
+#ifndef SPIFFS_TEST_VISUALISATION
+#define SPIFFS_TEST_VISUALISATION         1
+#endif
+#if SPIFFS_TEST_VISUALISATION
+#ifndef spiffs_printf
+#define spiffs_printf(...)                printf(__VA_ARGS__)
+#endif
+// spiffs_printf argument for a free page
+#ifndef SPIFFS_TEST_VIS_FREE_STR
+#define SPIFFS_TEST_VIS_FREE_STR          "_"
+#endif
+// spiffs_printf argument for a deleted page
+#ifndef SPIFFS_TEST_VIS_DELE_STR
+#define SPIFFS_TEST_VIS_DELE_STR          "/"
+#endif
+// spiffs_printf argument for an index page for given object id
+#ifndef SPIFFS_TEST_VIS_INDX_STR
+#define SPIFFS_TEST_VIS_INDX_STR(id)      "i"
+#endif
+// spiffs_printf argument for a data page for given object id
+#ifndef SPIFFS_TEST_VIS_DATA_STR
+#define SPIFFS_TEST_VIS_DATA_STR(id)      "d"
+#endif
+#endif
+
+// Types depending on configuration such as the amount of flash bytes
+// given to spiffs file system in total (spiffs_file_system_size),
+// the logical block size (log_block_size), and the logical page size
+// (log_page_size)
+
+// Block index type. Make sure the size of this type can hold
+// the highest number of all blocks - i.e. spiffs_file_system_size / log_block_size
+typedef u8_t spiffs_block_ix;
+// Page index type. Make sure the size of this type can hold
+// the highest page number of all pages - i.e. spiffs_file_system_size / log_page_size
+typedef u16_t spiffs_page_ix;
+// Object id type - most significant bit is reserved for index flag. Make sure the
+// size of this type can hold the highest object id on a full system,
+// i.e. 2 + (spiffs_file_system_size / (2*log_page_size))*2
+typedef u16_t spiffs_obj_id;
+// Object span index type. Make sure the size of this type can
+// hold the largest possible span index on the system -
+// i.e. (spiffs_file_system_size / log_page_size) - 1
+typedef u16_t spiffs_span_ix;
+
+#endif /* SPIFFS_CONFIG_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mdot/spiffs_nucleus.h	Fri Sep 14 15:39:09 2018 -0500
@@ -0,0 +1,696 @@
+/*
+ * spiffs_nucleus.h
+ *
+ *  Created on: Jun 15, 2013
+ *      Author: petera
+ */
+
+/* SPIFFS layout
+ *
+ * spiffs is designed for following spi flash characteristics:
+ *   - only big areas of data (blocks) can be erased
+ *   - erasing resets all bits in a block to ones
+ *   - writing pulls ones to zeroes
+ *   - zeroes cannot be pulled to ones, without erase
+ *   - wear leveling
+ *
+ * spiffs is also meant to be run on embedded, memory constraint devices.
+ *
+ * Entire area is divided in blocks. Entire area is also divided in pages.
+ * Each block contains same number of pages. A page cannot be erased, but a
+ * block can be erased.
+ *
+ * Entire area must be block_size * x
+ * page_size must be block_size / (2^y) where y > 2
+ *
+ * ex: area = 1024*1024 bytes, block size = 65536 bytes, page size = 256 bytes
+ *
+ * BLOCK 0  PAGE 0       object lookup 1
+ *          PAGE 1       object lookup 2
+ *          ...
+ *          PAGE n-1     object lookup n
+ *          PAGE n       object data 1
+ *          PAGE n+1     object data 2
+ *          ...
+ *          PAGE n+m-1   object data m
+ *
+ * BLOCK 1  PAGE n+m     object lookup 1
+ *          PAGE n+m+1   object lookup 2
+ *          ...
+ *          PAGE 2n+m-1  object lookup n
+ *          PAGE 2n+m    object data 1
+ *          PAGE 2n+m    object data 2
+ *          ...
+ *          PAGE 2n+2m-1 object data m
+ * ...
+ *
+ * n is number of object lookup pages, which is number of pages needed to index all pages
+ * in a block by object id
+ *   : block_size / page_size * sizeof(obj_id) / page_size
+ * m is number data pages, which is number of pages in block minus number of lookup pages
+ *   : block_size / page_size - block_size / page_size * sizeof(obj_id) / page_size
+ * thus, n+m is total number of pages in a block
+ *   : block_size / page_size
+ *
+ * ex: n = 65536/256*2/256 = 2, m = 65536/256 - 2 = 254 => n+m = 65536/256 = 256
+ *
+ * Object lookup pages contain object id entries. Each entry represent the corresponding
+ * data page.
+ * Assuming a 16 bit object id, an object id being 0xffff represents a free page.
+ * An object id being 0x0000 represents a deleted page.
+ *
+ * ex: page 0 : lookup : 0008 0001 0aaa ffff ffff ffff ffff ffff ..
+ *     page 1 : lookup : ffff ffff ffff ffff ffff ffff ffff ffff ..
+ *     page 2 : data   : data for object id 0008
+ *     page 3 : data   : data for object id 0001
+ *     page 4 : data   : data for object id 0aaa
+ *     ...
+ *
+ *
+ * Object data pages can be either object index pages or object content.
+ * All object data pages contains a data page header, containing object id and span index.
+ * The span index denotes the object page ordering amongst data pages with same object id.
+ * This applies to both object index pages (when index spans more than one page of entries),
+ * and object data pages.
+ * An object index page contains page entries pointing to object content page. The entry index
+ * in a object index page correlates to the span index in the actual object data page.
+ * The first object index page (span index 0) is called object index header page, and also
+ * contains object flags (directory/file), size, object name etc.
+ *
+ * ex:
+ *  BLOCK 1
+ *    PAGE 256: objectl lookup page 1
+ *      [*123] [ 123] [ 123] [ 123]
+ *      [ 123] [*123] [ 123] [ 123]
+ *      [free] [free] [free] [free] ...
+ *    PAGE 257: objectl lookup page 2
+ *      [free] [free] [free] [free] ...
+ *    PAGE 258: object index page (header)
+ *      obj.id:0123 span.ix:0000 flags:INDEX
+ *      size:1600 name:ex.txt type:file
+ *      [259] [260] [261] [262]
+ *    PAGE 259: object data page
+ *      obj.id:0123 span.ix:0000 flags:DATA
+ *    PAGE 260: object data page
+ *      obj.id:0123 span.ix:0001 flags:DATA
+ *    PAGE 261: object data page
+ *      obj.id:0123 span.ix:0002 flags:DATA
+ *    PAGE 262: object data page
+ *      obj.id:0123 span.ix:0003 flags:DATA
+ *    PAGE 263: object index page
+ *      obj.id:0123 span.ix:0001 flags:INDEX
+ *      [264] [265] [fre] [fre]
+ *      [fre] [fre] [fre] [fre]
+ *    PAGE 264: object data page
+ *      obj.id:0123 span.ix:0004 flags:DATA
+ *    PAGE 265: object data page
+ *      obj.id:0123 span.ix:0005 flags:DATA
+ *
+ */
+#ifndef SPIFFS_NUCLEUS_H_
+#define SPIFFS_NUCLEUS_H_
+
+#define _SPIFFS_ERR_CHECK_FIRST         (SPIFFS_ERR_INTERNAL - 1)
+#define SPIFFS_ERR_CHECK_OBJ_ID_MISM    (SPIFFS_ERR_INTERNAL - 1)
+#define SPIFFS_ERR_CHECK_SPIX_MISM      (SPIFFS_ERR_INTERNAL - 2)
+#define SPIFFS_ERR_CHECK_FLAGS_BAD      (SPIFFS_ERR_INTERNAL - 3)
+#define _SPIFFS_ERR_CHECK_LAST          (SPIFFS_ERR_INTERNAL - 4)
+
+#define SPIFFS_VIS_COUNTINUE            (SPIFFS_ERR_INTERNAL - 20)
+#define SPIFFS_VIS_COUNTINUE_RELOAD     (SPIFFS_ERR_INTERNAL - 21)
+#define SPIFFS_VIS_END                  (SPIFFS_ERR_INTERNAL - 22)
+
+#define SPIFFS_EV_IX_UPD                0
+#define SPIFFS_EV_IX_NEW                1
+#define SPIFFS_EV_IX_DEL                2
+
+#define SPIFFS_OBJ_ID_IX_FLAG           (1<<(8*sizeof(spiffs_obj_id)-1))
+
+#define SPIFFS_UNDEFINED_LEN            (-1)
+
+#define SPIFFS_OBJ_ID_DELETED           ((spiffs_obj_id)0)
+#define SPIFFS_OBJ_ID_FREE              ((spiffs_obj_id)-1)
+
+#if SPIFFS_SINGLETON == 0
+#define SPIFFS_CFG_LOG_PAGE_SZ(fs) \
+  ((fs)->cfg.log_page_size)
+#define SPIFFS_CFG_LOG_BLOCK_SZ(fs) \
+  ((fs)->cfg.log_block_size)
+#define SPIFFS_CFG_PHYS_SZ(fs) \
+  ((fs)->cfg.phys_size)
+#define SPIFFS_CFG_PHYS_ERASE_SZ(fs) \
+  ((fs)->cfg.phys_erase_block)
+#define SPIFFS_CFG_PHYS_ADDR(fs) \
+  ((fs)->cfg.phys_addr)
+#endif
+
+// total number of pages
+#define SPIFFS_MAX_PAGES(fs) \
+  ( SPIFFS_CFG_PHYS_SZ(fs)/SPIFFS_CFG_LOG_PAGE_SZ(fs) )
+// total number of pages per block, including object lookup pages
+#define SPIFFS_PAGES_PER_BLOCK(fs) \
+  ( SPIFFS_CFG_LOG_BLOCK_SZ(fs)/SPIFFS_CFG_LOG_PAGE_SZ(fs) )
+// number of object lookup pages per block
+#define SPIFFS_OBJ_LOOKUP_PAGES(fs)     \
+  (MAX(1, (SPIFFS_PAGES_PER_BLOCK(fs) * sizeof(spiffs_obj_id)) / SPIFFS_CFG_LOG_PAGE_SZ(fs)) )
+// checks if page index belongs to object lookup
+#define SPIFFS_IS_LOOKUP_PAGE(fs,pix)     \
+  (((pix) % SPIFFS_PAGES_PER_BLOCK(fs)) < SPIFFS_OBJ_LOOKUP_PAGES(fs))
+// number of object lookup entries in all object lookup pages
+#define SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs) \
+  (SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs))
+// converts a block to physical address
+#define SPIFFS_BLOCK_TO_PADDR(fs, block) \
+  ( SPIFFS_CFG_PHYS_ADDR(fs) + (block)* SPIFFS_CFG_LOG_BLOCK_SZ(fs) )
+// converts a object lookup entry to page index
+#define SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, block, entry) \
+  ((block)*SPIFFS_PAGES_PER_BLOCK(fs) + (SPIFFS_OBJ_LOOKUP_PAGES(fs) + entry))
+// converts a object lookup entry to physical address of corresponding page
+#define SPIFFS_OBJ_LOOKUP_ENTRY_TO_PADDR(fs, block, entry) \
+  (SPIFFS_BLOCK_TO_PADDR(fs, block) + (SPIFFS_OBJ_LOOKUP_PAGES(fs) + entry) * SPIFFS_CFG_LOG_PAGE_SZ(fs) )
+// converts a page to physical address
+#define SPIFFS_PAGE_TO_PADDR(fs, page) \
+  ( SPIFFS_CFG_PHYS_ADDR(fs) + (page) * SPIFFS_CFG_LOG_PAGE_SZ(fs) )
+// converts a physical address to page
+#define SPIFFS_PADDR_TO_PAGE(fs, addr) \
+  ( ((addr) -  SPIFFS_CFG_PHYS_ADDR(fs)) / SPIFFS_CFG_LOG_PAGE_SZ(fs) )
+// gives index in page for a physical address
+#define SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr) \
+  ( ((addr) - SPIFFS_CFG_PHYS_ADDR(fs)) % SPIFFS_CFG_LOG_PAGE_SZ(fs) )
+// returns containing block for given page
+#define SPIFFS_BLOCK_FOR_PAGE(fs, page) \
+  ( (page) / SPIFFS_PAGES_PER_BLOCK(fs) )
+// returns starting page for block
+#define SPIFFS_PAGE_FOR_BLOCK(fs, block) \
+  ( (block) * SPIFFS_PAGES_PER_BLOCK(fs) )
+// converts page to entry in object lookup page
+#define SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, page) \
+  ( (page) % SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs) )
+// returns data size in a data page
+#define SPIFFS_DATA_PAGE_SIZE(fs) \
+    ( SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_header) )
+// returns physical address for block's erase count
+#define SPIFFS_ERASE_COUNT_PADDR(fs, bix) \
+  ( SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_OBJ_LOOKUP_PAGES(fs) * SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_obj_id) )
+
+// define helpers object
+
+// entries in an object header page index
+#define SPIFFS_OBJ_HDR_IX_LEN(fs) \
+  ((SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_object_ix_header))/sizeof(spiffs_page_ix))
+// entries in an object page index
+#define SPIFFS_OBJ_IX_LEN(fs) \
+  ((SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_object_ix))/sizeof(spiffs_page_ix))
+// object index entry for given data span index
+#define SPIFFS_OBJ_IX_ENTRY(fs, spix) \
+  ((spix) < SPIFFS_OBJ_HDR_IX_LEN(fs) ? (spix) : (((spix)-SPIFFS_OBJ_HDR_IX_LEN(fs))%SPIFFS_OBJ_IX_LEN(fs)))
+// object index span index number for given data span index or entry
+#define SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, spix) \
+  ((spix) < SPIFFS_OBJ_HDR_IX_LEN(fs) ? 0 : (1+((spix)-SPIFFS_OBJ_HDR_IX_LEN(fs))/SPIFFS_OBJ_IX_LEN(fs)))
+
+
+#define SPIFFS_OP_T_OBJ_LU    (0<<0)
+#define SPIFFS_OP_T_OBJ_LU2   (1<<0)
+#define SPIFFS_OP_T_OBJ_IX    (2<<0)
+#define SPIFFS_OP_T_OBJ_DA    (3<<0)
+#define SPIFFS_OP_C_DELE      (0<<2)
+#define SPIFFS_OP_C_UPDT      (1<<2)
+#define SPIFFS_OP_C_MOVS      (2<<2)
+#define SPIFFS_OP_C_MOVD      (3<<2)
+#define SPIFFS_OP_C_FLSH      (4<<2)
+#define SPIFFS_OP_C_READ      (5<<2)
+#define SPIFFS_OP_C_WRTHRU    (6<<2)
+
+#define SPIFFS_OP_TYPE_MASK (3<<0)
+#define SPIFFS_OP_COM_MASK  (7<<2)
+
+
+// if 0, this page is written to, else clean
+#define SPIFFS_PH_FLAG_USED   (1<<0)
+// if 0, writing is finalized, else under modification
+#define SPIFFS_PH_FLAG_FINAL  (1<<1)
+// if 0, this is an index page, else a data page
+#define SPIFFS_PH_FLAG_INDEX  (1<<2)
+// if 0, page is deleted, else valid
+#define SPIFFS_PH_FLAG_DELET  (1<<7)
+// if 0, this index header is being deleted
+#define SPIFFS_PH_FLAG_IXDELE (1<<6)
+
+
+#define SPIFFS_CHECK_MOUNT(fs) \
+  ((fs)->block_count > 0)
+
+#define SPIFFS_CHECK_RES(res) \
+  do { \
+    if ((res) < SPIFFS_OK) return (res); \
+  } while (0);
+
+#define SPIFFS_API_CHECK_MOUNT(fs) \
+  if (!SPIFFS_CHECK_MOUNT((fs))) { \
+    (fs)->err_code = SPIFFS_ERR_NOT_MOUNTED; \
+    return -1; \
+  }
+
+#define SPIFFS_API_CHECK_RES(fs, res) \
+  if ((res) < SPIFFS_OK) { \
+    (fs)->err_code = (res); \
+    return -1; \
+  }
+
+#define SPIFFS_API_CHECK_RES_UNLOCK(fs, res) \
+  if ((res) < SPIFFS_OK) { \
+    (fs)->err_code = (res); \
+    SPIFFS_UNLOCK(fs); \
+    return -1; \
+  }
+
+#define SPIFFS_VALIDATE_OBJIX(ph, objid, spix) \
+    if (((ph).flags & SPIFFS_PH_FLAG_USED) != 0) return SPIFFS_ERR_IS_FREE; \
+    if (((ph).flags & SPIFFS_PH_FLAG_DELET) == 0) return SPIFFS_ERR_DELETED; \
+    if (((ph).flags & SPIFFS_PH_FLAG_FINAL) != 0) return SPIFFS_ERR_NOT_FINALIZED; \
+    if (((ph).flags & SPIFFS_PH_FLAG_INDEX) != 0) return SPIFFS_ERR_NOT_INDEX; \
+    if (((objid) & SPIFFS_OBJ_ID_IX_FLAG) == 0) return SPIFFS_ERR_NOT_INDEX; \
+    if ((ph).span_ix != (spix)) return SPIFFS_ERR_INDEX_SPAN_MISMATCH;
+    //if ((spix) == 0 && ((ph).flags & SPIFFS_PH_FLAG_IXDELE) == 0) return SPIFFS_ERR_DELETED;
+
+#define SPIFFS_VALIDATE_DATA(ph, objid, spix) \
+    if (((ph).flags & SPIFFS_PH_FLAG_USED) != 0) return SPIFFS_ERR_IS_FREE; \
+    if (((ph).flags & SPIFFS_PH_FLAG_DELET) == 0) return SPIFFS_ERR_DELETED; \
+    if (((ph).flags & SPIFFS_PH_FLAG_FINAL) != 0) return SPIFFS_ERR_NOT_FINALIZED; \
+    if (((ph).flags & SPIFFS_PH_FLAG_INDEX) == 0) return SPIFFS_ERR_IS_INDEX; \
+    if ((objid) & SPIFFS_OBJ_ID_IX_FLAG) return SPIFFS_ERR_IS_INDEX; \
+    if ((ph).span_ix != (spix)) return SPIFFS_ERR_DATA_SPAN_MISMATCH;
+
+
+// check id
+#define SPIFFS_VIS_CHECK_ID     (1<<0)
+// report argument object id to visitor - else object lookup id is reported
+#define SPIFFS_VIS_CHECK_PH     (1<<1)
+// stop searching at end of all look up pages
+#define SPIFFS_VIS_NO_WRAP      (1<<2)
+
+#if SPIFFS_CACHE
+
+#define SPIFFS_CACHE_FLAG_DIRTY       (1<<0)
+#define SPIFFS_CACHE_FLAG_WRTHRU      (1<<1)
+#define SPIFFS_CACHE_FLAG_OBJLU       (1<<2)
+#define SPIFFS_CACHE_FLAG_OBJIX       (1<<3)
+#define SPIFFS_CACHE_FLAG_DATA        (1<<4)
+#define SPIFFS_CACHE_FLAG_TYPE_WR     (1<<7)
+
+#define SPIFFS_CACHE_PAGE_SIZE(fs) \
+  (sizeof(spiffs_cache_page) + SPIFFS_CFG_LOG_PAGE_SZ(fs))
+
+#define spiffs_get_cache(fs) \
+  ((spiffs_cache *)((fs)->cache))
+
+#define spiffs_get_cache_page_hdr(fs, c, ix) \
+  ((spiffs_cache_page *)(&((c)->cpages[(ix) * SPIFFS_CACHE_PAGE_SIZE(fs)])))
+
+#define spiffs_get_cache_page(fs, c, ix) \
+  ((u8_t *)(&((c)->cpages[(ix) * SPIFFS_CACHE_PAGE_SIZE(fs)])) + sizeof(spiffs_cache_page))
+
+// cache page struct
+typedef struct {
+  // cache flags
+  u8_t flags;
+  // cache page index
+  u8_t ix;
+  // last access of this cache page
+  u32_t last_access;
+  union {
+    // type read cache
+    struct {
+      // read cache page index
+      spiffs_page_ix pix;
+    };
+#if SPIFFS_CACHE_WR
+    // type write cache
+    struct {
+      // write cache
+      spiffs_obj_id obj_id;
+      // offset in cache page
+      u32_t offset;
+      // size of cache page
+      u16_t size;
+    };
+#endif
+  };
+} spiffs_cache_page;
+
+// cache struct
+typedef struct {
+  u8_t cpage_count;
+  u32_t last_access;
+  u32_t cpage_use_map;
+  u32_t cpage_use_mask;
+  u8_t *cpages;
+} spiffs_cache;
+
+#endif
+
+
+// spiffs nucleus file descriptor
+typedef struct {
+  // the filesystem of this descriptor
+  spiffs *fs;
+  // number of file descriptor - if 0, the file descriptor is closed
+  spiffs_file file_nbr;
+  // object id - if SPIFFS_OBJ_ID_ERASED, the file was deleted
+  spiffs_obj_id obj_id;
+  // size of the file
+  u32_t size;
+  // cached object index header page index
+  spiffs_page_ix objix_hdr_pix;
+  // cached offset object index page index
+  spiffs_page_ix cursor_objix_pix;
+  // cached offset object index span index
+  spiffs_span_ix cursor_objix_spix;
+  // current absolute offset
+  u32_t offset;
+  // current file descriptor offset
+  u32_t fdoffset;
+  // fd flags
+  spiffs_flags flags;
+#if SPIFFS_CACHE_WR
+  spiffs_cache_page *cache_page;
+#endif
+} spiffs_fd;
+
+
+// object structs
+
+// page header, part of each page except object lookup pages
+#ifdef __ICCARM__
+typedef __packed struct {
+#else
+typedef struct __attribute(( packed )) {
+#endif
+  // object id
+  spiffs_obj_id obj_id;
+  // object span index
+  spiffs_span_ix span_ix;
+  // flags
+  u8_t flags;
+} spiffs_page_header;
+
+// object index header page header
+#ifdef __ICCARM__
+typedef __packed struct {
+#else
+typedef struct __attribute(( packed )) {
+#endif
+  // common page header
+  spiffs_page_header p_hdr;
+  // alignment
+  u8_t _align[4 - (sizeof(spiffs_page_header)&3)==0 ? 4 : (sizeof(spiffs_page_header)&3)];
+  // size of object
+  u32_t size;
+  // type of object
+  spiffs_obj_type type;
+  // name of object
+  u8_t name[SPIFFS_OBJ_NAME_LEN];
+} spiffs_page_object_ix_header;
+
+// object index page header
+#ifdef __ICCARM__
+typedef __packed struct {
+#else
+typedef struct __attribute(( packed )) {
+#endif
+ spiffs_page_header p_hdr;
+ u8_t _align[4 - (sizeof(spiffs_page_header)&3)==0 ? 4 : (sizeof(spiffs_page_header)&3)];
+} spiffs_page_object_ix;
+
+// callback func for object lookup visitor
+typedef s32_t (*spiffs_visitor_f)(spiffs *fs, spiffs_obj_id id, spiffs_block_ix bix, int ix_entry,
+    u32_t user_data, void *user_p);
+
+
+#if SPIFFS_CACHE
+#define _spiffs_rd(fs, op, fh, addr, len, dst) \
+    spiffs_phys_rd((fs), (op), (fh), (addr), (len), (dst))
+#define _spiffs_wr(fs, op, fh, addr, len, src) \
+    spiffs_phys_wr((fs), (op), (fh), (addr), (len), (src))
+#else
+#define _spiffs_rd(fs, op, fh, addr, len, dst) \
+    spiffs_phys_rd((fs), (addr), (len), (dst))
+#define _spiffs_wr(fs, op, fh, addr, len, src) \
+    spiffs_phys_wr((fs), (addr), (len), (src))
+#endif
+
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+// ---------------
+
+s32_t spiffs_phys_rd(
+    spiffs *fs,
+#if SPIFFS_CACHE
+    u8_t op,
+    spiffs_file fh,
+#endif
+    u32_t addr,
+    u32_t len,
+    u8_t *dst);
+
+s32_t spiffs_phys_wr(
+    spiffs *fs,
+#if SPIFFS_CACHE
+    u8_t op,
+    spiffs_file fh,
+#endif
+    u32_t addr,
+    u32_t len,
+    u8_t *src);
+
+s32_t spiffs_phys_cpy(
+    spiffs *fs,
+    spiffs_file fh,
+    u32_t dst,
+    u32_t src,
+    u32_t len);
+
+s32_t spiffs_phys_count_free_blocks(
+    spiffs *fs);
+
+s32_t spiffs_obj_lu_find_entry_visitor(
+    spiffs *fs,
+    spiffs_block_ix starting_block,
+    int starting_lu_entry,
+    u8_t flags,
+    spiffs_obj_id obj_id,
+    spiffs_visitor_f v,
+    u32_t user_data,
+    void *user_p,
+    spiffs_block_ix *block_ix,
+    int *lu_entry);
+
+// ---------------
+
+s32_t spiffs_obj_lu_scan(
+    spiffs *fs);
+
+s32_t spiffs_obj_lu_find_free_obj_id(
+    spiffs *fs,
+    spiffs_obj_id *obj_id);
+
+s32_t spiffs_obj_lu_find_free(
+    spiffs *fs,
+    spiffs_block_ix starting_block,
+    int starting_lu_entry,
+    spiffs_block_ix *block_ix,
+    int *lu_entry);
+
+s32_t spiffs_obj_lu_find_id(
+    spiffs *fs,
+    spiffs_block_ix starting_block,
+    int starting_lu_entry,
+    spiffs_obj_id obj_id,
+    spiffs_block_ix *block_ix,
+    int *lu_entry);
+
+s32_t spiffs_obj_lu_find_id_and_span(
+    spiffs *fs,
+    spiffs_obj_id obj_id,
+    spiffs_span_ix spix,
+    spiffs_page_ix exclusion_pix,
+    spiffs_page_ix *pix);
+
+s32_t spiffs_obj_lu_find_id_and_span_by_phdr(
+    spiffs *fs,
+    spiffs_obj_id obj_id,
+    spiffs_span_ix spix,
+    spiffs_page_ix exclusion_pix,
+    spiffs_page_ix *pix);
+
+// ---------------
+
+s32_t spiffs_page_allocate_data(
+    spiffs *fs,
+    spiffs_obj_id obj_id,
+    spiffs_page_header *ph,
+    u8_t *data,
+    u32_t len,
+    u32_t page_offs,
+    u8_t finalize,
+    spiffs_page_ix *pix);
+
+s32_t spiffs_page_move(
+    spiffs *fs,
+    spiffs_file fh,
+    u8_t *page_data,
+    spiffs_obj_id obj_id,
+    spiffs_page_header *page_hdr,
+    spiffs_page_ix src_pix,
+    spiffs_page_ix *dst_pix);
+
+s32_t spiffs_page_delete(
+    spiffs *fs,
+    spiffs_page_ix pix);
+
+// ---------------
+
+s32_t spiffs_object_create(
+    spiffs *fs,
+    spiffs_obj_id obj_id,
+    u8_t name[SPIFFS_OBJ_NAME_LEN],
+    spiffs_obj_type type,
+    spiffs_page_ix *objix_hdr_pix);
+
+s32_t spiffs_object_update_index_hdr(
+    spiffs *fs,
+    spiffs_fd *fd,
+    spiffs_obj_id obj_id,
+    spiffs_page_ix objix_hdr_pix,
+    u8_t *new_objix_hdr_data,
+    u8_t name[SPIFFS_OBJ_NAME_LEN],
+    u32_t size,
+    spiffs_page_ix *new_pix);
+
+void spiffs_cb_object_event(
+    spiffs *fs,
+    spiffs_fd *fd,
+    int ev,
+    spiffs_obj_id obj_id,
+    spiffs_span_ix spix,
+    spiffs_page_ix new_pix,
+    u32_t new_size);
+
+s32_t spiffs_object_open_by_id(
+    spiffs *fs,
+    spiffs_obj_id obj_id,
+    spiffs_fd *f,
+    spiffs_flags flags,
+    spiffs_mode mode);
+
+s32_t spiffs_object_open_by_page(
+    spiffs *fs,
+    spiffs_page_ix pix,
+    spiffs_fd *f,
+    spiffs_flags flags,
+    spiffs_mode mode);
+
+s32_t spiffs_object_append(
+    spiffs_fd *fd,
+    u32_t offset,
+    u8_t *data,
+    u32_t len);
+
+s32_t spiffs_object_modify(
+    spiffs_fd *fd,
+    u32_t offset,
+    u8_t *data,
+    u32_t len);
+
+s32_t spiffs_object_read(
+    spiffs_fd *fd,
+    u32_t offset,
+    u32_t len,
+    u8_t *dst);
+
+s32_t spiffs_object_truncate(
+    spiffs_fd *fd,
+    u32_t new_len,
+    u8_t remove_object);
+
+s32_t spiffs_object_find_object_index_header_by_name(
+    spiffs *fs,
+    u8_t name[SPIFFS_OBJ_NAME_LEN],
+    spiffs_page_ix *pix);
+
+// ---------------
+
+s32_t spiffs_gc_check(
+    spiffs *fs,
+    u32_t len);
+
+s32_t spiffs_gc_erase_page_stats(
+    spiffs *fs,
+    spiffs_block_ix bix);
+
+s32_t spiffs_gc_find_candidate(
+    spiffs *fs,
+    spiffs_block_ix **block_candidate,
+    int *candidate_count);
+
+s32_t spiffs_gc_clean(
+    spiffs *fs,
+    spiffs_block_ix bix);
+
+s32_t spiffs_gc_quick(
+    spiffs *fs);
+
+// ---------------
+
+s32_t spiffs_fd_find_new(
+    spiffs *fs,
+    spiffs_fd **fd);
+
+s32_t spiffs_fd_return(
+    spiffs *fs,
+    spiffs_file f);
+
+s32_t spiffs_fd_get(
+    spiffs *fs,
+    spiffs_file f,
+    spiffs_fd **fd);
+
+#if SPIFFS_CACHE
+void spiffs_cache_init(
+    spiffs *fs);
+
+void spiffs_cache_drop_page(
+    spiffs *fs,
+    spiffs_page_ix pix);
+
+#if SPIFFS_CACHE_WR
+spiffs_cache_page *spiffs_cache_page_allocate_by_fd(
+    spiffs *fs,
+    spiffs_fd *fd);
+
+void spiffs_cache_fd_release(
+    spiffs *fs,
+    spiffs_cache_page *cp);
+
+spiffs_cache_page *spiffs_cache_page_get_by_fd(
+    spiffs *fs,
+    spiffs_fd *fd);
+#endif
+#endif
+
+s32_t spiffs_lookup_consistency_check(
+    spiffs *fs,
+    u8_t check_all_objects);
+
+s32_t spiffs_page_consistency_check(
+    spiffs *fs);
+
+s32_t spiffs_object_index_consistency_check(
+    spiffs *fs);
+
+#endif /* SPIFFS_NUCLEUS_H_ */