code wiki / (root) / nx_robot_timing.nx

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}