asd

Dependencies:   DHT libmDot ISL29011

Files at this revision

API Documentation at this revision

Comitter:
hooony
Date:
Mon Mar 27 09:43:43 2017 +0000
Commit message:
asd

Changed in this revision

.hgignore Show annotated file Show diff for this revision Revisions of this file
DHT.lib Show annotated file Show diff for this revision Revisions of this file
examples/example_config.h Show annotated file Show diff for this revision Revisions of this file
examples/inc/RadioEvent.h Show annotated file Show diff for this revision Revisions of this file
examples/inc/dot_util.h Show annotated file Show diff for this revision Revisions of this file
examples/lib/ISL29011.lib Show annotated file Show diff for this revision Revisions of this file
examples/src/auto_ota_example.cpp Show annotated file Show diff for this revision Revisions of this file
examples/src/class_c_example.cpp Show annotated file Show diff for this revision Revisions of this file
examples/src/dot_util.cpp Show annotated file Show diff for this revision Revisions of this file
examples/src/manual_example.cpp Show annotated file Show diff for this revision Revisions of this file
examples/src/ota_example.cpp Show annotated file Show diff for this revision Revisions of this file
examples/src/peer_to_peer_example.cpp Show annotated file Show diff for this revision Revisions of this file
libmDot.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore	Mon Mar 27 09:43:43 2017 +0000
@@ -0,0 +1,4 @@
+mbed-os
+.build
+/mdot/
+/mdot-library/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DHT.lib	Mon Mar 27 09:43:43 2017 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/Wimpie/code/DHT/#9b5b3200688f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/example_config.h	Mon Mar 27 09:43:43 2017 +0000
@@ -0,0 +1,13 @@
+#ifndef __EXAMPLE__CONFIG_H__
+#define __EXAMPLE__CONFIG_H__
+
+#define OTA_EXAMPLE              1  // see ota_example.cpp
+#define AUTO_OTA_EXAMPLE         2  // see auto_ota_example.cpp
+#define MANUAL_EXAMPLE           3  // see manual_example.cpp
+#define PEER_TO_PEER_EXAMPLE     4  // see peer_to_peer_example.cpp
+#define CLASS_C_EXAMPLE          5  // see class_c_example.cpp
+
+// the active example is the one that will be compiled
+#define ACTIVE_EXAMPLE  OTA_EXAMPLE
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/inc/RadioEvent.h	Mon Mar 27 09:43:43 2017 +0000
@@ -0,0 +1,78 @@
+#ifndef __RADIO_EVENT_H__
+#define __RADIO_EVENT_H__
+
+#include "dot_util.h"
+#include "mDotEvent.h"
+
+class RadioEvent : public mDotEvent
+{
+ 
+public:
+    RadioEvent() {}
+ 
+    virtual ~RadioEvent() {}
+ 
+    /*!
+     * 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) {
+ 
+        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);
+        }
+ 
+        if (flags->Bits.Rx) {
+            
+            logDebug("Rx %d bytes", info->RxBufferSize);
+            if (info->RxBufferSize > 0) {
+                // print RX data as hexadecimal
+                //printf("Rx data: %s\r\n", mts::Text::bin2hexString(info->RxBuffer, info->RxBufferSize).c_str());
+
+                // print RX data as string
+                std::string rx((const char*)info->RxBuffer, info->RxBufferSize);
+                printf("Rx data: %s\r\n", rx.c_str());
+            }
+        }
+    }
+};
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/inc/dot_util.h	Mon Mar 27 09:43:43 2017 +0000
@@ -0,0 +1,41 @@
+#ifndef __DOT_UTIL_H__
+#define __DOT_UTIL_H__
+
+#include "mbed.h"
+#include "mDot.h"
+#include "MTSLog.h"
+#include "MTSText.h"
+#include "ISL29011.h"
+#include "example_config.h"
+
+extern mDot* dot;
+
+void display_config();
+
+void update_ota_config_name_phrase(std::string network_name, std::string network_passphrase, uint8_t frequency_sub_band, bool public_network, uint8_t ack);
+
+void update_ota_config_id_key(uint8_t *network_id, uint8_t *network_key, uint8_t frequency_sub_band, bool public_network, uint8_t ack);
+
+void update_manual_config(uint8_t *network_address, uint8_t *network_session_key, uint8_t *data_session_key, uint8_t frequency_sub_band, bool public_network, uint8_t ack);
+
+void update_peer_to_peer_config(uint8_t *network_address, uint8_t *network_session_key, uint8_t *data_session_key, uint32_t tx_frequency, uint8_t tx_datarate, uint8_t tx_power);
+
+void update_network_link_check_config(uint8_t link_check_count, uint8_t link_check_threshold);
+
+void join_network();
+
+void sleep_wake_rtc_only(bool deepsleep);
+
+void sleep_wake_interrupt_only(bool deepsleep);
+
+void sleep_wake_rtc_or_interrupt(bool deepsleep);
+
+void sleep_save_io();
+
+void sleep_configure_io();
+
+void sleep_restore_io();
+
+void send_data(std::vector<uint8_t> data);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/lib/ISL29011.lib	Mon Mar 27 09:43:43 2017 +0000
@@ -0,0 +1,1 @@
+https://developer.mbed.org/teams/Multi-Hackers/code/ISL29011/#c1d5f4999b9e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/src/auto_ota_example.cpp	Mon Mar 27 09:43:43 2017 +0000
@@ -0,0 +1,148 @@
+#include "dot_util.h"
+#include "RadioEvent.h"
+ 
+#if ACTIVE_EXAMPLE == AUTO_OTA_EXAMPLE
+
+/////////////////////////////////////////////////////////////////////////////
+// -------------------- DOT LIBRARY REQUIRED ------------------------------//
+// * Because these example programs can be used for both mDot and xDot     //
+//     devices, the LoRa stack is not included. The libmDot library should //
+//     be imported if building for mDot devices. The libxDot library       //
+//     should be imported if building for xDot devices.                    //
+// * https://developer.mbed.org/teams/MultiTech/code/libmDot-dev-mbed5/    //
+// * https://developer.mbed.org/teams/MultiTech/code/libmDot-mbed5/        //
+// * https://developer.mbed.org/teams/MultiTech/code/libxDot-dev-mbed5/    //
+// * https://developer.mbed.org/teams/MultiTech/code/libxDot-mbed5/        //
+/////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////
+// * these options must match the settings on your gateway //
+// * edit their values to match your configuration         //
+// * frequency sub band is only relevant for the 915 bands //
+// * either the network name and passphrase can be used or //
+//     the network ID (8 bytes) and KEY (16 bytes)         //
+/////////////////////////////////////////////////////////////
+static std::string network_name = "MultiTech";
+static std::string network_passphrase = "MultiTech";
+static uint8_t network_id[] = { 0x6C, 0x4E, 0xEF, 0x66, 0xF4, 0x79, 0x86, 0xA6 };
+static uint8_t network_key[] = { 0x1F, 0x33, 0xA1, 0x70, 0xA5, 0xF1, 0xFD, 0xA0, 0xAB, 0x69, 0x7A, 0xAE, 0x2B, 0x95, 0x91, 0x6B };
+static uint8_t frequency_sub_band = 0;
+static bool public_network = false;
+static uint8_t ack = 0;
+
+// deepsleep consumes slightly less current than sleep
+// in sleep mode, IO state is maintained, RAM is retained, and application will resume after waking up
+// in deepsleep mode, IOs float, RAM is lost, and application will start from beginning after waking up
+// if deep_sleep == true, device will enter deepsleep mode
+static bool deep_sleep = true;
+
+mDot* dot = NULL;
+
+Serial pc(USBTX, USBRX);
+
+#if defined(TARGET_XDOT_L151CC)
+I2C i2c(I2C_SDA, I2C_SCL);
+ISL29011 lux(i2c);
+#else
+AnalogIn lux(XBEE_AD0);
+#endif
+
+int main() {
+    // Custom event handler for automatically displaying RX data
+    RadioEvent events;
+
+    pc.baud(115200);
+
+    mts::MTSLog::setLogLevel(mts::MTSLog::TRACE_LEVEL);
+    
+    dot = mDot::getInstance();
+
+    // attach the custom events handler
+    dot->setEvents(&events);
+
+    if (!dot->getStandbyFlag()) {
+        logInfo("mbed-os library version: %d", MBED_LIBRARY_VERSION);
+
+        // start from a well-known state
+        logInfo("defaulting Dot configuration");
+        dot->resetConfig();
+        dot->resetNetworkSession();
+
+        // make sure library logging is turned on
+        dot->setLogLevel(mts::MTSLog::INFO_LEVEL);
+
+        // update configuration if necessary
+        // in AUTO_OTA mode the session is automatically saved, so saveNetworkSession and restoreNetworkSession are not needed
+        if (dot->getJoinMode() != mDot::AUTO_OTA) {
+            logInfo("changing network join mode to AUTO_OTA");
+            if (dot->setJoinMode(mDot::AUTO_OTA) != mDot::MDOT_OK) {
+                logError("failed to set network join mode to AUTO_OTA");
+            }
+        }
+        // in OTA and AUTO_OTA join modes, the credentials can be passed to the library as a name and passphrase or an ID and KEY
+        // only one method or the other should be used!
+        // network ID = crc64(network name)
+        // network KEY = cmac(network passphrase)
+        update_ota_config_name_phrase(network_name, network_passphrase, frequency_sub_band, public_network, ack);
+        //update_ota_config_id_key(network_id, network_key, frequency_sub_band, public_network, ack);
+    
+        // configure network link checks
+        // network link checks are a good alternative to requiring the gateway to ACK every packet and should allow a single gateway to handle more Dots
+        // check the link every count packets
+        // declare the Dot disconnected after threshold failed link checks
+        // for count = 3 and threshold = 5, the Dot will be considered disconnected after 15 missed packets in a row
+        update_network_link_check_config(3, 5);
+
+        // save changes to configuration
+        logInfo("saving configuration");
+        if (!dot->saveConfig()) {
+            logError("failed to save configuration");
+        }
+    
+        // display configuration
+        display_config();
+    }
+
+    while (true) {
+        uint16_t light;
+        std::vector<uint8_t> tx_data;
+
+        // join network if not joined
+        if (!dot->getNetworkJoinStatus()) {
+            join_network();
+        }
+
+#if defined(TARGET_XDOT_L151CC)
+        // configure the ISL29011 sensor on the xDot-DK for continuous ambient light sampling, 16 bit conversion, and maximum range
+        lux.setMode(ISL29011::ALS_CONT);
+        lux.setResolution(ISL29011::ADC_16BIT);
+        lux.setRange(ISL29011::RNG_64000);
+
+        // get the latest light sample and send it to the gateway
+        light = lux.getData();
+        tx_data.push_back((light >> 8) & 0xFF);
+        tx_data.push_back(light & 0xFF);
+        logInfo("light: %lu [0x%04X]", light, light);
+        send_data(tx_data);
+
+        // put the LSL29011 ambient light sensor into a low power state
+        lux.setMode(ISL29011::PWR_DOWN);
+#else 
+        // get some dummy data and send it to the gateway
+        light = lux.read_u16();
+        tx_data.push_back((light >> 8) & 0xFF);
+        tx_data.push_back(light & 0xFF);
+        logInfo("light: %lu [0x%04X]", light, light);
+        send_data(tx_data);
+#endif
+
+        // ONLY ONE of the three functions below should be uncommented depending on the desired wakeup method
+        //sleep_wake_rtc_only(deep_sleep);
+        //sleep_wake_interrupt_only(deep_sleep);
+        sleep_wake_rtc_or_interrupt(deep_sleep);
+    }
+ 
+    return 0;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/src/class_c_example.cpp	Mon Mar 27 09:43:43 2017 +0000
@@ -0,0 +1,142 @@
+#include "dot_util.h"
+#include "RadioEvent.h"
+ 
+#if ACTIVE_EXAMPLE == CLASS_C_EXAMPLE
+
+/////////////////////////////////////////////////////////////////////////////
+// -------------------- DOT LIBRARY REQUIRED ------------------------------//
+// * Because these example programs can be used for both mDot and xDot     //
+//     devices, the LoRa stack is not included. The libmDot library should //
+//     be imported if building for mDot devices. The libxDot library       //
+//     should be imported if building for xDot devices.                    //
+// * https://developer.mbed.org/teams/MultiTech/code/libmDot-dev-mbed5/    //
+// * https://developer.mbed.org/teams/MultiTech/code/libmDot-mbed5/        //
+// * https://developer.mbed.org/teams/MultiTech/code/libxDot-dev-mbed5/    //
+// * https://developer.mbed.org/teams/MultiTech/code/libxDot-mbed5/        //
+/////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////
+// * these options must match the settings on your gateway //
+// * edit their values to match your configuration         //
+// * frequency sub band is only relevant for the 915 bands //
+// * either the network name and passphrase can be used or //
+//     the network ID (8 bytes) and KEY (16 bytes)         //
+/////////////////////////////////////////////////////////////
+static std::string network_name = "MultiTech";
+static std::string network_passphrase = "MultiTech";
+static uint8_t network_id[] = { 0x6C, 0x4E, 0xEF, 0x66, 0xF4, 0x79, 0x86, 0xA6 };
+static uint8_t network_key[] = { 0x1F, 0x33, 0xA1, 0x70, 0xA5, 0xF1, 0xFD, 0xA0, 0xAB, 0x69, 0x7A, 0xAE, 0x2B, 0x95, 0x91, 0x6B };
+static uint8_t frequency_sub_band = 0;
+static bool public_network = false;
+static uint8_t ack = 1;
+
+mDot* dot = NULL;
+
+Serial pc(USBTX, USBRX);
+
+#if defined(TARGET_XDOT_L151CC)
+I2C i2c(I2C_SDA, I2C_SCL);
+ISL29011 lux(i2c);
+#else
+AnalogIn lux(XBEE_AD0);
+#endif
+
+int main() {
+    // Custom event handler for automatically displaying RX data
+    RadioEvent events;
+
+    pc.baud(115200);
+
+    mts::MTSLog::setLogLevel(mts::MTSLog::TRACE_LEVEL);
+    
+    dot = mDot::getInstance();
+
+    logInfo("mbed-os library version: %d", MBED_LIBRARY_VERSION);
+
+    // start from a well-known state
+    logInfo("defaulting Dot configuration");
+    dot->resetConfig();
+    dot->resetNetworkSession();
+
+        // make sure library logging is turned on
+    dot->setLogLevel(mts::MTSLog::INFO_LEVEL);
+
+    // attach the custom events handler
+    dot->setEvents(&events);
+
+    // update configuration if necessary
+    if (dot->getJoinMode() != mDot::OTA) {
+        logInfo("changing network join mode to OTA");
+        if (dot->setJoinMode(mDot::OTA) != mDot::MDOT_OK) {
+            logError("failed to set network join mode to OTA");
+        }
+    }
+    // in OTA and AUTO_OTA join modes, the credentials can be passed to the library as a name and passphrase or an ID and KEY
+    // only one method or the other should be used!
+    // network ID = crc64(network name)
+    // network KEY = cmac(network passphrase)
+    update_ota_config_name_phrase(network_name, network_passphrase, frequency_sub_band, public_network, ack);
+    //update_ota_config_id_key(network_id, network_key, frequency_sub_band, public_network, ack);
+
+    // configure the Dot for class C operation
+    // the Dot must also be configured on the gateway for class C
+    // use the lora-query application to do this on a Conduit: http://www.multitech.net/developer/software/lora/lora-network-server/
+    // to provision your Dot for class C operation with a 3rd party gateway, see the gateway or network provider documentation
+    logInfo("changing network mode to class C");
+    if (dot->setClass("C") != mDot::MDOT_OK) {
+        logError("failed to set network mode to class C");
+    }
+    
+    // save changes to configuration
+    logInfo("saving configuration");
+    if (!dot->saveConfig()) {
+        logError("failed to save configuration");
+    }
+
+    // display configuration
+    display_config();
+
+#if defined(TARGET_XDOT_L151CC)
+    // configure the ISL29011 sensor on the xDot-DK for continuous ambient light sampling, 16 bit conversion, and maximum range
+    lux.setMode(ISL29011::ALS_CONT);
+    lux.setResolution(ISL29011::ADC_16BIT);
+    lux.setRange(ISL29011::RNG_64000);
+#endif 
+
+    while (true) {
+        uint16_t light;
+        std::vector<uint8_t> tx_data;
+
+        // join network if not joined
+        if (!dot->getNetworkJoinStatus()) {
+            join_network();
+        }
+
+#if defined(TARGET_XDOT_L151CC)
+        // get the latest light sample and send it to the gateway
+        light = lux.getData();
+        tx_data.push_back((light >> 8) & 0xFF);
+        tx_data.push_back(light & 0xFF);
+        logInfo("light: %lu [0x%04X]", light, light);
+        send_data(tx_data);
+#else 
+        // get some dummy data and send it to the gateway
+        light = lux.read_u16();
+        tx_data.push_back((light >> 8) & 0xFF);
+        tx_data.push_back(light & 0xFF);
+        logInfo("light: %lu [0x%04X]", light, light);
+        send_data(tx_data);
+#endif
+
+        // the Dot can't sleep in class C mode
+        // it must be waiting for data from the gateway
+        // send data every 30s
+        logInfo("waiting for 30s");
+        wait(30);
+    }
+ 
+    return 0;
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/src/dot_util.cpp	Mon Mar 27 09:43:43 2017 +0000
@@ -0,0 +1,703 @@
+#include "dot_util.h"
+#if defined(TARGET_XDOT_L151CC)
+#include "xdot_low_power.h"
+#endif
+
+#if defined(TARGET_MTS_MDOT_F411RE)
+uint32_t portA[6];
+uint32_t portB[6];
+uint32_t portC[6];
+uint32_t portD[6];
+uint32_t portH[6];
+#endif
+
+
+void display_config() {
+    // display configuration and library version information
+    logInfo("=====================");
+    logInfo("general configuration");
+    logInfo("=====================");
+    logInfo("version ------------------ %s", dot->getId().c_str());
+    logInfo("device ID/EUI ------------ %s", mts::Text::bin2hexString(dot->getDeviceId()).c_str());
+    logInfo("frequency band ----------- %s", mDot::FrequencyBandStr(dot->getFrequencyBand()).c_str());
+    if (dot->getFrequencySubBand() != mDot::FB_EU868) {
+        logInfo("frequency sub band ------- %u", dot->getFrequencySubBand());
+    }
+    logInfo("public network ----------- %s", dot->getPublicNetwork() ? "on" : "off");
+    logInfo("=========================");
+    logInfo("credentials configuration");
+    logInfo("=========================");
+    logInfo("device class ------------- %s", dot->getClass().c_str());
+    logInfo("network join mode -------- %s", mDot::JoinModeStr(dot->getJoinMode()).c_str());
+    if (dot->getJoinMode() == mDot::MANUAL || dot->getJoinMode() == mDot::PEER_TO_PEER) {
+	logInfo("network address ---------- %s", mts::Text::bin2hexString(dot->getNetworkAddress()).c_str());
+	logInfo("network session key------- %s", mts::Text::bin2hexString(dot->getNetworkSessionKey()).c_str());
+	logInfo("data session key---------- %s", mts::Text::bin2hexString(dot->getDataSessionKey()).c_str());
+    } else {
+	logInfo("network name ------------- %s", dot->getNetworkName().c_str());
+	logInfo("network phrase ----------- %s", dot->getNetworkPassphrase().c_str());
+	logInfo("network EUI -------------- %s", mts::Text::bin2hexString(dot->getNetworkId()).c_str());
+	logInfo("network KEY -------------- %s", mts::Text::bin2hexString(dot->getNetworkKey()).c_str());
+    }
+    logInfo("========================");
+    logInfo("communication parameters");
+    logInfo("========================");
+    if (dot->getJoinMode() == mDot::PEER_TO_PEER) {
+	logInfo("TX frequency ------------- %lu", dot->getTxFrequency());
+    } else {
+	logInfo("acks --------------------- %s, %u attempts", dot->getAck() > 0 ? "on" : "off", dot->getAck());
+    }
+    logInfo("TX datarate -------------- %s", mDot::DataRateStr(dot->getTxDataRate()).c_str());
+    logInfo("TX power ----------------- %lu dBm", dot->getTxPower());
+    logInfo("atnenna gain ------------- %u dBm", dot->getAntennaGain());
+}
+
+void update_ota_config_name_phrase(std::string network_name, std::string network_passphrase, uint8_t frequency_sub_band, bool public_network, uint8_t ack) {
+    std::string current_network_name = dot->getNetworkName();
+    std::string current_network_passphrase = dot->getNetworkPassphrase();
+    uint8_t current_frequency_sub_band = dot->getFrequencySubBand();
+    bool current_public_network = dot->getPublicNetwork();
+    uint8_t current_ack = dot->getAck();
+    
+    if (current_network_name != network_name) {
+        logInfo("changing network name from \"%s\" to \"%s\"", current_network_name.c_str(), network_name.c_str());
+        if (dot->setNetworkName(network_name) != mDot::MDOT_OK) {
+            logError("failed to set network name to \"%s\"", network_name.c_str());
+        }
+    }
+    
+    if (current_network_passphrase != network_passphrase) {
+        logInfo("changing network passphrase from \"%s\" to \"%s\"", current_network_passphrase.c_str(), network_passphrase.c_str());
+        if (dot->setNetworkPassphrase(network_passphrase) != mDot::MDOT_OK) {
+            logError("failed to set network passphrase to \"%s\"", network_passphrase.c_str());
+        }
+    }
+    
+    if (current_frequency_sub_band != frequency_sub_band) {
+        logInfo("changing frequency sub band from %u to %u", current_frequency_sub_band, frequency_sub_band);
+        if (dot->setFrequencySubBand(frequency_sub_band) != mDot::MDOT_OK) {
+            logError("failed to set frequency sub band to %u", frequency_sub_band);
+        }
+    }
+    
+    if (current_public_network != public_network) {
+        logInfo("changing public network from %s to %s", current_public_network ? "on" : "off", public_network ? "on" : "off");
+        if (dot->setPublicNetwork(public_network) != mDot::MDOT_OK) {
+            logError("failed to set public network to %s", public_network ? "on" : "off");
+        }
+    }
+    
+    if (current_ack != ack) {
+        logInfo("changing acks from %u to %u", current_ack, ack);
+        if (dot->setAck(ack) != mDot::MDOT_OK) {
+            logError("failed to set acks to %u", ack);
+        }
+    }
+}
+
+void update_ota_config_id_key(uint8_t *network_id, uint8_t *network_key, uint8_t frequency_sub_band, bool public_network, uint8_t ack) {
+    std::vector<uint8_t> current_network_id = dot->getNetworkId();
+    std::vector<uint8_t> current_network_key = dot->getNetworkKey();
+    uint8_t current_frequency_sub_band = dot->getFrequencySubBand();
+    bool current_public_network = dot->getPublicNetwork();
+    uint8_t current_ack = dot->getAck();
+
+    std::vector<uint8_t> network_id_vector(network_id, network_id + 8);
+    std::vector<uint8_t> network_key_vector(network_key, network_key + 16);
+    
+    if (current_network_id != network_id_vector) {
+        logInfo("changing network ID from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_id).c_str(), mts::Text::bin2hexString(network_id_vector).c_str());
+        if (dot->setNetworkId(network_id_vector) != mDot::MDOT_OK) {
+            logError("failed to set network ID to \"%s\"", mts::Text::bin2hexString(network_id_vector).c_str());
+        }
+    }
+    
+    if (current_network_key != network_key_vector) {
+        logInfo("changing network KEY from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_key).c_str(), mts::Text::bin2hexString(network_key_vector).c_str());
+        if (dot->setNetworkKey(network_key_vector) != mDot::MDOT_OK) {
+            logError("failed to set network KEY to \"%s\"", mts::Text::bin2hexString(network_key_vector).c_str());
+        }
+    }
+    
+    if (current_frequency_sub_band != frequency_sub_band) {
+        logInfo("changing frequency sub band from %u to %u", current_frequency_sub_band, frequency_sub_band);
+        if (dot->setFrequencySubBand(frequency_sub_band) != mDot::MDOT_OK) {
+            logError("failed to set frequency sub band to %u", frequency_sub_band);
+        }
+    }
+    
+    if (current_public_network != public_network) {
+        logInfo("changing public network from %s to %s", current_public_network ? "on" : "off", public_network ? "on" : "off");
+        if (dot->setPublicNetwork(public_network) != mDot::MDOT_OK) {
+            logError("failed to set public network to %s", public_network ? "on" : "off");
+        }
+    }
+    
+    if (current_ack != ack) {
+        logInfo("changing acks from %u to %u", current_ack, ack);
+        if (dot->setAck(ack) != mDot::MDOT_OK) {
+            logError("failed to set acks to %u", ack);
+        }
+    }
+}
+
+void update_manual_config(uint8_t *network_address, uint8_t *network_session_key, uint8_t *data_session_key, uint8_t frequency_sub_band, bool public_network, uint8_t ack) {
+    std::vector<uint8_t> current_network_address = dot->getNetworkAddress();
+    std::vector<uint8_t> current_network_session_key = dot->getNetworkSessionKey();
+    std::vector<uint8_t> current_data_session_key = dot->getDataSessionKey();
+    uint8_t current_frequency_sub_band = dot->getFrequencySubBand();
+    bool current_public_network = dot->getPublicNetwork();
+    uint8_t current_ack = dot->getAck();
+
+    std::vector<uint8_t> network_address_vector(network_address, network_address + 4);
+    std::vector<uint8_t> network_session_key_vector(network_session_key, network_session_key + 16);
+    std::vector<uint8_t> data_session_key_vector(data_session_key, data_session_key + 16);
+
+    if (current_network_address != network_address_vector) {
+        logInfo("changing network address from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_address).c_str(), mts::Text::bin2hexString(network_address_vector).c_str());
+        if (dot->setNetworkAddress(network_address_vector) != mDot::MDOT_OK) {
+            logError("failed to set network address to \"%s\"", mts::Text::bin2hexString(network_address_vector).c_str());
+        }
+    }
+    
+    if (current_network_session_key != network_session_key_vector) {
+        logInfo("changing network session key from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_session_key).c_str(), mts::Text::bin2hexString(network_session_key_vector).c_str());
+        if (dot->setNetworkSessionKey(network_session_key_vector) != mDot::MDOT_OK) {
+            logError("failed to set network session key to \"%s\"", mts::Text::bin2hexString(network_session_key_vector).c_str());
+        }
+    }
+    
+    if (current_data_session_key != data_session_key_vector) {
+        logInfo("changing data session key from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_data_session_key).c_str(), mts::Text::bin2hexString(data_session_key_vector).c_str());
+        if (dot->setDataSessionKey(data_session_key_vector) != mDot::MDOT_OK) {
+            logError("failed to set data session key to \"%s\"", mts::Text::bin2hexString(data_session_key_vector).c_str());
+        }
+    }
+    
+    if (current_frequency_sub_band != frequency_sub_band) {
+        logInfo("changing frequency sub band from %u to %u", current_frequency_sub_band, frequency_sub_band);
+        if (dot->setFrequencySubBand(frequency_sub_band) != mDot::MDOT_OK) {
+            logError("failed to set frequency sub band to %u", frequency_sub_band);
+        }
+    }
+    
+    if (current_public_network != public_network) {
+        logInfo("changing public network from %s to %s", current_public_network ? "on" : "off", public_network ? "on" : "off");
+        if (dot->setPublicNetwork(public_network) != mDot::MDOT_OK) {
+            logError("failed to set public network to %s", public_network ? "on" : "off");
+        }
+    }
+    
+    if (current_ack != ack) {
+        logInfo("changing acks from %u to %u", current_ack, ack);
+        if (dot->setAck(ack) != mDot::MDOT_OK) {
+            logError("failed to set acks to %u", ack);
+        }
+    }
+}
+
+void update_peer_to_peer_config(uint8_t *network_address, uint8_t *network_session_key, uint8_t *data_session_key, uint32_t tx_frequency, uint8_t tx_datarate, uint8_t tx_power) {
+    std::vector<uint8_t> current_network_address = dot->getNetworkAddress();
+    std::vector<uint8_t> current_network_session_key = dot->getNetworkSessionKey();
+    std::vector<uint8_t> current_data_session_key = dot->getDataSessionKey();
+    uint32_t current_tx_frequency = dot->getTxFrequency();
+    uint8_t current_tx_datarate = dot->getTxDataRate();
+    uint8_t current_tx_power = dot->getTxPower();
+
+    std::vector<uint8_t> network_address_vector(network_address, network_address + 4);
+    std::vector<uint8_t> network_session_key_vector(network_session_key, network_session_key + 16);
+    std::vector<uint8_t> data_session_key_vector(data_session_key, data_session_key + 16);
+
+    if (current_network_address != network_address_vector) {
+        logInfo("changing network address from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_address).c_str(), mts::Text::bin2hexString(network_address_vector).c_str());
+        if (dot->setNetworkAddress(network_address_vector) != mDot::MDOT_OK) {
+            logError("failed to set network address to \"%s\"", mts::Text::bin2hexString(network_address_vector).c_str());
+        }
+    }
+    
+    if (current_network_session_key != network_session_key_vector) {
+        logInfo("changing network session key from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_session_key).c_str(), mts::Text::bin2hexString(network_session_key_vector).c_str());
+        if (dot->setNetworkSessionKey(network_session_key_vector) != mDot::MDOT_OK) {
+            logError("failed to set network session key to \"%s\"", mts::Text::bin2hexString(network_session_key_vector).c_str());
+        }
+    }
+    
+    if (current_data_session_key != data_session_key_vector) {
+        logInfo("changing data session key from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_data_session_key).c_str(), mts::Text::bin2hexString(data_session_key_vector).c_str());
+        if (dot->setDataSessionKey(data_session_key_vector) != mDot::MDOT_OK) {
+            logError("failed to set data session key to \"%s\"", mts::Text::bin2hexString(data_session_key_vector).c_str());
+        }
+    }
+    
+    if (current_tx_frequency != tx_frequency) {
+	logInfo("changing TX frequency from %lu to %lu", current_tx_frequency, tx_frequency);
+	if (dot->setTxFrequency(tx_frequency) != mDot::MDOT_OK) {
+	    logError("failed to set TX frequency to %lu", tx_frequency);
+	}
+    }
+
+    if (current_tx_datarate != tx_datarate) {
+	logInfo("changing TX datarate from %u to %u", current_tx_datarate, tx_datarate);
+	if (dot->setTxDataRate(tx_datarate) != mDot::MDOT_OK) {
+	    logError("failed to set TX datarate to %u", tx_datarate);
+	}
+    }
+
+    if (current_tx_power != tx_power) {
+	logInfo("changing TX power from %u to %u", current_tx_power, tx_power);
+	if (dot->setTxPower(tx_power) != mDot::MDOT_OK) {
+	    logError("failed to set TX power to %u", tx_power);
+	}
+    }
+}
+
+void update_network_link_check_config(uint8_t link_check_count, uint8_t link_check_threshold) {
+    uint8_t current_link_check_count = dot->getLinkCheckCount();
+    uint8_t current_link_check_threshold = dot->getLinkCheckThreshold();
+
+    if (current_link_check_count != link_check_count) {
+	logInfo("changing link check count from %u to %u", current_link_check_count, link_check_count);
+	if (dot->setLinkCheckCount(link_check_count) != mDot::MDOT_OK) {
+	    logError("failed to set link check count to %u", link_check_count);
+	}
+    }
+
+    if (current_link_check_threshold != link_check_threshold) {
+	logInfo("changing link check threshold from %u to %u", current_link_check_threshold, link_check_threshold);
+	if (dot->setLinkCheckThreshold(link_check_threshold) != mDot::MDOT_OK) {
+	    logError("failed to set link check threshold to %u", link_check_threshold);
+	}
+    }
+}
+
+void join_network() {
+    int32_t j_attempts = 0;
+    int32_t ret = mDot::MDOT_ERROR;
+    
+    // attempt to join the network
+    while (ret != mDot::MDOT_OK) {
+        logInfo("attempt %d to join network", ++j_attempts);
+        ret = dot->joinNetwork();
+        if (ret != mDot::MDOT_OK) {
+            logError("failed to join network %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
+            // in some frequency bands we need to wait until another channel is available before transmitting again
+            uint32_t delay_s = (dot->getNextTxMs() / 1000) + 1;
+            if (delay_s < 2) {
+                logInfo("waiting %lu s until next free channel", delay_s);
+                wait(delay_s);
+            } else {
+                logInfo("sleeping %lu s until next free channel", delay_s);
+                dot->sleep(delay_s, mDot::RTC_ALARM, false);
+            }
+        }
+    }
+}
+
+void sleep_wake_rtc_only(bool deepsleep) {
+    // in some frequency bands we need to wait until another channel is available before transmitting again
+    // wait at least 10s between transmissions
+    uint32_t delay_s = dot->getNextTxMs() / 1000;
+    if (delay_s < 10) {
+        delay_s = 10;
+    }
+    
+    logInfo("%ssleeping %lus", deepsleep ? "deep" : "", delay_s);
+    logInfo("application will %s after waking up", deepsleep ? "execute from beginning" : "resume");
+
+    // lowest current consumption in sleep mode can only be achieved by configuring IOs as analog inputs with no pull resistors
+    // the library handles all internal IOs automatically, but the external IOs are the application's responsibility
+    // certain IOs may require internal pullup or pulldown resistors because leaving them floating would cause extra current consumption
+    // for xDot: UART_*, I2C_*, SPI_*, GPIO*, WAKE
+    // for mDot: XBEE_*, USBTX, USBRX, PB_0, PB_1
+    // steps are:
+    //   * save IO configuration
+    //   * configure IOs to reduce current consumption
+    //   * sleep
+    //   * restore IO configuration
+    if (! deepsleep) {
+	// save the GPIO state.
+	sleep_save_io();
+
+	// configure GPIOs for lowest current
+	sleep_configure_io();
+    }
+    
+    // go to sleep/deepsleep for delay_s seconds and wake using the RTC alarm
+    dot->sleep(delay_s, mDot::RTC_ALARM, deepsleep);
+
+    if (! deepsleep) {
+	// restore the GPIO state.
+	sleep_restore_io();
+    }
+}
+
+void sleep_wake_interrupt_only(bool deepsleep) {
+#if defined (TARGET_XDOT_L151CC)
+    if (deepsleep) {
+        // for xDot, WAKE pin (connected to S2 on xDot-DK) is the only pin that can wake the processor from deepsleep
+        // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call
+    } else {
+        // configure WAKE pin (connected to S2 on xDot-DK) as the pin that will wake the xDot from low power modes
+        //      other pins can be confgured instead: GPIO0-3 or UART_RX
+        dot->setWakePin(WAKE);    
+    }
+
+    logInfo("%ssleeping until interrupt on %s pin", deepsleep ? "deep" : "", deepsleep ? "WAKE" : mDot::pinName2Str(dot->getWakePin()).c_str());
+#else
+
+    if (deepsleep) {
+        // for mDot, XBEE_DIO7 pin is the only pin that can wake the processor from deepsleep
+        // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call
+    } else {
+        // configure XBEE_DIO7 pin as the pin that will wake the mDot from low power modes
+        //      other pins can be confgured instead: XBEE_DIO2-6, XBEE_DI8, XBEE_DIN
+        dot->setWakePin(XBEE_DIO7);    
+    }
+
+    logInfo("%ssleeping until interrupt on %s pin", deepsleep ? "deep" : "", deepsleep ? "DIO7" : mDot::pinName2Str(dot->getWakePin()).c_str());
+#endif
+
+    logInfo("application will %s after waking up", deepsleep ? "execute from beginning" : "resume");
+
+    // lowest current consumption in sleep mode can only be achieved by configuring IOs as analog inputs with no pull resistors
+    // the library handles all internal IOs automatically, but the external IOs are the application's responsibility
+    // certain IOs may require internal pullup or pulldown resistors because leaving them floating would cause extra current consumption
+    // for xDot: UART_*, I2C_*, SPI_*, GPIO*, WAKE
+    // for mDot: XBEE_*, USBTX, USBRX, PB_0, PB_1
+    // steps are:
+    //   * save IO configuration
+    //   * configure IOs to reduce current consumption
+    //   * sleep
+    //   * restore IO configuration
+    if (! deepsleep) {
+	// save the GPIO state.
+	sleep_save_io();
+
+	// configure GPIOs for lowest current
+	sleep_configure_io();
+    }
+    
+    // go to sleep/deepsleep and wake on rising edge of configured wake pin (only the WAKE pin in deepsleep)
+    // since we're not waking on the RTC alarm, the interval is ignored
+    dot->sleep(0, mDot::INTERRUPT, deepsleep);
+
+    if (! deepsleep) {
+	// restore the GPIO state.
+	sleep_restore_io();
+    }
+}
+
+void sleep_wake_rtc_or_interrupt(bool deepsleep) {
+    // in some frequency bands we need to wait until another channel is available before transmitting again
+    // wait at least 10s between transmissions
+    uint32_t delay_s = dot->getNextTxMs() / 1000;
+    if (delay_s < 10) {
+        delay_s = 10;
+    }
+
+#if defined (TARGET_XDOT_L151CC)
+    if (deepsleep) {
+        // for xDot, WAKE pin (connected to S2 on xDot-DK) is the only pin that can wake the processor from deepsleep
+        // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call
+    } else {
+        // configure WAKE pin (connected to S2 on xDot-DK) as the pin that will wake the xDot from low power modes
+        //      other pins can be confgured instead: GPIO0-3 or UART_RX
+        dot->setWakePin(WAKE);    
+    }
+
+    logInfo("%ssleeping %lus or until interrupt on %s pin", deepsleep ? "deep" : "", delay_s, deepsleep ? "WAKE" : mDot::pinName2Str(dot->getWakePin()).c_str());
+#else
+    if (deepsleep) {
+        // for mDot, XBEE_DIO7 pin is the only pin that can wake the processor from deepsleep
+        // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call
+    } else {
+        // configure XBEE_DIO7 pin as the pin that will wake the mDot from low power modes
+        //      other pins can be confgured instead: XBEE_DIO2-6, XBEE_DI8, XBEE_DIN
+        dot->setWakePin(XBEE_DIO7);    
+    }
+
+    logInfo("%ssleeping %lus or until interrupt on %s pin", deepsleep ? "deep" : "", delay_s, deepsleep ? "DIO7" : mDot::pinName2Str(dot->getWakePin()).c_str());
+#endif
+
+    logInfo("application will %s after waking up", deepsleep ? "execute from beginning" : "resume");
+
+    // lowest current consumption in sleep mode can only be achieved by configuring IOs as analog inputs with no pull resistors
+    // the library handles all internal IOs automatically, but the external IOs are the application's responsibility
+    // certain IOs may require internal pullup or pulldown resistors because leaving them floating would cause extra current consumption
+    // for xDot: UART_*, I2C_*, SPI_*, GPIO*, WAKE
+    // for mDot: XBEE_*, USBTX, USBRX, PB_0, PB_1
+    // steps are:
+    //   * save IO configuration
+    //   * configure IOs to reduce current consumption
+    //   * sleep
+    //   * restore IO configuration
+    if (! deepsleep) {
+	// save the GPIO state.
+	sleep_save_io();
+
+	// configure GPIOs for lowest current
+	sleep_configure_io();
+    }
+    
+    // go to sleep/deepsleep and wake using the RTC alarm after delay_s seconds or rising edge of configured wake pin (only the WAKE pin in deepsleep)
+    // whichever comes first will wake the xDot
+    dot->sleep(delay_s, mDot::RTC_ALARM_OR_INTERRUPT, deepsleep);
+
+    if (! deepsleep) {
+	// restore the GPIO state.
+	sleep_restore_io();
+    }
+}
+
+void sleep_save_io() {
+#if defined(TARGET_XDOT_L151CC)
+	xdot_save_gpio_state();
+#else
+	portA[0] = GPIOA->MODER;
+	portA[1] = GPIOA->OTYPER;
+	portA[2] = GPIOA->OSPEEDR;
+	portA[3] = GPIOA->PUPDR;
+	portA[4] = GPIOA->AFR[0];
+	portA[5] = GPIOA->AFR[1];
+
+	portB[0] = GPIOB->MODER;
+	portB[1] = GPIOB->OTYPER;
+	portB[2] = GPIOB->OSPEEDR;
+	portB[3] = GPIOB->PUPDR;
+	portB[4] = GPIOB->AFR[0];
+	portB[5] = GPIOB->AFR[1];
+
+	portC[0] = GPIOC->MODER;
+	portC[1] = GPIOC->OTYPER;
+	portC[2] = GPIOC->OSPEEDR;
+	portC[3] = GPIOC->PUPDR;
+	portC[4] = GPIOC->AFR[0];
+	portC[5] = GPIOC->AFR[1];
+
+	portD[0] = GPIOD->MODER;
+	portD[1] = GPIOD->OTYPER;
+	portD[2] = GPIOD->OSPEEDR;
+	portD[3] = GPIOD->PUPDR;
+	portD[4] = GPIOD->AFR[0];
+	portD[5] = GPIOD->AFR[1];
+
+	portH[0] = GPIOH->MODER;
+	portH[1] = GPIOH->OTYPER;
+	portH[2] = GPIOH->OSPEEDR;
+	portH[3] = GPIOH->PUPDR;
+	portH[4] = GPIOH->AFR[0];
+	portH[5] = GPIOH->AFR[1];
+#endif
+}
+
+void sleep_configure_io() {
+#if defined(TARGET_XDOT_L151CC)
+    // GPIO Ports Clock Enable
+    __GPIOA_CLK_ENABLE();
+    __GPIOB_CLK_ENABLE();
+    __GPIOC_CLK_ENABLE();
+    __GPIOH_CLK_ENABLE();
+
+    GPIO_InitTypeDef GPIO_InitStruct;
+
+    // UART1_TX, UART1_RTS & UART1_CTS to analog nopull - RX could be a wakeup source
+    GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_11 | GPIO_PIN_12;
+    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+    // I2C_SDA & I2C_SCL to analog nopull
+    GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;
+    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+
+    // SPI_MOSI, SPI_MISO, SPI_SCK, & SPI_NSS to analog nopull
+    GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
+    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+
+    // iterate through potential wake pins - leave the configured wake pin alone if one is needed
+    if (dot->getWakePin() != WAKE || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_0;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+    if (dot->getWakePin() != GPIO0 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_4;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+    if (dot->getWakePin() != GPIO1 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_5;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+    if (dot->getWakePin() != GPIO2 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_0;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+    }
+    if (dot->getWakePin() != GPIO3 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_2;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+    }
+    if (dot->getWakePin() != UART1_RX || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_10;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+#else
+    /* GPIO Ports Clock Enable */
+    __GPIOA_CLK_ENABLE();
+    __GPIOB_CLK_ENABLE();
+    __GPIOC_CLK_ENABLE();
+
+    GPIO_InitTypeDef GPIO_InitStruct;
+
+    // XBEE_DOUT, XBEE_DIN, XBEE_DO8, XBEE_RSSI, USBTX, USBRX, PA_12, PA_13, PA_14 & PA_15 to analog nopull
+    GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_6 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 
+                | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
+    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);    
+
+    // PB_0, PB_1, PB_3 & PB_4 to analog nopull
+    GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3 | GPIO_PIN_4;
+    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); 
+
+    // PC_9 & PC_13 to analog nopull
+    GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_13;
+    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); 
+
+    // iterate through potential wake pins - leave the configured wake pin alone if one is needed
+    // XBEE_DIN - PA3
+    // XBEE_DIO2 - PA5
+    // XBEE_DIO3 - PA4
+    // XBEE_DIO4 - PA7
+    // XBEE_DIO5 - PC1
+    // XBEE_DIO6 - PA1
+    // XBEE_DIO7 - PA0
+    // XBEE_SLEEPRQ - PA11
+                
+    if (dot->getWakePin() != XBEE_DIN || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_3;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+
+    if (dot->getWakePin() != XBEE_DIO2 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_5;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+
+    if (dot->getWakePin() != XBEE_DIO3 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_4;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+
+         if (dot->getWakePin() != XBEE_DIO4 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_7;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+
+     if (dot->getWakePin() != XBEE_DIO5 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_1;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
+    }
+
+     if (dot->getWakePin() != XBEE_DIO6 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_1;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+
+     if (dot->getWakePin() != XBEE_DIO7 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_0;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+
+     if (dot->getWakePin() != XBEE_SLEEPRQ|| dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_11;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+#endif
+}
+
+void sleep_restore_io() {
+#if defined(TARGET_XDOT_L151CC)
+    xdot_restore_gpio_state();
+#else
+    GPIOA->MODER = portA[0];
+    GPIOA->OTYPER = portA[1];
+    GPIOA->OSPEEDR = portA[2];
+    GPIOA->PUPDR = portA[3];
+    GPIOA->AFR[0] = portA[4];
+    GPIOA->AFR[1] = portA[5];
+
+    GPIOB->MODER = portB[0];
+    GPIOB->OTYPER = portB[1];
+    GPIOB->OSPEEDR = portB[2];
+    GPIOB->PUPDR = portB[3];
+    GPIOB->AFR[0] = portB[4];
+    GPIOB->AFR[1] = portB[5];
+
+    GPIOC->MODER = portC[0];
+    GPIOC->OTYPER = portC[1];
+    GPIOC->OSPEEDR = portC[2];
+    GPIOC->PUPDR = portC[3];
+    GPIOC->AFR[0] = portC[4];
+    GPIOC->AFR[1] = portC[5];
+
+    GPIOD->MODER = portD[0];
+    GPIOD->OTYPER = portD[1];
+    GPIOD->OSPEEDR = portD[2];
+    GPIOD->PUPDR = portD[3];
+    GPIOD->AFR[0] = portD[4];
+    GPIOD->AFR[1] = portD[5];
+
+    GPIOH->MODER = portH[0];
+    GPIOH->OTYPER = portH[1];
+    GPIOH->OSPEEDR = portH[2];
+    GPIOH->PUPDR = portH[3];
+    GPIOH->AFR[0] = portH[4];
+    GPIOH->AFR[1] = portH[5];
+#endif
+}
+
+void send_data(std::vector<uint8_t> data) {
+    uint32_t ret;
+
+    ret = dot->send(data);
+    if (ret != mDot::MDOT_OK) {
+        logError("failed to send data to %s [%d][%s]", dot->getJoinMode() == mDot::PEER_TO_PEER ? "peer" : "gateway", ret, mDot::getReturnCodeString(ret).c_str());
+    } else {
+        logInfo("successfully sent data to %s", dot->getJoinMode() == mDot::PEER_TO_PEER ? "peer" : "gateway");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/src/manual_example.cpp	Mon Mar 27 09:43:43 2017 +0000
@@ -0,0 +1,151 @@
+#include "dot_util.h"
+#include "RadioEvent.h"
+ 
+#if ACTIVE_EXAMPLE == MANUAL_EXAMPLE
+
+/////////////////////////////////////////////////////////////////////////////
+// -------------------- DOT LIBRARY REQUIRED ------------------------------//
+// * Because these example programs can be used for both mDot and xDot     //
+//     devices, the LoRa stack is not included. The libmDot library should //
+//     be imported if building for mDot devices. The libxDot library       //
+//     should be imported if building for xDot devices.                    //
+// * https://developer.mbed.org/teams/MultiTech/code/libmDot-dev-mbed5/    //
+// * https://developer.mbed.org/teams/MultiTech/code/libmDot-mbed5/        //
+// * https://developer.mbed.org/teams/MultiTech/code/libxDot-dev-mbed5/    //
+// * https://developer.mbed.org/teams/MultiTech/code/libxDot-mbed5/        //
+/////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////
+// * these options must match the settings on your gateway //
+// * edit their values to match your configuration         //
+// * frequency sub band is only relevant for the 915 bands //
+/////////////////////////////////////////////////////////////
+static uint8_t network_address[] = { 0x01, 0x02, 0x03, 0x04 };
+static uint8_t network_session_key[] = { 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04 };
+static uint8_t data_session_key[] = { 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04 };
+static uint8_t frequency_sub_band = 6;
+static bool public_network = false;
+static uint8_t ack = 1;
+
+// deepsleep consumes slightly less current than sleep
+// in sleep mode, IO state is maintained, RAM is retained, and application will resume after waking up
+// in deepsleep mode, IOs float, RAM is lost, and application will start from beginning after waking up
+// if deep_sleep == true, device will enter deepsleep mode
+static bool deep_sleep = true;
+
+mDot* dot = NULL;
+
+Serial pc(USBTX, USBRX);
+
+#if defined(TARGET_XDOT_L151CC)
+I2C i2c(I2C_SDA, I2C_SCL);
+ISL29011 lux(i2c);
+#else
+AnalogIn lux(XBEE_AD0);
+#endif
+
+int main() {
+    // Custom event handler for automatically displaying RX data
+    RadioEvent events;
+
+    pc.baud(115200);
+
+    mts::MTSLog::setLogLevel(mts::MTSLog::TRACE_LEVEL);
+    
+    dot = mDot::getInstance();
+
+    // attach the custom events handler
+    dot->setEvents(&events);
+
+    if (!dot->getStandbyFlag()) {
+        logInfo("mbed-os library version: %d", MBED_LIBRARY_VERSION);
+
+        // start from a well-known state
+        logInfo("defaulting Dot configuration");
+        dot->resetConfig();
+        dot->resetNetworkSession();
+
+        // make sure library logging is turned on
+        dot->setLogLevel(mts::MTSLog::INFO_LEVEL);
+
+        // update configuration if necessary
+        if (dot->getJoinMode() != mDot::MANUAL) {
+            logInfo("changing network join mode to MANUAL");
+            if (dot->setJoinMode(mDot::MANUAL) != mDot::MDOT_OK) {
+                logError("failed to set network join mode to MANUAL");
+            }
+        }
+        // in MANUAL join mode there is no join request/response transaction
+        // as long as the Dot is configured correctly and provisioned correctly on the gateway, it should be able to communicate
+        // network address - 4 bytes (00000001 - FFFFFFFE)
+        // network session key - 16 bytes
+        // data session key - 16 bytes
+        // to provision your Dot with a Conduit gateway, follow the following steps
+        //   * ssh into the Conduit
+        //   * provision the Dot using the lora-query application: http://www.multitech.net/developer/software/lora/lora-network-server/
+        //      lora-query -a 01020304 A 0102030401020304 <your Dot's device ID> 01020304010203040102030401020304 01020304010203040102030401020304
+        //   * if you change the network address, network session key, or data session key, make sure you update them on the gateway
+        // to provision your Dot with a 3rd party gateway, see the gateway or network provider documentation
+        update_manual_config(network_address, network_session_key, data_session_key, frequency_sub_band, public_network, ack);
+
+        // save changes to configuration
+        logInfo("saving configuration");
+        if (!dot->saveConfig()) {
+            logError("failed to save configuration");
+        }
+
+        // display configuration
+        display_config();
+    } else {
+        // restore the saved session if the dot woke from deepsleep mode
+        // useful to use with deepsleep because session info is otherwise lost when the dot enters deepsleep
+        logInfo("restoring network session from NVM");
+        dot->restoreNetworkSession();
+    }
+    
+
+    while (true) {
+        uint16_t light;
+        std::vector<uint8_t> tx_data;
+
+#if defined(TARGET_XDOT_L151CC)
+        // configure the ISL29011 sensor on the xDot-DK for continuous ambient light sampling, 16 bit conversion, and maximum range
+        lux.setMode(ISL29011::ALS_CONT);
+        lux.setResolution(ISL29011::ADC_16BIT);
+        lux.setRange(ISL29011::RNG_64000);
+
+        // get the latest light sample and send it to the gateway
+        light = lux.getData();
+        tx_data.push_back((light >> 8) & 0xFF);
+        tx_data.push_back(light & 0xFF);
+        logInfo("light: %lu [0x%04X]", light, light);
+        send_data(tx_data);
+
+        // put the LSL29011 ambient light sensor into a low power state
+        lux.setMode(ISL29011::PWR_DOWN);
+#else 
+        // get some dummy data and send it to the gateway
+        light = lux.read_u16();
+        tx_data.push_back((light >> 8) & 0xFF);
+        tx_data.push_back(light & 0xFF);
+        logInfo("light: %lu [0x%04X]", light, light);
+        send_data(tx_data);
+#endif
+
+        // if going into deepsleep mode, save the session so we don't need to join again after waking up
+        // not necessary if going into sleep mode since RAM is retained
+        if (deep_sleep) {
+            logInfo("saving network session to NVM");
+            dot->saveNetworkSession();
+        }
+
+        // ONLY ONE of the three functions below should be uncommented depending on the desired wakeup method
+        //sleep_wake_rtc_only(deep_sleep);
+        //sleep_wake_interrupt_only(deep_sleep);
+        sleep_wake_rtc_or_interrupt(deep_sleep);
+    }
+ 
+    return 0;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/src/ota_example.cpp	Mon Mar 27 09:43:43 2017 +0000
@@ -0,0 +1,159 @@
+#include "dot_util.h"
+#include "RadioEvent.h"
+ 
+#if ACTIVE_EXAMPLE == OTA_EXAMPLE
+
+/////////////////////////////////////////////////////////////////////////////
+// -------------------- DOT LIBRARY REQUIRED ------------------------------//
+// * Because these example programs can be used for both mDot and xDot     //
+//     devices, the LoRa stack is not included. The libmDot library should //
+//     be imported if building for mDot devices. The libxDot library       //
+//     should be imported if building for xDot devices.                    //
+// * https://developer.mbed.org/teams/MultiTech/code/libmDot-dev-mbed5/    //
+// * https://developer.mbed.org/teams/MultiTech/code/libmDot-mbed5/        //
+// * https://developer.mbed.org/teams/MultiTech/code/libxDot-dev-mbed5/    //
+// * https://developer.mbed.org/teams/MultiTech/code/libxDot-mbed5/        //
+/////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////
+// * these options must match the settings on your gateway //
+// * edit their values to match your configuration         //
+// * frequency sub band is only relevant for the 915 bands //
+// * either the network name and passphrase can be used or //
+//     the network ID (8 bytes) and KEY (16 bytes)         //
+/////////////////////////////////////////////////////////////
+static std::string network_name = "MultiTech";
+static std::string network_passphrase = "MultiTech";
+static uint8_t network_id[] = { 0x6C, 0x4E, 0xEF, 0x66, 0xF4, 0x79, 0x86, 0xA6 };
+static uint8_t network_key[] = { 0x1F, 0x33, 0xA1, 0x70, 0xA5, 0xF1, 0xFD, 0xA0, 0xAB, 0x69, 0x7A, 0xAE, 0x2B, 0x95, 0x91, 0x6B };
+static uint8_t frequency_sub_band = 0;
+static bool public_network = false;
+static uint8_t ack = 0;
+
+// deepsleep consumes slightly less current than sleep
+// in sleep mode, IO state is maintained, RAM is retained, and application will resume after waking up
+// in deepsleep mode, IOs float, RAM is lost, and application will start from beginning after waking up
+// if deep_sleep == true, device will enter deepsleep mode
+static bool deep_sleep = false;
+
+mDot* dot = NULL;
+
+Serial pc(USBTX, USBRX);
+
+#if defined(TARGET_XDOT_L151CC)
+I2C i2c(I2C_SDA, I2C_SCL);
+ISL29011 lux(i2c);
+#else
+AnalogIn lux(XBEE_AD0);
+#endif
+
+int main() {
+    // Custom event handler for automatically displaying RX data
+    RadioEvent events;
+
+    pc.baud(115200);
+
+    mts::MTSLog::setLogLevel(mts::MTSLog::TRACE_LEVEL);
+    
+    dot = mDot::getInstance();
+
+    // attach the custom events handler
+    dot->setEvents(&events);
+
+    if (!dot->getStandbyFlag()) {
+        logInfo("mbed-os library version: %d", MBED_LIBRARY_VERSION);
+
+        // start from a well-known state
+        logInfo("defaulting Dot configuration");
+        dot->resetConfig();
+        dot->resetNetworkSession();
+
+        // make sure library logging is turned on
+        dot->setLogLevel(mts::MTSLog::INFO_LEVEL);
+
+        // update configuration if necessary
+        if (dot->getJoinMode() != mDot::OTA) {
+            logInfo("changing network join mode to OTA");
+            if (dot->setJoinMode(mDot::OTA) != mDot::MDOT_OK) {
+                logError("failed to set network join mode to OTA");
+            }
+        }
+        // in OTA and AUTO_OTA join modes, the credentials can be passed to the library as a name and passphrase or an ID and KEY
+        // only one method or the other should be used!
+        // network ID = crc64(network name)
+        // network KEY = cmac(network passphrase)
+        update_ota_config_name_phrase(network_name, network_passphrase, frequency_sub_band, public_network, ack);
+        //update_ota_config_id_key(network_id, network_key, frequency_sub_band, public_network, ack);
+
+        // configure network link checks
+        // network link checks are a good alternative to requiring the gateway to ACK every packet and should allow a single gateway to handle more Dots
+        // check the link every count packets
+        // declare the Dot disconnected after threshold failed link checks
+        // for count = 3 and threshold = 5, the Dot will be considered disconnected after 15 missed packets in a row
+        update_network_link_check_config(3, 5);
+    
+        // save changes to configuration
+        logInfo("saving configuration");
+        if (!dot->saveConfig()) {
+            logError("failed to save configuration");
+        }
+
+        // display configuration
+        display_config();
+    } else {
+        // restore the saved session if the dot woke from deepsleep mode
+        // useful to use with deepsleep because session info is otherwise lost when the dot enters deepsleep
+        logInfo("restoring network session from NVM");
+        dot->restoreNetworkSession();
+    }
+
+    while (true) {
+        uint16_t light;
+        std::vector<uint8_t> tx_data;
+
+        // join network if not joined
+        if (!dot->getNetworkJoinStatus()) {
+            join_network();
+        }
+
+#if defined(TARGET_XDOT_L151CC)
+        // configure the ISL29011 sensor on the xDot-DK for continuous ambient light sampling, 16 bit conversion, and maximum range
+        lux.setMode(ISL29011::ALS_CONT);
+        lux.setResolution(ISL29011::ADC_16BIT);
+        lux.setRange(ISL29011::RNG_64000);
+
+        // get the latest light sample and send it to the gateway
+        light = lux.getData();
+        tx_data.push_back((light >> 8) & 0xFF);
+        tx_data.push_back(light & 0xFF);
+        logInfo("light: %lu [0x%04X]", light, light);
+        send_data(tx_data);
+
+        // put the LSL29011 ambient light sensor into a low power state
+        lux.setMode(ISL29011::PWR_DOWN);
+#else 
+        // get some dummy data and send it to the gateway
+        light = lux.read_u16();
+        tx_data.push_back((light >> 8) & 0xFF);
+        tx_data.push_back(light & 0xFF);
+        logInfo("light: %lu [0x%04X]", light, light);
+        send_data(tx_data);
+#endif
+
+        // if going into deepsleep mode, save the session so we don't need to join again after waking up
+        // not necessary if going into sleep mode since RAM is retained
+        if (deep_sleep) {
+            logInfo("saving network session to NVM");
+            dot->saveNetworkSession();
+        }
+
+        // ONLY ONE of the three functions below should be uncommented depending on the desired wakeup method
+        //sleep_wake_rtc_only(deep_sleep);
+        //sleep_wake_interrupt_only(deep_sleep);
+        sleep_wake_rtc_or_interrupt(deep_sleep);
+    }
+ 
+    return 0;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/src/peer_to_peer_example.cpp	Mon Mar 27 09:43:43 2017 +0000
@@ -0,0 +1,154 @@
+#include "dot_util.h"
+#include "RadioEvent.h"
+ 
+#if ACTIVE_EXAMPLE == PEER_TO_PEER_EXAMPLE
+
+/////////////////////////////////////////////////////////////////////////////
+// -------------------- DOT LIBRARY REQUIRED ------------------------------//
+// * Because these example programs can be used for both mDot and xDot     //
+//     devices, the LoRa stack is not included. The libmDot library should //
+//     be imported if building for mDot devices. The libxDot library       //
+//     should be imported if building for xDot devices.                    //
+// * https://developer.mbed.org/teams/MultiTech/code/libmDot-dev-mbed5/    //
+// * https://developer.mbed.org/teams/MultiTech/code/libmDot-mbed5/        //
+// * https://developer.mbed.org/teams/MultiTech/code/libxDot-dev-mbed5/    //
+// * https://developer.mbed.org/teams/MultiTech/code/libxDot-mbed5/        //
+/////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////
+// * these options must match between the two devices in   //
+//   order for communication to be successful
+/////////////////////////////////////////////////////////////
+static uint8_t network_address[] = { 0x01, 0x02, 0x03, 0x04 };
+static uint8_t network_session_key[] = { 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04 };
+static uint8_t data_session_key[] = { 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04 };
+
+mDot* dot = NULL;
+
+Serial pc(USBTX, USBRX);
+
+#if defined(TARGET_XDOT_L151CC)
+I2C i2c(I2C_SDA, I2C_SCL);
+ISL29011 lux(i2c);
+#else
+AnalogIn lux(XBEE_AD0);
+#endif
+
+int main() {
+    // Custom event handler for automatically displaying RX data
+    RadioEvent events;
+    uint32_t tx_frequency;
+    uint8_t tx_datarate;
+    uint8_t tx_power;
+    uint8_t frequency_band;
+
+    pc.baud(115200);
+
+    mts::MTSLog::setLogLevel(mts::MTSLog::TRACE_LEVEL);
+    
+    dot = mDot::getInstance();
+
+    logInfo("mbed-os library version: %d", MBED_LIBRARY_VERSION);
+
+    // start from a well-known state
+    logInfo("defaulting Dot configuration");
+    dot->resetConfig();
+
+    // make sure library logging is turned on
+    dot->setLogLevel(mts::MTSLog::INFO_LEVEL);
+
+    // attach the custom events handler
+    dot->setEvents(&events);
+
+    // update configuration if necessary
+    if (dot->getJoinMode() != mDot::PEER_TO_PEER) {
+        logInfo("changing network join mode to PEER_TO_PEER");
+        if (dot->setJoinMode(mDot::PEER_TO_PEER) != mDot::MDOT_OK) {
+            logError("failed to set network join mode to PEER_TO_PEER");
+        }
+    }
+    frequency_band = dot->getFrequencyBand();
+    switch (frequency_band) {
+        case mDot::FB_EU868:
+            // 250kHz channels achieve higher throughput
+            // DR6 : SF7 @ 250kHz
+            // DR0 - DR5 (125kHz channels) available but much slower
+            tx_frequency = 869850000;
+            tx_datarate = mDot::DR6;
+            // the 869850000 frequency is 100% duty cycle if the total power is under 7 dBm - tx power 4 + antenna gain 3 = 7
+            tx_power = 4;
+            break;
+        case mDot::FB_US915:
+        case mDot::FB_AU915:
+        default:
+            // 500kHz channels achieve highest throughput
+            // DR8 : SF12 @ 500kHz
+            // DR9 : SF11 @ 500kHz
+            // DR10 : SF10 @ 500kHz
+            // DR11 : SF9 @ 500kHz
+            // DR12 : SF8 @ 500kHz
+            // DR13 : SF7 @ 500kHz
+            // DR0 - DR3 (125kHz channels) available but much slower
+            tx_frequency = 915500000;
+            tx_datarate = mDot::DR13;
+            // 915 bands have no duty cycle restrictions, set tx power to max
+            tx_power = 20;
+            break;
+    }
+    // in PEER_TO_PEER mode there is no join request/response transaction
+    // as long as both Dots are configured correctly, they should be able to communicate
+    update_peer_to_peer_config(network_address, network_session_key, data_session_key, tx_frequency, tx_datarate, tx_power);
+
+    // save changes to configuration
+    logInfo("saving configuration");
+    if (!dot->saveConfig()) {
+        logError("failed to save configuration");
+    }
+
+    // display configuration
+    display_config();
+
+#if defined(TARGET_XDOT_L151CC)
+    // configure the ISL29011 sensor on the xDot-DK for continuous ambient light sampling, 16 bit conversion, and maximum range
+    lux.setMode(ISL29011::ALS_CONT);
+    lux.setResolution(ISL29011::ADC_16BIT);
+    lux.setRange(ISL29011::RNG_64000);
+#endif
+
+    while (true) {
+        uint16_t light;
+        std::vector<uint8_t> tx_data;
+
+        // join network if not joined
+        if (!dot->getNetworkJoinStatus()) {
+            join_network();
+        }
+
+#if defined(TARGET_XDOT_L151CC)
+        // get the latest light sample and send it to the gateway
+        light = lux.getData();
+        tx_data.push_back((light >> 8) & 0xFF);
+        tx_data.push_back(light & 0xFF);
+        logInfo("light: %lu [0x%04X]", light, light);
+        send_data(tx_data);
+#else 
+        // get some dummy data and send it to the gateway
+        light = lux.read_u16();
+        tx_data.push_back((light >> 8) & 0xFF);
+        tx_data.push_back(light & 0xFF);
+        logInfo("light: %lu [0x%04X]", light, light);
+        send_data(tx_data);
+#endif
+
+        // the Dot can't sleep in PEER_TO_PEER mode
+        // it must be waiting for data from the other Dot
+        // send data every 5 seconds
+        logInfo("waiting for 5s");
+        wait(5);
+    }
+ 
+    return 0;
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmDot.lib	Mon Mar 27 09:43:43 2017 +0000
@@ -0,0 +1,1 @@
+https://developer.mbed.org/teams/MultiTech/code/libmDot/#0b4eb17d07ae
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Mar 27 09:43:43 2017 +0000
@@ -0,0 +1,139 @@
+#include "mbed.h"
+#include "mDot.h"
+#include "MTSLog.h"
+#include "DHT.h"
+#include <string>
+#include <vector>
+#include <algorithm>
+
+// these options must match the settings on your Conduit
+// uncomment the following lines and edit their values to match your configuration
+static std::string config_network_name = "<house123>";
+static std::string config_network_pass = "<12345678>";
+static uint8_t config_frequency_sub_band = 7;
+DHT sensor(PB_1, DHT11);
+
+Serial pc(USBTX,USBRX);
+
+int main() {
+    int32_t ret;
+    mDot* dot;
+    std::vector<uint8_t> data;
+    std::string data_str = "hello!";
+    
+    float temperature = 0.0;
+ //   pc.baud(115200);
+    pc.printf("mDot LoRa Temperature & Humidity Sensor data\n\r");
+    
+   // printf("hihihi\n");
+ wait(0.2);
+while (true)
+    {
+        int readResult = sensor.readData();
+        if (readResult != 0)
+        {
+            printf("\r\n error %d", readResult);
+        }
+        else {
+            printf ("\r\n Temp = %f", sensor.ReadTemperature(CELCIUS));
+        }
+        wait(20);
+    }
+    
+    // get a mDot handle
+    dot = mDot::getInstance();
+    
+    // print library version information
+    logInfo("version: %s", dot->getId().c_str());
+
+    //*******************************************
+    // configuration
+    //*******************************************
+    // reset to default config so we know what state we're in
+    dot->resetConfig();
+    
+    dot->setLogLevel(mts::MTSLog::INFO_LEVEL);
+
+    // set up the mDot with our network information: frequency sub band, network name, and network password
+    // these can all be saved in NVM so they don't need to be set every time - see mDot::saveConfig()
+    
+    // frequency sub band is only applicable in the 915 (US) frequency band
+    // if using a MultiTech Conduit gateway, use the same sub band as your Conduit (1-8) - the mDot will use the 8 channels in that sub band
+    // if using a gateway that supports all 64 channels, use sub band 0 - the mDot will use all 64 channels
+    logInfo("setting frequency sub band");
+    if ((ret = dot->setFrequencySubBand(config_frequency_sub_band)) != mDot::MDOT_OK) {
+        logError("failed to set frequency sub band %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
+    }
+    
+    logInfo("setting network name");
+    if ((ret = dot->setNetworkName(config_network_name)) != mDot::MDOT_OK) {
+        logError("failed to set network name %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
+    }
+    
+    logInfo("setting network password");
+    if ((ret = dot->setNetworkPassphrase(config_network_pass)) != mDot::MDOT_OK) {
+        logError("failed to set network password %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
+    }
+    
+    // a higher spreading factor allows for longer range but lower throughput
+    // in the 915 (US) frequency band, spreading factors 7 - 10 are available
+    // in the 868 (EU) frequency band, spreading factors 7 - 12 are available
+    logInfo("setting TX spreading factor");
+    if ((ret = dot->setTxDataRate(mDot::SF_10)) != mDot::MDOT_OK) {
+        logError("failed to set TX datarate %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
+    }
+    
+    // request receive confirmation of packets from the gateway
+    logInfo("enabling ACKs");
+    if ((ret = dot->setAck(1)) != mDot::MDOT_OK) {
+        logError("failed to enable ACKs %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
+    }
+    
+    // set join mode to AUTO_OTA so the mDot doesn't have to rejoin after sleeping
+    logInfo("setting join mode to AUTO_OTA");
+    if ((ret = dot->setJoinMode(mDot::AUTO_OTA)) != mDot::MDOT_OK) {
+        logError("failed to set join mode %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
+    }
+    
+    // save this configuration to the mDot's NVM
+    logInfo("saving config");
+    if (! dot->saveConfig()) {
+        logError("failed to save configuration");
+    }
+    //*******************************************
+    // end of configuration
+    //*******************************************
+
+    // format data for sending to the gateway
+    for (std::string::iterator it = data_str.begin(); it != data_str.end(); it++)
+        data.push_back((uint8_t) *it);
+
+    // join the network if not joined
+    if (!dot->getNetworkJoinStatus()) {
+        logInfo("network not joined, joining network");
+        if ((ret = dot->joinNetwork()) != mDot::MDOT_OK) {
+            logError("failed to join network %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
+        }
+    }
+    if (dot->getNetworkJoinStatus()) {
+        // send the data
+        // ACKs are enabled by default, so we're expecting to get one back
+        if ((ret = dot->send(data)) != mDot::MDOT_OK) {
+            logError("failed to send %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
+        } else {
+            logInfo("successfully sent data to gateway");
+        }
+    }
+
+    // in the 868 (EU) frequency band, we need to wait until another channel is available before transmitting again
+    uint32_t sleep_time = std::max((uint32_t)10000, (uint32_t)dot->getNextTxMs()) / 1000;
+    logInfo("going to sleep...");
+
+    // go to deepsleep and wake up automatically sleep_time seconds later
+    dot->sleep(sleep_time, mDot::RTC_ALARM);
+
+    // go to deepsleep and wake up on rising edge of WKUP pin (PA0/XBEE_CTS/XBEE_DIO7)
+    // dot->sleep(0, mDot::INTERRUPT);
+
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-os.lib	Mon Mar 27 09:43:43 2017 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/mbed-os/#a6f3fd1a60d5df59246d7caf3f108c4d34e1808e