Fork to see if I can get working

Dependencies:   BufferedSerial OneWire WinbondSPIFlash libxDot-dev-mbed5-deprecated

Fork of xDotBridge_update_test20180823 by Matt Briggs

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers dot_util.cpp Source File

dot_util.cpp

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