please dont rip this site

PIC Microcontoller Basic Math Method PIC18F4520

by Peter G. Harrison

(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/11/24 10:19,
TOP NEW HELP FIND: 
18.117.166.193: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?
Please DO link to this page! Digg it! / MAKE!

<A HREF="http://sxlist.com/TECHREF/member/petergharrison-btinternet-/18Fmathstest2_asm.htm"> PIC Microcontoller Basic Math Method PIC18F4520 by Peter G. Harrison</A>

After you find an appropriate page, you are invited to your to this massmind site! (posts will be visible only to you before review) Just type a nice message (short messages are blocked as spam) in the box and press the Post button. (HTML welcomed, but not the <A tag: Instead, use the link box to link to another page. A tutorial is available Members can login to post directly, become page editors, and be credited for their posts.


Link? Put it here: 
if you want a response, please enter your email address: 
Attn spammers: All posts are reviewed before being made visible to anyone other than the poster.
Did you find what you needed?