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:
Mike Fiore
Date:
Tue Oct 11 16:33:45 2016 -0500
Revision:
15:364df461110f
Parent:
11:d2e31743433a
Child:
21:09d05faf0e13
disable ACKs and enable network link checks for OTA and AUTO_OTA examples

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