Welcome to the Parallax Discussion Forums, sign-up to participate.
--- Straight line algorithm for Tachyon 5v7 --- Useful for anywhere where a bunch of numbers have to change in fixed non-integer ratios to arrive simultaneously at a target --- e.g. vector graphics, multi-stepper control, sound synthesis, lighting faders PUBLIC 3 := AXES --- number of axes to run AXES 4* := AXESL --- byte loop count for the arrays of longs AXES longs POSN --- Start and present position array AXES longs GOAL --- the target array AXES longs ACC --- axis accumulator PRIVATE AXES longs DELTA --- set to GOAL minus initial POSN long TBASE --- timebase, set from the biggest DELTA long SLCOUNT --- counter to keep track of progress pri [SL] ( -- ) --- slarray indexer I 4* + ; --- inc or dec the I'th member of POSN, dependent on whether --- I'th member of DELTA is pos or neg pri STEPPOSN ( -- ) POSN [SL] DELTA [SL] @ 0< IF -- ELSE ++ THEN ; pri !DELTAS ( -- ) --- initialise DELTAS AXES FOR I 4* >R GOAL R@ + @ POSN R@ + @ - DELTA R> + ! NEXT ; --- TBASE set to the largest DELTA pri !TBASE ( -- ) 0 AXES FOR DELTA [SL] @ ABS MAX NEXT TBASE ! ; --- initialise straight line engine for new line pub !SLINIT ( starts goals -- ) ACC AXESL 0 FILL --- zero the accumulators GOAL AXESL CMOVE --- set the target position POSN AXESL CMOVE --- set the starting position 0 SLCOUNT ! !DELTAS --- calculate all goals minus starts !TBASE --- TBASE set to the largest DELTA ; --- step one place along the 'straight line', POSN is set to new position --- flg returned true if arrived at GOAL, else false pub SLSTEP ( -- flg ) AXES FOR ACC [SL] DUP @ DELTA [SL] @ ABS + ( ptr-to-ACC ACC+|DELTA| -- ) DUP ( ptr-to-ACC ACC+|DELTA| ACC+|DELTA| -- ) TBASE @ > ( ptr-to-ACC ACC+|DELTA| -- ) IF TBASE @ - ( ptr-to-ACC ACC+|DELTA|-TBASE -- ) STEPPOSN --- dec POSN if DELTA -ve, else inc POSN THEN SWAP ! ( -- ) --- and save new ACC value NEXT SLCOUNT @ TBASE @ = SLCOUNT ++ ; --- Test words TABLE MYSTART -15 , 10 , 13 , --- test start values TABLE MYGOAL 15 , 21 , -7 , --- test goal values --- test of !SLINIT pub test!SLINIT ( -- ) MYSTART MYGOAL !SLINIT ; --- print AXES size array of longs pub .ARR ( adr -- ) AXES FOR DUP [SL] @ . SPACE NEXT DROP ; --- Print all variables pub .SL ( -- ) CR ." POSN = " POSN .ARR CR ." GOAL = " GOAL .ARR CR ." DELTA = " DELTA .ARR CR ." TBASE = " TBASE @. CR ." SLCOUNT = " SLCOUNT @. CR ; --- demo that straight line alg. works pub SLDEMO ( -- ) MYSTART MYGOAL !SLINIT --- initialise straight line engine ." STRAIGHT LINE DEMO" CR .SL CR ." POSN steps by coordinates ..." CR BEGIN SLSTEP POSN .ARR CR UNTIL ." End of straight line" CR ; --- time the demo, so no printing in the loop pub SLTIME ( -- ) MYSTART MYGOAL !SLINIT --- initialise straight line engine ." STRAIGHT LINE TIMING DEMO" CR .SL CR ." POSN steps by coordinates ..." CR LAP BEGIN SLSTEP UNTIL LAP TBASE @ . ." Steps in " AXES . ." Axes took" CR .LAP CR ." End of straight line" CR ;Run SLDEMO to see the coordinates at each step. Run SLTIME to get some idea of how long the engine takes. So - I bet there's clever ways of making this faster - or has anyone got an even faster algorithm?. Might be good as part of a ROM? :-)