' {$STAMP BS2pe} ' {$PBASIC 2.5} ' Tracy Allen, eme systems, http://www.emesystems.com ' CORDIC computation of ARCTAN from values x and y ' Computes to 2 decimal places, but accuracy is ~0.02 ' Accuracy is better with larger numbers, for example atn 1/1 and atn 1000/1000 ' should both give 45 degrees, but roundoff errors affect atn 1/1 more. ' The CORDIC algorithm works for inputs in quadrants 1 and 4, so ' this program provides a wrapper for quadrants 2 and 3. ' The anglular measure in this program assigns the value 16284 to a 45 degree angle, ' and that is used to calculate the values in the table, tans. ' A step at the end of the program converts this to standard degrees. ' This program provides three different methods for computing the rotation (#DEFINE method=). ' One uses straihtforward IF-THEN branching on the sign, while the other ' two eschew the IF-THEN in favor of algebraic manipulation of the sign. ' The trick for the Stamp is division of a negative number. ' Examples: ' 45 degrees, x=10000, y=10000 ' 22.5 degrees, x=9239, y=3827 ' 30 degrees, x=8660, y=5000 ' The program also computes the length of the vector SQR(x^2+y^2), ' again more error with small numbers. ' Enable the DEBUG statement within the CORDIC loop to see inner operation. atans DATA Word 16384, Word 9672,Word 5110,Word 2594, Word 1302 DATA Word 652,Word 326, Word 163, Word 81 DATA Word 41, Word 20, Word 10, Word 5, Word 3, Word 1,Word 0 x VAR Word xs VAR x.BIT15 xx VAR Word y VAR Word ys VAR y.BIT15 yy VAR Word z VAR Word zs VAR z.BIT15 atan2 VAR Word idx VAR Nib quadrant23 VAR Bit DO DEBUG "enter x coordinate:" DEBUGIN SDEC x DEBUG "enter y coordinate:" DEBUGIN SDEC y quadrant23=xs IF quadrant23 THEN x=-x ' move to 1st or 4th quadrant, where cordic works 'x=9239 'y=-3827 z=0 FOR idx=0 TO 15 READ idx*2+atans, Word atan2 #DEFINE method=3 ' method 1 uses branch on sign, method 2&3 use computed direction #SELECT method #CASE 1 IF ys THEN ' y<0, ys=1, d=+1 xx = x +(ABS y >> idx) ' y<0 on entry y = y + (-xs ^ (ABS x >> idx) + xs) z = z - atan2 ELSE ' y>=0, ys=0, d=-1 xx = x + (y >> idx) ' y>=0 on entry y = y - (-xs ^ (ABS x >> idx) + xs) z = z + atan2 ENDIF #CASE 2 ' term (-ys ^ (ABS y >> idx) + ys) is division by power of 2 sign extended ' term -ys ^ (.) + ys is 2s complement, addition/subtraction depending on sign bit, ys. xx = x + (-ys ^ (-ys ^ (ABS y >> idx) + ys) + ys) yy = y - (-ys ^ (-xs ^ (ABS x >> idx) + xs) + ys) z = z + (-ys ^ atan2 + ys) y=yy #CASE 3 ' term (y >> idx | (-ys << (16-idx))) is division by power of 2 sign extended xx = x + (-ys ^ (y >> idx | (-ys << (16-idx))) + ys) yy = y - (-ys ^ (x >> idx | (-xs << (16-idx))) + ys) z = z + (-ys ^ atan2 + ys) y=yy #ENDSELECT x=xx ' include the following DEBUG to see internal operation ' DEBUG CR,DEC idx,TAB,SDEC atan2,TAB,SDEC x,TAB,SDEC y,TAB,SDEC z NEXT DEBUG CR,"the angle is: ", SDEC z,TAB z = -zs ^ (ABS z ** 18000) + zs IF quadrant23 THEN ' wrapper for 2nd and 3rd quadrants IF zs THEN z=z-9000 ELSE z=z+9000 ENDIF x = x ** 39793 ' vector has been rotated to x axis, multiply by CORDIC gain 0.607 DEBUG REP "-"\zs,DEC ABS z/100, ".",DEC2 ABS z," degrees",TAB DEBUG "length: ",DEC x,CR,CR LOOP