Page 1 of 1
Trig functions on LPC812
Posted: Sun Jan 25, 2015 1:36 pm
by Ivar
I need a sin(x) function and found one in the ARMBasic manual. However the example there does not compile on my LPC812 eval board.
Code: Select all
'example code from: ARMBasic.pdf : Runtime Library / Floating Point Functions/ trig Functions (page 214)
#define include_trig
#include <AB_Math.bas>
for i=0 to 90 step 10
print i,sin(_deg2rad *i),cos(_deg2rad *i),tan((_deg2rad *i)
next i
AB_Math.bas: 567: Out of code space, found powi((_halfpi-symm),2)*divbyfact(2))+(powi((_halfpi-symm),4)*divbyfact(4))-(powi((_halfpi-symm),6)*divbyfact(6)))
Can anybody confirm this issue or maybe suggest a solution ?
Trig functions on LPC812
Posted: Sun Jan 25, 2015 6:39 pm
by basicchip
The LPC812 only has 4K available for user BASIC programs, and the error you are getting is out of code space.
The AB math lib was contributed by a user, and intensively checked, but it was not developed for small spaces.
We have been thinking about publishing an integer version of BASIC for the LPC812 which would free up another 4K. Yes I know BASIC on early micros was condensed into 4K (I just finished Isaacson's "The Innovators", and we are being wasteful at 12K which has floating point, string and download support. And that is why we have support for a range chips with memories from 16K to 512K.
Trig functions on LPC812
Posted: Mon Jan 26, 2015 12:49 pm
by Ivar
@basicchip
Thank you for your quick reaction. Now I understand the problem I could solve it by only copying the sin(x) code from the library directly in my code. The compiler told me the other things I had to copy from the library and now I have a working sin(x) function !
Trig functions on LPC812
Posted: Mon Jan 26, 2015 1:40 pm
by basicchip
Hi Ivar-
Please publish your condensed sin(x) code here when you have it working. thanks
Trig functions on LPC812
Posted: Wed Jan 28, 2015 2:29 pm
by Ivar
It works. No code of myself, just the right lines from AB-Math.bas. I would be happy to share them but i am unsure of the policy of Coridium on possible copyright issues. But if you start with these lines and the code for sin(x), the compiler will tell you the 2 or 3 other functions you need. 3 minutes work.
Code: Select all
const _nan = $7fc00000
CONST DivByFact = { 0.0, 1.00000000000000000000000, 0.50000000000000000000000,
0.16666666666666700000000, 0.04166666666666670000000, 0.00833333333333333000000,
0.00138888888888889000000, 0.00019841269841269800000, 0.00002480158730158730000,
0.00000275573192239859000, 0.00000027557319223985900, 0.00000002505210838544170 }
const _2pi = 6.283185307179590000
const _halfpi = 1.570796326794900000
const _qtrpi = 0.785398163397448000
function fix(x as single) as integer
' fix truncates a floating-point expression to its integer portion, returning an integer
' print fix(12.49), fix(12.54) 'output is: 12 12
return x
endfunction
function floor(x as single) as single
' floor returns the largest integral single value not greater than fparam
' floor of 3.8 is 3.0, floor of -2.3 is -3.0
if(x = fix(x)) or x>=0 then return fix(x) else return fix(x)-1
endfunction
function int(x as single) as integer
return floor(x)
endfunction
Trig functions on LPC812
Posted: Wed Jan 28, 2015 2:48 pm
by basicchip
Feel free to post it here.
Bruce Eisenhard, Coridium Corp
Trig functions on LPC812
Posted: Wed Jan 28, 2015 7:37 pm
by Ivar
Thanks Bruce. Just to be sure.
Code: Select all
'=== Workaround to use sine function (library AB_Math.bas being too big for the memory of the LPC812 eval board):
'===
'=== 1) Do not include AB_Math.bas
'=== 2) Only include the code between the dashed lines to your program:
'=== The code is taken straight from AB_Math. Except for the constants _rad2deg and _deg2rad everything is essential.
'===
'=== At the end of this file at main: you find a some example code to show it works.
'-------------- start of AB_Math code ---------------------------------------------------------------------
const _nan = $7fc00000
CONST DivByFact = { 0.0, 1.00000000000000000000000, 0.50000000000000000000000,
0.16666666666666700000000, 0.04166666666666670000000, 0.00833333333333333000000,
0.00138888888888889000000, 0.00019841269841269800000, 0.00002480158730158730000,
0.00000275573192239859000, 0.00000027557319223985900, 0.00000002505210838544170 }
const _2pi = 6.283185307179590000
const _halfpi = 1.570796326794900000
const _qtrpi = 0.785398163397448000
const _rad2deg = 57.295779513082320876798154814105 'x*180/pi
const _deg2rad = 0.01745329251994329576923690768489 'x*pi/180
function fix(x as single) as integer
' fix truncates a floating-point expression to its integer portion, returning an integer
' print fix(12.49), fix(12.54) 'output is: 12 12
return x
endfunction
function floor(x as single) as single
' floor returns the largest integral single value not greater than fparam
' floor of 3.8 is 3.0, floor of -2.3 is -3.0
if(x = fix(x)) or x>=0 then return fix(x) else return fix(x)-1
endfunction
function int(x as single) as integer
return floor(x)
endfunction
function fmod(n as single, d as single) as single
' returns the floating-point remainder of numerator/denominator.
if d <> 0 then return n-(fix(n/d)*d) else return _nan
endfunction
function powi(b as single, e as integer) as single
' returns the base raised to the integral power of exponent
dim res as single
if e = 0 then return 1
if e = 1 then return b
res = 1
while e ' iterate thru the exponent, moving it towards zero while multiplying the base
res = res*if(e<0,1/b,b)
e = e+if(e<0,1,-1)
loop
return res
endfunction
function reducerange(x as single, sc as single, byref m as integer) as single
' this is used to reduce a number to within a range and maintain the phase angles
' for some gawd awful reason, this kicked my arse for hours over a few nights,
' i strongly suspect that i got lost as i couldn't see the gd forest 'cause of all of
' the effin trees. i was, admittedly, buring the candle at both ends too.
' this is a function that can be optimized a lot i suspect.
' however, i am still tired and ... it ain't broke, boss...
dim res as single
dim scsign, xsign as integer
xsign=1
scsign =1
if x < 0 then
xsign = -1
x *= -1
endif
if sc < 0 then
scsign = -1
sc *= -1
endif
res = fmod(x,sc)
m = (int(x/sc))
if (res = 0) and (m = 1) and (xsign=scsign)
' print "same side same val - unity"
m = 0
return x * xsign
elseif (res = 0) and (m = 1) and (xsign<>scsign)
' print "opposite unities"
m = 2 * if(scsign=-1,-1,1)
return sc * scsign
elseif (res = 0) and (m > 1) and (xsign <> scsign)
' print "opposite side - multiples: ";m
m = if(scsign=-1,-m-1,m+1)
return sc * scsign
elseif (res = 0) and (m > 1) 'and xsign = scsign
' print "same side - multiples: ";m
m = if(scsign=1,(m-1)*-1,m-1)
return sc * scsign
elseif scsign = 1 and xsign = 1
m *= -1
return res
elseif scsign = 1 and xsign = -1
m += 1
return sc - res
elseif scsign = -1 and xsign = -1
return res * -1
else ' scsign = -1 and xsign = 1
m += 1
m *= -1
return res - sc
endif
endfunction
function sin(rad as single) as single ' using polynomial - good
' domain and range: from the graphs above we see that for both the sin and cos functions the
' domain is all real numbers and the range is all reals from -1 to +1 inclusive. for the tan
' function the domain is all real numbers except ±p/2, ±3p/2, ±5p/2, …,
' (or in degrees: ±90°, ±270°, ±450°, …), where the tan function is undefined.
' the range of the tan function is all real numbers.
dim multiple as integer
dim period, symm as single
period = reducerange(rad,_2pi,multiple) ' 0-360
symm = reducerange(period,_halfpi,multiple) ' 0-90
if multiple = -1 then symm = _halfpi-symm
if multiple = -3 then symm = _halfpi-symm
if symm <=_qtrpi ' <=45 deg
return if(multiple<-1,-1,1)*(symm-(powi(symm,3)*divbyfact(3))+(powi(symm,5)*divbyfact(5))-(powi(symm,7)*divbyfact(7)))
else
return if(multiple<-1,-1,1)*(1-(powi((_halfpi-symm),2)*divbyfact(2))+(powi((_halfpi-symm),4)*divbyfact(4))-(powi((_halfpi-symm),6)*divbyfact(6)))
endif
endfunction
'-------------- end of AB_Math code ---------------------------------------------------------------------
main:
'=== example from ARMbasic.pdf( Trigonometric Functions) adapted to use only sin(x)
for i=0 to 90 step 10
print i,sin(_deg2rad *i)
next i