Multitech xDot Utils

Committer:
Lucian Corduneanu
Date:
Mon May 21 18:08:09 2018 +0300
Revision:
4:db99b2a7d062
Parent:
3:7fa5603c10dc
Child:
6:febbdd0d0e55
Refactor & update the multitech dot utils to the latest version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
lucian@1.0.0.127.in-addr.arpa 1:73cea350269e 1 #include "ChannelPlan.h"
lucian@1.0.0.127.in-addr.arpa 1:73cea350269e 2 #include "plans/ChannelPlan_EU868.h"
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 3 #include "MultitechDot.h"
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 4
lucian@192-168-0-103.rdsnet.ro 2:8d1c64670642 5 MultitechDot *MultitechDot::get_instance(struct dot_config *config) {
lucian@1.0.0.127.in-addr.arpa 1:73cea350269e 6 using namespace lora;
lucian@192-168-0-103.rdsnet.ro 2:8d1c64670642 7
lucian@1.0.0.127.in-addr.arpa 1:73cea350269e 8 ChannelPlan *plan = new ChannelPlan_EU868();
lucian@192-168-0-103.rdsnet.ro 2:8d1c64670642 9 MultitechDot *dot = (MultitechDot *) mDot::getInstance(plan);
lucian@192-168-0-103.rdsnet.ro 2:8d1c64670642 10
lucian@192-168-0-103.rdsnet.ro 2:8d1c64670642 11 dot->config(config);
lucian@192-168-0-103.rdsnet.ro 2:8d1c64670642 12
lucian@192-168-0-103.rdsnet.ro 2:8d1c64670642 13 return dot;
lucian@1.0.0.127.in-addr.arpa 1:73cea350269e 14 }
lucian@1.0.0.127.in-addr.arpa 1:73cea350269e 15
lucian@192-168-0-103.rdsnet.ro 2:8d1c64670642 16 void MultitechDot::config(struct dot_config *config) {
lucian@192-168-0-103.rdsnet.ro 2:8d1c64670642 17 _config = config;
lucian@192-168-0-103.rdsnet.ro 2:8d1c64670642 18
lucian@192-168-0-103.rdsnet.ro 2:8d1c64670642 19 this->setLogLevel(config->log_level);
lucian@192-168-0-108.rdsnet.ro 3:7fa5603c10dc 20 this->setDisableDutyCycle(config->disable_duty_cycle);
lucian@192-168-0-103.rdsnet.ro 2:8d1c64670642 21
lucian@192-168-0-103.rdsnet.ro 2:8d1c64670642 22 logInfo("Start configuring the device");
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 23 if (!this->getStandbyFlag()) {
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 24 logInfo("mbed-os library version: %d", MBED_LIBRARY_VERSION);
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 25
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 26 // start from a well-known state
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 27 logInfo("defaulting Dot configuration");
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 28 this->resetConfig();
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 29 this->resetNetworkSession();
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 30
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 31 // update configuration if necessary
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 32 if (this->getJoinMode() != this->MANUAL) {
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 33 logInfo("changing network join mode to MANUAL");
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 34 if (this->setJoinMode(this->MANUAL) != this->MDOT_OK) {
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 35 logError("failed to set network join mode to MANUAL");
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 36 }
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 37 }
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 38 // in MANUAL join mode there is no join request/response transaction
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 39 // as long as the Dot is configured correctly and provisioned correctly on the gateway, it should be able to communicate
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 40 // network address - 4 bytes (00000001 - FFFFFFFE)
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 41 // network session key - 16 bytes
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 42 // data session key - 16 bytes
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 43 // to provision your Dot with a Conduit gateway, follow the following steps
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 44 // * ssh into the Conduit
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 45 // * provision the Dot using the lora-query application: http://www.multitech.net/developer/software/lora/lora-network-server/
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 46 // lora-query -a 01020304 A 0102030401020304 <your Dot's device ID> 01020304010203040102030401020304 01020304010203040102030401020304
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 47 // * if you change the network address, network session key, or data session key, make sure you update them on the gateway
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 48 // to provision your Dot with a 3rd party gateway, see the gateway or network provider documentation
lucian@192-168-0-103.rdsnet.ro 2:8d1c64670642 49 this->update_manual_config(config);
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 50
Lucian Corduneanu 4:db99b2a7d062 51 // enable or disable Adaptive Data Rate
Lucian Corduneanu 4:db99b2a7d062 52 this->setAdr(config->adr);
Lucian Corduneanu 4:db99b2a7d062 53
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 54 // save changes to configuration
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 55 logInfo("saving configuration");
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 56 if (!this->saveConfig()) {
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 57 logError("failed to save configuration");
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 58 }
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 59
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 60 // display configuration
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 61 this->display_config();
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 62 } else {
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 63 // restore the saved session if the dot woke from deepsleep mode
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 64 // useful to use with deepsleep because session info is otherwise lost when the dot enters deepsleep
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 65 logInfo("restoring network session from NVM");
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 66 this->restoreNetworkSession();
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 67 }
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 68 }
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 69
lucian@192-168-0-103.rdsnet.ro 2:8d1c64670642 70 struct dot_config *MultitechDot::get_config() {
lucian@192-168-0-103.rdsnet.ro 2:8d1c64670642 71 return _config;
lucian@192-168-0-103.rdsnet.ro 2:8d1c64670642 72 }
lucian@192-168-0-103.rdsnet.ro 2:8d1c64670642 73
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 74
lucian@192-168-0-103.rdsnet.ro 2:8d1c64670642 75 void MultitechDot::update_manual_config(struct dot_config *config) {
Lucian Corduneanu 4:db99b2a7d062 76 BaseDot::update_manual_config(
Lucian Corduneanu 4:db99b2a7d062 77 config->network_address,
Lucian Corduneanu 4:db99b2a7d062 78 config->network_session_key,
Lucian Corduneanu 4:db99b2a7d062 79 config->data_session_key,
Lucian Corduneanu 4:db99b2a7d062 80 config->frequency_sub_band,
Lucian Corduneanu 4:db99b2a7d062 81 config->public_network,
Lucian Corduneanu 4:db99b2a7d062 82 config->ack
Lucian Corduneanu 4:db99b2a7d062 83 );
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 84 }
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 85
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 86 void MultitechDot::sleep_wake_rtc_or_interrupt(uint32_t delay_s, bool deepsleep) {
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 87 if (deepsleep) {
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 88 // for xDot, WAKE pin (connected to S2 on xDot-DK) is the only pin that can wake the processor from deepsleep
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 89 // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the this->sleep call
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 90 } else {
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 91 // configure WAKE pin (connected to S2 on xDot-DK) as the pin that will wake the xDot from low power modes
lucian@192-168-0-108.rdsnet.ro 3:7fa5603c10dc 92 // other pins can be configured instead: GPIO0-3 or UART_RX
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 93 this->setWakePin(WAKE);
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 94 }
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 95
lucian@192-168-0-108.rdsnet.ro 3:7fa5603c10dc 96 logInfo("%s sleeping %lus or until interrupt on %s pin", deepsleep ? "deep" : "", delay_s,
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 97 deepsleep ? "WAKE" : this->pinName2Str(this->getWakePin()).c_str());
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 98
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 99 logInfo("application will %s after waking up", deepsleep ? "execute from beginning" : "resume");
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 100
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 101 // lowest current consumption in sleep mode can only be achieved by configuring IOs as analog inputs with no pull resistors
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 102 // the library handles all internal IOs automatically, but the external IOs are the application's responsibility
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 103 // certain IOs may require internal pullup or pulldown resistors because leaving them floating would cause extra current consumption
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 104 // for xDot: UART_*, I2C_*, SPI_*, GPIO*, WAKE
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 105 // for mDot: XBEE_*, USBTX, USBRX, PB_0, PB_1
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 106 // steps are:
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 107 // * save IO configuration
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 108 // * configure IOs to reduce current consumption
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 109 // * sleep
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 110 // * restore IO configuration
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 111 if (!deepsleep) {
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 112 // save the GPIO state.
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 113 this->sleep_save_io();
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 114
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 115 // configure GPIOs for lowest current
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 116 this->sleep_configure_io();
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 117 }
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 118
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 119 // 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)
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 120 // whichever comes first will wake the xDot
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 121 this->sleep(delay_s, this->RTC_ALARM_OR_INTERRUPT, deepsleep);
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 122
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 123 if (!deepsleep) {
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 124 // restore the GPIO state.
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 125 this->sleep_restore_io();
lucian@1.0.0.127.in-addr.arpa 1:73cea350269e 126 this->sleep_reset_hsi();
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 127 }
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 128 }
lucian@1.0.0.127.in-addr.arpa 0:a5748bc6e3e1 129
lucian@1.0.0.127.in-addr.arpa 1:73cea350269e 130 void MultitechDot::sleep_reset_hsi() {
lucian@1.0.0.127.in-addr.arpa 1:73cea350269e 131 // Enable the HSI (to clock the ADC)
lucian@1.0.0.127.in-addr.arpa 1:73cea350269e 132 RCC_OscInitTypeDef RCC_OscInitStruct;
lucian@1.0.0.127.in-addr.arpa 1:73cea350269e 133 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
lucian@1.0.0.127.in-addr.arpa 1:73cea350269e 134 RCC_OscInitStruct.HSIState = RCC_HSI_ON;
lucian@1.0.0.127.in-addr.arpa 1:73cea350269e 135 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
lucian@1.0.0.127.in-addr.arpa 1:73cea350269e 136 HAL_RCC_OscConfig(&RCC_OscInitStruct);
lucian@1.0.0.127.in-addr.arpa 1:73cea350269e 137 }