Cliff Hacks Things.

Monday, May 19, 2008

Trig in PropellerForth

Among many other nice features, the Parallax Propeller microcontroller has a single-quadrant sine table in ROM. This makes implementing sine and cosine fast and simple, for medium-precision (13-bit) work.

Here's a simple port of Parallax's routines to PropellerForth.


\ Address of table in ROM
E000 constant sin-base

\ Computes the sign of an angle.
\ The angle is a 13-bit number (0x1FFF = almost 360 degrees).
\ The result is a 16.16 fixed-point signed integer.
: sin ( angle13 -- n16_16 )
dup 1000 and >R \ Stash a flag for Quadr.3/4 onto the rstack
dup 0800 and if negate then \ Invert angle for Quadr.2/4
2* sin-base or H@ \ Compute word address and fetch
R> if negate then ; \ Negate result for Quadr.3/4

: cos ( angle13 -- n16_16 ) 0800 + sin ;

With PropellerForth v8.05 this gives a runtime of 1088-1152 cycles for sin, and an additional 240 cycles for cos -- 31x slower than a native implementation. (v8.02 will be slower.)

It can be made slightly faster by (1) replacing the numbers with CONSTANTs and (2) inlining 2*, which is not a primitive, as "1 lshift", for a runtime of 993-1056 cycles -- 28x slower than native, at the cost of a 22 more bytes of space.

Update: Huh. Through some optimizations to the kernel, I can shave off another 100 cycles -- for a runtime of 896-926 cycles. However, it costs 248 bytes in the kernel, and eliminates a hook I was hoping to use for single-step and breakpoints. I'll have to weigh this.



Post a Comment

<< Home