nx_robot_step_gate.nx source
↩ module page · 111 lines · 4934 B
1// nx_robot_step_gate.nx -- R-ROBO-1 GATE: multi-axis stepper step generation (the actuation
2// primitive). Commands a synchronized 3-axis move (X=+20, Y=+8, Z=-5 steps), generates the pulse
3// plan via nx_robot_step, and VERIFIES: each axis emits EXACTLY |delta| pulses, directions are
4// correct, the final reconstructed position equals the target EXACTLY (integer, no drift), and the
5// Bresenham invariant holds on every minor axis (max deviation == 0..nt, i.e. evenly distributed).
6// NEGATIVE CONTROL: a deliberately front-loaded (non-Bresenham) sequence VIOLATES the invariant
7// (deviation > nt), proving the evenness check has teeth. 100% sovereign, integer-only.
8// license_tier: ORIGINAL expect_exit: 0
9import "nx_syscalls.nx"
10import "nx_robot_step.nx"
11
12func sw(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
13func sn(v: i64) -> i64 {
14 if v == 0 { sys_write(1, "0" as *u8, 1); return 0 }
15 var m: i64 = v
16 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m }
17 let d: *u8 = sys_mmap(24); var k: i64 = 0
18 while m > 0 { d[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
19 let o: *u8 = sys_mmap(24); var i: i64 = 0
20 while i < k { o[i] = d[k - 1 - i]; i = i + 1 }
21 sys_write(1, o, k); return 0
22}
23
24func check(name: *u8, cond: i64, tot: *i64) -> i64 {
25 if cond == 1 { sw(" ok " as *u8); tot[0] = tot[0] + 1 }
26 else { sw(" FAIL " as *u8); tot[1] = tot[1] + 1 }
27 sw(name); sw("\n" as *u8)
28 return 0
29}
30
31func abs_i(v: i64) -> i64 { if v < 0 { return 0 - v } return v }
32
33func main() -> i64 {
34 let tot: *i64 = sys_mmap(16) as *i64
35 tot[0] = 0; tot[1] = 0
36
37 sw("=== nx_robot_step_gate R-ROBO-1 -- multi-axis stepper step generation (integer Bresenham) ===\n" as *u8)
38
39 let naxes: i64 = 3
40 let delta: *i64 = sys_mmap(64) as *i64
41 delta[0] = 20; delta[1] = 8; delta[2] = 0 - 5 // X=+20, Y=+8, Z=-5
42 let dir: *i64 = sys_mmap(64) as *i64
43 let max_ticks: i64 = 256
44 let puls: *i64 = sys_mmap(max_ticks * naxes * 8) as *i64
45
46 let nt: i64 = robot_step_plan(delta, naxes, dir, puls, max_ticks)
47 sw(" n_ticks=" as *u8); sn(nt); sw(" (=max|delta|, the major axis)\n" as *u8)
48
49 // directions
50 var okdir: i64 = 0
51 if dir[0] == 1 { if dir[1] == 1 { if dir[2] == (0 - 1) { okdir = 1 } } }
52 check("directions correct (X+ Y+ Z-)" as *u8, okdir, tot)
53
54 // exact pulse counts per axis
55 var i: i64 = 0
56 var okcount: i64 = 1
57 while i < naxes {
58 let c: i64 = robot_step_count(puls, naxes, nt, i)
59 if c != abs_i(delta[i]) { okcount = 0 }
60 sw(" axis " as *u8); sn(i); sw(" pulses=" as *u8); sn(c); sw(" expected=" as *u8); sn(abs_i(delta[i])); sw("\n" as *u8)
61 i = i + 1
62 }
63 check("each axis emits EXACTLY |delta| pulses" as *u8, okcount, tot)
64
65 // final reconstructed position == target (exact integer, no drift)
66 var okpos: i64 = 1
67 i = 0
68 while i < naxes {
69 let c: i64 = robot_step_count(puls, naxes, nt, i)
70 let pos: i64 = c * dir[i]
71 if pos != delta[i] { okpos = 0 }
72 i = i + 1
73 }
74 check("final reconstructed position == commanded target (exact)" as *u8, okpos, tot)
75
76 // major axis pulses every tick
77 var cmaj: i64 = robot_step_count(puls, naxes, nt, 0)
78 var okmaj: i64 = 0
79 if cmaj == nt { okmaj = 1 }
80 check("major axis X pulses every tick (cmaj==nt)" as *u8, okmaj, tot)
81
82 // Bresenham invariant on minor axes: max deviation must be <= nt (evenly distributed)
83 let devY: i64 = robot_step_max_dev(puls, naxes, nt, 1, abs_i(delta[1]))
84 let devZ: i64 = robot_step_max_dev(puls, naxes, nt, 2, abs_i(delta[2]))
85 sw(" Bresenham maxdev Y=" as *u8); sn(devY); sw(" Z=" as *u8); sn(devZ); sw(" bound=" as *u8); sn(nt); sw("\n" as *u8)
86 var okbres: i64 = 0
87 if devY <= nt { if devZ <= nt { okbres = 1 } }
88 check("Bresenham invariant holds on minor axes (maxdev <= nt)" as *u8, okbres, tot)
89
90 // NEGATIVE CONTROL: front-load Y's 8 pulses into the first 8 ticks -> must VIOLATE the invariant
91 let bad: *i64 = sys_mmap(max_ticks * naxes * 8) as *i64
92 var t: i64 = 0
93 while t < nt {
94 bad[t * naxes + 0] = 1 // X every tick (fine)
95 var py: i64 = 0
96 if t < 8 { py = 1 } // all 8 Y pulses crammed up front
97 bad[t * naxes + 1] = py
98 bad[t * naxes + 2] = 0
99 t = t + 1
100 }
101 let baddev: i64 = robot_step_max_dev(bad, naxes, nt, 1, abs_i(delta[1]))
102 sw(" front-loaded Y maxdev=" as *u8); sn(baddev); sw(" (must exceed bound " as *u8); sn(nt); sw(")\n" as *u8)
103 var negok: i64 = 0
104 if baddev > nt { negok = 1 }
105 check("NEG-CONTROL: front-loaded sequence VIOLATES invariant (check has teeth)" as *u8, negok, tot)
106
107 sw("=== VERDICT pass=" as *u8); sn(tot[0]); sw(" fail=" as *u8); sn(tot[1]); sw(" ===\n" as *u8)
108 if tot[1] == 0 { sys_exit(0) }
109 sys_exit(1)
110 return 1
111}