1
/* ---------------------------------------------------------------------------------------
5
Created by Reiner Patommel
7
THIS SOFTWARE IS NOT COPYRIGHTED
9
This source code is offered for use in the public domain. You may
10
use, modify or distribute it freely.
12
This code is distributed in the hope that it will be useful, but
13
WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
14
DISCLAIMED. This includes but is not limited to warranties of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20
*----------------------------------------------------------------------------------------
21
* A = atan2(float A, float B)
22
*---------------------------------------------------------------------------------------*/
38
TEXT_SEG(fplib, atan2)
42
CP rB3, __zero_reg__ ; if (y != 0)
43
BRNE _atan2_normalize ; calculate
44
CP rA3, __zero_reg__ ; if (y == 0 && x == 0)
45
BREQ _atan2_NAN ; return Argument Error
46
SBRC rA3, 7 ; if (y == 0 && x < 0)
47
RJMP _atan2_PI ; return PI
48
XJMP _U(__fp_zero) ; if (x == 0 && y == 0) return 0
54
LDI rA0, 0xDB ; load PI
57
XJMP _U(__fp_nanERANGE)
59
_atan2_normalize: ; normalize x and y to be LESS or EQUAL 1
62
ORI sign, 1 ; remember sign of x (bit 0 set: x < 0)
64
ORI sign, 2 ; remember sign of y (bit 1 set: y < 0)
66
ANDI rA3, 0x7F ; make |x|
67
ANDI rB3, 0x7F ; make |y|
71
CPC rA3, rB3 ; |x| >= |y| ?
74
RCALL _atan2_scale ; rA3:rA2 = int(28140 * x / y)
76
MOV X_lo, rA2 ; X = int(28140 * x / y)
78
LDI Y_lo, 0xEC ; Y = 28140
79
RJMP _atan2_cordic_loop_init
92
EOR rA0, rB0 ; swap A and B
93
RCALL _atan2_scale ; Y = int(28140 * y / x)
95
LDI X_lo, 0xEC ; X = 28140
97
_atan2_cordic_loop_init: ; run cordic in vectoring mode
98
CLR Z_hi ; i.e. drive Y to zero and accumulate Z
100
CLR lcount ; lcount = 0
101
LDI ZL, LOW(table_atan2)
102
LDI ZH, HIGH(table_atan2) ; set pointer to table
104
CPI lcount, 15 ; lcount >= 15 ?
105
BRLO _atan2_cordic_loop_2
106
RJMP _atan2_finish ; ok done with cordic
107
_atan2_cordic_loop_2:
112
CLT ; following shift must be "logical shift"
113
RCALL _atan2_shift ; rA3:rA2 = X >> lcount
115
MOV tmp_lo, rA2 ; tmp = X >> lcount
120
BST rA3, 7 ; following shift must be "arithmetic shift"
121
RCALL _atan2_shift ; rA3:rA2 = Y >> lcount
122
CP Y_lo, __zero_reg__
123
CPC Y_hi, __zero_reg__ ; Y < 0 ?
127
ADC X_hi, rA3 ; X = X + Y >> lcount
131
SBC Y_hi, tmp_hi ; Y = Y - tmp >> lcount
132
LPMRdZpp(tmp_lo) ; tmp = Rad[lcount]
135
ADC Z_hi, tmp_hi ; Z = Z + Rad[lcount]
136
INC lcount ; lcount++
137
RJMP _atan2_cordic_loop
140
SBC X_hi, rA3 ; X = X - Y >> lcount
144
ADC Y_hi, tmp_hi ; Y = Y + tmp >> lcount
146
LPMRdZpp(tmp_hi) ; tmp = Rad[lcount]
148
SBC Z_hi, tmp_hi ; Z = Z - Rad[lcount]
149
INC lcount ; lcount++
150
RJMP _atan2_cordic_loop
152
_atan2_shift: ; A = A >> lcount
153
MOV __tmp_reg__, lcount ; get current loop count
156
BREQ _atan2_shift_done ; we are done
159
BLD rA3, 7 ; LSR for "unsigned" int. ASR for "signed" int
161
RJMP _atan2_shift_loop
165
_atan2_scale: ; A = int(28140 * A / B)
166
XCALL _U(__divsf3) ; A = A / B
167
RCALL _atan2_scale_load ; B = 28140
168
XCALL _U(__mulsf3) ; A = 28140 * A / B
169
XCALL _U(__fixsfsi) ; A = (long int)(28140 * A / B)
170
MOV Y_hi, X_hi ; but, we have a short int
174
_atan2_scale_load: ; B = 28140.0
181
_atan2_finish: ; convert to float and clean-up
186
XCALL _U(__floatsisf) ; A = (float)A
189
SBRC sign, 0 ; x < 0 ?
191
_atan2_xpos: ; here: x > 0
192
RCALL _atan2_scale_load ; B = 28140.0
193
XCALL _U(__divsf3) ; A = A / B
195
SBRC sign, 1 ; y < 0 ?
198
_atan2_xneg: ; here: x < 0
202
LDI rB0, 0x35 ; load M_PI * 28140.0
203
ORI rA3, 0x80 ; negate A
204
XCALL _U(__addsf3) ; A = -A + B = B - A
205
RCALL _atan2_scale_load ; B = 28140.0
206
XCALL _U(__divsf3) ; A = A / B
208
SBRC sign, 1 ; y < 0 ?
211
_atan2_yneg: ; here: y < 0
212
ORI rA3, 0x80 ; negate A
213
RET ; return -(A / B)
216
; --------------------------------------------------------------------------------------
218
.word 22101, 13047, 6893, 3499, 1756, 879, 439, 219, 109, 54, 27, 13, 6, 3, 1
219
; --------------------------------------------------------------------------------------