Files
JBao_Magic_Box_FW/apps/usr_app/app_led.c
T
2026-08-25 14:59:39 +08:00

216 lines
6.0 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/******************************************************************************
* @file app_led.c
* @brief CBC2 灯效适配:充电红与待机绿可同时亮,不再 if-else 互斥
* @author cyWu <1917507415@qq.com>
* @date 2026.08.25
* @version V2.0.0
* @history
* - V1.0.0, 2026.08.21, cyWu, 首次发布
* - V1.1.0, 2026.08.25, cyWu, 开机绿灯只提示几秒
* - V2.0.0, 2026.08.25, cyWu, 改用充电板 LED 事件表,红绿通道独立
* - V2.1.0, 2026.08.25, cyWu, 自己从 app_power/app_pair 取数并内部组装
* - V2.2.0, 2026.08.25, cyWu, 重启/清场逻辑各提一个小函数,把意图写进注释
******************************************************************************/
#include "app_led.h"
#include "led_manager.h"
#include "bsp_hw.h"
#include "board_pin.h"
#include "app_power.h"
#include "app_pair.h"
static uint8_t s_initialized;
static void led_start_pair_result(uint8_t ok);
/**
* @brief 重新播放一次「一次性/限时」灯效,让它从第 0 帧重新开始
* @note led.c 的 LED_EventAdd 只有在“该优先级槽位当前不是这个事件”时才会把
* currentTime 重置为现在;如果动画正播到一半直接再 Add 一次,事件已经
* 占着槽位,不会重置,会接着上次的进度走。所以要先 Delete 清空槽位,
* 再 Add 才能强制重新计时——这不是多余代码,是“重启”这个事件的手段。
* @param evt 要重启的事件(切模式闪、开机绿灯提示、配对结果)
* @return 无
*/
static void led_restart(LED_Event_t evt)
{
LED_EventDelete(evt);
LED_EventAdd(evt);
}
/**
* @brief 绿灯正被切模式/配对结果占用(不含配对快闪本身)
* @return 1=绿灯忙
*/
static uint8_t green_pattern_busy(void)
{
return (uint8_t)(LED_IsEventExist(LED_EVENT_MODE)
|| LED_IsEventExist(LED_EVENT_PAIR_OK)
|| LED_IsEventExist(LED_EVENT_PAIR_FAIL));
}
/**
* @brief 绿灯正被配对/切模式/结果占用时,不要再挂待机绿
* @return 1=绿灯忙
*/
static uint8_t green_busy(void)
{
return (uint8_t)(LED_IsEventExist(LED_EVENT_PAIRING) || green_pattern_busy());
}
/**
* @brief 灯效初始化
* @return APP_LED_OK=成功
*/
AppLed_Ret_t app_led_init(void)
{
if (s_initialized) {
return APP_LED_OK;
}
user_led_init();
s_initialized = 1;
return APP_LED_OK;
}
/**
* @brief 查询模块是否已初始化
* @return APP_LED_OK=已初始化,APP_LED_ERR_NOT_INIT=未初始化
*/
AppLed_Ret_t app_led_get_status(void)
{
return s_initialized ? APP_LED_OK : APP_LED_ERR_NOT_INIT;
}
/**
* @brief 请求切模式绿灯闪两下(与配对灯同优先级,会盖住配对闪)
* @return 无
*/
void app_led_request_mode_blink(void)
{
if (!s_initialized) {
return;
}
led_restart(LED_EVENT_MODE);
}
/**
* @brief 重新挂待机绿灯(常亮或提示几秒,看 BOARD_LED_STANDBY_ON
* @return 无
*/
void app_led_hint_power_on(void)
{
if (!s_initialized) {
return;
}
led_restart(LED_EVENT_STANDBY);
}
/**
* @brief 播放一次性配对结果灯
* @param ok 1=成功常绿,0=失败红绿交替
* @return 无
*/
static void led_start_pair_result(uint8_t ok)
{
LED_EventDelete(LED_EVENT_PAIRING);
led_restart(ok ? LED_EVENT_PAIR_OK : LED_EVENT_PAIR_FAIL);
}
/**
* @brief 功能关闭(DP0=0)时清掉所有“功能相关”的灯事件
* @note 故意不用 LED_EventAllDelete():那会把优先级表全清空,连充电红/满灯
* LED_EVENT_CHARGE / LED_EVENT_CHARGE_FULL)也会跟着灭掉。但充电状态
* 和 DP0 开关是两码事——设备功能关着也可能正在充电,充电灯必须继续亮,
* 所以这里只挑功能相关的几个事件逐个删,充电事件不动它。
* @return 无
*/
static void led_clear_function_events(void)
{
LED_EventDelete(LED_EVENT_STANDBY);
LED_EventDelete(LED_EVENT_PAIRING);
LED_EventDelete(LED_EVENT_MODE);
LED_EventDelete(LED_EVENT_PAIR_OK);
LED_EventDelete(LED_EVENT_PAIR_FAIL);
LED_EventDelete(LED_EVENT_LOWBAT);
}
/**
* @brief 按优先级刷新灯:充电/低电从 app_power 取,配对从 app_pair 取,
* 只有“功能是否开”这一项由调用方传入
* @param dt 距上次调用的毫秒数
* @param app_power 1=功能开(DP0),0=功能关,功能灯全灭
* @return 无
*/
void app_led_run(uint16_t dt, uint8_t app_power)
{
uint8_t charge_led;
uint8_t low_bat;
uint8_t pairing;
uint8_t func_on;
AppPairEvt_t pair_evt;
if (!s_initialized) {
return;
}
pair_evt = app_pair_tick_1ms(dt);
if (pair_evt == APP_PAIR_EVT_OK) {
led_start_pair_result(1);
} else if (pair_evt == APP_PAIR_EVT_FAIL) {
led_start_pair_result(0);
}
charge_led = app_power_charge_led();
low_bat = app_power_low_bat();
func_on = app_power ? 1 : 0;
pairing = (uint8_t)(app_pair_is_active() && func_on);
if (charge_led == 1) {
LED_EventAdd(LED_EVENT_CHARGE);
} else {
LED_EventDelete(LED_EVENT_CHARGE);
}
if (charge_led == 2) {
LED_EventAdd(LED_EVENT_CHARGE_FULL);
} else {
LED_EventDelete(LED_EVENT_CHARGE_FULL);
}
if (pairing && !green_pattern_busy()) {
LED_EventAdd(LED_EVENT_PAIRING);
} else if (!pairing) {
LED_EventDelete(LED_EVENT_PAIRING);
}
if (func_on && low_bat && (charge_led == 0)) {
LED_EventAdd(LED_EVENT_LOWBAT);
} else {
LED_EventDelete(LED_EVENT_LOWBAT);
}
if (!func_on) {
led_clear_function_events();
} else {
#if BOARD_LED_STANDBY_ON
if ((charge_led != 2) && !pairing && !green_busy()) {
LED_EventAdd(LED_EVENT_STANDBY);
} else {
LED_EventDelete(LED_EVENT_STANDBY);
}
#endif
}
user_led_handle();
}
/**
* @brief 清空全部灯事件并灭灯
* @return 无
*/
void app_led_clear(void)
{
LED_EventAllDelete();
bsp_led_all_off();
}