Multitech xDot Utils
MultitechDot.cpp@4:db99b2a7d062, 2018-05-21 (annotated)
- 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?
User | Revision | Line number | New 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 | } |