Skip to content

Commit

Permalink
fix: device sleep (part 1) (#3590)
Browse files Browse the repository at this point in the history
* fix sleep part 1

* always show wakeup reason in debug log

* fix screen turn on issue

* avoid unnecessary reboot when entering light sleep

* set DIO1 based on radio type

---------

Co-authored-by: Ben Meadors <[email protected]>
  • Loading branch information
mverch67 and thebentern authored Apr 12, 2024
1 parent 8fd32f3 commit 4c9646f
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 24 deletions.
23 changes: 13 additions & 10 deletions src/PowerFSM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,18 +102,21 @@ static void lsIdle()
powerFSM.trigger(EVENT_SERIAL_CONNECTED);
break;

case ESP_SLEEP_WAKEUP_GPIO:
// GPIO wakeup is now used for all ESP32 devices during light sleep
powerFSM.trigger(EVENT_PRESS);
break;

default:
// We woke for some other reason (device interrupt?)
LOG_INFO("wakeCause2 %d\n", wakeCause2);
// We woke for some other reason (button press, device IRQ interrupt)

// Let the NB state handle the IRQ (and that state will handle stuff like IRQs etc)
// we lie and say "wake timer" because the interrupt will be handled by the regular IRQ code
powerFSM.trigger(EVENT_WAKE_TIMER);
#ifdef BUTTON_PIN
bool pressed = !digitalRead(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN);
#else
bool pressed = false;
#endif
if (pressed) { // If we woke because of press, instead generate a PRESS event.
powerFSM.trigger(EVENT_PRESS);
} else {
// Otherwise let the NB state handle the IRQ (and that state will handle stuff like IRQs etc)
// we lie and say "wake timer" because the interrupt will be handled by the regular IRQ code
powerFSM.trigger(EVENT_WAKE_TIMER);
}
break;
}
} else {
Expand Down
5 changes: 5 additions & 0 deletions src/detect/LoRaRadioType.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma once

enum LoRaRadioType { NO_RADIO, STM32WLx_RADIO, SIM_RADIO, RF95_RADIO, SX1262_RADIO, SX1268_RADIO, LLCC68_RADIO, SX1280_RADIO };

extern LoRaRadioType radioType;
11 changes: 11 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ NRF52Bluetooth *nrf52Bluetooth;
#include "SX1262Interface.h"
#include "SX1268Interface.h"
#include "SX1280Interface.h"
#include "detect/LoRaRadioType.h"

#ifdef ARCH_STM32WL
#include "STM32WLE5JCInterface.h"
Expand Down Expand Up @@ -142,6 +143,9 @@ ATECCX08A atecc;
Adafruit_DRV2605 drv;
#endif

// Global LoRa radio type
LoRaRadioType radioType = NO_RADIO;

bool isVibrating = false;

bool eink_found = true;
Expand Down Expand Up @@ -793,6 +797,7 @@ void setup()
rIf = NULL;
} else {
LOG_INFO("STM32WL Radio init succeeded, using STM32WL radio\n");
radioType = STM32WLx_RADIO;
}
}
#endif
Expand All @@ -806,6 +811,7 @@ void setup()
rIf = NULL;
} else {
LOG_INFO("Using SIMULATED radio!\n");
radioType = SIM_RADIO;
}
}
#endif
Expand All @@ -819,6 +825,7 @@ void setup()
rIf = NULL;
} else {
LOG_INFO("RF95 Radio init succeeded, using RF95 radio\n");
radioType = RF95_RADIO;
}
}
#endif
Expand All @@ -832,6 +839,7 @@ void setup()
rIf = NULL;
} else {
LOG_INFO("SX1262 Radio init succeeded, using SX1262 radio\n");
radioType = SX1262_RADIO;
}
}
#endif
Expand All @@ -845,6 +853,7 @@ void setup()
rIf = NULL;
} else {
LOG_INFO("SX1268 Radio init succeeded, using SX1268 radio\n");
radioType = SX1268_RADIO;
}
}
#endif
Expand All @@ -858,6 +867,7 @@ void setup()
rIf = NULL;
} else {
LOG_INFO("LLCC68 Radio init succeeded, using LLCC68 radio\n");
radioType = LLCC68_RADIO;
}
}
#endif
Expand All @@ -871,6 +881,7 @@ void setup()
rIf = NULL;
} else {
LOG_INFO("SX1280 Radio init succeeded, using SX1280 radio\n");
radioType = SX1280_RADIO;
}
}
#endif
Expand Down
61 changes: 47 additions & 14 deletions src/sleep.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "MeshRadio.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "detect/LoRaRadioType.h"
#include "error.h"
#include "main.h"
#include "sleep.h"
Expand Down Expand Up @@ -153,7 +154,7 @@ void initDeepSleep()
// If waking from sleep, release any and all RTC GPIOs
if (wakeCause != ESP_SLEEP_WAKEUP_UNDEFINED) {
LOG_DEBUG("Disabling any holds on RTC IO pads\n");
for (uint8_t i = 0; i <= 45; i++) {
for (uint8_t i = 0; i <= GPIO_NUM_MAX; i++) {
if (rtc_gpio_is_valid_gpio((gpio_num_t)i))
rtc_gpio_hold_dis((gpio_num_t)i);
}
Expand Down Expand Up @@ -360,33 +361,51 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r
#endif
auto res = esp_sleep_enable_gpio_wakeup();
if (res != ESP_OK) {
LOG_DEBUG("esp_sleep_enable_gpio_wakeup result %d\n", res);
LOG_ERROR("esp_sleep_enable_gpio_wakeup result %d\n", res);
}
assert(res == ESP_OK);
res = esp_sleep_enable_timer_wakeup(sleepUsec);
if (res != ESP_OK) {
LOG_DEBUG("esp_sleep_enable_timer_wakeup result %d\n", res);
LOG_ERROR("esp_sleep_enable_timer_wakeup result %d\n", res);
}
assert(res == ESP_OK);

console->flush();
res = esp_light_sleep_start();
if (res != ESP_OK) {
LOG_DEBUG("esp_light_sleep_start result %d\n", res);
LOG_ERROR("esp_light_sleep_start result %d\n", res);
}
assert(res == ESP_OK);
// commented out because it's not that crucial;
// if it sporadically happens the node will go into light sleep during the next round
// assert(res == ESP_OK);

#ifdef BUTTON_PIN
// Disable wake-on-button interrupt. Re-attach normal button-interrupts
gpio_wakeup_disable(pin);
buttonThread->attachButtonInterrupts();
#endif

#if !defined(SOC_PM_SUPPORT_EXT_WAKEUP) && defined(LORA_DIO1) && (LORA_DIO1 != RADIOLIB_NC)
if (radioType != RF95_RADIO) {
gpio_wakeup_disable((gpio_num_t)LORA_DIO1);
}
#endif
#if defined(RF95_IRQ) && (RF95_IRQ != RADIOLIB_NC)
if (radioType == RF95_RADIO) {
gpio_wakeup_disable((gpio_num_t)RF95_IRQ);
}
#endif

esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
#ifdef BUTTON_PIN
if (cause == ESP_SLEEP_WAKEUP_GPIO) {
LOG_INFO("Exit light sleep gpio: btn=%d\n",
!digitalRead(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN));
}
} else
#endif
{
LOG_INFO("Exit light sleep cause: %d\n", cause);
}

return cause;
}
Expand Down Expand Up @@ -428,20 +447,34 @@ bool shouldLoraWake(uint32_t msecToWake)
void enableLoraInterrupt()
{
#if SOC_PM_SUPPORT_EXT_WAKEUP && defined(LORA_DIO1) && (LORA_DIO1 != RADIOLIB_NC)
rtc_gpio_pulldown_en((gpio_num_t)LORA_DIO1);
gpio_pulldown_en((gpio_num_t)LORA_DIO1);
#if defined(LORA_RESET) && (LORA_RESET != RADIOLIB_NC)
rtc_gpio_pullup_en((gpio_num_t)LORA_RESET);
gpio_pullup_en((gpio_num_t)LORA_RESET);
#endif
#if defined(LORA_CS) && (LORA_CS != RADIOLIB_NC)
rtc_gpio_pullup_en((gpio_num_t)LORA_CS);
gpio_pullup_en((gpio_num_t)LORA_CS);
#endif
// Setup deep sleep with wakeup by external source
esp_sleep_enable_ext0_wakeup((gpio_num_t)LORA_DIO1, RISING);

if (rtc_gpio_is_valid_gpio((gpio_num_t)LORA_DIO1)) {
// Setup light/deep sleep with wakeup by external source
LOG_INFO("setup LORA_DIO1 (GPIO%02d) with wakeup by external source\n", LORA_DIO1);
esp_sleep_enable_ext0_wakeup((gpio_num_t)LORA_DIO1, HIGH);
} else {
LOG_INFO("setup LORA_DIO1 (GPIO%02d) with wakeup by gpio interrupt\n", LORA_DIO1);
gpio_wakeup_enable((gpio_num_t)LORA_DIO1, GPIO_INTR_HIGH_LEVEL);
}

#elif defined(LORA_DIO1) && (LORA_DIO1 != RADIOLIB_NC)
gpio_wakeup_enable((gpio_num_t)LORA_DIO1, GPIO_INTR_HIGH_LEVEL); // SX126x/SX128x interrupt, active high
if (radioType != RF95_RADIO) {
LOG_INFO("setup LORA_DIO1 (GPIO%02d) with wakeup by gpio interrupt\n", LORA_DIO1);
gpio_wakeup_enable((gpio_num_t)LORA_DIO1, GPIO_INTR_HIGH_LEVEL); // SX126x/SX128x interrupt, active high
}
#endif
#ifdef RF95_IRQ
gpio_wakeup_enable((gpio_num_t)RF95_IRQ, GPIO_INTR_HIGH_LEVEL); // RF95 interrupt, active high
#if defined(RF95_IRQ) && (RF95_IRQ != RADIOLIB_NC)
if (radioType == RF95_RADIO) {
LOG_INFO("setup RF95_IRQ (GPIO%02d) with wakeup by gpio interrupt\n", RF95_IRQ);
gpio_wakeup_enable((gpio_num_t)RF95_IRQ, GPIO_INTR_HIGH_LEVEL); // RF95 interrupt, active high
}
#endif
}
#endif

0 comments on commit 4c9646f

Please sign in to comment.