2026-07-17 09:08:53 +08:00
|
|
|
|
#include "app_manager.h"
|
|
|
|
|
|
#include "clock.h"
|
|
|
|
|
|
#include "xtell.h"
|
|
|
|
|
|
#include "ui.h"
|
|
|
|
|
|
#include "rgb.h"
|
|
|
|
|
|
#include "event.h"
|
|
|
|
|
|
#include "system.h"
|
|
|
|
|
|
#include "../Drivers/rf.h"
|
|
|
|
|
|
#include "../Drivers/lcd.h"
|
2026-07-28 18:03:20 +08:00
|
|
|
|
#include "../Drivers/pcf8563.h"
|
2026-07-17 09:08:53 +08:00
|
|
|
|
|
|
|
|
|
|
// 外部引用的全局系统状态变量
|
|
|
|
|
|
extern SystemState current_state;
|
|
|
|
|
|
extern volatile u16 ms_tick;
|
|
|
|
|
|
|
|
|
|
|
|
// 待机时钟应用内特有的编辑时间私有变量
|
|
|
|
|
|
static u8 time_edit_active = 0; // 标识当前是否正在编辑修改时间中 (1:是, 0:否)
|
|
|
|
|
|
static u8 time_edit_field = 1; // 标识当前聚焦在哪一个参数上进行微调 (1:修改小时, 2:修改分钟)
|
|
|
|
|
|
static u8 time_edit_blink_on = 1; // 时钟修改时光标闪烁周期状态位
|
|
|
|
|
|
|
|
|
|
|
|
// 声明本应用的生命周期回调函数
|
|
|
|
|
|
static void ClockApp_OnStart(void);
|
|
|
|
|
|
static void ClockApp_onRun(void);
|
|
|
|
|
|
static void ClockApp_onClose(void);
|
|
|
|
|
|
static EventResult ClockApp_onEvent(SystemEvent *evt);
|
|
|
|
|
|
|
|
|
|
|
|
// 实体化定义待机时钟应用控制块
|
|
|
|
|
|
WristbandApp clock_app = {
|
|
|
|
|
|
APP_ID_CLOCK,
|
|
|
|
|
|
"Clock",
|
|
|
|
|
|
ClockApp_OnStart,
|
|
|
|
|
|
ClockApp_onRun,
|
|
|
|
|
|
ClockApp_onClose,
|
|
|
|
|
|
ClockApp_onEvent
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 触发启动时间设置状态机,准备修改时钟
|
|
|
|
|
|
*/
|
|
|
|
|
|
void Start_Time_Edit(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
time_edit_active = 1;
|
|
|
|
|
|
time_edit_field = 1;
|
|
|
|
|
|
time_edit_blink_on = 1;
|
|
|
|
|
|
current_state = STATE_SET_TIME; // 系统切入时间设置状态
|
|
|
|
|
|
|
|
|
|
|
|
// FCOB 幻彩灯条双灯珠均显示蓝色常亮 (R=0, G=0, B=180),进行模式视觉区分
|
|
|
|
|
|
RGB_Send(0, 0, 180, 0, 0, 180);
|
|
|
|
|
|
|
|
|
|
|
|
// 振动马达单次短震 50 毫秒,提供触觉反馈
|
|
|
|
|
|
MOTOR = 1;
|
|
|
|
|
|
Delay_ms(50);
|
|
|
|
|
|
MOTOR = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// 渲染显示时间编辑界面,默认高亮编辑小时字段,消隐位开启
|
|
|
|
|
|
UI_ShowSetTimePage(current_hour, current_min, time_edit_field, 1);
|
|
|
|
|
|
XTELL_LOG("[ClockApp] Time edit started.\r\n");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief ClockApp 启动回调
|
|
|
|
|
|
*/
|
|
|
|
|
|
static void ClockApp_OnStart(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
time_edit_active = 0;
|
|
|
|
|
|
current_state = STATE_NORMAL; // 系统切入正常待机状态
|
|
|
|
|
|
RF_SetMode(1); // 开启天线并置为接收模式,监听无线探测器
|
2026-07-28 18:03:20 +08:00
|
|
|
|
|
|
|
|
|
|
// 尝试从 PCF8563 RTC 芯片中读取硬件时间 (具备非阻塞防卡死保护)
|
|
|
|
|
|
if (PCF8563_Init()) {
|
|
|
|
|
|
PCF8563_ReadTime(¤t_hour, ¤t_min, ¤t_sec);
|
|
|
|
|
|
XTELL_LOG("[ClockApp] RTC Hardware Synced OK!\r\n");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
XTELL_LOG("[ClockApp] RTC Hardware Offline, using system clock.\r\n");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 绘制并渲染待机时钟主页面画面
|
|
|
|
|
|
UI_ShowClockPage(current_state, current_hour, current_min);
|
2026-07-17 09:08:53 +08:00
|
|
|
|
|
|
|
|
|
|
// 关断/熄灭 FCOB 双灯条
|
|
|
|
|
|
RGB_Send(0, 0, 0, 0, 0, 0);
|
|
|
|
|
|
|
|
|
|
|
|
XTELL_LOG("[ClockApp] Started\r\n");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief ClockApp 轮询主回调
|
|
|
|
|
|
*/
|
|
|
|
|
|
static void ClockApp_onRun(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (time_edit_active)
|
|
|
|
|
|
{
|
|
|
|
|
|
// ====== 时间设置闪烁动画 (周期 500ms) ======
|
|
|
|
|
|
u8 blink = (ms_tick / 500) % 2;
|
|
|
|
|
|
if (blink != time_edit_blink_on)
|
|
|
|
|
|
{
|
|
|
|
|
|
time_edit_blink_on = blink;
|
|
|
|
|
|
// 每次闪烁状态发生变化,重新刷写屏幕数值
|
|
|
|
|
|
UI_ShowSetTimePage(current_hour, current_min, time_edit_field, time_edit_blink_on);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// 软时钟发生分钟改变,需要通知屏幕重画时钟主页
|
|
|
|
|
|
if (clock_updated) {
|
|
|
|
|
|
clock_updated = 0;
|
|
|
|
|
|
UI_ShowClockPage(current_state, current_hour, current_min);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief ClockApp 退出清理回调
|
|
|
|
|
|
*/
|
|
|
|
|
|
static void ClockApp_onClose(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
time_edit_active = 0;
|
|
|
|
|
|
RGB_Send(0, 0, 0, 0, 0, 0); // 关闭灯条
|
|
|
|
|
|
XTELL_LOG("[ClockApp] Closed\r\n");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief ClockApp 接收事件处理回调 (按键导航与布撤防交互)
|
|
|
|
|
|
*/
|
|
|
|
|
|
static EventResult ClockApp_onEvent(SystemEvent *evt)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (time_edit_active)
|
|
|
|
|
|
{
|
|
|
|
|
|
// ====== 处于时间设置状态下的按键拦截处理机 ======
|
|
|
|
|
|
if (evt->key_event == KEY_EVENT_UP_CLICK)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 短按 ▲ 键增加数值 (小时/分钟循环相加)
|
|
|
|
|
|
if (time_edit_field == 1) {
|
|
|
|
|
|
current_hour = (current_hour + 1) % 24;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
current_min = (current_min + 1) % 60;
|
|
|
|
|
|
}
|
|
|
|
|
|
UI_ShowSetTimePage(current_hour, current_min, time_edit_field, 1);
|
|
|
|
|
|
return EVENT_HANDLED; // 吞掉并消化事件
|
|
|
|
|
|
}
|
|
|
|
|
|
if (evt->key_event == KEY_EVENT_DOWN_CLICK)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 短按 ▼ 键减小数值
|
|
|
|
|
|
if (time_edit_field == 1) {
|
|
|
|
|
|
current_hour = (current_hour == 0) ? 23 : (current_hour - 1);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
current_min = (current_min == 0) ? 59 : (current_min - 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
UI_ShowSetTimePage(current_hour, current_min, time_edit_field, 1);
|
|
|
|
|
|
return EVENT_HANDLED;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (evt->key_event == KEY_EVENT_CONFIRM_LONG)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 长按 ■ 确认键切换调节字段 (在修改小时与修改分钟间跳转)
|
|
|
|
|
|
if (time_edit_field == 1) {
|
|
|
|
|
|
time_edit_field = 2;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
time_edit_field = 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
UI_ShowSetTimePage(current_hour, current_min, time_edit_field, 1);
|
|
|
|
|
|
return EVENT_HANDLED;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (evt->key_event == KEY_EVENT_CONFIRM_CLICK)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 短按 ■ 确认键保存最新时钟配置并退出编辑模式
|
|
|
|
|
|
time_edit_active = 0;
|
|
|
|
|
|
current_state = STATE_NORMAL;
|
|
|
|
|
|
RGB_Send(0, 0, 0, 0, 0, 0); // 熄灭蓝色指示灯
|
|
|
|
|
|
|
2026-07-28 18:03:20 +08:00
|
|
|
|
// 同步将最新时间 (hour, min, 0秒) 写入 PCF8563 芯片寄存器
|
|
|
|
|
|
PCF8563_WriteTime(current_hour, current_min, 0);
|
|
|
|
|
|
|
2026-07-17 09:08:53 +08:00
|
|
|
|
// 退出短振反馈
|
|
|
|
|
|
MOTOR = 1; Delay_ms(50); MOTOR = 0;
|
|
|
|
|
|
|
|
|
|
|
|
UI_ShowClockPage(current_state, current_hour, current_min);
|
|
|
|
|
|
return EVENT_HANDLED;
|
|
|
|
|
|
}
|
|
|
|
|
|
return EVENT_HANDLED; // 在时间设置模式下屏蔽拦截其他一切无关按键事件
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ====== 正常时钟待机状态下的按键拦截处理 ======
|
|
|
|
|
|
|
|
|
|
|
|
// 1. 长按 ■ 确认键,打开设置主菜单 MenuApp
|
|
|
|
|
|
if (evt->key_event == KEY_EVENT_CONFIRM_LONG) {
|
|
|
|
|
|
AppManager_SwitchToForeground(&menu_app);
|
|
|
|
|
|
return EVENT_HANDLED;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 2. 长按 ▲ 键,一键切换系统的 布防 (ARMED) 和 撤防 (DISARMED) 状态
|
|
|
|
|
|
if (evt->key_event == KEY_EVENT_UP_LONG) {
|
|
|
|
|
|
if (current_state == STATE_ARMED) {
|
|
|
|
|
|
current_state = STATE_DISARMED;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
current_state = STATE_ARMED;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 布撤防状态切换成功后进行 100ms 短震确认,并重新刷写时钟待机页
|
|
|
|
|
|
MOTOR = 1; Delay_ms(100); MOTOR = 0;
|
|
|
|
|
|
UI_ShowClockPage(current_state, current_hour, current_min);
|
|
|
|
|
|
return EVENT_HANDLED;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return EVENT_IGNORED; // 其他未被关心的事件交由后台应用或丢弃
|
|
|
|
|
|
}
|