feat(ui): extend set_clock_app to edit day/month/year, not just time
time_edit_field now cycles through 5 fields (hour/min/day/month/year) via long-press CONFIRM. Up/down adjusts whichever field is focused, with day clamped to Days_In_Month() when month/year changes, and Clock_RecalcWeekday() called after every date edit so the weekday label stays in sync. UI_UpdateSetTimeDigit() now also refreshes the weekday abbreviation when editing day/month/year, since the computed weekday can change independently of which digit was actually touched. Save writes the full date+weekday via PCF8563_WriteDateTime(). Also removes PCF8563_ReadTime()/WriteTime(), now unused since every caller was updated to the DateTime variants directly.
This commit is contained in:
@@ -12,7 +12,7 @@ extern SystemState current_state;
|
|||||||
extern volatile u16 ms_tick;
|
extern volatile u16 ms_tick;
|
||||||
|
|
||||||
// 本应用私有的时间编辑状态
|
// 本应用私有的时间编辑状态
|
||||||
static u8 time_edit_field = 1; // 标识当前聚焦在哪一个参数上进行微调 (1:修改小时, 2:修改分钟)
|
static u8 time_edit_field = 1; // 当前聚焦调节的字段 (1:小时, 2:分钟, 3:日, 4:月, 5:年)
|
||||||
static u8 time_edit_blink_on = 1; // 时钟修改时光标闪烁周期状态位
|
static u8 time_edit_blink_on = 1; // 时钟修改时光标闪烁周期状态位
|
||||||
|
|
||||||
// 声明本应用的生命周期回调函数
|
// 声明本应用的生命周期回调函数
|
||||||
@@ -49,7 +49,7 @@ static void SetClockApp_OnStart(void)
|
|||||||
MOTOR = 0;
|
MOTOR = 0;
|
||||||
|
|
||||||
// 渲染显示时间编辑界面,默认高亮编辑小时字段,消隐位开启
|
// 渲染显示时间编辑界面,默认高亮编辑小时字段,消隐位开启
|
||||||
UI_ShowSetTimePage(current_hour, current_min, time_edit_field, 1);
|
UI_ShowSetTimePage(current_hour, current_min, current_day, current_month, current_year, current_weekday, time_edit_field, 1);
|
||||||
XTELL_LOG("[SetClockApp] Started\r\n");
|
XTELL_LOG("[SetClockApp] Started\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,8 +63,8 @@ static void SetClockApp_onRun(void)
|
|||||||
if (blink != time_edit_blink_on)
|
if (blink != time_edit_blink_on)
|
||||||
{
|
{
|
||||||
time_edit_blink_on = blink;
|
time_edit_blink_on = blink;
|
||||||
// 每次闪烁状态发生变化,只局部刷新正在调节的那个数字,不整屏重绘
|
// 每次闪烁状态发生变化,只局部刷新正在调节的那个字段,不整屏重绘
|
||||||
UI_UpdateSetTimeDigit(current_hour, current_min, time_edit_field, time_edit_blink_on);
|
UI_UpdateSetTimeDigit(current_hour, current_min, current_day, current_month, current_year, current_weekday, time_edit_field, time_edit_blink_on);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,49 +84,83 @@ static EventResult SetClockApp_onEvent(SystemEvent *evt)
|
|||||||
{
|
{
|
||||||
if (evt->key_event == KEY_EVENT_UP_CLICK)
|
if (evt->key_event == KEY_EVENT_UP_CLICK)
|
||||||
{
|
{
|
||||||
// 短按 ▲ 键增加数值 (小时/分钟循环相加)
|
// 短按 ▲ 键增加当前聚焦字段的数值 (各字段独立循环)
|
||||||
if (time_edit_field == 1) {
|
switch (time_edit_field) {
|
||||||
current_hour = (current_hour + 1) % 24;
|
case 1: current_hour = (current_hour + 1) % 24; break;
|
||||||
} else {
|
case 2: current_min = (current_min + 1) % 60; break;
|
||||||
current_min = (current_min + 1) % 60;
|
case 3:
|
||||||
|
current_day = (current_day >= Days_In_Month(current_year, current_month)) ? 1 : (current_day + 1);
|
||||||
|
Clock_RecalcWeekday();
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
current_month = (current_month >= 12) ? 1 : (current_month + 1);
|
||||||
|
// 月份变化后,若当前日超出新月份的最大天数,截断到最大天数
|
||||||
|
if (current_day > Days_In_Month(current_year, current_month)) {
|
||||||
|
current_day = Days_In_Month(current_year, current_month);
|
||||||
|
}
|
||||||
|
Clock_RecalcWeekday();
|
||||||
|
break;
|
||||||
|
default: // 5: 年
|
||||||
|
current_year = (current_year >= 99) ? 0 : (current_year + 1);
|
||||||
|
if (current_day > Days_In_Month(current_year, current_month)) {
|
||||||
|
current_day = Days_In_Month(current_year, current_month);
|
||||||
|
}
|
||||||
|
Clock_RecalcWeekday();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
time_edit_blink_on = 1; // 调值后强制显示 (不处于消隐周期)
|
time_edit_blink_on = 1; // 调值后强制显示 (不处于消隐周期)
|
||||||
UI_UpdateSetTimeDigit(current_hour, current_min, time_edit_field, 1);
|
UI_UpdateSetTimeDigit(current_hour, current_min, current_day, current_month, current_year, current_weekday, time_edit_field, 1);
|
||||||
return EVENT_HANDLED;
|
return EVENT_HANDLED;
|
||||||
}
|
}
|
||||||
if (evt->key_event == KEY_EVENT_DOWN_CLICK)
|
if (evt->key_event == KEY_EVENT_DOWN_CLICK)
|
||||||
{
|
{
|
||||||
// 短按 ▼ 键减小数值
|
// 短按 ▼ 键减小当前聚焦字段的数值 (各字段独立循环)
|
||||||
if (time_edit_field == 1) {
|
switch (time_edit_field) {
|
||||||
current_hour = (current_hour == 0) ? 23 : (current_hour - 1);
|
case 1: current_hour = (current_hour == 0) ? 23 : (current_hour - 1); break;
|
||||||
} else {
|
case 2: current_min = (current_min == 0) ? 59 : (current_min - 1); break;
|
||||||
current_min = (current_min == 0) ? 59 : (current_min - 1);
|
case 3:
|
||||||
|
current_day = (current_day <= 1) ? Days_In_Month(current_year, current_month) : (current_day - 1);
|
||||||
|
Clock_RecalcWeekday();
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
current_month = (current_month <= 1) ? 12 : (current_month - 1);
|
||||||
|
if (current_day > Days_In_Month(current_year, current_month)) {
|
||||||
|
current_day = Days_In_Month(current_year, current_month);
|
||||||
|
}
|
||||||
|
Clock_RecalcWeekday();
|
||||||
|
break;
|
||||||
|
default: // 5: 年
|
||||||
|
current_year = (current_year == 0) ? 99 : (current_year - 1);
|
||||||
|
if (current_day > Days_In_Month(current_year, current_month)) {
|
||||||
|
current_day = Days_In_Month(current_year, current_month);
|
||||||
|
}
|
||||||
|
Clock_RecalcWeekday();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
time_edit_blink_on = 1; // 调值后强制显示 (不处于消隐周期)
|
time_edit_blink_on = 1; // 调值后强制显示 (不处于消隐周期)
|
||||||
UI_UpdateSetTimeDigit(current_hour, current_min, time_edit_field, 1);
|
UI_UpdateSetTimeDigit(current_hour, current_min, current_day, current_month, current_year, current_weekday, time_edit_field, 1);
|
||||||
return EVENT_HANDLED;
|
return EVENT_HANDLED;
|
||||||
}
|
}
|
||||||
if (evt->key_event == KEY_EVENT_CONFIRM_LONG)
|
if (evt->key_event == KEY_EVENT_CONFIRM_LONG)
|
||||||
{
|
{
|
||||||
// 长按 ■ 确认键切换调节字段 (在修改小时与修改分钟间跳转)
|
// 长按 ■ 确认键切换调节字段 (小时 -> 分钟 -> 日 -> 月 -> 年 -> 循环回小时)
|
||||||
if (time_edit_field == 1) {
|
time_edit_field = (time_edit_field >= 5) ? 1 : (time_edit_field + 1);
|
||||||
time_edit_field = 2;
|
time_edit_blink_on = 1; // 切换焦点后所有字段都应处于可见状态
|
||||||
} else {
|
// 全部字段各局部刷新一次,避免切换前正处于消隐周期的那个字段停留在涂黑状态
|
||||||
time_edit_field = 1;
|
UI_UpdateSetTimeDigit(current_hour, current_min, current_day, current_month, current_year, current_weekday, 1, 1);
|
||||||
}
|
UI_UpdateSetTimeDigit(current_hour, current_min, current_day, current_month, current_year, current_weekday, 2, 1);
|
||||||
time_edit_blink_on = 1; // 切换焦点后两个字段都应处于可见状态
|
UI_UpdateSetTimeDigit(current_hour, current_min, current_day, current_month, current_year, current_weekday, 3, 1);
|
||||||
// 两个数字区域都局部刷新一次,避免切换前正处于消隐周期的那个数字停留在涂黑状态
|
UI_UpdateSetTimeDigit(current_hour, current_min, current_day, current_month, current_year, current_weekday, 4, 1);
|
||||||
UI_UpdateSetTimeDigit(current_hour, current_min, 1, 1);
|
UI_UpdateSetTimeDigit(current_hour, current_min, current_day, current_month, current_year, current_weekday, 5, 1);
|
||||||
UI_UpdateSetTimeDigit(current_hour, current_min, 2, 1);
|
|
||||||
return EVENT_HANDLED;
|
return EVENT_HANDLED;
|
||||||
}
|
}
|
||||||
if (evt->key_event == KEY_EVENT_CONFIRM_CLICK)
|
if (evt->key_event == KEY_EVENT_CONFIRM_CLICK)
|
||||||
{
|
{
|
||||||
// 短按 ■ 确认键保存最新时钟配置,退出到主菜单 (父 App)
|
// 短按 ■ 确认键保存最新时间与日期配置,退出到主菜单 (父 App)
|
||||||
current_state = STATE_PAIR_MENU;
|
current_state = STATE_PAIR_MENU;
|
||||||
|
|
||||||
// 同步将最新时间 (hour, min, 0秒) 写入 PCF8563 芯片寄存器
|
// 同步将最新时间与日期 (含算好的星期) 一次性写入 PCF8563 芯片寄存器
|
||||||
PCF8563_WriteTime(current_hour, current_min, 0);
|
PCF8563_WriteDateTime(current_hour, current_min, 0, current_day, current_month, current_year, current_weekday);
|
||||||
|
|
||||||
// 退出短振反馈
|
// 退出短振反馈
|
||||||
MOTOR = 1; Delay_ms(50); MOTOR = 0;
|
MOTOR = 1; Delay_ms(50); MOTOR = 0;
|
||||||
|
|||||||
9
App/ui.c
9
App/ui.c
@@ -480,13 +480,14 @@ void UI_ShowSetTimePage(u8 hour, u8 min, u8 day, u8 month, u8 year, u8 weekday,
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 局部刷新时间设置界面里"正在调节的那一个"字段 (小时/分钟/日/月/年)
|
* @brief 局部刷新时间设置界面里"正在调节的那一个"字段 (小时/分钟/日/月/年)
|
||||||
|
* @param weekday 根据当前日期算出的星期 (0=周日, ..., 6=周六),调节日/月/年时顺带刷新星期缩写
|
||||||
* @param selection 1:小时, 2:分钟, 3:日, 4:月, 5:年
|
* @param selection 1:小时, 2:分钟, 3:日, 4:月, 5:年
|
||||||
* @param blink_on 1:显示数值, 0:消隐(涂黑),用于 500ms 周期闪烁效果
|
* @param blink_on 1:显示数值, 0:消隐(涂黑),用于 500ms 周期闪烁效果
|
||||||
* @details 小时/分钟用 32x32px 大字体区域;日/月/年用日期栏里对应的 16x16px 小字体区域,
|
* @details 小时/分钟用 32x32px 大字体区域;日/月/年用日期栏里对应的 16x16px 小字体区域,
|
||||||
* 都只重画自己那一小块,不触碰锁头/电池/冒号/AM-PM/星期文字等其它内容,
|
* 都只重画自己那一小块,不触碰锁头/电池/冒号/AM-PM/星期文字等其它内容,
|
||||||
* 避免每次闪烁或调值都整屏 LCD_Clear() 造成全屏闪烁。
|
* 避免每次闪烁或调值都整屏 LCD_Clear() 造成全屏闪烁。
|
||||||
*/
|
*/
|
||||||
void UI_UpdateSetTimeDigit(u8 hour, u8 min, u8 day, u8 month, u8 year, u8 selection, u8 blink_on)
|
void UI_UpdateSetTimeDigit(u8 hour, u8 min, u8 day, u8 month, u8 year, u8 weekday, u8 selection, u8 blink_on)
|
||||||
{
|
{
|
||||||
char buf[3];
|
char buf[3];
|
||||||
u16 x;
|
u16 x;
|
||||||
@@ -503,6 +504,12 @@ void UI_UpdateSetTimeDigit(u8 hour, u8 min, u8 day, u8 month, u8 year, u8 select
|
|||||||
default: x = DATE_BAR_YEAR_X; y = DATE_BAR_Y; w = DATE_BAR_FIELD_W; h = 16; value = year; break;
|
default: x = DATE_BAR_YEAR_X; y = DATE_BAR_Y; w = DATE_BAR_FIELD_W; h = 16; value = year; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 调节日/月/年时,星期缩写可能因为日期变化而改变,顺带刷新一下 (不参与闪烁,始终显示)
|
||||||
|
if (selection >= 3) {
|
||||||
|
LCD_FillRect(DATE_BAR_START_X, DATE_BAR_Y, 24, 16, COLOR_BLACK);
|
||||||
|
LCD_ShowString(DATE_BAR_START_X, DATE_BAR_Y, Lang_Get((StringID)(STR_WEEKDAY_SUN + weekday)), COLOR_GRAY, COLOR_BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
if (!blink_on) {
|
if (!blink_on) {
|
||||||
// 灭周期:直接把这一小块涂黑,形成消隐效果
|
// 灭周期:直接把这一小块涂黑,形成消隐效果
|
||||||
LCD_FillRect(x, y, w, h, COLOR_BLACK);
|
LCD_FillRect(x, y, w, h, COLOR_BLACK);
|
||||||
|
|||||||
3
App/ui.h
3
App/ui.h
@@ -91,9 +91,10 @@ void UI_ShowSetTimePage(u8 hour, u8 min, u8 day, u8 month, u8 year, u8 weekday,
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 局部刷新时间设置界面里正在调节的那一个字段 (小时/分钟/日/月/年),用于闪烁/调值时避免整屏重绘
|
* @brief 局部刷新时间设置界面里正在调节的那一个字段 (小时/分钟/日/月/年),用于闪烁/调值时避免整屏重绘
|
||||||
|
* @param weekday 根据当前日期算出的星期 (0=周日, ..., 6=周六),调节日/月/年时顺带刷新星期缩写
|
||||||
* @param selection 1:小时, 2:分钟, 3:日, 4:月, 5:年
|
* @param selection 1:小时, 2:分钟, 3:日, 4:月, 5:年
|
||||||
* @param blink_on 1:显示数值, 0:消隐(涂黑)
|
* @param blink_on 1:显示数值, 0:消隐(涂黑)
|
||||||
*/
|
*/
|
||||||
void UI_UpdateSetTimeDigit(u8 hour, u8 min, u8 day, u8 month, u8 year, u8 selection, u8 blink_on);
|
void UI_UpdateSetTimeDigit(u8 hour, u8 min, u8 day, u8 month, u8 year, u8 weekday, u8 selection, u8 blink_on);
|
||||||
|
|
||||||
#endif // __UI_H__
|
#endif // __UI_H__
|
||||||
|
|||||||
@@ -310,45 +310,6 @@ bit PCF8563_ReadDateTime(u8 *hour, u8 *min, u8 *sec, u8 *day, u8 *month, u8 *yea
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 从 PCF8563 读取当前时间 (兼容旧接口,只取时分秒,丢弃日期部分)
|
|
||||||
*/
|
|
||||||
bit PCF8563_ReadTime(u8 *hour, u8 *min, u8 *sec)
|
|
||||||
{
|
|
||||||
u8 day, month, year;
|
|
||||||
return PCF8563_ReadDateTime(hour, min, sec, &day, &month, &year);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 将时间精准写入 PCF8563 RTC 芯片 (只写时分秒三个寄存器,不触碰日期寄存器)
|
|
||||||
*/
|
|
||||||
bit PCF8563_WriteTime(u8 hour, u8 min, u8 sec)
|
|
||||||
{
|
|
||||||
I2C_Start();
|
|
||||||
I2C_SendByte(PCF8563_ADDR_WRITE);
|
|
||||||
if (!I2C_WaitAck()) return 0;
|
|
||||||
|
|
||||||
// 定位写入起始寄存器 0x02
|
|
||||||
I2C_SendByte(REG_VL_SECONDS);
|
|
||||||
if (!I2C_WaitAck()) return 0;
|
|
||||||
|
|
||||||
// 写入秒
|
|
||||||
I2C_SendByte(DEC2BCD(sec & 0x7F));
|
|
||||||
if (!I2C_WaitAck()) return 0;
|
|
||||||
|
|
||||||
// 写入分
|
|
||||||
I2C_SendByte(DEC2BCD(min & 0x7F));
|
|
||||||
if (!I2C_WaitAck()) return 0;
|
|
||||||
|
|
||||||
// 写入时
|
|
||||||
I2C_SendByte(DEC2BCD(hour & 0x3F));
|
|
||||||
if (!I2C_WaitAck()) return 0;
|
|
||||||
|
|
||||||
I2C_Stop();
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 将时间与日期一次性连续写入 PCF8563 RTC 芯片 (寄存器 0x02~0x08 共 7 字节连续写入)
|
* @brief 将时间与日期一次性连续写入 PCF8563 RTC 芯片 (寄存器 0x02~0x08 共 7 字节连续写入)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -24,24 +24,6 @@
|
|||||||
*/
|
*/
|
||||||
bit PCF8563_Init(void);
|
bit PCF8563_Init(void);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 从 PCF8563 芯片读取当前时间 (时、分、秒)
|
|
||||||
* @param hour 小时指针 (0~23)
|
|
||||||
* @param min 分钟指针 (0~59)
|
|
||||||
* @param sec 秒钟指针 (0~59)
|
|
||||||
* @return bit 1: 读取成功, 0: 通讯失败
|
|
||||||
*/
|
|
||||||
bit PCF8563_ReadTime(u8 *hour, u8 *min, u8 *sec);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 将指定的时间 (时、分、秒) 写入 PCF8563 芯片
|
|
||||||
* @param hour 小时 (0~23)
|
|
||||||
* @param min 分钟 (0~59)
|
|
||||||
* @param sec 秒钟 (0~59)
|
|
||||||
* @return bit 1: 写入成功, 0: 通讯失败
|
|
||||||
*/
|
|
||||||
bit PCF8563_WriteTime(u8 hour, u8 min, u8 sec);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 从 PCF8563 芯片连续读取时间与日期 (时/分/秒/日/月/年)
|
* @brief 从 PCF8563 芯片连续读取时间与日期 (时/分/秒/日/月/年)
|
||||||
* @param hour 小时指针 (0~23)
|
* @param hour 小时指针 (0~23)
|
||||||
|
|||||||
Reference in New Issue
Block a user