code wiki / (root) / nx_print_telemetry_test.nx

nx_print_telemetry_test.nx source

↩ module page · 120 lines · 4942 B

1// nx_print_telemetry_test.nx -- exercise the unified telemetry 2// pump across all 4 enabled surfaces. 3// 4// Closed-form invariants: 5// (a) Empty event (all has_* = 0): no issue, no count 6// (b) Motion-only event with normal values: no issue 7// (c) Motion + thermal + runout + shift all populated, normal: no issue 8// (d) Shift drift fires LAYER_SHIFT (priority 1) 9// (e) When multiple kinds fire on one tick, returned verdict is 10// the priority-1 winner BUT n_issues_total counts all fires 11// (f) Partial population: has_motion=1, others 0; runout sensor 12// set but has_runout=0 -> no runout fire 13// (g) Null m / null ev returns NONE 14// 15// expect_exit: 0 16// license_tier: ORIGINAL 17 18import "nx_syscalls.nx" 19import "nx_print_runtime_monitor.nx" 20import "nx_print_telemetry.nx" 21 22const Q14: i64 = 16384 23 24func main() -> i64 { 25 let m: *NxRuntimeMonitor = nx_runtime_monitor_new(5000, 3, 5 * Q14, 2 * Q14) 26 if (m as i64) == 0 { return 5 } 27 nx_runtime_monitor_set_thermal(m, 2, 2000) 28 nx_runtime_monitor_set_layer_shift_tolerance(m, (3 * Q14) / 10) 29 30 // ===== (a) Empty event: no issue ===== 31 let e0: *NxPrintTelemetry = nx_print_telemetry_new() 32 if (e0 as i64) == 0 { return 6 } 33 let v0: i64 = nx_runtime_monitor_pump_telemetry(m, e0) 34 if v0 != NX_RT_ISSUE_NONE { return 10 } 35 if m.n_issues_total != 0 { return 11 } 36 37 // ===== (b) Motion-only event, normal ===== 38 let e1: *NxPrintTelemetry = nx_print_telemetry_new() 39 e1.event_time_ms = 0 40 e1.z_q14 = 0 41 e1.e_q14 = 0 42 e1.xy_delta_q14 = 0 43 e1.has_motion = 1 44 if nx_runtime_monitor_pump_telemetry(m, e1) != NX_RT_ISSUE_NONE { return 20 } 45 // Second event progresses normally 46 let e1b: *NxPrintTelemetry = nx_print_telemetry_new() 47 e1b.event_time_ms = 5000 48 e1b.z_q14 = Q14 / 5 // 0.2mm 49 e1b.e_q14 = 10 * Q14 50 e1b.xy_delta_q14 = 50 * Q14 51 e1b.has_motion = 1 52 if nx_runtime_monitor_pump_telemetry(m, e1b) != NX_RT_ISSUE_NONE { return 21 } 53 if m.n_issues_total != 0 { return 22 } 54 55 // ===== (c) All four surfaces populated, normal values ===== 56 let e2: *NxPrintTelemetry = nx_print_telemetry_new() 57 e2.event_time_ms = 10000 58 e2.z_q14 = 2 * Q14 / 5 59 e2.e_q14 = 20 * Q14 60 e2.xy_delta_q14 = 50 * Q14 61 e2.has_motion = 1 62 e2.bed_actual_c = 60 63 e2.bed_setpoint_c = 60 64 e2.hotend_actual_c = 210 65 e2.hotend_setpoint_c = 210 66 e2.chamber_actual_c = 30 67 e2.chamber_setpoint_c = 30 68 e2.has_thermal = 1 69 e2.runout_triggered = 0 70 e2.has_runout = 1 71 e2.commanded_x_q14 = 100 * Q14 72 e2.actual_x_q14 = 100 * Q14 73 e2.commanded_y_q14 = 100 * Q14 74 e2.actual_y_q14 = 100 * Q14 75 e2.has_shift = 1 76 if nx_runtime_monitor_pump_telemetry(m, e2) != NX_RT_ISSUE_NONE { return 30 } 77 78 // ===== (d) Shift drift fires LAYER_SHIFT (priority 1) ===== 79 let e3: *NxPrintTelemetry = nx_print_telemetry_new() 80 e3.event_time_ms = 15000 81 e3.commanded_x_q14 = 100 * Q14 82 e3.actual_x_q14 = 100 * Q14 - Q14 // 1mm drift > 0.3mm tol 83 e3.commanded_y_q14 = 100 * Q14 84 e3.actual_y_q14 = 100 * Q14 85 e3.has_shift = 1 86 let v3: i64 = nx_runtime_monitor_pump_telemetry(m, e3) 87 if v3 != NX_RT_ISSUE_LAYER_SHIFT { return 40 } 88 89 // ===== (e) Multiple kinds fire on one tick -> priority winner returned, 90 // n_issues_total counts every fire. 91 let pre_count: i64 = m.n_issues_total 92 let e4: *NxPrintTelemetry = nx_print_telemetry_new() 93 e4.event_time_ms = 20000 94 e4.commanded_x_q14 = 100 * Q14 95 e4.actual_x_q14 = 100 * Q14 - Q14 // drift -> LAYER_SHIFT 96 e4.commanded_y_q14 = 100 * Q14 97 e4.actual_y_q14 = 100 * Q14 98 e4.has_shift = 1 99 e4.runout_triggered = 1 // edge 0->1 -> RUNOUT 100 e4.has_runout = 1 101 let v4: i64 = nx_runtime_monitor_pump_telemetry(m, e4) 102 if v4 != NX_RT_ISSUE_LAYER_SHIFT { return 50 } // priority 1 wins 103 // Both fired: count incremented by 2 104 if m.n_issues_total != pre_count + 2 { return 51 } 105 106 // ===== (f) Partial population: has_runout = 0, runout_triggered = 1 107 // -> no runout fire ===== 108 let m2: *NxRuntimeMonitor = nx_runtime_monitor_new(5000, 3, 5 * Q14, 2 * Q14) 109 let e5: *NxPrintTelemetry = nx_print_telemetry_new() 110 e5.runout_triggered = 1 111 e5.has_runout = 0 // explicitly skip runout surface 112 if nx_runtime_monitor_pump_telemetry(m2, e5) != NX_RT_ISSUE_NONE { return 60 } 113 if m2.n_issues_total != 0 { return 61 } 114 115 // ===== (g) Null guards ===== 116 if nx_runtime_monitor_pump_telemetry(0 as *NxRuntimeMonitor, e0) != NX_RT_ISSUE_NONE { return 70 } 117 if nx_runtime_monitor_pump_telemetry(m, 0 as *NxPrintTelemetry) != NX_RT_ISSUE_NONE { return 71 } 118 119 return 0 120}