LoRa sending TSL lux sensor

Dependencies:   TSL2561_I2C libmDot-mbed5

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