/* * 模块名称:UI Display Port (LVGL 离屏显示端口) * 模块功能:提供 LVGL 1bpp 离屏渲染端口与远程 keypad 输入设备 * 适用平台:STM32F407ZGTx * 作者:王建锋 * 创建日期:2026-08-29 * 修改记录: * 2026-08-29 王建锋 创建初始版本 */ #ifndef UI_PORT_H #define UI_PORT_H #include #include #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 */