
Example programs for MultiTech Dot devices demonstrating how to use the Dot devices and the Dot libraries for LoRa communication.
Dependencies: ISL29011
Dependents: Dot-Examples-delujoc
dot_util.cpp
00001 #include "dot_util.h" 00002 #if defined(TARGET_XDOT_L151CC) 00003 #include "xdot_low_power.h" 00004 #endif 00005 00006 #if defined(TARGET_MTS_MDOT_F411RE) 00007 uint32_t portA[6]; 00008 uint32_t portB[6]; 00009 uint32_t portC[6]; 00010 uint32_t portD[6]; 00011 uint32_t portH[6]; 00012 #endif 00013 00014 00015 lora::ChannelPlan* create_channel_plan() { 00016 lora::ChannelPlan* plan; 00017 00018 #if CHANNEL_PLAN == CP_US915 00019 plan = new lora::ChannelPlan_US915(); 00020 #elif CHANNEL_PLAN == CP_AU915 00021 plan = new lora::ChannelPlan_AU915(); 00022 #elif CHANNEL_PLAN == CP_EU868 00023 plan = new lora::ChannelPlan_EU868(); 00024 #elif CHANNEL_PLAN == CP_KR920 00025 plan = new lora::ChannelPlan_KR920(); 00026 #elif CHANNEL_PLAN == CP_IN865 00027 plan = new lora::ChannelPlan_IN865(); 00028 #elif CHANNEL_PLAN == CP_AS923 00029 plan = new lora::ChannelPlan_AS923(); 00030 #elif CHANNEL_PLAN == CP_AS923_2 00031 plan = new lora::ChannelPlan_AS923(); 00032 #elif CHANNEL_PLAN == CP_AS923_3 00033 plan = new lora::ChannelPlan_AS923(); 00034 #elif CHANNEL_PLAN == CP_AS923_JAPAN 00035 plan = new lora::ChannelPlan_AS923_Japan(); 00036 #elif CHANNEL_PLAN == CP_AS923_JAPAN1 00037 plan = new lora::ChannelPlan_AS923_Japan1(); 00038 #elif CHANNEL_PLAN == CP_AS923_JAPAN2 00039 plan = new lora::ChannelPlan_AS923_Japan2(); 00040 #elif CHANNEL_PLAN == CP_RU864 00041 plan = new lora::ChannelPlan_RU864(); 00042 #endif 00043 00044 return plan; 00045 } 00046 00047 00048 void display_config() { 00049 // display configuration and library version information 00050 logInfo("====================="); 00051 logInfo("general configuration"); 00052 logInfo("====================="); 00053 logInfo("version ------------------ %s", dot->getId().c_str()); 00054 logInfo("device ID/EUI ------------ %s", mts::Text::bin2hexString(dot->getDeviceId()).c_str()); 00055 logInfo("default channel plan ----- %s", mDot::FrequencyBandStr(dot->getDefaultFrequencyBand()).c_str()); 00056 logInfo("current channel plan ----- %s", mDot::FrequencyBandStr(dot->getFrequencyBand()).c_str()); 00057 if (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) { 00058 logInfo("frequency sub band ------- %u", dot->getFrequencySubBand()); 00059 } 00060 00061 std::string network_mode_str("Undefined"); 00062 uint8_t network_mode = dot->getPublicNetwork(); 00063 if (network_mode == lora::PRIVATE_MTS) 00064 network_mode_str = "Private MTS"; 00065 else if (network_mode == lora::PUBLIC_LORAWAN) 00066 network_mode_str = "Public LoRaWAN"; 00067 else if (network_mode == lora::PRIVATE_LORAWAN) 00068 network_mode_str = "Private LoRaWAN"; 00069 logInfo("public network ----------- %s", network_mode_str.c_str()); 00070 00071 logInfo("========================="); 00072 logInfo("credentials configuration"); 00073 logInfo("========================="); 00074 logInfo("device class ------------- %s", dot->getClass().c_str()); 00075 logInfo("network join mode -------- %s", mDot::JoinModeStr(dot->getJoinMode()).c_str()); 00076 if (dot->getJoinMode() == mDot::MANUAL || dot->getJoinMode() == mDot::PEER_TO_PEER) { 00077 logInfo("network address ---------- %s", mts::Text::bin2hexString(dot->getNetworkAddress()).c_str()); 00078 logInfo("network session key------- %s", mts::Text::bin2hexString(dot->getNetworkSessionKey()).c_str()); 00079 logInfo("data session key---------- %s", mts::Text::bin2hexString(dot->getDataSessionKey()).c_str()); 00080 } else { 00081 logInfo("network name ------------- %s", dot->getNetworkName().c_str()); 00082 logInfo("network phrase ----------- %s", dot->getNetworkPassphrase().c_str()); 00083 logInfo("network EUI -------------- %s", mts::Text::bin2hexString(dot->getNetworkId()).c_str()); 00084 logInfo("network KEY -------------- %s", mts::Text::bin2hexString(dot->getNetworkKey()).c_str()); 00085 } 00086 logInfo("========================"); 00087 logInfo("communication parameters"); 00088 logInfo("========================"); 00089 if (dot->getJoinMode() == mDot::PEER_TO_PEER) { 00090 logInfo("TX frequency ------------- %lu", dot->getTxFrequency()); 00091 } else { 00092 logInfo("acks --------------------- %s, %u attempts", dot->getAck() > 0 ? "on" : "off", dot->getAck()); 00093 } 00094 logInfo("TX datarate -------------- %s", mDot::DataRateStr(dot->getTxDataRate()).c_str()); 00095 logInfo("TX power ----------------- %lu dBm", dot->getTxPower()); 00096 logInfo("antenna gain ------------- %u dBm", dot->getAntennaGain()); 00097 logInfo("LBT ---------------------- %s", dot->getLbtTimeUs() ? "on" : "off"); 00098 if (dot->getLbtTimeUs()) { 00099 logInfo("LBT time ----------------- %lu us", dot->getLbtTimeUs()); 00100 logInfo("LBT threshold ------------ %d dBm", dot->getLbtThreshold()); 00101 } 00102 } 00103 00104 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) { 00105 std::string current_network_name = dot->getNetworkName(); 00106 std::string current_network_passphrase = dot->getNetworkPassphrase(); 00107 uint8_t current_frequency_sub_band = dot->getFrequencySubBand(); 00108 uint8_t current_network_type = dot->getPublicNetwork(); 00109 uint8_t current_ack = dot->getAck(); 00110 00111 if (current_network_name != network_name) { 00112 logInfo("changing network name from \"%s\" to \"%s\"", current_network_name.c_str(), network_name.c_str()); 00113 if (dot->setNetworkName(network_name) != mDot::MDOT_OK) { 00114 logError("failed to set network name to \"%s\"", network_name.c_str()); 00115 } 00116 } 00117 00118 if (current_network_passphrase != network_passphrase) { 00119 logInfo("changing network passphrase from \"%s\" to \"%s\"", current_network_passphrase.c_str(), network_passphrase.c_str()); 00120 if (dot->setNetworkPassphrase(network_passphrase) != mDot::MDOT_OK) { 00121 logError("failed to set network passphrase to \"%s\"", network_passphrase.c_str()); 00122 } 00123 } 00124 00125 if (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) { 00126 if (current_frequency_sub_band != frequency_sub_band) { 00127 logInfo("changing frequency sub band from %u to %u", current_frequency_sub_band, frequency_sub_band); 00128 if (dot->setFrequencySubBand(frequency_sub_band) != mDot::MDOT_OK) { 00129 logError("failed to set frequency sub band to %u", frequency_sub_band); 00130 } 00131 } 00132 } 00133 00134 if (current_network_type != network_type) { 00135 if (dot->setPublicNetwork(network_type) != mDot::MDOT_OK) { 00136 logError("failed to set network type"); 00137 } 00138 } 00139 00140 if (current_ack != ack) { 00141 logInfo("changing acks from %u to %u", current_ack, ack); 00142 if (dot->setAck(ack) != mDot::MDOT_OK) { 00143 logError("failed to set acks to %u", ack); 00144 } 00145 } 00146 } 00147 00148 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) { 00149 std::vector<uint8_t> current_network_id = dot->getNetworkId(); 00150 std::vector<uint8_t> current_network_key = dot->getNetworkKey(); 00151 uint8_t current_frequency_sub_band = dot->getFrequencySubBand(); 00152 uint8_t current_network_type = dot->getPublicNetwork(); 00153 uint8_t current_ack = dot->getAck(); 00154 00155 std::vector<uint8_t> network_id_vector(network_id, network_id + 8); 00156 std::vector<uint8_t> network_key_vector(network_key, network_key + 16); 00157 00158 if (current_network_id != network_id_vector) { 00159 logInfo("changing network ID from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_id).c_str(), mts::Text::bin2hexString(network_id_vector).c_str()); 00160 if (dot->setNetworkId(network_id_vector) != mDot::MDOT_OK) { 00161 logError("failed to set network ID to \"%s\"", mts::Text::bin2hexString(network_id_vector).c_str()); 00162 } 00163 } 00164 00165 if (current_network_key != network_key_vector) { 00166 logInfo("changing network KEY from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_key).c_str(), mts::Text::bin2hexString(network_key_vector).c_str()); 00167 if (dot->setNetworkKey(network_key_vector) != mDot::MDOT_OK) { 00168 logError("failed to set network KEY to \"%s\"", mts::Text::bin2hexString(network_key_vector).c_str()); 00169 } 00170 } 00171 00172 if (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) { 00173 if (current_frequency_sub_band != frequency_sub_band) { 00174 logInfo("changing frequency sub band from %u to %u", current_frequency_sub_band, frequency_sub_band); 00175 if (dot->setFrequencySubBand(frequency_sub_band) != mDot::MDOT_OK) { 00176 logError("failed to set frequency sub band to %u", frequency_sub_band); 00177 } 00178 } 00179 } 00180 00181 if (current_network_type != network_type) { 00182 if (dot->setPublicNetwork(network_type) != mDot::MDOT_OK) { 00183 logError("failed to set network type"); 00184 } 00185 } 00186 00187 if (current_ack != ack) { 00188 logInfo("changing acks from %u to %u", current_ack, ack); 00189 if (dot->setAck(ack) != mDot::MDOT_OK) { 00190 logError("failed to set acks to %u", ack); 00191 } 00192 } 00193 } 00194 00195 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) { 00196 std::vector<uint8_t> current_network_address = dot->getNetworkAddress(); 00197 std::vector<uint8_t> current_network_session_key = dot->getNetworkSessionKey(); 00198 std::vector<uint8_t> current_data_session_key = dot->getDataSessionKey(); 00199 uint8_t current_frequency_sub_band = dot->getFrequencySubBand(); 00200 uint8_t current_network_type = dot->getPublicNetwork(); 00201 uint8_t current_ack = dot->getAck(); 00202 00203 std::vector<uint8_t> network_address_vector(network_address, network_address + 4); 00204 std::vector<uint8_t> network_session_key_vector(network_session_key, network_session_key + 16); 00205 std::vector<uint8_t> data_session_key_vector(data_session_key, data_session_key + 16); 00206 00207 if (current_network_address != network_address_vector) { 00208 logInfo("changing network address from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_address).c_str(), mts::Text::bin2hexString(network_address_vector).c_str()); 00209 if (dot->setNetworkAddress(network_address_vector) != mDot::MDOT_OK) { 00210 logError("failed to set network address to \"%s\"", mts::Text::bin2hexString(network_address_vector).c_str()); 00211 } 00212 } 00213 00214 if (current_network_session_key != network_session_key_vector) { 00215 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()); 00216 if (dot->setNetworkSessionKey(network_session_key_vector) != mDot::MDOT_OK) { 00217 logError("failed to set network session key to \"%s\"", mts::Text::bin2hexString(network_session_key_vector).c_str()); 00218 } 00219 } 00220 00221 if (current_data_session_key != data_session_key_vector) { 00222 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()); 00223 if (dot->setDataSessionKey(data_session_key_vector) != mDot::MDOT_OK) { 00224 logError("failed to set data session key to \"%s\"", mts::Text::bin2hexString(data_session_key_vector).c_str()); 00225 } 00226 } 00227 00228 if (current_frequency_sub_band != frequency_sub_band) { 00229 logInfo("changing frequency sub band from %u to %u", current_frequency_sub_band, frequency_sub_band); 00230 if (dot->setFrequencySubBand(frequency_sub_band) != mDot::MDOT_OK) { 00231 logError("failed to set frequency sub band to %u", frequency_sub_band); 00232 } 00233 } 00234 00235 if (current_network_type != network_type) { 00236 if (dot->setPublicNetwork(network_type) != mDot::MDOT_OK) { 00237 logError("failed to set network type"); 00238 } 00239 } 00240 00241 if (current_ack != ack) { 00242 logInfo("changing acks from %u to %u", current_ack, ack); 00243 if (dot->setAck(ack) != mDot::MDOT_OK) { 00244 logError("failed to set acks to %u", ack); 00245 } 00246 } 00247 } 00248 00249 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) { 00250 std::vector<uint8_t> current_network_address = dot->getNetworkAddress(); 00251 std::vector<uint8_t> current_network_session_key = dot->getNetworkSessionKey(); 00252 std::vector<uint8_t> current_data_session_key = dot->getDataSessionKey(); 00253 uint32_t current_tx_frequency = dot->getTxFrequency(); 00254 uint8_t current_tx_datarate = dot->getTxDataRate(); 00255 uint8_t current_tx_power = dot->getTxPower(); 00256 00257 std::vector<uint8_t> network_address_vector(network_address, network_address + 4); 00258 std::vector<uint8_t> network_session_key_vector(network_session_key, network_session_key + 16); 00259 std::vector<uint8_t> data_session_key_vector(data_session_key, data_session_key + 16); 00260 00261 if (current_network_address != network_address_vector) { 00262 logInfo("changing network address from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_address).c_str(), mts::Text::bin2hexString(network_address_vector).c_str()); 00263 if (dot->setNetworkAddress(network_address_vector) != mDot::MDOT_OK) { 00264 logError("failed to set network address to \"%s\"", mts::Text::bin2hexString(network_address_vector).c_str()); 00265 } 00266 } 00267 00268 if (current_network_session_key != network_session_key_vector) { 00269 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()); 00270 if (dot->setNetworkSessionKey(network_session_key_vector) != mDot::MDOT_OK) { 00271 logError("failed to set network session key to \"%s\"", mts::Text::bin2hexString(network_session_key_vector).c_str()); 00272 } 00273 } 00274 00275 if (current_data_session_key != data_session_key_vector) { 00276 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()); 00277 if (dot->setDataSessionKey(data_session_key_vector) != mDot::MDOT_OK) { 00278 logError("failed to set data session key to \"%s\"", mts::Text::bin2hexString(data_session_key_vector).c_str()); 00279 } 00280 } 00281 00282 if (current_tx_frequency != tx_frequency) { 00283 logInfo("changing TX frequency from %lu to %lu", current_tx_frequency, tx_frequency); 00284 if (dot->setTxFrequency(tx_frequency) != mDot::MDOT_OK) { 00285 logError("failed to set TX frequency to %lu", tx_frequency); 00286 } 00287 } 00288 00289 if (current_tx_datarate != tx_datarate) { 00290 logInfo("changing TX datarate from %u to %u", current_tx_datarate, tx_datarate); 00291 if (dot->setTxDataRate(tx_datarate) != mDot::MDOT_OK) { 00292 logError("failed to set TX datarate to %u", tx_datarate); 00293 } 00294 } 00295 00296 if (current_tx_power != tx_power) { 00297 logInfo("changing TX power from %u to %u", current_tx_power, tx_power); 00298 if (dot->setTxPower(tx_power) != mDot::MDOT_OK) { 00299 logError("failed to set TX power to %u", tx_power); 00300 } 00301 } 00302 } 00303 00304 void update_network_link_check_config(uint8_t link_check_count, uint8_t link_check_threshold) { 00305 uint8_t current_link_check_count = dot->getLinkCheckCount(); 00306 uint8_t current_link_check_threshold = dot->getLinkCheckThreshold(); 00307 00308 if (current_link_check_count != link_check_count) { 00309 logInfo("changing link check count from %u to %u", current_link_check_count, link_check_count); 00310 if (dot->setLinkCheckCount(link_check_count) != mDot::MDOT_OK) { 00311 logError("failed to set link check count to %u", link_check_count); 00312 } 00313 } 00314 00315 if (current_link_check_threshold != link_check_threshold) { 00316 logInfo("changing link check threshold from %u to %u", current_link_check_threshold, link_check_threshold); 00317 if (dot->setLinkCheckThreshold(link_check_threshold) != mDot::MDOT_OK) { 00318 logError("failed to set link check threshold to %u", link_check_threshold); 00319 } 00320 } 00321 } 00322 00323 void join_network() { 00324 int32_t j_attempts = 0; 00325 int32_t ret = mDot::MDOT_ERROR; 00326 00327 // attempt to join the network 00328 while (ret != mDot::MDOT_OK) { 00329 logInfo("attempt %d to join network", ++j_attempts); 00330 ret = dot->joinNetwork(); 00331 if (ret != mDot::MDOT_OK) { 00332 logError("failed to join network %d:%s", ret, mDot::getReturnCodeString(ret).c_str()); 00333 // in some frequency bands we need to wait until another channel is available before transmitting again 00334 uint32_t delay_s = (dot->getNextTxMs() / 1000) + 1; 00335 if (delay_s < 5) { 00336 logInfo("waiting %lu s until next free channel", delay_s); 00337 ThisThread::sleep_for(std::chrono::seconds(delay_s)); 00338 } else { 00339 logInfo("sleeping %lu s until next free channel", delay_s); 00340 dot->sleep(delay_s, mDot::RTC_ALARM, false); 00341 } 00342 } 00343 } 00344 } 00345 00346 void sleep_wake_rtc_only(bool deepsleep) { 00347 // in some frequency bands we need to wait until another channel is available before transmitting again 00348 // wait at least 10s between transmissions 00349 uint32_t delay_s = dot->getNextTxMs() / 1000; 00350 if (delay_s < 10) { 00351 delay_s = 10; 00352 } 00353 00354 logInfo("%ssleeping %lus", deepsleep ? "deep" : "", delay_s); 00355 logInfo("application will %s after waking up", deepsleep ? "execute from beginning" : "resume"); 00356 00357 // lowest current consumption in sleep mode can only be achieved by configuring IOs as analog inputs with no pull resistors 00358 // the library handles all internal IOs automatically, but the external IOs are the application's responsibility 00359 // certain IOs may require internal pullup or pulldown resistors because leaving them floating would cause extra current consumption 00360 // for xDot: UART_*, I2C_*, SPI_*, GPIO*, WAKE 00361 // for mDot: XBEE_*, USBTX, USBRX, PB_0, PB_1 00362 // steps are: 00363 // * save IO configuration 00364 // * configure IOs to reduce current consumption 00365 // * sleep 00366 // * restore IO configuration 00367 if (! deepsleep) { 00368 // save the GPIO state. 00369 sleep_save_io(); 00370 00371 // configure GPIOs for lowest current 00372 sleep_configure_io(); 00373 } 00374 00375 // go to sleep/deepsleep for delay_s seconds and wake using the RTC alarm 00376 dot->sleep(delay_s, mDot::RTC_ALARM, deepsleep); 00377 00378 if (! deepsleep) { 00379 // restore the GPIO state. 00380 sleep_restore_io(); 00381 } 00382 } 00383 00384 void sleep_wake_interrupt_only(bool deepsleep) { 00385 #if defined (TARGET_XDOT_L151CC) 00386 if (deepsleep) { 00387 // for xDot, WAKE pin (connected to S2 on xDot-DK) is the only pin that can wake the processor from deepsleep 00388 // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call 00389 } else { 00390 // configure WAKE pin (connected to S2 on xDot-DK) as the pin that will wake the xDot from low power modes 00391 // other pins can be confgured instead: GPIO0-3 or UART_RX 00392 dot->setWakePin(WAKE); 00393 } 00394 00395 logInfo("%ssleeping until interrupt on %s pin", deepsleep ? "deep" : "", deepsleep ? "WAKE" : mDot::pinName2Str(dot->getWakePin()).c_str()); 00396 #else 00397 00398 if (deepsleep) { 00399 // for mDot, XBEE_DIO7 pin is the only pin that can wake the processor from deepsleep 00400 // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call 00401 } else { 00402 // configure XBEE_DIO7 pin as the pin that will wake the mDot from low power modes 00403 // other pins can be confgured instead: XBEE_DIO2-6, XBEE_DI8, XBEE_DIN 00404 dot->setWakePin(XBEE_DIO7); 00405 } 00406 00407 logInfo("%ssleeping until interrupt on %s pin", deepsleep ? "deep" : "", deepsleep ? "DIO7" : mDot::pinName2Str(dot->getWakePin()).c_str()); 00408 #endif 00409 00410 logInfo("application will %s after waking up", deepsleep ? "execute from beginning" : "resume"); 00411 00412 // lowest current consumption in sleep mode can only be achieved by configuring IOs as analog inputs with no pull resistors 00413 // the library handles all internal IOs automatically, but the external IOs are the application's responsibility 00414 // certain IOs may require internal pullup or pulldown resistors because leaving them floating would cause extra current consumption 00415 // for xDot: UART_*, I2C_*, SPI_*, GPIO*, WAKE 00416 // for mDot: XBEE_*, USBTX, USBRX, PB_0, PB_1 00417 // steps are: 00418 // * save IO configuration 00419 // * configure IOs to reduce current consumption 00420 // * sleep 00421 // * restore IO configuration 00422 if (! deepsleep) { 00423 // save the GPIO state. 00424 sleep_save_io(); 00425 00426 // configure GPIOs for lowest current 00427 sleep_configure_io(); 00428 } 00429 00430 // go to sleep/deepsleep and wake on rising edge of configured wake pin (only the WAKE pin in deepsleep) 00431 // since we're not waking on the RTC alarm, the interval is ignored 00432 dot->sleep(0, mDot::INTERRUPT, deepsleep); 00433 00434 if (! deepsleep) { 00435 // restore the GPIO state. 00436 sleep_restore_io(); 00437 } 00438 } 00439 00440 void sleep_wake_rtc_or_interrupt(bool deepsleep) { 00441 // in some frequency bands we need to wait until another channel is available before transmitting again 00442 // wait at least 10s between transmissions 00443 uint32_t delay_s = dot->getNextTxMs() / 1000; 00444 if (delay_s < 10) { 00445 delay_s = 10; 00446 } 00447 00448 #if defined (TARGET_XDOT_L151CC) 00449 if (deepsleep) { 00450 // for xDot, WAKE pin (connected to S2 on xDot-DK) is the only pin that can wake the processor from deepsleep 00451 // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call 00452 } else { 00453 // configure WAKE pin (connected to S2 on xDot-DK) as the pin that will wake the xDot from low power modes 00454 // other pins can be confgured instead: GPIO0-3 or UART_RX 00455 dot->setWakePin(WAKE); 00456 } 00457 00458 logInfo("%ssleeping %lus or until interrupt on %s pin", deepsleep ? "deep" : "", delay_s, deepsleep ? "WAKE" : mDot::pinName2Str(dot->getWakePin()).c_str()); 00459 #else 00460 if (deepsleep) { 00461 // for mDot, XBEE_DIO7 pin is the only pin that can wake the processor from deepsleep 00462 // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call 00463 } else { 00464 // configure XBEE_DIO7 pin as the pin that will wake the mDot from low power modes 00465 // other pins can be confgured instead: XBEE_DIO2-6, XBEE_DI8, XBEE_DIN 00466 dot->setWakePin(XBEE_DIO7); 00467 } 00468 00469 logInfo("%ssleeping %lus or until interrupt on %s pin", deepsleep ? "deep" : "", delay_s, deepsleep ? "DIO7" : mDot::pinName2Str(dot->getWakePin()).c_str()); 00470 #endif 00471 00472 logInfo("application will %s after waking up", deepsleep ? "execute from beginning" : "resume"); 00473 00474 // lowest current consumption in sleep mode can only be achieved by configuring IOs as analog inputs with no pull resistors 00475 // the library handles all internal IOs automatically, but the external IOs are the application's responsibility 00476 // certain IOs may require internal pullup or pulldown resistors because leaving them floating would cause extra current consumption 00477 // for xDot: UART_*, I2C_*, SPI_*, GPIO*, WAKE 00478 // for mDot: XBEE_*, USBTX, USBRX, PB_0, PB_1 00479 // steps are: 00480 // * save IO configuration 00481 // * configure IOs to reduce current consumption 00482 // * sleep 00483 // * restore IO configuration 00484 if (! deepsleep) { 00485 // save the GPIO state. 00486 sleep_save_io(); 00487 00488 // configure GPIOs for lowest current 00489 sleep_configure_io(); 00490 } 00491 00492 // 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) 00493 // whichever comes first will wake the xDot 00494 dot->sleep(delay_s, mDot::RTC_ALARM_OR_INTERRUPT, deepsleep); 00495 00496 if (! deepsleep) { 00497 // restore the GPIO state. 00498 sleep_restore_io(); 00499 } 00500 } 00501 00502 void sleep_save_io() { 00503 #if defined(TARGET_XDOT_L151CC) 00504 xdot_save_gpio_state(); 00505 #else 00506 portA[0] = GPIOA->MODER; 00507 portA[1] = GPIOA->OTYPER; 00508 portA[2] = GPIOA->OSPEEDR; 00509 portA[3] = GPIOA->PUPDR; 00510 portA[4] = GPIOA->AFR[0]; 00511 portA[5] = GPIOA->AFR[1]; 00512 00513 portB[0] = GPIOB->MODER; 00514 portB[1] = GPIOB->OTYPER; 00515 portB[2] = GPIOB->OSPEEDR; 00516 portB[3] = GPIOB->PUPDR; 00517 portB[4] = GPIOB->AFR[0]; 00518 portB[5] = GPIOB->AFR[1]; 00519 00520 portC[0] = GPIOC->MODER; 00521 portC[1] = GPIOC->OTYPER; 00522 portC[2] = GPIOC->OSPEEDR; 00523 portC[3] = GPIOC->PUPDR; 00524 portC[4] = GPIOC->AFR[0]; 00525 portC[5] = GPIOC->AFR[1]; 00526 00527 portD[0] = GPIOD->MODER; 00528 portD[1] = GPIOD->OTYPER; 00529 portD[2] = GPIOD->OSPEEDR; 00530 portD[3] = GPIOD->PUPDR; 00531 portD[4] = GPIOD->AFR[0]; 00532 portD[5] = GPIOD->AFR[1]; 00533 00534 portH[0] = GPIOH->MODER; 00535 portH[1] = GPIOH->OTYPER; 00536 portH[2] = GPIOH->OSPEEDR; 00537 portH[3] = GPIOH->PUPDR; 00538 portH[4] = GPIOH->AFR[0]; 00539 portH[5] = GPIOH->AFR[1]; 00540 #endif 00541 } 00542 00543 void sleep_configure_io() { 00544 #if defined(TARGET_XDOT_L151CC) 00545 // GPIO Ports Clock Enable 00546 __GPIOA_CLK_ENABLE(); 00547 __GPIOB_CLK_ENABLE(); 00548 __GPIOC_CLK_ENABLE(); 00549 __GPIOH_CLK_ENABLE(); 00550 00551 GPIO_InitTypeDef GPIO_InitStruct; 00552 00553 // UART1_TX, UART1_RTS & UART1_CTS to analog nopull - RX could be a wakeup source 00554 GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_11 | GPIO_PIN_12; 00555 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; 00556 GPIO_InitStruct.Pull = GPIO_NOPULL; 00557 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 00558 00559 // I2C_SDA & I2C_SCL to analog nopull 00560 GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9; 00561 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; 00562 GPIO_InitStruct.Pull = GPIO_NOPULL; 00563 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); 00564 00565 // SPI_MOSI, SPI_MISO, SPI_SCK, & SPI_NSS to analog nopull 00566 GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15; 00567 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; 00568 GPIO_InitStruct.Pull = GPIO_NOPULL; 00569 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); 00570 00571 // iterate through potential wake pins - leave the configured wake pin alone if one is needed 00572 if (dot->getWakePin() != WAKE || dot->getWakeMode() == mDot::RTC_ALARM) { 00573 GPIO_InitStruct.Pin = GPIO_PIN_0; 00574 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; 00575 GPIO_InitStruct.Pull = GPIO_NOPULL; 00576 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 00577 } 00578 if (dot->getWakePin() != GPIO0 || dot->getWakeMode() == mDot::RTC_ALARM) { 00579 GPIO_InitStruct.Pin = GPIO_PIN_4; 00580 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; 00581 GPIO_InitStruct.Pull = GPIO_NOPULL; 00582 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 00583 } 00584 if (dot->getWakePin() != GPIO1 || dot->getWakeMode() == mDot::RTC_ALARM) { 00585 GPIO_InitStruct.Pin = GPIO_PIN_5; 00586 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; 00587 GPIO_InitStruct.Pull = GPIO_NOPULL; 00588 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 00589 } 00590 if (dot->getWakePin() != GPIO2 || dot->getWakeMode() == mDot::RTC_ALARM) { 00591 GPIO_InitStruct.Pin = GPIO_PIN_0; 00592 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; 00593 GPIO_InitStruct.Pull = GPIO_NOPULL; 00594 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); 00595 } 00596 if (dot->getWakePin() != GPIO3 || dot->getWakeMode() == mDot::RTC_ALARM) { 00597 GPIO_InitStruct.Pin = GPIO_PIN_2; 00598 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; 00599 GPIO_InitStruct.Pull = GPIO_NOPULL; 00600 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); 00601 } 00602 if (dot->getWakePin() != UART1_RX || dot->getWakeMode() == mDot::RTC_ALARM) { 00603 GPIO_InitStruct.Pin = GPIO_PIN_10; 00604 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; 00605 GPIO_InitStruct.Pull = GPIO_NOPULL; 00606 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 00607 } 00608 #else 00609 /* GPIO Ports Clock Enable */ 00610 __GPIOA_CLK_ENABLE(); 00611 __GPIOB_CLK_ENABLE(); 00612 __GPIOC_CLK_ENABLE(); 00613 00614 GPIO_InitTypeDef GPIO_InitStruct; 00615 00616 // XBEE_DOUT, XBEE_DIN, XBEE_DO8, XBEE_RSSI, USBTX, USBRX, PA_12, PA_13, PA_14 & PA_15 to analog nopull 00617 GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_6 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 00618 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15; 00619 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; 00620 GPIO_InitStruct.Pull = GPIO_NOPULL; 00621 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 00622 00623 // PB_0, PB_1, PB_3 & PB_4 to analog nopull 00624 GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3 | GPIO_PIN_4; 00625 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; 00626 GPIO_InitStruct.Pull = GPIO_NOPULL; 00627 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); 00628 00629 // PC_9 & PC_13 to analog nopull 00630 GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_13; 00631 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; 00632 GPIO_InitStruct.Pull = GPIO_NOPULL; 00633 HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); 00634 00635 // iterate through potential wake pins - leave the configured wake pin alone if one is needed 00636 // XBEE_DIN - PA3 00637 // XBEE_DIO2 - PA5 00638 // XBEE_DIO3 - PA4 00639 // XBEE_DIO4 - PA7 00640 // XBEE_DIO5 - PC1 00641 // XBEE_DIO6 - PA1 00642 // XBEE_DIO7 - PA0 00643 // XBEE_SLEEPRQ - PA11 00644 00645 if (dot->getWakePin() != XBEE_DIN || dot->getWakeMode() == mDot::RTC_ALARM) { 00646 GPIO_InitStruct.Pin = GPIO_PIN_3; 00647 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; 00648 GPIO_InitStruct.Pull = GPIO_NOPULL; 00649 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 00650 } 00651 00652 if (dot->getWakePin() != XBEE_DIO2 || dot->getWakeMode() == mDot::RTC_ALARM) { 00653 GPIO_InitStruct.Pin = GPIO_PIN_5; 00654 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; 00655 GPIO_InitStruct.Pull = GPIO_NOPULL; 00656 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 00657 } 00658 00659 if (dot->getWakePin() != XBEE_DIO3 || dot->getWakeMode() == mDot::RTC_ALARM) { 00660 GPIO_InitStruct.Pin = GPIO_PIN_4; 00661 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; 00662 GPIO_InitStruct.Pull = GPIO_NOPULL; 00663 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 00664 } 00665 00666 if (dot->getWakePin() != XBEE_DIO4 || dot->getWakeMode() == mDot::RTC_ALARM) { 00667 GPIO_InitStruct.Pin = GPIO_PIN_7; 00668 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; 00669 GPIO_InitStruct.Pull = GPIO_NOPULL; 00670 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 00671 } 00672 00673 if (dot->getWakePin() != XBEE_DIO5 || dot->getWakeMode() == mDot::RTC_ALARM) { 00674 GPIO_InitStruct.Pin = GPIO_PIN_1; 00675 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; 00676 GPIO_InitStruct.Pull = GPIO_NOPULL; 00677 HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); 00678 } 00679 00680 if (dot->getWakePin() != XBEE_DIO6 || dot->getWakeMode() == mDot::RTC_ALARM) { 00681 GPIO_InitStruct.Pin = GPIO_PIN_1; 00682 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; 00683 GPIO_InitStruct.Pull = GPIO_NOPULL; 00684 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 00685 } 00686 00687 if (dot->getWakePin() != XBEE_DIO7 || dot->getWakeMode() == mDot::RTC_ALARM) { 00688 GPIO_InitStruct.Pin = GPIO_PIN_0; 00689 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; 00690 GPIO_InitStruct.Pull = GPIO_NOPULL; 00691 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 00692 } 00693 00694 if (dot->getWakePin() != XBEE_SLEEPRQ|| dot->getWakeMode() == mDot::RTC_ALARM) { 00695 GPIO_InitStruct.Pin = GPIO_PIN_11; 00696 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; 00697 GPIO_InitStruct.Pull = GPIO_NOPULL; 00698 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 00699 } 00700 #endif 00701 } 00702 00703 void sleep_restore_io() { 00704 #if defined(TARGET_XDOT_L151CC) 00705 xdot_restore_gpio_state(); 00706 #else 00707 GPIOA->MODER = portA[0]; 00708 GPIOA->OTYPER = portA[1]; 00709 GPIOA->OSPEEDR = portA[2]; 00710 GPIOA->PUPDR = portA[3]; 00711 GPIOA->AFR[0] = portA[4]; 00712 GPIOA->AFR[1] = portA[5]; 00713 00714 GPIOB->MODER = portB[0]; 00715 GPIOB->OTYPER = portB[1]; 00716 GPIOB->OSPEEDR = portB[2]; 00717 GPIOB->PUPDR = portB[3]; 00718 GPIOB->AFR[0] = portB[4]; 00719 GPIOB->AFR[1] = portB[5]; 00720 00721 GPIOC->MODER = portC[0]; 00722 GPIOC->OTYPER = portC[1]; 00723 GPIOC->OSPEEDR = portC[2]; 00724 GPIOC->PUPDR = portC[3]; 00725 GPIOC->AFR[0] = portC[4]; 00726 GPIOC->AFR[1] = portC[5]; 00727 00728 GPIOD->MODER = portD[0]; 00729 GPIOD->OTYPER = portD[1]; 00730 GPIOD->OSPEEDR = portD[2]; 00731 GPIOD->PUPDR = portD[3]; 00732 GPIOD->AFR[0] = portD[4]; 00733 GPIOD->AFR[1] = portD[5]; 00734 00735 GPIOH->MODER = portH[0]; 00736 GPIOH->OTYPER = portH[1]; 00737 GPIOH->OSPEEDR = portH[2]; 00738 GPIOH->PUPDR = portH[3]; 00739 GPIOH->AFR[0] = portH[4]; 00740 GPIOH->AFR[1] = portH[5]; 00741 #endif 00742 } 00743 00744 int send_data(std::vector<uint8_t> data) { 00745 int32_t ret; 00746 00747 ret = dot->send(data); 00748 if (ret != mDot::MDOT_OK) { 00749 logError("failed to send data to %s [%d][%s]", dot->getJoinMode() == mDot::PEER_TO_PEER ? "peer" : "gateway", ret, mDot::getReturnCodeString(ret).c_str()); 00750 } else { 00751 logInfo("successfully sent data to %s", dot->getJoinMode() == mDot::PEER_TO_PEER ? "peer" : "gateway"); 00752 } 00753 00754 return ret; 00755 } 00756
Generated on Tue Jul 12 2022 13:03:22 by
