code wiki / (root) / nx_robot_timing.nx

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}