UI 内容页框架加实时页自动刷新机制(交流量页启用,300ms)
- ui_content_page:描述符尾部追加 auto_ms/auto_seq 可选字段(缺省=0/NULL= 旧行为逐位不变);页打开期间框架持一只 lv_timer,仅当发布序号变过才整页 失效(零空转失效),关页即销;新 API ui_content_page_auto_poll - ui_page_ac.c:.auto_ms=300(≥200ms 发布节拍、避 400=2×200 锁相、300= 15×20ms LVGL 整刷周期;最坏屏上滞后 500ms;完整取值账目在代码注释) - simulator:rt 帧装配收口 sim_fill_rt_frame(n=0 冻结帧保 74 张黄金逐字节 一致,n≥1 确定性斜坡);新增 --rtlive 两态自检 + 窗口模式 200ms 节拍发布; check_content_pages.py 增 [rtlive] 零按键 A≠B 落屏断言 - docs/UI设计:供给说明新增 §5.5 自动刷新口径;内容页架构 §3.1/§四/§九 同步 (并修正 s_open 判定旧描述) - 台账:Keil 构建后按固定顺序回填(Code=256,588 / RW_IRAM1 +8B / UI +8B) 验证:模拟器 0错0警;菜单 8 状态 + 内容页 74 张 + rtlive(A≠B 30 字节)PASS (lead 独立复跑 RC=0);Keil 0错0警;mem-budget --gate / mem-numbers --scan 绿。
This commit is contained in:
+200
-84
@@ -6,6 +6,8 @@
|
||||
* 创建日期:2026-08-31
|
||||
* 修改记录:
|
||||
* v1.0 2026-08-31 王建锋 创建:基于 lv_port_pc_vscode 适配
|
||||
* v1.1 2026-11-13 DTU 项目组 task-2:rt 帧装配收口成 sim_fill_rt_frame 唯一装配口 +
|
||||
* --rtlive 两态自检 + 窗口模式 200ms 节拍重发 live 帧
|
||||
*
|
||||
* @file main.c
|
||||
* @brief LVGL 模拟器入口 — 160x160 1bpp 单色菜单 UI
|
||||
@@ -26,6 +28,13 @@
|
||||
* seq 字符:u=↑ d=↓ l=← r=→ e=Enter s=Esc(其余字符忽略)
|
||||
* 每键经 lv_group_send_data 注入(与 keypad 输入设备同路径),驱动 5 帧后取快照
|
||||
*
|
||||
* 实时页自动刷新自检模式(无窗口,两态比对,退出码 0=两枪都出图):
|
||||
* lvgl_sim.exe --rtlive <seq> shotA.bin shotB.bin
|
||||
* 先注键开到目标页拍 A(冻结帧 n=0);随后发布一帧确定性斜坡帧(仿真设备还在
|
||||
* 采集,发布序号前进)并直调生产判定体 ui_content_page_auto_poll(无头无定时器
|
||||
* 节拍,直调顶替),再拍 B。A 不等于 B 逐字节成立 = 不按任何键,新数据照样刷屏;
|
||||
* 像素差异断言在 simulator/tests/check_content_pages.py 里做
|
||||
*
|
||||
* 配置轮询自检模式(无窗口、进程内闭环、退出码 0=PASS / 非0=FAIL):
|
||||
* lvgl_sim.exe --cfgtest
|
||||
* 验证链:net_cfg_load(只读 INI;旧 NCFG 档迁移已于 2026-10-10 删除)
|
||||
@@ -64,6 +73,7 @@
|
||||
#include "sim_port.h"
|
||||
#include "ui_menu.h"
|
||||
#include "ui_standby.h"
|
||||
#include "ui_content_page.h" /* task-2:--rtlive 直调框架自动刷新判定体 */
|
||||
#include "ui_net_sink.h"
|
||||
#include "net_cfg.h"
|
||||
#include "cfg_file.h"
|
||||
@@ -972,6 +982,123 @@ static void sim_publish_par_frame(void) {
|
||||
s_par_pub_sum = par.checksum;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:组装一帧 rt 快照——黄金冻结帧(n=0)与 live 斜坡帧(n>=1)共用这唯一
|
||||
* 装配口,仿真假数据不存在第二份
|
||||
* 入口参数:p_rt - 目标帧(调用方持有,本函数先整帧清零) ui_data_rt_t *
|
||||
* n - 帧号;0 = 黄金冻结帧(逐字节等于重构前,74 张黄金参考建立在
|
||||
* 它上面),>0 = 确定性斜坡帧(三角波 0..5..0 周期 11 帧,无随机,
|
||||
* 仅 --rtlive 自检与窗口模式节拍使用) uint32_t
|
||||
* 返回值:无
|
||||
* 限定条件:--noclock / --epoch 形态旗标已就位(时钟段读它们)
|
||||
* 函数说明:随 n 变的只有显示相关字段(相量/遥测/tick/墙钟秒),品质位与遥信位图
|
||||
* 原样冻结——模拟的是设备还在采集,不是设备自己变坏了
|
||||
*/
|
||||
static void sim_fill_rt_frame(ui_data_rt_t *p_rt, uint32_t n) {
|
||||
uint8_t i;
|
||||
|
||||
(void)memset(p_rt, 0, sizeof(*p_rt));
|
||||
p_rt->valid = 1u;
|
||||
p_rt->eng = UI_DATA_ENG_PIN;
|
||||
p_rt->tick_ms = 0u;
|
||||
/* 遥测下标 = adc_semantic_t 语义序(UA/UB/UC/UN/IA/IB/IC/IN/TEMP)。
|
||||
* 模拟器不 include adc_input.h,故这里用语义序注释对照,不写符号名 */
|
||||
p_rt->yc[0].val = 0.8123f; /* UA 基波(引脚电压域) */
|
||||
p_rt->yc[0].qds = 0u;
|
||||
p_rt->yc[1].val = 0.0f; /* UB:V0.1 硬件削顶无采样源 */
|
||||
p_rt->yc[1].qds = UI_DATA_Q_IV | UI_DATA_Q_OV;
|
||||
p_rt->yc[2].qds = UI_DATA_Q_IV | UI_DATA_Q_OV; /* UC 同上 */
|
||||
p_rt->yc[3].val = 0.0054f; /* UN 零序电压基波 */
|
||||
p_rt->yc[3].qds = 0u;
|
||||
p_rt->yc[4].val = 0.0456f; /* IA 基波 */
|
||||
p_rt->yc[4].qds = 0u;
|
||||
p_rt->yc[5].qds = UI_DATA_Q_IV | UI_DATA_Q_OV; /* IB */
|
||||
p_rt->yc[6].qds = UI_DATA_Q_IV | UI_DATA_Q_OV; /* IC */
|
||||
p_rt->yc[7].qds = UI_DATA_Q_IV | UI_DATA_Q_OV; /* IN */
|
||||
p_rt->yc[8].val = 2048.0f; /* TEMP:码值(不参与线性标定) */
|
||||
p_rt->yc[8].qds = UI_DATA_Q_RAW;
|
||||
/* 相量实例槽(序 = phasor k_inst[]:IA-F1/UA-F1/UN-F1/IA-F2/IA-F5) */
|
||||
p_rt->ph_n = 5u;
|
||||
p_rt->ph[0].val = 0.0456f;
|
||||
p_rt->ph[1].val = 0.8123f;
|
||||
p_rt->ph[2].val = 0.0054f;
|
||||
p_rt->ph[3].val = 0.0017f; /* IA 二次谐波(涌流制动监视量) */
|
||||
p_rt->ph[4].val = 0.0008f; /* IA 五次谐波(选线用) */
|
||||
for (i = 0u; (i < UI_DATA_PH_MAX) && (i < p_rt->ph_n); i++) {
|
||||
p_rt->ph[i].qds = 0u;
|
||||
}
|
||||
for (; i < UI_DATA_PH_MAX; i++) {
|
||||
p_rt->ph[i].qds = UI_DATA_Q_IV; /* 未发布的槽:无效,页面显示 "--" */
|
||||
}
|
||||
p_rt->yx_bits = 0u; /* 固定帧无动作态 */
|
||||
p_rt->yx_valid = 0x4043C000ULL; /* YX15~18/23/31 有效位图(与点表同集合) */
|
||||
/* 双点位图照写侧口径给(App/protocol/iec104/iec104_pts.c 的 YX_DP_N = 4 → bit0~3)。
|
||||
* 这 4 点**不在**上面的有效位图里(V0.1 无开入硬件),所以遥信页对它们打 "--"——
|
||||
* 刻意不把 bit0 塞进 yx_valid 让画面多两个汉字好看:那会让黄金参考显示成"这台设备
|
||||
* 有开关位置遥信",而真机上没有(屏上的话必须与本机一致,同页脚页码那条裁定) */
|
||||
p_rt->yx_dp = 0x0FULL;
|
||||
p_rt->freq_valid = 0u; /* eng=0 期间幅值门恒失效 → 无新鲜读数 */
|
||||
p_rt->freq_hz = 0.0f;
|
||||
/* 墙钟两态(道F task-3):--noclock 把这台机器装成"RTC 异常/未对时"——只有
|
||||
* 这样才照得到时钟设置页的 "--" + "无时钟"徽标形态;面板设过时以面板值为准,
|
||||
* 这就是页面上"回读证据"的唯一来源(真机那边是 SD2506 回读 + 快照层重发) */
|
||||
p_rt->clock_ok = (s_noclock == 0) ? 1u : 0u;
|
||||
if (s_noclock != 0) {
|
||||
p_rt->clock[0] = 0; /* 无效时标 = 空串(页面据此显 "--",绝不显 1970) */
|
||||
} else if (s_sim_epoch != 0u) {
|
||||
ui_data_clock_t ck;
|
||||
|
||||
if (ui_data_clock_from_epoch(s_sim_epoch, &ck) == 0) {
|
||||
(void)ui_data_clock_format(&ck, p_rt->clock, sizeof(p_rt->clock));
|
||||
} else {
|
||||
p_rt->clock[0] = 0;
|
||||
p_rt->clock_ok = 0u;
|
||||
}
|
||||
} else {
|
||||
(void)snprintf(p_rt->clock, sizeof(p_rt->clock), "%s", "2026-10-25 08:00:00");
|
||||
}
|
||||
|
||||
/* live 斜坡(n=0 完全不进本段:黄金像素逐位不变)。三角波避免单调漂移——窗口
|
||||
* 模式跑多久数值域都有界;相量实例与对应遥测写同值(镜像 App/app/ui_data_feed.c
|
||||
* 的同源纪律)。freq 保持 freq_valid=0:eng=0 期间幅值门恒失效,不为了让 Hz 行
|
||||
* 看着在动就伪造新鲜读数 */
|
||||
if (n != 0u) {
|
||||
uint32_t k = n % 11u;
|
||||
uint32_t s = (k <= 5u) ? k : (10u - k);
|
||||
float f = (float)s;
|
||||
|
||||
p_rt->tick_ms = n * 200u;
|
||||
p_rt->yc[0].val = 0.8123f + (0.0020f * f);
|
||||
p_rt->yc[3].val = 0.0054f + (0.0002f * f);
|
||||
p_rt->yc[4].val = 0.0456f + (0.0004f * f);
|
||||
p_rt->ph[0].val = p_rt->yc[4].val;
|
||||
p_rt->ph[1].val = p_rt->yc[0].val;
|
||||
p_rt->ph[2].val = p_rt->yc[3].val;
|
||||
p_rt->ph[3].val = 0.0017f + (0.0001f * f);
|
||||
p_rt->ph[4].val = 0.0008f + (0.0001f * f);
|
||||
if ((p_rt->clock_ok != 0u) && (p_rt->clock[0] != (char)0) && (s_sim_epoch == 0u)) {
|
||||
(void)snprintf(p_rt->clock, sizeof(p_rt->clock), "2026-10-25 08:00:%02u",
|
||||
(unsigned int)(n % 60u));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:发布一帧 live 斜坡快照(--rtlive 自检与窗口模式节拍共用;真机对应
|
||||
* App/app/ui_data_feed.c 的 200ms 发布拍)
|
||||
* 入口参数:n - 帧号(>=1;0 是冻结帧,只由 sim_publish_data_frames 开局发一次) uint32_t
|
||||
* 返回值:无
|
||||
* 限定条件:ui_data_init() 之后
|
||||
* 函数说明:ui_data_publish_rt 自带发布序号前进——这正是内容页框架自动失效的触发
|
||||
* 源(序号变过才整页失效,见 ui_content_page_auto_poll)
|
||||
*/
|
||||
static void sim_publish_rt_live(uint32_t n) {
|
||||
ui_data_rt_t rt;
|
||||
|
||||
sim_fill_rt_frame(&rt, n);
|
||||
(void)ui_data_publish_rt(&rt);
|
||||
}
|
||||
|
||||
static void sim_publish_data_frames(void) {
|
||||
ui_data_rt_t rt;
|
||||
ui_data_info_t info;
|
||||
@@ -979,68 +1106,10 @@ static void sim_publish_data_frames(void) {
|
||||
|
||||
ui_data_init();
|
||||
|
||||
(void)memset(&rt, 0, sizeof(rt));
|
||||
rt.valid = 1u;
|
||||
rt.eng = UI_DATA_ENG_PIN;
|
||||
rt.tick_ms = 0u;
|
||||
/* 遥测下标 = adc_semantic_t 语义序(UA/UB/UC/UN/IA/IB/IC/IN/TEMP)。
|
||||
* 模拟器不 include adc_input.h,故这里用语义序注释对照,不写符号名 */
|
||||
rt.yc[0].val = 0.8123f; /* UA 基波(引脚电压域) */
|
||||
rt.yc[0].qds = 0u;
|
||||
rt.yc[1].val = 0.0f; /* UB:V0.1 硬件削顶无采样源 */
|
||||
rt.yc[1].qds = UI_DATA_Q_IV | UI_DATA_Q_OV;
|
||||
rt.yc[2].qds = UI_DATA_Q_IV | UI_DATA_Q_OV; /* UC 同上 */
|
||||
rt.yc[3].val = 0.0054f; /* UN 零序电压基波 */
|
||||
rt.yc[3].qds = 0u;
|
||||
rt.yc[4].val = 0.0456f; /* IA 基波 */
|
||||
rt.yc[4].qds = 0u;
|
||||
rt.yc[5].qds = UI_DATA_Q_IV | UI_DATA_Q_OV; /* IB */
|
||||
rt.yc[6].qds = UI_DATA_Q_IV | UI_DATA_Q_OV; /* IC */
|
||||
rt.yc[7].qds = UI_DATA_Q_IV | UI_DATA_Q_OV; /* IN */
|
||||
rt.yc[8].val = 2048.0f; /* TEMP:码值(不参与线性标定) */
|
||||
rt.yc[8].qds = UI_DATA_Q_RAW;
|
||||
/* 相量实例槽(序 = phasor k_inst[]:IA-F1/UA-F1/UN-F1/IA-F2/IA-F5) */
|
||||
rt.ph_n = 5u;
|
||||
rt.ph[0].val = 0.0456f;
|
||||
rt.ph[1].val = 0.8123f;
|
||||
rt.ph[2].val = 0.0054f;
|
||||
rt.ph[3].val = 0.0017f; /* IA 二次谐波(涌流制动监视量) */
|
||||
rt.ph[4].val = 0.0008f; /* IA 五次谐波(选线用) */
|
||||
for (i = 0u; (i < UI_DATA_PH_MAX) && (i < rt.ph_n); i++) {
|
||||
rt.ph[i].qds = 0u;
|
||||
}
|
||||
for (; i < UI_DATA_PH_MAX; i++) {
|
||||
rt.ph[i].qds = UI_DATA_Q_IV; /* 未发布的槽:无效,页面显示 "--" */
|
||||
}
|
||||
rt.yx_bits = 0u; /* 固定帧无动作态 */
|
||||
rt.yx_valid = 0x4043C000ULL; /* YX15~18/23/31 有效位图(与点表同集合) */
|
||||
/* 双点位图照写侧口径给(App/protocol/iec104/iec104_pts.c 的 YX_DP_N = 4 → bit0~3)。
|
||||
* 这 4 点**不在**上面的有效位图里(V0.1 无开入硬件),所以遥信页对它们打 "--"——
|
||||
* 刻意不把 bit0 塞进 yx_valid 让画面多两个汉字好看:那会让黄金参考显示成"这台设备
|
||||
* 有开关位置遥信",而真机上没有(屏上的话必须与本机一致,同页脚页码那条裁定) */
|
||||
rt.yx_dp = 0x0FULL;
|
||||
rt.freq_valid = 0u; /* eng=0 期间幅值门恒失效 → 无新鲜读数 */
|
||||
rt.freq_hz = 0.0f;
|
||||
/* 墙钟两态(道F task-3):--noclock 把这台机器装成"RTC 异常/未对时"——只有
|
||||
* 这样才照得到时钟设置页的 "--" + "无时钟"徽标形态;面板设过时以面板值为准,
|
||||
* 这就是页面上"回读证据"的唯一来源(真机那边是 SD2506 回读 + 快照层重发) */
|
||||
rt.clock_ok = (s_noclock == 0) ? 1u : 0u;
|
||||
if (s_noclock != 0) {
|
||||
rt.clock[0] = 0; /* 无效时标 = 空串(页面据此显 "--",绝不显 1970) */
|
||||
} else if (s_sim_epoch != 0u) {
|
||||
ui_data_clock_t ck;
|
||||
|
||||
if (ui_data_clock_from_epoch(s_sim_epoch, &ck) == 0) {
|
||||
(void)ui_data_clock_format(&ck, rt.clock, sizeof(rt.clock));
|
||||
} else {
|
||||
rt.clock[0] = 0;
|
||||
rt.clock_ok = 0u;
|
||||
}
|
||||
} else {
|
||||
(void)snprintf(rt.clock, sizeof(rt.clock), "%s", "2026-10-25 08:00:00");
|
||||
}
|
||||
sim_fill_rt_frame(&rt, 0u); /* 冻结帧:黄金基准,装配与斜坡逻辑见 sim_fill_rt_frame */
|
||||
(void)ui_data_publish_rt(&rt);
|
||||
|
||||
|
||||
/* 定值帧:出厂默认 + 封存(幂等),再按 prot_set 现状发一帧(见上面两个函数) */
|
||||
(void)prot_set_init();
|
||||
sim_publish_par_frame();
|
||||
@@ -1153,14 +1222,49 @@ static void sim_param_pump(void) {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:把当前屏快照(I1)写成像素文件(run_headless 首枪与 --rtlive 第二枪共用)
|
||||
* 入口参数:path - 输出文件路径(写入 160x160 I1 原始像素) const char *
|
||||
* 返回值:0 - 成功;1 - 快照失败或文件打不开 int
|
||||
* 限定条件:离屏显示与目标屏已就绪(无头上下文内调用)
|
||||
* 函数说明:I1 缓冲区布局 [palette 8B][pixel data],跳调色板只写像素;快照即整屏
|
||||
* 同步重渲,不依赖 lv_timer_handler(无头禁驱动帧循环的纪律不变)
|
||||
*/
|
||||
static int snap_to_file(const char *path) {
|
||||
lv_draw_buf_t *snap = lv_snapshot_take(lv_screen_active(), LV_COLOR_FORMAT_I1);
|
||||
if (snap == NULL) {
|
||||
fprintf(stderr, "[shot] snapshot failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t snap_w = snap->header.w;
|
||||
uint32_t snap_h = snap->header.h;
|
||||
uint32_t pal_bytes = LV_COLOR_INDEXED_PALETTE_SIZE(LV_COLOR_FORMAT_I1) * (uint32_t)sizeof(lv_color32_t);
|
||||
const uint8_t * px = snap->data + pal_bytes; /* 只读:写文件时不再改动快照 */
|
||||
uint32_t px_bytes = (uint32_t)snap->header.stride * (uint32_t)snap_h;
|
||||
FILE *fp = fopen(path, "wb");
|
||||
if (fp == NULL) {
|
||||
lv_draw_buf_destroy(snap);
|
||||
fprintf(stderr, "fopen failed: %s\n", path);
|
||||
return 1;
|
||||
}
|
||||
size_t wn = fwrite(px, 1, px_bytes, fp);
|
||||
fclose(fp);
|
||||
lv_draw_buf_destroy(snap);
|
||||
printf("screenshot: %s (%zu bytes, %ux%u I1)\n", path, wn, snap_w, snap_h);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:无窗口离屏渲染(可注入键序列)并导出末帧像素
|
||||
* 入口参数:keys - 键序列(u=上 d=下 l=左 r=右 e=确认 s=返回;空 = 不注键) const char *
|
||||
* path - 输出文件(写入 160x160 I1 原始像素) const char *
|
||||
* standby - 非 0 = 注键后强制进入待机屏再截图(--standby 模式) int
|
||||
* path_b - 非 NULL = --rtlive 模式:A 枪出图后发布一帧 live 斜坡帧并直调
|
||||
* 框架自动刷新判定体,再拍 B 写到本路径 const char *
|
||||
* 返回值:0 - 成功;非 0 - 失败 int
|
||||
*/
|
||||
static int run_headless(const char * keys, const char * path, int standby) {
|
||||
static int run_headless(const char * keys, const char * path, int standby, const char * path_b) {
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
lv_init();
|
||||
lv_delay_set_cb(shot_delay_cb);
|
||||
@@ -1256,28 +1360,24 @@ static int run_headless(const char * keys, const char * path, int standby) {
|
||||
(unsigned)(mon.total_size - mon.free_size), (unsigned)mon.free_size);
|
||||
|
||||
/* 用 snapshot 把整屏渲进独立 I1 draw_buf(避开 I1+FULL 的渲染死循环) */
|
||||
lv_draw_buf_t *snap = lv_snapshot_take(lv_screen_active(), LV_COLOR_FORMAT_I1);
|
||||
if (snap == NULL) {
|
||||
fprintf(stderr, "[shot] snapshot failed\n");
|
||||
return 1;
|
||||
int rc = snap_to_file(path);
|
||||
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
uint32_t snap_w = snap->header.w;
|
||||
uint32_t snap_h = snap->header.h;
|
||||
/* I1 缓冲区布局:[palette 8B][pixel data],跳过 palette 只写像素 */
|
||||
uint32_t pal_bytes = LV_COLOR_INDEXED_PALETTE_SIZE(LV_COLOR_FORMAT_I1) * (uint32_t)sizeof(lv_color32_t);
|
||||
const uint8_t * px = snap->data + pal_bytes; /* 只读:写文件时不再改动快照 */
|
||||
uint32_t px_bytes = (uint32_t)snap->header.stride * (uint32_t)snap_h;
|
||||
FILE *fp = fopen(path, "wb");
|
||||
if (fp == NULL) {
|
||||
lv_draw_buf_destroy(snap);
|
||||
fprintf(stderr, "fopen failed: %s\n", path);
|
||||
return 1;
|
||||
/* --rtlive 第二枪:发布前进过序号的 live 斜坡帧后,无头没有定时器节拍,
|
||||
* 直调生产判定体 ui_content_page_auto_poll 顶替——它就是板端定时器回调里
|
||||
* 跑的同一份代码;"数据变过才失效"的判定与真机逐句相同 */
|
||||
if (path_b != NULL) {
|
||||
sim_publish_rt_live(1u);
|
||||
ui_content_page_auto_poll();
|
||||
rc = snap_to_file(path_b);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
printf("rtlive: frames written (A=%s B=%s)\n", path, path_b);
|
||||
}
|
||||
size_t n = fwrite(px, 1, px_bytes, fp);
|
||||
fclose(fp);
|
||||
lv_draw_buf_destroy(snap);
|
||||
printf("screenshot: %s (%zu bytes, %ux%u I1)\n", path, n, snap_w, snap_h);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1624,7 +1724,7 @@ static int run_logtest(void) {
|
||||
* 函数功能:模拟器入口(解析模式开关 → 窗口模式或无头自检)
|
||||
* 入口参数:argc - 参数个数 int
|
||||
* argv - 参数数组(--screenshot / --keys / --standby / --cfgtest /
|
||||
* --logtest / --idle / --noclock) char **
|
||||
* --logtest / --idle / --noclock / --rtlive) char **
|
||||
* 返回值:0 - 正常退出或自检 PASS;非 0 - 失败 int
|
||||
*/
|
||||
int main(int argc, char **argv) {
|
||||
@@ -1652,13 +1752,16 @@ int main(int argc, char **argv) {
|
||||
/* 截图/自检模式:--screenshot / --keys / --standby / --cfgtest / --logtest */
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "--screenshot") == 0 && (i + 1) < argc) {
|
||||
return run_headless("", argv[i + 1], 0);
|
||||
return run_headless("", argv[i + 1], 0, NULL);
|
||||
}
|
||||
if (strcmp(argv[i], "--keys") == 0 && (i + 2) < argc) {
|
||||
return run_headless(argv[i + 1], argv[i + 2], 0);
|
||||
return run_headless(argv[i + 1], argv[i + 2], 0, NULL);
|
||||
}
|
||||
if (strcmp(argv[i], "--standby") == 0 && (i + 1) < argc) {
|
||||
return run_headless("", argv[i + 1], 1);
|
||||
return run_headless("", argv[i + 1], 1, NULL);
|
||||
}
|
||||
if (strcmp(argv[i], "--rtlive") == 0 && (i + 3) < argc) {
|
||||
return run_headless(argv[i + 1], argv[i + 2], 0, argv[i + 3]);
|
||||
}
|
||||
if (strcmp(argv[i], "--cfgtest") == 0) {
|
||||
return run_cfgtest();
|
||||
@@ -1759,6 +1862,11 @@ int main(int argc, char **argv) {
|
||||
/* 配置文件轮询起点(2s 周期,与 MCU netTask 一致) */
|
||||
uint32_t cfg_last_poll = (uint32_t)SDL_GetTicks();
|
||||
|
||||
/* rt live 节拍(窗口模式实时演示):镜像板端 ui_data_feed 的 200ms 发布拍;
|
||||
* 无头回归模式根本不走本循环——黄金参考永远建立在冻结帧 n=0 上 */
|
||||
uint32_t rt_last_pub = cfg_last_poll;
|
||||
uint32_t rt_live_n = 0u;
|
||||
|
||||
/* 主循环:驱动 LVGL 定时器与刷新
|
||||
* 注意:SDL 事件(键盘/窗口/退出)由 LVGL SDL 驱动内部 5ms 定时器
|
||||
* (lv_sdl_window.c 的 sdl_event_handler)统一轮询分发,
|
||||
@@ -1791,6 +1899,14 @@ int main(int argc, char **argv) {
|
||||
cfg_file_poll();
|
||||
}
|
||||
|
||||
/* rt 帧按拍重发(窗口实时演示,板端 feed 同款 200ms 拍):确定性斜坡帧、
|
||||
* 无随机;发布序号前进后,实时页由内容页框架自动失效定时器刷屏——
|
||||
* 打开交流量页不按键即可看到数值自己走 */
|
||||
if ((uint32_t)(now_ms - rt_last_pub) >= 200u) {
|
||||
rt_last_pub = now_ms;
|
||||
sim_publish_rt_live(++rt_live_n);
|
||||
}
|
||||
|
||||
/* 驱动 LVGL 定时器与刷新 */
|
||||
uint32_t sleep_ms = lv_timer_handler();
|
||||
if (sleep_ms == LV_NO_TIMER_READY) {
|
||||
|
||||
Reference in New Issue
Block a user