feat(104遥测): 卡9改读L2快照+死区运行化2点确认 + 卡11绑频0x401D(道D M5/M6)
卡 9(App/protocol/iec104/iec104_pts.*,「数据可信」,docs/子系统设计/ IEC104上行设计说明.md §3.1/§4 同步): - 数据源换轨:板端默认 YC 源从直读 phasor 改为**整体透传 L2 遥测快照** (meas_get 双区无锁;"新不新、能不能信"只在发布侧判一次,M5-② 落地); iec104_pts_src_t 表尾追加 yc_read_ex(带品质)——旧注入源走 legacy 退路, 品质由返回值推导,行为与卡 9 前**完全一致**(存量假源用例零改动) - 品质映射 s_q_map:MEAS_QDS_* 低字节=线上 QDS 同值直传;CLIPPED→IV (「削顶通道 104 恒 IV」口径不变、从点表绑死 -1 改品质驱动——UB/UC/IB/ IC/IN 五路现绑快照槽,V0.2/N-18 削顶消失后**零改动自动启用**);IV 优先 NT;快照从未发布(开机 <200ms)→ IV|NT;无效信息体清零(旧线上口径保持) - 死区运行化:运行时副本 s_yc_db(ROM 默认 = 点表列,卡 6 额定 0.5% 档不变) + iec104_pts_yc_set_deadband()/iec104_pts_yc_deadband()——卡 10 运行参数段 (8020H)的接线点已留;非法 idx/负值/NaN 拒绝、成功时清该点待确认计数 - COV 遥测腿升级(lead 裁②"卡 9 是消费者"):判定 = 相对**上次上送值**(非 上次读值,防慢漂移吃基准)连续 2 个新测量点越死区才确认上送;回摆入带即 撤销候选;品质翻转当拍直报(含 0x401D 的 IV 进出)。测量点推进:板端按 快照 seq 去重(100ms poll vs 200ms 快照——不去重则同一帧把单点噪声计满 2 点,抗噪语义失效);注入源=每次调用一测点(单测步进自持) 卡 11:YC 表加 src 类型(PTS_SRC_MEAS/FREQ);0x401D 绑快照 freq_hz(与 freq_get 同源);snap.freq_valid==0 → IV 清零(卡 11 DoD 原句) 测试与文档:test/host/iec104 97→127 断言——TC-008 语义更新为 2 点确认; 新 TC-IEC104-025~028(024 号被存量 B7 用例裸标签占用,让号并改用全家长 形态)板端默认源走**真实 L2 链**(ring→phasor→freq→meas,非桩):未发布 NT/值透传/CLIPPED→IV 清零/绑频收敛 ±0.02Hz/未新鲜 IV/死区运行档压旧档/ 回摆撤销/seq 去重同帧不计数/换帧只变品质按集合直报;id_registry 族游标 023→028;IEC104 上行设计说明 §3.1 表+注/§4/§7/§8 第 4 条/变更记录同步。 无新 .c(uvprojx 零改动);PC 主站读回一致与频率 ±0.01Hz 属网络对端验证 ——步骤清单已发 lead 排窗,本轮零台架动作。 gate:@build 0 错 0 警(Code=218128 RO=21624 RW=1272 ZI=132864);增量 vs adeef7d:Flash +348B、RAM(RW+ZI) +48B(低于 96B 预估,链接器并洞), IRAM1 58.5% 不变;iec104Task 栈 worst=1456B margin=1104B(43%) PASS 无抬栈 (stack_report);--all-files 全量实跑:其余钩子全绿(含修掉一处 cppcheck variableScope 后),仅 mem-budget + mem-numbers 两红 = 台账受管区 vs .map 漂移(回填属 lead 单写者区,批 1/道D-1 同口径): gate: only mem-budget/mem-numbers pending lead ledger backfill BOM/CR/U+FFFD/字面量 ASCII 逐文件自查通过(未触碰带 BOM 文件)。
This commit is contained in:
@@ -17,7 +17,8 @@
|
||||
* TC-IEC104-005 OPEN 态 I 帧忽略(序号不消费)
|
||||
* TC-IEC104-006 总召全流程:actcon→4 分片(首召 COT=4)→actterm;二召 COT=2;RBT→COT=4
|
||||
* TC-IEC104-007 遥信变位 COV(COT=3);无效位不触发
|
||||
* TC-IEC104-008 遥测死区 COV:死区内不发 / 越死区发
|
||||
* TC-IEC104-008 遥测死区 COV(卡 9 起 = 2 点确认):死区内不发 / 首越只挂起 /
|
||||
* 连续第 2 越点上送
|
||||
* TC-IEC104-009 k 窗:12 未确认停发;S 确认后恢复
|
||||
* TC-IEC104-010 w 阈:收满 8 发 S
|
||||
* TC-IEC104-011 t2 到期发 S
|
||||
@@ -33,6 +34,17 @@
|
||||
* TC-IEC104-021 C_TS / C_RP actcon
|
||||
* TC-IEC104-022 周期上送 COT=1(YC 组 + 频率)
|
||||
* TC-IEC104-023 k 窗满 COV 不丢事件(pend 暂存,窗开后补发)
|
||||
* —— 以下为「数据可信」卡 9/卡 11(道D,2026-10-25;板端默认源 = 真实
|
||||
L2 链 ring→phasor→freq→meas,非桩)——
|
||||
* TC-IEC104-025 板端源读快照(024 号被存量 B7 用例的裸标签占用):未发布
|
||||
* IV|NT / 值=基波有效值 / 削顶 CLIPPED
|
||||
* →线上 IV 清零 / 干净路品质 0 / 频率未新鲜 IV
|
||||
* TC-IEC104-026 0x401D 绑频:收敛后 ±0.02 Hz / freq_valid==0 → IV 清零
|
||||
* (卡 11 DoD 原句)
|
||||
* TC-IEC104-027 死区运行时化:set/get + 非法拒 + 运行档压住旧档步长 +
|
||||
* 2 点确认/回摆撤销/init 复位 ROM 默认
|
||||
* TC-IEC104-028 品质翻转直报(假源)+ 板端 seq 去重(同帧不计两点)+
|
||||
* 换帧只变品质时按集合直报
|
||||
*
|
||||
* 通过:全部 TC PASS(main 返回 0)。
|
||||
* 创建日期:2026-10-12(B4)
|
||||
@@ -54,6 +66,7 @@ static int s_total = 0, s_passed = 0, s_failed = 0;
|
||||
#include "sample_ring.c"
|
||||
#include "phasor.c"
|
||||
#include "freq.c"
|
||||
#include "meas.c" /* 卡 9:板端默认 YC 源 = L2 遥测快照(真实链,非桩) */
|
||||
#include "prot_elm.c"
|
||||
#include "iec104_pts.c"
|
||||
#include "iec104_link.c"
|
||||
@@ -515,11 +528,14 @@ static void tc_cov_yc(void)
|
||||
* 旧拟定码值死区 10 已由「数据可信」卡 6 重定) */
|
||||
iec104_link_poll(&g_lk, now + 100u);
|
||||
CHECK(cap_i_count() == 0, "TC-008 inside the deadband nothing is uploaded");
|
||||
s_f_yc[0] = 101.25f; /* 101.25-100.4=0.85 > 0.5 */
|
||||
s_f_yc[0] = 101.25f; /* 101.25-100=1.25 > 0.5,第 1 越点 */
|
||||
iec104_link_poll(&g_lk, now + 200u);
|
||||
CHECK(cap_i_count() == 0, "TC-IEC104-008 first deadband crossing only arms (2-point confirm)");
|
||||
iec104_link_poll(&g_lk, now + 300u); /* 第 2 个连续测点仍越 -> 确认上送 */
|
||||
CHECK((cap_i_count() == 1) && (cap_i(0, &c) == 0) && (c.type == 13u)
|
||||
&& (c.cot == IEC104_COT_SPONT) && (c.ioa == 0x4011u)
|
||||
&& (iec104_get_float(c.obj) == 101.25f), "TC-008 crossing the deadband uploads");
|
||||
&& (iec104_get_float(c.obj) == 101.25f),
|
||||
"TC-IEC104-008 second consecutive crossing uploads (Card 9 confirm)");
|
||||
}
|
||||
|
||||
static void feed_rd(uint32_t now)
|
||||
@@ -912,6 +928,178 @@ static void tc_cov_kfull(void)
|
||||
&& (c.cot == IEC104_COT_SPONT), "TC-023 once the window opens the backlogged event is sent, none lost");
|
||||
}
|
||||
|
||||
/* ========== 卡 9/卡 11:板端默认源(真实 L2 链:ring→phasor→freq→meas) ========== */
|
||||
|
||||
/* 与 App/task/adc_task.c 同型的单拍编排:压环 → phasor_run →(可选 freq_run)。
|
||||
* 9 路同幅错相正弦(整周波 → 各路基波有效值 = A/√2,与相位无关,期望好算) */
|
||||
static double s_ph2 = 0.0;
|
||||
static void snap_beats(int n, double amp, int run_freq)
|
||||
{
|
||||
float f[ADC_SEM_COUNT];
|
||||
int i;
|
||||
int s;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
for (s = 0; s < (int)ADC_SEM_TEMP; s++) {
|
||||
f[s] = (float)(amp * sin(s_ph2 + (double)s * 0.35));
|
||||
}
|
||||
f[ADC_SEM_TEMP] = 1234.0f;
|
||||
s_ph2 += 2.0 * 3.14159265358979323846 * 50.0 / 1000.0; /* 50 Hz */
|
||||
(void)sample_ring_push_frame(f, (uint8_t)ADC_SEM_COUNT);
|
||||
phasor_run();
|
||||
if (run_freq != 0) {
|
||||
freq_run();
|
||||
}
|
||||
}
|
||||
}
|
||||
/* 200 ms 发布拍(读同拍 freq 状态,adc_task v3.2 编排的镜像) */
|
||||
static void snap_pub(uint32_t ms, uint32_t clip_mask)
|
||||
{
|
||||
meas_tick(ms, freq_valid(), freq_last(), clip_mask);
|
||||
}
|
||||
|
||||
static void tc_pts_snap(void)
|
||||
{
|
||||
float v;
|
||||
uint8_t q;
|
||||
|
||||
reset_all(1000u);
|
||||
iec104_pts_bind_src(NULL); /* 板端默认源 = 真实快照链 */
|
||||
(void)phasor_init(); /* 环 + 相量双区清零 */
|
||||
(void)meas_init();
|
||||
CHECK((iec104_pts_yc_read(0u, &v, &q) == -1)
|
||||
&& (q == (uint8_t)(IEC104_QDS_IV | IEC104_QDS_NT)) && (v == 0.0f),
|
||||
"TC-IEC104-025 before first publish -> IV|NT, value zero");
|
||||
snap_beats(20, 100.0, 0);
|
||||
snap_pub(200u, 0xE6u); /* 削顶位图同板端默认构建(cl=0xE6) */
|
||||
CHECK((iec104_pts_yc_read(0u, &v, &q) == 0) && (q == 0u)
|
||||
&& (fabsf(v - 70.711f) < 0.1f),
|
||||
"TC-IEC104-025 UA = snapshot fundamental RMS (engineering domain)");
|
||||
CHECK((iec104_pts_yc_read(3u, &v, &q) == 0) && (q == 0u),
|
||||
"TC-IEC104-025 UN (bit3 not in 0xE6) stays valid");
|
||||
CHECK((iec104_pts_yc_read(4u, &v, &q) == 0) && (q == 0u),
|
||||
"TC-IEC104-025 IA valid");
|
||||
CHECK((iec104_pts_yc_read(1u, &v, &q) == -1) && (q == IEC104_QDS_IV)
|
||||
&& (v == 0.0f), "TC-IEC104-025 clipped UB: CLIPPED maps to wire IV, value zero");
|
||||
CHECK((iec104_pts_yc_read(2u, &v, &q) == -1) && (q == IEC104_QDS_IV),
|
||||
"TC-IEC104-025 clipped UC IV");
|
||||
CHECK((iec104_pts_yc_read(5u, &v, &q) == -1) && (q == IEC104_QDS_IV),
|
||||
"TC-IEC104-025 clipped IB IV");
|
||||
CHECK((iec104_pts_yc_read(8u, &v, &q) == -1) && (q == IEC104_QDS_IV),
|
||||
"TC-IEC104-025 freq point published but not fresh -> IV (Card 11 rule)");
|
||||
}
|
||||
|
||||
static void tc_pts_freq(void)
|
||||
{
|
||||
float v;
|
||||
uint8_t q;
|
||||
int k;
|
||||
|
||||
reset_all(1000u);
|
||||
iec104_pts_bind_src(NULL);
|
||||
(void)phasor_init();
|
||||
(void)freq_init();
|
||||
(void)meas_init();
|
||||
for (k = 0; k < 5; k++) { /* 100 拍:测频启动收敛需 20 拍 */
|
||||
snap_beats(20, 100.0, 1);
|
||||
snap_pub((uint32_t)(k + 1) * 200u, 0u);
|
||||
}
|
||||
CHECK(freq_valid() == 1u, "TC-IEC104-026 drive precondition: freq converged");
|
||||
CHECK((iec104_pts_yc_read(8u, &v, &q) == 0) && (q == 0u)
|
||||
&& (fabsf(v - 50.0f) <= 0.02f),
|
||||
"TC-IEC104-026 0x401D carries freq reading within 0.02 Hz of synthetic 50.000");
|
||||
for (k = 0; k < 3; k++) { /* 浮空:幅值门落下 */
|
||||
snap_beats(20, 0.0, 1);
|
||||
snap_pub((uint32_t)(6 + k) * 200u, 0u);
|
||||
}
|
||||
CHECK((freq_valid() == 0u) && (iec104_pts_yc_read(8u, &v, &q) == -1)
|
||||
&& (q == IEC104_QDS_IV) && (v == 0.0f),
|
||||
"TC-IEC104-026 freq_valid==0 -> IV with zeroed value (Card 11 DoD)");
|
||||
}
|
||||
|
||||
static void tc_db_runtime(void)
|
||||
{
|
||||
iec104_pts_cov_t cov;
|
||||
|
||||
reset_all(1000u); /* 假源在场 = 每次 cov_check 一测点 */
|
||||
CHECK((iec104_pts_yc_set_deadband(0u, 2.0f) == 0)
|
||||
&& (iec104_pts_yc_deadband(0u) == 2.0f),
|
||||
"TC-IEC104-027 runtime deadband write + readback");
|
||||
CHECK((iec104_pts_yc_set_deadband(9u, 1.0f) == -1)
|
||||
&& (iec104_pts_yc_set_deadband(0u, -0.1f) == -1)
|
||||
&& (iec104_pts_yc_deadband(0u) == 2.0f),
|
||||
"TC-IEC104-027 bad idx / negative rejected, RAM untouched");
|
||||
CHECK(iec104_pts_yc_deadband(8u) == 0.5f, "TC-IEC104-027 freq point ROM default kept");
|
||||
s_f_yc[0] = 100.0f;
|
||||
iec104_pts_cov_check(&cov); /* 建线 rep=100(档 2.0) */
|
||||
s_f_yc[0] = 101.0f; /* 越旧档 0.5、未越运行档 2.0 */
|
||||
iec104_pts_cov_check(&cov);
|
||||
CHECK((cov.yc_changed & 0x0001u) == 0u, "TC-IEC104-027 runtime db gates the old step");
|
||||
iec104_pts_cov_check(&cov);
|
||||
CHECK((cov.yc_changed & 0x0001u) == 0u, "TC-IEC104-027 2nd point under 2.0 still silent");
|
||||
|
||||
iec104_pts_init(); /* 恢复 ROM 默认档(0.5) */
|
||||
iec104_pts_bind_src(&g_fake);
|
||||
s_f_yc[0] = 100.0f;
|
||||
iec104_pts_cov_check(&cov); /* 建线 */
|
||||
s_f_yc[0] = 100.6f; /* d=0.6 > 0.5,第 1 越 */
|
||||
iec104_pts_cov_check(&cov);
|
||||
CHECK((cov.yc_changed & 0x0001u) == 0u, "TC-IEC104-027 crossing arms only (2-point)");
|
||||
iec104_pts_cov_check(&cov);
|
||||
CHECK((cov.yc_changed & 0x0001u) != 0u, "TC-IEC104-027 second consecutive crossing confirms");
|
||||
s_f_yc[0] = 101.4f; /* 新基准 100.6 起 d=0.8 第 1 越 */
|
||||
iec104_pts_cov_check(&cov);
|
||||
CHECK((cov.yc_changed & 0x0001u) == 0u, "TC-IEC104-027 pullback test step 1 armed");
|
||||
s_f_yc[0] = 100.8f; /* 回摆入死区 -> 撤销候选 */
|
||||
iec104_pts_cov_check(&cov);
|
||||
s_f_yc[0] = 101.4f; /* 重新起算:单点不报 */
|
||||
iec104_pts_cov_check(&cov);
|
||||
CHECK((cov.yc_changed & 0x0001u) == 0u, "TC-IEC104-027 pullback cleared pending count");
|
||||
iec104_pts_cov_check(&cov);
|
||||
CHECK((cov.yc_changed & 0x0001u) != 0u, "TC-IEC104-027 two fresh crossings confirm again");
|
||||
}
|
||||
|
||||
static void tc_cov_qds_seq(void)
|
||||
{
|
||||
iec104_pts_cov_t cov;
|
||||
|
||||
reset_all(1000u); /* 假源段:品质翻转 */
|
||||
s_f_yc[1] = 50.0f;
|
||||
iec104_pts_cov_check(&cov);
|
||||
s_f_yc_rc[1] = -1;
|
||||
iec104_pts_cov_check(&cov);
|
||||
CHECK((cov.yc_changed & 0x0002u) != 0u, "TC-IEC104-028 valid->IV reported at once");
|
||||
iec104_pts_cov_check(&cov);
|
||||
CHECK((cov.yc_changed & 0x0002u) == 0u, "TC-IEC104-028 IV steady state not repeated");
|
||||
s_f_yc_rc[1] = 0;
|
||||
iec104_pts_cov_check(&cov);
|
||||
CHECK((cov.yc_changed & 0x0002u) != 0u, "TC-IEC104-028 IV->valid recovery reported at once");
|
||||
|
||||
iec104_pts_init(); /* 板端段:seq 去重 */
|
||||
iec104_pts_bind_src(NULL);
|
||||
(void)phasor_init();
|
||||
(void)meas_init();
|
||||
snap_beats(20, 100.0, 0);
|
||||
snap_pub(200u, 0u); /* seq=1 */
|
||||
iec104_pts_cov_check(&cov); /* 建线帧 */
|
||||
CHECK(cov.yc_changed == 0u, "TC-IEC104-028 baseline frame silent");
|
||||
snap_beats(20, 200.0, 0);
|
||||
snap_pub(400u, 0u); /* seq=2:第 1 越点 */
|
||||
iec104_pts_cov_check(&cov);
|
||||
CHECK((cov.yc_changed & 0x0001u) == 0u, "TC-IEC104-028 one new frame arms only");
|
||||
iec104_pts_cov_check(&cov);
|
||||
iec104_pts_cov_check(&cov); /* 无换帧:不得计为第 2 点 */
|
||||
CHECK((cov.yc_changed & 0x0001u) == 0u, "TC-IEC104-028 same frame never counts twice");
|
||||
snap_beats(20, 200.0, 0);
|
||||
snap_pub(600u, 0u); /* seq=3:连续第 2 越点 */
|
||||
iec104_pts_cov_check(&cov);
|
||||
CHECK((cov.yc_changed & 0x0001u) != 0u, "TC-IEC104-028 second new frame confirms");
|
||||
snap_pub(800u, 0xE6u); /* 换帧仅变品质(削顶注入) */
|
||||
iec104_pts_cov_check(&cov);
|
||||
CHECK((cov.yc_changed & 0x00E6u) == 0x00E6u,
|
||||
"TC-IEC104-028 clipped flip per frame reported as a set");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("=== IEC104 Protocol Stack Host Tests ===\n");
|
||||
@@ -939,6 +1127,10 @@ int main(void)
|
||||
tc_ts_rp();
|
||||
tc_periodic();
|
||||
tc_cov_kfull();
|
||||
tc_pts_snap();
|
||||
tc_pts_freq();
|
||||
tc_db_runtime();
|
||||
tc_cov_qds_seq();
|
||||
printf("=== IEC104 Tests: %d/%d PASSED (failed=%d) ===\n",
|
||||
s_passed, s_total, s_failed);
|
||||
return (s_failed == 0) ? 0 : 1;
|
||||
|
||||
Reference in New Issue
Block a user