nguyen hoang / Mbed OS Dot-Examples_1008

Dependencies:   libmDot-mbed5 ISL29011

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