Files
STM32F4-Base/Drivers/BSP/UI/ui_port.h
T
wandering1 7708f12c10 fix(ui/screenlink): 按键应答扣到按键后画面,反馈典型 250-450 ms 降至 70-135 ms
按键召唤答的是按键前的旧帧:uiTask 还没消化键答案就发走了,新画面
只能等下一次周期召唤(280 ms/轮)才带得出——真机反馈 250-450 ms 的
主构成(根因账本 docs/子系统设计/屏板链路设计说明.md §7.1)。

改动(用户批准范围 A+B+C;屏板固件未动,决策三不变):
- sb_link:按键召唤改为只入队不起发;uiTask 同拍重绘并组帧成功后交
  凭据(sb_link_key_rendered),TIM3 1 kHz 的 sb_link_ms_tick 以 ≤1 ms
  放行新帧。140 ms 截止(SB_KEY_RESP_MAX_MS,+59.6 ms 线上 <205 ms
  屏板放弃线)保底发旧帧,"一召一答"契约不破;线忙时同旧丢单、
  不留扣件。起发两中断源(USART1 IDLE/TIM3)共用 sb_tx_kick,
  "判忙→占位"在 PRIMASK 临界区原子完成。
- ui_task:排空注键挪到组帧之前,注键→即派即绘→组帧同拍闭环;
  组帧返回 BSP_OK 才交重绘凭据(BUSY 拍帧还没反映按键)。
- ui_port:注键单槽改 8 深环(连按不再互相覆盖,满丢最旧+计数);
  新增 ui_port_service_keys:同拍 lv_indev_read + lv_refr_now,
  省掉 indev ≤20 ms + 刷新 ≤20 ms 两段等待。
- ui_menu_view:菜单移动选中只失效新旧两行带(黄金参考零像素变化),
  滚动/异常回退整框失效。
- simulator:窗口循环 sleep 扣除本轮已耗时(原先无条件睡满
  lv_timer_handler 返回值,叠加 Windows Sleep 15.6 ms 粒度放大观感)。
- 串口 TX 上报新增 dfok/dfold(凭据放行新帧数/超时保底旧帧数):
  dfold 连涨 = uiTask 被饿 ≥140 ms 的直接现场证据。

验证:test/host/sb_link 164/164(新增 18 条:不立刻起发/凭据放行/
140 ms 截止保底/忙时不留扣件/陈旧凭据不放行等边界);菜单 8 状态 +
内容页 66 张黄金像素 PASS;Keil @build 0 错误 0 警告(两次);
BOM 99 文件无漂移、代码规范、doc-links 本次文件零问题、cppcheck PASS。
文档:屏板规划文档已被主干收编进设计说明,延迟账本落
docs/子系统设计/屏板链路设计说明.md §7.1,并同步 §4 口径、§8 接口、
§9.1 单测台账 146→164、§10 坑账本补条。

RAM 台账(分支不跑 --write,并行分支提交约定):本笔盖戳行
RW_IRAM1 94,336 B (72.0%) / RW_CCM 57,376 B (87.9%),较上一台账行
+4,400 B——为距上次台账构建以来分支累计差(含批 3 状态灯等未盖戳
提交),非全部本笔引入;本次自身增量按对象计为 ui_port.o +12 B
(8 深键环+丢计数+indev 指针)与 sb_link/o 数十字节级。
gate: only mem-budget/mem-numbers pending lead ledger backfill
(合并落主干后 Lead 统一 --write 回填受管区)。
2026-10-30 09:50:31 +08:00

112 lines
4.6 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* 模块名称:UI Display Port (LVGL 离屏显示端口)
* 模块功能:提供 LVGL 1bpp 离屏渲染端口与远程 keypad 输入设备
* 适用平台:STM32F407ZGTx
* 作者:王建锋
* 创建日期:2026-08-29
* 修改记录:
* 2026-08-29 王建锋 创建初始版本
*/
#ifndef UI_PORT_H
#define UI_PORT_H
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/* 屏幕尺寸与帧缓冲(160x160 1bpp = 3200 字节) */
#define UI_SCREEN_W 160
#define UI_SCREEN_H 160
#define UI_FB_SIZE ((UI_SCREEN_W * UI_SCREEN_H) / 8)
/*
* LVGL 索引色(I1)绘制缓冲布局 = [palette][pixel data](2026-09-21 台架实证;
* 改本端口或升级 LVGL 版本前必读):
* - lv_draw_buf_create() : 尺寸 = stride*h + LV_COLOR_INDEXED_PALETTE_SIZE(cf)*4
* - lv_draw_buf_goto_xy()/lv_draw.c : 取绘制指针时 data += palette(像素不从缓冲首址开始)
* - lv_refr get_max_row() : 从 data_size 里扣掉 palette 才当可用像素
* 但 lv_display_set_buffers()/lv_draw_buf_init() 的容量校验**只看 stride*h(不含 palette)**,
* 故"只给 stride*h"会被静默接受;实测两种后果:
* 1) 末 palette 个像素字节写到缓冲之外(金丝雀实测越界 8B,曾打脏紧邻 .bss 的
* s_frame_box[0] 指针 → 野指针 HardFault);
* 2) flush 回调收到的首地址含 palette,照原样整帧拷贝会让推流画面整体错位 8B。
* 规则:绘制缓冲按 UI_DRAW_BUF_SIZE 提供、上报 LVGL 的尺寸也用 UI_DRAW_BUF_SIZE;
* flush 取像素必须 color_p + UI_DRAW_BUF_PALETTE。
* 注:此处用字面量 8(I1 = 2 色 x 4 字节)以免头文件依赖 lvgl.h;ui_port.c 已按
* LV_COLOR_INDEXED_PALETTE_SIZE(LV_COLOR_FORMAT_I1)*4 核对一致。
*/
#define UI_DRAW_BUF_PALETTE 8u
#define UI_DRAW_BUF_SIZE (UI_FB_SIZE + UI_DRAW_BUF_PALETTE)
/* 远端按键码(与 DTU-HMI key.h 保持一致) */
#define UI_KEY_UP 0x02
#define UI_KEY_DOWN 0x40
#define UI_KEY_LEFT 0x10
#define UI_KEY_RIGHT 0x08
#define UI_KEY_ENTER 0x20
#define UI_KEY_ESC 0x01
/*
* 函数功能:初始化 LVGL 显示端口与按键输入设备
* 入口参数:无
* 返回值:0 - 成功,其他 - 失败(显示或输入设备创建失败)
* 限定条件:无
* 函数说明:1. 初始化 LVGL 内核并创建 1bpp 离屏显示设备
* 2. 创建 keypad 输入设备及默认输入组,用于菜单导航
* 3. 需在 lv_tick_inc/lv_timer_handler 被周期调用后方可刷新
*/
int ui_port_init(void);
/*
* 函数功能:获取内存帧缓冲首地址
* 入口参数:无
* 返回值:帧缓冲首地址 uint8_t * 固定长度 UI_FB_SIZE 字节
* 限定条件:ui_port_init() 已成功调用
* 函数说明:1. 帧缓冲由 flush 回调写入最新渲染结果
* 2. 供 RemoDispBus 服务端读取并推送至远端
*/
uint8_t *ui_port_get_framebuffer(void);
/*
* 函数功能:向输入队列喂入一个远端按键值
* 入口参数:key_val - 远端键码 uint8_t UI_KEY_* 取值之一
* 返回值:无
* 限定条件:无
* 函数说明:1. 将远端键码映射为 LVGL 按键后缓存
* 2. 由 keypad 读取回调在下次轮询时上报,驱动菜单导航
*/
void ui_port_queue_key(uint8_t key_val);
/*
* 函数功能:UI 周期步进(更新系统节拍并刷新 LVGL)
* 入口参数:tick_ms - 距上次调用的毫秒数 uint32_t 建议 10
* 返回值:无
* 限定条件:ui_port_init() 已成功调用
* 函数说明:1. 调用 lv_tick_inc 推进 LVGL 内部时钟
* 2. 调用 lv_timer_handler 处理重绘,结果经 flush 写入帧缓冲
* 3. 须由任务以固定周期调用,否则界面停止刷新
*/
void ui_port_step(uint32_t tick_ms);
/*
* 函数功能:立即消费队列中的待处理按键并让改动落屏(按键提速,2026-10-30)
* 入口参数:无
* 返回值:无
* 限定条件:ui_port_init() 已成功调用;与 ui_port_step 同一任务上下文
* 函数说明:1. 队列空 = 空操作(不触发输入读取)
* 2. 非空则立刻 lv_indev_read 派发键事件 + lv_refr_now 把脏区绘进
* 帧缓冲——调用方据此可在**同一拍**完成"注键→派发→重绘",
* 不等下一个 20 ms 输入轮询 / 刷新定时器(按键反馈提速 A 项)
* 3. 只消费队列头部一个键;连按时其余按键仍由周期轮询逐个派发
*/
void ui_port_service_keys(void);
#ifdef __cplusplus
}
#endif
#endif /* UI_PORT_H */