Ver código fonte

Supported sleep for all ESP32-based repeaters

Kevin Le 5 meses atrás
pai
commit
570ff77569
1 arquivos alterados com 46 adições e 14 exclusões
  1. 46 14
      src/helpers/ESP32Board.h

+ 46 - 14
src/helpers/ESP32Board.h

@@ -12,7 +12,8 @@
 #include <rom/rtc.h>
 #include <sys/time.h>
 #include <Wire.h>
-#include "driver/rtc_io.h"
+#include "soc/rtc.h"
+#include "esp_system.h"
 
 class ESP32Board : public mesh::MainBoard {
 protected:
@@ -60,25 +61,56 @@ public:
     return raw / 4;
   }
 
-  void enterLightSleep(uint32_t secs) {
-#if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(P_LORA_DIO_1) // Supported ESP32 variants
-    if (rtc_gpio_is_valid_gpio((gpio_num_t)P_LORA_DIO_1)) { // Only enter sleep mode if P_LORA_DIO_1 is RTC pin
-      esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
-      esp_sleep_enable_ext1_wakeup((1L << P_LORA_DIO_1), ESP_EXT1_WAKEUP_ANY_HIGH); // To wake up when receiving a LoRa packet
+  uint32_t getIRQGpio() {
+    return P_LORA_DIO_1; // default for SX1262
+  }
+
+  void sleep(uint32_t secs) override {
+    // Skip if not allow to sleep
+    if (inhibit_sleep) {
+      return;
+    }
 
-      if (secs > 0) {
-        esp_sleep_enable_timer_wakeup(secs * 1000000); // To wake up every hour to do periodically jobs
-      }
+    // Use more accurate clock in sleep
+#if SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256
+    if (rtc_clk_slow_src_get() != SOC_RTC_SLOW_CLK_SRC_RC_FAST) {
 
-      esp_light_sleep_start(); // CPU enters light sleep
+      // Switch slow clock source to RC_FAST / 256 (~31.25 kHz)
+      rtc_clk_slow_src_set(SOC_RTC_SLOW_CLK_SRC_RC_FAST);
+
+      // Calibrate slow clock
+      esp_clk_slow_boot_cal(1024);
     }
 #endif
-  }
 
-  void sleep(uint32_t secs) override {
-    if (!inhibit_sleep) {
-      enterLightSleep(secs);      // To wake up after "secs" seconds or when receiving a LoRa packet
+    // Configure GPIO wakeup
+    gpio_num_t wakeupPin = (gpio_num_t)getIRQGpio();
+    esp_sleep_enable_gpio_wakeup();
+    gpio_wakeup_enable((gpio_num_t)wakeupPin, GPIO_INTR_HIGH_LEVEL); // Wake up when receiving a LoRa packet
+
+    // Configure timer wakeup
+    if (secs > 0) {
+      esp_sleep_enable_timer_wakeup(secs * 1000000ULL); // Wake up periodically to do scheduled jobs
+    }
+
+    // Disable CPU interrupt servicing
+    noInterrupts();
+
+    // Skip sleep if there is a LoRa packet
+    if (digitalRead(wakeupPin) == HIGH) {
+      interrupts();
+      return;
     }
+
+    // MCU enters light sleep
+    esp_light_sleep_start();
+
+    // Avoid ISR flood during wakeup due to HIGH LEVEL interrupt
+    gpio_wakeup_disable(wakeupPin);
+    gpio_set_intr_type(wakeupPin, GPIO_INTR_POSEDGE);
+
+    // Enable CPU interrupt servicing
+    interrupts();
   }
 
   uint8_t getStartupReason() const override { return startup_reason; }