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