list p=16C64,t=ON,c=132,n=80,st=off radix dec include "P16C64.INC" cblock 0x20 result temp x endc ORG 0 ;Reset Vector GOTO Main ORG 4 ;Interrupt Vector Main BCF STATUS,RP0 ;Point to BANK 0 MOVLW 0 MOVWF x xxx CALL arcsine INCF x,F GOTO xxx ;---------------------------------------------------------- ; ;arcsine ; ; The purpose of this routine is to take the arcsine 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/2 for the normal arcsine function. Specifically, this ;algorithm computes: ; ; arcsine(x) = real_arcsine(x/256) * 256 / (pi/2) ; ; where, real_arcsine returns the real arcsine of its argument ;in radians. ; ; The algorithm is a table look-up algorithm plus first order ;linear interpolation. The psuedo code is: ; ;unsigned char arcsine(unigned char x) ;{ ; unsigned char i; ; ; i = x >> 4; ; return(arcsin[i] + ((arcsin[i+1] - arcsin[i]) * (x & 0xf))/16); ;} ; ; ; The accuracy is reasonable for x<150 or so. After that, the ;relatively steep arcsine severly deviates from a straight line ;approximation. The maximum error is around 5. arcsine SWAPF x,W ANDLW 0xf ADDLW 1 MOVWF temp ;Temporarily store the index CALL arc_sine_table ;Get a2=asin( (x>>4) + 1) MOVWF result ;Store temporarily in result DECF temp,W ;Get the saved index CALL arc_sine_table ;Get a1=asin( (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_sine_table ADDWF PCL,F RETLW 0 RETLW 10 ;asin(1/16) = 3.583deg * 256/90 RETLW 20 RETLW 31 RETLW 41 RETLW 52 RETLW 63 RETLW 74 RETLW 85 RETLW 97 RETLW 110 RETLW 124 RETLW 138 RETLW 154 RETLW 173 RETLW 198 RETLW 240 END