diff --git a/main/boards/magiclick-c3-v2/config.json b/main/boards/magiclick-c3-v2/config.json index 2f221b55..f3eeb8f6 100644 --- a/main/boards/magiclick-c3-v2/config.json +++ b/main/boards/magiclick-c3-v2/config.json @@ -3,7 +3,10 @@ "builds": [ { "name": "magiclick-c3-v2", - "sdkconfig_append": [] + "sdkconfig_append": [ + "CONFIG_PM_ENABLE=y", + "CONFIG_FREERTOS_USE_TICKLESS_IDLE=y" + ] } ] } \ No newline at end of file diff --git a/main/boards/magiclick-c3-v2/magiclick_c3_v2_board.cc b/main/boards/magiclick-c3-v2/magiclick_c3_v2_board.cc index b5f68a33..bd7c295a 100644 --- a/main/boards/magiclick-c3-v2/magiclick_c3_v2_board.cc +++ b/main/boards/magiclick-c3-v2/magiclick_c3_v2_board.cc @@ -16,6 +16,8 @@ #include #include "font_awesome_symbols.h" #include +#include +#include #define TAG "magiclick_c3_v2" @@ -98,6 +100,81 @@ private: i2c_master_bus_handle_t codec_i2c_bus_; Button boot_button_; GC9107Display* display_; + esp_timer_handle_t power_save_timer_ = nullptr; + bool sleep_mode_enabled_ = false; + int power_save_ticks_ = 0; + + void InitializePowerSaveTimer() { + esp_timer_create_args_t power_save_timer_args = { + .callback = [](void *arg) { + auto board = static_cast(arg); + board->PowerSaveCheck(); + }, + .arg = this, + .dispatch_method = ESP_TIMER_TASK, + .name = "power_save_timer", + .skip_unhandled_events = false, + }; + ESP_ERROR_CHECK(esp_timer_create(&power_save_timer_args, &power_save_timer_)); + ESP_ERROR_CHECK(esp_timer_start_periodic(power_save_timer_, 1000000)); + } + + void PowerSaveCheck() { + // 如果待机超过一定时间,则进入睡眠模式 + const int seconds_to_sleep = 120; + auto& app = Application::GetInstance(); + if (app.GetDeviceState() != kDeviceStateIdle) { + power_save_ticks_ = 0; + return; + } + + power_save_ticks_++; + if (power_save_ticks_ >= seconds_to_sleep) { + EnableSleepMode(true); + } + } + + void EnableSleepMode(bool enable) { + power_save_ticks_ = 0; + if (!sleep_mode_enabled_ && enable) { + ESP_LOGI(TAG, "Enabling sleep mode"); + auto display = GetDisplay(); + display->SetChatMessage("system", ""); + display->SetEmotion("sleepy"); + // 如果是LCD,还可以调节屏幕亮度 + display->SetBacklight(1); + + auto codec = GetAudioCodec(); + codec->EnableInput(false); + + esp_pm_config_t pm_config = { + .max_freq_mhz = 160, + .min_freq_mhz = 40, + .light_sleep_enable = true, + }; + esp_pm_configure(&pm_config); + sleep_mode_enabled_ = true; + } else if (sleep_mode_enabled_ && !enable) { + esp_pm_config_t pm_config = { + .max_freq_mhz = 160, + .min_freq_mhz = 160, + .light_sleep_enable = false, + }; + esp_pm_configure(&pm_config); + ESP_LOGI(TAG, "Disabling sleep mode"); + + auto codec = GetAudioCodec(); + codec->EnableInput(true); + + auto display = GetDisplay(); + display->SetChatMessage("system", ""); + display->SetEmotion("happy"); + // 如果是LCD,还可以调节屏幕亮度 + display->SetBacklight(50); + + sleep_mode_enabled_ = false; + } + } void InitializeCodecI2c() { // Initialize I2C peripheral @@ -124,6 +201,7 @@ private: } }); boot_button_.OnPressDown([this]() { + EnableSleepMode(false); Application::GetInstance().StartListening(); }); boot_button_.OnPressUp([this]() { @@ -195,6 +273,7 @@ public: InitializeCodecI2c(); InitializeButtons(); + InitializePowerSaveTimer(); InitializeSpi(); InitializeGc9107Display(); InitializeIot(); diff --git a/main/boards/magiclick-c3/config.json b/main/boards/magiclick-c3/config.json index f4dc4f3c..09eb3fdf 100644 --- a/main/boards/magiclick-c3/config.json +++ b/main/boards/magiclick-c3/config.json @@ -3,7 +3,10 @@ "builds": [ { "name": "magiclick-c3", - "sdkconfig_append": [] + "sdkconfig_append": [ + "CONFIG_PM_ENABLE=y", + "CONFIG_FREERTOS_USE_TICKLESS_IDLE=y" + ] } ] } \ No newline at end of file diff --git a/main/boards/magiclick-c3/magiclick_c3_board.cc b/main/boards/magiclick-c3/magiclick_c3_board.cc index a0a6c5cb..e4087f43 100644 --- a/main/boards/magiclick-c3/magiclick_c3_board.cc +++ b/main/boards/magiclick-c3/magiclick_c3_board.cc @@ -14,7 +14,8 @@ #include "esp_lcd_nv3023.h" #include "font_awesome_symbols.h" #include - +#include +#include #define TAG "magiclick_c3" LV_FONT_DECLARE(font_puhui_16_4); @@ -62,6 +63,81 @@ private: i2c_master_bus_handle_t codec_i2c_bus_; Button boot_button_; NV3023Display* display_; + esp_timer_handle_t power_save_timer_ = nullptr; + bool sleep_mode_enabled_ = false; + int power_save_ticks_ = 0; + + void InitializePowerSaveTimer() { + esp_timer_create_args_t power_save_timer_args = { + .callback = [](void *arg) { + auto board = static_cast(arg); + board->PowerSaveCheck(); + }, + .arg = this, + .dispatch_method = ESP_TIMER_TASK, + .name = "power_save_timer", + .skip_unhandled_events = false, + }; + ESP_ERROR_CHECK(esp_timer_create(&power_save_timer_args, &power_save_timer_)); + ESP_ERROR_CHECK(esp_timer_start_periodic(power_save_timer_, 1000000)); + } + + void PowerSaveCheck() { + // 如果待机超过一定时间,则进入睡眠模式 + const int seconds_to_sleep = 120; + auto& app = Application::GetInstance(); + if (app.GetDeviceState() != kDeviceStateIdle) { + power_save_ticks_ = 0; + return; + } + + power_save_ticks_++; + if (power_save_ticks_ >= seconds_to_sleep) { + EnableSleepMode(true); + } + } + + void EnableSleepMode(bool enable) { + power_save_ticks_ = 0; + if (!sleep_mode_enabled_ && enable) { + ESP_LOGI(TAG, "Enabling sleep mode"); + auto display = GetDisplay(); + display->SetChatMessage("system", ""); + display->SetEmotion("sleepy"); + // 如果是LCD,还可以调节屏幕亮度 + display->SetBacklight(1); + + auto codec = GetAudioCodec(); + codec->EnableInput(false); + + esp_pm_config_t pm_config = { + .max_freq_mhz = 160, + .min_freq_mhz = 40, + .light_sleep_enable = true, + }; + esp_pm_configure(&pm_config); + sleep_mode_enabled_ = true; + } else if (sleep_mode_enabled_ && !enable) { + esp_pm_config_t pm_config = { + .max_freq_mhz = 160, + .min_freq_mhz = 160, + .light_sleep_enable = false, + }; + esp_pm_configure(&pm_config); + ESP_LOGI(TAG, "Disabling sleep mode"); + + auto codec = GetAudioCodec(); + codec->EnableInput(true); + + auto display = GetDisplay(); + display->SetChatMessage("system", ""); + display->SetEmotion("happy"); + // 如果是LCD,还可以调节屏幕亮度 + display->SetBacklight(50); + + sleep_mode_enabled_ = false; + } + } void InitializeCodecI2c() { // Initialize I2C peripheral @@ -88,6 +164,7 @@ private: } }); boot_button_.OnPressDown([this]() { + EnableSleepMode(false); Application::GetInstance().StartListening(); }); boot_button_.OnPressUp([this]() { @@ -153,6 +230,7 @@ public: InitializeCodecI2c(); InitializeButtons(); + InitializePowerSaveTimer(); InitializeSpi(); InitializeNv3023Display(); InitializeIot();