/** * @file app_controller.c * @brief 应用控制器实现 — 层级状态机 (HSM) * * 事件路由表: * 当前状态 │ 事件 │ 下一状态 │ 动作 * ──────────────┼───────────────────┼────────────────┼──────────────── * OFF │ SINGLE_CLICK │ ON │ Led_On() * ON │ SINGLE_CLICK │ OFF │ Led_Off() * ON │ DOUBLE_CLICK │ BLINK_SLOW │ Led_SetBlink(1000) * BLINK_SLOW │ DOUBLE_CLICK │ BLINK_FAST │ Led_SetBlink(200) * BLINK_FAST │ DOUBLE_CLICK │ OFF │ Led_Off() * 任意非 BREATH │ LONG_PRESS_START │ BREATHING │ Led_SetBreathing() * BREATHING │ LONG_PRESS_START │ OFF │ Led_Off() */ #include "app_controller.h" #include #include #include /* ======== 内部结构体 ======== */ struct AppCtrl_S { LedDriver_S* led; Btn_FSM* btn; AppState_E state; }; /* ======== 静态内存池 ======== */ static AppCtrl_S g_app_pool[APP_MAX_INSTANCES]; static uint8_t g_app_used[APP_MAX_INSTANCES]; /* ======== 调试日志(PC 模拟时打印) ======== */ #ifdef APP_DEBUG_LOG static void app_log(const char* fmt, ...) { va_list ap; va_start(ap, fmt); vprintf(fmt, ap); va_end(ap); } #else #define app_log(...) ((void)0) #endif /* ======== 状态转换函数 ======== */ static void transition_to(AppCtrl_S* me, AppState_E new_state) { AppState_E old = me->state; /* 退出动作 (exit action) */ switch (old) { case APP_STATE_BLINK_SLOW: case APP_STATE_BLINK_FAST: /* 退出闪烁前无特殊清理 */ break; case APP_STATE_BREATHING: /* 退出呼吸灯前无特殊清理 */ break; default: break; } /* 进入动作 (entry action) */ switch (new_state) { case APP_STATE_OFF: Led_Off(me->led); app_log("[APP] OFF\n"); break; case APP_STATE_ON: Led_On(me->led); app_log("[APP] ON\n"); break; case APP_STATE_BLINK_SLOW: Led_SetBlink(me->led, 1000); /* 1 秒周期 */ app_log("[APP] BLINK_SLOW (1s)\n"); break; case APP_STATE_BLINK_FAST: Led_SetBlink(me->led, 200); /* 0.2 秒周期 */ app_log("[APP] BLINK_FAST (0.2s)\n"); break; case APP_STATE_BREATHING: Led_SetBreathing(me->led); app_log("[APP] BREATHING\n"); break; default: break; } me->state = new_state; } /* ======== 按键事件回调 ======== */ static void on_single_click(Btn_FSM* btn, void* user_data) { AppCtrl_S* me = (AppCtrl_S*)user_data; (void)btn; app_log("[BTN] SINGLE_CLICK in state=%d\n", me->state); switch (me->state) { case APP_STATE_OFF: transition_to(me, APP_STATE_ON); break; case APP_STATE_ON: transition_to(me, APP_STATE_OFF); break; case APP_STATE_BLINK_SLOW: case APP_STATE_BLINK_FAST: transition_to(me, APP_STATE_OFF); break; case APP_STATE_BREATHING: transition_to(me, APP_STATE_OFF); break; default: break; } } static void on_double_click(Btn_FSM* btn, void* user_data) { AppCtrl_S* me = (AppCtrl_S*)user_data; (void)btn; app_log("[BTN] DOUBLE_CLICK in state=%d\n", me->state); switch (me->state) { case APP_STATE_ON: transition_to(me, APP_STATE_BLINK_SLOW); break; case APP_STATE_BLINK_SLOW: transition_to(me, APP_STATE_BLINK_FAST); break; case APP_STATE_BLINK_FAST: transition_to(me, APP_STATE_OFF); break; case APP_STATE_OFF: /* OFF 状态双击 → 直接快闪 */ transition_to(me, APP_STATE_BLINK_FAST); break; case APP_STATE_BREATHING: /* 呼吸灯中双击 → 退出到 OFF */ transition_to(me, APP_STATE_OFF); break; default: break; } } static void on_long_press(Btn_FSM* btn, void* user_data) { AppCtrl_S* me = (AppCtrl_S*)user_data; (void)btn; app_log("[BTN] LONG_PRESS_START in state=%d\n", me->state); switch (me->state) { case APP_STATE_BREATHING: /* 呼吸灯中长按 → 退出到 OFF */ transition_to(me, APP_STATE_OFF); break; default: /* 其他任意状态长按 → 进入呼吸灯 */ transition_to(me, APP_STATE_BREATHING); break; } } /* ======== 公开 API ======== */ AppCtrl_S* AppCtrl_Create(LedDriver_S* led, Btn_FSM* btn) { if (led == (void*)0 || btn == (void*)0) return (void*)0; for (uint8_t i = 0; i < APP_MAX_INSTANCES; i++) { if (g_app_used[i] == 0) { g_app_used[i] = 1; AppCtrl_S* me = &g_app_pool[i]; memset(me, 0, sizeof(AppCtrl_S)); me->led = led; me->btn = btn; me->state = APP_STATE_OFF; return me; } } return (void*)0; } void AppCtrl_Destroy(AppCtrl_S* me) { if (me == (void*)0) return; Led_Off(me->led); for (uint8_t i = 0; i < APP_MAX_INSTANCES; i++) { if (&g_app_pool[i] == me) { g_app_used[i] = 0; break; } } } void AppCtrl_Init(AppCtrl_S* me) { if (me == (void*)0) return; /* 注册按键回调 */ Btn_Attach(me->btn, BTN_EVT_SINGLE_CLICK, on_single_click, me); Btn_Attach(me->btn, BTN_EVT_DOUBLE_CLICK, on_double_click, me); Btn_Attach(me->btn, BTN_EVT_LONG_PRESS_START, on_long_press, me); /* 初始状态 */ Led_Off(me->led); me->state = APP_STATE_OFF; app_log("[APP] Initialized, state=OFF\n"); } void AppCtrl_Poll(AppCtrl_S* me, uint32_t now_ms) { if (me == (void*)0) return; Led_Poll(me->led, now_ms); } AppState_E AppCtrl_GetState(const AppCtrl_S* me) { if (me == (void*)0) return APP_STATE_OFF; return me->state; } const char* AppCtrl_StateName(AppState_E state) { static const char* names[] = { "OFF", "ON", "BLINK_SLOW", "BLINK_FAST", "BREATHING" }; if (state < APP_STATE_COUNT) { return names[state]; } return "UNKNOWN"; }