;CORDIC ATAN2 function
;Coded by Robert Weaver, 2018-02-12
;On entry, the 12 bit (0..8191) values of x and y should be in xL,xH,yL,yH
;The upper 4 bits of xH and yH must be zero.
;Input values are assumed to be positive. Hence the angle is in the first quadrant.
;On completion, the angle (in degrees) is in AngleH and AngleL
;The integer part is in AngleH, and the fractional part is in AngleL
;If no error, then on return wreg contains 1, otherwise it contains 0.
;Due to the 16 bit math operations, the maximum error in the result is +/- 0.048 degrees.
cblock 0x20
xH,xL,yH,yL,angleH,angleL ; Input and output variables
index,count,tL,tH,vL,vH ; counters and temporary storage
endc
;Arctan lookup tables (degrees)
;Each entry is the arctan of a negative power of 2
;starting with 2^-1 and ending with 2^-14
LU_AngleFrac ;This table is the fractional part
addwf pcl,f
retlw .144
retlw .9
retlw .32
retlw .147
retlw .202
retlw .229
retlw .114
retlw .57
retlw .28
retlw .14
retlw .7
retlw .4
retlw .2
retlw .1
LU_AngleInt ;This table is the integer part
addwf pcl,f
retlw .26
retlw .14
retlw .7
retlw .3
retlw .1
retlw .0
retlw .0
retlw .0
retlw .0
retlw .0
retlw .0
retlw .0
retlw .0
retlw .0
nTable equ LU_AngleInt - LU_AngleFrac ; calc size of lookup table
;Main entry point for Atan2 function
Atan2
clrf angleH
clrf angleL
;Check for all zero input combinations
movf xL,w
iorwf xH,w
iorwf yL,w
iorwf yH,w
btfsc status,z
retlw 0 ; Both inputs are zero which is indeterminate, return error
;check if y=0
movf yH,w
iorwf yL,w
btfsc status,z
retlw 1 ; angle is zero, so return
;check for x=0
movlw 90
movwf angleH
movf xH,w
iorwf xL,w
btfsc status,z
retlw 1 ;angle is 90, so return
movlw 45
movwf angleH
; Scale up x and y to improve resolution
ScaleXY
bcf status,c ;shift xH and yH left
rlf xL,f
rlf xH,f
bcf status,c
rlf yL,f
rlf yH,f
movf xH,w
iorwf yH,w
andlw 0xF0
btfsc status,z
goto ScaleXY
;xH and yH are now normalized
;calc x and y initial values
;save old x, as it will be overwritten
movf xH,w
movwf vH
movf xL,w
movwf vL
;calc x=x+y
addwf yL,w
movwf xL
btfsc status,c
incf xH,f
movf yH,w
addwf xH,f
;calc y=y-x
movf vL,w
subwf yL,f
btfss status,c
decf yH,f
movf vH,w
subwf yH,f
clrf index ;Loop counter and lookup table index
MainLoop
;shift x and y values
movf index,w
movwf count
;calc x y shift
movf yH,w
movwf tH
movf yL,w
movwf tL
movf xH,w
movwf vH
movf xL,w
movwf vL
btfss yH,7 ;check for negative y
goto ShiftLoop
comf tH,f
comf tL,f
incf tL,f
btfsc status,z
incf tH,f
ShiftLoop
bcf status,c
rrf vH,f
rrf vL,f
bcf status,c
rrf tH,f
rrf tL,f
bcf status,c
decfsz count,f
goto ShiftLoop
;calc new xH and yH
btfsc yH,7
goto NewXYcalc
;y=y+/-yH>>index
comf vH,f
comf vL,f
incf vL,f
btfsc status,z
incf vH,f
NewXYcalc
movf vL,w
addwf yL,f
btfsc status,c
incf yH,f
movf vH,w
addwf yH,f
;x=x+y>>index
movf tL,w
addwf xL,f
btfsc status,c
incf xH,f
movf tH,w
addwf xH,f
; Sum Angle from lookup table
movf index,w
call LU_AngleFrac
movwf tL
movf index,w
call LU_AngleInt
movwf tH
btfss yH,7
goto AddSum
comf tH,f
comf tL,f
incf tL,f
btfsc status,z
incf tH,f
AddSum
movf tL,w
addwf angleL,f
btfsc status,c
incf angleH,f
movf tH,w
addwf angleH,f
incf index,f
movlw nTable
subwf index,w
btfss status,z
goto MainLoop
retlw 1