ESP32-PaxCounter/src/reset.cpp

178 lines
4.4 KiB
C++
Raw Normal View History

// Basic Config
#include "globals.h"
#include "reset.h"
// Local logging tag
static const char TAG[] = __FILE__;
2020-12-09 10:15:12 +01:00
// Conversion factor for micro seconds to seconds
#define uS_TO_S_FACTOR 1000000ULL
// variables keep its values after a wakeup from sleep
RTC_DATA_ATTR runmode_t RTC_runmode = RUNMODE_POWERCYCLE;
2020-12-10 15:10:28 +01:00
RTC_DATA_ATTR struct timeval RTC_sleep_start_time;
timeval sleep_stop_time;
2020-12-09 10:15:12 +01:00
const char *runmode[4] = {"powercycle", "normal", "wakeup", "update"};
void do_reset(bool warmstart) {
if (warmstart) {
2020-12-09 10:15:12 +01:00
ESP_LOGI(TAG, "restarting device (warmstart), keeping runmode %s",
runmode[RTC_runmode]);
} else {
#if (HAS_LORA)
2020-12-09 10:15:12 +01:00
if (RTC_runmode == RUNMODE_NORMAL) {
LMIC_shutdown();
2020-12-09 10:15:12 +01:00
}
#endif
RTC_runmode = RUNMODE_POWERCYCLE;
2020-12-09 10:15:12 +01:00
ESP_LOGI(TAG, "restarting device (coldstart), setting runmode %s",
runmode[RTC_runmode]);
}
esp_restart();
}
void do_after_reset(void) {
struct timeval sleep_stop_time;
uint64_t sleep_time_ms;
switch (esp_sleep_get_wakeup_cause()) {
case ESP_SLEEP_WAKEUP_EXT0: // Wakeup caused by external signal using RTC_IO
case ESP_SLEEP_WAKEUP_EXT1: // Wakeup caused by external signal using
// RTC_CNTL
case ESP_SLEEP_WAKEUP_TIMER: // Wakeup caused by timer
case ESP_SLEEP_WAKEUP_TOUCHPAD: // Wakeup caused by touchpad
case ESP_SLEEP_WAKEUP_ULP: // Wakeup caused by ULP program
// calculate time spent in deep sleep
gettimeofday(&sleep_stop_time, NULL);
sleep_time_ms =
(sleep_stop_time.tv_sec - RTC_sleep_start_time.tv_sec) * 1000 +
(sleep_stop_time.tv_usec - RTC_sleep_start_time.tv_usec) / 1000;
ESP_LOGI(TAG, "Time spent in deep sleep: %d ms", sleep_time_ms);
2019-10-27 16:13:33 +01:00
RTC_runmode = RUNMODE_WAKEUP;
break;
case ESP_SLEEP_WAKEUP_ALL:
case ESP_SLEEP_WAKEUP_GPIO:
case ESP_SLEEP_WAKEUP_UART:
case ESP_SLEEP_WAKEUP_UNDEFINED:
default:
// not a deep sleep reset
2019-10-27 16:13:33 +01:00
RTC_runmode = RUNMODE_POWERCYCLE;
break;
} // switch
2020-12-09 10:15:12 +01:00
ESP_LOGI(TAG, "Starting Software v%s, runmode %s", PROGVERSION,
runmode[RTC_runmode]);
}
void enter_deepsleep(const uint64_t wakeup_sec = 60,
2020-12-10 15:10:28 +01:00
gpio_num_t wakeup_gpio = GPIO_NUM_MAX) {
int i;
// validate wake up pin, if we have
if (!GPIO_IS_VALID_GPIO(wakeup_gpio))
wakeup_gpio = GPIO_NUM_MAX;
2020-12-09 10:15:12 +01:00
// ensure we are in normal runmode, not udpate or wakeup
if ((RTC_runmode != RUNMODE_NORMAL)
#if (HAS_LORA)
|| (LMIC.opmode & (OP_JOINING | OP_REJOIN))
#endif
2020-12-10 15:10:28 +01:00
)
return;
2020-12-09 10:15:12 +01:00
2020-12-10 15:10:28 +01:00
ESP_LOGI(TAG, "Preparing to sleep...");
// stop further enqueuing of senddata
sendTimer.detach();
2020-12-10 22:14:41 +01:00
// shutdown MQTT safely
#ifdef HAS_MQTT
// to come
#endif
// shutdown SPI safely
#ifdef HAS_SPI
// to come
#endif
// halt interrupts accessing i2c bus
mask_user_IRQ();
2020-12-10 15:10:28 +01:00
// switch off radio
#if (BLECOUNTER)
stop_BLEscan();
btStop();
#endif
#if (WIFICOUNTER)
switch_wifi_sniffer(0);
#endif
// wait a while (max 100 sec) to clear send queues
2020-12-09 10:15:12 +01:00
ESP_LOGI(TAG, "Waiting until send queues are empty...");
2020-12-10 15:10:28 +01:00
for (i = 10; i > 0; i--) {
if (!allQueuesEmtpy())
vTaskDelay(pdMS_TO_TICKS(10000));
else
break;
}
if (i == 0)
goto Error;
2020-12-10 15:10:28 +01:00
// shutdown LMIC safely, waiting max 100 sec
#if (HAS_LORA)
2020-12-09 10:15:12 +01:00
ESP_LOGI(TAG, "Waiting until LMIC is idle...");
2020-12-10 15:10:28 +01:00
for (i = 10; i > 0; i--) {
if ((LMIC.opmode & OP_TXRXPEND) ||
os_queryTimeCriticalJobs(sec2osticks(wakeup_sec)))
vTaskDelay(pdMS_TO_TICKS(10000));
else
break;
}
if (i == 0)
goto Error;
2019-10-27 16:13:33 +01:00
2020-12-09 10:15:12 +01:00
SaveLMICToRTC(wakeup_sec);
#endif // (HAS_LORA)
2019-10-27 16:13:33 +01:00
// switch off display
#ifdef HAS_DISPLAY
dp_shutdown();
#endif
// reduce power if has PMU
#ifdef HAS_PMU
AXP192_power(pmu_power_sleep);
#endif
// shutdown i2c bus
i2c_deinit();
// configure wakeup sources
// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/sleep_modes.html
// set up RTC wakeup timer, if we have
if (wakeup_sec > 0) {
esp_sleep_enable_timer_wakeup(wakeup_sec * uS_TO_S_FACTOR);
}
// set wakeup gpio, if we have
if (wakeup_gpio != GPIO_NUM_MAX) {
rtc_gpio_isolate(wakeup_gpio); // minimize deep sleep current
esp_sleep_enable_ext1_wakeup(1ULL << wakeup_gpio, ESP_EXT1_WAKEUP_ALL_LOW);
}
2020-12-10 15:10:28 +01:00
// time stamp sleep start time. Deep sleep.
gettimeofday(&RTC_sleep_start_time, NULL);
2020-12-09 10:15:12 +01:00
ESP_LOGI(TAG, "Going to sleep, good bye.");
esp_deep_sleep_start();
2020-12-10 15:10:28 +01:00
Error:
ESP_LOGE(TAG, "Can't go to sleep. Resetting.");
do_reset(true);
}