Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Revision 43:97fd5b4de956, committed 2021-07-07
- Comitter:
- jose_23991
- Date:
- Wed Jul 07 11:34:06 2021 +0000
- Parent:
- 42:20f6b29a9903
- Commit message:
- Basic xDot Bootlaoder+ABP+FUOTA code to check available memory for user app
Changed in this revision
--- a/examples/example_config.h Tue May 25 09:54:33 2021 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -#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 -#define CLASS_B_EXAMPLE 6 // see class_b_example.cpp -#define FOTA_EXAMPLE 7 // see fota_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_2 -// CP_AS923_3 -// CP_AS923_JAPAN -// CP_AS923_JAPAN1 -// CP_AS923_JAPAN2 -// CP_IN865 -// CP_RU864 - -#if !defined(CHANNEL_PLAN) -#define CHANNEL_PLAN CP_US915 -#endif - -#endif
--- a/examples/inc/RadioEvent.h Tue May 25 09:54:33 2021 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,99 +0,0 @@ -#ifndef __RADIO_EVENT_H__ -#define __RADIO_EVENT_H__ - -#include "dot_util.h" -#include "mDotEvent.h" -#include "Fota.h" -#include "example_config.h" - -class RadioEvent : public mDotEvent -{ - -public: - RadioEvent() {} - - virtual ~RadioEvent() {} - - virtual void PacketRx(uint8_t port, uint8_t *payload, uint16_t size, int16_t rssi, int16_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 - } - - /*! - * MAC layer event callback prototype. - * - * \param [IN] flags Bit field indicating the MAC events occurred - * \param [IN] info Details about MAC events occurred - */ - virtual void MacEvent(LoRaMacEventFlags* flags, LoRaMacEventInfo* info) { - - if (mts::MTSLog::getLogLevel() == mts::MTSLog::TRACE_LEVEL) { - std::string msg = "OK"; - switch (info->Status) { - case LORAMAC_EVENT_INFO_STATUS_ERROR: - msg = "ERROR"; - break; - case LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT: - msg = "TX_TIMEOUT"; - break; - case LORAMAC_EVENT_INFO_STATUS_RX_TIMEOUT: - msg = "RX_TIMEOUT"; - break; - case LORAMAC_EVENT_INFO_STATUS_RX_ERROR: - msg = "RX_ERROR"; - break; - case LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL: - msg = "JOIN_FAIL"; - break; - case LORAMAC_EVENT_INFO_STATUS_DOWNLINK_FAIL: - msg = "DOWNLINK_FAIL"; - break; - case LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL: - msg = "ADDRESS_FAIL"; - break; - case LORAMAC_EVENT_INFO_STATUS_MIC_FAIL: - msg = "MIC_FAIL"; - break; - default: - break; - } - logTrace("Event: %s", msg.c_str()); - - logTrace("Flags Tx: %d Rx: %d RxData: %d RxSlot: %d LinkCheck: %d JoinAccept: %d", - flags->Bits.Tx, flags->Bits.Rx, flags->Bits.RxData, flags->Bits.RxSlot, flags->Bits.LinkCheck, flags->Bits.JoinAccept); - logTrace("Info: Status: %d ACK: %d Retries: %d TxDR: %d RxPort: %d RxSize: %d RSSI: %d SNR: %d Energy: %d Margin: %d Gateways: %d", - info->Status, info->TxAckReceived, info->TxNbRetries, info->TxDatarate, info->RxPort, info->RxBufferSize, - info->RxRssi, info->RxSnr, info->Energy, info->DemodMargin, info->NbGateways); - } - - if (flags->Bits.Rx) { - - logInfo("Rx %d bytes", info->RxBufferSize); - - if (info->RxBufferSize > 0) { -#if ACTIVE_EXAMPLE != FOTA_EXAMPLE - // print RX data as string and hexadecimal - std::string rx((const char*)info->RxBuffer, info->RxBufferSize); - printf("Rx data: %s [%s]\r\n", rx.c_str(), mts::Text::bin2hexString(info->RxBuffer, info->RxBufferSize).c_str()); -#endif - } - } - } - - -#if ACTIVE_EXAMPLE == FOTA_EXAMPLE - virtual void ServerTime(uint32_t seconds, uint8_t sub_seconds) { - mDotEvent::ServerTime(seconds, sub_seconds); - - Fota::getInstance()->setClockOffset(seconds); - } -#endif -}; - -#endif -
--- a/examples/inc/dot_util.h Tue May 25 09:54:33 2021 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -#ifndef __DOT_UTIL_H__ -#define __DOT_UTIL_H__ - -#include "mbed.h" -#include "mDot.h" -#include "ChannelPlans.h" -#include "MTSLog.h" -#include "MTSText.h" -#include "ISL29011.h" -#include "example_config.h" - -extern mDot* dot; - -lora::ChannelPlan* create_channel_plan(); - -void display_config(); - -void update_ota_config_name_phrase(std::string network_name, std::string network_passphrase, uint8_t frequency_sub_band, lora::NetworkType network_type, uint8_t ack); - -void update_ota_config_id_key(uint8_t *network_id, uint8_t *network_key, uint8_t frequency_sub_band, lora::NetworkType public_network, uint8_t ack); - -void update_manual_config(uint8_t *network_address, uint8_t *network_session_key, uint8_t *data_session_key, uint8_t frequency_sub_band, lora::NetworkType network_type, uint8_t ack); - -void update_peer_to_peer_config(uint8_t *network_address, uint8_t *network_session_key, uint8_t *data_session_key, uint32_t tx_frequency, uint8_t tx_datarate, uint8_t tx_power); - -void update_network_link_check_config(uint8_t link_check_count, uint8_t link_check_threshold); - -void join_network(); - -void sleep_wake_rtc_only(bool deepsleep); - -void sleep_wake_interrupt_only(bool deepsleep); - -void sleep_wake_rtc_or_interrupt(bool deepsleep); - -void sleep_save_io(); - -void sleep_configure_io(); - -void sleep_restore_io(); - -int send_data(std::vector<uint8_t> data); - -#endif
--- a/examples/lib/ISL29011.lib Tue May 25 09:54:33 2021 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -https://developer.mbed.org/teams/Multi-Hackers/code/ISL29011/#953adca17438
--- a/examples/src/auto_ota_example.cpp Tue May 25 09:54:33 2021 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,170 +0,0 @@ -#include "dot_util.h" -#include "RadioEvent.h" - -#if ACTIVE_EXAMPLE == AUTO_OTA_EXAMPLE - -///////////////////////////////////////////////////////////////////////////// -// -------------------- DOT LIBRARY REQUIRED ------------------------------// -// * Because these example programs can be used for both mDot and xDot // -// devices, the LoRa stack is not included. The libmDot library should // -// be imported if building for mDot devices. The libxDot library // -// should be imported if building for xDot devices. // -// * https://developer.mbed.org/teams/MultiTech/code/libmDot-dev-mbed5/ // -// * https://developer.mbed.org/teams/MultiTech/code/libmDot-mbed5/ // -// * https://developer.mbed.org/teams/MultiTech/code/libxDot-dev-mbed5/ // -// * https://developer.mbed.org/teams/MultiTech/code/libxDot-mbed5/ // -///////////////////////////////////////////////////////////////////////////// - -///////////////////////////////////////////////////////////// -// * these options must match the settings on your gateway // -// * edit their values to match your configuration // -// * frequency sub band is only relevant for the 915 bands // -// * either the network name and passphrase can be used or // -// the network ID (8 bytes) and KEY (16 bytes) // -///////////////////////////////////////////////////////////// -static std::string network_name = "MultiTech"; -static std::string network_passphrase = "MultiTech"; -static uint8_t network_id[] = { 0x6C, 0x4E, 0xEF, 0x66, 0xF4, 0x79, 0x86, 0xA6 }; -static uint8_t network_key[] = { 0x1F, 0x33, 0xA1, 0x70, 0xA5, 0xF1, 0xFD, 0xA0, 0xAB, 0x69, 0x7A, 0xAE, 0x2B, 0x95, 0x91, 0x6B }; -static uint8_t frequency_sub_band = 0; -static lora::NetworkType network_type = lora::PUBLIC_LORAWAN; -static uint8_t join_delay = 5; -static uint8_t ack = 0; -static bool adr = true; - -// deepsleep consumes slightly less current than sleep -// in sleep mode, IO state is maintained, RAM is retained, and application will resume after waking up -// in deepsleep mode, IOs float, RAM is lost, and application will start from beginning after waking up -// if deep_sleep == true, device will enter deepsleep mode -static bool deep_sleep = true; - -mDot* dot = NULL; -lora::ChannelPlan* plan = NULL; - -mbed::UnbufferedSerial pc(USBTX, USBRX); - -#if defined(TARGET_XDOT_L151CC) -I2C i2c(I2C_SDA, I2C_SCL); -ISL29011 lux(i2c); -#else -AnalogIn lux(XBEE_AD0); -#endif - -int main() { - // Custom event handler for automatically displaying RX data - RadioEvent events; - - pc.baud(115200); - -#if defined(TARGET_XDOT_L151CC) - i2c.frequency(400000); -#endif - - mts::MTSLog::setLogLevel(mts::MTSLog::TRACE_LEVEL); - - // Create channel plan - plan = create_channel_plan(); - assert(plan); - - dot = mDot::getInstance(plan); - assert(dot); - - // attach the custom events handler - dot->setEvents(&events); - - if (!dot->getStandbyFlag() && !dot->getPreserveSession()) { - logInfo("mbed-os library version: %d.%d.%d", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION); - - // start from a well-known state - logInfo("defaulting Dot configuration"); - dot->resetConfig(); - dot->resetNetworkSession(); - - // make sure library logging is turned on - dot->setLogLevel(mts::MTSLog::INFO_LEVEL); - - // update configuration if necessary - // in AUTO_OTA mode the session is automatically saved, so saveNetworkSession and restoreNetworkSession are not needed - if (dot->getJoinMode() != mDot::AUTO_OTA) { - logInfo("changing network join mode to AUTO_OTA"); - if (dot->setJoinMode(mDot::AUTO_OTA) != mDot::MDOT_OK) { - logError("failed to set network join mode to AUTO_OTA"); - } - } - - // To preserve session over power-off or reset enable this flag - // dot->setPreserveSession(true); - - // in OTA and AUTO_OTA join modes, the credentials can be passed to the library as a name and passphrase or an ID and KEY - // only one method or the other should be used! - // network ID = crc64(network name) - // network KEY = cmac(network passphrase) - update_ota_config_name_phrase(network_name, network_passphrase, frequency_sub_band, network_type, ack); - //update_ota_config_id_key(network_id, network_key, frequency_sub_band, network_type, ack); - - // configure network link checks - // network link checks are a good alternative to requiring the gateway to ACK every packet and should allow a single gateway to handle more Dots - // check the link every count packets - // declare the Dot disconnected after threshold failed link checks - // for count = 3 and threshold = 5, the Dot will ask for a link check response every 5 packets and will consider the connection lost if it fails to receive 3 responses in a row - update_network_link_check_config(3, 5); - - // enable or disable Adaptive Data Rate - dot->setAdr(adr); - - // Configure the join delay - dot->setJoinDelay(join_delay); - - // save changes to configuration - logInfo("saving configuration"); - if (!dot->saveConfig()) { - logError("failed to save configuration"); - } - - // display configuration - display_config(); - } - - while (true) { - uint16_t light; - std::vector<uint8_t> tx_data; - - // join network if not joined - if (!dot->getNetworkJoinStatus()) { - join_network(); - } - -#if defined(TARGET_XDOT_L151CC) - // configure the ISL29011 sensor on the xDot-DK for continuous ambient light sampling, 16 bit conversion, and maximum range - lux.setMode(ISL29011::ALS_CONT); - lux.setResolution(ISL29011::ADC_16BIT); - lux.setRange(ISL29011::RNG_64000); - - // get the latest light sample and send it to the gateway - light = lux.getData(); - tx_data.push_back((light >> 8) & 0xFF); - tx_data.push_back(light & 0xFF); - logInfo("light: %lu [0x%04X]", light, light); - send_data(tx_data); - - // put the LSL29011 ambient light sensor into a low power state - lux.setMode(ISL29011::PWR_DOWN); -#else - // get some dummy data and send it to the gateway - light = lux.read_u16(); - tx_data.push_back((light >> 8) & 0xFF); - tx_data.push_back(light & 0xFF); - logInfo("light: %lu [0x%04X]", light, light); - send_data(tx_data); -#endif - - // ONLY ONE of the three functions below should be uncommented depending on the desired wakeup method - //sleep_wake_rtc_only(deep_sleep); - //sleep_wake_interrupt_only(deep_sleep); - sleep_wake_rtc_or_interrupt(deep_sleep); - } - - return 0; -} - -#endif
--- a/examples/src/class_b_example.cpp Tue May 25 09:54:33 2021 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,183 +0,0 @@ -#include "dot_util.h" -#include "RadioEvent.h" - -#if ACTIVE_EXAMPLE == CLASS_B_EXAMPLE - -///////////////////////////////////////////////////////////////////////////// -// -------------------- DOT LIBRARY REQUIRED ------------------------------// -// * Because these example programs can be used for both mDot and xDot // -// devices, the LoRa stack is not included. The libmDot library should // -// be imported if building for mDot devices. The libxDot library // -// should be imported if building for xDot devices. // -// * https://developer.mbed.org/teams/MultiTech/code/libmDot-dev-mbed5/ // -// * https://developer.mbed.org/teams/MultiTech/code/libmDot-mbed5/ // -// * https://developer.mbed.org/teams/MultiTech/code/libxDot-dev-mbed5/ // -// * https://developer.mbed.org/teams/MultiTech/code/libxDot-mbed5/ // -///////////////////////////////////////////////////////////////////////////// - -///////////////////////////////////////////////////////////// -// * these options must match the settings on your gateway // -// * edit their values to match your configuration // -// * frequency sub band is only relevant for the 915 bands // -// * either the network name and passphrase can be used or // -// the network ID (8 bytes) and KEY (16 bytes) // -///////////////////////////////////////////////////////////// -static std::string network_name = "MultiTech"; -static std::string network_passphrase = "MultiTech"; -static uint8_t network_id[] = { 0x6C, 0x4E, 0xEF, 0x66, 0xF4, 0x79, 0x86, 0xA6 }; -static uint8_t network_key[] = { 0x1F, 0x33, 0xA1, 0x70, 0xA5, 0xF1, 0xFD, 0xA0, 0xAB, 0x69, 0x7A, 0xAE, 0x2B, 0x95, 0x91, 0x6B }; -static uint8_t frequency_sub_band = 1; -static lora::NetworkType public_network = lora::PUBLIC_LORAWAN; -static uint8_t join_delay = 5; -static uint8_t ack = 3; -static bool adr = true; - -// Number of ping slots to open per beacon interval - see mDot.h -static uint8_t ping_periodicity = 4; - -mDot* dot = NULL; -lora::ChannelPlan* plan = NULL; - -mbed::UnbufferedSerial pc(USBTX, USBRX); - -#if defined(TARGET_XDOT_L151CC) -I2C i2c(I2C_SDA, I2C_SCL); -ISL29011 lux(i2c); -#else -AnalogIn lux(XBEE_AD0); -#endif - -int main() { - // Custom event handler for automatically displaying RX data - RadioEvent events; - - pc.baud(115200); - -#if defined(TARGET_XDOT_L151CC) - i2c.frequency(400000); -#endif - - mts::MTSLog::setLogLevel(mts::MTSLog::TRACE_LEVEL); - - // Create channel plan - plan = create_channel_plan(); - assert(plan); - - dot = mDot::getInstance(plan); - assert(dot); - - logInfo("mbed-os library version: %d.%d.%d", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION); - - // start from a well-known state - logInfo("defaulting Dot configuration"); - dot->resetConfig(); - dot->resetNetworkSession(); - - // make sure library logging is turned on - dot->setLogLevel(mts::MTSLog::INFO_LEVEL); - - // attach the custom events handler - dot->setEvents(&events); - - // update configuration if necessary - if (dot->getJoinMode() != mDot::OTA) { - logInfo("changing network join mode to OTA"); - if (dot->setJoinMode(mDot::OTA) != mDot::MDOT_OK) { - logError("failed to set network join mode to OTA"); - } - } - // in OTA and AUTO_OTA join modes, the credentials can be passed to the library as a name and passphrase or an ID and KEY - // only one method or the other should be used! - // network ID = crc64(network name) - // network KEY = cmac(network passphrase) - update_ota_config_name_phrase(network_name, network_passphrase, frequency_sub_band, public_network, ack); - //update_ota_config_id_key(network_id, network_key, frequency_sub_band, public_network, ack); - - // enable or disable Adaptive Data Rate - dot->setAdr(adr); - - // Configure the join delay - dot->setJoinDelay(join_delay); - - // Configure the class B ping periodicity - dot->setPingPeriodicity(ping_periodicity); - - // save changes to configuration - logInfo("saving configuration"); - if (!dot->saveConfig()) { - logError("failed to save configuration"); - } - - // display configuration - display_config(); - - // join the network - must do this before attempting to switch to class B - join_network(); - - // configure the Dot for class B operation - // the Dot must also be configured on the gateway for class B - // use the lora-query application to do this on a Conduit: http://www.multitech.net/developer/software/lora/lora-network-server/ - // to provision your Dot for class B operation with a 3rd party gateway, see the gateway or network provider documentation - // Note: we won't actually switch to class B until we receive a beacon (mDotEvent::BeaconRx fires) - logInfo("changing network mode to class B"); - - if (dot->setClass("B") != mDot::MDOT_OK) { - logError("Failed to set network mode to class B"); - logInfo("Reset the MCU to try again"); - return 0; - } - - // Start a timer to check the beacon was acquired - LowPowerTimer bcn_timer; - bcn_timer.start(); - - while (true) { - std::vector<uint8_t> tx_data; - static bool send_uplink = true; - - // Check if we locked the beacon yet and send an uplink to notify the network server - // To receive data from the gateway in class B ping slots, we must have received a beacon - // already, and sent one uplink to signal to the network server that we are in class B mode - if (events.BeaconLocked && send_uplink) { - logInfo("Acquired a beacon lock"); - - // Add a random delay before trying the uplink to avoid collisions w/ other motes - srand(dot->getRadioRandom()); - uint32_t rand_delay = rand() % 5000; - logInfo("Applying a random delay of %d ms before class notification uplink", rand_delay); - ThisThread::sleep_for(std::chrono::milliseconds(rand_delay)); - - // Ensure the link is idle before trying to transmit - while (!dot->getIsIdle()) { - ThisThread::sleep_for(10ms); - } - - if (send_data(tx_data) != mDot::MDOT_OK) { - logError("Failed to inform the network server we are in class B"); - logInfo("Reset the MCU to try again"); - return 0; - } - - logInfo("Enqueued packets may now be scheduled on class B ping slots"); - send_uplink = false; - bcn_timer.stop(); - } else if (!events.BeaconLocked) { - logInfo("Waiting to receive a beacon.."); - - if (bcn_timer.read() > lora::DEFAULT_BEACON_PERIOD) { - if (dot->setClass("B") != mDot::MDOT_OK) { - logError("Failed to set network mode to class B"); - logInfo("Reset the MCU to try again"); - return 0; - } - - bcn_timer.reset(); - } - } - ThisThread::sleep_for(10s); - } - - return 0; -} - -#endif
--- a/examples/src/class_c_example.cpp Tue May 25 09:54:33 2021 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,161 +0,0 @@ -#include "dot_util.h" -#include "RadioEvent.h" - -#if ACTIVE_EXAMPLE == CLASS_C_EXAMPLE - -///////////////////////////////////////////////////////////////////////////// -// -------------------- DOT LIBRARY REQUIRED ------------------------------// -// * Because these example programs can be used for both mDot and xDot // -// devices, the LoRa stack is not included. The libmDot library should // -// be imported if building for mDot devices. The libxDot library // -// should be imported if building for xDot devices. // -// * https://developer.mbed.org/teams/MultiTech/code/libmDot-dev-mbed5/ // -// * https://developer.mbed.org/teams/MultiTech/code/libmDot-mbed5/ // -// * https://developer.mbed.org/teams/MultiTech/code/libxDot-dev-mbed5/ // -// * https://developer.mbed.org/teams/MultiTech/code/libxDot-mbed5/ // -///////////////////////////////////////////////////////////////////////////// - -///////////////////////////////////////////////////////////// -// * these options must match the settings on your gateway // -// * edit their values to match your configuration // -// * frequency sub band is only relevant for the 915 bands // -// * either the network name and passphrase can be used or // -// the network ID (8 bytes) and KEY (16 bytes) // -///////////////////////////////////////////////////////////// -static std::string network_name = "MultiTech"; -static std::string network_passphrase = "MultiTech"; -static uint8_t network_id[] = { 0x6C, 0x4E, 0xEF, 0x66, 0xF4, 0x79, 0x86, 0xA6 }; -static uint8_t network_key[] = { 0x1F, 0x33, 0xA1, 0x70, 0xA5, 0xF1, 0xFD, 0xA0, 0xAB, 0x69, 0x7A, 0xAE, 0x2B, 0x95, 0x91, 0x6B }; -static uint8_t frequency_sub_band = 0; -static lora::NetworkType network_type = lora::PUBLIC_LORAWAN; -static uint8_t join_delay = 5; -static uint8_t ack = 1; -static bool adr = true; - -mDot* dot = NULL; -lora::ChannelPlan* plan = NULL; - -mbed::UnbufferedSerial pc(USBTX, USBRX); - -#if defined(TARGET_XDOT_L151CC) -I2C i2c(I2C_SDA, I2C_SCL); -ISL29011 lux(i2c); -#else -AnalogIn lux(XBEE_AD0); -#endif - -int main() { - // Custom event handler for automatically displaying RX data - RadioEvent events; - - pc.baud(115200); - -#if defined(TARGET_XDOT_L151CC) - i2c.frequency(400000); -#endif - - mts::MTSLog::setLogLevel(mts::MTSLog::TRACE_LEVEL); - - // Create channel plan - plan = create_channel_plan(); - assert(plan); - - dot = mDot::getInstance(plan); - assert(dot); - - logInfo("mbed-os library version: %d.%d.%d", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION); - - // start from a well-known state - logInfo("defaulting Dot configuration"); - dot->resetConfig(); - dot->resetNetworkSession(); - - // make sure library logging is turned on - dot->setLogLevel(mts::MTSLog::INFO_LEVEL); - - // attach the custom events handler - dot->setEvents(&events); - - // update configuration if necessary - if (dot->getJoinMode() != mDot::OTA) { - logInfo("changing network join mode to OTA"); - if (dot->setJoinMode(mDot::OTA) != mDot::MDOT_OK) { - logError("failed to set network join mode to OTA"); - } - } - // in OTA and AUTO_OTA join modes, the credentials can be passed to the library as a name and passphrase or an ID and KEY - // only one method or the other should be used! - // network ID = crc64(network name) - // network KEY = cmac(network passphrase) - update_ota_config_name_phrase(network_name, network_passphrase, frequency_sub_band, network_type, ack); - //update_ota_config_id_key(network_id, network_key, frequency_sub_band, network_type, ack); - - // configure the Dot for class C operation - // the Dot must also be configured on the gateway for class C - // use the lora-query application to do this on a Conduit: http://www.multitech.net/developer/software/lora/lora-network-server/ - // to provision your Dot for class C operation with a 3rd party gateway, see the gateway or network provider documentation - logInfo("changing network mode to class C"); - if (dot->setClass("C") != mDot::MDOT_OK) { - logError("failed to set network mode to class C"); - } - - // enable or disable Adaptive Data Rate - dot->setAdr(adr); - - // Configure the join delay - dot->setJoinDelay(join_delay); - - // save changes to configuration - logInfo("saving configuration"); - if (!dot->saveConfig()) { - logError("failed to save configuration"); - } - - // display configuration - display_config(); - - while (true) { - uint16_t light; - std::vector<uint8_t> tx_data; - - // join network if not joined - if (!dot->getNetworkJoinStatus()) { - join_network(); - } - -#if defined(TARGET_XDOT_L151CC) - // configure the ISL29011 sensor on the xDot-DK for continuous ambient light sampling, 16 bit conversion, and maximum range - lux.setMode(ISL29011::ALS_CONT); - lux.setResolution(ISL29011::ADC_16BIT); - lux.setRange(ISL29011::RNG_64000); - - // get the latest light sample and send it to the gateway - light = lux.getData(); - tx_data.push_back((light >> 8) & 0xFF); - tx_data.push_back(light & 0xFF); - logInfo("light: %lu [0x%04X]", light, light); - send_data(tx_data); - - // put the LSL29011 ambient light sensor into a low power state - lux.setMode(ISL29011::PWR_DOWN); -#else - // get some dummy data and send it to the gateway - light = lux.read_u16(); - tx_data.push_back((light >> 8) & 0xFF); - tx_data.push_back(light & 0xFF); - logInfo("light: %lu [0x%04X]", light, light); - send_data(tx_data); -#endif - - // the Dot can't sleep in class C mode - // it must be waiting for data from the gateway - // send data every 30s - logInfo("waiting for 30s"); - ThisThread::sleep_for(30s); - } - - return 0; -} - -#endif -
--- a/examples/src/dot_util.cpp Tue May 25 09:54:33 2021 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,756 +0,0 @@ -#include "dot_util.h" -#if defined(TARGET_XDOT_L151CC) -#include "xdot_low_power.h" -#endif - -#if defined(TARGET_MTS_MDOT_F411RE) -uint32_t portA[6]; -uint32_t portB[6]; -uint32_t portC[6]; -uint32_t portD[6]; -uint32_t portH[6]; -#endif - - -lora::ChannelPlan* create_channel_plan() { - lora::ChannelPlan* plan; - -#if CHANNEL_PLAN == CP_US915 - plan = new lora::ChannelPlan_US915(); -#elif CHANNEL_PLAN == CP_AU915 - plan = new lora::ChannelPlan_AU915(); -#elif CHANNEL_PLAN == CP_EU868 - plan = new lora::ChannelPlan_EU868(); -#elif CHANNEL_PLAN == CP_KR920 - plan = new lora::ChannelPlan_KR920(); -#elif CHANNEL_PLAN == CP_IN865 - plan = new lora::ChannelPlan_IN865(); -#elif CHANNEL_PLAN == CP_AS923 - plan = new lora::ChannelPlan_AS923(); -#elif CHANNEL_PLAN == CP_AS923_2 - plan = new lora::ChannelPlan_AS923(); -#elif CHANNEL_PLAN == CP_AS923_3 - plan = new lora::ChannelPlan_AS923(); -#elif CHANNEL_PLAN == CP_AS923_JAPAN - plan = new lora::ChannelPlan_AS923_Japan(); -#elif CHANNEL_PLAN == CP_AS923_JAPAN1 - plan = new lora::ChannelPlan_AS923_Japan1(); -#elif CHANNEL_PLAN == CP_AS923_JAPAN2 - plan = new lora::ChannelPlan_AS923_Japan2(); -#elif CHANNEL_PLAN == CP_RU864 - plan = new lora::ChannelPlan_RU864(); -#endif - - return plan; -} - - -void display_config() { - // display configuration and library version information - logInfo("====================="); - logInfo("general configuration"); - logInfo("====================="); - logInfo("version ------------------ %s", dot->getId().c_str()); - logInfo("device ID/EUI ------------ %s", mts::Text::bin2hexString(dot->getDeviceId()).c_str()); - logInfo("default channel plan ----- %s", mDot::FrequencyBandStr(dot->getDefaultFrequencyBand()).c_str()); - logInfo("current channel plan ----- %s", mDot::FrequencyBandStr(dot->getFrequencyBand()).c_str()); - if (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) { - logInfo("frequency sub band ------- %u", dot->getFrequencySubBand()); - } - - std::string network_mode_str("Undefined"); - uint8_t network_mode = dot->getPublicNetwork(); - if (network_mode == lora::PRIVATE_MTS) - network_mode_str = "Private MTS"; - else if (network_mode == lora::PUBLIC_LORAWAN) - network_mode_str = "Public LoRaWAN"; - else if (network_mode == lora::PRIVATE_LORAWAN) - network_mode_str = "Private LoRaWAN"; - logInfo("public network ----------- %s", network_mode_str.c_str()); - - logInfo("========================="); - logInfo("credentials configuration"); - logInfo("========================="); - logInfo("device class ------------- %s", dot->getClass().c_str()); - logInfo("network join mode -------- %s", mDot::JoinModeStr(dot->getJoinMode()).c_str()); - if (dot->getJoinMode() == mDot::MANUAL || dot->getJoinMode() == mDot::PEER_TO_PEER) { - logInfo("network address ---------- %s", mts::Text::bin2hexString(dot->getNetworkAddress()).c_str()); - logInfo("network session key------- %s", mts::Text::bin2hexString(dot->getNetworkSessionKey()).c_str()); - logInfo("data session key---------- %s", mts::Text::bin2hexString(dot->getDataSessionKey()).c_str()); - } else { - logInfo("network name ------------- %s", dot->getNetworkName().c_str()); - logInfo("network phrase ----------- %s", dot->getNetworkPassphrase().c_str()); - logInfo("network EUI -------------- %s", mts::Text::bin2hexString(dot->getNetworkId()).c_str()); - logInfo("network KEY -------------- %s", mts::Text::bin2hexString(dot->getNetworkKey()).c_str()); - } - logInfo("========================"); - logInfo("communication parameters"); - logInfo("========================"); - if (dot->getJoinMode() == mDot::PEER_TO_PEER) { - logInfo("TX frequency ------------- %lu", dot->getTxFrequency()); - } else { - logInfo("acks --------------------- %s, %u attempts", dot->getAck() > 0 ? "on" : "off", dot->getAck()); - } - logInfo("TX datarate -------------- %s", mDot::DataRateStr(dot->getTxDataRate()).c_str()); - logInfo("TX power ----------------- %lu dBm", dot->getTxPower()); - logInfo("antenna gain ------------- %u dBm", dot->getAntennaGain()); - logInfo("LBT ---------------------- %s", dot->getLbtTimeUs() ? "on" : "off"); - if (dot->getLbtTimeUs()) { - logInfo("LBT time ----------------- %lu us", dot->getLbtTimeUs()); - logInfo("LBT threshold ------------ %d dBm", dot->getLbtThreshold()); - } -} - -void update_ota_config_name_phrase(std::string network_name, std::string network_passphrase, uint8_t frequency_sub_band, lora::NetworkType network_type, uint8_t ack) { - std::string current_network_name = dot->getNetworkName(); - std::string current_network_passphrase = dot->getNetworkPassphrase(); - uint8_t current_frequency_sub_band = dot->getFrequencySubBand(); - uint8_t current_network_type = dot->getPublicNetwork(); - uint8_t current_ack = dot->getAck(); - - if (current_network_name != network_name) { - logInfo("changing network name from \"%s\" to \"%s\"", current_network_name.c_str(), network_name.c_str()); - if (dot->setNetworkName(network_name) != mDot::MDOT_OK) { - logError("failed to set network name to \"%s\"", network_name.c_str()); - } - } - - if (current_network_passphrase != network_passphrase) { - logInfo("changing network passphrase from \"%s\" to \"%s\"", current_network_passphrase.c_str(), network_passphrase.c_str()); - if (dot->setNetworkPassphrase(network_passphrase) != mDot::MDOT_OK) { - logError("failed to set network passphrase to \"%s\"", network_passphrase.c_str()); - } - } - - if (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) { - if (current_frequency_sub_band != frequency_sub_band) { - logInfo("changing frequency sub band from %u to %u", current_frequency_sub_band, frequency_sub_band); - if (dot->setFrequencySubBand(frequency_sub_band) != mDot::MDOT_OK) { - logError("failed to set frequency sub band to %u", frequency_sub_band); - } - } - } - - if (current_network_type != network_type) { - if (dot->setPublicNetwork(network_type) != mDot::MDOT_OK) { - logError("failed to set network type"); - } - } - - if (current_ack != ack) { - logInfo("changing acks from %u to %u", current_ack, ack); - if (dot->setAck(ack) != mDot::MDOT_OK) { - logError("failed to set acks to %u", ack); - } - } -} - -void update_ota_config_id_key(uint8_t *network_id, uint8_t *network_key, uint8_t frequency_sub_band, lora::NetworkType network_type, uint8_t ack) { - std::vector<uint8_t> current_network_id = dot->getNetworkId(); - std::vector<uint8_t> current_network_key = dot->getNetworkKey(); - uint8_t current_frequency_sub_band = dot->getFrequencySubBand(); - uint8_t current_network_type = dot->getPublicNetwork(); - uint8_t current_ack = dot->getAck(); - - std::vector<uint8_t> network_id_vector(network_id, network_id + 8); - std::vector<uint8_t> network_key_vector(network_key, network_key + 16); - - if (current_network_id != network_id_vector) { - logInfo("changing network ID from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_id).c_str(), mts::Text::bin2hexString(network_id_vector).c_str()); - if (dot->setNetworkId(network_id_vector) != mDot::MDOT_OK) { - logError("failed to set network ID to \"%s\"", mts::Text::bin2hexString(network_id_vector).c_str()); - } - } - - if (current_network_key != network_key_vector) { - logInfo("changing network KEY from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_key).c_str(), mts::Text::bin2hexString(network_key_vector).c_str()); - if (dot->setNetworkKey(network_key_vector) != mDot::MDOT_OK) { - logError("failed to set network KEY to \"%s\"", mts::Text::bin2hexString(network_key_vector).c_str()); - } - } - - if (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) { - if (current_frequency_sub_band != frequency_sub_band) { - logInfo("changing frequency sub band from %u to %u", current_frequency_sub_band, frequency_sub_band); - if (dot->setFrequencySubBand(frequency_sub_band) != mDot::MDOT_OK) { - logError("failed to set frequency sub band to %u", frequency_sub_band); - } - } - } - - if (current_network_type != network_type) { - if (dot->setPublicNetwork(network_type) != mDot::MDOT_OK) { - logError("failed to set network type"); - } - } - - if (current_ack != ack) { - logInfo("changing acks from %u to %u", current_ack, ack); - if (dot->setAck(ack) != mDot::MDOT_OK) { - logError("failed to set acks to %u", ack); - } - } -} - -void update_manual_config(uint8_t *network_address, uint8_t *network_session_key, uint8_t *data_session_key, uint8_t frequency_sub_band, lora::NetworkType network_type, uint8_t ack) { - std::vector<uint8_t> current_network_address = dot->getNetworkAddress(); - std::vector<uint8_t> current_network_session_key = dot->getNetworkSessionKey(); - std::vector<uint8_t> current_data_session_key = dot->getDataSessionKey(); - uint8_t current_frequency_sub_band = dot->getFrequencySubBand(); - uint8_t current_network_type = dot->getPublicNetwork(); - uint8_t current_ack = dot->getAck(); - - std::vector<uint8_t> network_address_vector(network_address, network_address + 4); - std::vector<uint8_t> network_session_key_vector(network_session_key, network_session_key + 16); - std::vector<uint8_t> data_session_key_vector(data_session_key, data_session_key + 16); - - if (current_network_address != network_address_vector) { - logInfo("changing network address from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_address).c_str(), mts::Text::bin2hexString(network_address_vector).c_str()); - if (dot->setNetworkAddress(network_address_vector) != mDot::MDOT_OK) { - logError("failed to set network address to \"%s\"", mts::Text::bin2hexString(network_address_vector).c_str()); - } - } - - if (current_network_session_key != network_session_key_vector) { - logInfo("changing network session key from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_session_key).c_str(), mts::Text::bin2hexString(network_session_key_vector).c_str()); - if (dot->setNetworkSessionKey(network_session_key_vector) != mDot::MDOT_OK) { - logError("failed to set network session key to \"%s\"", mts::Text::bin2hexString(network_session_key_vector).c_str()); - } - } - - if (current_data_session_key != data_session_key_vector) { - logInfo("changing data session key from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_data_session_key).c_str(), mts::Text::bin2hexString(data_session_key_vector).c_str()); - if (dot->setDataSessionKey(data_session_key_vector) != mDot::MDOT_OK) { - logError("failed to set data session key to \"%s\"", mts::Text::bin2hexString(data_session_key_vector).c_str()); - } - } - - if (current_frequency_sub_band != frequency_sub_band) { - logInfo("changing frequency sub band from %u to %u", current_frequency_sub_band, frequency_sub_band); - if (dot->setFrequencySubBand(frequency_sub_band) != mDot::MDOT_OK) { - logError("failed to set frequency sub band to %u", frequency_sub_band); - } - } - - if (current_network_type != network_type) { - if (dot->setPublicNetwork(network_type) != mDot::MDOT_OK) { - logError("failed to set network type"); - } - } - - if (current_ack != ack) { - logInfo("changing acks from %u to %u", current_ack, ack); - if (dot->setAck(ack) != mDot::MDOT_OK) { - logError("failed to set acks to %u", ack); - } - } -} - -void update_peer_to_peer_config(uint8_t *network_address, uint8_t *network_session_key, uint8_t *data_session_key, uint32_t tx_frequency, uint8_t tx_datarate, uint8_t tx_power) { - std::vector<uint8_t> current_network_address = dot->getNetworkAddress(); - std::vector<uint8_t> current_network_session_key = dot->getNetworkSessionKey(); - std::vector<uint8_t> current_data_session_key = dot->getDataSessionKey(); - uint32_t current_tx_frequency = dot->getTxFrequency(); - uint8_t current_tx_datarate = dot->getTxDataRate(); - uint8_t current_tx_power = dot->getTxPower(); - - std::vector<uint8_t> network_address_vector(network_address, network_address + 4); - std::vector<uint8_t> network_session_key_vector(network_session_key, network_session_key + 16); - std::vector<uint8_t> data_session_key_vector(data_session_key, data_session_key + 16); - - if (current_network_address != network_address_vector) { - logInfo("changing network address from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_address).c_str(), mts::Text::bin2hexString(network_address_vector).c_str()); - if (dot->setNetworkAddress(network_address_vector) != mDot::MDOT_OK) { - logError("failed to set network address to \"%s\"", mts::Text::bin2hexString(network_address_vector).c_str()); - } - } - - if (current_network_session_key != network_session_key_vector) { - logInfo("changing network session key from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_session_key).c_str(), mts::Text::bin2hexString(network_session_key_vector).c_str()); - if (dot->setNetworkSessionKey(network_session_key_vector) != mDot::MDOT_OK) { - logError("failed to set network session key to \"%s\"", mts::Text::bin2hexString(network_session_key_vector).c_str()); - } - } - - if (current_data_session_key != data_session_key_vector) { - logInfo("changing data session key from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_data_session_key).c_str(), mts::Text::bin2hexString(data_session_key_vector).c_str()); - if (dot->setDataSessionKey(data_session_key_vector) != mDot::MDOT_OK) { - logError("failed to set data session key to \"%s\"", mts::Text::bin2hexString(data_session_key_vector).c_str()); - } - } - - if (current_tx_frequency != tx_frequency) { - logInfo("changing TX frequency from %lu to %lu", current_tx_frequency, tx_frequency); - if (dot->setTxFrequency(tx_frequency) != mDot::MDOT_OK) { - logError("failed to set TX frequency to %lu", tx_frequency); - } - } - - if (current_tx_datarate != tx_datarate) { - logInfo("changing TX datarate from %u to %u", current_tx_datarate, tx_datarate); - if (dot->setTxDataRate(tx_datarate) != mDot::MDOT_OK) { - logError("failed to set TX datarate to %u", tx_datarate); - } - } - - if (current_tx_power != tx_power) { - logInfo("changing TX power from %u to %u", current_tx_power, tx_power); - if (dot->setTxPower(tx_power) != mDot::MDOT_OK) { - logError("failed to set TX power to %u", tx_power); - } - } -} - -void update_network_link_check_config(uint8_t link_check_count, uint8_t link_check_threshold) { - uint8_t current_link_check_count = dot->getLinkCheckCount(); - uint8_t current_link_check_threshold = dot->getLinkCheckThreshold(); - - if (current_link_check_count != link_check_count) { - logInfo("changing link check count from %u to %u", current_link_check_count, link_check_count); - if (dot->setLinkCheckCount(link_check_count) != mDot::MDOT_OK) { - logError("failed to set link check count to %u", link_check_count); - } - } - - if (current_link_check_threshold != link_check_threshold) { - logInfo("changing link check threshold from %u to %u", current_link_check_threshold, link_check_threshold); - if (dot->setLinkCheckThreshold(link_check_threshold) != mDot::MDOT_OK) { - logError("failed to set link check threshold to %u", link_check_threshold); - } - } -} - -void join_network() { - int32_t j_attempts = 0; - int32_t ret = mDot::MDOT_ERROR; - - // attempt to join the network - while (ret != mDot::MDOT_OK) { - logInfo("attempt %d to join network", ++j_attempts); - ret = dot->joinNetwork(); - if (ret != mDot::MDOT_OK) { - logError("failed to join network %d:%s", ret, mDot::getReturnCodeString(ret).c_str()); - // in some frequency bands we need to wait until another channel is available before transmitting again - uint32_t delay_s = (dot->getNextTxMs() / 1000) + 1; - if (delay_s < 5) { - logInfo("waiting %lu s until next free channel", delay_s); - ThisThread::sleep_for(std::chrono::seconds(delay_s)); - } else { - logInfo("sleeping %lu s until next free channel", delay_s); - dot->sleep(delay_s, mDot::RTC_ALARM, false); - } - } - } -} - -void sleep_wake_rtc_only(bool deepsleep) { - // in some frequency bands we need to wait until another channel is available before transmitting again - // wait at least 10s between transmissions - uint32_t delay_s = dot->getNextTxMs() / 1000; - if (delay_s < 10) { - delay_s = 10; - } - - logInfo("%ssleeping %lus", deepsleep ? "deep" : "", delay_s); - logInfo("application will %s after waking up", deepsleep ? "execute from beginning" : "resume"); - - // lowest current consumption in sleep mode can only be achieved by configuring IOs as analog inputs with no pull resistors - // the library handles all internal IOs automatically, but the external IOs are the application's responsibility - // certain IOs may require internal pullup or pulldown resistors because leaving them floating would cause extra current consumption - // for xDot: UART_*, I2C_*, SPI_*, GPIO*, WAKE - // for mDot: XBEE_*, USBTX, USBRX, PB_0, PB_1 - // steps are: - // * save IO configuration - // * configure IOs to reduce current consumption - // * sleep - // * restore IO configuration - if (! deepsleep) { - // save the GPIO state. - sleep_save_io(); - - // configure GPIOs for lowest current - sleep_configure_io(); - } - - // go to sleep/deepsleep for delay_s seconds and wake using the RTC alarm - dot->sleep(delay_s, mDot::RTC_ALARM, deepsleep); - - if (! deepsleep) { - // restore the GPIO state. - sleep_restore_io(); - } -} - -void sleep_wake_interrupt_only(bool deepsleep) { -#if defined (TARGET_XDOT_L151CC) - if (deepsleep) { - // for xDot, WAKE pin (connected to S2 on xDot-DK) is the only pin that can wake the processor from deepsleep - // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call - } else { - // configure WAKE pin (connected to S2 on xDot-DK) as the pin that will wake the xDot from low power modes - // other pins can be confgured instead: GPIO0-3 or UART_RX - dot->setWakePin(WAKE); - } - - logInfo("%ssleeping until interrupt on %s pin", deepsleep ? "deep" : "", deepsleep ? "WAKE" : mDot::pinName2Str(dot->getWakePin()).c_str()); -#else - - if (deepsleep) { - // for mDot, XBEE_DIO7 pin is the only pin that can wake the processor from deepsleep - // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call - } else { - // configure XBEE_DIO7 pin as the pin that will wake the mDot from low power modes - // other pins can be confgured instead: XBEE_DIO2-6, XBEE_DI8, XBEE_DIN - dot->setWakePin(XBEE_DIO7); - } - - logInfo("%ssleeping until interrupt on %s pin", deepsleep ? "deep" : "", deepsleep ? "DIO7" : mDot::pinName2Str(dot->getWakePin()).c_str()); -#endif - - logInfo("application will %s after waking up", deepsleep ? "execute from beginning" : "resume"); - - // lowest current consumption in sleep mode can only be achieved by configuring IOs as analog inputs with no pull resistors - // the library handles all internal IOs automatically, but the external IOs are the application's responsibility - // certain IOs may require internal pullup or pulldown resistors because leaving them floating would cause extra current consumption - // for xDot: UART_*, I2C_*, SPI_*, GPIO*, WAKE - // for mDot: XBEE_*, USBTX, USBRX, PB_0, PB_1 - // steps are: - // * save IO configuration - // * configure IOs to reduce current consumption - // * sleep - // * restore IO configuration - if (! deepsleep) { - // save the GPIO state. - sleep_save_io(); - - // configure GPIOs for lowest current - sleep_configure_io(); - } - - // go to sleep/deepsleep and wake on rising edge of configured wake pin (only the WAKE pin in deepsleep) - // since we're not waking on the RTC alarm, the interval is ignored - dot->sleep(0, mDot::INTERRUPT, deepsleep); - - if (! deepsleep) { - // restore the GPIO state. - sleep_restore_io(); - } -} - -void sleep_wake_rtc_or_interrupt(bool deepsleep) { - // in some frequency bands we need to wait until another channel is available before transmitting again - // wait at least 10s between transmissions - uint32_t delay_s = dot->getNextTxMs() / 1000; - if (delay_s < 10) { - delay_s = 10; - } - -#if defined (TARGET_XDOT_L151CC) - if (deepsleep) { - // for xDot, WAKE pin (connected to S2 on xDot-DK) is the only pin that can wake the processor from deepsleep - // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call - } else { - // configure WAKE pin (connected to S2 on xDot-DK) as the pin that will wake the xDot from low power modes - // other pins can be confgured instead: GPIO0-3 or UART_RX - dot->setWakePin(WAKE); - } - - logInfo("%ssleeping %lus or until interrupt on %s pin", deepsleep ? "deep" : "", delay_s, deepsleep ? "WAKE" : mDot::pinName2Str(dot->getWakePin()).c_str()); -#else - if (deepsleep) { - // for mDot, XBEE_DIO7 pin is the only pin that can wake the processor from deepsleep - // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call - } else { - // configure XBEE_DIO7 pin as the pin that will wake the mDot from low power modes - // other pins can be confgured instead: XBEE_DIO2-6, XBEE_DI8, XBEE_DIN - dot->setWakePin(XBEE_DIO7); - } - - logInfo("%ssleeping %lus or until interrupt on %s pin", deepsleep ? "deep" : "", delay_s, deepsleep ? "DIO7" : mDot::pinName2Str(dot->getWakePin()).c_str()); -#endif - - logInfo("application will %s after waking up", deepsleep ? "execute from beginning" : "resume"); - - // lowest current consumption in sleep mode can only be achieved by configuring IOs as analog inputs with no pull resistors - // the library handles all internal IOs automatically, but the external IOs are the application's responsibility - // certain IOs may require internal pullup or pulldown resistors because leaving them floating would cause extra current consumption - // for xDot: UART_*, I2C_*, SPI_*, GPIO*, WAKE - // for mDot: XBEE_*, USBTX, USBRX, PB_0, PB_1 - // steps are: - // * save IO configuration - // * configure IOs to reduce current consumption - // * sleep - // * restore IO configuration - if (! deepsleep) { - // save the GPIO state. - sleep_save_io(); - - // configure GPIOs for lowest current - sleep_configure_io(); - } - - // go to sleep/deepsleep and wake using the RTC alarm after delay_s seconds or rising edge of configured wake pin (only the WAKE pin in deepsleep) - // whichever comes first will wake the xDot - dot->sleep(delay_s, mDot::RTC_ALARM_OR_INTERRUPT, deepsleep); - - if (! deepsleep) { - // restore the GPIO state. - sleep_restore_io(); - } -} - -void sleep_save_io() { -#if defined(TARGET_XDOT_L151CC) - xdot_save_gpio_state(); -#else - portA[0] = GPIOA->MODER; - portA[1] = GPIOA->OTYPER; - portA[2] = GPIOA->OSPEEDR; - portA[3] = GPIOA->PUPDR; - portA[4] = GPIOA->AFR[0]; - portA[5] = GPIOA->AFR[1]; - - portB[0] = GPIOB->MODER; - portB[1] = GPIOB->OTYPER; - portB[2] = GPIOB->OSPEEDR; - portB[3] = GPIOB->PUPDR; - portB[4] = GPIOB->AFR[0]; - portB[5] = GPIOB->AFR[1]; - - portC[0] = GPIOC->MODER; - portC[1] = GPIOC->OTYPER; - portC[2] = GPIOC->OSPEEDR; - portC[3] = GPIOC->PUPDR; - portC[4] = GPIOC->AFR[0]; - portC[5] = GPIOC->AFR[1]; - - portD[0] = GPIOD->MODER; - portD[1] = GPIOD->OTYPER; - portD[2] = GPIOD->OSPEEDR; - portD[3] = GPIOD->PUPDR; - portD[4] = GPIOD->AFR[0]; - portD[5] = GPIOD->AFR[1]; - - portH[0] = GPIOH->MODER; - portH[1] = GPIOH->OTYPER; - portH[2] = GPIOH->OSPEEDR; - portH[3] = GPIOH->PUPDR; - portH[4] = GPIOH->AFR[0]; - portH[5] = GPIOH->AFR[1]; -#endif -} - -void sleep_configure_io() { -#if defined(TARGET_XDOT_L151CC) - // GPIO Ports Clock Enable - __GPIOA_CLK_ENABLE(); - __GPIOB_CLK_ENABLE(); - __GPIOC_CLK_ENABLE(); - __GPIOH_CLK_ENABLE(); - - GPIO_InitTypeDef GPIO_InitStruct; - - // UART1_TX, UART1_RTS & UART1_CTS to analog nopull - RX could be a wakeup source - GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_11 | GPIO_PIN_12; - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - GPIO_InitStruct.Pull = GPIO_NOPULL; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - - // I2C_SDA & I2C_SCL to analog nopull - GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9; - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - GPIO_InitStruct.Pull = GPIO_NOPULL; - HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); - - // SPI_MOSI, SPI_MISO, SPI_SCK, & SPI_NSS to analog nopull - GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15; - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - GPIO_InitStruct.Pull = GPIO_NOPULL; - HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); - - // iterate through potential wake pins - leave the configured wake pin alone if one is needed - if (dot->getWakePin() != WAKE || dot->getWakeMode() == mDot::RTC_ALARM) { - GPIO_InitStruct.Pin = GPIO_PIN_0; - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - GPIO_InitStruct.Pull = GPIO_NOPULL; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - } - if (dot->getWakePin() != GPIO0 || dot->getWakeMode() == mDot::RTC_ALARM) { - GPIO_InitStruct.Pin = GPIO_PIN_4; - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - GPIO_InitStruct.Pull = GPIO_NOPULL; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - } - if (dot->getWakePin() != GPIO1 || dot->getWakeMode() == mDot::RTC_ALARM) { - GPIO_InitStruct.Pin = GPIO_PIN_5; - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - GPIO_InitStruct.Pull = GPIO_NOPULL; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - } - if (dot->getWakePin() != GPIO2 || dot->getWakeMode() == mDot::RTC_ALARM) { - GPIO_InitStruct.Pin = GPIO_PIN_0; - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - GPIO_InitStruct.Pull = GPIO_NOPULL; - HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); - } - if (dot->getWakePin() != GPIO3 || dot->getWakeMode() == mDot::RTC_ALARM) { - GPIO_InitStruct.Pin = GPIO_PIN_2; - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - GPIO_InitStruct.Pull = GPIO_NOPULL; - HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); - } - if (dot->getWakePin() != UART1_RX || dot->getWakeMode() == mDot::RTC_ALARM) { - GPIO_InitStruct.Pin = GPIO_PIN_10; - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - GPIO_InitStruct.Pull = GPIO_NOPULL; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - } -#else - /* GPIO Ports Clock Enable */ - __GPIOA_CLK_ENABLE(); - __GPIOB_CLK_ENABLE(); - __GPIOC_CLK_ENABLE(); - - GPIO_InitTypeDef GPIO_InitStruct; - - // XBEE_DOUT, XBEE_DIN, XBEE_DO8, XBEE_RSSI, USBTX, USBRX, PA_12, PA_13, PA_14 & PA_15 to analog nopull - GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_6 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 - | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15; - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - GPIO_InitStruct.Pull = GPIO_NOPULL; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - - // PB_0, PB_1, PB_3 & PB_4 to analog nopull - GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3 | GPIO_PIN_4; - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - GPIO_InitStruct.Pull = GPIO_NOPULL; - HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); - - // PC_9 & PC_13 to analog nopull - GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_13; - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - GPIO_InitStruct.Pull = GPIO_NOPULL; - HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); - - // iterate through potential wake pins - leave the configured wake pin alone if one is needed - // XBEE_DIN - PA3 - // XBEE_DIO2 - PA5 - // XBEE_DIO3 - PA4 - // XBEE_DIO4 - PA7 - // XBEE_DIO5 - PC1 - // XBEE_DIO6 - PA1 - // XBEE_DIO7 - PA0 - // XBEE_SLEEPRQ - PA11 - - if (dot->getWakePin() != XBEE_DIN || dot->getWakeMode() == mDot::RTC_ALARM) { - GPIO_InitStruct.Pin = GPIO_PIN_3; - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - GPIO_InitStruct.Pull = GPIO_NOPULL; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - } - - if (dot->getWakePin() != XBEE_DIO2 || dot->getWakeMode() == mDot::RTC_ALARM) { - GPIO_InitStruct.Pin = GPIO_PIN_5; - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - GPIO_InitStruct.Pull = GPIO_NOPULL; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - } - - if (dot->getWakePin() != XBEE_DIO3 || dot->getWakeMode() == mDot::RTC_ALARM) { - GPIO_InitStruct.Pin = GPIO_PIN_4; - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - GPIO_InitStruct.Pull = GPIO_NOPULL; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - } - - if (dot->getWakePin() != XBEE_DIO4 || dot->getWakeMode() == mDot::RTC_ALARM) { - GPIO_InitStruct.Pin = GPIO_PIN_7; - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - GPIO_InitStruct.Pull = GPIO_NOPULL; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - } - - if (dot->getWakePin() != XBEE_DIO5 || dot->getWakeMode() == mDot::RTC_ALARM) { - GPIO_InitStruct.Pin = GPIO_PIN_1; - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - GPIO_InitStruct.Pull = GPIO_NOPULL; - HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); - } - - if (dot->getWakePin() != XBEE_DIO6 || dot->getWakeMode() == mDot::RTC_ALARM) { - GPIO_InitStruct.Pin = GPIO_PIN_1; - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - GPIO_InitStruct.Pull = GPIO_NOPULL; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - } - - if (dot->getWakePin() != XBEE_DIO7 || dot->getWakeMode() == mDot::RTC_ALARM) { - GPIO_InitStruct.Pin = GPIO_PIN_0; - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - GPIO_InitStruct.Pull = GPIO_NOPULL; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - } - - if (dot->getWakePin() != XBEE_SLEEPRQ|| dot->getWakeMode() == mDot::RTC_ALARM) { - GPIO_InitStruct.Pin = GPIO_PIN_11; - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - GPIO_InitStruct.Pull = GPIO_NOPULL; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - } -#endif -} - -void sleep_restore_io() { -#if defined(TARGET_XDOT_L151CC) - xdot_restore_gpio_state(); -#else - GPIOA->MODER = portA[0]; - GPIOA->OTYPER = portA[1]; - GPIOA->OSPEEDR = portA[2]; - GPIOA->PUPDR = portA[3]; - GPIOA->AFR[0] = portA[4]; - GPIOA->AFR[1] = portA[5]; - - GPIOB->MODER = portB[0]; - GPIOB->OTYPER = portB[1]; - GPIOB->OSPEEDR = portB[2]; - GPIOB->PUPDR = portB[3]; - GPIOB->AFR[0] = portB[4]; - GPIOB->AFR[1] = portB[5]; - - GPIOC->MODER = portC[0]; - GPIOC->OTYPER = portC[1]; - GPIOC->OSPEEDR = portC[2]; - GPIOC->PUPDR = portC[3]; - GPIOC->AFR[0] = portC[4]; - GPIOC->AFR[1] = portC[5]; - - GPIOD->MODER = portD[0]; - GPIOD->OTYPER = portD[1]; - GPIOD->OSPEEDR = portD[2]; - GPIOD->PUPDR = portD[3]; - GPIOD->AFR[0] = portD[4]; - GPIOD->AFR[1] = portD[5]; - - GPIOH->MODER = portH[0]; - GPIOH->OTYPER = portH[1]; - GPIOH->OSPEEDR = portH[2]; - GPIOH->PUPDR = portH[3]; - GPIOH->AFR[0] = portH[4]; - GPIOH->AFR[1] = portH[5]; -#endif -} - -int send_data(std::vector<uint8_t> data) { - int32_t ret; - - ret = dot->send(data); - if (ret != mDot::MDOT_OK) { - logError("failed to send data to %s [%d][%s]", dot->getJoinMode() == mDot::PEER_TO_PEER ? "peer" : "gateway", ret, mDot::getReturnCodeString(ret).c_str()); - } else { - logInfo("successfully sent data to %s", dot->getJoinMode() == mDot::PEER_TO_PEER ? "peer" : "gateway"); - } - - return ret; -} -
--- a/examples/src/fota_example.cpp Tue May 25 09:54:33 2021 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,229 +0,0 @@ -#include "dot_util.h" -#include "RadioEvent.h" - -#if ACTIVE_EXAMPLE == FOTA_EXAMPLE - - -#if defined(TARGET_XDOT_L151CC) -//#include "SPIFBlockDevice.h" -//#include "DataFlashBlockDevice.h" -#endif - -///////////////////////////////////////////////////////////////////////////// -// -------------------- DOT LIBRARY REQUIRED ------------------------------// -// * Because these example programs can be used for both mDot and xDot // -// devices, the LoRa stack is not included. The libmDot library should // -// be imported if building for mDot devices. The libxDot library // -// should be imported if building for xDot devices. // -// * https://developer.mbed.org/teams/MultiTech/code/libmDot-dev-mbed5/ // -// * https://developer.mbed.org/teams/MultiTech/code/libmDot-mbed5/ // -// * https://developer.mbed.org/teams/MultiTech/code/libxDot-dev-mbed5/ // -// * https://developer.mbed.org/teams/MultiTech/code/libxDot-mbed5/ // -///////////////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////////// -// -------------------- DEFINITIONS REQUIRED ---------------------------- // -// Add define for FOTA in mbed_app.json or on command line // -// Command line // -// mbed compile -t GCC_ARM -m MTS_MDOT_F411RE -DFOTA=1 // -// mbed_app.json // -// { // -// "macros": [ // -// "FOTA" // -// ] // -// } // -// // -//////////////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////////// -// -------------------------- XDOT EXTERNAL STORAGE --------------------- // -// An external storage device is required for FOTA on an XDot. The // -// storage device must meet the following criteria: // -// * Work with MBed OS DataFlashBlockDevice or SPIFBlockDevice classes // -// * Maximum 4KB sector erase size // -// * Maximum 512 byte page size // -// * SPIF type components must support Serial Flash Discoverable // -// Parameters (SFDP) // -// // -// Refer to mbed_app.json included in this project for configuration // -// parameters requried for external storage. // -// // -// Modify code below to create a BlockDevice object. // -//////////////////////////////////////////////////////////////////////////// - - -///////////////////////////////////////////////////////////// -// * these options must match the settings on your gateway // -// * edit their values to match your configuration // -// * frequency sub band is only relevant for the 915 bands // -// * either the network name and passphrase can be used or // -// the network ID (8 bytes) and KEY (16 bytes) // -///////////////////////////////////////////////////////////// - -static std::string network_name = "MultiTech"; -static std::string network_passphrase = "MultiTech"; -static uint8_t network_id[] = { 0x6C, 0x4E, 0xEF, 0x66, 0xF4, 0x79, 0x86, 0xA6 }; -static uint8_t network_key[] = { 0x1F, 0x33, 0xA1, 0x70, 0xA5, 0xF1, 0xFD, 0xA0, 0xAB, 0x69, 0x7A, 0xAE, 0x2B, 0x95, 0x91, 0x6B }; -static uint8_t frequency_sub_band = 0; -static lora::NetworkType network_type = lora::PUBLIC_LORAWAN; -static uint8_t join_delay = 5; -static uint8_t ack = 1; -static bool adr = true; - -mDot* dot = NULL; -lora::ChannelPlan* plan = NULL; - -mbed::UnbufferedSerial pc(USBTX, USBRX); - -#if defined(TARGET_XDOT_L151CC) -I2C i2c(I2C_SDA, I2C_SCL); -ISL29011 lux(i2c); -#else -AnalogIn lux(XBEE_AD0); -#endif - -int main() { - // Custom event handler for automatically displaying RX data - RadioEvent events; - - pc.baud(115200); - -#if defined(TARGET_XDOT_L151CC) - i2c.frequency(400000); -#endif - - mts::MTSLog::setLogLevel(mts::MTSLog::TRACE_LEVEL); - - // Create channel plan - plan = create_channel_plan(); - assert(plan); - -#if defined(TARGET_XDOT_L151CC) - - mbed::BlockDevice* ext_bd = NULL; - - // XDot requires an external storage device for FOTA (see above). - // If one is connected provide the block device object to the mDot instance. - // - // ** Uncomment the appropriate block device here and include statement above - // - //ext_bd = new SPIFBlockDevice(); - //ext_bd = new DataFlashBlockDevice(); - ext_bd->init(); - dot = mDot::getInstance(plan, ext_bd); -#else - dot = mDot::getInstance(plan); -#endif - assert(dot); - - logInfo("mbed-os library version: %d.%d.%d", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION); - - // Initialize FOTA singleton - Fota::getInstance(dot); - - - // start from a well-known state - logInfo("defaulting Dot configuration"); - dot->resetConfig(); - dot->resetNetworkSession(); - - // make sure library logging is turned on - dot->setLogLevel(mts::MTSLog::INFO_LEVEL); - - // attach the custom events handler - dot->setEvents(&events); - - // update configuration if necessary - if (dot->getJoinMode() != mDot::OTA) { - logInfo("changing network join mode to OTA"); - if (dot->setJoinMode(mDot::OTA) != mDot::MDOT_OK) { - logError("failed to set network join mode to OTA"); - } - } - // in OTA and AUTO_OTA join modes, the credentials can be passed to the library as a name and passphrase or an ID and KEY - // only one method or the other should be used! - // network ID = crc64(network name) - // network KEY = cmac(network passphrase) - update_ota_config_name_phrase(network_name, network_passphrase, frequency_sub_band, network_type, ack); - //update_ota_config_id_key(network_id, network_key, frequency_sub_band, network_type, ack); - - // configure the Dot for class C operation - // the Dot must also be configured on the gateway for class C - // use the lora-query application to do this on a Conduit: http://www.multitech.net/developer/software/lora/lora-network-server/ - // to provision your Dot for class C operation with a 3rd party gateway, see the gateway or network provider documentation - logInfo("changing network mode to class C"); - if (dot->setClass("C") != mDot::MDOT_OK) { - logError("failed to set network mode to class C"); - } - - // enable or disable Adaptive Data Rate - dot->setAdr(adr); - - // Configure the join delay - dot->setJoinDelay(join_delay); - - // save changes to configuration - logInfo("saving configuration"); - if (!dot->saveConfig()) { - logError("failed to save configuration"); - } - - // display configuration - display_config(); - - while (true) { - uint16_t light; - std::vector<uint8_t> tx_data; - - // join network if not joined - if (!dot->getNetworkJoinStatus()) { - join_network(); - } - -#if defined(TARGET_XDOT_L151CC) - // configure the ISL29011 sensor on the xDot-DK for continuous ambient light sampling, 16 bit conversion, and maximum range - lux.setMode(ISL29011::ALS_CONT); - lux.setResolution(ISL29011::ADC_16BIT); - lux.setRange(ISL29011::RNG_64000); - - // get the latest light sample and send it to the gateway - light = lux.getData(); - tx_data.push_back((light >> 8) & 0xFF); - tx_data.push_back(light & 0xFF); - logInfo("light: %lu [0x%04X]", light, light); - send_data(tx_data); - - // put the LSL29011 ambient light sensor into a low power state - lux.setMode(ISL29011::PWR_DOWN); -#else - // get some dummy data and send it to the gateway - light = lux.read_u16(); - tx_data.push_back((light >> 8) & 0xFF); - tx_data.push_back(light & 0xFF); - logInfo("light: %lu [0x%04X]", light, light); - send_data(tx_data); -#endif - - // the Dot can't sleep in class C mode - // it must be waiting for data from the gateway - // send data every 30s - if (Fota::getInstance()->timeToStart() != 0) { - logInfo("waiting for 30s"); - ThisThread::sleep_for(30s); - } else { - // Reduce uplinks during FOTA, dot cannot receive while transmitting - // Too many lost packets will cause FOTA to fail - logInfo("FOTA starting in %d seconds", Fota::getInstance()->timeToStart()); - logInfo("waiting for 300s"); - ThisThread::sleep_for(300s); - } - - } - - return 0; -} - -#endif -
--- a/examples/src/manual_example.cpp Tue May 25 09:54:33 2021 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,168 +0,0 @@ -#include "dot_util.h" -#include "RadioEvent.h" - -#if ACTIVE_EXAMPLE == MANUAL_EXAMPLE - -///////////////////////////////////////////////////////////////////////////// -// -------------------- DOT LIBRARY REQUIRED ------------------------------// -// * Because these example programs can be used for both mDot and xDot // -// devices, the LoRa stack is not included. The libmDot library should // -// be imported if building for mDot devices. The libxDot library // -// should be imported if building for xDot devices. // -// * https://developer.mbed.org/teams/MultiTech/code/libmDot-dev-mbed5/ // -// * https://developer.mbed.org/teams/MultiTech/code/libmDot-mbed5/ // -// * https://developer.mbed.org/teams/MultiTech/code/libxDot-dev-mbed5/ // -// * https://developer.mbed.org/teams/MultiTech/code/libxDot-mbed5/ // -///////////////////////////////////////////////////////////////////////////// - -///////////////////////////////////////////////////////////// -// * these options must match the settings on your gateway // -// * edit their values to match your configuration // -// * frequency sub band is only relevant for the 915 bands // -///////////////////////////////////////////////////////////// -static uint8_t network_address[] = { 0x01, 0x02, 0x03, 0x04 }; -static uint8_t network_session_key[] = { 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04 }; -static uint8_t data_session_key[] = { 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04 }; -static uint8_t frequency_sub_band = 6; -static lora::NetworkType network_type = lora::PUBLIC_LORAWAN; -static uint8_t join_delay = 5; -static uint8_t ack = 1; -static bool adr = true; - -// deepsleep consumes slightly less current than sleep -// in sleep mode, IO state is maintained, RAM is retained, and application will resume after waking up -// in deepsleep mode, IOs float, RAM is lost, and application will start from beginning after waking up -// if deep_sleep == true, device will enter deepsleep mode -static bool deep_sleep = true; - -mDot* dot = NULL; -lora::ChannelPlan* plan = NULL; - -mbed::UnbufferedSerial pc(USBTX, USBRX); - -#if defined(TARGET_XDOT_L151CC) -I2C i2c(I2C_SDA, I2C_SCL); -ISL29011 lux(i2c); -#else -AnalogIn lux(XBEE_AD0); -#endif - -int main() { - // Custom event handler for automatically displaying RX data - RadioEvent events; - - pc.baud(115200); - -#if defined(TARGET_XDOT_L151CC) - i2c.frequency(400000); -#endif - - mts::MTSLog::setLogLevel(mts::MTSLog::TRACE_LEVEL); - - // Create channel plan - plan = create_channel_plan(); - assert(plan); - - dot = mDot::getInstance(plan); - assert(dot); - - // attach the custom events handler - dot->setEvents(&events); - - if (!dot->getStandbyFlag()) { - logInfo("mbed-os library version: %d.%d.%d", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION); - - // start from a well-known state - logInfo("defaulting Dot configuration"); - dot->resetConfig(); - dot->resetNetworkSession(); - - // make sure library logging is turned on - dot->setLogLevel(mts::MTSLog::INFO_LEVEL); - - // update configuration if necessary - if (dot->getJoinMode() != mDot::MANUAL) { - logInfo("changing network join mode to MANUAL"); - if (dot->setJoinMode(mDot::MANUAL) != mDot::MDOT_OK) { - logError("failed to set network join mode to MANUAL"); - } - } - // in MANUAL join mode there is no join request/response transaction - // as long as the Dot is configured correctly and provisioned correctly on the gateway, it should be able to communicate - // network address - 4 bytes (00000001 - FFFFFFFE) - // network session key - 16 bytes - // data session key - 16 bytes - // to provision your Dot with a Conduit gateway, follow the following steps - // * ssh into the Conduit - // * provision the Dot using the lora-query application: http://www.multitech.net/developer/software/lora/lora-network-server/ - // lora-query -a 01020304 A 0102030401020304 <your Dot's device ID> 01020304010203040102030401020304 01020304010203040102030401020304 - // * if you change the network address, network session key, or data session key, make sure you update them on the gateway - // to provision your Dot with a 3rd party gateway, see the gateway or network provider documentation - update_manual_config(network_address, network_session_key, data_session_key, frequency_sub_band, network_type, ack); - - // enable or disable Adaptive Data Rate - dot->setAdr(adr); - - // Configure the join delay - dot->setJoinDelay(join_delay); - - // save changes to configuration - logInfo("saving configuration"); - if (!dot->saveConfig()) { - logError("failed to save configuration"); - } - - // display configuration - display_config(); - } else { - // restore the saved session if the dot woke from deepsleep mode - // useful to use with deepsleep because session info is otherwise lost when the dot enters deepsleep - logInfo("restoring network session from NVM"); - dot->restoreNetworkSession(); - } - - while (true) { - uint16_t light; - std::vector<uint8_t> tx_data; - -#if defined(TARGET_XDOT_L151CC) - // configure the ISL29011 sensor on the xDot-DK for continuous ambient light sampling, 16 bit conversion, and maximum range - lux.setMode(ISL29011::ALS_CONT); - lux.setResolution(ISL29011::ADC_16BIT); - lux.setRange(ISL29011::RNG_64000); - - // get the latest light sample and send it to the gateway - light = lux.getData(); - tx_data.push_back((light >> 8) & 0xFF); - tx_data.push_back(light & 0xFF); - logInfo("light: %lu [0x%04X]", light, light); - send_data(tx_data); - - // put the LSL29011 ambient light sensor into a low power state - lux.setMode(ISL29011::PWR_DOWN); -#else - // get some dummy data and send it to the gateway - light = lux.read_u16(); - tx_data.push_back((light >> 8) & 0xFF); - tx_data.push_back(light & 0xFF); - logInfo("light: %lu [0x%04X]", light, light); - send_data(tx_data); -#endif - - // if going into deepsleep mode, save the session so we don't need to join again after waking up - // not necessary if going into sleep mode since RAM is retained - if (deep_sleep) { - logInfo("saving network session to NVM"); - dot->saveNetworkSession(); - } - - // ONLY ONE of the three functions below should be uncommented depending on the desired wakeup method - //sleep_wake_rtc_only(deep_sleep); - //sleep_wake_interrupt_only(deep_sleep); - sleep_wake_rtc_or_interrupt(deep_sleep); - } - - return 0; -} - -#endif
--- a/examples/src/ota_example.cpp Tue May 25 09:54:33 2021 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,181 +0,0 @@ -#include "dot_util.h" -#include "RadioEvent.h" - -#if ACTIVE_EXAMPLE == OTA_EXAMPLE - -///////////////////////////////////////////////////////////////////////////// -// -------------------- DOT LIBRARY REQUIRED ------------------------------// -// * Because these example programs can be used for both mDot and xDot // -// devices, the LoRa stack is not included. The libmDot library should // -// be imported if building for mDot devices. The libxDot library // -// should be imported if building for xDot devices. // -// * https://developer.mbed.org/teams/MultiTech/code/libmDot-dev-mbed5/ // -// * https://developer.mbed.org/teams/MultiTech/code/libmDot-mbed5/ // -// * https://developer.mbed.org/teams/MultiTech/code/libxDot-dev-mbed5/ // -// * https://developer.mbed.org/teams/MultiTech/code/libxDot-mbed5/ // -///////////////////////////////////////////////////////////////////////////// - -///////////////////////////////////////////////////////////// -// * these options must match the settings on your gateway // -// * edit their values to match your configuration // -// * frequency sub band is only relevant for the 915 bands // -// * either the network name and passphrase can be used or // -// the network ID (8 bytes) and KEY (16 bytes) // -///////////////////////////////////////////////////////////// -static std::string network_name = "MultiTech"; -static std::string network_passphrase = "MultiTech"; -static uint8_t network_id[] = { 0x6C, 0x4E, 0xEF, 0x66, 0xF4, 0x79, 0x86, 0xA6 }; -static uint8_t network_key[] = { 0x1F, 0x33, 0xA1, 0x70, 0xA5, 0xF1, 0xFD, 0xA0, 0xAB, 0x69, 0x7A, 0xAE, 0x2B, 0x95, 0x91, 0x6B }; -static uint8_t frequency_sub_band = 0; -static lora::NetworkType network_type = lora::PUBLIC_LORAWAN; -static uint8_t join_delay = 5; -static uint8_t ack = 0; -static bool adr = true; - -// deepsleep consumes slightly less current than sleep -// in sleep mode, IO state is maintained, RAM is retained, and application will resume after waking up -// in deepsleep mode, IOs float, RAM is lost, and application will start from beginning after waking up -// if deep_sleep == true, device will enter deepsleep mode -static bool deep_sleep = false; - -mDot* dot = NULL; -lora::ChannelPlan* plan = NULL; - -mbed::UnbufferedSerial pc(USBTX, USBRX); - -#if defined(TARGET_XDOT_L151CC) -I2C i2c(I2C_SDA, I2C_SCL); -ISL29011 lux(i2c); -#else -AnalogIn lux(XBEE_AD0); -#endif - -int main() { - // Custom event handler for automatically displaying RX data - RadioEvent events; - - pc.baud(115200); - -#if defined(TARGET_XDOT_L151CC) - i2c.frequency(400000); -#endif - - mts::MTSLog::setLogLevel(mts::MTSLog::TRACE_LEVEL); - - // Create channel plan - plan = create_channel_plan(); - assert(plan); - - dot = mDot::getInstance(plan); - assert(dot); - - // attach the custom events handler - dot->setEvents(&events); - - if (!dot->getStandbyFlag() && !dot->getPreserveSession()) { - logInfo("mbed-os library version: %d.%d.%d", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION); - - // start from a well-known state - logInfo("defaulting Dot configuration"); - dot->resetConfig(); - dot->resetNetworkSession(); - - // make sure library logging is turned on - dot->setLogLevel(mts::MTSLog::INFO_LEVEL); - - // update configuration if necessary - if (dot->getJoinMode() != mDot::OTA) { - logInfo("changing network join mode to OTA"); - if (dot->setJoinMode(mDot::OTA) != mDot::MDOT_OK) { - logError("failed to set network join mode to OTA"); - } - } - - // To preserve session over power-off or reset enable this flag - // dot->setPreserveSession(true); - - // in OTA and AUTO_OTA join modes, the credentials can be passed to the library as a name and passphrase or an ID and KEY - // only one method or the other should be used! - // network ID = crc64(network name) - // network KEY = cmac(network passphrase) - update_ota_config_name_phrase(network_name, network_passphrase, frequency_sub_band, network_type, ack); - //update_ota_config_id_key(network_id, network_key, frequency_sub_band, network_type, ack); - - // configure network link checks - // network link checks are a good alternative to requiring the gateway to ACK every packet and should allow a single gateway to handle more Dots - // check the link every count packets - // declare the Dot disconnected after threshold failed link checks - // for count = 3 and threshold = 5, the Dot will ask for a link check response every 5 packets and will consider the connection lost if it fails to receive 3 responses in a row - update_network_link_check_config(3, 5); - - // enable or disable Adaptive Data Rate - dot->setAdr(adr); - - // Configure the join delay - dot->setJoinDelay(join_delay); - - // save changes to configuration - logInfo("saving configuration"); - if (!dot->saveConfig()) { - logError("failed to save configuration"); - } - - // display configuration - display_config(); - } else { - // restore the saved session if the dot woke from deepsleep mode - // useful to use with deepsleep because session info is otherwise lost when the dot enters deepsleep - logInfo("restoring network session from NVM"); - dot->restoreNetworkSession(); - } - - while (true) { - uint16_t light; - std::vector<uint8_t> tx_data; - - // join network if not joined - if (!dot->getNetworkJoinStatus()) { - join_network(); - } - -#if defined(TARGET_XDOT_L151CC) - // configure the ISL29011 sensor on the xDot-DK for continuous ambient light sampling, 16 bit conversion, and maximum range - lux.setMode(ISL29011::ALS_CONT); - lux.setResolution(ISL29011::ADC_16BIT); - lux.setRange(ISL29011::RNG_64000); - - // get the latest light sample and send it to the gateway - light = lux.getData(); - tx_data.push_back((light >> 8) & 0xFF); - tx_data.push_back(light & 0xFF); - logInfo("light: %lu [0x%04X]", light, light); - send_data(tx_data); - - // put the LSL29011 ambient light sensor into a low power state - lux.setMode(ISL29011::PWR_DOWN); -#else - // get some dummy data and send it to the gateway - light = lux.read_u16(); - tx_data.push_back((light >> 8) & 0xFF); - tx_data.push_back(light & 0xFF); - logInfo("light: %lu [0x%04X]", light, light); - send_data(tx_data); -#endif - - // if going into deepsleep mode, save the session so we don't need to join again after waking up - // not necessary if going into sleep mode since RAM is retained - if (deep_sleep) { - logInfo("saving network session to NVM"); - dot->saveNetworkSession(); - } - - // ONLY ONE of the three functions below should be uncommented depending on the desired wakeup method - //sleep_wake_rtc_only(deep_sleep); - //sleep_wake_interrupt_only(deep_sleep); - sleep_wake_rtc_or_interrupt(deep_sleep); - } - - return 0; -} - -#endif
--- a/examples/src/peer_to_peer_example.cpp Tue May 25 09:54:33 2021 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,191 +0,0 @@ -#include "dot_util.h" -#include "RadioEvent.h" - -#if ACTIVE_EXAMPLE == PEER_TO_PEER_EXAMPLE - -///////////////////////////////////////////////////////////////////////////// -// -------------------- DOT LIBRARY REQUIRED ------------------------------// -// * Because these example programs can be used for both mDot and xDot // -// devices, the LoRa stack is not included. The libmDot library should // -// be imported if building for mDot devices. The libxDot library // -// should be imported if building for xDot devices. // -// * https://developer.mbed.org/teams/MultiTech/code/libmDot-dev-mbed5/ // -// * https://developer.mbed.org/teams/MultiTech/code/libmDot-mbed5/ // -// * https://developer.mbed.org/teams/MultiTech/code/libxDot-dev-mbed5/ // -// * https://developer.mbed.org/teams/MultiTech/code/libxDot-mbed5/ // -///////////////////////////////////////////////////////////////////////////// - -///////////////////////////////////////////////////////////// -// * these options must match between the two devices in // -// order for communication to be successful -///////////////////////////////////////////////////////////// -static uint8_t network_address[] = { 0x01, 0x02, 0x03, 0x04 }; -static uint8_t network_session_key[] = { 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04 }; -static uint8_t data_session_key[] = { 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04 }; - -mDot* dot = NULL; -lora::ChannelPlan* plan = NULL; - -mbed::UnbufferedSerial pc(USBTX, USBRX); - -#if defined(TARGET_XDOT_L151CC) -I2C i2c(I2C_SDA, I2C_SCL); -ISL29011 lux(i2c); -#else -AnalogIn lux(XBEE_AD0); -#endif - -int main() { - // Custom event handler for automatically displaying RX data - RadioEvent events; - uint32_t tx_frequency; - uint8_t tx_datarate; - uint8_t tx_power; - uint8_t frequency_band; - - pc.baud(115200); - -#if defined(TARGET_XDOT_L151CC) - i2c.frequency(400000); -#endif - - mts::MTSLog::setLogLevel(mts::MTSLog::TRACE_LEVEL); - - // Create channel plan - plan = create_channel_plan(); - assert(plan); - - dot = mDot::getInstance(plan); - assert(dot); - - logInfo("mbed-os library version: %d.%d.%d", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION); - - // start from a well-known state - logInfo("defaulting Dot configuration"); - dot->resetConfig(); - - // make sure library logging is turned on - dot->setLogLevel(mts::MTSLog::INFO_LEVEL); - - // attach the custom events handler - dot->setEvents(&events); - - // update configuration if necessary - if (dot->getJoinMode() != mDot::PEER_TO_PEER) { - logInfo("changing network join mode to PEER_TO_PEER"); - if (dot->setJoinMode(mDot::PEER_TO_PEER) != mDot::MDOT_OK) { - logError("failed to set network join mode to PEER_TO_PEER"); - } - } - frequency_band = dot->getFrequencyBand(); - switch (frequency_band) { - case lora::ChannelPlan::EU868_OLD: - case lora::ChannelPlan::EU868: - // 250kHz channels achieve higher throughput - // DR_6 : SF7 @ 250kHz - // DR_0 - DR_5 (125kHz channels) available but much slower - tx_frequency = 869850000; - tx_datarate = lora::DR_6; - // the 869850000 frequency is 100% duty cycle if the total power is under 7 dBm - tx power 4 + antenna gain 3 = 7 - tx_power = 4; - break; - - case lora::ChannelPlan::US915_OLD: - case lora::ChannelPlan::US915: - case lora::ChannelPlan::AU915_OLD: - case lora::ChannelPlan::AU915: - // 500kHz channels achieve highest throughput - // DR_8 : SF12 @ 500kHz - // DR_9 : SF11 @ 500kHz - // DR_10 : SF10 @ 500kHz - // DR_11 : SF9 @ 500kHz - // DR_12 : SF8 @ 500kHz - // DR_13 : SF7 @ 500kHz - // DR_0 - DR_3 (125kHz channels) available but much slower - tx_frequency = 915500000; - tx_datarate = lora::DR_13; - // 915 bands have no duty cycle restrictions, set tx power to max - tx_power = 20; - break; - - case lora::ChannelPlan::AS923: - case lora::ChannelPlan::AS923_JAPAN: - // 250kHz channels achieve higher throughput - // DR_6 : SF7 @ 250kHz - // DR_0 - DR_5 (125kHz channels) available but much slower - tx_frequency = 924800000; - tx_datarate = lora::DR_6; - tx_power = 16; - break; - - case lora::ChannelPlan::KR920: - // DR_5 : SF7 @ 125kHz - tx_frequency = 922700000; - tx_datarate = lora::DR_5; - tx_power = 14; - break; - - default: - while (true) { - logFatal("no known channel plan in use - extra configuration is needed!"); - ThisThread::sleep_for(5s); - } - break; - } - // in PEER_TO_PEER mode there is no join request/response transaction - // as long as both Dots are configured correctly, they should be able to communicate - update_peer_to_peer_config(network_address, network_session_key, data_session_key, tx_frequency, tx_datarate, tx_power); - - // save changes to configuration - logInfo("saving configuration"); - if (!dot->saveConfig()) { - logError("failed to save configuration"); - } - - // display configuration - display_config(); - - while (true) { - uint16_t light; - std::vector<uint8_t> tx_data; - - // join network if not joined - if (!dot->getNetworkJoinStatus()) { - join_network(); - } - -#if defined(TARGET_XDOT_L151CC) - // configure the ISL29011 sensor on the xDot-DK for continuous ambient light sampling, 16 bit conversion, and maximum range - lux.setMode(ISL29011::ALS_CONT); - lux.setResolution(ISL29011::ADC_16BIT); - lux.setRange(ISL29011::RNG_64000); - - // get the latest light sample and send it to the gateway - light = lux.getData(); - tx_data.push_back((light >> 8) & 0xFF); - tx_data.push_back(light & 0xFF); - logInfo("light: %lu [0x%04X]", light, light); - send_data(tx_data); - - // put the LSL29011 ambient light sensor into a low power state - lux.setMode(ISL29011::PWR_DOWN); -#else - // get some dummy data and send it to the gateway - light = lux.read_u16(); - tx_data.push_back((light >> 8) & 0xFF); - tx_data.push_back(light & 0xFF); - logInfo("light: %lu [0x%04X]", light, light); - send_data(tx_data); -#endif - - // the Dot can't sleep in PEER_TO_PEER mode - // it must be waiting for data from the other Dot - // send data every 5 seconds - logInfo("waiting for 5s"); - ThisThread::sleep_for(5s); - } - - return 0; -} - -#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/inc/RadioEvent.h Wed Jul 07 11:34:06 2021 +0000 @@ -0,0 +1,100 @@ +#ifndef __RADIO_EVENT_H__ +#define __RADIO_EVENT_H__ + +#include "dot_util.h" +#include "mDotEvent.h" +#if defined(FOTA) + #include "Fota.h" +#endif + +class RadioEvent : public mDotEvent +{ + +public: + RadioEvent() {} + + virtual ~RadioEvent() {} + + virtual void PacketRx(uint8_t port, uint8_t *payload, uint16_t size, int16_t rssi, int16_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 defined(FOTA) + if(port == 200 || port == 201 || port == 202) { + Fota::getInstance()->processCmd(payload, port, size); + } +#endif + } + + /*! + * MAC layer event callback prototype. + * + * \param [IN] flags Bit field indicating the MAC events occurred + * \param [IN] info Details about MAC events occurred + */ + virtual void MacEvent(LoRaMacEventFlags* flags, LoRaMacEventInfo* info) { + + if (mts::MTSLog::getLogLevel() == mts::MTSLog::TRACE_LEVEL) { + std::string msg = "OK"; + switch (info->Status) { + case LORAMAC_EVENT_INFO_STATUS_ERROR: + msg = "ERROR"; + break; + case LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT: + msg = "TX_TIMEOUT"; + break; + case LORAMAC_EVENT_INFO_STATUS_RX_TIMEOUT: + msg = "RX_TIMEOUT"; + break; + case LORAMAC_EVENT_INFO_STATUS_RX_ERROR: + msg = "RX_ERROR"; + break; + case LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL: + msg = "JOIN_FAIL"; + break; + case LORAMAC_EVENT_INFO_STATUS_DOWNLINK_FAIL: + msg = "DOWNLINK_FAIL"; + break; + case LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL: + msg = "ADDRESS_FAIL"; + break; + case LORAMAC_EVENT_INFO_STATUS_MIC_FAIL: + msg = "MIC_FAIL"; + break; + default: + break; + } + logTrace("Event: %s", msg.c_str()); + + logTrace("Flags Tx: %d Rx: %d RxData: %d RxSlot: %d LinkCheck: %d JoinAccept: %d", + flags->Bits.Tx, flags->Bits.Rx, flags->Bits.RxData, flags->Bits.RxSlot, flags->Bits.LinkCheck, flags->Bits.JoinAccept); + logTrace("Info: Status: %d ACK: %d Retries: %d TxDR: %d RxPort: %d RxSize: %d RSSI: %d SNR: %d Energy: %d Margin: %d Gateways: %d", + info->Status, info->TxAckReceived, info->TxNbRetries, info->TxDatarate, info->RxPort, info->RxBufferSize, + info->RxRssi, info->RxSnr, info->Energy, info->DemodMargin, info->NbGateways); + } + + if (flags->Bits.Rx) { + + logInfo("Rx %d bytes", info->RxBufferSize); + + if (info->RxBufferSize > 0) { +#if !defined(FOTA) + // print RX data as string and hexadecimal + std::string rx((const char*)info->RxBuffer, info->RxBufferSize); + printf("Rx data: %s [%s]\r\n", rx.c_str(), mts::Text::bin2hexString(info->RxBuffer, info->RxBufferSize).c_str()); +#endif + } + } + } + + +#if defined(FOTA) + virtual void ServerTime(uint32_t seconds, uint8_t sub_seconds) { + mDotEvent::ServerTime(seconds, sub_seconds); + + Fota::getInstance()->setClockOffset(seconds); + } +#endif +}; + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/inc/dot_util.h Wed Jul 07 11:34:06 2021 +0000 @@ -0,0 +1,42 @@ +#ifndef __DOT_UTIL_H__ +#define __DOT_UTIL_H__ + +#include "mbed.h" +#include "mDot.h" +#include "ChannelPlans.h" +#include "MTSLog.h" +#include "MTSText.h" + +extern mDot* dot; + +lora::ChannelPlan* create_channel_plan(); + +void display_config(); + +void update_ota_config_name_phrase(std::string network_name, std::string network_passphrase, uint8_t frequency_sub_band, lora::NetworkType network_type, uint8_t ack); + +void update_ota_config_id_key(uint8_t *network_id, uint8_t *network_key, uint8_t frequency_sub_band, lora::NetworkType public_network, uint8_t ack); + +void update_manual_config(uint8_t *network_address, uint8_t *network_session_key, uint8_t *data_session_key, uint8_t frequency_sub_band, lora::NetworkType network_type, uint8_t ack); + +void update_peer_to_peer_config(uint8_t *network_address, uint8_t *network_session_key, uint8_t *data_session_key, uint32_t tx_frequency, uint8_t tx_datarate, uint8_t tx_power); + +void update_network_link_check_config(uint8_t link_check_count, uint8_t link_check_threshold); + +void join_network(); + +void sleep_wake_rtc_only(bool deepsleep); + +void sleep_wake_interrupt_only(bool deepsleep); + +void sleep_wake_rtc_or_interrupt(bool deepsleep); + +void sleep_save_io(); + +void sleep_configure_io(); + +void sleep_restore_io(); + +int send_data(std::vector<uint8_t> data); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libxDot.lib Wed Jul 07 11:34:06 2021 +0000 @@ -0,0 +1,1 @@ +https://github.com/MultiTechSystems/libxDot/#d07c6a8801aba435dd6acc238ec4294419b94728
--- a/mbed-os.lib Tue May 25 09:54:33 2021 -0500 +++ b/mbed-os.lib Wed Jul 07 11:34:06 2021 +0000 @@ -1,1 +1,1 @@ -https://github.com/ARMmbed/mbed-os/#a6207cadad0acd1876f436dc6baeddf46c42af06 +https://github.com/ARMmbed/mbed-os/#a6207cadad0acd1876f436dc6baeddf46c42af06
--- a/setup.sh Tue May 25 09:54:33 2021 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -if [ ! -d ISL29011 ]; then - hg clone https://developer.mbed.org/teams/Multi-Hackers/code/ISL29011/ -fi
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dot_util.cpp Wed Jul 07 11:34:06 2021 +0000 @@ -0,0 +1,758 @@ +#include "dot_util.h" +#if defined(TARGET_XDOT_L151CC) +#include "xdot_low_power.h" +#endif + +#if defined(TARGET_MTS_MDOT_F411RE) +uint32_t portA[6]; +uint32_t portB[6]; +uint32_t portC[6]; +uint32_t portD[6]; +uint32_t portH[6]; +#endif + + +lora::ChannelPlan* create_channel_plan() { + lora::ChannelPlan* plan; + +#if CHANNEL_PLAN == CP_US915 + plan = new lora::ChannelPlan_US915(); +#elif CHANNEL_PLAN == CP_AU915 + plan = new lora::ChannelPlan_AU915(); +#elif CHANNEL_PLAN == CP_EU868 + plan = new lora::ChannelPlan_EU868(); +#elif CHANNEL_PLAN == CP_KR920 + plan = new lora::ChannelPlan_KR920(); +#elif CHANNEL_PLAN == CP_IN865 + plan = new lora::ChannelPlan_IN865(); +#elif CHANNEL_PLAN == CP_AS923 + plan = new lora::ChannelPlan_AS923(); +#elif CHANNEL_PLAN == CP_AS923_2 + plan = new lora::ChannelPlan_AS923(); +#elif CHANNEL_PLAN == CP_AS923_3 + plan = new lora::ChannelPlan_AS923(); +#elif CHANNEL_PLAN == CP_AS923_JAPAN + plan = new lora::ChannelPlan_AS923_Japan(); +#elif CHANNEL_PLAN == CP_AS923_JAPAN1 + plan = new lora::ChannelPlan_AS923_Japan1(); +#elif CHANNEL_PLAN == CP_AS923_JAPAN2 + plan = new lora::ChannelPlan_AS923_Japan2(); +#elif CHANNEL_PLAN == CP_RU864 + plan = new lora::ChannelPlan_RU864(); +#else + plan = new lora::ChannelPlan_US915(); +#endif + + return plan; +} + + +void display_config() { + // display configuration and library version information + logInfo("====================="); + logInfo("general configuration"); + logInfo("====================="); + logInfo("version ------------------ %s", dot->getId().c_str()); + logInfo("device ID/EUI ------------ %s", mts::Text::bin2hexString(dot->getDeviceId()).c_str()); + logInfo("default channel plan ----- %s", mDot::FrequencyBandStr(dot->getDefaultFrequencyBand()).c_str()); + logInfo("current channel plan ----- %s", mDot::FrequencyBandStr(dot->getFrequencyBand()).c_str()); + if (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) { + logInfo("frequency sub band ------- %u", dot->getFrequencySubBand()); + } + + std::string network_mode_str("Undefined"); + uint8_t network_mode = dot->getPublicNetwork(); + if (network_mode == lora::PRIVATE_MTS) + network_mode_str = "Private MTS"; + else if (network_mode == lora::PUBLIC_LORAWAN) + network_mode_str = "Public LoRaWAN"; + else if (network_mode == lora::PRIVATE_LORAWAN) + network_mode_str = "Private LoRaWAN"; + logInfo("public network ----------- %s", network_mode_str.c_str()); + + logInfo("========================="); + logInfo("credentials configuration"); + logInfo("========================="); + logInfo("device class ------------- %s", dot->getClass().c_str()); + logInfo("network join mode -------- %s", mDot::JoinModeStr(dot->getJoinMode()).c_str()); + if (dot->getJoinMode() == mDot::MANUAL || dot->getJoinMode() == mDot::PEER_TO_PEER) { + logInfo("network address ---------- %s", mts::Text::bin2hexString(dot->getNetworkAddress()).c_str()); + logInfo("network session key------- %s", mts::Text::bin2hexString(dot->getNetworkSessionKey()).c_str()); + logInfo("data session key---------- %s", mts::Text::bin2hexString(dot->getDataSessionKey()).c_str()); + } else { + logInfo("network name ------------- %s", dot->getNetworkName().c_str()); + logInfo("network phrase ----------- %s", dot->getNetworkPassphrase().c_str()); + logInfo("network EUI -------------- %s", mts::Text::bin2hexString(dot->getNetworkId()).c_str()); + logInfo("network KEY -------------- %s", mts::Text::bin2hexString(dot->getNetworkKey()).c_str()); + } + logInfo("========================"); + logInfo("communication parameters"); + logInfo("========================"); + if (dot->getJoinMode() == mDot::PEER_TO_PEER) { + logInfo("TX frequency ------------- %lu", dot->getTxFrequency()); + } else { + logInfo("acks --------------------- %s, %u attempts", dot->getAck() > 0 ? "on" : "off", dot->getAck()); + } + logInfo("TX datarate -------------- %s", mDot::DataRateStr(dot->getTxDataRate()).c_str()); + logInfo("TX power ----------------- %lu dBm", dot->getTxPower()); + logInfo("antenna gain ------------- %u dBm", dot->getAntennaGain()); + logInfo("LBT ---------------------- %s", dot->getLbtTimeUs() ? "on" : "off"); + if (dot->getLbtTimeUs()) { + logInfo("LBT time ----------------- %lu us", dot->getLbtTimeUs()); + logInfo("LBT threshold ------------ %d dBm", dot->getLbtThreshold()); + } +} + +void update_ota_config_name_phrase(std::string network_name, std::string network_passphrase, uint8_t frequency_sub_band, lora::NetworkType network_type, uint8_t ack) { + std::string current_network_name = dot->getNetworkName(); + std::string current_network_passphrase = dot->getNetworkPassphrase(); + uint8_t current_frequency_sub_band = dot->getFrequencySubBand(); + uint8_t current_network_type = dot->getPublicNetwork(); + uint8_t current_ack = dot->getAck(); + + if (current_network_name != network_name) { + logInfo("changing network name from \"%s\" to \"%s\"", current_network_name.c_str(), network_name.c_str()); + if (dot->setNetworkName(network_name) != mDot::MDOT_OK) { + logError("failed to set network name to \"%s\"", network_name.c_str()); + } + } + + if (current_network_passphrase != network_passphrase) { + logInfo("changing network passphrase from \"%s\" to \"%s\"", current_network_passphrase.c_str(), network_passphrase.c_str()); + if (dot->setNetworkPassphrase(network_passphrase) != mDot::MDOT_OK) { + logError("failed to set network passphrase to \"%s\"", network_passphrase.c_str()); + } + } + + if (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) { + if (current_frequency_sub_band != frequency_sub_band) { + logInfo("changing frequency sub band from %u to %u", current_frequency_sub_band, frequency_sub_band); + if (dot->setFrequencySubBand(frequency_sub_band) != mDot::MDOT_OK) { + logError("failed to set frequency sub band to %u", frequency_sub_band); + } + } + } + + if (current_network_type != network_type) { + if (dot->setPublicNetwork(network_type) != mDot::MDOT_OK) { + logError("failed to set network type"); + } + } + + if (current_ack != ack) { + logInfo("changing acks from %u to %u", current_ack, ack); + if (dot->setAck(ack) != mDot::MDOT_OK) { + logError("failed to set acks to %u", ack); + } + } +} + +void update_ota_config_id_key(uint8_t *network_id, uint8_t *network_key, uint8_t frequency_sub_band, lora::NetworkType network_type, uint8_t ack) { + std::vector<uint8_t> current_network_id = dot->getNetworkId(); + std::vector<uint8_t> current_network_key = dot->getNetworkKey(); + uint8_t current_frequency_sub_band = dot->getFrequencySubBand(); + uint8_t current_network_type = dot->getPublicNetwork(); + uint8_t current_ack = dot->getAck(); + + std::vector<uint8_t> network_id_vector(network_id, network_id + 8); + std::vector<uint8_t> network_key_vector(network_key, network_key + 16); + + if (current_network_id != network_id_vector) { + logInfo("changing network ID from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_id).c_str(), mts::Text::bin2hexString(network_id_vector).c_str()); + if (dot->setNetworkId(network_id_vector) != mDot::MDOT_OK) { + logError("failed to set network ID to \"%s\"", mts::Text::bin2hexString(network_id_vector).c_str()); + } + } + + if (current_network_key != network_key_vector) { + logInfo("changing network KEY from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_key).c_str(), mts::Text::bin2hexString(network_key_vector).c_str()); + if (dot->setNetworkKey(network_key_vector) != mDot::MDOT_OK) { + logError("failed to set network KEY to \"%s\"", mts::Text::bin2hexString(network_key_vector).c_str()); + } + } + + if (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) { + if (current_frequency_sub_band != frequency_sub_band) { + logInfo("changing frequency sub band from %u to %u", current_frequency_sub_band, frequency_sub_band); + if (dot->setFrequencySubBand(frequency_sub_band) != mDot::MDOT_OK) { + logError("failed to set frequency sub band to %u", frequency_sub_band); + } + } + } + + if (current_network_type != network_type) { + if (dot->setPublicNetwork(network_type) != mDot::MDOT_OK) { + logError("failed to set network type"); + } + } + + if (current_ack != ack) { + logInfo("changing acks from %u to %u", current_ack, ack); + if (dot->setAck(ack) != mDot::MDOT_OK) { + logError("failed to set acks to %u", ack); + } + } +} + +void update_manual_config(uint8_t *network_address, uint8_t *network_session_key, uint8_t *data_session_key, uint8_t frequency_sub_band, lora::NetworkType network_type, uint8_t ack) { + std::vector<uint8_t> current_network_address = dot->getNetworkAddress(); + std::vector<uint8_t> current_network_session_key = dot->getNetworkSessionKey(); + std::vector<uint8_t> current_data_session_key = dot->getDataSessionKey(); + uint8_t current_frequency_sub_band = dot->getFrequencySubBand(); + uint8_t current_network_type = dot->getPublicNetwork(); + uint8_t current_ack = dot->getAck(); + + std::vector<uint8_t> network_address_vector(network_address, network_address + 4); + std::vector<uint8_t> network_session_key_vector(network_session_key, network_session_key + 16); + std::vector<uint8_t> data_session_key_vector(data_session_key, data_session_key + 16); + + if (current_network_address != network_address_vector) { + logInfo("changing network address from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_address).c_str(), mts::Text::bin2hexString(network_address_vector).c_str()); + if (dot->setNetworkAddress(network_address_vector) != mDot::MDOT_OK) { + logError("failed to set network address to \"%s\"", mts::Text::bin2hexString(network_address_vector).c_str()); + } + } + + if (current_network_session_key != network_session_key_vector) { + logInfo("changing network session key from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_session_key).c_str(), mts::Text::bin2hexString(network_session_key_vector).c_str()); + if (dot->setNetworkSessionKey(network_session_key_vector) != mDot::MDOT_OK) { + logError("failed to set network session key to \"%s\"", mts::Text::bin2hexString(network_session_key_vector).c_str()); + } + } + + if (current_data_session_key != data_session_key_vector) { + logInfo("changing data session key from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_data_session_key).c_str(), mts::Text::bin2hexString(data_session_key_vector).c_str()); + if (dot->setDataSessionKey(data_session_key_vector) != mDot::MDOT_OK) { + logError("failed to set data session key to \"%s\"", mts::Text::bin2hexString(data_session_key_vector).c_str()); + } + } + + if (current_frequency_sub_band != frequency_sub_band) { + logInfo("changing frequency sub band from %u to %u", current_frequency_sub_band, frequency_sub_band); + if (dot->setFrequencySubBand(frequency_sub_band) != mDot::MDOT_OK) { + logError("failed to set frequency sub band to %u", frequency_sub_band); + } + } + + if (current_network_type != network_type) { + if (dot->setPublicNetwork(network_type) != mDot::MDOT_OK) { + logError("failed to set network type"); + } + } + + if (current_ack != ack) { + logInfo("changing acks from %u to %u", current_ack, ack); + if (dot->setAck(ack) != mDot::MDOT_OK) { + logError("failed to set acks to %u", ack); + } + } +} + +void update_peer_to_peer_config(uint8_t *network_address, uint8_t *network_session_key, uint8_t *data_session_key, uint32_t tx_frequency, uint8_t tx_datarate, uint8_t tx_power) { + std::vector<uint8_t> current_network_address = dot->getNetworkAddress(); + std::vector<uint8_t> current_network_session_key = dot->getNetworkSessionKey(); + std::vector<uint8_t> current_data_session_key = dot->getDataSessionKey(); + uint32_t current_tx_frequency = dot->getTxFrequency(); + uint8_t current_tx_datarate = dot->getTxDataRate(); + uint8_t current_tx_power = dot->getTxPower(); + + std::vector<uint8_t> network_address_vector(network_address, network_address + 4); + std::vector<uint8_t> network_session_key_vector(network_session_key, network_session_key + 16); + std::vector<uint8_t> data_session_key_vector(data_session_key, data_session_key + 16); + + if (current_network_address != network_address_vector) { + logInfo("changing network address from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_address).c_str(), mts::Text::bin2hexString(network_address_vector).c_str()); + if (dot->setNetworkAddress(network_address_vector) != mDot::MDOT_OK) { + logError("failed to set network address to \"%s\"", mts::Text::bin2hexString(network_address_vector).c_str()); + } + } + + if (current_network_session_key != network_session_key_vector) { + logInfo("changing network session key from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_session_key).c_str(), mts::Text::bin2hexString(network_session_key_vector).c_str()); + if (dot->setNetworkSessionKey(network_session_key_vector) != mDot::MDOT_OK) { + logError("failed to set network session key to \"%s\"", mts::Text::bin2hexString(network_session_key_vector).c_str()); + } + } + + if (current_data_session_key != data_session_key_vector) { + logInfo("changing data session key from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_data_session_key).c_str(), mts::Text::bin2hexString(data_session_key_vector).c_str()); + if (dot->setDataSessionKey(data_session_key_vector) != mDot::MDOT_OK) { + logError("failed to set data session key to \"%s\"", mts::Text::bin2hexString(data_session_key_vector).c_str()); + } + } + + if (current_tx_frequency != tx_frequency) { + logInfo("changing TX frequency from %lu to %lu", current_tx_frequency, tx_frequency); + if (dot->setTxFrequency(tx_frequency) != mDot::MDOT_OK) { + logError("failed to set TX frequency to %lu", tx_frequency); + } + } + + if (current_tx_datarate != tx_datarate) { + logInfo("changing TX datarate from %u to %u", current_tx_datarate, tx_datarate); + if (dot->setTxDataRate(tx_datarate) != mDot::MDOT_OK) { + logError("failed to set TX datarate to %u", tx_datarate); + } + } + + if (current_tx_power != tx_power) { + logInfo("changing TX power from %u to %u", current_tx_power, tx_power); + if (dot->setTxPower(tx_power) != mDot::MDOT_OK) { + logError("failed to set TX power to %u", tx_power); + } + } +} + +void update_network_link_check_config(uint8_t link_check_count, uint8_t link_check_threshold) { + uint8_t current_link_check_count = dot->getLinkCheckCount(); + uint8_t current_link_check_threshold = dot->getLinkCheckThreshold(); + + if (current_link_check_count != link_check_count) { + logInfo("changing link check count from %u to %u", current_link_check_count, link_check_count); + if (dot->setLinkCheckCount(link_check_count) != mDot::MDOT_OK) { + logError("failed to set link check count to %u", link_check_count); + } + } + + if (current_link_check_threshold != link_check_threshold) { + logInfo("changing link check threshold from %u to %u", current_link_check_threshold, link_check_threshold); + if (dot->setLinkCheckThreshold(link_check_threshold) != mDot::MDOT_OK) { + logError("failed to set link check threshold to %u", link_check_threshold); + } + } +} + +void join_network() { + int32_t j_attempts = 0; + int32_t ret = mDot::MDOT_ERROR; + + // attempt to join the network + while (ret != mDot::MDOT_OK) { + logInfo("attempt %d to join network", ++j_attempts); + ret = dot->joinNetwork(); + if (ret != mDot::MDOT_OK) { + logError("failed to join network %d:%s", ret, mDot::getReturnCodeString(ret).c_str()); + // in some frequency bands we need to wait until another channel is available before transmitting again + uint32_t delay_s = (dot->getNextTxMs() / 1000) + 1; + if (delay_s < 5) { + logInfo("waiting %lu s until next free channel", delay_s); + ThisThread::sleep_for(std::chrono::seconds(delay_s)); + } else { + logInfo("sleeping %lu s until next free channel", delay_s); + dot->sleep(delay_s, mDot::RTC_ALARM, false); + } + } + } +} + +void sleep_wake_rtc_only(bool deepsleep) { + // in some frequency bands we need to wait until another channel is available before transmitting again + // wait at least 10s between transmissions + uint32_t delay_s = dot->getNextTxMs() / 1000; + if (delay_s < 10) { + delay_s = 10; + } + + logInfo("%ssleeping %lus", deepsleep ? "deep" : "", delay_s); + logInfo("application will %s after waking up", deepsleep ? "execute from beginning" : "resume"); + + // lowest current consumption in sleep mode can only be achieved by configuring IOs as analog inputs with no pull resistors + // the library handles all internal IOs automatically, but the external IOs are the application's responsibility + // certain IOs may require internal pullup or pulldown resistors because leaving them floating would cause extra current consumption + // for xDot: UART_*, I2C_*, SPI_*, GPIO*, WAKE + // for mDot: XBEE_*, USBTX, USBRX, PB_0, PB_1 + // steps are: + // * save IO configuration + // * configure IOs to reduce current consumption + // * sleep + // * restore IO configuration + if (! deepsleep) { + // save the GPIO state. + sleep_save_io(); + + // configure GPIOs for lowest current + sleep_configure_io(); + } + + // go to sleep/deepsleep for delay_s seconds and wake using the RTC alarm + dot->sleep(delay_s, mDot::RTC_ALARM, deepsleep); + + if (! deepsleep) { + // restore the GPIO state. + sleep_restore_io(); + } +} + +void sleep_wake_interrupt_only(bool deepsleep) { +#if defined (TARGET_XDOT_L151CC) + if (deepsleep) { + // for xDot, WAKE pin (connected to S2 on xDot-DK) is the only pin that can wake the processor from deepsleep + // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call + } else { + // configure WAKE pin (connected to S2 on xDot-DK) as the pin that will wake the xDot from low power modes + // other pins can be confgured instead: GPIO0-3 or UART_RX + dot->setWakePin(WAKE); + } + + logInfo("%ssleeping until interrupt on %s pin", deepsleep ? "deep" : "", deepsleep ? "WAKE" : mDot::pinName2Str(dot->getWakePin()).c_str()); +#else + + if (deepsleep) { + // for mDot, XBEE_DIO7 pin is the only pin that can wake the processor from deepsleep + // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call + } else { + // configure XBEE_DIO7 pin as the pin that will wake the mDot from low power modes + // other pins can be confgured instead: XBEE_DIO2-6, XBEE_DI8, XBEE_DIN + dot->setWakePin(XBEE_DIO7); + } + + logInfo("%ssleeping until interrupt on %s pin", deepsleep ? "deep" : "", deepsleep ? "DIO7" : mDot::pinName2Str(dot->getWakePin()).c_str()); +#endif + + logInfo("application will %s after waking up", deepsleep ? "execute from beginning" : "resume"); + + // lowest current consumption in sleep mode can only be achieved by configuring IOs as analog inputs with no pull resistors + // the library handles all internal IOs automatically, but the external IOs are the application's responsibility + // certain IOs may require internal pullup or pulldown resistors because leaving them floating would cause extra current consumption + // for xDot: UART_*, I2C_*, SPI_*, GPIO*, WAKE + // for mDot: XBEE_*, USBTX, USBRX, PB_0, PB_1 + // steps are: + // * save IO configuration + // * configure IOs to reduce current consumption + // * sleep + // * restore IO configuration + if (! deepsleep) { + // save the GPIO state. + sleep_save_io(); + + // configure GPIOs for lowest current + sleep_configure_io(); + } + + // go to sleep/deepsleep and wake on rising edge of configured wake pin (only the WAKE pin in deepsleep) + // since we're not waking on the RTC alarm, the interval is ignored + dot->sleep(0, mDot::INTERRUPT, deepsleep); + + if (! deepsleep) { + // restore the GPIO state. + sleep_restore_io(); + } +} + +void sleep_wake_rtc_or_interrupt(bool deepsleep) { + // in some frequency bands we need to wait until another channel is available before transmitting again + // wait at least 10s between transmissions + uint32_t delay_s = dot->getNextTxMs() / 1000; + if (delay_s < 10) { + delay_s = 10; + } + +#if defined (TARGET_XDOT_L151CC) + if (deepsleep) { + // for xDot, WAKE pin (connected to S2 on xDot-DK) is the only pin that can wake the processor from deepsleep + // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call + } else { + // configure WAKE pin (connected to S2 on xDot-DK) as the pin that will wake the xDot from low power modes + // other pins can be confgured instead: GPIO0-3 or UART_RX + dot->setWakePin(WAKE); + } + + logInfo("%ssleeping %lus or until interrupt on %s pin", deepsleep ? "deep" : "", delay_s, deepsleep ? "WAKE" : mDot::pinName2Str(dot->getWakePin()).c_str()); +#else + if (deepsleep) { + // for mDot, XBEE_DIO7 pin is the only pin that can wake the processor from deepsleep + // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call + } else { + // configure XBEE_DIO7 pin as the pin that will wake the mDot from low power modes + // other pins can be confgured instead: XBEE_DIO2-6, XBEE_DI8, XBEE_DIN + dot->setWakePin(XBEE_DIO7); + } + + logInfo("%ssleeping %lus or until interrupt on %s pin", deepsleep ? "deep" : "", delay_s, deepsleep ? "DIO7" : mDot::pinName2Str(dot->getWakePin()).c_str()); +#endif + + logInfo("application will %s after waking up", deepsleep ? "execute from beginning" : "resume"); + + // lowest current consumption in sleep mode can only be achieved by configuring IOs as analog inputs with no pull resistors + // the library handles all internal IOs automatically, but the external IOs are the application's responsibility + // certain IOs may require internal pullup or pulldown resistors because leaving them floating would cause extra current consumption + // for xDot: UART_*, I2C_*, SPI_*, GPIO*, WAKE + // for mDot: XBEE_*, USBTX, USBRX, PB_0, PB_1 + // steps are: + // * save IO configuration + // * configure IOs to reduce current consumption + // * sleep + // * restore IO configuration + if (! deepsleep) { + // save the GPIO state. + sleep_save_io(); + + // configure GPIOs for lowest current + sleep_configure_io(); + } + + // go to sleep/deepsleep and wake using the RTC alarm after delay_s seconds or rising edge of configured wake pin (only the WAKE pin in deepsleep) + // whichever comes first will wake the xDot + dot->sleep(delay_s, mDot::RTC_ALARM_OR_INTERRUPT, deepsleep); + + if (! deepsleep) { + // restore the GPIO state. + sleep_restore_io(); + } +} + +void sleep_save_io() { +#if defined(TARGET_XDOT_L151CC) + xdot_save_gpio_state(); +#else + portA[0] = GPIOA->MODER; + portA[1] = GPIOA->OTYPER; + portA[2] = GPIOA->OSPEEDR; + portA[3] = GPIOA->PUPDR; + portA[4] = GPIOA->AFR[0]; + portA[5] = GPIOA->AFR[1]; + + portB[0] = GPIOB->MODER; + portB[1] = GPIOB->OTYPER; + portB[2] = GPIOB->OSPEEDR; + portB[3] = GPIOB->PUPDR; + portB[4] = GPIOB->AFR[0]; + portB[5] = GPIOB->AFR[1]; + + portC[0] = GPIOC->MODER; + portC[1] = GPIOC->OTYPER; + portC[2] = GPIOC->OSPEEDR; + portC[3] = GPIOC->PUPDR; + portC[4] = GPIOC->AFR[0]; + portC[5] = GPIOC->AFR[1]; + + portD[0] = GPIOD->MODER; + portD[1] = GPIOD->OTYPER; + portD[2] = GPIOD->OSPEEDR; + portD[3] = GPIOD->PUPDR; + portD[4] = GPIOD->AFR[0]; + portD[5] = GPIOD->AFR[1]; + + portH[0] = GPIOH->MODER; + portH[1] = GPIOH->OTYPER; + portH[2] = GPIOH->OSPEEDR; + portH[3] = GPIOH->PUPDR; + portH[4] = GPIOH->AFR[0]; + portH[5] = GPIOH->AFR[1]; +#endif +} + +void sleep_configure_io() { +#if defined(TARGET_XDOT_L151CC) + // GPIO Ports Clock Enable + __GPIOA_CLK_ENABLE(); + __GPIOB_CLK_ENABLE(); + __GPIOC_CLK_ENABLE(); + __GPIOH_CLK_ENABLE(); + + GPIO_InitTypeDef GPIO_InitStruct; + + // UART1_TX, UART1_RTS & UART1_CTS to analog nopull - RX could be a wakeup source + GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_11 | GPIO_PIN_12; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + // I2C_SDA & I2C_SCL to analog nopull + GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + // SPI_MOSI, SPI_MISO, SPI_SCK, & SPI_NSS to analog nopull + GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + // iterate through potential wake pins - leave the configured wake pin alone if one is needed + if (dot->getWakePin() != WAKE || dot->getWakeMode() == mDot::RTC_ALARM) { + GPIO_InitStruct.Pin = GPIO_PIN_0; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + } + if (dot->getWakePin() != GPIO0 || dot->getWakeMode() == mDot::RTC_ALARM) { + GPIO_InitStruct.Pin = GPIO_PIN_4; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + } + if (dot->getWakePin() != GPIO1 || dot->getWakeMode() == mDot::RTC_ALARM) { + GPIO_InitStruct.Pin = GPIO_PIN_5; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + } + if (dot->getWakePin() != GPIO2 || dot->getWakeMode() == mDot::RTC_ALARM) { + GPIO_InitStruct.Pin = GPIO_PIN_0; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + } + if (dot->getWakePin() != GPIO3 || dot->getWakeMode() == mDot::RTC_ALARM) { + GPIO_InitStruct.Pin = GPIO_PIN_2; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + } + if (dot->getWakePin() != UART1_RX || dot->getWakeMode() == mDot::RTC_ALARM) { + GPIO_InitStruct.Pin = GPIO_PIN_10; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + } +#else + /* GPIO Ports Clock Enable */ + __GPIOA_CLK_ENABLE(); + __GPIOB_CLK_ENABLE(); + __GPIOC_CLK_ENABLE(); + + GPIO_InitTypeDef GPIO_InitStruct; + + // XBEE_DOUT, XBEE_DIN, XBEE_DO8, XBEE_RSSI, USBTX, USBRX, PA_12, PA_13, PA_14 & PA_15 to analog nopull + GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_6 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 + | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + // PB_0, PB_1, PB_3 & PB_4 to analog nopull + GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3 | GPIO_PIN_4; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + // PC_9 & PC_13 to analog nopull + GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_13; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + // iterate through potential wake pins - leave the configured wake pin alone if one is needed + // XBEE_DIN - PA3 + // XBEE_DIO2 - PA5 + // XBEE_DIO3 - PA4 + // XBEE_DIO4 - PA7 + // XBEE_DIO5 - PC1 + // XBEE_DIO6 - PA1 + // XBEE_DIO7 - PA0 + // XBEE_SLEEPRQ - PA11 + + if (dot->getWakePin() != XBEE_DIN || dot->getWakeMode() == mDot::RTC_ALARM) { + GPIO_InitStruct.Pin = GPIO_PIN_3; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + } + + if (dot->getWakePin() != XBEE_DIO2 || dot->getWakeMode() == mDot::RTC_ALARM) { + GPIO_InitStruct.Pin = GPIO_PIN_5; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + } + + if (dot->getWakePin() != XBEE_DIO3 || dot->getWakeMode() == mDot::RTC_ALARM) { + GPIO_InitStruct.Pin = GPIO_PIN_4; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + } + + if (dot->getWakePin() != XBEE_DIO4 || dot->getWakeMode() == mDot::RTC_ALARM) { + GPIO_InitStruct.Pin = GPIO_PIN_7; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + } + + if (dot->getWakePin() != XBEE_DIO5 || dot->getWakeMode() == mDot::RTC_ALARM) { + GPIO_InitStruct.Pin = GPIO_PIN_1; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + } + + if (dot->getWakePin() != XBEE_DIO6 || dot->getWakeMode() == mDot::RTC_ALARM) { + GPIO_InitStruct.Pin = GPIO_PIN_1; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + } + + if (dot->getWakePin() != XBEE_DIO7 || dot->getWakeMode() == mDot::RTC_ALARM) { + GPIO_InitStruct.Pin = GPIO_PIN_0; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + } + + if (dot->getWakePin() != XBEE_SLEEPRQ|| dot->getWakeMode() == mDot::RTC_ALARM) { + GPIO_InitStruct.Pin = GPIO_PIN_11; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + } +#endif +} + +void sleep_restore_io() { +#if defined(TARGET_XDOT_L151CC) + xdot_restore_gpio_state(); +#else + GPIOA->MODER = portA[0]; + GPIOA->OTYPER = portA[1]; + GPIOA->OSPEEDR = portA[2]; + GPIOA->PUPDR = portA[3]; + GPIOA->AFR[0] = portA[4]; + GPIOA->AFR[1] = portA[5]; + + GPIOB->MODER = portB[0]; + GPIOB->OTYPER = portB[1]; + GPIOB->OSPEEDR = portB[2]; + GPIOB->PUPDR = portB[3]; + GPIOB->AFR[0] = portB[4]; + GPIOB->AFR[1] = portB[5]; + + GPIOC->MODER = portC[0]; + GPIOC->OTYPER = portC[1]; + GPIOC->OSPEEDR = portC[2]; + GPIOC->PUPDR = portC[3]; + GPIOC->AFR[0] = portC[4]; + GPIOC->AFR[1] = portC[5]; + + GPIOD->MODER = portD[0]; + GPIOD->OTYPER = portD[1]; + GPIOD->OSPEEDR = portD[2]; + GPIOD->PUPDR = portD[3]; + GPIOD->AFR[0] = portD[4]; + GPIOD->AFR[1] = portD[5]; + + GPIOH->MODER = portH[0]; + GPIOH->OTYPER = portH[1]; + GPIOH->OSPEEDR = portH[2]; + GPIOH->PUPDR = portH[3]; + GPIOH->AFR[0] = portH[4]; + GPIOH->AFR[1] = portH[5]; +#endif +} + +int send_data(std::vector<uint8_t> data) { + int32_t ret; + + ret = dot->send(data); + if (ret != mDot::MDOT_OK) { + logError("failed to send data to %s [%d][%s]", dot->getJoinMode() == mDot::PEER_TO_PEER ? "peer" : "gateway", ret, mDot::getReturnCodeString(ret).c_str()); + } else { + logInfo("successfully sent data to %s", dot->getJoinMode() == mDot::PEER_TO_PEER ? "peer" : "gateway"); + } + + return ret; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main.cpp Wed Jul 07 11:34:06 2021 +0000 @@ -0,0 +1,152 @@ + +/* Libraries */ + +#include "mbed.h" +#include "mDot.h" +#include "ChannelPlans.h" +#include "RadioEvent.h" +#include "dot_util.h" + +#if defined(FOTA) + #include "Fota.h" + #include "SPIFBlockDevice.h" + #include "DataFlashBlockDevice.h" +#endif + +/*****************************************************************************/ + +/* Connection Parameters */ + +// Channel Plan +// The active channel plan is the one that will be compiled +// CP_US915, CP_AU915, CP_EU868, CP_KR920, CP_AS923, CP_AS923_2, CP_AS923_3, +// CP_AS923_JAPAN, CP_AS923_JAPAN1, CP_AS923_JAPAN2, CP_IN865, CP_RU864 +#if !defined(CHANNEL_PLAN) + #define CHANNEL_PLAN CP_EU868 +#endif + +static uint8_t network_address[] = { 0x01, 0x02, 0x03, 0x04 }; +static uint8_t network_session_key[] = { 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04 }; +static uint8_t data_session_key[] = { 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04 }; +static uint8_t frequency_sub_band = 6; +static lora::NetworkType network_type = lora::PUBLIC_LORAWAN; +static uint8_t join_delay = 5; +static uint8_t ack = 1; +static bool adr = true; + +/*****************************************************************************/ + +/* Global Elements */ + +mDot* dot = NULL; +lora::ChannelPlan* plan = NULL; + +/*****************************************************************************/ + +/* Main Function */ + +int main() +{ + RadioEvent events; + + // Create channel plan + plan = create_channel_plan(); + assert(plan); + + #if defined(FOTA) + mbed::BlockDevice* ext_bd = NULL; + + ext_bd = new SPIFBlockDevice(); + int ret = ext_bd->init(); + if (ext_bd->init() < 0) + { + delete ext_bd; + ext_bd = new DataFlashBlockDevice(); + ret = ext_bd->init(); + // Check for zero size because DataFlashBlockDevice doesn't + // return an error if the chip is not present + if ((ret < 0) || (ext_bd->size() == 0)) + { + delete ext_bd; + ext_bd = NULL; + } + } + + dot = mDot::getInstance(plan, ext_bd); + + if (ext_bd != NULL) + { + logInfo("External flash device detected, type: %s, size: 0x%08x", + ext_bd->get_type(), (uint32_t)ext_bd->size()); + } + + Fota::getInstance(dot); + #else + dot = mDot::getInstance(plan); + #endif + assert(dot); + + // attach the custom events handler + dot->setEvents(&events); + + if (!dot->getStandbyFlag()) { + logInfo("mbed-os library version: %d.%d.%d", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION); + + // start from a well-known state + logInfo("defaulting Dot configuration"); + dot->resetConfig(); + dot->resetNetworkSession(); + + // make sure library logging is turned on + dot->setLogLevel(mts::MTSLog::INFO_LEVEL); + + // update configuration if necessary + if (dot->getJoinMode() != mDot::MANUAL) { + logInfo("changing network join mode to MANUAL"); + if (dot->setJoinMode(mDot::MANUAL) != mDot::MDOT_OK) { + logError("failed to set network join mode to MANUAL"); + } + } + // in MANUAL join mode there is no join request/response transaction + // as long as the Dot is configured correctly and provisioned correctly on the gateway, it should be able to communicate + // network address - 4 bytes (00000001 - FFFFFFFE) + // network session key - 16 bytes + // data session key - 16 bytes + // to provision your Dot with a Conduit gateway, follow the following steps + // * ssh into the Conduit + // * provision the Dot using the lora-query application: http://www.multitech.net/developer/software/lora/lora-network-server/ + // lora-query -a 01020304 A 0102030401020304 <your Dot's device ID> 01020304010203040102030401020304 01020304010203040102030401020304 + // * if you change the network address, network session key, or data session key, make sure you update them on the gateway + // to provision your Dot with a 3rd party gateway, see the gateway or network provider documentation + update_manual_config(network_address, network_session_key, data_session_key, frequency_sub_band, network_type, ack); + + // enable or disable Adaptive Data Rate + dot->setAdr(adr); + + // Configure the join delay + dot->setJoinDelay(join_delay); + + // save changes to configuration + logInfo("saving configuration"); + if (!dot->saveConfig()) { + logError("failed to save configuration"); + } + + // display configuration + display_config(); + } else { + // restore the saved session if the dot woke from deepsleep mode + // useful to use with deepsleep because session info is otherwise lost when the dot enters deepsleep + logInfo("restoring network session from NVM"); + dot->restoreNetworkSession(); + } + + while(1) + { + + } + + return 0; +} + +/*****************************************************************************/