/*****************************************************include files **************************************************************************/ #include "screen_brightness.h" #include "LVGL/lvgl_init.h" #include "ui.h" /******************************************************* variable declaration ************************************************************************/ /* * 亮度模型:UI/BLE 的 0~100% 线性映射到面板 PWM [BRIGHTNESS_PWM_MIN, BRIGHTNESS_PWM_MAX]。 * 选 55 作为下限:约 21.5% 全量程,且 (255-55)=200,duty = 55 + percent*2,0~100 与整数 PWM 一一对应、无除法舍入误差。 * 若硬件需其它暗场门限,只改 BRIGHTNESS_PWM_MIN(需保持 SPAN 与映射公式一致或同步改除法)。 */ #define BRIGHTNESS_PWM_MIN 55 #define BRIGHTNESS_PWM_MAX 255 #define BRIGHTNESS_PWM_SPAN (BRIGHTNESS_PWM_MAX - BRIGHTNESS_PWM_MIN) // 当前面板 PWM(BRIGHTNESS_PWM_MIN~BRIGHTNESS_PWM_MAX);未读 NVS 前取中间偏亮,避免明显过暗 uint8_t g_current_brightness = (uint8_t)(BRIGHTNESS_PWM_MIN + BRIGHTNESS_PWM_SPAN * 3 / 4); static bool g_brightness_dirty = false; static uint8_t g_brightness_commit_pending = 0; static TimerHandle_t g_brightness_commit_timer = NULL; /******************************************************* functions declaration ************************************************************************/ void save_brightness_to_nvs(uint8_t value); /* forward declaration for timer callback */ void commit_brightness_if_dirty(void); extern esp_err_t panel_qspi_amoled_set_brightness(esp_lcd_panel_handle_t panel, uint8_t brightness); /******************************************************* functions definition ************************************************************************/ // 保存亮度到 NVS void save_brightness_to_nvs(uint8_t value) { nvs_handle_t my_handle; esp_err_t err = nvs_open("system_cfg", NVS_READWRITE, &my_handle); if (err == ESP_OK) { nvs_set_u8(my_handle, "brightness", value); nvs_commit(my_handle); nvs_close(my_handle); // ESP_LOGI("NVS", "亮度已保存: %d", value); } } static void brightness_commit_timer_cb(TimerHandle_t xTimer) { (void)xTimer; save_brightness_to_nvs(g_brightness_commit_pending); } // 从 NVS 读取亮度 void load_brightness_from_nvs(void) { nvs_handle_t my_handle; esp_err_t err = nvs_open("system_cfg", NVS_READONLY, &my_handle); if (err == ESP_OK) { uint8_t saved_val = 0; if (nvs_get_u8(my_handle, "brightness", &saved_val) == ESP_OK) { g_current_brightness = saved_val; if (g_current_brightness < BRIGHTNESS_PWM_MIN) g_current_brightness = BRIGHTNESS_PWM_MIN; if (g_current_brightness > BRIGHTNESS_PWM_MAX) g_current_brightness = BRIGHTNESS_PWM_MAX; ESP_LOGI("NVS", "加载保存的亮度: %d", g_current_brightness); } nvs_close(my_handle); } } // ================= 对外接口 ================= // 设置亮度 (供 UI 和 BLE 调用) // 参数 percent: 0-100,0 对应 PWM_MIN、100 对应 PWM_MAX void set_system_brightness(int percent) { if (percent < 0) percent = 0; if (percent > 100) percent = 100; uint8_t duty = (uint8_t)(BRIGHTNESS_PWM_MIN + ((unsigned)percent * BRIGHTNESS_PWM_SPAN) / 100U); // 3. 应用到硬件 if (panel_handle) { panel_qspi_amoled_set_brightness(panel_handle, duty); } // 4. 更新全局变量并保存 if (g_current_brightness != duty) { g_current_brightness = duty; g_brightness_dirty = true; request_brightness_slider_sync(); } /* BLE/UI 共用:有变更时经定时器落盘 NVS(避免在回调里同步写) */ commit_brightness_if_dirty(); } /* 退出亮度界面时调用:只写一次 NVS,避免频繁保存导致不稳定 */ void commit_brightness_if_dirty(void) { if (!g_brightness_dirty) return; g_brightness_commit_pending = g_current_brightness; g_brightness_dirty = false; /* NVS 写放到 timer 任务上下文,避免在 LVGL 点击事件回调里同步写导致崩溃 */ if (g_brightness_commit_timer == NULL) { g_brightness_commit_timer = xTimerCreate("brightness_commit_tmr", pdMS_TO_TICKS(50), pdFALSE, NULL, brightness_commit_timer_cb); } if (g_brightness_commit_timer) { xTimerStop(g_brightness_commit_timer, 0); if (xTimerStart(g_brightness_commit_timer, 0) != pdPASS) { /* 定时器队列满等异常时仍落盘,避免已清 dirty 却永不写入 NVS */ save_brightness_to_nvs(g_brightness_commit_pending); } } else { /* xTimerCreate 失败(如堆不足)时直接写 NVS,否则与蓝牙路径行为不一致 */ save_brightness_to_nvs(g_brightness_commit_pending); } } // 获取当前亮度百分比 (供 UI 初始化滑块与 BLE 查询,0~100) int get_system_brightness_percent(void) { unsigned d = g_current_brightness; if (d <= BRIGHTNESS_PWM_MIN) return 0; if (d >= BRIGHTNESS_PWM_MAX) return 100; return (int)((d - BRIGHTNESS_PWM_MIN) * 100U / BRIGHTNESS_PWM_SPAN); } // 【核心函数 2】设置是否阻止休眠 (例如 OTA 时调用 set_block_sleep(true)) void set_block_auto_sleep(bool block) { block_auto_sleep = block; if (block) { system_keep_alive(); // 阻止时顺便刷新一下时间 } } /* 亮度滑动条同步:将设置页滑动条与当前系统亮度对齐 */ void request_brightness_slider_sync(void) { extern lv_ui guider_ui; extern int get_system_brightness_percent(void); int percent = get_system_brightness_percent(); if (guider_ui.screen_set_slider_light != NULL && lv_obj_is_valid(guider_ui.screen_set_slider_light)) { lv_slider_set_value(guider_ui.screen_set_slider_light, percent, LV_ANIM_OFF); } }