Echo example of class C devices receiving downlink and sending as next uplink

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