Files
stc32g128k/work-order/wo-05

83 lines
10 KiB
Plaintext
Raw Normal View History

# 工单 WO-05细节问题修复清单
**优先级**:中
**状态**:待处理
---
## 问题列表
1. 开机启动瞬间背光应保持关闭,等所有初始化都完成、即将进入 `while(1)` 主循环前才点亮,避免开机闪烁。
2. 长按 KEY_CONFIRM 打开主菜单后10 秒内无任何按键操作,自动关闭菜单返回时钟界面。
3. 按 App 重新梳理菜单导航结构menu_app 只保留 4 个入口(语言开关内置于 menu_app其余 3 项各自跳转到独立的 App),每个子 App 统一用长按 CONFIRM 退出、回到自己的父 App而不是像现在这样有的退回上一级、有的直接跳回主菜单/首页,规则不统一。
4. 默认菜单语言改为英文(目前首次开机/Flash 擦除态默认是法语)。
5. 主菜单上下键切换菜单项允许循环切换(到顶/底后可以绕到另一端)。
6. P3.6 进入休眠前改成电平触发方式作为唤醒源,现在经常唤醒不了处理器。
---
## 实现思路
### 1. 背光延迟点亮
- `Drivers/lcd.c` 的 `LCD_Init()` 第 89 行 `SGM_CTRL = 0;`(点亮背光)在整个 ST7789V 寄存器初始化序列**最开头**就执行了,这就是闪烁的直接原因——去掉这一行(或改成 `SGM_CTRL = 1` 熄灭)。
- `App/system.c` 的 `GPIO_Init()` 只把 P1.7 配置成推挽输出,没有写初始电平,上电瞬间电平不确定;补一行 `SGM_CTRL = 1;`(熄灭),让背光从上电第一刻就确定是关的。
- `App/main.c` 的 `main()` 里,在 `AppManager_StartApp(APP_ID_HOME)`(画出第一帧时钟界面,若第 3 条改名重构先落地)之后、`while(1)` 之前,加一行 `SGM_CTRL = 0;` 点亮背光。
### 2. 菜单 10 秒无操作自动关闭
- 现有的 `inactivity_timer`(`App/main.c`)是全局 60 秒深度休眠计时,粒度和用途都不一样,不能直接复用。
- 在 `App/app_menu.c` 里新增一个 `static u16 menu_idle_enter_ms`,仿照 `Drivers/rf.c` 的 `RF_CheckDecodeWatchdog()`/`app_menu.c` 里已有的 `last_bind_tx_ms` 那种 `ms_tick` 环绕安全减法模式(`ms_tick` 是 0~999 循环的 1ms 计时)。
- `MenuApp_onEvent()` 每收到一次按键事件就刷新这个时间戳。
- 需要一个周期性检查点:目前 AppManager 框架没有 `OnTick`/`OnUpdate` 回调,需要确认要不要新增一个,或者简单地在 `main.c` 的 `while(1)` 里,当前台 App 是 `menu_app` 时调用一个新增的 `MenuApp_CheckIdleTimeout()`。超时后调用 `AppManager_SwitchToForeground(&home_app)`(若第 3 条改名重构先落地,否则仍是 `&clock_app`)。
### 3. 按 App 重新梳理菜单导航结构
**现状问题**`app_menu.c` 用一个 `menu_level`(0/1/2)在单个 App 内部模拟出三层菜单,其中 `menu_level=1` 短按 CONFIRM 会切换到独立的 `pair_app``pair_app` 退出时又统一调用 `AppManager_SwitchToForeground(&menu_app)`,而 `MenuApp_OnStart()`/`MenuApp_onClose()` 都会无条件把 `menu_level` 清零——导致不管从哪个子菜单退出,最后都被强制拉回顶层主菜单,退出规则不统一,也不符合"退出到上一级"的预期。时间设置(`Start_Time_Edit()`)则是另一套模式:混在 `clock_app` 内部用 `time_edit_active` 标志位实现,进入时还要先 `AppManager_SwitchToForeground(&clock_app)` 闪一下正常时钟画面再叠加编辑界面,也是一处潜在的画面闪烁点。
**改造方向 —— 完全去掉 `menu_level` 这个概念,统一按 App 组织,父子关系一致、退出手势一致**`clock_app` 已经确认是开机默认显示的 App(`App/main.c:280` 开机调用 `AppManager_StartApp(APP_ID_CLOCK)`),直接更名为 `home_app`;从中新建一个专门的 `set_clock_app` 承载时间设置。
| App | 现状 | 改造后 |
|---|---|---|
| `home_app`(时钟主页) | 即现有 `clock_app`(`App/app_clock.c`),兼管时间编辑(`time_edit_active`) | 整体更名:文件 `App/app_clock.c`→`App/app_home.c`,结构体实例 `clock_app`→`home_app``APP_ID_CLOCK`→`APP_ID_HOME`,函数前缀 `ClockApp_*`→`HomeApp_*`;剥离时间编辑逻辑,只保留待机时钟显示与布撤防 |
| `menu_app`(主菜单) | 内部 `menu_level` 0/1/2 三态,语言开关 + 传感器子菜单 + 摄像头绑定全挤在一个 App 里 | 不再有 `menu_level`,只保留顶层 4 项列表(`menu_select` 0~3语言开关内置处理不跳转);其余 3 项短按 CONFIRM 各自切到独立 App |
| `set_clock_app`(时间设置) | 不是独立 App是 `clock_app` 内的一个模式标志(`time_edit_active`) | 新建独立 App(`App/app_set_clock.c`),从 `app_clock.c` 抽出 `Start_Time_Edit`/`time_edit_*` 相关代码 |
| `pair_app`(传感器配对) | 已经是独立 App但传感器类型选择这一步(门磁/PIR/烟感/气感/水浸)现在留在 `menu_app` 的 `menu_level=1` 里,选完才切到 `pair_app` 开始搜索 | 把类型选择合并成 `pair_app` 的新初始状态(比如 `PAIR_STATE_SELECT_TYPE`,排在现有 `PAIR_STATE_WAIT` 之前)`menu_app` 上"传感器配对"这一项短按 CONFIRM 直接整体切到 `pair_app``pair_app` 不管在哪个状态退出,都统一回到 `menu_app` |
| `ipc_bind_app`(摄像头绑定) | 不是独立 App是 `menu_app` 内 `menu_level=2` 的一段代码(呼吸灯+定时发射绑定帧) | 新建独立 App(`App/app_ipc_bind.c`),仿照 `pair_app` 的结构抽出来 |
**统一导航规则**
- `home_app` 长按 CONFIRM → 进入 `menu_app`。
- `menu_app` 长按 CONFIRM → 回到 `home_app`(现有行为,不变,只是改了名字)。
- `menu_app` 顶层短按 CONFIRM 选中某一项 → 进入对应子 App(`set_clock_app`/`pair_app`/`ipc_bind_app`)。
- 三个子 App 无论是长按 CONFIRM 主动退出、还是完成/超时自动退出(`pair_app` 的成功/失败/取消),都统一 → 回到 `menu_app`(它们共同的父 App),不再有"直接跳回首页"或"退到某个具体层级"的特殊情况。
**需要新增/修改的文件**
- `App/app_clock.c` → 更名为 `App/app_home.c``clock_app`→`home_app`、`APP_ID_CLOCK`→`APP_ID_HOME`、`ClockApp_*`→`HomeApp_*` 函数全部改名;去掉时间编辑相关代码(`time_edit_active`/`time_edit_field`/`time_edit_blink_on`/`Start_Time_Edit`),长按 CONFIRM 改为切到 `menu_app`(不变)。
- 新建 `App/app_set_clock.c`:承接从 `app_clock.c` 抽出来的时间编辑逻辑,退出(短按 CONFIRM 保存 或 长按退出)统一改为 `AppManager_SwitchToForeground(&menu_app)`。
- 新建 `App/app_ipc_bind.c`:把 `app_menu.c` 里 `menu_level==2` 的呼吸灯效果、`EV1527_Transmit` 绑定广播、`last_bind_tx_ms` 计时都搬过去,退出统一改为 `AppManager_SwitchToForeground(&menu_app)`。
- 精简 `App/app_menu.c`:彻底去掉 `menu_level` 变量和三态分支,只保留 `menu_select` 这一个 0~3 的顶层索引;短按 CONFIRM 按 `menu_select` 分支跳转到三个子 App 或原地切语言。
- `App/app_manager.h`(或对应头文件)`APP_ID_CLOCK`→`APP_ID_HOME`,新增 `APP_ID_SET_CLOCK`/`APP_ID_IPC_BIND``extern WristbandApp clock_app` 等声明一并改名/新增。
- 全仓库搜索 `clock_app`/`APP_ID_CLOCK` 的引用点(至少 `App/main.c`、`App/app_menu.c`、`App/app_pair.c`、`App/event.c` 中出现过)统一改名,避免漏改。
- `wristband.uvproj`:文件改名(`app_clock.c`→`app_home.c`)与两个新文件(`app_set_clock.c`、`app_ipc_bind.c`)都要同步维护工程文件列表,不能像之前 `isr_jump.asm` 那样漏加。
**待确认的行为变化**:现在"时间设置"短按 CONFIRM 保存后,是直接回到时钟主页;改造后按统一规则会回到 `menu_app`(主菜单)而不是直接回时钟——这是一个和现状不一样的地方,需要确认是否符合预期,还是希望 `set_clock_app` 作为特例、保存后也直接回 `home_app`。
### 4. 默认语言改英文
- `App/language.c``static Language current_lang = LANG_FR;` 改成 `LANG_EN`。
- 同文件 `Lang_Init()` 里的越界回退分支 `(lang < LANG_COUNT) ? lang : LANG_FR` 改成 `: LANG_EN`。
- 两处都要改,否则开机静态初始值和 Flash 擦除态回退值会不一致。
### 5. 菜单上下循环切换
- 涉及两处 UP/DOWN 边界判断(若第 3 条的 App 化重构先落地,第二处会搬到 `pair_app` 里,但改法一样)
- `App/app_menu.c` 顶层菜单(现第 106-121 行4 项,索引 0~3)
- 传感器类型选择(现在是 `app_menu.c` 的 `menu_level==1`,第 158-172 行;重构后是 `pair_app` 的 `PAIR_STATE_SELECT_TYPE`5 项,索引 0~4)
- 现在是 `if (menu_select > 0) menu_select--;` / `if (menu_select < MAX) menu_select++;`,到边界就不动;改成到边界时绕到另一端,例如 UP 在 `menu_select==0` 时跳到 `MAX`DOWN 在 `menu_select==MAX` 时跳回 `0`。
### 6. P3.6 休眠前改电平触发唤醒
- 现状:`RF_HandleEdgeInterrupt()` 用软件乒乓单边沿切换模拟双边沿触发,`P3IM0` 会在上升沿/下降沿之间动态翻转;`Enter_Low_Power_Sleep()` 进入休眠前完全没有重新设置 `P3IM0`/`P3IM1`,导致进入 Power Down 那一刻 `P3IM0` 具体停在哪个方向是不确定的,如果停在"等下降沿"而实际先来的是上升沿,就可能唤醒不了或唤醒延迟。
- **需要注意**:根据 WO-04 §2.9 查到的《STC32G 技术手册》15.1.3 节真值表,`PxIM1/PxIM0` 的"高电平中断"和"低电平中断"两种模式**都标注为不支持掉电唤醒**,只有下降沿/上升沿两种边沿模式支持。这与本条需求(改成电平触发来解决唤醒不了的问题)在文档上是矛盾的,实现时要先在真机上实测电平触发是否真的能唤醒;如果实测不行,退回到"休眠前强制把 P3IM0/P3IM1 设成固定的某一个边沿方向(比如固定成上升沿),不再依赖乒乓切换留下的随机状态"这个更符合手册说明的方案。
- 具体改法(不管选电平还是固定边沿):在 `App/system.c` 的 `Enter_Low_Power_Sleep()` 里,`P3WKUE |= 0x40;` 之前,加一段显式设置 `P3IM1`/`P3IM0` 的代码,覆盖掉睡前可能残留的任意状态;如果验证后确定要改回边沿触发,`Wakeup_Restore()` 里对应也要把 `P3IM1`/`P3IM0` 重新设回 `RF_Init()` 里的初始方向,保证唤醒后解码状态机从一个已知状态重新开始。