feat(wave): 故障录波数据面、接线与单通道回放页(软件闭环交付)
数据面(App/algo,纯逻辑,双端编译) - wave_ring:8 路 × 320 点列优先环(1 kHz,预触发 160 + 后触发 160),adcTask 唯一写者;触发/冻结/封存/冷却四态,冻结持续到落盘回执才解冻,滞留 2 s 自弃 兜底——下一次真故障无波可录比丢一段更贵 - wave_store:段头编解码 + 拉模式打包游标 + 自带无表位运算 CRC-16/MODBUS(带 锚点自检)+ 段名与整段长度等式;格式不依赖平台类型宽度 - 段头只存原始码值与封存瞬间生效系数,工程量只当单位标签、不进任何算式 - 三套主机单测(环 113 / 编解码 170 / 触发状态机 110),全部无桩、生产源原样 纳入;新文件补 stddef 是 ARMCC 与主机差异,主机侧照不出这条分叉 - test/host/wave_read.py 是按 §6.2 的独立第二实现(dump/fft/shape/plot),92 条 自洽断言;三份合成段互读双校验全过、哈希钉死,格式面双向闭合 - 三套新单测不加专属钩子,由覆盖率总闸全量真跑(沿用既有裁定) 接线(任务层) - adc_cal:新增生效系数的 32 位定点原值入口(与既有浮点入口共用生效视图), 段头按最低有效位精确记账,不经浮点回算 - adcTask:每拍压 8 路语义原始码值并推进状态机,封存那一拍同拍交棒封存瞬间事实; 台架定周期自抓走双层编译门,产品镜像里零存在;串口新增一条 wave: 周期行 - defaultTask:卷空闲后一次心跳整段搬完(try 锁 + 256 字节分片 + 一次完整开档到 关档),成败都回执;失败先删半成品再计错,段号只在成功时推进;持锁超 50 ms 补一条告警并记历史峰值(喂狗余量可核) - Lead 复核补第四道并发陷阱:采集任务优先级高于落盘道,搬段中途它可能正好把滞留 超时的本段自弃、甚至封出下一段——数据区校验和是对「实际读到的字节」算的, 半新半旧的段照样自洽,故关档后复检环侧身份判废:删文件、不补账、段号不推进 - Lead 复核抓到触发挂号不是原子操作(旧实现分三个字节写,消费者可在窗口里读到 上一段的触发源与元件号):已把载荷压进一个字节,越界当场拒且不记任何计数; 段文件字节布局零改动,三份合成段哈希逐字节不变 - protectTask:保护启动上升沿同点请求录波,一拍一次、元件号取最低位;判据本体 零改动 人机(160×160 单色屏) - 菜单树节点 26「手动录波」绑页面 + 记录查询组末新增「录波回放」叶,重跑生成器 得 43 节点 / 34 叶 / 30 已绑,页面映射 28 → 30 - 回放页一屏一路、触发点前后各一周波共 40 点、每点 3 像素阶梯线(只用水平与 垂直两种线段——单色屏斜线会被阈值裁掉);零点虚线、触发光标、窗口峰值、 单位徽标与形状受限徽标;空态与坏段各一句显式文案,绝不用半截波形冒充数据 - ui_data 新增录波注入通道(六件操作表、三态返回);执行侧胶水带段头缓存、 手动请求后连缓存一起作废、逐点走全仓唯一的码值换算入口 - 模拟器接真实环与编解码合成两段(含坏段与空态旗标),6 张新黄金参考,既有 60 张逐字节零漂移未用更新模式;字库 218 → 224 字 / 319 字形 - 两份图形配置里图表组件仍为关;零堆分配;页面池水位不变 - 回放读路径的 uiTask 阻塞上界按实码写清:一次渲染 = 段表刷新 + 未缓存段头最坏 22 次小读;已验段只剩一次开窗读 + 40 点解码;无实测数不编,实测归台架、 仪器用已在跑的单轮工作耗时探针,不新加埋点 台账与文档 - 内存台账:录波环与落盘/回放静态逐条入册,三档对照 81,536 → 88,296 → 89,936 字节(62.2% → 68.6%),累计 +8,400;预估 5.9 KB 与实测 +6,760 的差额点名; 散列文件头注释同步;任务栈表核对后无需抬栈;体积趋势行与同码凭证由权威构建 重打(0 错误 0 警告,四项体积与上一轮相同——本轮改动只有注释与声明位置) - 设计说明:§5 补第四条并发陷阱;§6.3 定字段口径(两份独立实现的共同依据); §7 回填实测;§9 周期行写实;§10 台架判据改两段式且不比绝对相位;§12 补读路径 风险行;抬头状态改成「代码面已交付、未做完的只有板级那一轮」 - 卡片:软件闭环一栏列证据;台架三条按用户裁定保持未完成,不做虚假销项 - 口径同步:数据可信、UI 补齐、页面补齐规划、产品需求、采集短板评测、任务规划 索引与两份 README;陈旧现状句清扫 16 处(带日期戳的历史取数行一律不动) - 门禁说明:nested-comment 记仓库根探测必须兼容 linked worktree 的 gitdir 文件 形态(修前该钩子在任务树里恒报环境错、静默不可用);coding-standard 记 「函数头注释超过 24 行就把函数功能挤出回看窗口」这条机制与本次现场 - 覆盖率基线登记两个新覆盖模块(套件 41 → 44 套);环单测重打后该文件有效行 227 → 226、覆盖行 226 → 225,比率仍 99.6%,是分母变小不是覆盖率回退 为什么是单一提交:文档链接、双端注册、生成器幂等(菜单与字库)、内存数字与 体积事实源、编号门禁这五道整仓门禁要求代码、页面、菜单树、字库、文档与台账 同处一个提交才自洽,按数据面/接线/人机/台账拆成四笔必然红其中至少四道 编号门禁新增行 14 处命中已按语义改写:魔数常量按字符命名、段名样例改由格式串 生成、频谱表头改 f / 2x / 5x 并加一行图例;改写后自洽断言 92 条仍全过
This commit is contained in:
+393
-1
@@ -72,7 +72,10 @@
|
||||
#include "ui_w_records.h" /* task-6 记录 reader 注入点(镜像 App/task/ui_task.c 的绑定) */
|
||||
#include "ui_w_soe.h" /* task-15 SOE 记录 reader 注入点(同上:镜像真机绑定) */
|
||||
#include "ui_data.h" /* task-14 快照存侧:模拟器在此直接发布固定帧(装配器不进模拟器) */
|
||||
#include "prot_set.h" /* task-14 定值出厂默认(App/algo 纯算法,双端可编,见 simulator/CMakeLists) */
|
||||
#include "prot_set.h"
|
||||
#include "wave_ring.h" /* 录波假源:真环(不进 SIM_EXEMPT,见下方块注释) */
|
||||
#include "wave_store.h" /* 录波假源:真段格式与定点换算(同一条链) */
|
||||
#include "adc_cal.h" /* ADC_CAL_K_Q16_* 封存系数原值(不手抄对照表) */ /* task-14 定值出厂默认(App/algo 纯算法,双端可编,见 simulator/CMakeLists) */
|
||||
|
||||
/* 屏幕尺寸(与 MCU 端一致) */
|
||||
#define SIM_SCREEN_W 160
|
||||
@@ -482,6 +485,383 @@ static void sim_comm_pump(void) {
|
||||
}
|
||||
s_comm_dirty = 0u;
|
||||
}
|
||||
|
||||
/* ═════════ 故障录波假源(UI 道,2026-10-29):真 ring + 真 store + 合成节拍 ═════════
|
||||
* 口径(lead 裁定):wave_ring.c / wave_store.c **不进 SIM_EXEMPT**——模拟器链
|
||||
* 的就是板端那份实现,回放页在模拟器里出的是**真波形**:合成 1kHz 节拍喂进
|
||||
* ring,封存后用 wave_ring_read_cb 作 wave_store 打包游标的数据源产整段,
|
||||
* 读侧再走 head_parse / data_off / le_decode / code_to_milli 同一条链——
|
||||
* 与 prot_set.c 同一条「双端共享核心、不造第二真相」。
|
||||
* 数值全取头文件宏与 wave_store 现算(WAVE_ST_* / ADC_CAL_K_Q16_*),
|
||||
* 不手抄对照表。旗标:--wave-empty 拍「无录波段」空态黄金;--wave-bad 拍
|
||||
* 「该段不可读」黄金(故意翻转数据区一字节,让**真 CRC 判废**去拒绝它——
|
||||
* 不是把「不可读」写死在假件返回值里)。
|
||||
*/
|
||||
#define SW_IMG_MAX 2u /* 两段:左右键切段的像素证据(段号 + 相位都不同) */
|
||||
|
||||
static uint8_t s_wave_img[SW_IMG_MAX][WAVE_ST_SEG_SZ_CUR];
|
||||
static uint8_t s_wave_idxval[SW_IMG_MAX]; /* 槽位对应的段号(模拟盘上编号) */
|
||||
static uint8_t s_wave_cnt;
|
||||
static int s_wave_empty; /* --wave-empty */
|
||||
static int s_wave_bad; /* --wave-bad */
|
||||
static uint32_t s_wave_now = 1000u; /* 合成毫秒(跨段单调) */
|
||||
static uint32_t s_wave_seq = 10u; /* 合成帧序号(跨段单调) */
|
||||
|
||||
/*
|
||||
* 函数功能:合成第 t 拍的 8 路原始码值
|
||||
* 入口参数:t - 合成拍号
|
||||
* 返回:无(写 codes[8],下标 = 语义号:UA UB UC UN IA IB IC IN)
|
||||
* 函数说明:TPAFE 三路(sem 0/3/4)双极 50Hz 正弦(1kHz 采样每周波 20 点,
|
||||
* 幅度 ±8000 码 = 引脚域约 ±1.2V);STM32 五路(sem 1/2/5/6/7)
|
||||
* 半波 0..2048 且**钉死下轨**(V0.1 单极性无偏置的事实还原——
|
||||
* 回放页必须让「贴 0 线」与「削顶」在像素上可分辨)
|
||||
*/
|
||||
static void sim_wave_codes(uint32_t a_t, int16_t *a_codes) {
|
||||
/* 50Hz 正弦 20 点表(×8000 满幅一半再取整,固定表 = 逐像素可复现) */
|
||||
static const int16_t k_sine[20] = {
|
||||
0, 2351, 4530, 6428, 7893, 8000, 7893, 6428, 4530, 2351,
|
||||
0, -2351, -4530, -6428, -7893, -8000, -7893, -6428, -4530, -2351
|
||||
};
|
||||
int16_t half = (int16_t)(4095 - (a_t % 20u) * 200u);
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0u; i < 8u; i++) {
|
||||
if ((i == 0u) || (i == 3u) || (i == 4u)) {
|
||||
a_codes[i] = k_sine[a_t % 20u];
|
||||
} else {
|
||||
a_codes[i] = (half > 0) ? half : 0; /* 半波衰减再钉下轨 0 */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:同步跑完一整段「触发 → 冻结 → 封存 → 打包 → ACK → 冷却」
|
||||
* 入口参数:无
|
||||
* 返回值:无(成功则 s_wave_cnt++,坏图旗标开启时翻转数据区一字节)
|
||||
* 限定条件:仅 uiTask/主线程绘制期外的同步调用(假件特权,真机无此路径)
|
||||
* 函数说明:无头模式没有 lv_timer_handler 的 1ms 泵(同 sim_yt_pump 的
|
||||
* 「当场排空」理由)——截图前必须把这段状态机原地跑完,
|
||||
* 否则回放页永远停在空态,阶梯线/0 线/峰值/徽标就全都没有
|
||||
* 像素证据。冷却 500ms 也要泵过去:下一段从 IDLE 起
|
||||
*/
|
||||
static void sim_wave_capture_one(void) {
|
||||
wave_seal_cal_t cal;
|
||||
wave_seg_meta_t meta;
|
||||
wave_pack_ctx_t ctx;
|
||||
int16_t codes[8];
|
||||
uint8_t buf[256];
|
||||
static uint8_t slot_pfx;
|
||||
static uint8_t inited; /* ring 一次性初始化(假件镜像 adc 侧上电) */
|
||||
uint32_t out_len = 0u;
|
||||
uint32_t total;
|
||||
int32_t r;
|
||||
uint32_t t;
|
||||
uint8_t i;
|
||||
|
||||
if (s_wave_cnt >= SW_IMG_MAX) {
|
||||
return;
|
||||
}
|
||||
if (inited == 0u) {
|
||||
wave_ring_init();
|
||||
inited = 1u;
|
||||
}
|
||||
/* 预滚历史 ≥ 预窗:触发前的 200 拍先喂进环(真机上环一直在滚,
|
||||
* 模拟器的环不预滚的话预窗就是 init 全零——回放页两周波里只有一半
|
||||
* 有波形,像素证据废一半)。push 在 IDLE/FREEZE 都写环(SEALED 才丢),
|
||||
* 契约见 App/algo/wave_ring.c 的 wave_ring_push 头注 */
|
||||
for (t = 0u; t < 200u; t++) {
|
||||
sim_wave_codes(s_wave_seq + t, codes);
|
||||
(void)wave_ring_push(codes, 8u);
|
||||
(void)wave_ring_tick(s_wave_now + t, s_wave_seq + t);
|
||||
}
|
||||
s_wave_now += 200u;
|
||||
s_wave_seq += 200u;
|
||||
if (wave_ring_request((uint8_t)WAVE_TRIG_MANUAL, 0u) != 0) {
|
||||
return;
|
||||
}
|
||||
r = 0;
|
||||
for (t = 0u; t < 4000u; t++) {
|
||||
sim_wave_codes(s_wave_seq + t, codes);
|
||||
(void)wave_ring_push(codes, 8u);
|
||||
r = wave_ring_tick(s_wave_now + t, s_wave_seq + t);
|
||||
if (r == 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (r != 1) {
|
||||
return;
|
||||
}
|
||||
s_wave_now += t + 1u;
|
||||
s_wave_seq += t + 1u;
|
||||
/* 封存交棒:V0.1 真值口径(未标定 → VALID 全 0;CLIPPED 五路 = 0xE6;
|
||||
* 系数取宏原值,float 一面都不碰——§6.3) */
|
||||
(void)memset(&cal, 0, sizeof(cal));
|
||||
cal.eng = (uint8_t)WAVE_ENG_PIN;
|
||||
cal.flags_seq = 0u;
|
||||
cal.clip_mask = 0xE6u;
|
||||
cal.wall = 0u;
|
||||
for (i = 0u; i < 8u; i++) {
|
||||
cal.ch[i].sem = i;
|
||||
if ((i == 0u) || (i == 3u) || (i == 4u)) {
|
||||
cal.ch[i].conv = 0u;
|
||||
cal.ch[i].bits = 16u;
|
||||
cal.ch[i].k_q16 = (int32_t)ADC_CAL_K_Q16_TPAFE;
|
||||
cal.ch[i].avail = 0u;
|
||||
} else {
|
||||
cal.ch[i].conv = 1u;
|
||||
cal.ch[i].bits = 12u;
|
||||
cal.ch[i].k_q16 = (int32_t)ADC_CAL_K_Q16_STM32;
|
||||
cal.ch[i].avail = (uint8_t)0x02u; /* 只 CLIPPED,无 VALID */
|
||||
}
|
||||
cal.ch[i].b_codes = 0;
|
||||
}
|
||||
if (wave_ring_latch_meta(&cal) != 0) {
|
||||
return;
|
||||
}
|
||||
if (wave_ring_sealed_meta(&meta) != 0) {
|
||||
return;
|
||||
}
|
||||
total = wave_store_seg_size(&meta);
|
||||
if ((total == 0u) || (total > (uint32_t)WAVE_ST_SEG_SZ_CUR)) {
|
||||
return;
|
||||
}
|
||||
if (wave_store_pack_start(&ctx, &meta, wave_ring_read_cb, NULL) != 0) {
|
||||
return;
|
||||
}
|
||||
for (;;) {
|
||||
uint32_t len = 0u;
|
||||
|
||||
r = wave_store_pack_next(&ctx, buf, (uint32_t)sizeof(buf), &len);
|
||||
if ((r != 0) && (r != WAVE_ST_DONE)) {
|
||||
return;
|
||||
}
|
||||
if ((out_len + len) > (uint32_t)WAVE_ST_SEG_SZ_CUR) {
|
||||
return;
|
||||
}
|
||||
(void)memcpy(&s_wave_img[s_wave_cnt][out_len], buf, len);
|
||||
out_len += len;
|
||||
if (r == WAVE_ST_DONE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (out_len != total) {
|
||||
return;
|
||||
}
|
||||
if (s_wave_bad != 0) {
|
||||
/* 翻转数据区一点:真 seg_check 的双 CRC 判废会拒它——UI 侧必须
|
||||
* 走到「该段不可读」而不是画半截线(伪造证据的反面教材做成像素) */
|
||||
s_wave_img[s_wave_cnt][WAVE_ST_HEAD_BYTES(WAVE_ST_CH_NUM) + 16u] ^= 0xA5u;
|
||||
}
|
||||
s_wave_idxval[s_wave_cnt] = slot_pfx;
|
||||
slot_pfx = (uint8_t)((slot_pfx + 1u) % WAVE_ST_SEG_MAX);
|
||||
s_wave_cnt++;
|
||||
(void)wave_ring_write_done(0);
|
||||
/* 泵过冷却窗(COOL = 500ms 只加 ovf 不采新触发;不泵则第二段起不来) */
|
||||
for (t = 0u; t < (WAVE_RING_COOL_MS + 1u); t++) {
|
||||
sim_wave_codes(s_wave_seq + t, codes);
|
||||
(void)wave_ring_push(codes, 8u);
|
||||
(void)wave_ring_tick(s_wave_now + t, s_wave_seq + t);
|
||||
}
|
||||
s_wave_now += WAVE_RING_COOL_MS + 1u;
|
||||
s_wave_seq += WAVE_RING_COOL_MS + 1u;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:懒触发建段(回放页第一次取数时把两段建齐)
|
||||
* 入口参数:无
|
||||
* 返回值:无
|
||||
* 限定条件:录波通道的 first/next 入口调用
|
||||
*/
|
||||
static void sim_wave_service(void) {
|
||||
if (s_wave_empty != 0) {
|
||||
return;
|
||||
}
|
||||
while (s_wave_cnt < SW_IMG_MAX) {
|
||||
sim_wave_capture_one();
|
||||
}
|
||||
}
|
||||
|
||||
/* 函数功能:按段号找槽位 int */
|
||||
static int sim_wave_slot(uint8_t a_idx) {
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0u; i < s_wave_cnt; i++) {
|
||||
if (s_wave_idxval[i] == a_idx) {
|
||||
return (int)i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:验段并把头解析进 p_meta(坏段拒得干净) int
|
||||
* 说明:这里用全图 seg_check 与真机的流式判废**判据相同**(尺寸等式 +
|
||||
* 双 CRC + sem==index),只差在真机为省 RAM 分窗——判定结果一致
|
||||
* 就是「模拟器像素 = 真机行为」的前提
|
||||
*/
|
||||
static int sim_wave_verified(int a_slot, wave_seg_meta_t *p_meta) {
|
||||
if (a_slot < 0) {
|
||||
return UI_WAVE_NONE;
|
||||
}
|
||||
if (wave_store_seg_check(s_wave_img[a_slot], WAVE_ST_SEG_SZ_CUR,
|
||||
p_meta) != 0) {
|
||||
return UI_WAVE_BAD;
|
||||
}
|
||||
return UI_WAVE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:模拟器侧「手动录波」按键的受理判定(第五注入通道的 manual_req 实现)
|
||||
* 入口参数:无
|
||||
* 返 回 值:0 = 受理(界面据此显示已请求);-1 = 拒绝 int
|
||||
* 限定条件:仅 UI 线程上下文(与固件 ui_task.c 的同名 ops 一一对应)
|
||||
* 函数说明:--wave-empty 旗标下恒拒,目的是让「录波进行中/无段可录」那条文案在
|
||||
* 模拟器里有像素证据;真受理路径只置计数,段的生成走 sim_wave_service()
|
||||
* 的懒路径(等 UI 真的来要数据时才造出一段,避免开机就烧 CPU)。
|
||||
*/
|
||||
static int sim_wave_manual_req(void) { if (s_wave_empty != 0) {
|
||||
return -1; /* 空态旗标:触发也拒(ERR 分支要有像素证据) */
|
||||
}
|
||||
return 0; /* 受理 = ring 已 IDLE 可来一段;段的生成走懒路径 */
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:取开屏默认段号(回放页第一次进页面时的落点)
|
||||
* 入口参数:a_idx 输出段号
|
||||
* 返 回 值:UI_WAVE_OK 已给出;UI_WAVE_NONE 一段都没有 int
|
||||
* 限定条件:仅 UI 线程上下文
|
||||
* 函数说明:与固件侧同口径——按**数值**取最大号(不是「时间最新」,回绕后两者
|
||||
* 不等价),页顶显示的段号就是这一句的自证。
|
||||
*/
|
||||
static int sim_wave_seg_first(uint8_t *a_idx) { sim_wave_service();
|
||||
if (s_wave_cnt == 0u) {
|
||||
return UI_WAVE_NONE;
|
||||
}
|
||||
*a_idx = s_wave_idxval[s_wave_cnt - 1u];
|
||||
return UI_WAVE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:切到数值上前一段(镜像 LR 左键;段号表按数值升序)
|
||||
* 入口参数:a_cur 当前段号;a_out 输出切换后的段号
|
||||
* 返 回 值:UI_WAVE_OK 已给出;UI_WAVE_NONE 一段都没有 int
|
||||
* 限定条件:仅 UI 线程上下文;当前段不在表里(被覆盖)时退回最大号
|
||||
*/
|
||||
static int sim_wave_seg_prev(uint8_t a_cur, uint8_t *a_out) { sim_wave_service();
|
||||
if (s_wave_cnt == 0u) {
|
||||
return UI_WAVE_NONE;
|
||||
}
|
||||
{
|
||||
int pos = sim_wave_slot(a_cur);
|
||||
if (pos < 0) {
|
||||
pos = (int)s_wave_cnt - 1;
|
||||
}
|
||||
pos = (pos + (int)s_wave_cnt - 1) % (int)s_wave_cnt;
|
||||
*a_out = s_wave_idxval[pos];
|
||||
}
|
||||
return UI_WAVE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:切到数值上后一段(镜像 LR 右键)
|
||||
* 入口参数:a_cur 当前段号;a_out 输出切换后的段号
|
||||
* 返 回 值:UI_WAVE_OK 已给出;UI_WAVE_NONE 一段都没有 int
|
||||
* 限定条件:仅 UI 线程上下文;表内循环(到尾回头),与固件侧同语义
|
||||
*/
|
||||
static int sim_wave_seg_next(uint8_t a_cur, uint8_t *a_out) { sim_wave_service();
|
||||
if (s_wave_cnt == 0u) {
|
||||
return UI_WAVE_NONE;
|
||||
}
|
||||
{
|
||||
int pos = sim_wave_slot(a_cur);
|
||||
if (pos < 0) {
|
||||
pos = 0;
|
||||
}
|
||||
pos = (pos + 1) % (int)s_wave_cnt;
|
||||
*a_out = s_wave_idxval[pos];
|
||||
}
|
||||
return UI_WAVE_OK;
|
||||
}
|
||||
|
||||
static int sim_wave_seg_head(uint8_t a_idx, uint8_t *a_eng, uint8_t *a_trig,
|
||||
uint8_t *a_clip) {
|
||||
wave_seg_meta_t meta;
|
||||
int rc = sim_wave_verified(sim_wave_slot(a_idx), &meta);
|
||||
|
||||
if (rc != UI_WAVE_OK) {
|
||||
return rc;
|
||||
}
|
||||
*a_eng = meta.eng;
|
||||
*a_trig = meta.trig_src;
|
||||
*a_clip = (uint8_t)(meta.clip_mask & 0xFFu);
|
||||
return UI_WAVE_OK;
|
||||
}
|
||||
|
||||
static int sim_wave_seg_win(uint8_t a_idx, uint8_t a_ch, int16_t *a_codes,
|
||||
int32_t *a_peak_milli) {
|
||||
wave_seg_meta_t meta;
|
||||
int slot = sim_wave_slot(a_idx);
|
||||
int rc = sim_wave_verified(slot, &meta);
|
||||
uint32_t start;
|
||||
uint32_t off;
|
||||
uint32_t got = 0u;
|
||||
int16_t raw[UI_WAVE_WIN_PTS];
|
||||
int32_t peak = 0;
|
||||
int32_t milli;
|
||||
uint8_t i;
|
||||
|
||||
if (rc != UI_WAVE_OK) {
|
||||
return rc;
|
||||
}
|
||||
if ((a_ch >= meta.ch_count) || (meta.pre_pts < (UI_WAVE_WIN_PTS / 2u))) {
|
||||
return UI_WAVE_BAD;
|
||||
}
|
||||
start = (uint32_t)meta.pre_pts - (UI_WAVE_WIN_PTS / 2u);
|
||||
off = wave_store_data_off(meta.ch_count, meta.pts_per_ch, a_ch, start);
|
||||
if (off == 0xFFFFFFFFu) {
|
||||
return UI_WAVE_BAD;
|
||||
}
|
||||
if (wave_store_le_decode(&s_wave_img[slot][off], UI_WAVE_WIN_PTS * 2u,
|
||||
raw, UI_WAVE_WIN_PTS, &got) != 0 ||
|
||||
got != UI_WAVE_WIN_PTS) {
|
||||
return UI_WAVE_BAD;
|
||||
}
|
||||
for (i = 0u; i < UI_WAVE_WIN_PTS; i++) {
|
||||
int32_t v;
|
||||
|
||||
v = (int32_t)raw[i] + meta.ch[a_ch].b_codes;
|
||||
if (v > 32767L) {
|
||||
v = 32767L;
|
||||
} else if (v < (-32768L)) {
|
||||
v = -32768L;
|
||||
}
|
||||
a_codes[i] = (int16_t)v;
|
||||
/* 同尺说明与真机胶水同款(App/task/ui_task.c seg_win 注释):
|
||||
* code_to_milli 内部 (raw + b_codes) × k(App/algo/wave_store.c:567),
|
||||
* b 只在唯一口径里加一次,PK 与屏上波形同尺 */
|
||||
if (wave_store_code_to_milli(&meta.ch[a_ch], raw[i], &milli) == 0) {
|
||||
/* 「正峰优先」并列判据与真机胶水同款(App/task/ui_task.c
|
||||
* seg_win 注释):等幅异号时取正,峰值读数不随触发相位漂 */
|
||||
if (((milli < 0 ? -milli : milli) > (peak < 0 ? -peak : peak)) ||
|
||||
(((milli < 0 ? -milli : milli) == (peak < 0 ? -peak : peak)) &&
|
||||
(milli > peak))) {
|
||||
peak = milli;
|
||||
}
|
||||
}
|
||||
}
|
||||
*a_peak_milli = peak;
|
||||
return UI_WAVE_OK;
|
||||
}
|
||||
|
||||
/* 录波通道假表(与真机 s_wave_ops 同形状六件) */
|
||||
static const ui_data_wave_ops_t s_wave_ops = {
|
||||
sim_wave_manual_req,
|
||||
sim_wave_seg_first,
|
||||
sim_wave_seg_prev,
|
||||
sim_wave_seg_next,
|
||||
sim_wave_seg_head,
|
||||
sim_wave_seg_win
|
||||
};
|
||||
/*
|
||||
* 函数功能:SOE 记录假源——固定 3 条(镜像 App/task/ui_task.c 真机绑定的形态)
|
||||
* 入口参数:无
|
||||
@@ -819,6 +1199,9 @@ static int run_headless(const char * keys, const char * path, int standby) {
|
||||
if (ui_data_comm_bind(&s_comm_ops) != 0) { /* 道G task-9 通讯参数假表(两处同文 replace_all) */
|
||||
printf("[sim] UI comm bind: FAIL\n");
|
||||
}
|
||||
if (ui_data_wave_bind(&s_wave_ops) != 0) { /* 录波通道假表(两处同文,镜像真机绑定) */
|
||||
printf("[sim] UI wave bind: FAIL\n");
|
||||
}
|
||||
/* task-14 数据快照:镜像 ui_task.c 的 ui_data_init + 首帧发布(先于建页,
|
||||
* 页面任何时刻打开都拿得到帧,不必等装配节拍) */
|
||||
sim_publish_data_frames();
|
||||
@@ -1252,6 +1635,12 @@ int main(int argc, char **argv) {
|
||||
if (strcmp(argv[i], "--comm-nopump") == 0) {
|
||||
s_comm_nopump = 1; /* 道G task-9:通讯页 WAIT 态黄金专用(同款语义独立开关) */
|
||||
}
|
||||
if (strcmp(argv[i], "--wave-empty") == 0) {
|
||||
s_wave_empty = 1; /* 录波回放空态黄金专用:不建段且触发拒收 */
|
||||
}
|
||||
if (strcmp(argv[i], "--wave-bad") == 0) {
|
||||
s_wave_bad = 1; /* 「该段不可读」黄金专用:数据区翻一点让真 CRC 判废 */
|
||||
}
|
||||
}
|
||||
|
||||
/* 截图/自检模式:--screenshot / --keys / --standby / --cfgtest / --logtest */
|
||||
@@ -1329,6 +1718,9 @@ int main(int argc, char **argv) {
|
||||
if (ui_data_comm_bind(&s_comm_ops) != 0) { /* 道G task-9 通讯参数假表(两处同文 replace_all) */
|
||||
printf("[sim] UI comm bind: FAIL\n");
|
||||
}
|
||||
if (ui_data_wave_bind(&s_wave_ops) != 0) { /* 录波通道假表(两处同文,镜像真机绑定) */
|
||||
printf("[sim] UI wave bind: FAIL\n");
|
||||
}
|
||||
/* task-14 数据快照:镜像 ui_task.c 的 ui_data_init + 首帧发布(先于建页,
|
||||
* 页面任何时刻打开都拿得到帧,不必等装配节拍) */
|
||||
sim_publish_data_frames();
|
||||
|
||||
Reference in New Issue
Block a user