fix(wave): 回放页开页作废钉表重扫 + 判废串口逐次留痕(#93 F1/F2)
F1 开机后 FTP 新 STOR 段不进回放页钉住段表(#68 轮现场发现): 注入表新增第七件 wave_enter 作废钩子(纯内存零 I/O),页面 pg_init(方案 A)与空态左右键再探(方案 B)各调一次;重扫仍懒 在首帧绘制,开页链零 I/O 不破;页内普通按键不作废,2026-11-02 钉表防抖纪律零改动。manual_req 同族同纪律:段表与段头缓存一起 作废,同号覆盖不拿旧尺子量新段。 F2 数据 CRC 判废串口静默(同轮发现):ui_task_wave_load_head() 五类 BAD 出口(头解析/长度等式/窗读/尾读/CRC 不符)收敛为一条 `ui wave head idx=%u reject=%u stored=0x%04X calc=0x%04X`; reject=5 带 stored/calc 值对,与 PC 侧 wave_read REJECT 行同名 同值互证;reject 1..4 两字段 0 占位。ERROR 级、不判重(判废是 低频人工动作,逐次留痕),裁定与判读表随第二笔提交入手册 §3。 验证:keil 0 err 0 warn(ER_IROM1 285940 B,+224 B,内存两份 台账 --write 同步随本笔入库);ui-golden 菜单 8 态 + 内容页 74 张全过、录波回放三态像素零刷(模拟器假桩 no-op 即行为不变); 宿主 ui_data 295 / ui_sink 17 / wave_ring 113 / wave_store 170 / wave_trig 110 全绿。板级五项验收进行中,设计说明 §10 / 手册 §3-§4 修订与台账销项随第二笔。
This commit is contained in:
+85
-8
@@ -419,9 +419,12 @@ static const ui_soe_reader_t s_soe_reader = { ui_task_soe_count, ui_task_soe_get
|
||||
* 解码 40 点 + 逐点 code_to_milli 峰值扫描 40 次(int64 乘除,
|
||||
* 微秒级)——不是全段 8×320 扫描,回放页一屏只碰一个通道一窗;
|
||||
* - 纯内存不碰卷的路径(评审据此看最坏的落点):manual_req 只投一个
|
||||
* 请求字节;已缓存段的上下切道、左右切段的段号表环游;空态与坏态
|
||||
* 直接返回。所以最坏只落在「第一次进回放页 / 第一次切到未缓存段」
|
||||
* 这类一次性动作上,同段内连续按键不重复付 ②。
|
||||
* 请求字节;wave_enter 只翻两个作废旗标(#93 F1,不取锁不开盘);
|
||||
* 已缓存段的上下切道、左右切段的段号表环游;空态与坏态直接返回。
|
||||
* 所以最坏落在「进回放页(#93 F1 起每次开页都先作废、首帧付一次 ①,
|
||||
* 总额仍封死在首帧那一帧)/ 第一次切到未缓存段」这类一次性动作上,
|
||||
* 同段内连续按键不重复付 ②;空态再探盘的按键付 ①(方案 B 自带的
|
||||
* 语义——盘真 0 段时每次再探重扫正是该付的,成本有界在空态按键数)。
|
||||
* 没有实测数,上面是与落盘道同一把尺的**推算**:落盘道的告警线是
|
||||
* 50 ms / 21 次写,读路径无簇分配、不写 FAT 元数据,只会更便宜,故按
|
||||
* 同量级不高于它估——一次渲染最坏一窗 ≈ 段表 + 一段全验 + 一窗,仍远
|
||||
@@ -433,7 +436,8 @@ static const ui_soe_reader_t s_soe_reader = { ui_task_soe_count, ui_task_soe_get
|
||||
*/
|
||||
static uint8_t s_wave_idx[WAVE_ST_SEG_MAX]; /* 盘上现存段号升序表 */
|
||||
static uint8_t s_wave_cnt; /* 表内条数 */
|
||||
static uint8_t s_wave_scanned; /* 表是否有效(manual_req 后作废) */
|
||||
static uint8_t s_wave_scanned; /* 表是否有效(manual_req /
|
||||
* wave_enter 后作废,#93 F1) */
|
||||
static uint8_t s_wave_cached_idx; /* 段头缓存属于哪一段 */
|
||||
static uint8_t s_wave_cache_ok; /* 该段已验完整(头+数据 CRC) */
|
||||
static wave_seg_meta_t s_wave_meta; /* 已验段的头(172B,唯一驻留) */
|
||||
@@ -567,6 +571,18 @@ static uint8_t ui_task_wave_find(uint8_t a_idx, uint8_t *a_pos) {
|
||||
return 0u;
|
||||
}
|
||||
|
||||
/*
|
||||
* 判废原因码(#93 F2:ui_task_wave_load_head 五类 BAD 出口收敛成一条
|
||||
* 串口留痕,reject= 字段取值即本组宏)。值域是判读表与 PC 侧互证的
|
||||
* 接口的一部分:只增不改义。1 收「拿不到一个解析得动的头」的一切
|
||||
* (头窗读败 = 无从解析,与 head_parse 拒收、段长字段自相矛盾同族)。
|
||||
*/
|
||||
#define UI_WAVE_REJ_HEAD 1u /* 头窗读败 / head_parse 拒收 / seg_size 自相矛盾 */
|
||||
#define UI_WAVE_REJ_LEN 2u /* 长度等式不符(文件尺寸 != 头算出的整段尺寸) */
|
||||
#define UI_WAVE_REJ_WIN 3u /* 数据区流式读窗失败 */
|
||||
#define UI_WAVE_REJ_TAIL 4u /* 尾 2B(存储 CRC)读失败 */
|
||||
#define UI_WAVE_REJ_CRC 5u /* 数据 CRC 不符(留痕带 stored/calc,可与 PC 侧 wave_read REJECT 行对值互证) */
|
||||
|
||||
/*
|
||||
* 函数功能:读段并做完整性判定(头 CRC 由 head_parse 判,数据 CRC 流式判),
|
||||
* 成功则把段头留在 s_wave_meta 供 seg_win 免重读
|
||||
@@ -581,7 +597,10 @@ static uint8_t ui_task_wave_find(uint8_t a_idx, uint8_t *a_pos) {
|
||||
* 成本的代价换「CRC 不符必须拒收」永远现算,不做跨键存的位图
|
||||
* 函数说明:缓存命中(同段且已验)直接返 OK——左右切段回到上一段、上下切
|
||||
* 通道都靠它把重复的 5250B 全扫压成一次;文件读中途消失(被别的
|
||||
* 写者轮转掉)按 NONE 处理,页面下轮自然重扫
|
||||
* 写者轮转掉)按 NONE 处理,页面下轮自然重扫;五类判废(reject=
|
||||
* 原因码见上方 UI_WAVE_REJ_* 组)在本函数收尾统一收敛成一条
|
||||
* DBG_ERROR——只有串口在手的远程轮也要有判废可查面(#93 F2,
|
||||
* 电平与不判重两条裁定记录在设计说明 §10 的 2026-11-07 节)
|
||||
*/
|
||||
static int ui_task_wave_load_head(uint8_t a_idx) {
|
||||
static FIL f; /* static:FIL = 528B,理由同 soe_store_read */
|
||||
@@ -591,6 +610,11 @@ static int ui_task_wave_load_head(uint8_t a_idx) {
|
||||
FRESULT ofr; /* 开档 FR 码:开档失败留痕用 */
|
||||
UINT br = 0u;
|
||||
int rc;
|
||||
uint8_t reject = 0u; /* 判废原因码 UI_WAVE_REJ_*(#93 F2 留痕;
|
||||
* 0 = 没走到任何判废点。BAD 时必非 0) */
|
||||
uint16_t crc_stored = 0u; /* 仅 reject=UI_WAVE_REJ_CRC 时有值:与 PC 侧
|
||||
* wave_read REJECT 行互证的 stored/calc 对 */
|
||||
uint16_t crc_calc = 0u;
|
||||
|
||||
if ((s_wave_cache_ok != 0u) && (s_wave_cached_idx == a_idx)) {
|
||||
return UI_WAVE_OK;
|
||||
@@ -641,6 +665,7 @@ static int ui_task_wave_load_head(uint8_t a_idx) {
|
||||
fr = f_read(&f, s_wave_buf, n, &br);
|
||||
if ((fr != FR_OK) || (br != n)) {
|
||||
rc = UI_WAVE_BAD;
|
||||
reject = UI_WAVE_REJ_WIN;
|
||||
break;
|
||||
}
|
||||
crc = wave_store_crc_update(crc, s_wave_buf, n);
|
||||
@@ -649,14 +674,27 @@ static int ui_task_wave_load_head(uint8_t a_idx) {
|
||||
/* 第四步:读回存储值比对(低字节在前) */
|
||||
if ((rc == UI_WAVE_BAD) && (f_lseek(&f, size - 2u) == FR_OK) &&
|
||||
(f_read(&f, tail, 2u, &br) == FR_OK) && (br == 2u)) {
|
||||
if (crc == (uint16_t)(tail[0] | ((uint16_t)tail[1] << 8))) {
|
||||
uint16_t stored = (uint16_t)(tail[0] | ((uint16_t)tail[1] << 8));
|
||||
|
||||
if (crc == stored) {
|
||||
rc = UI_WAVE_OK;
|
||||
} else if (reject == 0u) {
|
||||
/* 窗读全程跑完还对不上才是真判废(stored/calc 对值得留
|
||||
* 给 wave_read 互证);窗已判废(REJ_WIN)时 crc 是半截
|
||||
* 值,既不覆原因也不留这对比值——免得互证对上一个假数 */
|
||||
reject = UI_WAVE_REJ_CRC;
|
||||
crc_calc = crc;
|
||||
crc_stored = stored;
|
||||
}
|
||||
} else if (reject == 0u) {
|
||||
reject = UI_WAVE_REJ_TAIL; /* 尾 2B 定位/读失败 */
|
||||
}
|
||||
} else if (total == 0u) {
|
||||
rc = UI_WAVE_BAD; /* seg_size 返 0 = 头字段自相矛盾,判废 */
|
||||
reject = UI_WAVE_REJ_HEAD;
|
||||
} else {
|
||||
rc = UI_WAVE_BAD; /* 长度与头部字段不符,判废 */
|
||||
reject = UI_WAVE_REJ_LEN;
|
||||
}
|
||||
(void)f_close(&f);
|
||||
}
|
||||
@@ -671,6 +709,21 @@ static int ui_task_wave_load_head(uint8_t a_idx) {
|
||||
* 没有任何视觉面——必须留痕(10-31 半轮栽就栽在这类静默面上) */
|
||||
DBG_ERROR("ui wave head idx=%u open fail fr=%d", (unsigned)a_idx,
|
||||
(int)ofr);
|
||||
} else if (rc == UI_WAVE_BAD) {
|
||||
/* #93 F2:五类判废出口(头/长度等式/窗/尾/CRC)收敛成这一条
|
||||
* 留痕——有画面在手判废有画面自证,只有串口在手的远程无人轮
|
||||
* 判废不留痕就是事后黑箱。BAD 不写 cache_ok = 每次进坏段都
|
||||
* 付一次完整校验,留痕与按键、画面一一对应,刻意**不判重**
|
||||
* ——判废是低频人工动作,逐次留痕正是取证要的东西(电平
|
||||
* ERROR + 不判重两条裁定见设计说明 §10 的 2026-11-07 节)。
|
||||
* reject= 原因码表与「reject!=5 时两个 CRC 字段恒 0x0000」
|
||||
* 判读口径见手册 §3;reject=5 的 stored/calc 与 PC 侧
|
||||
* wave_read 的 REJECT 行同名同值、可对值互证。[ERR] 会命中
|
||||
* /serial-boot-test 的 Forbidden 清单 → 坏段轮里按「预期内」
|
||||
* 点名放行(同手册),正常盘上本行一条都不会出现 */
|
||||
DBG_ERROR("ui wave head idx=%u reject=%u stored=0x%04X calc=0x%04X",
|
||||
(unsigned)a_idx, (unsigned)reject,
|
||||
(unsigned)crc_stored, (unsigned)crc_calc);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
@@ -698,6 +751,29 @@ static int ui_task_wave_manual_req(void) {
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:回放页开页 / 空态再探盘的作废钩子——作废段表与段头缓存
|
||||
* (#93 F1 方案 A/B;与 manual_req 受理支同一条作废纪律,字段
|
||||
* 契约见 ui_data.h wave_enter 注)
|
||||
* 入口参数:无
|
||||
* 返回值:无
|
||||
* 限定条件:uiTask(页面框架 init_cb / key_cb 链都跑在本任务上;作废的
|
||||
* 是本任务私有缓存,无锁无竞态);纯内存零 I/O,开页链不破
|
||||
* 函数说明:只翻旗标不重扫——重扫仍懒在 ui_task_wave_table() 首次取数。
|
||||
* manual_req 的作废盖「本机自己新落段」,本件盖「别的写者
|
||||
* (FTP STOR)在上次开页之后投放的新段」:11-02 把钉表防抖立
|
||||
* 成纪律时把这两种情形一起钉死了,开页因此看不见新段(#93 F1
|
||||
* 发现面)。页内普通按键**不调本件** = 防抖纪律原样保留;空
|
||||
* 态左右键调(方案 B)只在盘真 0 段时逐次重探——「新段可能已
|
||||
* 落」这条注释里写了一直没机制兑现的语义从此有兑现。残留纪律
|
||||
* (手册 §4 / 设计说明 §10 留痕):**页开着时**投放的段要再开
|
||||
* 一次页才可见,页开着追新段本波不做
|
||||
*/
|
||||
static void ui_task_wave_enter(void) {
|
||||
s_wave_scanned = 0u;
|
||||
s_wave_cache_ok = 0u;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:取盘上「数值最大段号」(回放页开屏落点)
|
||||
* 入口参数:a_idx - 出参段号
|
||||
@@ -903,9 +979,10 @@ static int ui_task_wave_seg_win(uint8_t a_idx, uint8_t a_ch,
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* 录波通道函数表(六件齐全;ui_data_wave_bind 拒绝残表,缺件就是装配错) */
|
||||
/* 录波通道函数表(七件齐全;ui_data_wave_bind 拒绝残表,缺件就是装配错) */
|
||||
static const ui_data_wave_ops_t s_wave_ops = {
|
||||
ui_task_wave_manual_req,
|
||||
ui_task_wave_enter,
|
||||
ui_task_wave_seg_first,
|
||||
ui_task_wave_seg_prev,
|
||||
ui_task_wave_seg_next,
|
||||
@@ -1014,7 +1091,7 @@ void ui_task_func(void *argument) {
|
||||
DBG_ERROR("UI maint bind: FAIL");
|
||||
}
|
||||
/* 录波通道注入(故障录波道 UI 侧,2026-10-29):手动录波触发页与回放页
|
||||
* 的唯一数据入口,同样先于 ui_menu_init。未注入窗口里六件按「无录波段」
|
||||
* 的唯一数据入口,同样先于 ui_menu_init。未注入窗口里七件按「无录波段」
|
||||
* 空态渲染(不画线、不崩);残表 = 装配错,启动日志必须可见 */
|
||||
if (ui_data_wave_bind(&s_wave_ops) != 0) {
|
||||
DBG_ERROR("UI wave bind: FAIL");
|
||||
|
||||
Reference in New Issue
Block a user