Programa WARIIOT AIDI421 clase C.

Dependencies:   libxDot-mbed5

Fork of mDot_claseC by Damez

Files at this revision

API Documentation at this revision

Comitter:
gabrielap
Date:
Wed Jun 03 15:25:22 2020 +0000
Commit message:
Programa base para proyecto con mDot en clase C.

Changed in this revision

CONTRIBUTING.md Show annotated file Show diff for this revision Revisions of this file
README.md Show annotated file Show diff for this revision Revisions of this file
RadioEvent.h Show annotated file Show diff for this revision Revisions of this file
dot_util.cpp Show annotated file Show diff for this revision Revisions of this file
dot_util.h Show annotated file Show diff for this revision Revisions of this file
libxDot-mbed5.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/CONTRIBUTING.md	Wed Jun 03 15:25:22 2020 +0000
@@ -0,0 +1,6 @@
+# Contributing to Mbed OS
+
+Mbed OS is an open-source, device software platform for the Internet of Things. Contributions are an important part of the platform, and our goal is to make it as simple as possible to become a contributor.
+
+To encourage productive collaboration, as well as robust, consistent and maintainable code, we have a set of guidelines for [contributing to Mbed OS](https://os.mbed.com/docs/mbed-os/latest/contributing/index.html).
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README.md	Wed Jun 03 15:25:22 2020 +0000
@@ -0,0 +1,65 @@
+![](./resources/official_armmbed_example_badge.png)
+# Blinky Mbed OS example
+
+The example project is part of the [Arm Mbed OS Official Examples](https://os.mbed.com/code/) and is the [getting started example for Mbed OS](https://os.mbed.com/docs/mbed-os/v5.14/quick-start/index.html). It contains an application that repeatedly blinks an LED on supported [Mbed boards](https://os.mbed.com/platforms/).
+
+You can build the project with all supported [Mbed OS build tools](https://os.mbed.com/docs/mbed-os/latest/tools/index.html). However, this example project specifically refers to the command-line interface tool [Arm Mbed CLI](https://github.com/ARMmbed/mbed-cli#installing-mbed-cli).
+(Note: To see a rendered example you can import into the Arm Online Compiler, please see our [import quick start](https://os.mbed.com/docs/mbed-os/latest/quick-start/online-with-the-online-compiler.html#importing-the-code).)
+
+1. [Install Mbed CLI](https://os.mbed.com/docs/mbed-os/latest/quick-start/offline-with-mbed-cli.html).
+
+1. Clone this repository on your system, and change the current directory to where the project was cloned:
+
+    ```bash
+    $ git clone git@github.com:armmbed/mbed-os-example-blinky && cd mbed-os-example-blinky
+    ```
+
+    Alternatively, you can download the example project with Arm Mbed CLI using the `import` subcommand:
+
+    ```bash
+    $ mbed import mbed-os-example-blinky && cd mbed-os-example-blinky
+    ```
+
+
+## Application functionality
+
+The `main()` function is the single thread in the application. It toggles the state of a digital output connected to an LED on the board.
+
+## Building and running
+
+1. Connect a USB cable between the USB port on the board and the host computer.
+2. <a name="build_cmd"></a> Run the following command to build the example project and program the microcontroller flash memory:
+    ```bash
+    $ mbed compile -m <TARGET> -t <TOOLCHAIN> --flash
+    ```
+The binary is located at `./BUILD/<TARGET>/<TOOLCHAIN>/mbed-os-example-blinky.bin`.
+
+Alternatively, you can manually copy the binary to the board, which you mount on the host computer over USB.
+
+Depending on the target, you can build the example project with the `GCC_ARM`, `ARM` or `IAR` toolchain. After installing Arm Mbed CLI, run the command below to determine which toolchain supports your target:
+
+```bash
+$ mbed compile -S
+```
+
+## Expected output
+The LED on your target turns on and off every 500 milliseconds.
+
+
+## Troubleshooting
+If you have problems, you can review the [documentation](https://os.mbed.com/docs/latest/tutorials/debugging.html) for suggestions on what could be wrong and how to fix it.
+
+## Related Links
+
+* [Mbed OS Stats API](https://os.mbed.com/docs/latest/apis/mbed-statistics.html).
+* [Mbed OS Configuration](https://os.mbed.com/docs/latest/reference/configuration.html).
+* [Mbed OS Serial Communication](https://os.mbed.com/docs/latest/tutorials/serial-communication.html).
+* [Mbed OS bare metal](https://os.mbed.com/docs/mbed-os/latest/reference/mbed-os-bare-metal.html).
+* [Mbed boards](https://os.mbed.com/platforms/).
+
+### License and contributions
+
+The software is provided under Apache-2.0 license. Contributions to this project are accepted under the same license. Please see contributing.md for more info.
+
+This project contains code from other projects. The original license text is included in those source files. They must comply with our license guide.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RadioEvent.h	Wed Jun 03 15:25:22 2020 +0000
@@ -0,0 +1,92 @@
+#ifndef __RADIO_EVENT_H__
+#define __RADIO_EVENT_H__
+
+#include "dot_util.h"
+#include "mDotEvent.h"
+#include "Fota.h"
+
+class RadioEvent : public mDotEvent
+{
+
+public:
+    RadioEvent() {}
+
+    virtual ~RadioEvent() {}
+
+    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) {
+        mDotEvent::PacketRx(port, payload, size, rssi, snr, ctrl, slot, retries, address, dupRx);
+
+#if ACTIVE_EXAMPLE == FOTA_EXAMPLE
+        if(port == 200 || port == 201 || port == 202) {
+            Fota::getInstance()->processCmd(payload, port, size);
+        }
+#endif
+    }
+
+    /*!
+     * 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);
+            logInfo("Rx %d bytes", info->RxBufferSize);
+            if (info->RxBufferSize > 0) {
+                //logInfo("Rx data: %S\r\n", mts::Text::bin2hexString(info->RxBuffer, info->RxBufferSize).c_str());
+//#if ACTIVE_EXAMPLE != FOTA_EXAMPLE
+                // print RX data as string and hexadecimal
+                std::string rx((const char*)info->RxBuffer, info->RxBufferSize);
+                //printf("Rx data: %s [%s]\r\n", rx.c_str(), mts::Text::bin2hexString(info->RxBuffer, info->RxBufferSize).c_str());
+                logInfo("Rx data: %s [%s]\r\n", rx.c_str(), mts::Text::bin2hexString(info->RxBuffer, info->RxBufferSize).c_str());
+//#endif      
+            }
+        }
+    }
+};
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dot_util.cpp	Wed Jun 03 15:25:22 2020 +0000
@@ -0,0 +1,847 @@
+#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("default channel plan ----- %s", mDot::FrequencyBandStr(dot->getDefaultFrequencyBand()).c_str());
+    logInfo("current channel plan ----- %s", mDot::FrequencyBandStr(dot->getFrequencyBand()).c_str());
+    if (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) {
+        logInfo("frequency sub band ------- %u", dot->getFrequencySubBand());
+    }
+
+    std::string network_mode_str("Undefined");
+    uint8_t network_mode = dot->getPublicNetwork();
+    if (network_mode == lora::PRIVATE_MTS)
+        network_mode_str = "Private MTS";
+    else if (network_mode == lora::PUBLIC_LORAWAN)
+        network_mode_str = "Public LoRaWAN";
+    else if (network_mode == lora::PRIVATE_LORAWAN)
+        network_mode_str = "Private LoRaWAN";
+    logInfo("public network ----------- %s", network_mode_str.c_str());
+
+    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("antenna gain ------------- %u dBm", dot->getAntennaGain());
+    logInfo("LBT ---------------------- %s", dot->getLbtTimeUs() ? "on" : "off");
+    if (dot->getLbtTimeUs()) {
+	logInfo("LBT time ----------------- %lu us", dot->getLbtTimeUs());
+	logInfo("LBT threshold ------------ %d dBm", dot->getLbtThreshold());
+    }
+}
+
+void update_ota_config_name_phrase(std::string network_name, std::string network_passphrase, uint8_t frequency_sub_band, lora::NetworkType network_type, 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();
+    uint8_t current_network_type = 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 (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) {
+	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_network_type != network_type) {
+        if (dot->setPublicNetwork(network_type) != mDot::MDOT_OK) {
+            logError("failed to set network type");
+        }
+    }
+
+    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, lora::NetworkType network_type, 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();
+    uint8_t current_network_type = 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 (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) {
+	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_network_type != network_type) {
+        if (dot->setPublicNetwork(network_type) != mDot::MDOT_OK) {
+            logError("failed to set network type");
+        }
+    }
+    
+    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, lora::NetworkType network_type, 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();
+    uint8_t current_network_type = 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_network_type != network_type) {
+        if (dot->setPublicNetwork(network_type) != mDot::MDOT_OK) {
+            logError("failed to set network type");
+        }
+    }
+    
+    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 < 5) {
+                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 join_network(uint32_t delay_s) {
+    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());
+           
+            logInfo("sleeping %lu s para luego reintentar enlace", delay_s);
+            //dot->sleep(delay_s, mDot::RTC_ALARM, false);
+            wait(delay_s);
+            }
+    }
+}
+ 
+
+/*
+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 = 55;// para que envie un dato cada una hora, contemplando que tarda 5 seg en hacer el calculo //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_rtc_only(bool deepsleep,uint32_t time_sleep_s) {
+    // 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 = time_sleep_s;// para que envie un dato cada una hora, contemplando que tarda 5 seg en hacer el calculo //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_wake_rtc_or_interrupt(bool deepsleep, uint32_t time_sleep_s) {
+    // 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 = time_sleep_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.Pin = GPIO_PIN_9;
+    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
+}
+
+int send_data(std::vector<uint8_t> data) {
+    int32_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");
+    }
+
+    return ret;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dot_util.h	Wed Jun 03 15:25:22 2020 +0000
@@ -0,0 +1,44 @@
+#ifndef __DOT_UTIL_H__
+#define __DOT_UTIL_H__
+
+#include "mbed.h"
+#include "mDot.h"
+#include "ChannelPlans.h"
+#include "MTSLog.h"
+#include "MTSText.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, lora::NetworkType network_type, uint8_t ack);
+
+void update_ota_config_id_key(uint8_t *network_id, uint8_t *network_key, uint8_t frequency_sub_band, lora::NetworkType 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, lora::NetworkType network_type, 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 join_network(uint32_t delay_s);
+
+void sleep_wake_rtc_only(bool deepsleep, uint32_t time_sleep_s);
+
+void sleep_wake_interrupt_only(bool deepsleep);
+
+//void sleep_wake_rtc_or_interrupt(bool deepsleep);
+void sleep_wake_rtc_or_interrupt(bool deepsleep, uint32_t time_sleep_s);
+
+void sleep_save_io();
+
+void sleep_configure_io();
+
+void sleep_restore_io();
+
+int send_data(std::vector<uint8_t> data);
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libxDot-mbed5.lib	Wed Jun 03 15:25:22 2020 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/teams/MultiTech/code/libxDot-mbed5/#3101c522ae11
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Jun 03 15:25:22 2020 +0000
@@ -0,0 +1,312 @@
+#include "dot_util.h"
+#include "RadioEvent.h"
+ 
+
+/////////////////////////////////////////////////////////////////////////////
+// -------------------- 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 = 1;
+static lora::NetworkType network_type = lora::PUBLIC_LORAWAN;
+static uint8_t join_delay = 5;
+static uint8_t ack = 1;
+static bool adr = true;
+
+mDot* dot = NULL;
+lora::ChannelPlan* plan = NULL;
+
+Serial pc(USBTX, USBRX);
+
+#if !defined(CHANNEL_PLAN)
+#define CHANNEL_PLAN CP_AU915
+#endif
+int TIEMPO_Tx=30;
+int TIEMPO_REINTENTOS_CONSECUTIVOS=10;
+int cantidad_REINTENTOS=0;
+int TIEMPO_RANDOM_SUP=60;
+int TIEMPO_RANDOM_INF=20;
+
+Ticker timer_payload;
+Ticker timer_Reintento;
+Ticker timer_random_rango;
+
+int flag_payload=1;
+int flag_Tx=0;
+int flag_random_rango=0;
+
+uint32_t Tiempo_reintento_join=10;   // en seg
+uint32_t Tiempo_reintento_join_2=15; // en seg
+/////***************DECLARACION DE FUNCIONES**********************////
+
+void func_timer_payload(void);
+void func_timer_Reintento(void);
+void func_timer_random_rango(void);
+/////***************DEFINICION DE FUNCIONES**********************////
+
+void func_timer_payload(void)
+{
+    flag_payload=1;
+}
+
+void func_timer_Reintento(void)
+{
+    flag_Tx=1;
+}
+void func_timer_random_rango(void)
+{
+    flag_Tx=1;
+}
+//////////////////////////////////////////////////////////////////////
+
+int main() {
+    // Custom event handler for automatically displaying RX data
+    RadioEvent events;
+    //mDotEvent events;
+
+    pc.baud(115200);
+
+    mts::MTSLog::setLogLevel(mts::MTSLog::TRACE_LEVEL);
+
+    plan = new lora::ChannelPlan_US915();
+    MBED_ASSERT(plan);
+
+    dot = mDot::getInstance(plan);
+    MBED_ASSERT(dot);
+
+    logInfo("mbed-os library version: %d.%d.%d", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_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, network_type, ack);
+    update_ota_config_id_key(network_id, network_key, frequency_sub_band, network_type, ack);
+
+    dot->setLinkCheckThreshold(3);
+
+    // 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");
+    }
+
+    // enable or disable Adaptive Data Rate
+    dot->setAdr(adr);
+
+    // Configure the join delay
+    dot->setJoinDelay(join_delay);
+
+    // save changes to configuration
+    logInfo("saving configuration");
+    if (!dot->saveConfig()) {
+        logError("failed to save configuration");
+    }
+
+    // display configuration
+    display_config();
+
+    uint16_t valor=0;
+    uint32_t Downlink_Counter=0;
+    uint32_t Downlink_Counter_old=0;
+
+    std::vector<uint8_t> tx_data;
+    std::vector<uint8_t> rx_data;
+
+    timer_payload.attach(&func_timer_payload, TIEMPO_Tx);
+
+    
+    int flag_error_envio=0;
+    int num_intentos=0;
+    int cantidad_envios= 1 + cantidad_REINTENTOS;
+    int tiempo_rand=0;
+    
+
+    // join network if not joined
+    if (!dot->getNetworkJoinStatus()) {
+        //join_network(Tiempo_reintento_join);
+        join_network(Tiempo_reintento_join);
+    }
+
+    while (true) {
+
+        // join network if not joined
+        if (!dot->getNetworkJoinStatus()) {
+            // Elimito todos los timer para que no molesten, ademas no se van a usar hasta que no este enlazado otra vez
+            // pense que molestaban para reenlazar pero no
+            timer_payload.detach();
+
+            //join_network(Tiempo_reintento_join_2);
+            join_network(Tiempo_reintento_join_2);
+            // Una vez enlazado voy a medir y transmitir y ya activo el timer
+            flag_payload=1;
+            timer_payload.attach(&func_timer_payload, TIEMPO_Tx);
+        }
+        
+        if(flag_payload) // mediciones y armado de payload
+        {          
+
+            printf("\n\rarmando payload\n\r");
+            
+            tx_data.clear();
+            //// El payload es un valor que se va incrementando
+            valor++;
+            tx_data.push_back((valor >> 8) & 0xFF);
+            tx_data.push_back(valor & 0xFF);
+
+            // Flags
+            flag_payload=0;
+            flag_Tx=1;
+            flag_error_envio=0;
+            num_intentos=0;
+        }
+
+        if(flag_Tx)
+        {
+            if(flag_error_envio==1)
+            {
+                timer_random_rango.detach();
+                printf("\n\rElimino timer timer_random_rango\n\r");
+                
+            }
+            
+
+            // Envio
+            logInfo("send valor: %d", valor);           
+
+            if(((cantidad_envios - flag_error_envio - num_intentos) != 0) && send_data(tx_data)!=0) // si falla el envio y si todavia no se hicieron todos los reintentos
+            {
+                num_intentos++;
+                if(num_intentos==1 && ((cantidad_envios - flag_error_envio - num_intentos) != 0))// si es la primera vez que entra al if y si num de reintentos es mayor a cero
+                {
+                    timer_Reintento.attach(&func_timer_Reintento, TIEMPO_REINTENTOS_CONSECUTIVOS);
+                    printf("\n\rActivo timer timer_Tx\n\r");
+                }
+                    
+                
+            }
+            else
+            {   
+                if(flag_error_envio==0 && (cantidad_envios - flag_error_envio - num_intentos) == 0)
+                {
+                    // Activo timer 3
+                    // initialize random seed: 
+                    srand (time(NULL));
+                    
+                    // Defino el intervalo del valor random y obtengo un valor
+                    tiempo_rand = rand() % (TIEMPO_RANDOM_SUP-TIEMPO_RANDOM_INF) + TIEMPO_RANDOM_INF;
+                    //logInfo("tiempo_rand = %d\n\r\n", tiempo_rand);
+                    logInfo("tiempo_rand  = %d\n\r\n",tiempo_rand);
+
+                    timer_random_rango.attach(&func_timer_random_rango, tiempo_rand);
+                    printf("\n\rActivo timer timer_random_rango\n\r");
+
+                    flag_error_envio=1;
+                    num_intentos=0;
+
+                }
+
+                // elimino timer
+                timer_Reintento.detach();
+                printf("\n\rElimino timer timer_Tx\n\r");
+
+
+                // Actualizo el contador 
+                // en este caso siempre va a llegar un msj sea solo con el ACK o con un payload tambien
+                Downlink_Counter=dot->getDownLinkCounter();
+                Downlink_Counter_old=Downlink_Counter;
+                
+                // Recepcion Rx1
+                // Leo el buffer si hay un payload
+                // Hasta Payload de 200 Bytes recibe, maximo desconocido      
+                if(dot->recv(rx_data)==dot->MDOT_OK)
+                {
+                    printf("longitud = %d", rx_data.size());
+
+                    // Muestra todos los Bytes
+                    printf("\n\rDato %d recibido:", Downlink_Counter);
+                    for(int i=0;i<rx_data.size();i++)
+                    {
+                        printf("%02X ", rx_data[i]);
+                    }
+                    printf("\n\r");
+                    
+                    rx_data.clear();
+
+                }
+            }
+                      
+            flag_Tx=0;
+        }
+
+        // Recepcion Rx2
+        // Si llego un msje
+        if (Downlink_Counter_old!=(Downlink_Counter=dot->getDownLinkCounter()))
+        {
+             Downlink_Counter_old=Downlink_Counter;
+            // Leo el buffer
+            // MAX Payload 52 Bytes (Rx total 65 Bytes)
+            if(dot->recv(rx_data)==dot->MDOT_OK)
+            {
+                printf("longitud = %d", rx_data.size());
+                
+                // Muestra todos los Bytes
+                printf("\n\rDato %d recibido:", Downlink_Counter);
+                for(int i=0;i<rx_data.size();i++)
+                {
+                    printf("%02X ", rx_data[i]);
+                }
+                printf("\n\r");            
+
+                rx_data.clear();
+            }          
+        }
+       
+        
+    }
+ 
+    return 0;
+}
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-os.lib	Wed Jun 03 15:25:22 2020 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/mbed-os/#1bf6b20df9d3cd5f29f001ffc6f0d0fcbbb96118