Example programs for MultiTech Dot devices demonstrating how to use the Dot devices and the Dot libraries for LoRa communication.

Dependencies:   ISL29011

Dependents:   Dot-Examples-delujoc

This project has moved to github

Please see GitHub Dot-Examples

Dot Library Not Included!

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.

Dot Library Limitations

Commit messages in Dot Library repositories specify the version of the library and the version of mbed-os it was compiled against. We recommend building your application with the version of mbed-os specified in the commit message of the version of the Dot library you're using. This will ensure that you don't run into any runtime issues caused by differences in the mbed-os versions.

Example Programs Description

This application contains multiple example programs. Each example demonstrates a different way to configure and use a Dot. A short summary of each example is provided below. Common code used by multiple examples is in the dot_utils.cpp file.

All examples print logging, including RX data, on the USB debug port at 115200 baud. Each example defaults the Dot's configuration and saves the new configuration to NVM.

OTA Example

This example demonstrates configuring the Dot for OTA join mode and entering sleep or deepsleep mode between transactions with the gateway. If deepsleep mode is used, the session is saved and restored so that a rejoin is not necessary after waking up even though RAM contents have been lost. ACKs are disabled, but network link checks are configured - if enough link checks are missed, the Dot will no longer be considered joined to the network and will attempt to rejoin before transmitting more data.

AUTO_OTA Example

This example demonstrates configuring the Dot for AUTO_OTA join mode and entering sleep or deepsleep mode between transactions with the gateway. AUTO_OTA join mode automatically saves and restores the session when deepsleep mode is used, so the manual saving and restoring of the session is not necessary. ACKs are disabled, but network link checks are configured - if enough link checks are missed, the Dot will no longer be considered joined to the network and will attempt to rejoin before transmitting more data.

Manual Example

This example demonstrates configuring the Dot for MANUAL join mode and entering sleep or deepsleep mode between transactions with the gateway. The Dot must be provisioned on the gateway before its packets will be accepted! Follow these steps to provision the Dot on a Conduit gateway:

  • ssh into the conduit
  • use the lorq-query application to provision the Dot on the gateway
    • lora-query -a 01020304 A 0102030401020304 <your Dot's device ID> 01020304010203040102030401020304 01020304010203040102030401020304
    • if any of the credentials change on the Dot side, they must be updated on the gateway side as well

To provision a Dot on a third-party gateway, see the gateway or network provider documentation.

Class B Example

This example demonstrates how to configure the dot for an OTA join, how to acquire a lock on a GPS synchronized beacon, and then to subsequently enter class B mode of operation. After a successful join, the device will request to the dot-library to switch to class B. When this happens, the library will send an uplink to the network server (hence we must be joined first before entering this mode) requesting the GPS time to calculate when the next beacon is expected. Once this time elapses, the dot will open an rx window to demodulate the broadcasted beacon and fire an mDotEvent::BeaconRx event upon successful reception. After the beacon is received, the example sends an uplink which will have the class B bit in the packet's frame control set to indicate to the network server that downlinks may now be scheduled on ping slots. The lora-query application can be used to configure a Conduit gateway to communicate with a Dot in class B mode. For information on how to inform a third-party gateway that a Dot is operating in class B mode, see the gateway or network provider documentation.

Class C Example

This example demonstrates configuring the Dot for OTA join mode and communicating with the gateway using class C mode. In class C mode the gateway can send a packet to the Dot at any time, so it must be listening whenever it is not transmitting. This means that the Dot cannot enter sleep or deepsleep mode. The gateway will not immediately send packets to the Dot (outside the receive windows following a transmission from the Dot) until it is informed that the Dot is operating in class C mode. The lora-query application can be used to configure a Conduit gateway to communicate with a Dot in class C mode. For information on how to inform a third-party gateway that a Dot is operating in class C mode, see the gateway or network provider documentation.

FOTA Example

Full FOTA support is available on mDot and on xDot with external flash. See this article for details on adding external flash for xDot FOTA.

Without external flash xDot can use the FOTA example to dynamically join a multicast session only. After joining the multicast session the received Fragmentation packets could be handed to a host MCU for processing and at completion the firmware can be loaded into the xDot using the bootloader and y-modem. See xDot Developer Guide.

This example demonstrates how to incorporate over-the-air updates to an application. The example uses a Class C application. Class A or B functionality could also be used. The device will automatically enter into Class C operation for the FOTA operation, Class B would be disabled during the FOTA transfer.

  • Add the following code to allow Fota to use the Dot instance

examples/src/fota_example.cpp

    // Initialize FOTA singleton
    Fota::getInstance(dot);
  • Add fragmentation and multicast handling the the PacketRx event

examples/inc/RadioEvent.h

    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, uint32_t fcnt, bool dupRx) {
        mDotEvent::PacketRx(port, payload, size, rssi, snr, ctrl, slot, retries, address, fcnt, dupRx);

#if ACTIVE_EXAMPLE == FOTA_EXAMPLE
        if(port == 200 || port == 201 || port == 202) {
            Fota::getInstance()->processCmd(payload, port, size);
        }
#endif
    }

A definition is needed to enable FOTA.

mbed_app.json

{
    "macros": [
        "FOTA=1"
    ]
}


Peer to Peer Example

This example demonstrates configuring Dots for peer to peer communication without a gateway. It should be compiled and run on two Dots. Peer to peer communication uses LoRa modulation but uses a single higher throughput (usually 500kHz or 250kHz) datarate. It is similar to class C operation - when a Dot isn't transmitting, it's listening for packets from the other Dot. Both Dots must be configured exactly the same for peer to peer communication to be successful.


Choosing An Example Program and Channel Plan

Only the active example is compiled. The active example can be updated by changing the ACTIVE_EXAMPLE definition in the examples/example_config.h file.

By default the OTA_EXAMPLE will be compiled and the US915 channel plan will be used.

example_config.h

#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
#if !defined(ACTIVE_EXAMPLE)
#define ACTIVE_EXAMPLE  OTA_EXAMPLE
#endif

// the active channel plan is the one that will be compiled
// options are :
//      CP_US915
//      CP_AU915
//      CP_EU868
//      CP_KR920
//      CP_AS923
//      CP_AS923_JAPAN
#if !defined(CHANNEL_PLAN)
#define CHANNEL_PLAN CP_US915
#endif

#endif


Compile the AUTO_OTA_EXAMPLE and use the EU868 channel plan instead.

example_config.h

#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
#if !defined(ACTIVE_EXAMPLE)
#define ACTIVE_EXAMPLE  AUTO_OTA_EXAMPLE
#endif

// the active channel plan is the one that will be compiled
// options are :
//      CP_US915
//      CP_AU915
//      CP_EU868
//      CP_KR920
//      CP_AS923
//      CP_AS923_JAPAN
#if !defined(CHANNEL_PLAN)
#define CHANNEL_PLAN CP_EU868
#endif

#endif



Dot Libraries

Stable and development libraries are available for both mDot and xDot platforms. The library chosen must match the target platform. Compiling for the mDot platform with the xDot library or vice versa will not succeed.

mDot Library

Development library for mDot.

libmDot-dev

Stable library for mDot.

libmDot-stable


For mbed-os 5 use:

Import librarylibmDot-mbed5

Stable version of the mDot library for mbed 5. This version of the library is suitable for deployment scenarios. See lastest commit message for version of mbed-os library that has been tested against.

xDot Library

Development library for xDot.

libxDot-dev

Stable library for xDot.

libxDot-stable


For mbed-os 5 use:

Import librarylibxDot-mbed5

Stable version of the xDot library for mbed 5. This version of the library is suitable for deployment scenarios.

Committer:
jreiss
Date:
Wed Apr 24 12:50:08 2019 +0000
Revision:
33:15ea8f985c54
Parent:
31:b1d5811e3d5d
Child:
42:20f6b29a9903
Add Class B example; Update mbed-os to 5.11.1; Update mbed verison macros

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mfiore 0:a151a6350d7f 1 #include "dot_util.h"
Mike Fiore 7:724cb82a113e 2 #if defined(TARGET_XDOT_L151CC)
Mike Fiore 7:724cb82a113e 3 #include "xdot_low_power.h"
Mike Fiore 7:724cb82a113e 4 #endif
Mike Fiore 7:724cb82a113e 5
Mike Fiore 7:724cb82a113e 6 #if defined(TARGET_MTS_MDOT_F411RE)
Mike Fiore 7:724cb82a113e 7 uint32_t portA[6];
Mike Fiore 7:724cb82a113e 8 uint32_t portB[6];
Mike Fiore 7:724cb82a113e 9 uint32_t portC[6];
Mike Fiore 7:724cb82a113e 10 uint32_t portD[6];
Mike Fiore 7:724cb82a113e 11 uint32_t portH[6];
Mike Fiore 7:724cb82a113e 12 #endif
Mike Fiore 7:724cb82a113e 13
mfiore 0:a151a6350d7f 14
mfiore 0:a151a6350d7f 15 void display_config() {
mfiore 0:a151a6350d7f 16 // display configuration and library version information
Mike Fiore 10:4d0b765f7b9e 17 logInfo("=====================");
mfiore 0:a151a6350d7f 18 logInfo("general configuration");
Mike Fiore 10:4d0b765f7b9e 19 logInfo("=====================");
Mike Fiore 10:4d0b765f7b9e 20 logInfo("version ------------------ %s", dot->getId().c_str());
Mike Fiore 10:4d0b765f7b9e 21 logInfo("device ID/EUI ------------ %s", mts::Text::bin2hexString(dot->getDeviceId()).c_str());
Mike Fiore 21:09d05faf0e13 22 logInfo("default channel plan ----- %s", mDot::FrequencyBandStr(dot->getDefaultFrequencyBand()).c_str());
Mike Fiore 21:09d05faf0e13 23 logInfo("current channel plan ----- %s", mDot::FrequencyBandStr(dot->getFrequencyBand()).c_str());
Mike Fiore 21:09d05faf0e13 24 if (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) {
Mike Fiore 10:4d0b765f7b9e 25 logInfo("frequency sub band ------- %u", dot->getFrequencySubBand());
mfiore 1:c4915e00d2ce 26 }
Evan Hosseini 31:b1d5811e3d5d 27
Evan Hosseini 31:b1d5811e3d5d 28 std::string network_mode_str("Undefined");
Evan Hosseini 31:b1d5811e3d5d 29 uint8_t network_mode = dot->getPublicNetwork();
Evan Hosseini 31:b1d5811e3d5d 30 if (network_mode == lora::PRIVATE_MTS)
Evan Hosseini 31:b1d5811e3d5d 31 network_mode_str = "Private MTS";
Evan Hosseini 31:b1d5811e3d5d 32 else if (network_mode == lora::PUBLIC_LORAWAN)
Evan Hosseini 31:b1d5811e3d5d 33 network_mode_str = "Public LoRaWAN";
Evan Hosseini 31:b1d5811e3d5d 34 else if (network_mode == lora::PRIVATE_LORAWAN)
Evan Hosseini 31:b1d5811e3d5d 35 network_mode_str = "Private LoRaWAN";
Evan Hosseini 31:b1d5811e3d5d 36 logInfo("public network ----------- %s", network_mode_str.c_str());
Evan Hosseini 31:b1d5811e3d5d 37
Mike Fiore 10:4d0b765f7b9e 38 logInfo("=========================");
mfiore 0:a151a6350d7f 39 logInfo("credentials configuration");
Mike Fiore 10:4d0b765f7b9e 40 logInfo("=========================");
Mike Fiore 10:4d0b765f7b9e 41 logInfo("device class ------------- %s", dot->getClass().c_str());
Mike Fiore 10:4d0b765f7b9e 42 logInfo("network join mode -------- %s", mDot::JoinModeStr(dot->getJoinMode()).c_str());
Mike Fiore 11:d2e31743433a 43 if (dot->getJoinMode() == mDot::MANUAL || dot->getJoinMode() == mDot::PEER_TO_PEER) {
Mike Fiore 10:4d0b765f7b9e 44 logInfo("network address ---------- %s", mts::Text::bin2hexString(dot->getNetworkAddress()).c_str());
Mike Fiore 10:4d0b765f7b9e 45 logInfo("network session key------- %s", mts::Text::bin2hexString(dot->getNetworkSessionKey()).c_str());
Mike Fiore 10:4d0b765f7b9e 46 logInfo("data session key---------- %s", mts::Text::bin2hexString(dot->getDataSessionKey()).c_str());
Mike Fiore 8:e667f4a507b1 47 } else {
Mike Fiore 10:4d0b765f7b9e 48 logInfo("network name ------------- %s", dot->getNetworkName().c_str());
Mike Fiore 10:4d0b765f7b9e 49 logInfo("network phrase ----------- %s", dot->getNetworkPassphrase().c_str());
Mike Fiore 10:4d0b765f7b9e 50 logInfo("network EUI -------------- %s", mts::Text::bin2hexString(dot->getNetworkId()).c_str());
Mike Fiore 10:4d0b765f7b9e 51 logInfo("network KEY -------------- %s", mts::Text::bin2hexString(dot->getNetworkKey()).c_str());
Mike Fiore 8:e667f4a507b1 52 }
Mike Fiore 10:4d0b765f7b9e 53 logInfo("========================");
mfiore 0:a151a6350d7f 54 logInfo("communication parameters");
Mike Fiore 10:4d0b765f7b9e 55 logInfo("========================");
Mike Fiore 11:d2e31743433a 56 if (dot->getJoinMode() == mDot::PEER_TO_PEER) {
Mike Fiore 11:d2e31743433a 57 logInfo("TX frequency ------------- %lu", dot->getTxFrequency());
Mike Fiore 11:d2e31743433a 58 } else {
Mike Fiore 11:d2e31743433a 59 logInfo("acks --------------------- %s, %u attempts", dot->getAck() > 0 ? "on" : "off", dot->getAck());
Mike Fiore 11:d2e31743433a 60 }
Mike Fiore 10:4d0b765f7b9e 61 logInfo("TX datarate -------------- %s", mDot::DataRateStr(dot->getTxDataRate()).c_str());
Mike Fiore 10:4d0b765f7b9e 62 logInfo("TX power ----------------- %lu dBm", dot->getTxPower());
Mike Fiore 21:09d05faf0e13 63 logInfo("antenna gain ------------- %u dBm", dot->getAntennaGain());
Mike Fiore 21:09d05faf0e13 64 logInfo("LBT ---------------------- %s", dot->getLbtTimeUs() ? "on" : "off");
Mike Fiore 21:09d05faf0e13 65 if (dot->getLbtTimeUs()) {
Mike Fiore 21:09d05faf0e13 66 logInfo("LBT time ----------------- %lu us", dot->getLbtTimeUs());
Mike Fiore 21:09d05faf0e13 67 logInfo("LBT threshold ------------ %d dBm", dot->getLbtThreshold());
Mike Fiore 21:09d05faf0e13 68 }
mfiore 0:a151a6350d7f 69 }
mfiore 0:a151a6350d7f 70
Evan Hosseini 31:b1d5811e3d5d 71 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) {
mfiore 0:a151a6350d7f 72 std::string current_network_name = dot->getNetworkName();
mfiore 0:a151a6350d7f 73 std::string current_network_passphrase = dot->getNetworkPassphrase();
mfiore 0:a151a6350d7f 74 uint8_t current_frequency_sub_band = dot->getFrequencySubBand();
Evan Hosseini 31:b1d5811e3d5d 75 uint8_t current_network_type = dot->getPublicNetwork();
mfiore 0:a151a6350d7f 76 uint8_t current_ack = dot->getAck();
mfiore 0:a151a6350d7f 77
mfiore 0:a151a6350d7f 78 if (current_network_name != network_name) {
mfiore 0:a151a6350d7f 79 logInfo("changing network name from \"%s\" to \"%s\"", current_network_name.c_str(), network_name.c_str());
mfiore 0:a151a6350d7f 80 if (dot->setNetworkName(network_name) != mDot::MDOT_OK) {
mfiore 0:a151a6350d7f 81 logError("failed to set network name to \"%s\"", network_name.c_str());
mfiore 0:a151a6350d7f 82 }
mfiore 0:a151a6350d7f 83 }
mfiore 0:a151a6350d7f 84
mfiore 0:a151a6350d7f 85 if (current_network_passphrase != network_passphrase) {
mfiore 0:a151a6350d7f 86 logInfo("changing network passphrase from \"%s\" to \"%s\"", current_network_passphrase.c_str(), network_passphrase.c_str());
mfiore 0:a151a6350d7f 87 if (dot->setNetworkPassphrase(network_passphrase) != mDot::MDOT_OK) {
mfiore 0:a151a6350d7f 88 logError("failed to set network passphrase to \"%s\"", network_passphrase.c_str());
mfiore 0:a151a6350d7f 89 }
mfiore 0:a151a6350d7f 90 }
mfiore 0:a151a6350d7f 91
Mike Fiore 21:09d05faf0e13 92 if (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) {
Mike Fiore 21:09d05faf0e13 93 if (current_frequency_sub_band != frequency_sub_band) {
Mike Fiore 21:09d05faf0e13 94 logInfo("changing frequency sub band from %u to %u", current_frequency_sub_band, frequency_sub_band);
Mike Fiore 21:09d05faf0e13 95 if (dot->setFrequencySubBand(frequency_sub_band) != mDot::MDOT_OK) {
Mike Fiore 21:09d05faf0e13 96 logError("failed to set frequency sub band to %u", frequency_sub_band);
Mike Fiore 21:09d05faf0e13 97 }
Mike Fiore 21:09d05faf0e13 98 }
mfiore 0:a151a6350d7f 99 }
Evan Hosseini 30:2f5ae37e6c47 100
Evan Hosseini 31:b1d5811e3d5d 101 if (current_network_type != network_type) {
Evan Hosseini 31:b1d5811e3d5d 102 if (dot->setPublicNetwork(network_type) != mDot::MDOT_OK) {
Evan Hosseini 31:b1d5811e3d5d 103 logError("failed to set network type");
Evan Hosseini 30:2f5ae37e6c47 104 }
Evan Hosseini 30:2f5ae37e6c47 105 }
Evan Hosseini 30:2f5ae37e6c47 106
mfiore 0:a151a6350d7f 107 if (current_ack != ack) {
mfiore 0:a151a6350d7f 108 logInfo("changing acks from %u to %u", current_ack, ack);
mfiore 0:a151a6350d7f 109 if (dot->setAck(ack) != mDot::MDOT_OK) {
mfiore 0:a151a6350d7f 110 logError("failed to set acks to %u", ack);
mfiore 0:a151a6350d7f 111 }
mfiore 0:a151a6350d7f 112 }
mfiore 0:a151a6350d7f 113 }
mfiore 0:a151a6350d7f 114
Evan Hosseini 31:b1d5811e3d5d 115 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) {
Mike Fiore 5:97ed5f2f099e 116 std::vector<uint8_t> current_network_id = dot->getNetworkId();
Mike Fiore 5:97ed5f2f099e 117 std::vector<uint8_t> current_network_key = dot->getNetworkKey();
Mike Fiore 5:97ed5f2f099e 118 uint8_t current_frequency_sub_band = dot->getFrequencySubBand();
Evan Hosseini 31:b1d5811e3d5d 119 uint8_t current_network_type = dot->getPublicNetwork();
Mike Fiore 5:97ed5f2f099e 120 uint8_t current_ack = dot->getAck();
Mike Fiore 5:97ed5f2f099e 121
Mike Fiore 5:97ed5f2f099e 122 std::vector<uint8_t> network_id_vector(network_id, network_id + 8);
Mike Fiore 5:97ed5f2f099e 123 std::vector<uint8_t> network_key_vector(network_key, network_key + 16);
Mike Fiore 5:97ed5f2f099e 124
Mike Fiore 5:97ed5f2f099e 125 if (current_network_id != network_id_vector) {
Mike Fiore 5:97ed5f2f099e 126 logInfo("changing network ID from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_id).c_str(), mts::Text::bin2hexString(network_id_vector).c_str());
Mike Fiore 5:97ed5f2f099e 127 if (dot->setNetworkId(network_id_vector) != mDot::MDOT_OK) {
Mike Fiore 5:97ed5f2f099e 128 logError("failed to set network ID to \"%s\"", mts::Text::bin2hexString(network_id_vector).c_str());
Mike Fiore 5:97ed5f2f099e 129 }
Mike Fiore 5:97ed5f2f099e 130 }
Mike Fiore 5:97ed5f2f099e 131
Mike Fiore 5:97ed5f2f099e 132 if (current_network_key != network_key_vector) {
Mike Fiore 5:97ed5f2f099e 133 logInfo("changing network KEY from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_key).c_str(), mts::Text::bin2hexString(network_key_vector).c_str());
Mike Fiore 5:97ed5f2f099e 134 if (dot->setNetworkKey(network_key_vector) != mDot::MDOT_OK) {
Mike Fiore 5:97ed5f2f099e 135 logError("failed to set network KEY to \"%s\"", mts::Text::bin2hexString(network_key_vector).c_str());
Mike Fiore 5:97ed5f2f099e 136 }
Mike Fiore 5:97ed5f2f099e 137 }
Mike Fiore 5:97ed5f2f099e 138
Mike Fiore 21:09d05faf0e13 139 if (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) {
Mike Fiore 21:09d05faf0e13 140 if (current_frequency_sub_band != frequency_sub_band) {
Mike Fiore 21:09d05faf0e13 141 logInfo("changing frequency sub band from %u to %u", current_frequency_sub_band, frequency_sub_band);
Mike Fiore 21:09d05faf0e13 142 if (dot->setFrequencySubBand(frequency_sub_band) != mDot::MDOT_OK) {
Mike Fiore 21:09d05faf0e13 143 logError("failed to set frequency sub band to %u", frequency_sub_band);
Mike Fiore 21:09d05faf0e13 144 }
Mike Fiore 21:09d05faf0e13 145 }
Mike Fiore 5:97ed5f2f099e 146 }
Mike Fiore 5:97ed5f2f099e 147
Evan Hosseini 31:b1d5811e3d5d 148 if (current_network_type != network_type) {
Evan Hosseini 31:b1d5811e3d5d 149 if (dot->setPublicNetwork(network_type) != mDot::MDOT_OK) {
Evan Hosseini 31:b1d5811e3d5d 150 logError("failed to set network type");
Mike Fiore 5:97ed5f2f099e 151 }
Mike Fiore 5:97ed5f2f099e 152 }
Mike Fiore 5:97ed5f2f099e 153
Mike Fiore 5:97ed5f2f099e 154 if (current_ack != ack) {
Mike Fiore 5:97ed5f2f099e 155 logInfo("changing acks from %u to %u", current_ack, ack);
Mike Fiore 5:97ed5f2f099e 156 if (dot->setAck(ack) != mDot::MDOT_OK) {
Mike Fiore 5:97ed5f2f099e 157 logError("failed to set acks to %u", ack);
Mike Fiore 5:97ed5f2f099e 158 }
Mike Fiore 5:97ed5f2f099e 159 }
Mike Fiore 5:97ed5f2f099e 160 }
Mike Fiore 5:97ed5f2f099e 161
Evan Hosseini 31:b1d5811e3d5d 162 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) {
Mike Fiore 8:e667f4a507b1 163 std::vector<uint8_t> current_network_address = dot->getNetworkAddress();
Mike Fiore 8:e667f4a507b1 164 std::vector<uint8_t> current_network_session_key = dot->getNetworkSessionKey();
Mike Fiore 8:e667f4a507b1 165 std::vector<uint8_t> current_data_session_key = dot->getDataSessionKey();
Mike Fiore 8:e667f4a507b1 166 uint8_t current_frequency_sub_band = dot->getFrequencySubBand();
Evan Hosseini 31:b1d5811e3d5d 167 uint8_t current_network_type = dot->getPublicNetwork();
Mike Fiore 8:e667f4a507b1 168 uint8_t current_ack = dot->getAck();
Mike Fiore 8:e667f4a507b1 169
Mike Fiore 8:e667f4a507b1 170 std::vector<uint8_t> network_address_vector(network_address, network_address + 4);
Mike Fiore 8:e667f4a507b1 171 std::vector<uint8_t> network_session_key_vector(network_session_key, network_session_key + 16);
Mike Fiore 8:e667f4a507b1 172 std::vector<uint8_t> data_session_key_vector(data_session_key, data_session_key + 16);
Mike Fiore 8:e667f4a507b1 173
Mike Fiore 8:e667f4a507b1 174 if (current_network_address != network_address_vector) {
Mike Fiore 8:e667f4a507b1 175 logInfo("changing network address from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_address).c_str(), mts::Text::bin2hexString(network_address_vector).c_str());
Mike Fiore 8:e667f4a507b1 176 if (dot->setNetworkAddress(network_address_vector) != mDot::MDOT_OK) {
Mike Fiore 8:e667f4a507b1 177 logError("failed to set network address to \"%s\"", mts::Text::bin2hexString(network_address_vector).c_str());
Mike Fiore 8:e667f4a507b1 178 }
Mike Fiore 8:e667f4a507b1 179 }
Mike Fiore 8:e667f4a507b1 180
Mike Fiore 8:e667f4a507b1 181 if (current_network_session_key != network_session_key_vector) {
Mike Fiore 8:e667f4a507b1 182 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());
Mike Fiore 8:e667f4a507b1 183 if (dot->setNetworkSessionKey(network_session_key_vector) != mDot::MDOT_OK) {
Mike Fiore 8:e667f4a507b1 184 logError("failed to set network session key to \"%s\"", mts::Text::bin2hexString(network_session_key_vector).c_str());
Mike Fiore 8:e667f4a507b1 185 }
Mike Fiore 8:e667f4a507b1 186 }
Mike Fiore 8:e667f4a507b1 187
Mike Fiore 8:e667f4a507b1 188 if (current_data_session_key != data_session_key_vector) {
Mike Fiore 8:e667f4a507b1 189 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());
Mike Fiore 8:e667f4a507b1 190 if (dot->setDataSessionKey(data_session_key_vector) != mDot::MDOT_OK) {
Mike Fiore 8:e667f4a507b1 191 logError("failed to set data session key to \"%s\"", mts::Text::bin2hexString(data_session_key_vector).c_str());
Mike Fiore 8:e667f4a507b1 192 }
Mike Fiore 8:e667f4a507b1 193 }
Mike Fiore 8:e667f4a507b1 194
Mike Fiore 8:e667f4a507b1 195 if (current_frequency_sub_band != frequency_sub_band) {
Mike Fiore 8:e667f4a507b1 196 logInfo("changing frequency sub band from %u to %u", current_frequency_sub_band, frequency_sub_band);
Mike Fiore 8:e667f4a507b1 197 if (dot->setFrequencySubBand(frequency_sub_band) != mDot::MDOT_OK) {
Mike Fiore 8:e667f4a507b1 198 logError("failed to set frequency sub band to %u", frequency_sub_band);
Mike Fiore 8:e667f4a507b1 199 }
Mike Fiore 8:e667f4a507b1 200 }
Mike Fiore 8:e667f4a507b1 201
Evan Hosseini 31:b1d5811e3d5d 202 if (current_network_type != network_type) {
Evan Hosseini 31:b1d5811e3d5d 203 if (dot->setPublicNetwork(network_type) != mDot::MDOT_OK) {
Evan Hosseini 31:b1d5811e3d5d 204 logError("failed to set network type");
Mike Fiore 8:e667f4a507b1 205 }
Mike Fiore 8:e667f4a507b1 206 }
Mike Fiore 8:e667f4a507b1 207
Mike Fiore 8:e667f4a507b1 208 if (current_ack != ack) {
Mike Fiore 8:e667f4a507b1 209 logInfo("changing acks from %u to %u", current_ack, ack);
Mike Fiore 8:e667f4a507b1 210 if (dot->setAck(ack) != mDot::MDOT_OK) {
Mike Fiore 8:e667f4a507b1 211 logError("failed to set acks to %u", ack);
Mike Fiore 8:e667f4a507b1 212 }
Mike Fiore 8:e667f4a507b1 213 }
Mike Fiore 8:e667f4a507b1 214 }
Mike Fiore 8:e667f4a507b1 215
Mike Fiore 11:d2e31743433a 216 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) {
Mike Fiore 11:d2e31743433a 217 std::vector<uint8_t> current_network_address = dot->getNetworkAddress();
Mike Fiore 11:d2e31743433a 218 std::vector<uint8_t> current_network_session_key = dot->getNetworkSessionKey();
Mike Fiore 11:d2e31743433a 219 std::vector<uint8_t> current_data_session_key = dot->getDataSessionKey();
Mike Fiore 11:d2e31743433a 220 uint32_t current_tx_frequency = dot->getTxFrequency();
Mike Fiore 11:d2e31743433a 221 uint8_t current_tx_datarate = dot->getTxDataRate();
Mike Fiore 11:d2e31743433a 222 uint8_t current_tx_power = dot->getTxPower();
Mike Fiore 11:d2e31743433a 223
Mike Fiore 11:d2e31743433a 224 std::vector<uint8_t> network_address_vector(network_address, network_address + 4);
Mike Fiore 11:d2e31743433a 225 std::vector<uint8_t> network_session_key_vector(network_session_key, network_session_key + 16);
Mike Fiore 11:d2e31743433a 226 std::vector<uint8_t> data_session_key_vector(data_session_key, data_session_key + 16);
Mike Fiore 11:d2e31743433a 227
Mike Fiore 11:d2e31743433a 228 if (current_network_address != network_address_vector) {
Mike Fiore 11:d2e31743433a 229 logInfo("changing network address from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_address).c_str(), mts::Text::bin2hexString(network_address_vector).c_str());
Mike Fiore 11:d2e31743433a 230 if (dot->setNetworkAddress(network_address_vector) != mDot::MDOT_OK) {
Mike Fiore 11:d2e31743433a 231 logError("failed to set network address to \"%s\"", mts::Text::bin2hexString(network_address_vector).c_str());
Mike Fiore 11:d2e31743433a 232 }
Mike Fiore 11:d2e31743433a 233 }
Mike Fiore 11:d2e31743433a 234
Mike Fiore 11:d2e31743433a 235 if (current_network_session_key != network_session_key_vector) {
Mike Fiore 11:d2e31743433a 236 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());
Mike Fiore 11:d2e31743433a 237 if (dot->setNetworkSessionKey(network_session_key_vector) != mDot::MDOT_OK) {
Mike Fiore 11:d2e31743433a 238 logError("failed to set network session key to \"%s\"", mts::Text::bin2hexString(network_session_key_vector).c_str());
Mike Fiore 11:d2e31743433a 239 }
Mike Fiore 11:d2e31743433a 240 }
Mike Fiore 11:d2e31743433a 241
Mike Fiore 11:d2e31743433a 242 if (current_data_session_key != data_session_key_vector) {
Mike Fiore 11:d2e31743433a 243 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());
Mike Fiore 11:d2e31743433a 244 if (dot->setDataSessionKey(data_session_key_vector) != mDot::MDOT_OK) {
Mike Fiore 11:d2e31743433a 245 logError("failed to set data session key to \"%s\"", mts::Text::bin2hexString(data_session_key_vector).c_str());
Mike Fiore 11:d2e31743433a 246 }
Mike Fiore 11:d2e31743433a 247 }
Mike Fiore 11:d2e31743433a 248
Mike Fiore 11:d2e31743433a 249 if (current_tx_frequency != tx_frequency) {
Mike Fiore 11:d2e31743433a 250 logInfo("changing TX frequency from %lu to %lu", current_tx_frequency, tx_frequency);
Mike Fiore 11:d2e31743433a 251 if (dot->setTxFrequency(tx_frequency) != mDot::MDOT_OK) {
Mike Fiore 11:d2e31743433a 252 logError("failed to set TX frequency to %lu", tx_frequency);
Mike Fiore 11:d2e31743433a 253 }
Mike Fiore 11:d2e31743433a 254 }
Mike Fiore 11:d2e31743433a 255
Mike Fiore 11:d2e31743433a 256 if (current_tx_datarate != tx_datarate) {
Mike Fiore 11:d2e31743433a 257 logInfo("changing TX datarate from %u to %u", current_tx_datarate, tx_datarate);
Mike Fiore 11:d2e31743433a 258 if (dot->setTxDataRate(tx_datarate) != mDot::MDOT_OK) {
Mike Fiore 11:d2e31743433a 259 logError("failed to set TX datarate to %u", tx_datarate);
Mike Fiore 11:d2e31743433a 260 }
Mike Fiore 11:d2e31743433a 261 }
Mike Fiore 11:d2e31743433a 262
Mike Fiore 11:d2e31743433a 263 if (current_tx_power != tx_power) {
Mike Fiore 11:d2e31743433a 264 logInfo("changing TX power from %u to %u", current_tx_power, tx_power);
Mike Fiore 11:d2e31743433a 265 if (dot->setTxPower(tx_power) != mDot::MDOT_OK) {
Mike Fiore 11:d2e31743433a 266 logError("failed to set TX power to %u", tx_power);
Mike Fiore 11:d2e31743433a 267 }
Mike Fiore 11:d2e31743433a 268 }
Mike Fiore 11:d2e31743433a 269 }
Mike Fiore 11:d2e31743433a 270
Mike Fiore 15:364df461110f 271 void update_network_link_check_config(uint8_t link_check_count, uint8_t link_check_threshold) {
Mike Fiore 15:364df461110f 272 uint8_t current_link_check_count = dot->getLinkCheckCount();
Mike Fiore 15:364df461110f 273 uint8_t current_link_check_threshold = dot->getLinkCheckThreshold();
Mike Fiore 15:364df461110f 274
Mike Fiore 15:364df461110f 275 if (current_link_check_count != link_check_count) {
Mike Fiore 15:364df461110f 276 logInfo("changing link check count from %u to %u", current_link_check_count, link_check_count);
Mike Fiore 15:364df461110f 277 if (dot->setLinkCheckCount(link_check_count) != mDot::MDOT_OK) {
Mike Fiore 15:364df461110f 278 logError("failed to set link check count to %u", link_check_count);
Mike Fiore 15:364df461110f 279 }
Mike Fiore 15:364df461110f 280 }
Mike Fiore 15:364df461110f 281
Mike Fiore 15:364df461110f 282 if (current_link_check_threshold != link_check_threshold) {
Mike Fiore 15:364df461110f 283 logInfo("changing link check threshold from %u to %u", current_link_check_threshold, link_check_threshold);
Mike Fiore 15:364df461110f 284 if (dot->setLinkCheckThreshold(link_check_threshold) != mDot::MDOT_OK) {
Mike Fiore 15:364df461110f 285 logError("failed to set link check threshold to %u", link_check_threshold);
Mike Fiore 15:364df461110f 286 }
Mike Fiore 15:364df461110f 287 }
Mike Fiore 15:364df461110f 288 }
Mike Fiore 15:364df461110f 289
mfiore 0:a151a6350d7f 290 void join_network() {
mfiore 0:a151a6350d7f 291 int32_t j_attempts = 0;
mfiore 0:a151a6350d7f 292 int32_t ret = mDot::MDOT_ERROR;
mfiore 0:a151a6350d7f 293
mfiore 0:a151a6350d7f 294 // attempt to join the network
mfiore 0:a151a6350d7f 295 while (ret != mDot::MDOT_OK) {
mfiore 0:a151a6350d7f 296 logInfo("attempt %d to join network", ++j_attempts);
mfiore 0:a151a6350d7f 297 ret = dot->joinNetwork();
mfiore 0:a151a6350d7f 298 if (ret != mDot::MDOT_OK) {
mfiore 0:a151a6350d7f 299 logError("failed to join network %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
mfiore 0:a151a6350d7f 300 // in some frequency bands we need to wait until another channel is available before transmitting again
mfiore 0:a151a6350d7f 301 uint32_t delay_s = (dot->getNextTxMs() / 1000) + 1;
Evan Hosseini 25:56f7775c702f 302 if (delay_s < 5) {
mfiore 0:a151a6350d7f 303 logInfo("waiting %lu s until next free channel", delay_s);
mfiore 0:a151a6350d7f 304 wait(delay_s);
mfiore 0:a151a6350d7f 305 } else {
mfiore 0:a151a6350d7f 306 logInfo("sleeping %lu s until next free channel", delay_s);
mfiore 0:a151a6350d7f 307 dot->sleep(delay_s, mDot::RTC_ALARM, false);
mfiore 0:a151a6350d7f 308 }
mfiore 0:a151a6350d7f 309 }
mfiore 0:a151a6350d7f 310 }
mfiore 0:a151a6350d7f 311 }
mfiore 0:a151a6350d7f 312
mfiore 0:a151a6350d7f 313 void sleep_wake_rtc_only(bool deepsleep) {
mfiore 0:a151a6350d7f 314 // in some frequency bands we need to wait until another channel is available before transmitting again
mfiore 0:a151a6350d7f 315 // wait at least 10s between transmissions
mfiore 0:a151a6350d7f 316 uint32_t delay_s = dot->getNextTxMs() / 1000;
mfiore 0:a151a6350d7f 317 if (delay_s < 10) {
mfiore 0:a151a6350d7f 318 delay_s = 10;
mfiore 0:a151a6350d7f 319 }
mfiore 0:a151a6350d7f 320
mfiore 0:a151a6350d7f 321 logInfo("%ssleeping %lus", deepsleep ? "deep" : "", delay_s);
mfiore 0:a151a6350d7f 322 logInfo("application will %s after waking up", deepsleep ? "execute from beginning" : "resume");
Mike Fiore 7:724cb82a113e 323
Mike Fiore 7:724cb82a113e 324 // lowest current consumption in sleep mode can only be achieved by configuring IOs as analog inputs with no pull resistors
Mike Fiore 7:724cb82a113e 325 // the library handles all internal IOs automatically, but the external IOs are the application's responsibility
Mike Fiore 7:724cb82a113e 326 // certain IOs may require internal pullup or pulldown resistors because leaving them floating would cause extra current consumption
Mike Fiore 7:724cb82a113e 327 // for xDot: UART_*, I2C_*, SPI_*, GPIO*, WAKE
Mike Fiore 7:724cb82a113e 328 // for mDot: XBEE_*, USBTX, USBRX, PB_0, PB_1
Mike Fiore 7:724cb82a113e 329 // steps are:
Mike Fiore 7:724cb82a113e 330 // * save IO configuration
Mike Fiore 7:724cb82a113e 331 // * configure IOs to reduce current consumption
Mike Fiore 7:724cb82a113e 332 // * sleep
Mike Fiore 7:724cb82a113e 333 // * restore IO configuration
Mike Fiore 7:724cb82a113e 334 if (! deepsleep) {
Mike Fiore 7:724cb82a113e 335 // save the GPIO state.
Mike Fiore 7:724cb82a113e 336 sleep_save_io();
Mike Fiore 7:724cb82a113e 337
Mike Fiore 7:724cb82a113e 338 // configure GPIOs for lowest current
Mike Fiore 7:724cb82a113e 339 sleep_configure_io();
Mike Fiore 7:724cb82a113e 340 }
mfiore 0:a151a6350d7f 341
mfiore 0:a151a6350d7f 342 // go to sleep/deepsleep for delay_s seconds and wake using the RTC alarm
mfiore 0:a151a6350d7f 343 dot->sleep(delay_s, mDot::RTC_ALARM, deepsleep);
Mike Fiore 7:724cb82a113e 344
Mike Fiore 7:724cb82a113e 345 if (! deepsleep) {
Mike Fiore 7:724cb82a113e 346 // restore the GPIO state.
Mike Fiore 7:724cb82a113e 347 sleep_restore_io();
Mike Fiore 7:724cb82a113e 348 }
mfiore 0:a151a6350d7f 349 }
mfiore 0:a151a6350d7f 350
mfiore 0:a151a6350d7f 351 void sleep_wake_interrupt_only(bool deepsleep) {
mfiore 0:a151a6350d7f 352 #if defined (TARGET_XDOT_L151CC)
mfiore 0:a151a6350d7f 353 if (deepsleep) {
mfiore 0:a151a6350d7f 354 // for xDot, WAKE pin (connected to S2 on xDot-DK) is the only pin that can wake the processor from deepsleep
mfiore 0:a151a6350d7f 355 // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call
mfiore 0:a151a6350d7f 356 } else {
mfiore 0:a151a6350d7f 357 // configure WAKE pin (connected to S2 on xDot-DK) as the pin that will wake the xDot from low power modes
mfiore 0:a151a6350d7f 358 // other pins can be confgured instead: GPIO0-3 or UART_RX
mfiore 0:a151a6350d7f 359 dot->setWakePin(WAKE);
mfiore 0:a151a6350d7f 360 }
mfiore 0:a151a6350d7f 361
mfiore 2:ffac7b141b72 362 logInfo("%ssleeping until interrupt on %s pin", deepsleep ? "deep" : "", deepsleep ? "WAKE" : mDot::pinName2Str(dot->getWakePin()).c_str());
mfiore 0:a151a6350d7f 363 #else
Mike Fiore 7:724cb82a113e 364
mfiore 0:a151a6350d7f 365 if (deepsleep) {
mfiore 0:a151a6350d7f 366 // for mDot, XBEE_DIO7 pin is the only pin that can wake the processor from deepsleep
mfiore 0:a151a6350d7f 367 // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call
mfiore 0:a151a6350d7f 368 } else {
mfiore 0:a151a6350d7f 369 // configure XBEE_DIO7 pin as the pin that will wake the mDot from low power modes
mfiore 0:a151a6350d7f 370 // other pins can be confgured instead: XBEE_DIO2-6, XBEE_DI8, XBEE_DIN
mfiore 0:a151a6350d7f 371 dot->setWakePin(XBEE_DIO7);
mfiore 0:a151a6350d7f 372 }
mfiore 0:a151a6350d7f 373
mfiore 2:ffac7b141b72 374 logInfo("%ssleeping until interrupt on %s pin", deepsleep ? "deep" : "", deepsleep ? "DIO7" : mDot::pinName2Str(dot->getWakePin()).c_str());
mfiore 0:a151a6350d7f 375 #endif
mfiore 0:a151a6350d7f 376
mfiore 0:a151a6350d7f 377 logInfo("application will %s after waking up", deepsleep ? "execute from beginning" : "resume");
Mike Fiore 7:724cb82a113e 378
Mike Fiore 7:724cb82a113e 379 // lowest current consumption in sleep mode can only be achieved by configuring IOs as analog inputs with no pull resistors
Mike Fiore 7:724cb82a113e 380 // the library handles all internal IOs automatically, but the external IOs are the application's responsibility
Mike Fiore 7:724cb82a113e 381 // certain IOs may require internal pullup or pulldown resistors because leaving them floating would cause extra current consumption
Mike Fiore 7:724cb82a113e 382 // for xDot: UART_*, I2C_*, SPI_*, GPIO*, WAKE
Mike Fiore 7:724cb82a113e 383 // for mDot: XBEE_*, USBTX, USBRX, PB_0, PB_1
Mike Fiore 7:724cb82a113e 384 // steps are:
Mike Fiore 7:724cb82a113e 385 // * save IO configuration
Mike Fiore 7:724cb82a113e 386 // * configure IOs to reduce current consumption
Mike Fiore 7:724cb82a113e 387 // * sleep
Mike Fiore 7:724cb82a113e 388 // * restore IO configuration
Mike Fiore 7:724cb82a113e 389 if (! deepsleep) {
Mike Fiore 7:724cb82a113e 390 // save the GPIO state.
Mike Fiore 7:724cb82a113e 391 sleep_save_io();
Mike Fiore 7:724cb82a113e 392
Mike Fiore 7:724cb82a113e 393 // configure GPIOs for lowest current
Mike Fiore 7:724cb82a113e 394 sleep_configure_io();
Mike Fiore 7:724cb82a113e 395 }
mfiore 0:a151a6350d7f 396
mfiore 0:a151a6350d7f 397 // go to sleep/deepsleep and wake on rising edge of configured wake pin (only the WAKE pin in deepsleep)
mfiore 0:a151a6350d7f 398 // since we're not waking on the RTC alarm, the interval is ignored
mfiore 0:a151a6350d7f 399 dot->sleep(0, mDot::INTERRUPT, deepsleep);
Mike Fiore 7:724cb82a113e 400
Mike Fiore 7:724cb82a113e 401 if (! deepsleep) {
Mike Fiore 7:724cb82a113e 402 // restore the GPIO state.
Mike Fiore 7:724cb82a113e 403 sleep_restore_io();
Mike Fiore 7:724cb82a113e 404 }
mfiore 0:a151a6350d7f 405 }
mfiore 0:a151a6350d7f 406
mfiore 0:a151a6350d7f 407 void sleep_wake_rtc_or_interrupt(bool deepsleep) {
mfiore 0:a151a6350d7f 408 // in some frequency bands we need to wait until another channel is available before transmitting again
mfiore 0:a151a6350d7f 409 // wait at least 10s between transmissions
mfiore 0:a151a6350d7f 410 uint32_t delay_s = dot->getNextTxMs() / 1000;
mfiore 0:a151a6350d7f 411 if (delay_s < 10) {
mfiore 0:a151a6350d7f 412 delay_s = 10;
mfiore 0:a151a6350d7f 413 }
mfiore 0:a151a6350d7f 414
mfiore 0:a151a6350d7f 415 #if defined (TARGET_XDOT_L151CC)
mfiore 0:a151a6350d7f 416 if (deepsleep) {
mfiore 0:a151a6350d7f 417 // for xDot, WAKE pin (connected to S2 on xDot-DK) is the only pin that can wake the processor from deepsleep
mfiore 0:a151a6350d7f 418 // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call
mfiore 0:a151a6350d7f 419 } else {
mfiore 0:a151a6350d7f 420 // configure WAKE pin (connected to S2 on xDot-DK) as the pin that will wake the xDot from low power modes
mfiore 0:a151a6350d7f 421 // other pins can be confgured instead: GPIO0-3 or UART_RX
mfiore 0:a151a6350d7f 422 dot->setWakePin(WAKE);
mfiore 0:a151a6350d7f 423 }
mfiore 0:a151a6350d7f 424
mfiore 2:ffac7b141b72 425 logInfo("%ssleeping %lus or until interrupt on %s pin", deepsleep ? "deep" : "", delay_s, deepsleep ? "WAKE" : mDot::pinName2Str(dot->getWakePin()).c_str());
mfiore 0:a151a6350d7f 426 #else
mfiore 0:a151a6350d7f 427 if (deepsleep) {
mfiore 0:a151a6350d7f 428 // for mDot, XBEE_DIO7 pin is the only pin that can wake the processor from deepsleep
mfiore 0:a151a6350d7f 429 // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call
mfiore 0:a151a6350d7f 430 } else {
mfiore 0:a151a6350d7f 431 // configure XBEE_DIO7 pin as the pin that will wake the mDot from low power modes
mfiore 0:a151a6350d7f 432 // other pins can be confgured instead: XBEE_DIO2-6, XBEE_DI8, XBEE_DIN
mfiore 0:a151a6350d7f 433 dot->setWakePin(XBEE_DIO7);
mfiore 0:a151a6350d7f 434 }
mfiore 0:a151a6350d7f 435
mfiore 2:ffac7b141b72 436 logInfo("%ssleeping %lus or until interrupt on %s pin", deepsleep ? "deep" : "", delay_s, deepsleep ? "DIO7" : mDot::pinName2Str(dot->getWakePin()).c_str());
mfiore 0:a151a6350d7f 437 #endif
mfiore 0:a151a6350d7f 438
mfiore 0:a151a6350d7f 439 logInfo("application will %s after waking up", deepsleep ? "execute from beginning" : "resume");
mfiore 0:a151a6350d7f 440
Mike Fiore 7:724cb82a113e 441 // lowest current consumption in sleep mode can only be achieved by configuring IOs as analog inputs with no pull resistors
Mike Fiore 7:724cb82a113e 442 // the library handles all internal IOs automatically, but the external IOs are the application's responsibility
Mike Fiore 7:724cb82a113e 443 // certain IOs may require internal pullup or pulldown resistors because leaving them floating would cause extra current consumption
Mike Fiore 7:724cb82a113e 444 // for xDot: UART_*, I2C_*, SPI_*, GPIO*, WAKE
Mike Fiore 7:724cb82a113e 445 // for mDot: XBEE_*, USBTX, USBRX, PB_0, PB_1
Mike Fiore 7:724cb82a113e 446 // steps are:
Mike Fiore 7:724cb82a113e 447 // * save IO configuration
Mike Fiore 7:724cb82a113e 448 // * configure IOs to reduce current consumption
Mike Fiore 7:724cb82a113e 449 // * sleep
Mike Fiore 7:724cb82a113e 450 // * restore IO configuration
Mike Fiore 7:724cb82a113e 451 if (! deepsleep) {
Mike Fiore 7:724cb82a113e 452 // save the GPIO state.
Mike Fiore 7:724cb82a113e 453 sleep_save_io();
Mike Fiore 7:724cb82a113e 454
Mike Fiore 7:724cb82a113e 455 // configure GPIOs for lowest current
Mike Fiore 7:724cb82a113e 456 sleep_configure_io();
Mike Fiore 7:724cb82a113e 457 }
Mike Fiore 7:724cb82a113e 458
mfiore 0:a151a6350d7f 459 // 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)
mfiore 0:a151a6350d7f 460 // whichever comes first will wake the xDot
mfiore 0:a151a6350d7f 461 dot->sleep(delay_s, mDot::RTC_ALARM_OR_INTERRUPT, deepsleep);
Mike Fiore 7:724cb82a113e 462
Mike Fiore 7:724cb82a113e 463 if (! deepsleep) {
Mike Fiore 7:724cb82a113e 464 // restore the GPIO state.
Mike Fiore 7:724cb82a113e 465 sleep_restore_io();
Mike Fiore 7:724cb82a113e 466 }
Mike Fiore 7:724cb82a113e 467 }
Mike Fiore 7:724cb82a113e 468
Mike Fiore 7:724cb82a113e 469 void sleep_save_io() {
Mike Fiore 7:724cb82a113e 470 #if defined(TARGET_XDOT_L151CC)
Mike Fiore 7:724cb82a113e 471 xdot_save_gpio_state();
Mike Fiore 7:724cb82a113e 472 #else
Mike Fiore 7:724cb82a113e 473 portA[0] = GPIOA->MODER;
Mike Fiore 7:724cb82a113e 474 portA[1] = GPIOA->OTYPER;
Mike Fiore 7:724cb82a113e 475 portA[2] = GPIOA->OSPEEDR;
Mike Fiore 7:724cb82a113e 476 portA[3] = GPIOA->PUPDR;
Mike Fiore 7:724cb82a113e 477 portA[4] = GPIOA->AFR[0];
Mike Fiore 7:724cb82a113e 478 portA[5] = GPIOA->AFR[1];
Mike Fiore 7:724cb82a113e 479
Mike Fiore 7:724cb82a113e 480 portB[0] = GPIOB->MODER;
Mike Fiore 7:724cb82a113e 481 portB[1] = GPIOB->OTYPER;
Mike Fiore 7:724cb82a113e 482 portB[2] = GPIOB->OSPEEDR;
Mike Fiore 7:724cb82a113e 483 portB[3] = GPIOB->PUPDR;
Mike Fiore 7:724cb82a113e 484 portB[4] = GPIOB->AFR[0];
Mike Fiore 7:724cb82a113e 485 portB[5] = GPIOB->AFR[1];
Mike Fiore 7:724cb82a113e 486
Mike Fiore 7:724cb82a113e 487 portC[0] = GPIOC->MODER;
Mike Fiore 7:724cb82a113e 488 portC[1] = GPIOC->OTYPER;
Mike Fiore 7:724cb82a113e 489 portC[2] = GPIOC->OSPEEDR;
Mike Fiore 7:724cb82a113e 490 portC[3] = GPIOC->PUPDR;
Mike Fiore 7:724cb82a113e 491 portC[4] = GPIOC->AFR[0];
Mike Fiore 7:724cb82a113e 492 portC[5] = GPIOC->AFR[1];
Mike Fiore 7:724cb82a113e 493
Mike Fiore 7:724cb82a113e 494 portD[0] = GPIOD->MODER;
Mike Fiore 7:724cb82a113e 495 portD[1] = GPIOD->OTYPER;
Mike Fiore 7:724cb82a113e 496 portD[2] = GPIOD->OSPEEDR;
Mike Fiore 7:724cb82a113e 497 portD[3] = GPIOD->PUPDR;
Mike Fiore 7:724cb82a113e 498 portD[4] = GPIOD->AFR[0];
Mike Fiore 7:724cb82a113e 499 portD[5] = GPIOD->AFR[1];
Mike Fiore 7:724cb82a113e 500
Mike Fiore 7:724cb82a113e 501 portH[0] = GPIOH->MODER;
Mike Fiore 7:724cb82a113e 502 portH[1] = GPIOH->OTYPER;
Mike Fiore 7:724cb82a113e 503 portH[2] = GPIOH->OSPEEDR;
Mike Fiore 7:724cb82a113e 504 portH[3] = GPIOH->PUPDR;
Mike Fiore 7:724cb82a113e 505 portH[4] = GPIOH->AFR[0];
Mike Fiore 7:724cb82a113e 506 portH[5] = GPIOH->AFR[1];
Mike Fiore 7:724cb82a113e 507 #endif
Mike Fiore 7:724cb82a113e 508 }
Mike Fiore 7:724cb82a113e 509
Mike Fiore 7:724cb82a113e 510 void sleep_configure_io() {
Mike Fiore 7:724cb82a113e 511 #if defined(TARGET_XDOT_L151CC)
Mike Fiore 7:724cb82a113e 512 // GPIO Ports Clock Enable
Mike Fiore 7:724cb82a113e 513 __GPIOA_CLK_ENABLE();
Mike Fiore 7:724cb82a113e 514 __GPIOB_CLK_ENABLE();
Mike Fiore 7:724cb82a113e 515 __GPIOC_CLK_ENABLE();
Mike Fiore 7:724cb82a113e 516 __GPIOH_CLK_ENABLE();
Mike Fiore 7:724cb82a113e 517
Mike Fiore 7:724cb82a113e 518 GPIO_InitTypeDef GPIO_InitStruct;
Mike Fiore 7:724cb82a113e 519
Mike Fiore 7:724cb82a113e 520 // UART1_TX, UART1_RTS & UART1_CTS to analog nopull - RX could be a wakeup source
Mike Fiore 7:724cb82a113e 521 GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_11 | GPIO_PIN_12;
Mike Fiore 7:724cb82a113e 522 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 7:724cb82a113e 523 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 7:724cb82a113e 524 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 7:724cb82a113e 525
Mike Fiore 7:724cb82a113e 526 // I2C_SDA & I2C_SCL to analog nopull
Mike Fiore 7:724cb82a113e 527 GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;
Mike Fiore 7:724cb82a113e 528 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 7:724cb82a113e 529 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 7:724cb82a113e 530 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
Mike Fiore 7:724cb82a113e 531
Mike Fiore 7:724cb82a113e 532 // SPI_MOSI, SPI_MISO, SPI_SCK, & SPI_NSS to analog nopull
Mike Fiore 7:724cb82a113e 533 GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
Mike Fiore 7:724cb82a113e 534 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 7:724cb82a113e 535 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 7:724cb82a113e 536 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
Mike Fiore 7:724cb82a113e 537
Mike Fiore 7:724cb82a113e 538 // iterate through potential wake pins - leave the configured wake pin alone if one is needed
Mike Fiore 7:724cb82a113e 539 if (dot->getWakePin() != WAKE || dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 7:724cb82a113e 540 GPIO_InitStruct.Pin = GPIO_PIN_0;
Mike Fiore 7:724cb82a113e 541 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 7:724cb82a113e 542 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 7:724cb82a113e 543 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 7:724cb82a113e 544 }
Mike Fiore 7:724cb82a113e 545 if (dot->getWakePin() != GPIO0 || dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 7:724cb82a113e 546 GPIO_InitStruct.Pin = GPIO_PIN_4;
Mike Fiore 7:724cb82a113e 547 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 7:724cb82a113e 548 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 7:724cb82a113e 549 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 7:724cb82a113e 550 }
Mike Fiore 7:724cb82a113e 551 if (dot->getWakePin() != GPIO1 || dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 7:724cb82a113e 552 GPIO_InitStruct.Pin = GPIO_PIN_5;
Mike Fiore 7:724cb82a113e 553 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 7:724cb82a113e 554 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 7:724cb82a113e 555 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 7:724cb82a113e 556 }
Mike Fiore 7:724cb82a113e 557 if (dot->getWakePin() != GPIO2 || dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 7:724cb82a113e 558 GPIO_InitStruct.Pin = GPIO_PIN_0;
Mike Fiore 7:724cb82a113e 559 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 7:724cb82a113e 560 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 7:724cb82a113e 561 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
Mike Fiore 7:724cb82a113e 562 }
Mike Fiore 7:724cb82a113e 563 if (dot->getWakePin() != GPIO3 || dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 7:724cb82a113e 564 GPIO_InitStruct.Pin = GPIO_PIN_2;
Mike Fiore 7:724cb82a113e 565 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 7:724cb82a113e 566 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 7:724cb82a113e 567 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
Mike Fiore 7:724cb82a113e 568 }
Mike Fiore 7:724cb82a113e 569 if (dot->getWakePin() != UART1_RX || dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 7:724cb82a113e 570 GPIO_InitStruct.Pin = GPIO_PIN_10;
Mike Fiore 7:724cb82a113e 571 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 7:724cb82a113e 572 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 7:724cb82a113e 573 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 7:724cb82a113e 574 }
Mike Fiore 7:724cb82a113e 575 #else
Mike Fiore 7:724cb82a113e 576 /* GPIO Ports Clock Enable */
Mike Fiore 7:724cb82a113e 577 __GPIOA_CLK_ENABLE();
Mike Fiore 7:724cb82a113e 578 __GPIOB_CLK_ENABLE();
Mike Fiore 7:724cb82a113e 579 __GPIOC_CLK_ENABLE();
Mike Fiore 7:724cb82a113e 580
Mike Fiore 7:724cb82a113e 581 GPIO_InitTypeDef GPIO_InitStruct;
Mike Fiore 7:724cb82a113e 582
Mike Fiore 7:724cb82a113e 583 // XBEE_DOUT, XBEE_DIN, XBEE_DO8, XBEE_RSSI, USBTX, USBRX, PA_12, PA_13, PA_14 & PA_15 to analog nopull
Mike Fiore 7:724cb82a113e 584 GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_6 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10
Mike Fiore 7:724cb82a113e 585 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
Mike Fiore 7:724cb82a113e 586 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 7:724cb82a113e 587 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 7:724cb82a113e 588 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 7:724cb82a113e 589
Mike Fiore 7:724cb82a113e 590 // PB_0, PB_1, PB_3 & PB_4 to analog nopull
Mike Fiore 7:724cb82a113e 591 GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3 | GPIO_PIN_4;
Mike Fiore 7:724cb82a113e 592 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 7:724cb82a113e 593 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 7:724cb82a113e 594 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
Mike Fiore 7:724cb82a113e 595
Mike Fiore 7:724cb82a113e 596 // PC_9 & PC_13 to analog nopull
Mike Fiore 7:724cb82a113e 597 GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_13;
Mike Fiore 7:724cb82a113e 598 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 7:724cb82a113e 599 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 7:724cb82a113e 600 HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
Mike Fiore 7:724cb82a113e 601
Mike Fiore 7:724cb82a113e 602 // iterate through potential wake pins - leave the configured wake pin alone if one is needed
Mike Fiore 7:724cb82a113e 603 // XBEE_DIN - PA3
Mike Fiore 7:724cb82a113e 604 // XBEE_DIO2 - PA5
Mike Fiore 7:724cb82a113e 605 // XBEE_DIO3 - PA4
Mike Fiore 7:724cb82a113e 606 // XBEE_DIO4 - PA7
Mike Fiore 7:724cb82a113e 607 // XBEE_DIO5 - PC1
Mike Fiore 7:724cb82a113e 608 // XBEE_DIO6 - PA1
Mike Fiore 7:724cb82a113e 609 // XBEE_DIO7 - PA0
Mike Fiore 7:724cb82a113e 610 // XBEE_SLEEPRQ - PA11
Mike Fiore 7:724cb82a113e 611
Mike Fiore 7:724cb82a113e 612 if (dot->getWakePin() != XBEE_DIN || dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 7:724cb82a113e 613 GPIO_InitStruct.Pin = GPIO_PIN_3;
Mike Fiore 7:724cb82a113e 614 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 7:724cb82a113e 615 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 7:724cb82a113e 616 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 7:724cb82a113e 617 }
Mike Fiore 7:724cb82a113e 618
Mike Fiore 7:724cb82a113e 619 if (dot->getWakePin() != XBEE_DIO2 || dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 7:724cb82a113e 620 GPIO_InitStruct.Pin = GPIO_PIN_5;
Mike Fiore 7:724cb82a113e 621 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 7:724cb82a113e 622 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 7:724cb82a113e 623 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 7:724cb82a113e 624 }
Mike Fiore 7:724cb82a113e 625
Mike Fiore 7:724cb82a113e 626 if (dot->getWakePin() != XBEE_DIO3 || dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 7:724cb82a113e 627 GPIO_InitStruct.Pin = GPIO_PIN_4;
Mike Fiore 7:724cb82a113e 628 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 7:724cb82a113e 629 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 7:724cb82a113e 630 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 7:724cb82a113e 631 }
Mike Fiore 7:724cb82a113e 632
Mike Fiore 7:724cb82a113e 633 if (dot->getWakePin() != XBEE_DIO4 || dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 7:724cb82a113e 634 GPIO_InitStruct.Pin = GPIO_PIN_7;
Mike Fiore 7:724cb82a113e 635 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 7:724cb82a113e 636 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 7:724cb82a113e 637 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 7:724cb82a113e 638 }
Mike Fiore 7:724cb82a113e 639
Mike Fiore 7:724cb82a113e 640 if (dot->getWakePin() != XBEE_DIO5 || dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 7:724cb82a113e 641 GPIO_InitStruct.Pin = GPIO_PIN_1;
Mike Fiore 7:724cb82a113e 642 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 7:724cb82a113e 643 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 7:724cb82a113e 644 HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
Mike Fiore 7:724cb82a113e 645 }
Mike Fiore 7:724cb82a113e 646
Mike Fiore 7:724cb82a113e 647 if (dot->getWakePin() != XBEE_DIO6 || dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 7:724cb82a113e 648 GPIO_InitStruct.Pin = GPIO_PIN_1;
Mike Fiore 7:724cb82a113e 649 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 7:724cb82a113e 650 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 7:724cb82a113e 651 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 7:724cb82a113e 652 }
Mike Fiore 7:724cb82a113e 653
Mike Fiore 7:724cb82a113e 654 if (dot->getWakePin() != XBEE_DIO7 || dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 7:724cb82a113e 655 GPIO_InitStruct.Pin = GPIO_PIN_0;
Mike Fiore 7:724cb82a113e 656 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 7:724cb82a113e 657 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 7:724cb82a113e 658 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 7:724cb82a113e 659 }
Mike Fiore 7:724cb82a113e 660
Mike Fiore 7:724cb82a113e 661 if (dot->getWakePin() != XBEE_SLEEPRQ|| dot->getWakeMode() == mDot::RTC_ALARM) {
Mike Fiore 7:724cb82a113e 662 GPIO_InitStruct.Pin = GPIO_PIN_11;
Mike Fiore 7:724cb82a113e 663 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
Mike Fiore 7:724cb82a113e 664 GPIO_InitStruct.Pull = GPIO_NOPULL;
Mike Fiore 7:724cb82a113e 665 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Mike Fiore 7:724cb82a113e 666 }
Mike Fiore 7:724cb82a113e 667 #endif
Mike Fiore 7:724cb82a113e 668 }
Mike Fiore 7:724cb82a113e 669
Mike Fiore 7:724cb82a113e 670 void sleep_restore_io() {
Mike Fiore 7:724cb82a113e 671 #if defined(TARGET_XDOT_L151CC)
Mike Fiore 7:724cb82a113e 672 xdot_restore_gpio_state();
Mike Fiore 7:724cb82a113e 673 #else
Mike Fiore 7:724cb82a113e 674 GPIOA->MODER = portA[0];
Mike Fiore 7:724cb82a113e 675 GPIOA->OTYPER = portA[1];
Mike Fiore 7:724cb82a113e 676 GPIOA->OSPEEDR = portA[2];
Mike Fiore 7:724cb82a113e 677 GPIOA->PUPDR = portA[3];
Mike Fiore 7:724cb82a113e 678 GPIOA->AFR[0] = portA[4];
Mike Fiore 7:724cb82a113e 679 GPIOA->AFR[1] = portA[5];
Mike Fiore 7:724cb82a113e 680
Mike Fiore 7:724cb82a113e 681 GPIOB->MODER = portB[0];
Mike Fiore 7:724cb82a113e 682 GPIOB->OTYPER = portB[1];
Mike Fiore 7:724cb82a113e 683 GPIOB->OSPEEDR = portB[2];
Mike Fiore 7:724cb82a113e 684 GPIOB->PUPDR = portB[3];
Mike Fiore 7:724cb82a113e 685 GPIOB->AFR[0] = portB[4];
Mike Fiore 7:724cb82a113e 686 GPIOB->AFR[1] = portB[5];
Mike Fiore 7:724cb82a113e 687
Mike Fiore 7:724cb82a113e 688 GPIOC->MODER = portC[0];
Mike Fiore 7:724cb82a113e 689 GPIOC->OTYPER = portC[1];
Mike Fiore 7:724cb82a113e 690 GPIOC->OSPEEDR = portC[2];
Mike Fiore 7:724cb82a113e 691 GPIOC->PUPDR = portC[3];
Mike Fiore 7:724cb82a113e 692 GPIOC->AFR[0] = portC[4];
Mike Fiore 7:724cb82a113e 693 GPIOC->AFR[1] = portC[5];
Mike Fiore 7:724cb82a113e 694
Mike Fiore 7:724cb82a113e 695 GPIOD->MODER = portD[0];
Mike Fiore 7:724cb82a113e 696 GPIOD->OTYPER = portD[1];
Mike Fiore 7:724cb82a113e 697 GPIOD->OSPEEDR = portD[2];
Mike Fiore 7:724cb82a113e 698 GPIOD->PUPDR = portD[3];
Mike Fiore 7:724cb82a113e 699 GPIOD->AFR[0] = portD[4];
Mike Fiore 7:724cb82a113e 700 GPIOD->AFR[1] = portD[5];
Mike Fiore 7:724cb82a113e 701
Mike Fiore 7:724cb82a113e 702 GPIOH->MODER = portH[0];
Mike Fiore 7:724cb82a113e 703 GPIOH->OTYPER = portH[1];
Mike Fiore 7:724cb82a113e 704 GPIOH->OSPEEDR = portH[2];
Mike Fiore 7:724cb82a113e 705 GPIOH->PUPDR = portH[3];
Mike Fiore 7:724cb82a113e 706 GPIOH->AFR[0] = portH[4];
Mike Fiore 7:724cb82a113e 707 GPIOH->AFR[1] = portH[5];
Mike Fiore 7:724cb82a113e 708 #endif
mfiore 0:a151a6350d7f 709 }
mfiore 0:a151a6350d7f 710
jreiss 33:15ea8f985c54 711 int send_data(std::vector<uint8_t> data) {
Mike Fiore 24:d80afce304c6 712 int32_t ret;
mfiore 0:a151a6350d7f 713
mfiore 0:a151a6350d7f 714 ret = dot->send(data);
mfiore 0:a151a6350d7f 715 if (ret != mDot::MDOT_OK) {
Mike Fiore 11:d2e31743433a 716 logError("failed to send data to %s [%d][%s]", dot->getJoinMode() == mDot::PEER_TO_PEER ? "peer" : "gateway", ret, mDot::getReturnCodeString(ret).c_str());
mfiore 0:a151a6350d7f 717 } else {
Mike Fiore 11:d2e31743433a 718 logInfo("successfully sent data to %s", dot->getJoinMode() == mDot::PEER_TO_PEER ? "peer" : "gateway");
mfiore 0:a151a6350d7f 719 }
jreiss 33:15ea8f985c54 720
jreiss 33:15ea8f985c54 721 return ret;
mfiore 0:a151a6350d7f 722 }
Mike Fiore 24:d80afce304c6 723