3dc7f4a088
两件事都落在这份方案文档里,合一笔提交(同一文件的两处改动按文件切分提交不干净,故合并说明)。 一、四个返回系数:口径从"我偏离文档"改成"文档原口径错了"(Lead 裁定 2026-10-25) - §3.2.2 表里 4 行小数位 3 → 2 并加 ⚠;落地注改写;同步去掉 ui_w_setview.c 注释与 tools/setview_check/check_setview_limits.py 文档串里的"偏离"措辞。 - 原口径 3 位来自"把 Q10 当成十进制存储"这个误会:Q10 存不下 0.95(0.95×1024 截成 972,真存 0.94921875),按 3 位显示等于多打一位根本不存在的数字;整定单写 0.95 的人看到屏上 0.949 会 怀疑装置、甚至反复重输(重输还是 0.949)。2 位才是这份存储在自己可分辨精度上的正确读数。 - 不改行为,只改文档与注释:屏上显示与行表换算逻辑一笔未动。 二、§3.1.3 落地注(遥信量页落地后回填,含两条命名取舍与一条通用陷阱) - 命名:idx0~3 屏上写「位置1~4」不写「YK1~4 位置」;idx30 写「保护闭锁」不写「闭锁1」;点表未 定义名的行用点号占位,不编造功能名。 - 值映射次序(先无效 → 再单双点 → 后位值)与双点支路"当前无自动化证据"的诚实登记。 - 通用陷阱:把 *_PUT(dst, 字面量) 宏用在 const char *const 表项上,sizeof(源) 变成指针宽度, CJK 名被截而短 ASCII 名恰好完好——只有像素文本断言会报"名字匹配不到而值在原位"。 跳过的门禁(三条同族):mem-numbers / mem-budget / size-gate(L0c),根因是台账与体积凭证待回填。
382 lines
20 KiB
C
382 lines
20 KiB
C
/*
|
||
* 模块名称:UI 定值查看视图模型(ui_w_setview)
|
||
* 模块功能:参数 / 定值 / 控制字 / 软压板四张视图表与它们的取数、换算、越界反显——
|
||
* 供四个查看页薄跳板共用;声明与分层理由见 ui_w_setview.h
|
||
* 适用平台:STM32F407ZGTx / PC 模拟器(共用源码)
|
||
* 作者:王建锋
|
||
* 创建日期:2026-10-25
|
||
* 修改记录:
|
||
* v1.0 2026-10-25 王建锋 创建(道E task-15 批 3)
|
||
*/
|
||
/* 头文件包含区 */
|
||
#include <string.h>
|
||
|
||
#include "ui_w_setview.h"
|
||
|
||
#include "ui_data.h"
|
||
#include "ui_tokens.h" /* UI_BUF_STRLEN:框架行缓冲长度(无帧占位串要写进同一缓冲) */
|
||
|
||
/* 静态变量定义区 */
|
||
|
||
/* 二态行的串表(下标 = 记录值;0/1 的语义来自 App/algo/prot_set.h 的 meta 注释:
|
||
* *_TRIP 0 = 告警 / 1 = 跳闸,*_EN 0 = 退出 / 1 = 投入;串表以 NULL 结尾,
|
||
* 组件按串表长度决定 ENTER 循环切换的范围) */
|
||
const char *const s_opts_trip[3] = { "告警", "跳闸", NULL };
|
||
const char *const s_opts_plate[3] = { "退出", "投入", NULL };
|
||
|
||
/*
|
||
* 四张视图表(Flash const)。行表的三项口径全部有真源,不在本文件里自由发挥:
|
||
* · id = App/algo/prot_set.h 的 prot_set_id_t 枚举序(BSP 不 include App 头,
|
||
* 故写裸数字并把枚举名注在行尾;对不上由主机单测与像素值两处暴露)
|
||
* · min/max = App/algo/prot_set.c 的 g_prot_set_meta 上下限(Q10)换算到本行
|
||
* decimals 后的整数——**照抄换算结果,不自己拟定**;整定页复用同一批表,
|
||
* 界内外一处一份,不会出现"查看看着合法、整定说越界"的两套边界
|
||
* · 显示名/小数位/单位 = docs/UI设计/页面扩充详细方案.md §3.2.2~§3.2.5 四张表。
|
||
* 其中四个返回系数按 **2 位小数** 显示:这不是我偏离文档,而是文档原口径(3 位)
|
||
* 本身错了——它把 Q10 当成了十进制存储。Q10 存不下 0.95:0.95×1024 截成 972,真存
|
||
* 的是 0.94921875;按 3 位显示等于打出一位根本不存在的"9",整定单上写 0.95 的人看
|
||
* 到 0.949 会怀疑装置、甚至反复重输(重输也还是 0.949)。2 位才是这份存储在自己
|
||
* 可分辨精度上的正确读数。§3.2.2 已同步修正(表里 3 位改 2 位并加 ⚠ 指向本注释)
|
||
* 单位挂在值串尾(A/V/ms/Hz 全 ASCII,不占中文字库):值列只有数字会让"60000"既是
|
||
* ms 又是 A,读者只能靠猜;行表带 unit 字段是本次给组件加的(NULL = 不挂)
|
||
*/
|
||
|
||
/* 参数视图(8 行 = 1 页) */
|
||
static const ui_w_setlist_row_t s_rows_param[8] = {
|
||
{ "PT一次", 27u, UI_W_SETLIST_KIND_NUM, 0u, 100, 500000, NULL, "V" }, /* PS_PT_PRI */
|
||
{ "PT二次", 28u, UI_W_SETLIST_KIND_NUM, 0u, 1, 200, NULL, "V" }, /* PS_PT_SEC */
|
||
{ "CT一次", 29u, UI_W_SETLIST_KIND_NUM, 0u, 1, 10000, NULL, "A" }, /* PS_CT_PRI */
|
||
{ "CT二次", 30u, UI_W_SETLIST_KIND_NUM, 0u, 1, 10, NULL, "A" }, /* PS_CT_SEC */
|
||
{ "过量返回", 25u, UI_W_SETLIST_KIND_NUM, 2u, 50, 100, NULL, NULL }, /* PS_RET_OVER */
|
||
{ "欠量返回", 26u, UI_W_SETLIST_KIND_NUM, 2u, 100, 150, NULL, NULL }, /* PS_RET_UNDER */
|
||
{ "过频返回", 38u, UI_W_SETLIST_KIND_NUM, 2u, 90, 100, NULL, NULL }, /* PS_RET_OF */
|
||
{ "低频返回", 39u, UI_W_SETLIST_KIND_NUM, 2u, 100, 110, NULL, NULL }, /* PS_RET_UF */
|
||
};
|
||
|
||
/* 定值视图(18 行 = 3 页) */
|
||
static const ui_w_setlist_row_t s_rows_set[18] = {
|
||
{ "Ⅰ段电流", 2u, UI_W_SETLIST_KIND_NUM, 2u, 0, 10000, NULL, "A" }, /* PS_OC1_CUR */
|
||
{ "Ⅰ段延时", 3u, UI_W_SETLIST_KIND_NUM, 0u, 0, 60000, NULL, "ms" }, /* PS_OC1_DLY */
|
||
{ "Ⅱ段电流", 6u, UI_W_SETLIST_KIND_NUM, 2u, 0, 10000, NULL, "A" }, /* PS_OC2_CUR */
|
||
{ "Ⅱ段延时", 7u, UI_W_SETLIST_KIND_NUM, 0u, 0, 60000, NULL, "ms" }, /* PS_OC2_DLY */
|
||
{ "Ⅲ段电流", 10u, UI_W_SETLIST_KIND_NUM, 2u, 0, 10000, NULL, "A" }, /* PS_OC3_CUR */
|
||
{ "Ⅲ段延时", 11u, UI_W_SETLIST_KIND_NUM, 0u, 0, 60000, NULL, "ms" }, /* PS_OC3_DLY */
|
||
{ "过负荷电流", 14u, UI_W_SETLIST_KIND_NUM, 2u, 0, 10000, NULL, "A" }, /* PS_OL_CUR */
|
||
{ "过负荷延时", 15u, UI_W_SETLIST_KIND_NUM, 0u, 0, 60000, NULL, "ms" }, /* PS_OL_DLY */
|
||
{ "过压定值", 17u, UI_W_SETLIST_KIND_NUM, 1u, 0, 2000, NULL, "V" }, /* PS_OV_VOL */
|
||
{ "过压延时", 18u, UI_W_SETLIST_KIND_NUM, 0u, 0, 60000, NULL, "ms" }, /* PS_OV_DLY */
|
||
{ "低压定值", 20u, UI_W_SETLIST_KIND_NUM, 1u, 0, 2000, NULL, "V" }, /* PS_UV_VOL */
|
||
{ "低压延时", 21u, UI_W_SETLIST_KIND_NUM, 0u, 0, 60000, NULL, "ms" }, /* PS_UV_DLY */
|
||
{ "零序定值", 23u, UI_W_SETLIST_KIND_NUM, 1u, 0, 2000, NULL, "V" }, /* PS_3U0_VOL */
|
||
{ "零序延时", 24u, UI_W_SETLIST_KIND_NUM, 0u, 0, 60000, NULL, "ms" }, /* PS_3U0_DLY */
|
||
{ "过频定值", 33u, UI_W_SETLIST_KIND_NUM, 2u, 5000, 5500, NULL, "Hz" }, /* PS_OF_HZ */
|
||
{ "过频延时", 34u, UI_W_SETLIST_KIND_NUM, 0u, 0, 60000, NULL, "ms" }, /* PS_OF_DLY */
|
||
{ "低频定值", 36u, UI_W_SETLIST_KIND_NUM, 2u, 4500, 5000, NULL, "Hz" }, /* PS_UF_HZ */
|
||
{ "低频延时", 37u, UI_W_SETLIST_KIND_NUM, 0u, 0, 60000, NULL, "ms" }, /* PS_UF_DLY */
|
||
};
|
||
|
||
/* 控制字视图(4 行 = 1 页) */
|
||
static const ui_w_setlist_row_t s_rows_word[4] = {
|
||
{ "Ⅰ段跳闸", 1u, UI_W_SETLIST_KIND_ENUM, 0u, 0, 0, s_opts_trip, NULL }, /* PS_OC1_TRIP */
|
||
{ "Ⅱ段跳闸", 5u, UI_W_SETLIST_KIND_ENUM, 0u, 0, 0, s_opts_trip, NULL }, /* PS_OC2_TRIP */
|
||
{ "Ⅲ段跳闸", 9u, UI_W_SETLIST_KIND_ENUM, 0u, 0, 0, s_opts_trip, NULL }, /* PS_OC3_TRIP */
|
||
{ "过负荷跳闸", 13u, UI_W_SETLIST_KIND_ENUM, 0u, 0, 0, s_opts_trip, NULL }, /* PS_OL_TRIP */
|
||
};
|
||
|
||
/* 软压板视图(10 行 = 2 页) */
|
||
static const ui_w_setlist_row_t s_rows_plate[10] = {
|
||
{ "Ⅰ段投入", 0u, UI_W_SETLIST_KIND_ENUM, 0u, 0, 0, s_opts_plate, NULL }, /* PS_OC1_EN */
|
||
{ "Ⅱ段投入", 4u, UI_W_SETLIST_KIND_ENUM, 0u, 0, 0, s_opts_plate, NULL }, /* PS_OC2_EN */
|
||
{ "Ⅲ段投入", 8u, UI_W_SETLIST_KIND_ENUM, 0u, 0, 0, s_opts_plate, NULL }, /* PS_OC3_EN */
|
||
{ "过负荷投入", 12u, UI_W_SETLIST_KIND_ENUM, 0u, 0, 0, s_opts_plate, NULL }, /* PS_OL_EN */
|
||
{ "过压投入", 16u, UI_W_SETLIST_KIND_ENUM, 0u, 0, 0, s_opts_plate, NULL }, /* PS_OV_EN */
|
||
{ "低压投入", 19u, UI_W_SETLIST_KIND_ENUM, 0u, 0, 0, s_opts_plate, NULL }, /* PS_UV_EN */
|
||
{ "零序投入", 22u, UI_W_SETLIST_KIND_ENUM, 0u, 0, 0, s_opts_plate, NULL }, /* PS_3U0_EN */
|
||
{ "过频投入", 32u, UI_W_SETLIST_KIND_ENUM, 0u, 0, 0, s_opts_plate, NULL }, /* PS_OF_EN */
|
||
{ "低频投入", 35u, UI_W_SETLIST_KIND_ENUM, 0u, 0, 0, s_opts_plate, NULL }, /* PS_UF_EN */
|
||
{ "保护总投入", 31u, UI_W_SETLIST_KIND_ENUM, 0u, 0, 0, s_opts_plate, NULL }, /* PS_GLOBAL_EN */
|
||
};
|
||
|
||
/*
|
||
* 每个定值项的显示小数位(下标 = 枚举序;二态项为 0,不参与数值换算)
|
||
* 为什么要单独一张表而不是从行表里找:组件的 get(id) 回调只给 id 不给行号,
|
||
* 同一 id 只会出现在一张视图里(四张表恰好覆盖 0..39 各一次,由主机单测钉住),
|
||
* 所以这张表是无歧义的,且比遍历四张表便宜
|
||
*/
|
||
static const uint8_t s_dec[UI_DATA_SET_N] = {
|
||
0, 0, 2, 0, 0, 0, 2, 0, 0, 0,
|
||
2, 0, 0, 0, 2, 0, 0, 1, 0, 0,
|
||
1, 0, 0, 1, 0, 2, 2, 0, 0, 0,
|
||
0, 0, 0, 2, 0, 0, 2, 0, 2, 2,
|
||
};
|
||
|
||
/* 无参数帧时值列的占位串(与全仓"读不到就 --"同一口径) */
|
||
#define SV_NO_DATA "--"
|
||
|
||
/* 参数帧缓存(四个查看页共用一份:同屏只开一页,无并发读者) */
|
||
static ui_data_par_t s_par;
|
||
static uint32_t s_par_seq = 0xFFFFFFFFu; /* 与任何合法发布序号都不同 */
|
||
static uint8_t s_par_ok;
|
||
|
||
/* 当前视图的行表(bad 回调只收到行号,需要它把行号换回 id 再查位图) */
|
||
static const ui_w_setlist_row_t *s_cur_rows;
|
||
static uint16_t s_cur_n; /* 当前视图行数(bad 回调的边界) */
|
||
|
||
/* 行表长度(编译期算,别手写数字——手写数字与表长不一致是最难查的错) */
|
||
#define SV_ROW_N(tbl) ((uint16_t)(sizeof(tbl) / sizeof((tbl)[0])))
|
||
|
||
/* 函数定义区 */
|
||
|
||
/*
|
||
* 函数功能:Q10 原值 → 指定小数位的定点显示值(四舍五入)
|
||
* 入口参数:a_q10 - Q10 原值(工程量 × 1024) int32_t
|
||
* a_dec - 小数位 0..3 uint8_t
|
||
* 返回值:工程量 × 10^a_dec int32_t
|
||
* 限定条件:|a_q10| 在 int32 范围内且换算后仍在 int32 内(行表生成时已按
|
||
* g_prot_set_meta 的最大量程核过:最大项 PT 一次额定 500000 V,d=0)
|
||
* 函数说明:不用浮点也不用 64 位除法——MicroLIB 的 soft-float 与 __aeabi_ldiv
|
||
* 一进镜像就是几百字节,而模拟器(宿主 CRT)永远照不出这笔代价(本仓
|
||
* 反复记录的同一条口径)。做法是拆整数段与小数段:
|
||
* v = ip×1024 + fp(fp∈[0,1023],负数用算术右移取 floor,fp 仍非负),
|
||
* 小数段按 10^d 缩放后四舍五入,满 10^d 就进位回整数段。
|
||
* 误差上界半个最低显示位——与 prot_set 自己的 Q10 精度同源,
|
||
* 屏上显示 10.00A 而实际 10.0004A 不是本页造成的,是存储精度
|
||
*/
|
||
static int32_t sv_q10_to_scaled(int32_t a_q10, uint8_t a_dec) {
|
||
static const int32_t p10[4] = { 1, 10, 100, 1000 };
|
||
int32_t ip;
|
||
uint32_t fp;
|
||
int32_t r;
|
||
|
||
ip = a_q10 >> 10;
|
||
fp = (uint32_t)a_q10 & 0x3FFu;
|
||
r = ip * p10[a_dec];
|
||
if (a_dec != 0u) {
|
||
uint32_t fr = (fp * (uint32_t)p10[a_dec] + 512u) >> 10; /* 作用域收在这里 */
|
||
if (fr >= (uint32_t)p10[a_dec]) { /* 小数段进位(如 0.9996 → 1.000) */
|
||
r += p10[a_dec];
|
||
fr -= (uint32_t)p10[a_dec];
|
||
}
|
||
r += (int32_t)fr;
|
||
}
|
||
return r;
|
||
}
|
||
|
||
/*
|
||
* 函数功能:读某定值项的显示值(组件 get 回调)
|
||
* 入口参数:a_id - 行表登记的 id(= 枚举序) uint8_t
|
||
* 返回值:工程量 × 10^decimals int32_t
|
||
* 限定条件:ui_w_setview_sync() 已先跑过且 ui_w_setview_ready() 为真
|
||
* (页面在值列打 "--" 之前不会走到这里)
|
||
* 函数说明:id 越界(>39)返回 0 属防御性死支——行表是本文件内 const,越界 id
|
||
* 只可能来自代码改动错误,由主机单测在构建期前拦,不靠运行期兜
|
||
*/
|
||
static int32_t sv_get(uint8_t a_id) {
|
||
if (a_id >= (uint8_t)UI_DATA_SET_N) {
|
||
return 0;
|
||
}
|
||
return sv_q10_to_scaled(s_par.q10[a_id], s_dec[a_id]);
|
||
}
|
||
|
||
/*
|
||
* 函数功能:只读视图的写回调占位(组件契约要求非 NULL)
|
||
* 入口参数:a_id/a_val - 未使用
|
||
* 返回值:无
|
||
* 限定条件:查看视图不可编辑,组件不会调到这里
|
||
* 函数说明:刻意空实现——查看页**没有任何**该写进 RAM 工作副本的语义;
|
||
* 真要在查看页改值,得先把整定批次的 commit/state 一起接上
|
||
*/
|
||
static void sv_set_unused(uint8_t a_id, int32_t a_val) {
|
||
(void)a_id;
|
||
(void)a_val;
|
||
}
|
||
|
||
/*
|
||
* 函数功能:某数据行是否越界(组件 bad 回调 → 反显高亮)
|
||
* 入口参数:a_row - 数据行下标(不含保存行) uint16_t
|
||
* 返回值:true = 反显;false = 正常 bool
|
||
* 限定条件:uiTask 绘制链内;s_cur_rows 已由 attach 设定
|
||
* 函数说明:位图来自 prot_set_bad_mask()(上一次整表装载/提交后仍在量程外的项),
|
||
* 经 par 帧 bad_mask + bad_valid 下发。bad_valid=0 表示位图无意义
|
||
* (App 侧只在位图非 0 时置 1),此时一律不反显——把"没数据"画成
|
||
* "这行有问题"是假告警,比不画更糟
|
||
*/
|
||
static bool sv_bad(uint16_t a_row) {
|
||
const ui_w_setlist_row_t *r;
|
||
uint64_t bit;
|
||
|
||
if ((s_cur_rows == NULL) || (s_par_ok == 0u) || (s_par.bad_valid == 0u)) {
|
||
return false;
|
||
}
|
||
if (a_row >= s_cur_n) {
|
||
return false; /* 行号越界(组件不会给,防御:越界不反显也不越读) */
|
||
}
|
||
r = &s_cur_rows[a_row];
|
||
if (r->id >= (uint8_t)UI_DATA_SET_N) {
|
||
return false;
|
||
}
|
||
bit = (uint64_t)1u << r->id;
|
||
return (s_par.bad_mask & bit) != 0u;
|
||
}
|
||
|
||
/*
|
||
* 函数功能:按发布序号取参数帧快照(接各查看页 refresh 前调用)
|
||
* 入口参数:无
|
||
* 返回值:无
|
||
* 限定条件:uiTask 上下文(页面绘制链内);只读快照层,不写任何东西
|
||
* 函数说明:序号没变就一帧都不重拷(一帧约 184 B;四个查看页共用这份缓存——同屏
|
||
* 只可能开着一页,彼此之间不存在并发读者)。读取失败把序号打回不可能的值,
|
||
* 下一轮一定重试,不会停在半新不旧的帧上
|
||
*/
|
||
void ui_w_setview_sync(void) {
|
||
uint32_t seq = ui_data_par_seq();
|
||
|
||
if ((seq == s_par_seq) && (s_par_ok != 0u)) {
|
||
return; /* 序号未变:一帧都不重拷 */
|
||
}
|
||
/* ui_data_par() 的通道是 0=成功 / -1=尚无首帧 / -2=参数无效(快照层的既有约定,
|
||
* 不是布尔成败)——把它当 bool 用会反义:模拟器与真机上都会永远"读不到",
|
||
* 于是整页值列恒 "--",而页面看起来完全正常(本函数第一版就踩了这一条,
|
||
* 是看像素图才发现满屏横杠,静态检查看不出来) */
|
||
if (ui_data_par(&s_par) != 0) {
|
||
s_par_ok = 0u;
|
||
s_par_seq = 0xFFFFFFFFu; /* 失败态不认序号,下一轮一定重试 */
|
||
(void)memset(&s_par, 0, sizeof(s_par));
|
||
return;
|
||
}
|
||
s_par_seq = seq;
|
||
s_par_ok = (s_par.valid != 0u) ? 1u : 0u;
|
||
}
|
||
|
||
/*
|
||
* 函数功能:逐行取数(页面 refresh 的直直通:先同步参数帧,再走组件)
|
||
* 入口参数:a_inst - 实例 ui_w_setlist_t *;a_row - 行下标 uint16_t
|
||
* a_name/a_value - 框架行缓冲(UI_BUF_STRLEN) char *
|
||
* 返回值:无
|
||
* 限定条件:框架绘制链内(uiTask)
|
||
* 函数说明:**参数帧未就位时只把值列打成 "--",名字照打**——空值会被读成"这项是 0",
|
||
* 整页空白会让人以为菜单坏了;打出"名字 + --"才说得出真正的事实
|
||
* ("这张表在等参数帧")。帧就位后走组件:数值行按小数位 + 单位,
|
||
* 二态行打串表词
|
||
*/
|
||
void ui_w_setview_refresh(ui_w_setlist_t *a_inst, uint16_t a_row,
|
||
char *a_name, char *a_value) {
|
||
ui_w_setview_sync();
|
||
if (ui_w_setview_ready() != 0u) {
|
||
ui_w_setlist_refresh(a_inst, a_row, a_name, a_value);
|
||
return;
|
||
}
|
||
a_name[0] = '\0';
|
||
a_value[0] = '\0';
|
||
if ((a_inst != NULL) && (a_inst->rows != NULL) && (a_row < a_inst->count)) {
|
||
(void)lv_snprintf(a_name, UI_BUF_STRLEN, "%s", a_inst->rows[a_row].name);
|
||
}
|
||
(void)lv_snprintf(a_value, UI_BUF_STRLEN, "%s", SV_NO_DATA);
|
||
}
|
||
|
||
/*
|
||
* 函数功能:参数帧是否已就位
|
||
* 入口参数:无
|
||
* 返回值:1 = 有有效帧可显示;0 = 尚无首帧或读取失败 uint8_t
|
||
* 限定条件:uiTask 上下文;纯查询,无副作用
|
||
* 函数说明:返回 uint8_t 而不是 bool 是**本层约定**(bsp-err 的 err-type:BSP 公开 API
|
||
* 不得返回 bool——bool 把"为什么失败"整条丢掉,而这里虽然确实不需要原因,
|
||
* 也不能给整层开一个按名字豁免的例外;先例见 ui_w_setlist_key 的键分发标志)。
|
||
* 调用方拿它决定值列打换算值还是打 "--",没有错误要上报
|
||
*/
|
||
uint8_t ui_w_setview_ready(void) {
|
||
return s_par_ok;
|
||
}
|
||
|
||
/*
|
||
* 函数功能:取某视图的行表与行数(结构自测用;页面不需要,attach 时才自己取)
|
||
* 入口参数:a_view - 视图编号 ui_w_setview_t;a_n - 行数输出(不可为 NULL) uint16_t *
|
||
* 返回值:行表首地址;视图号非法返回 NULL const ui_w_setlist_row_t *
|
||
* 限定条件:只读;行表是 const Flash 表
|
||
* 函数说明:存在的理由是让主机单测能把四张表当成数据来核(id 是否恰好覆盖 0..39
|
||
* 各一次、二态行有没有串表、小数位与 dec 查表是否一致)。这些约束在
|
||
* 编译期看不出来,页面上也只有当前可见的 8 行会被像素断言看到——
|
||
* 第 2、3 页的行错了对齐,屏幕上要翻两页才看得见,而人不会去翻
|
||
*/
|
||
const ui_w_setlist_row_t *ui_w_setview_table(ui_w_setview_t a_view, uint16_t *a_n) {
|
||
if (a_n == NULL) {
|
||
return NULL;
|
||
}
|
||
switch (a_view) {
|
||
case UI_W_SETVIEW_PARAM:
|
||
*a_n = SV_ROW_N(s_rows_param);
|
||
return s_rows_param;
|
||
case UI_W_SETVIEW_SET:
|
||
*a_n = SV_ROW_N(s_rows_set);
|
||
return s_rows_set;
|
||
case UI_W_SETVIEW_WORD:
|
||
*a_n = SV_ROW_N(s_rows_word);
|
||
return s_rows_word;
|
||
case UI_W_SETVIEW_PLATE:
|
||
*a_n = SV_ROW_N(s_rows_plate);
|
||
return s_rows_plate;
|
||
default:
|
||
*a_n = 0u;
|
||
return NULL;
|
||
}
|
||
}
|
||
|
||
/*
|
||
* 函数功能:取 id → 显示小数位的查表(结构自测用)
|
||
* 入口参数:a_n - 表长输出(= UI_DATA_SET_N) uint16_t *
|
||
* 返回值:表首地址 const uint8_t *
|
||
* 限定条件:只读
|
||
*/
|
||
const uint8_t *ui_w_setview_dec_table(uint16_t *a_n) {
|
||
if (a_n != NULL) {
|
||
*a_n = (uint16_t)UI_DATA_SET_N;
|
||
}
|
||
return s_dec;
|
||
}
|
||
|
||
/*
|
||
* 函数功能:把某个查看视图绑到定值表实例(行表 + 取数 + 反显一次配齐)
|
||
* 入口参数:a_inst - 页面持有的实例(可为 NULL,NULL 直接返回) ui_w_setlist_t *
|
||
* a_view - 视图编号 ui_w_setview_t
|
||
* 返回值:无
|
||
* 限定条件:页面 init_cb 内调用(uiTask);每次开页都重新绑,不信任上一次的残留
|
||
* 函数说明:先 memset 再填 —— 组件实例里的编辑态跨页留着就是脏状态;视图号非法
|
||
* 给空表(页面退化成 0 行空页,比按错表导航安全)
|
||
*/
|
||
void ui_w_setview_attach(ui_w_setlist_t *a_inst, ui_w_setview_t a_view) {
|
||
if (a_inst == NULL) {
|
||
return;
|
||
}
|
||
(void)memset(a_inst, 0, sizeof(*a_inst));
|
||
switch (a_view) {
|
||
case UI_W_SETVIEW_PARAM:
|
||
a_inst->rows = s_rows_param;
|
||
a_inst->count = SV_ROW_N(s_rows_param);
|
||
break;
|
||
case UI_W_SETVIEW_SET:
|
||
a_inst->rows = s_rows_set;
|
||
a_inst->count = SV_ROW_N(s_rows_set);
|
||
break;
|
||
case UI_W_SETVIEW_WORD:
|
||
a_inst->rows = s_rows_word;
|
||
a_inst->count = SV_ROW_N(s_rows_word);
|
||
break;
|
||
case UI_W_SETVIEW_PLATE:
|
||
a_inst->rows = s_rows_plate;
|
||
a_inst->count = SV_ROW_N(s_rows_plate);
|
||
break;
|
||
default:
|
||
a_inst->rows = NULL;
|
||
a_inst->count = 0u;
|
||
break;
|
||
}
|
||
s_cur_rows = a_inst->rows;
|
||
s_cur_n = a_inst->count;
|
||
a_inst->get = sv_get;
|
||
a_inst->set = sv_set_unused;
|
||
a_inst->commit = NULL; /* NULL = 查看视图:无保存行、禁编辑(§3.2.6) */
|
||
a_inst->state = NULL;
|
||
a_inst->bad = sv_bad;
|
||
ui_w_setlist_reset(a_inst);
|
||
}
|