-
Notifications
You must be signed in to change notification settings - Fork 0
/
fx8.jal
113 lines (78 loc) · 2.89 KB
/
fx8.jal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
const byte FXWIDTH = 8
const byte FXDOUBLE = 2*FXWIDTH
const byte FXHALF = FXWIDTH/2
const byte FXWORDSIZE = (FXWIDTH*8)
if !defined(FXFRACBITS) then
const byte FXFRACBITS = (FXWORDSIZE/2)
end if
const byte FXINTBITS = (FXWORDSIZE - FXFRACBITS)
function word_to_fx(sbyte*FXHALF in int) return sbyte*FXWIDTH is
pragma inline
return ((sbyte*FXWIDTH(int)) << FXFRACBITS)
end function
var sbyte*FXWIDTH fx_one = word_to_fx(1)
function trunc_fx(sbyte*FXWIDTH in fx_point) return sbyte*FXHALF is
pragma inline
return (sbyte*FXHALF(fx_point >> FXFRACBITS))
end function
function round_fx(sbyte*FXWIDTH in fx_point) return sbyte*FXHALF is
if (fx_point & (1 << (FXFRACBITS-1) )) >0 then -- >= 0.5
return ( sbyte*FXHALF(fx_point >> FXFRACBITS) +1)
else
return ( sbyte*FXHALF(fx_point >> FXFRACBITS))
end if
end function
-- thank goodness jal has arbitrary precision multiplication and division built in
function mult_fx(sbyte*FXDOUBLE in a, sbyte*FXDOUBLE in b) return sbyte*FXWIDTH is
return sbyte*FXWIDTH((a * b) >> FXFRACBITS) -- fix point
end function
function div_fx(sbyte*FXDOUBLE in a, sbyte*FXDOUBLE in b) return sbyte*FXWIDTH is
return sbyte*FXWIDTH( ((a<<FXWORDSIZE) / b) >> FXFRACBITS)
end function
-- 1 times powers of ten
const sbyte*FXHALF fx_tensints[] = {1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1}
-- 0xffffffff times negative powers of ten
const sbyte*FXHALF fx_tensfracs[] = {429496729, 42949672, 4294967, 429496, 42949, 4294, 429, 42, 4}
procedure format_dword_decfrac(volatile byte out device, dword in data) is
var byte pos = 0
var byte outch
device = "."
for 9 using pos loop
outch = "0"
while data >= fx_tensfracs[pos] loop
-- subtract another unit at this digit position
data = data - fx_tensfracs[pos]
-- increment digit that will be output
outch = outch + 1
end loop
device = outch
end loop
end procedure
procedure format_fx8(volatile byte out device, sbyte*FXWIDTH in data) is
format_sdword_dec(device, sdword(data>>FXFRACBITS), 10, 0)
format_dword_decfrac(device, dword(data))
end procedure
function char_is_digit(byte in char) return bit is
if (char < "0") | (char > "9") then
return 0
else
return 1
end if
end function
function read_fx8_from_string(byte in string[18]) return sbyte*FXWIDTH is
var byte digitpos
var sbyte*FXWIDTH temp = 0
for 10 using digitpos loop
if !!char_is_digit(string[digitpos]) then
return 0
end if
temp = temp + (fx_tensints[digitpos] * (string[digitpos]-48))
end loop
for 8 using digitpos loop
if !!char_is_digit(string[digitpos]) then
return 0
end if
temp = temp + (fx_tensfracs[digitpos] * (string[digitpos]-48))
end loop
return temp
end function