list p=16C84,t=ON,c=132,n=80,st=off
include "P16C84.INC"
cblock 0x0C
temp
x,y,a
x1,y1,cnt
result
endc
ORG 0 ;Reset Vector
GOTO Main
ORG 4 ;Interrupt Vector
Main
CLRF x
clrf x1
movlw 0x30
movwf y1
movwf x1
l1
movf y1,w
movwf y
movlw 3
addwf x1,w
movwf x1
movwf x
CALL FRAC_DIV
movf a,w
movwf x
CALL arctan
goto l1
FRAC_DIV:
;-------------------
;Fractional division
;
; Given x,y this routine finds:
; a = 256 * y / x
;
movlw 8 ;number of bits in the result
movwf cnt
clrf a ; the result
movf x,w
L1:
clrc
rlf y,f ;if msb of y is set we know x<y
rlf a,f ;and that the lsb of 'a' should be set
subwf y,f ;But we still need to subtract the
;divisor from the dividend just in
;case y is less than 256.
skpnc ;If y>x, but y<256
bsf a,0 ; we still need to set a:0
btfss a,0 ;If y<x then we shouldn't have
addwf y,f ;done the subtraction
decfsz cnt,f
goto L1
return
;----------------------------------------------------------
;
;arctan (as adapted from the similar arcsin function)
;
; The purpose of this routine is to take the arctan of an
;8-bit number that ranges from 0 < x < 255/256. In other
;words, the input, x, is an unsigned fraction whose implicit
;divisor is 256.
; The output is in a conveniently awkward format of binary
;radians (brads?). The output corresponds to the range of zero
;to pi/4 for the normal arctan function. Specifically, this
;algorithm computes:
;
; arctan(x) = real_arctan(x/256) * 256 / (pi/4)
; for 0 <= x <= 255
;
; where, real_arctan returns the real arctan of its argument
;in radians.
;
; The algorithm is a table look-up algorithm plus first order
;linear interpolation. The psuedo code is:
;
;unsigned char arctan(unsigned char x)
;{
; unsigned char i;
;
; i = x >> 4;
; return(arctan[i] + ((arctan[i+1] - arctan[i]) * (x & 0xf))/16);
;}
;
;
arctan
SWAPF x,W
ANDLW 0xf
ADDLW 1
MOVWF temp ;Temporarily store the index
CALL arc_tan_table ;Get a2=atan( (x>>4) + 1)
MOVWF result ;Store temporarily in result
DECF temp,W ;Get the saved index
CALL arc_tan_table ;Get a1=atan( (x>>4) )
SUBWF result,W ;W=a2-a1, This is always positive.
SUBWF result,F ;a1 = a1 - (a1-W) = W
CLRF temp ;Clear the product
CLRC
BTFSC x,0
ADDWF temp,F
RRF temp,F
CLRC
BTFSC x,1
ADDWF temp,F
RRF temp,F
CLRC
BTFSC x,2
ADDWF temp,F
RRF temp,F
CLRC
BTFSC x,3
ADDWF temp,F
RRF temp,W
ADDWF result,F
RETURN
arc_tan_table
ADDWF PCL,F
RETLW 0
RETLW 20 ;atan(1/16) = 3.576deg * 256/45
RETLW 41
RETLW 60
RETLW 80
RETLW 99
RETLW 117
RETLW 134
RETLW 151
RETLW 167
RETLW 182
RETLW 196
RETLW 210
RETLW 222
RETLW 234
RETLW 245
RETLW 0 ;atan(32/32) = 45deg * 256/45
END