nx_robot_timing.nx source
↩ module page · 71 lines · 2841 B
1// nx_robot_timing.nx -- SOVEREIGN step-timing / timer-ISR rung (below the signal rung): turns a
2// step COUNT into a time-SCHEDULE of pulses. A real MCU drives steppers from a timer ISR that fires
3// STEP edges at computed intervals; acceleration = intervals that start large (slow) and shrink to a
4// cruise floor. Integer ramp via isqrt (arrival of step k ~ sqrt(k) under constant accel; classic
5// no-float stepper ramp). NO FLOAT.
6// NEVER-BRICK (#26) BY CONSTRUCTION: every inter-step interval is floored at MIN -> the instantaneous
7// STEP RATE can never exceed 1/MIN. This is the safety bound the signal rung could not enforce (it
8// had no time): a too-fast step train skips steps / overruns the driver / can damage the mechanism.
9// Here it is impossible by construction, and the gate proves it by exhaustive sweep.
10// license_tier: ORIGINAL expect_exit: 0
11import "nx_syscalls.nx"
12
13// proven integer sqrt (Newton, floor)
14func ti_isqrt(v: i64) -> i64 {
15 if v <= 0 { return 0 }
16 if v < 4 { return 1 }
17 var x: i64 = v
18 var y: i64 = (x + 1) >> 1
19 var go: i64 = 1
20 while go == 1 { if y < x { x = y; y = (x + v / x) >> 1 } else { go = 0 } }
21 return x
22}
23
24// arrival time (timer ticks) of step k under constant-accel ramp: t(k) = isqrt(accel_k * k)
25func ti_arr(k: i64, accel_k: i64) -> i64 { return ti_isqrt(accel_k * k) }
26
27// FAIL-SAFE accel schedule: fill out_iv[0..n) with inter-step intervals from the ramp, each FLOORED
28// at min_iv (the never-brick max-rate cap). Returns n. Intervals start large then settle to min_iv.
29func schedule_accel(n: i64, accel_k: i64, min_iv: i64, out_iv: *i64) -> i64 {
30 var i: i64 = 0
31 while i < n {
32 var iv: i64 = ti_arr(i + 2, accel_k) - ti_arr(i + 1, accel_k)
33 if iv < min_iv { iv = min_iv } // never-brick floor = max step rate
34 out_iv[i] = iv
35 i = i + 1
36 }
37 return n
38}
39
40// the RAW (unclamped) interval at index i -- used ONLY by the gate's negative control
41func ti_raw_iv(i: i64, accel_k: i64) -> i64 { return ti_arr(i + 2, accel_k) - ti_arr(i + 1, accel_k) }
42
43// minimum interval over a schedule (for the never-brick check)
44func ti_min_iv(iv: *i64, n: i64) -> i64 {
45 if n <= 0 { return 0 }
46 var m: i64 = iv[0]
47 var i: i64 = 1
48 while i < n { if iv[i] < m { m = iv[i] } i = i + 1 }
49 return m
50}
51
52// cumulative time of the schedule (total move time)
53func ti_total(iv: *i64, n: i64) -> i64 {
54 var s: i64 = 0
55 var i: i64 = 0
56 while i < n { s = s + iv[i]; i = i + 1 }
57 return s
58}
59
60// TIMER-ISR model: how many steps have fired by time `now` (cumulative intervals <= now). Monotonic.
61func steps_fired_by(iv: *i64, n: i64, now: i64) -> i64 {
62 var s: i64 = 0
63 var c: i64 = 0
64 var i: i64 = 0
65 while i < n {
66 s = s + iv[i]
67 if s <= now { c = c + 1 }
68 i = i + 1
69 }
70 return c
71}