nx_robot_timing.nx source
↩ module page · 64 lines · 2669 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"
12import "nx_vecmath.nx"
13
14// proven integer sqrt (Newton, floor)
15func ti_isqrt(v: i64) -> i64 { return vm_isqrt(v) }
16
17// arrival time (timer ticks) of step k under constant-accel ramp: t(k) = isqrt(accel_k * k)
18func ti_arr(k: i64, accel_k: i64) -> i64 { return ti_isqrt(accel_k * k) }
19
20// FAIL-SAFE accel schedule: fill out_iv[0..n) with inter-step intervals from the ramp, each FLOORED
21// at min_iv (the never-brick max-rate cap). Returns n. Intervals start large then settle to min_iv.
22func schedule_accel(n: i64, accel_k: i64, min_iv: i64, out_iv: *i64) -> i64 {
23 var i: i64 = 0
24 while i < n {
25 var iv: i64 = ti_arr(i + 2, accel_k) - ti_arr(i + 1, accel_k)
26 if iv < min_iv { iv = min_iv } // never-brick floor = max step rate
27 out_iv[i] = iv
28 i = i + 1
29 }
30 return n
31}
32
33// the RAW (unclamped) interval at index i -- used ONLY by the gate's negative control
34func ti_raw_iv(i: i64, accel_k: i64) -> i64 { return ti_arr(i + 2, accel_k) - ti_arr(i + 1, accel_k) }
35
36// minimum interval over a schedule (for the never-brick check)
37func ti_min_iv(iv: *i64, n: i64) -> i64 {
38 if n <= 0 { return 0 }
39 var m: i64 = iv[0]
40 var i: i64 = 1
41 while i < n { if iv[i] < m { m = iv[i] } i = i + 1 }
42 return m
43}
44
45// cumulative time of the schedule (total move time)
46func ti_total(iv: *i64, n: i64) -> i64 {
47 var s: i64 = 0
48 var i: i64 = 0
49 while i < n { s = s + iv[i]; i = i + 1 }
50 return s
51}
52
53// TIMER-ISR model: how many steps have fired by time `now` (cumulative intervals <= now). Monotonic.
54func steps_fired_by(iv: *i64, n: i64, now: i64) -> i64 {
55 var s: i64 = 0
56 var c: i64 = 0
57 var i: i64 = 0
58 while i < n {
59 s = s + iv[i]
60 if s <= now { c = c + 1 }
61 i = i + 1
62 }
63 return c
64}