(also 18Fmathstest.inc)
;.......;.......;.......;.......;.......;.......;.......;.......;.......;.......;.......; ;**************************************************************************************** ; Filename: 18Fmathstest.asm * ; Date: 10/07/2013 * ; Author: Peter G Harrison * ; Company: PGH Consultants * ;**************************************************************************************** ; Files required: 18F4520_g.lkr Generic linker script for the PIC18F4520 * ; P18F4520.inc * ; 18Fmathstest.inc Configuration definition * ;**************************************************************************************** ;Revision History: * ;**************************************************************************************** ; ;**************************************************************************************** processor 18F4520 ; * list p=18F4520, n=65 ; define processor and pagelength * #include <P18F4520.inc> ; processor specific variable definitions * #include <18Fmathstest.inc> ; application specific config definitions * errorlevel -302,-306 ; suppress message 302 from list file * ;**************************************************************************************** ; ;**************************************************************************************** ;Define data variables * ;**************************************************************************************** ;**************************************************************************************** ;ACCESS ram - addressed directly * ;Groups separated to assist in register visibility during debug * ;**************************************************************************************** ; ;Maths - 4 byte accumulator registers group0 udata_acs 0x000 acc1_6 res 1 ; acc1_5 res 1 ; acc1_4 res 1 ; acc1_3 res 1 ; acc1_2 res 1 ; acc1_1 res 1 ; ; group1 udata_acs 0x008 acc2_6 res 1 ; acc2_5 res 1 ; acc2_4 res 1 ; main results register acc2_3 res 1 ; acc2_2 res 1 ; acc2_1 res 1 ; ; group2 udata_acs 0x010 acc3_6 res 1 ; acc3_5 res 1 ; acc3_4 res 1 ; acc3_3 res 1 ; acc3_2 res 1 ; acc3_1 res 1 ; ; group3 udata_acs 0x018 acc4_6 res 1 ; acc4_5 res 1 ; acc4_4 res 1 ; acc4_3 res 1 ; acc4_2 res 1 ; acc4_1 res 1 ; ; group4 udata_acs 0x020 mult_tmp res 1 ; maths temporary store shft_cnt res 1 ; multiplication and division loop count ; ;=======================================================================================* ;End of data area definition * ;=======================================================================================* ; ;**************************************************************************************** ;Baud rate constant calculations * ;**************************************************************************************** ; ;Serial I/O base frequency and system clock xtal_f equ d'7372800' ; OSC freq in Hz (gives exact baud rates) ; baud_9600 equ (xtal_f/(4*d'9600'))-1 baud_19200 equ (xtal_f/(4*d'19200'))-1 baud_38400 equ (xtal_f/(4*d'38400'))-1 baud_57600 equ (xtal_f/(4*d'57600'))-1 baud_115200 equ (xtal_f/(4*d'115200'))-1 ; ;Calculate baudrate when BRGH = 1 #define calc(baudrate) (xtal_f/(4*d'baudrate'))-1 ; ;**************************************************************************************** ; ;======================================================================================== ;Start of Programme * ;======================================================================================== ; RESET_VECTOR CODE 0x000 ; processor reset vector goto Start ; go to initialisation ; HPINT_VECTOR CODE 0x008 ; processor interrupt vector goto hprinth ; go to high priority interrupt handler routines ; LPINT_VECTOR CODE 0x018 ; processor interrupt vector goto lprinth ; go to low priority interrupt handler routines ; ; ;**************************************************************************************** ;**************************************************************************************** MAIN CODE 0x050 ; allow room for message strings ; ;======================================================================================== ;High priority interrupt routines * ;======================================================================================== ; hprinth retfie ; return from interrupt and re-enable ; ;======================================================================================== ;Low priority interrupt routines * ;======================================================================================== ; lprinth retfie ; return from interrupt and re-enable ; ; ;======================================================================================== ;Main * ;======================================================================================== ; ; clr1_4 ; acc1_4, acc1_3, acc1_2, acc1_1 = 0 ; clr1_2 ; acc1_2, acc1_1 = 0 ; clr2_4 ; acc2_4, acc2_3, acc2_2, acc2_1 = 0 ; clr2_2 ; acc2_2, acc2_1 = 0 ; clr3_4 ; acc1_4, acc1_3, acc1_2, acc1_1 = 0 ; clr3_2 ; acc1_2, acc1_1 = 0 ; clr4_4 ; acc2_4, acc2_3, acc2_2, acc2_1 = 0 ; clr4_2 ; acc2_2, acc2_1 = 0 ; ; sub16 ; 16 bit subtract, acc2 - acc1 -> acc2 ; add16 ; 16 bit add, acc2 + acc1 -> acc2 ; ; inc2 ; 32 bit increment acc2 + 1 -> acc2 ; dec2 ; 32 bit decrement acc2 - 1 -> acc2 ; ; sub32 ; 32 bit subtract, acc2 - acc1 -> acc2 ; add32 ; 32 bit add, acc2 + acc1 -> acc2 ; ; comp1 ; 32 bit 2's complement -acc1 -> acc1 ; comp2 ; 32 bit 2's complement -acc2 -> acc2 ; ; mul16 ; 16*16 multiply, acc2 x acc1 -> acc2 ; div2by1 ; 32/16 divide, acc2/acc1 -> acc2 (R hi, Q lo) ; div32 ; 32/16 divide, acc2/acc1 -> acc2 (R hi, Q lo) ; div48 ; 48/24 divide, acc2/acc1 -> acc2 (R hi, Q lo) ; ; sqrt16 ; 16 bit square root acc2_2:acc2_1 -> acc2_1 ; sqrt32 ; 32 bit square root acc2_4:acc2_1 -> acc1_2:1 ; ;======================================================================================== ; begin ;======================================================================================== ;Maths Routines * ;======================================================================================== ;Development basic maths routines call sub32 ; 32 bit subtract, acc2 - acc1 -> acc2 call add32 ; 32 bit add, acc2 + acc1 -> acc2 call comp1 ; 32 bit 2's complement -acc1 -> acc1 call comp2 ; 32 bit 2's complement -acc2 -> acc2 call mul16 ; 16*16 multiply, acc2 x acc1 -> acc2 call div2by1 ; 32/16 divide, acc2/acc1 -> acc2 (R hi, Q lo) call sqrt16 ; 16 bit square root acc2_2/1 -> acc2_1 call sqrt32 ; 32 bit square root acc2_4:acc2_1 -> acc1_2/1 call sqrt48 ; 48 bit square root acc2_6:acc2_1 -> acc1_3/2/1 ; ;Test routines call sqrt16test ; test routine for 16 bit square root extraction call sqrt32test ; test routine for 32 bit square root extraction call sqrt48test ; test routine for 48 bit square root extraction goto begin ; ; ;======================================================================================== ;Clear accumulators acc1 to to acc4 ;======================================================================================== ; clr1_6 clrf acc1_6 ; clear acc1 clrf acc1_5 ; clr1_4 clrf acc1_4 ; clrf acc1_3 ; clr1_2 clrf acc1_2 ; clrf acc1_1 ; return ; clr2_6 clrf acc2_6 ; clear acc2 clrf acc2_5 ; clr2_4 clrf acc2_4 ; clrf acc2_3 ; clr2_2 clrf acc2_2 ; clrf acc2_1 ; return ; clr3_6 clrf acc3_6 ; clear acc3 clrf acc3_5 ; clr3_4 clrf acc3_4 ; clrf acc3_3 ; clr3_2 clrf acc3_2 ; clrf acc3_1 ; return ; clr4_6 clrf acc4_6 ; clear acc4 clrf acc4_5 ; clr4_4 clrf acc4_4 ; clrf acc4_3 ; clr4_2 clrf acc4_2 ; clrf acc4_1 ; return ; ;======================================================================================== ;Unsigned 16 bit subtract. acc2_2:acc2_1 - acc1_2:acc1_1 -> acc2_2:acc2_1 * ;======================================================================================== ; sub16 movf acc1_1,w ; unsigned 16 bit subtract subwf acc2_1 ; movf acc1_2,w ; subwfb acc2_2 ; return ; ;======================================================================================== ;Unsigned 32 bit subtract. acc2_4:acc2_1 - acc1_4:acc1_1 -> acc2_4:acc2_1 * ;======================================================================================== ; sub32 movf acc1_1,w ; unsigned 32 bit subtract subwf acc2_1 ; movf acc1_2,w ; subwfb acc2_2 ; movf acc1_3,w ; subwfb acc2_3 ; movf acc1_4,w ; subwfb acc2_4 ; return ; ;======================================================================================== ;Unsigned 48 bit subtract. acc2_6:acc2_1 - acc1_6:acc1_1 -> acc2_6:acc2_1 * ;======================================================================================== ; sub48 movf acc1_1,w ; unsigned 32 bit subtract subwf acc2_1 ; movf acc1_2,w ; subwfb acc2_2 ; movf acc1_3,w ; subwfb acc2_3 ; movf acc1_4,w ; subwfb acc2_4 ; movf acc1_5,w ; subwfb acc2_5 ; movf acc1_6,w ; subwfb acc2_6 ; return ; ;======================================================================================== ;Unsigned 16 bit add. acc2_2:acc2_1 + acc1_2:acc1_1 -> acc2_2:acc2_1 * ;======================================================================================== ; add16 movf acc1_1,w ; unsigned 16 bit add addwf acc2_1 ; movf acc1_2,w ; addwfc acc2_2 ; return ; ;======================================================================================== ;Unsigned 32 bit add. acc2_4:acc2_1 + acc1_4:acc1_1 -> acc2_4:acc2_1 * ;======================================================================================== ; add32 movf acc1_1,w ; unsigned 32 bit add addwf acc2_1 ; movf acc1_2,w ; addwfc acc2_2 ; movf acc1_3,w ; addwfc acc2_3 ; movf acc1_4,w ; addwfc acc2_4 ; return ; ;======================================================================================== ;Unsigned 48 bit add. acc2_6:acc2_1 + acc1_6:acc1_1 -> acc2_6:acc2_1 * ;======================================================================================== ; add48 movf acc1_1,w ; unsigned 32 bit add addwf acc2_1 ; movf acc1_2,w ; addwfc acc2_2 ; movf acc1_3,w ; addwfc acc2_3 ; movf acc1_4,w ; addwfc acc2_4 ; movf acc1_5,w ; addwfc acc2_5 ; movf acc1_6,w ; addwfc acc2_6 ; return ; ;======================================================================================== ;2's complement acc1_4:acc1_1 * ;======================================================================================== ; comp1 comf acc1_1 ; complement acc1 comf acc1_2 ; comf acc1_3 ; comf acc1_4 ; incfsz acc1_1,f ; return ; incfsz acc1_2,f ; return ; incfsz acc1_3,f ; return ; incfsz acc1_4,f ; return ; ;======================================================================================== ;2's complement acc1_4:acc1_1 * ;======================================================================================== ; comp2 comf acc2_1 ; complement acc2 comf acc2_2 ; comf acc2_3 ; comf acc2_4 ; incfsz acc2_1,f ; return ; incfsz acc2_2,f ; return ; incfsz acc2_3,f ; return ; incfsz acc2_4,f ; return ; ;======================================================================================== ;Unsigned 32/16 bit division (approx 552 to 712 cycles) ;Inputs: Dividend - acc2_4 -> acc2_1 (32 bits) ; Divisor - acc1_2 -> acc1_1 (16 bits) ;Temporary: Counter - count ;Output: Quotient - acc2_2 -> acc2_1 (32 bits) ; Remainder- acc1_4 -> acc1_3 (16 bits) ;======================================================================================== ; div32 movlw d'32' ; 32-bit divide by 16-bit movwf shft_cnt clrf acc1_4 ; clear remainder clrf acc1_3 ; dvloop bcf STATUS,C ; set quotient bit to 0, shift left dividend & quotient rlcf acc2_1 ; low byte rlcf acc2_2 rlcf acc2_3 rlcf acc2_4 ; msb into carry rlcf acc1_3 ; and then into partial remainder rlcf acc1_4 ; bc subdiv ; if overflow then remainder > divisor so can subtract movf acc1_2,w ; compare partial remainder and divisor subwf acc1_4,w bnz testgt ; if hi bytes =, check low bytes, else check for > ; movf acc1_1,w ; high bytes are = so compare low bytes subwf acc1_3,w testgt bnc remrlt ; if carry set remainder > divisor, so ok to subtract ; subdiv movf acc1_1,w ; subtract divisor from partial remainder subwf acc1_3,f movf acc1_2,w subwfb acc1_4,f bsf acc2_1,0 ; set quotient bit to 1 ; ; quotient replaces dividend which is lost remrlt decfsz shft_cnt goto dvloop return ; ;======================================================================================== ;Unsigned 32 / 16 bits division *** NOT SURE ABOUT THIS ROUTINE !!!! ****** ;Dividend in acc2_ (max val H'FFFE0001' =4,294,836,225) ;Divisor in acc1_ (max value H'FFFF' =65,535) ;Ensure being within range or if a division by zero is going to happen. ; ;Return: quotient in acc2_2:1 (16 bits) and remainder in acc2_4:3 (16 bits) ;Result of acc2_4:acc2_1 / acc1_2:acc1_1 => acc2_2:acc2_1 (quotient) ;affected register: shft_cnt ;Typically 262 cycles ;======================================================================================== ; div2by1 movlw d'16' ;initialize the movwf shft_cnt ;shift counter ; divloop bcf STATUS,C ;we ensure that b0 rlcf acc2_1,f ;of acc2_1 is =0 rlcf acc2_2,f ;after the shifting rlcf acc2_3,f ;to the left of the rlcf acc2_4,f ;whole dividend ; ;Test carry flag, if = 1, then shift caused overflow so subtract acc1_1 from acc2_3 bc subtrct movf acc1_2,w ; compare acc1_2 subwf acc2_4,w ; against acc2_4 ; ;Test zero flag, if = 0,then acc1_2 != acc2_4. so check if acc1_2 < acc2_4 bnz acc1les movf acc1_1,w ; acc1_2 = acc2_4; now compare subwf acc2_3,w ; value of acc1_1 against acc2_3 ; ;Test carry flag, if = 1, then DSOR_ < DEND_ , so subtract acc1_2:L from acc2_4:2 acc1les bnc dec_ctr ; ;subtract divisor from MSBs of dividend subtrct movf acc1_1,w ; acc2_3 = acc2_3 - acc1_1 subwf acc2_3,f ; borrow not used (LSB) movf acc1_2,w ; acc2_4 = acc2_4 - acc1_2 subwfb acc2_4,f ; borrow used bsf acc2_1,0 ; flag "divisor was substracted from dividend" ; dec_ctr decfsz shft_cnt,f bra divloop return ; finished ; ;======================================================================================== ;Unsigned 48/24 bit division (approx 967 to 1447 cycles) ;Inputs: Dividend - acc2_6 -> acc2_1 (48 bits) ; Divisor - acc1_3 -> acc1_1 (24 bits) ;Temporary: Counter - shft_cnt ;Output: Quotient - acc2_6 -> acc2_1 (48 bits) ; Remainder- acc1_6 -> acc1_4 (24 bits) ;======================================================================================== ; div48 movlw d'48' ; 48-bit divide by 24-bit movwf shft_cnt clrf acc1_6 ; Clear remainder clrf acc1_5 clrf acc1_4 ; divdlp bcf STATUS,C ; Set quotient bit to 0, shift left dividend & quotient rlcf acc2_1 ; low byte rlcf acc2_2 rlcf acc2_3 rlcf acc2_4 rlcf acc2_5 rlcf acc2_6 ; most significant bit into carry rlcf acc1_4 ; and then into partial remainder rlcf acc1_5 rlcf acc1_6 ; bc subtdiv ; If overflow then remainder must be > divisor ; ;After subtraction, if Z set then check less significant bytes. If Z not set and C ;is set, partial remainder > divisor, so can subtract and set result bit in acc2 ; movf acc1_3,w ; Compare high bytes of partial remainder and divisor subwf acc1_6,w bnz test_gt ; bytes not equal, so check if remainder > divisor ; movf acc1_2,w ; middle bytes of partial remainder and divisor subwf acc1_5,w bnz test_gt ; bytes not equal, so check if remainder > divisor ; movf acc1_1,w ; subwf acc1_4,w ; test_gt bnc rmdrlt ; carry set if partial remainder > divisor ; subtdiv movf acc1_1,w ; Subtract divisor from partial remainder subwf acc1_4,f movf acc1_2,w subwfb acc1_5,f movf acc1_3,w subwfb acc1_6,f bsf acc2_1,0 ; Set quotient bit to 1 ; ; Quotient replaces dividend which is lost rmdrlt decfsz shft_cnt goto divdlp return ; ;======================================================================================== ;Unsigned 16 * 16 bit multiplication ;acc1_2:acc1_1 * acc2_2:acc2_1 -> acc2_4:acc2_1 ;acc1 value remains unchanged. ;affected register: mult_tmp ;28cycles ;======================================================================================== ; mul16 movf acc2_2,w mulwf acc1_2 ; acc1_2 * acc2_2 movff PRODH,acc2_4 ; into result movff PRODL,acc2_3 ; movf acc2_1,w mulwf acc1_1 ; acc1_1 * acc2_1; movff PRODH,mult_tmp movff PRODL,acc2_1 ; mulwf acc1_2 ; acc1_2 * acc2_1 movf PRODL,w addwf mult_tmp,f ; Add cross movf PRODH,w ; products addwfc acc2_3,f clrf WREG addwfc acc2_4,f ; movf acc2_2,w mulwf acc1_1 ; acc1_1 * acc2_2 movf PRODL,w ; addwf mult_tmp,w ; Add cross movwf acc2_2 movf PRODH,w ; products addwfc acc2_3,f clrf WREG addwfc acc2_4,f return ; ;======================================================================================== ; Unsigned 24 * 24 bit multiplication ; acc1_3:acc1_1 * acc2_3:acc2_1 -> acc2_6:acc2_1 ; 148 cycles, including initial moves and register clearances ;======================================================================================== mul24 movff acc2_3,acc3_6 movff acc2_2,acc3_5 movff acc2_1,acc3_4 movff acc1_3,acc3_3 movff acc1_2,acc3_2 movff acc1_1,acc3_1 ; call clr2_6 call clr1_6 ; movf acc3_6,w mulwf acc3_1 movff PRODH,acc2_4 movff PRODL,acc2_3 ; movf acc3_3,w mulwf acc3_4 movff PRODH,acc1_4 movff PRODL,acc1_3 ; call add48 ; movf acc3_2,w mulwf acc3_6 movff PRODH,acc1_5 movff PRODL,acc1_4 ; mulwf acc3_4 movff PRODH,acc1_3 movff PRODL,acc1_2 ; call add48 ; movf acc3_5,w mulwf acc3_3 movff PRODH,acc1_5 movff PRODL,acc1_4 ; mulwf acc3_1 movff PRODH,acc1_3 movff PRODL,acc1_2 ; call add48 ; movf acc3_6,w mulwf acc3_3 movff PRODH,acc1_6 movff PRODL,acc1_5 ; movf acc3_5,w mulwf acc3_2 movff PRODH,acc1_4 movff PRODL,acc1_3 ; movf acc3_4,w mulwf acc3_1 movff PRODH,acc1_2 movff PRODL,acc1_1 ; call add48 ; return ; ;======================================================================================== ;16 bit square root - sqrt16 ;Return with carry set if negative ; ;Inputs: acc2_2 : acc2_1 ;Output: acc2_1 returns with the 8 bit result ; ;30 Instructions 104 Cycles best case, 109 average, 122 worst case ;======================================================================================== ; sqrt16 movlw 0xc0 ;Initialize value for mask movwf acc2_4 ;Mask movlw 0x40 ;Initial value for the root clrf STATUS ; sq1 subwf acc2_2,f ;Subtract the root developed so far btfss STATUS,C ;If it is larger than acc2_2 goto sq5 ;then go restore the subtraction ; sq2 iorwf acc2_4,w ;Set the current bit sq3 bcf STATUS,C ;!!!TEMP DEBUG - see move with no extra bits!!! rlcf acc2_1,f ;Shift N left one position rlcf acc2_2,f rrcf acc2_4,f ;Shift the mask right, and pick up msb of N btfsc acc2_4,7 ;If msb of N is set, then unconditionally goto sq6 ;set the next bit (because subtracting the ; ;root is guranteed not to cause a borrow) ; xorwf acc2_4,w ;Append "01" to the root developed so far btfss STATUS,C ;If the lsb of mask was shifted into the carry goto sq1 ;then we're done. Otherwise, loop again. ; ;We are almost done. In the last iteration, we have 7 bits of the root. When ;"01" is appended to it, we will have a 9-bit number that must be subtracted ;from N. ; subwf acc2_2,f ; btfss STATUS,C ;If the upper 7 bits cause a borrow, then goto exitsq ;the appended "01" will as well: We're done. ; btfsc STATUS,Z ;If the result of the subtraction is zero btfsc acc2_1,7 ;AND the msb of acc2_1 is set then the LSB of the ; ;root is zero. xorlw 1 ;Otherwise, it is one. exitsq movwf acc2_1 ;result to acc2_1 clrf acc2_2 ; return ; ; sq6 btfsc STATUS,C ;Need to unconditionally set current bit of root. goto exitsq ;However, if through iterating, then leave. Note, ;C is set by shifting mask right & the LSB of root ;was set by iorwf at sq2. ; bcf acc2_4,7 ;Clear the MSB of N that got shifted into the mask. xorwf acc2_4,w ;Append "01" to the root developed so far. subwf acc2_2,f ;Subtract goto sq2 ;Go unconditionally set the current bit. ; sq5 addwf acc2_2,f ;Restore acc2_2 by reversing the subwf with a ADDWF goto sq3 ;Don't set the current bit ; ;======================================================================================== ; SQRT32 ;; Calculates the square root of a 32 bit number using the binary restoring method. ; ; Input: acc2_4:acc2_1 ; Mask: acc3_2:acc3_1 ; Result: acc1_2:acc1_1 ; ; Takes between 395 and 457 cycles (incl. call and return). ; Uses 64 words ROM, 8 bytes RAM including 4 holding the input. ;======================================================================================== ; sqrt32 movlw 0x40 ; Initial value for Result is... movwf acc1_2 ; ... 01000000 00000000 clrf acc1_1 ; ; movlw 0xC0 ; Initial value for mask is... movwf acc3_2 ; ... 11000000 00000000 clrf acc3_1 ; (second '1' is loop counter). ; compare movf acc1_1,w ; Compare root-so-far with current subwf acc2_3,f ; ... remainder. movf acc1_2,w ; subwfb acc2_4,f ; bc $+4 ; goto restore ; result is -ve, so need to restore ; setcurr movf acc3_1,w ; set the current bit in the result. iorwf acc1_1,f ; movf acc3_2,w ; iorwf acc1_2,f ; ; shftUp rlcf acc2_1,f ; rlcf acc2_2,f ; rlcf acc2_3,f ; rlcf acc2_4,f ; ; rrcf acc3_2,f ; Shift mask right for next bit, whilst rrcf acc3_1,f ; ... shifting in MSB from remainder. btfsc acc3_2,7 ; If MSB is set, unconditionally set the goto setnext ; ... next bit. ; movf acc3_1,w ; Append '01' to root-so-far xorwf acc1_1,f ; movf acc3_2,w ; xorwf acc1_2,f ; ; bc $+4 ; If second '1' in mask is shifted out, goto compare ; ... then that was the last normal iteration. ; movf acc1_1,w ; Last bit Generation. subwf acc2_3,f ; ... The final subtract is 17-bit (15-bit root movf acc1_2,w ; ... plus '01'). Subtract 16-bits: if result subwfb acc2_4,f ; ... generates a carry, last bit is 0. bc $+4 ; return ; movf acc2_3,w ; Clear zero flag if remainder non zero xorwf acc2_4,w ; ; movlw 1 ; bnz $+4 ; If result is 0 AND msb of N is '0', result bit btfsc acc2_2,7 ; ... is 0, otherwise '1'. xorwf acc1_1,f ; return ; ; setnext bnc $+4 ; If mask has shifted out, leave. final bit return ; ... has been set by iorwf at in1. bcf acc3_2,7 ; clear bit shifted in from input. ; movf acc3_1,w ; Append '01' to root-so-far xorwf acc1_1,f ; movf acc3_2,w ; xorwf acc1_2,f ; ; movf acc1_1,w ; This subtraction is guaranteed not to subwf acc2_3,f ; ... cause a borrow, so subtract and movf acc1_2,w ; ... jump back to insert a '1' in the subwfb acc2_4,f ; ... root. goto setcurr ; ; restore movf acc1_1,w ; A subtract above at Sub_Cmp was -ve, so addwf acc2_3,f ; ... restore the remainder by adding. movf acc1_2,w ; The current bit of the root is zero. addwfc acc2_4,f ; goto shftUp ; ; ;======================================================================================== ; SQRT48 ; Calculates the square root of a 48 bit number using the binary restoring method. ; Input: acc2_6:acc2_1 ; Mask: acc3_3:acc3_1 ; Result: acc1_3:acc1_1 ; ; Takes between 810 and 890 cycles (incl. call and return). ; Uses 84 words ROM, 10 bytes RAM including 4 holding the input. ;======================================================================================== ; sqrt48 movlw 0x40 ; Initial value for Result is... movwf acc1_3 ; ... 01000000 00000000 00000000 clrf acc1_2 ; clrf acc1_1 ; ; movlw 0xC0 ; Initial value for mask is... movwf acc3_3 ; ... 11000000 00000000 00000000 clrf acc3_2 ; (second '1' is loop counter). clrf acc3_1 ; ; comp movf acc1_1,w ; Compare root-so-far with current subwf acc2_4,f ; ... remainder. movf acc1_2,w ; subwfb acc2_5,f ; movf acc1_3,w ; subwfb acc2_6,f ; bc $+4 ; goto undosub ; result is -ve, so need to restore ; setbit movf acc3_1,w ; set the current bit in the result. iorwf acc1_1,f ; movf acc3_2,w ; iorwf acc1_2,f ; movf acc3_3,w ; iorwf acc1_3,f ; ; upshft rlcf acc2_1,f ; rlcf acc2_2,f ; rlcf acc2_3,f ; rlcf acc2_4,f ; rlcf acc2_5,f ; rlcf acc2_6,f ; ; rrcf acc3_3,f ; Shift mask right for next bit, whilst rrcf acc3_2,f ; ... shifting in MSB from remainder. rrcf acc3_1,f ; btfsc acc3_3,7 ; If MSB is set, unconditionally set the goto nextset ; ... next bit. ; movf acc3_1,w ; Append '01' to root-so-far xorwf acc1_1,f ; movf acc3_2,w ; xorwf acc1_2,f ; movf acc3_3,w ; xorwf acc1_3,f ; ; bc $+4 ; If second '1' in mask is shifted out, goto comp ; ... then that was the last normal iteration. ; movf acc1_1,w ; Last bit Generation. subwf acc2_4,f ; ... The final subtract is 15-bit (23-bit root movf acc1_2,w ; ... plus '01'). Subtract 24-bits: if result subwfb acc2_5,f ; ... generates a carry, last bit is 0. movf acc1_3,w ; subwfb acc2_6,f ; bc $+4 ; return ; movf acc2_4,w ; Clear zero flag if remainder non zero xorwf acc2_5,w ; xorwf acc2_6,w ; ; movlw 1 ; bnz $+4 ; If result is 0 AND msb of N is '0', result bit btfsc acc2_3,7 ; ... is 0, otherwise '1'. xorwf acc1_1,f ; return ; ; nextset bnc $+4 ; If mask has shifted out, leave. final bit return ; ... has been set by iorwf at in1. bcf acc3_3,7 ; clear bit shifted in from input. ; movf acc3_1,w ; Append '01' to root-so-far xorwf acc1_1,f ; movf acc3_2,w ; xorwf acc1_2,f ; movf acc3_3,w ; xorwf acc1_3,f ; ; movf acc1_1,w ; This subtraction is guaranteed not to subwf acc2_4,f ; ... cause a borrow, so subtract and movf acc1_2,w ; ... jump back to insert a '1' in the subwfb acc2_5,f ; ... root. movf acc1_3,w ; subwfb acc2_6,f ; goto setbit ; ; undosub movf acc1_1,w ; A subtract above at Sub_Cmp was -ve, so addwf acc2_4,f ; ... restore the remainder by adding. movf acc1_2,w ; The current bit of the root is zero. addwfc acc2_5,f ; movf acc1_3,w ; addwfc acc2_6,f ; goto upshft ; ; ;======================================================================================== ;End of Main Task * ;======================================================================================== ; ;======================================================================================== ;16 bit square root routine test ;======================================================================================== sqrt16test clrf acc4_4 clrf acc4_3 clrf acc4_2 clrf acc4_1 ; loop16 incf acc4_1 bnz cont16 incf acc4_2 ; cont16 movff acc4_1,acc2_1 movff acc4_2,acc2_2 call sqrt16 goto loop16 ; ;======================================================================================== ;32 bit square root routine test ;======================================================================================== ; sqrt32test clrf acc4_4 clrf acc4_3 clrf acc4_2 clrf acc4_1 ; loop32 incf acc4_1 bnz cont32 incf acc4_2 bnz cont32 incf acc4_3 bnz cont32 incf acc4_4 ; cont32 movff acc4_1,acc2_1 movff acc4_2,acc2_2 movff acc4_3,acc2_3 movff acc4_4,acc2_4 call sqrt32 goto loop32 ; ;======================================================================================== ;48 bit square root routine test ;======================================================================================== ; sqrt48test clrf acc4_6 clrf acc4_4 clrf acc4_4 clrf acc4_3 clrf acc4_2 clrf acc4_1 ; loop48 incf acc4_1 bnz cont48 incf acc4_2 bnz cont48 incf acc4_3 bnz cont48 incf acc4_4 bnz cont48 incf acc4_5 bnz cont48 incf acc4_6 ; cont48 movff acc4_1,acc2_1 movff acc4_2,acc2_2 movff acc4_3,acc2_3 movff acc4_4,acc2_4 movff acc4_5,acc2_5 movff acc4_6,acc2_6 call sqrt48 goto loop48 ; ;======================================================================================== ;Processor initialisation * ;======================================================================================== ; Start ; Start of programme execution ; ;Set up oscllator control register movlw b'00000000' ; ; | |--------------; SCS0 ; | |---------------; SCS1 ; | |----------------; IOFS ; | |-----------------; OSTS ; | |------------------; IRCF0 ; | |-------------------; IRCF1 ; ||--------------------; IRCF2 ; |---------------------; IDLEN movwf OSCCON ; see page 32 of Data Sheet DS39631E ; ;Initialiise I/O ports ;setup PORTA movlw b'00001111' ; bits 0 - 3 as input, the rest as output movwf TRISA ; see page 105 of Data Sheet DS39631E ; setup PORTB movlw b'11111111' ; all inputs movwf TRISB ; see page 108 of Data Sheet DS39631E ;setup PORTC movlw b'11000010' ; ; | |--------------; T1OSO ; | |---------------; T1OSI ; | |----------------; RC2 ; | |-----------------; RC3 ; | |------------------; RC4 ; | |-------------------; RC5 ; ||--------------------; TX ; |---------------------; RX movwf TRISC ; see page 111 of Data Sheet DS39631E ; setup PORTD movlw b'00000000' ; set all as outputs movwf TRISD ; see page 114 of Data Sheet DS39631E ; setup PORTE movlw b'00000000' ; set all as outputs movwf TRISE ; see page 118 of Data Sheet DS39631E ; ;ADC configuration movlw b'00000000' ; ; | |--------------; ADON ; | |---------------; GO/DONE- ; | |----------------; CHS0 ; | |-----------------; CHS1 ; | |------------------; CHS2 ; | |-------------------; CHS3 ; ||--------------------; - ; |---------------------; - movwf ADCON0 ; see page 223 of Data Sheet DS39631E ; movlw b'00001011' ; ; | |--------------; PCFQ0 ; | |---------------; PCFQ1 ; | |----------------; PCFQ2 ; | |-----------------; PCFQ3 ; | |------------------; VCFG0 ; | |-------------------; VCFG1 ; ||--------------------; - ; |---------------------; - movwf ADCON1 ; see page 224 of Data Sheet DS39631E ; movlw b'10010101' ; right just, 4tad, Fosc/16 ; | |--------------; ADCS0 ; | |---------------; ADCS1 ; | |----------------; ADCS2 ; | |-----------------; ACQT0 ; | |------------------; ACQT1 ; | |-------------------; ACQT2 ; ||--------------------; - ; |---------------------; ADFM movwf ADCON2 ; see page 225 of Data Sheet DS39631E ; ;Comparator module configuration movlw b'11110101' ; common CVREF, AN0/AN1 inputs, invert both o/p ; | |--------------; CM0 ; | |---------------; CM1 ; | |----------------; CM2 ; | |-----------------; CIS ; | |------------------; C1INV ; | |-------------------; C2INV ; ||--------------------; C1OUT ; |---------------------; C2OUT movwf CMCON ; See page 233 of Data Sheet DS39631E ; movlw b'11001000' ; Ref on, high range, set to 50% (current 65uA) ; | |--------------; CRV0 ; | |---------------; CRV1 ; | |----------------; CRV2 ; | |-----------------; CRV3 ; | |------------------; CVRSS (0 = high range 1 = low range) ; | |-------------------; CVRR (0 = Vdd - Vss 1 = Vref+ - Vref-) ; ||--------------------; CVROE (0 = reference disconnected from AN2 pin) ; |---------------------; CVREN (1 = reference enabled) movwf CVRCON ; See page 239 of Data Sheet DS39631E ; ;Serial I/O configuration movlw h'00' ; 0 for 9600 baud movwf SPBRGH ; set high byte ; movlw calc(9600) ; calculate baudrate for 9600 with brgh=1 movwf SPBRG ; and store it ; movlw b'00001000' ; ; | |--------------; ADBEN ; | |---------------; WUE ; | |----------------; - ; | |-----------------; BRG16 ; | |------------------; TXCKP ; | |-------------------; RXDTP ; ||--------------------; RCIDL ; |---------------------; ABDOVF movwf BAUDCON ; see page 204 of Data Sheet DS39631E ; movlw b'00100100' ; ; | |--------------; TX9D ; | |---------------; TRMT ; | |----------------; BRGH ; | |-----------------; SENDB ; | |------------------; SYNC ; | |-------------------; TXEN ; ||--------------------; TX9 ; |---------------------; CSRC movwf TXSTA ; see page 202 of Data Sheet DS39631E ; movlw b'10010000' ; ; | |--------------; RX9D ; | |---------------; OERR ; | |----------------; FERR ; | |-----------------; ADDEN ; | |------------------; CREN ; | |-------------------; SRE ; ||--------------------; RX9 ; |---------------------; SPEN movwf RCSTA ; see page 203 of Data Sheet DS39631E ; ;Timer configuration movlw b'11000110' ; ; | |--------------; T0PS0 ; | |---------------; T0PS1 ; | |----------------; T0PS2 ; | |-----------------; PSA ; | |------------------; T0SE ; | |-------------------; T0CS ; ||--------------------; T08BIT ; |---------------------; TMR0ON movwf T0CON ; see page 123 of Data Sheet DS39631E ; movlw b'10001011' ; ; | |--------------; TMR1ON ; | |---------------; TMR1CS ; | |----------------; T1SYNC- ; | |-----------------; T1OSCEN ; | |------------------; T1CKPS0 ; | |-------------------; T1CSPS1 ; ||--------------------; T1RUN ; |---------------------; RD16 movwf T1CON ; see page 127 of Data Sheet DS39631E ; movlw b'00000100' ; ; | |--------------; T2CKPS0 ; | |---------------; T2CKPS1 ; | |----------------; TMR2ON ; | |-----------------; T2OUTPS0 ; | |------------------; T2OUTPS1 ; | |-------------------; T2OUTPS2 ; ||--------------------; T2OUTPS3 ; |---------------------; - movwf T2CON ; see page 133 of Data Sheet DS39631E ; movlw b'00000000' ; ; | |--------------; TMR3ON ; | |---------------; TNR3CS ; | |----------------; T3SYNC- ; | |-----------------; T3CCP1 ; | |------------------; T3CCPS0 ; | |-------------------; T3CCPS1 ; ||--------------------; T3CCP2 ; |---------------------; RD16 movwf T3CON ; see page 135 of Data Sheet DS39631E ; ;Interrupt configuration movlw b'01110000' ; ; | |--------------; RBIF ; | |---------------; INT0IF ; | |----------------; TMR0IF ; | |-----------------; RBIE ; | |------------------; INT0IE ; | |-------------------; TMR0IE ; ||--------------------; PEIE ; |---------------------; GIE movwf INTCON ; see page 93 of Data Sheet DS39631E ; movlw b'11000000' ; ; | |--------------; RBIP ; | |---------------; - ; | |----------------; TMR0IP ; | |-----------------; - ; | |------------------; INTEDG2 ; | |-------------------; INTEDG1 ; ||--------------------; INTEDG0 ; |---------------------; RBPU- movwf INTCON2 ; see page 94 of Data Sheet DS39631E ; movlw b'00000000' ; ; | |--------------; INT1IF ; | |---------------; INT2IF ; | |----------------; - ; | |-----------------; INT1IE ; | |------------------; INT2IE ; | |-------------------; - ; ||--------------------; INT1IP ; |---------------------; INT2IP movwf INTCON3 ; see page 95 of Data Sheet DS39631E ; movlw b'00100001' ; ; | |--------------; TMR1IE ; | |---------------; TMR2IE ; | |----------------; CCP1IE ; | |-----------------; SSPIE ; | |------------------; TXIE ; | |-------------------; RCIE ; ||--------------------; ADIE ; |---------------------; PSPIE movwf PIE1 ; see page 98 of Data Sheet DS39631E ; movlw b'00000000' ; ; | |--------------; CCP2IE ; | |---------------; TMR3IE ; | |----------------; HLVDIE ; | |-----------------; BCLIE ; | |------------------; EEIE ; | |-------------------; - ; ||--------------------; CMIE ; |---------------------; OSCFIE movwf PIE2 ; see page 99 of Data Sheet DS39631E ; clrf PORTC ; clear PORTC clrf PORTD ; clear PORTD clrf PORTE ; clear PORTE ; ;Clear all user ram before start of main task. clr_ram lfsr FSR0,0x000 ; point to beginning of RAM clr_nxt clrf POSTINC0 ; clear location and inrement pointer movlw h'6' ; at top of RAM ? xorwf FSR0H,w ; check it bnz clr_nxt ; loop till top reached ; ; ;Reset all timers and clear any ourstanding interrupt requests. clrf PIR1 ; clear interrupt request reg 1 clrf PIR2 ; clear interrupt request reg 2 clrf TMR0 ; reset all timers clrf TMR1L ; clrf TMR1H ; ; ;**************************************************************************************** END ; directive 'end of program' * ;****************************************************************************************
file: /Techref/member/petergharrison-btinternet-/18Fmathstest2_asm.htm, 37KB, , updated: 2014/4/9 16:09, local time: 2024/12/1 09:49,
18.97.9.169:LOG IN
|
©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://massmind.org/Techref/member/petergharrison-btinternet-/18Fmathstest2_asm.htm"> PIC Microcontoller Basic Math Method PIC18F4520 by Peter G. Harrison</A> |
Did you find what you needed? |