Type-C 长供电、上电即工作、无软关机,删除 app_boot/app_power 及 DP0 开关相关逻辑, 去掉空占位 app_fan_run 和无效的 usr_timer_pick_mode/rearm(数码管 4ms 扫描已 priority=1, 系统本来就不会进低功耗)。按键 5s 配对 / 12s OTA 改走 key.c 长按分级,去掉自计时与 1~5s 死区。 新增 app_defer,NVM/配对/OTA 只在 ISR 置位、在 500ms 任务上下文落地,避免再在 usr_timer 里写 flash。 规格书与注释同步精简。
175 lines
5.3 KiB
C
175 lines
5.3 KiB
C
/******************************************************************************
|
|
* @file app_mode.c
|
|
* @brief CBR3 工作模式实现(P1):通风 25/5 循环、强力 15min 一轮
|
|
* @author cyWu <1917507415@qq.com>
|
|
* @date 2026.08.31
|
|
* @version V1.1.0,实现状态机(规格书第 9 章):通风 25/5、强力 15min 后停、
|
|
* 手动档快照、退出语义、开机从周期头
|
|
*
|
|
* @note 模式激活时强制覆盖风扇档位(通风=1 档、强力=3 档、通风停段=0),
|
|
* DP2 由 app_fan_get_gear 上报真实档位(app_function_poll 同步)。
|
|
* 退出方式(规格书 9 章):短按切档(app_mode_stop)、APP 写档位、
|
|
* APP 写 mode=0(恢复进入模式前的手动档快照)、强力自然到点(风扇 0)。
|
|
* 开机恢复不存相位:从 25min 开段 / 15min 从头计。
|
|
******************************************************************************/
|
|
|
|
#include "app_mode.h"
|
|
#include "app_fan.h"
|
|
#include "app_nvm.h"
|
|
#include "board_pin.h"
|
|
|
|
#define LOG_TAG_CONST APP
|
|
#define LOG_TAG "[APP_MODE]"
|
|
#define LOG_INFO_ENABLE
|
|
#include "debug.h"
|
|
|
|
/** 通风循环段 */
|
|
typedef enum {
|
|
MODE_VENT_ON = 0, /**< 开段 25min,强制 1 档 */
|
|
MODE_VENT_OFF /**< 停段 5min,风扇 0 */
|
|
} ModeVentPhase_t;
|
|
|
|
/** 模式状态机上下文 */
|
|
typedef struct {
|
|
uint8_t mode; /**< 0=关闭 1=通风 2=强力 */
|
|
uint8_t phase; /**< 通风段;其它模式恒 0 */
|
|
uint32_t run_ms; /**< 当前段已运行毫秒 */
|
|
uint8_t saved_gear;/**< 进入模式前的手动档快照(APP 写 mode=0 时恢复) */
|
|
} AppModeCtx_t;
|
|
|
|
static AppModeCtx_t s_mode;
|
|
|
|
/**
|
|
* @brief 初始化模式状态机
|
|
* @return 无
|
|
*/
|
|
void app_mode_init(void)
|
|
{
|
|
#if !BOARD_MODE_ENABLE
|
|
log_info("mode disabled\n");
|
|
return;
|
|
#endif
|
|
s_mode.mode = 0;
|
|
s_mode.phase = 0;
|
|
s_mode.run_ms = 0;
|
|
s_mode.saved_gear = 0;
|
|
log_info("mode init\n");
|
|
}
|
|
|
|
/**
|
|
* @brief 推进模式状态机(每个业务 tick 调用)
|
|
* @param dt 距上次调用的毫秒数
|
|
* @return 无
|
|
*/
|
|
void app_mode_run(uint16_t dt)
|
|
{
|
|
#if !BOARD_MODE_ENABLE
|
|
(void)dt;
|
|
return;
|
|
#endif
|
|
switch (s_mode.mode) {
|
|
case 1: /* 通风:开 25min 强制 1 档,停 5min 风扇 0,循环 */
|
|
if (s_mode.phase == MODE_VENT_ON) {
|
|
app_fan_set_gear(1);
|
|
s_mode.run_ms += dt;
|
|
if (s_mode.run_ms >= BOARD_MODE_VENT_ON_MS) {
|
|
s_mode.phase = MODE_VENT_OFF;
|
|
s_mode.run_ms = 0;
|
|
app_fan_set_gear(0);
|
|
app_nvm_mark_dirty();
|
|
log_info("vent on 25min over, off 5min\n");
|
|
}
|
|
} else {
|
|
s_mode.run_ms += dt;
|
|
if (s_mode.run_ms >= BOARD_MODE_VENT_OFF_MS) {
|
|
s_mode.phase = MODE_VENT_ON;
|
|
s_mode.run_ms = 0;
|
|
app_fan_set_gear(1);
|
|
app_nvm_mark_dirty();
|
|
log_info("vent off 5min over, on 25min\n");
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 2: /* 强力:强制 3 档,15min 到点风扇 0、mode 回 0 */
|
|
app_fan_set_gear(3);
|
|
s_mode.run_ms += dt;
|
|
if (s_mode.run_ms >= BOARD_MODE_POWER_ON_MS) {
|
|
log_info("power 15min over, mode=0 fan=0\n");
|
|
s_mode.mode = 0;
|
|
s_mode.phase = 0;
|
|
s_mode.run_ms = 0;
|
|
app_fan_set_gear(0);
|
|
app_nvm_mark_dirty();
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief APP 写 DP1 / 手动抢权 / 开机恢复:切到指定模式或退出
|
|
* @param mode 0=关闭模式(恢复手动档快照),1=通风,2=强力
|
|
* @note 模式 1/2 进入时快照当前实际档(即进入前的手动档),并立即强制档位;
|
|
* mode=0 时若原在模式中则恢复快照档。短按退出走 app_mode_stop()
|
|
* (不恢复快照,档位由短按逻辑立刻切到循环下一档)。
|
|
* @return 无
|
|
*/
|
|
void app_mode_set_manual(uint8_t mode)
|
|
{
|
|
#if !BOARD_MODE_ENABLE
|
|
(void)mode;
|
|
return;
|
|
#endif
|
|
if (mode > 2) {
|
|
mode = 0;
|
|
}
|
|
if (mode != 0) {
|
|
s_mode.saved_gear = app_fan_get_gear(); /* 快照进入前的手动档 */
|
|
s_mode.mode = mode;
|
|
s_mode.phase = MODE_VENT_ON;
|
|
s_mode.run_ms = 0; /* 不存相位:开机/手动切入都从周期头计 */
|
|
app_fan_set_gear((mode == 1) ? 1 : 3);
|
|
log_info("mode set %d, gear=%d\n", mode, app_fan_get_gear());
|
|
} else {
|
|
if (s_mode.mode != 0) {
|
|
/* 只在实际退出模式时恢复快照档,避免 load(0) 把恢复档清零 */
|
|
app_fan_set_gear(s_mode.saved_gear);
|
|
log_info("mode exit, restore gear=%d\n", s_mode.saved_gear);
|
|
}
|
|
s_mode.mode = 0;
|
|
s_mode.phase = 0;
|
|
s_mode.run_ms = 0;
|
|
}
|
|
app_nvm_mark_dirty();
|
|
}
|
|
|
|
/**
|
|
* @brief 查询当前逻辑模式
|
|
* @return 0/1/2
|
|
*/
|
|
uint8_t app_mode_get_active(void)
|
|
{
|
|
return s_mode.mode;
|
|
}
|
|
|
|
/**
|
|
* @brief 停止当前模式(短按退模式用:只清模式状态,不动风扇档位,
|
|
* 由调用方立刻切到循环下一档;关机流程则另行停风扇)
|
|
* @return 无
|
|
*/
|
|
void app_mode_stop(void)
|
|
{
|
|
#if !BOARD_MODE_ENABLE
|
|
return;
|
|
#endif
|
|
if (s_mode.mode != 0) {
|
|
app_nvm_mark_dirty();
|
|
}
|
|
s_mode.mode = 0;
|
|
s_mode.phase = 0;
|
|
s_mode.run_ms = 0;
|
|
}
|