2026-07-17 09:08:53 +08:00
|
|
|
|
#include "app_manager.h"
|
|
|
|
|
|
#include "xtell.h"
|
|
|
|
|
|
#include "ui.h"
|
|
|
|
|
|
#include "rgb.h"
|
|
|
|
|
|
#include "event.h"
|
|
|
|
|
|
#include "system.h"
|
2026-07-31 13:57:06 +08:00
|
|
|
|
#include "database.h"
|
|
|
|
|
|
#include "language.h"
|
2026-07-31 18:11:55 +08:00
|
|
|
|
#include "clock.h"
|
2026-07-17 09:08:53 +08:00
|
|
|
|
#include "../Drivers/rf.h"
|
|
|
|
|
|
|
|
|
|
|
|
// 外部全局变量引用
|
|
|
|
|
|
extern SystemState current_state;
|
|
|
|
|
|
extern u8 menu_select;
|
|
|
|
|
|
|
2026-07-31 18:11:55 +08:00
|
|
|
|
// 菜单闲置自动关闭超时 (秒):无任何按键操作达到这个时长,自动退出菜单返回时钟主页
|
|
|
|
|
|
#define MENU_IDLE_TIMEOUT_SEC 10
|
|
|
|
|
|
|
|
|
|
|
|
// 本应用私有变量:记录最近一次按键活动时的秒计时快照
|
|
|
|
|
|
static u8 menu_idle_start_sec = 0;
|
|
|
|
|
|
|
2026-07-17 09:08:53 +08:00
|
|
|
|
// 声明本应用的生命周期回调函数
|
|
|
|
|
|
static void MenuApp_OnStart(void);
|
2026-07-31 18:11:55 +08:00
|
|
|
|
static void MenuApp_onRun(void);
|
2026-07-17 09:08:53 +08:00
|
|
|
|
static void MenuApp_onClose(void);
|
|
|
|
|
|
static EventResult MenuApp_onEvent(SystemEvent *evt);
|
|
|
|
|
|
|
2026-07-31 18:05:23 +08:00
|
|
|
|
// 实体化定义菜单应用控制块 (顶层 4 项列表:语言切换/时间设置/传感器配对/摄像头绑定)
|
2026-07-17 09:08:53 +08:00
|
|
|
|
WristbandApp menu_app = {
|
|
|
|
|
|
APP_ID_MENU,
|
|
|
|
|
|
"Menu",
|
|
|
|
|
|
MenuApp_OnStart,
|
2026-07-31 18:11:55 +08:00
|
|
|
|
MenuApp_onRun,
|
2026-07-17 09:08:53 +08:00
|
|
|
|
MenuApp_onClose,
|
|
|
|
|
|
MenuApp_onEvent
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief MenuApp 启动回调
|
|
|
|
|
|
*/
|
|
|
|
|
|
static void MenuApp_OnStart(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
menu_select = 0;
|
2026-07-31 18:11:55 +08:00
|
|
|
|
menu_idle_start_sec = current_sec;
|
2026-07-17 09:08:53 +08:00
|
|
|
|
current_state = STATE_PAIR_MENU; // 系统运行状态设为对码配置菜单
|
|
|
|
|
|
RF_SetMode(0); // 关闭射频接收芯片,防止接收杂波干扰屏幕绘制
|
2026-07-31 18:05:23 +08:00
|
|
|
|
UI_ShowMainMenu(menu_select); // 绘制主菜单
|
2026-07-17 09:08:53 +08:00
|
|
|
|
RGB_Send(0, 0, 0, 0, 0, 0); // 熄灭所有灯条
|
|
|
|
|
|
XTELL_LOG("[MenuApp] Started\r\n");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-31 18:11:55 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief MenuApp 轮询主回调:检测闲置超时,无操作达到 MENU_IDLE_TIMEOUT_SEC 秒自动退出
|
|
|
|
|
|
*/
|
|
|
|
|
|
static void MenuApp_onRun(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
u8 elapsed = (current_sec >= menu_idle_start_sec)
|
|
|
|
|
|
? (current_sec - menu_idle_start_sec)
|
|
|
|
|
|
: (60 + current_sec - menu_idle_start_sec);
|
|
|
|
|
|
if (elapsed >= MENU_IDLE_TIMEOUT_SEC) {
|
|
|
|
|
|
XTELL_LOG("[MenuApp] Idle timeout, closing.\r\n");
|
|
|
|
|
|
AppManager_SwitchToForeground(&home_app);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-17 09:08:53 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief MenuApp 退出清理回调
|
|
|
|
|
|
*/
|
|
|
|
|
|
static void MenuApp_onClose(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
RGB_Send(0, 0, 0, 0, 0, 0); // 熄灭 RGB
|
|
|
|
|
|
RF_SetMode(1); // 重新开启无线接收模式
|
|
|
|
|
|
XTELL_LOG("[MenuApp] Closed\r\n");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-07-31 18:05:23 +08:00
|
|
|
|
* @brief MenuApp 接收按键与控制事件回调 (0-语言切换, 1-HORLOGE, 2-APPAIRAGE, 3-LIAISON)
|
2026-07-17 09:08:53 +08:00
|
|
|
|
*/
|
|
|
|
|
|
static EventResult MenuApp_onEvent(SystemEvent *evt)
|
|
|
|
|
|
{
|
2026-07-31 18:11:55 +08:00
|
|
|
|
menu_idle_start_sec = current_sec; // 任意按键活动都刷新闲置计时起点
|
|
|
|
|
|
|
2026-07-31 18:05:23 +08:00
|
|
|
|
if (evt->key_event == KEY_EVENT_UP_CLICK) {
|
|
|
|
|
|
// 短按 ▲ 键向上移动焦点,允许循环切换 (到顶绕到底)
|
|
|
|
|
|
menu_select = (menu_select == 0) ? 3 : (menu_select - 1);
|
|
|
|
|
|
UI_ShowMainMenu(menu_select);
|
|
|
|
|
|
return EVENT_HANDLED;
|
2026-07-17 09:08:53 +08:00
|
|
|
|
}
|
2026-07-31 18:05:23 +08:00
|
|
|
|
if (evt->key_event == KEY_EVENT_DOWN_CLICK) {
|
|
|
|
|
|
// 短按 ▼ 键向下移动焦点,允许循环切换 (到底绕到顶)
|
|
|
|
|
|
menu_select = (menu_select == 3) ? 0 : (menu_select + 1);
|
|
|
|
|
|
UI_ShowMainMenu(menu_select);
|
|
|
|
|
|
return EVENT_HANDLED;
|
2026-07-17 09:08:53 +08:00
|
|
|
|
}
|
2026-07-31 18:05:23 +08:00
|
|
|
|
if (evt->key_event == KEY_EVENT_CONFIRM_CLICK) {
|
|
|
|
|
|
// 短按 ■ 确认键,进入选定功能的子页面
|
|
|
|
|
|
if (menu_select == 0) {
|
|
|
|
|
|
// 功能 0:语言切换。原地在 FR/EN 间切换,立即保存并用新语言重绘当前菜单
|
|
|
|
|
|
Language new_lang = (Lang_Current() == LANG_FR) ? LANG_EN : LANG_FR;
|
|
|
|
|
|
Lang_Set(new_lang);
|
|
|
|
|
|
Save_Database(); // 语言字节与传感器数据库共用同一扇区持久化
|
|
|
|
|
|
MOTOR = 1; Delay_ms(50); MOTOR = 0; // 短震反馈,与其它确认操作风格一致
|
2026-07-17 09:08:53 +08:00
|
|
|
|
UI_ShowMainMenu(menu_select);
|
2026-07-31 18:05:23 +08:00
|
|
|
|
} else if (menu_select == 1) {
|
|
|
|
|
|
// 功能 1:设置时间。切换到独立的时间设置子 App
|
|
|
|
|
|
AppManager_SwitchToForeground(&set_clock_app);
|
|
|
|
|
|
} else if (menu_select == 2) {
|
|
|
|
|
|
// 功能 2:传感器学习。切换到独立的对码子 App (类型选择是它的第一个状态)
|
|
|
|
|
|
AppManager_SwitchToForeground(&pair_app);
|
|
|
|
|
|
} else if (menu_select == 3) {
|
|
|
|
|
|
// 功能 3:相机配对。切换到独立的摄像头绑定子 App
|
|
|
|
|
|
AppManager_SwitchToForeground(&ipc_bind_app);
|
2026-07-17 09:08:53 +08:00
|
|
|
|
}
|
2026-07-31 18:05:23 +08:00
|
|
|
|
return EVENT_HANDLED;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (evt->key_event == KEY_EVENT_CONFIRM_LONG) {
|
|
|
|
|
|
// 长按 ■ 确认键,退出设置菜单直接返回待机主页
|
|
|
|
|
|
AppManager_SwitchToForeground(&home_app);
|
|
|
|
|
|
return EVENT_HANDLED;
|
2026-07-17 09:08:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
return EVENT_IGNORED;
|
|
|
|
|
|
}
|