ON 20050109@12:51:57 PM at page: http://techref.massmind.org/techref/microchip/math/index.htm#38361.5360763889 James Newton[JMN-EFP-786] Says /techref/microchip/math/ftp://ftp.epemag.wimborne.co.uk/pub/PICS/PICtricks/ Misc. PIC routines, some good, some not so good. ON 20050109@12:52:20 PM at page: http://techref.massmind.org/techref/microchip/math/index.htm#38361.5363425926 James Newton[JMN-EFP-786] See also: /techref/microchip/math/ftp://ftp.epemag.wimborne.co.uk/pub/PICS/PICtricks/ Misc. PIC routines, some good, some not so good. ON 20050109@12:52:30 PM at page: http://techref.massmind.org/techref/microchip/math/index.htm#38361.5360763889 James Newton[JMN-EFP-786] removed post 38361.5360763889 |Delete ' Misc. PIC routines, some good, some not so good. ' ON 20050109@11:22:13 PM at page: http://techref.massmind.org/techref/microchip/math/basic.htm#38361.9737615741 James Newton[JMN-EFP-786] Says in a new file at: http://techref.massmind.org/techref/microchip/math/32bmath-ph.htm 32-bit signed integer math routines. add, subtract, multiply, divide, round, sqrt, bin2dec, dec2bin. By Peter Hemsley. ON 20050109@11:23:07 PM at page: http://techref.massmind.org/techref/microchip/math/basic.htm# James Newton[JMN-EFP-786] edited the page. Difference: http://techref.massmind.org/techref/diff.asp?url=H:\techref\microchip\math\basic.htm&version=3 ON 20050109@11:44:36 PM at page: http://techref.massmind.org/techref/microchip/math/32bmath-ph.htm# James Newton[JMN-EFP-786] edited the page. Difference: http://techref.massmind.org/techref/diff.asp?url=H:\techref\microchip\math\32bmath-ph.htm&version=0 ON 20050109@11:46:05 PM at page: http://techref.massmind.org/techref/microchip/math/32bmath-ph.htm# James Newton[JMN-EFP-786] edited the page. Difference: http://techref.massmind.org/techref/diff.asp?url=H:\techref\microchip\math\32bmath-ph.htm&version=1 ON 20050109@11:46:50 PM at page: http://techref.massmind.org/techref/microchip/math/32bmath-ph.htm#38361.9908564815 James Newton[JMN-EFP-786] Code:
;*** SIGNED 32-BIT INTEGER MATHS ROUTINES FOR PIC16 SERIES BY PETER HEMSLEY ***
;
;Functions:
;	add
;	subtract
;	multiply
;	divide
;	round
;	sqrt
;	bin2dec
;	dec2bin


;Variable declarations

mathram	equ	;(insert required ram address here)

	cblock mathram
REGA0				;lsb
REGA1
REGA2
REGA3				;msb

REGB0				;lsb
REGB1
REGB2
REGB3				;msb

REGC0				;lsb
REGC1
REGC2
REGC3				;msb

DSIGN				;Digit Sign. 0=positive,1=negative
DIGIT1				;MSD
DIGIT2
DIGIT3
DIGIT4
DIGIT5				;Decimal (BCD) digits
DIGIT6
DIGIT7
DIGIT8
DIGIT9
DIGIT10				;LSD

MTEMP
MCOUNT
DCOUNT
	endc


;*** 32 BIT SIGNED SUTRACT ***
;REGA - REGB -> REGA
;Return carry set if overflow

subtract
	call	negateb		;Negate REGB
	skpnc
	return			;Overflow

;*** 32 BIT SIGNED ADD ***
;REGA + REGB -> REGA
;Return carry set if overflow

add	movf	REGA3,w		;Compare signs
	xorwf	REGB3,w
	movwf	MTEMP

	call	addba		;Add REGB to REGA

	clrc			;Check signs
	movf	REGB3,w		;If signs are same
	xorwf	REGA3,w		;so must result sign
	btfss	MTEMP,7		;else overflow
	addlw	0x80
	return

;*** 32 BIT SIGNED MULTIPLY ***
;REGA * REGB -> REGA
;Return carry set if overflow

multiply
	clrf	MTEMP		;Reset sign flag
	call	absa		;Make REGA positive
	skpc
	call	absb		;Make REGB positive
	skpnc
	return			;Overflow

	call	movac		;Move REGA to REGC
	call	clra		;Clear product

	movlw	D'31'		;Loop counter
	movwf	MCOUNT

muloop	call	slac		;Shift left product and multiplicand
	
	rlf	REGC3,w		;Test MSB of multiplicand
	skpnc			;If multiplicand bit is a 1 then
	call	addba		;add multiplier to product

	skpc			;Check for overflow
	rlf	REGA3,w
	skpnc
	return

	decfsz	MCOUNT,f	;Next
	goto	muloop

	btfsc	MTEMP,0		;Check result sign
	call	negatea		;Negative
	return


;*** 32 BIT SIGNED DIVIDE ***
;REGA / REGB -> REGA
;Remainder in REGC
;Return carry set if overflow or division by zero

divide	clrf	MTEMP		;Reset sign flag
	movf	REGB0,w		;Trap division by zero
	iorwf	REGB1,w
	iorwf	REGB2,w
	iorwf	REGB3,w
	sublw	0
	skpc
	call	absa		;Make dividend (REGA) positive
	skpc
	call	absb		;Make divisor (REGB) positive
	skpnc
	return			;Overflow

	clrf	REGC0		;Clear remainder
	clrf	REGC1
	clrf	REGC2
	clrf	REGC3
	call	slac		;Purge sign bit

	movlw	D'31'		;Loop counter
	movwf	MCOUNT

dvloop	call	slac		;Shift dividend (REGA) msb into remainder (REGC)

	movf	REGB3,w		;Test if remainder (REGC) >= divisor (REGB)
	subwf	REGC3,w
	skpz
	goto	dtstgt
	movf	REGB2,w
	subwf	REGC2,w
	skpz
	goto	dtstgt
	movf	REGB1,w
	subwf	REGC1,w
	skpz
	goto	dtstgt
	movf	REGB0,w
	subwf	REGC0,w
dtstgt	skpc			;Carry set if remainder >= divisor
	goto	dremlt

	movf	REGB0,w		;Subtract divisor (REGB) from remainder (REGC)
	subwf	REGC0,f
	movf	REGB1,w
	skpc
	incfsz	REGB1,w
	subwf	REGC1,f
	movf	REGB2,w
	skpc
	incfsz	REGB2,w
	subwf	REGC2,f
	movf	REGB3,w
	skpc
	incfsz	REGB3,w
	subwf	REGC3,f
	clrc
	bsf	REGA0,0		;Set quotient bit

dremlt	decfsz	MCOUNT,f	;Next
	goto	dvloop

	btfsc	MTEMP,0		;Check result sign
	call	negatea		;Negative
	return

;*** ROUND RESULT OF DIVISION TO NEAREST INTEGER ***

round	clrf	MTEMP		;Reset sign flag
	call	absa		;Make positive
	clrc
	call	slc		;Multiply remainder by 2
	movf	REGB3,w		;Test if remainder (REGC) >= divisor (REGB)
	subwf	REGC3,w
	skpz
	goto	rtstgt
	movf	REGB2,w
	subwf	REGC2,w
	skpz
	goto	dtstgt
	movf	REGB1,w
	subwf	REGC1,w
	skpz
	goto	rtstgt
	movf	REGB0,w
	subwf	REGC0,w
rtstgt	skpc			;Carry set if remainder >= divisor
	goto	rremlt
	incfsz	REGA0,f		;Add 1 to quotient
	goto	rremlt
	incfsz	REGA1,f
	goto	rremlt
	incfsz	REGA2,f
	goto	rremlt
	incf	REGA3,f
	skpnz
	return			;Overflow,return carry set
rremlt	btfsc	MTEMP,0		;Restore sign
	call	negatea
	return


;*** 32 BIT SQUARE ROOT ***
;sqrt(REGA) -> REGA
;Return carry set if negative

sqrt	rlf	REGA3,w		;Trap negative values
	skpnc
	return

	call	movac		;Move REGA to REGC
	call	clrba		;Clear remainder (REGB) and root (REGA)

	movlw	D'16'		;Loop counter
	movwf	MCOUNT

sqloop	rlf	REGC0,f		;Shift two msb's
	rlf	REGC1,f		;into remainder
	rlf	REGC2,f
	rlf	REGC3,f
	rlf	REGB0,f
	rlf	REGB1,f
	rlf	REGB2,f
	rlf	REGC0,f
	rlf	REGC1,f
	rlf	REGC2,f
	rlf	REGC3,f
	rlf	REGB0,f
	rlf	REGB1,f
	rlf	REGB2,f

	setc			;Add 1 to root
	rlf	REGA0,f		;Align root
	rlf	REGA1,f
	rlf	REGA2,f

	movf	REGA2,w		;Test if remdr (REGB) >= root (REGA)
	subwf	REGB2,w
	skpz
	goto	ststgt
	movf	REGA1,w
	subwf	REGB1,w
	skpz
	goto	ststgt
	movf	REGA0,w
	subwf	REGB0,w
ststgt	skpc			;Carry set if remdr >= root
	goto	sremlt

	movf	REGA0,w		;Subtract root (REGA) from remdr (REGB)
	subwf	REGB0,f
	movf	REGA1,w
	skpc
	incfsz	REGA1,w
	subwf	REGB1,f
	movf	REGA2,w
	skpc
	incfsz	REGA2,w
	subwf	REGB2,f
	bsf	REGA0,1		;Set current root bit

sremlt	bcf	REGA0,0		;Clear test bit
	decfsz	MCOUNT,f	;Next
	goto	sqloop

	clrc
	rrf	REGA2,f		;Adjust root alignment
	rrf	REGA1,f
	rrf	REGA0,f
	return


;*** 32 BIT SIGNED BINARY TO DECIMAL ***
;REGA -> DIGITS 1 (MSD) TO 10 (LSD) & DSIGN
;DSIGN = 0 if REGA is positive, 1 if negative
;Return carry set if overflow
;Uses FSR register

bin2dec	clrf	MTEMP		;Reset sign flag
	call	absa		;Make REGA positive
	skpnc
	return			;Overflow

	call	clrdig		;Clear all digits

	movlw	D'32'		;Loop counter
	movwf	MCOUNT

b2dloop	rlf	REGA0,f		;Shift msb into carry
	rlf	REGA1,f
	rlf	REGA2,f
	rlf	REGA3,f

	movlw	DIGIT10
	movwf	FSR		;Pointer to digits
	movlw	D'10'		;10 digits to do
	movwf	DCOUNT

adjlp	rlf	INDF,f		;Shift digit and carry 1 bit left
	movlw	D'10'
	subwf	INDF,w		;Check and adjust for decimal overflow
	skpnc
	movwf	INDF

	decf	FSR,f		;Next digit
	decfsz	DCOUNT,f
	goto	adjlp

	decfsz	MCOUNT,f	;Next bit
	goto	b2dloop

	btfsc	MTEMP,0		;Check sign
	bsf	DSIGN,0		;Negative
	clrc
	return


;*** 32 BIT SIGNED DECIMAL TO BINARY ***
;Decimal DIGIT1 thro DIGIT(X) & DSIGN -> REGA
;Set DSIGN = 0 for positive, DSIGN = 1 for negative values
;Most significant digit in DIGIT1
;Enter this routine with digit count in w register
;Return carry set if overflow
;Uses FSR register

dec2bin	movwf	MTEMP		;Save digit count

	movlw	D'32'		;Outer bit loop counter
	movwf	MCOUNT

d2blp1	movlw	DIGIT1-1	;Set up pointer to MSD
	movwf	FSR
	movf	MTEMP,w		;Inner digit loop counter
	movwf	DCOUNT

	movlw	D'10'
	clrc			;Bring in '0' bit into MSD

d2blp2	incf	FSR,f
	skpnc
	addwf	INDF,f		;Add 10 if '1' bit from prev digit
	rrf	INDF,f		;Shift out LSB of digit

	decfsz	DCOUNT,f	;Next L.S. Digit
	goto	d2blp2

	rrf	REGA3,f		;Shift in carry from digits
	rrf	REGA2,f
	rrf	REGA1,f
	rrf	REGA0,f

	decfsz	MCOUNT,f	;Next bit
	goto	d2blp1

	movf	INDF,w		;Check for overflow
	addlw	0xFF
	skpc
	rlf	REGA3,w
	skpnc
	return

	btfsc	DSIGN,0		;Check result sign
	call	negatea		;Negative
	return


;UTILITY ROUTINES


;Add REGB to REGA (Unsigned)
;Used by add, multiply,

addba	movf	REGB0,w		;Add lo byte
	addwf	REGA0,f

	movf	REGB1,w		;Add mid-lo byte
	skpnc			;No carry_in, so just add
	incfsz	REGB1,w		;Add carry_in to REGB
	addwf	REGA1,f		;Add and propagate carry_out

	movf	REGB2,w		;Add mid-hi byte
	skpnc
	incfsz	REGB2,w
	addwf	REGA2,f

	movf	REGB3,w		;Add hi byte
	skpnc
	incfsz	REGB3,w
	addwf	REGA3,f
	return


;Move REGA to REGC
;Used by multiply, sqrt

movac	movf	REGA0,w
	movwf	REGC0
	movf	REGA1,w
	movwf	REGC1
	movf	REGA2,w
	movwf	REGC2
	movf	REGA3,w
	movwf	REGC3
	return


;Clear REGB and REGA
;Used by sqrt

clrba	clrf	REGB0
	clrf	REGB1
	clrf	REGB2
	clrf	REGB3

;Clear REGA
;Used by multiply, sqrt

clra	clrf	REGA0
	clrf	REGA1
	clrf	REGA2
	clrf	REGA3
	return


;Check sign of REGA and convert negative to positive
;Used by multiply, divide, bin2dec, round

absa	rlf	REGA3,w
	skpc
	return			;Positive

;Negate REGA
;Used by absa, multiply, divide, bin2dec, dec2bin, round

negatea	movf	REGA3,w		;Save sign in w
	andlw	0x80

	comf	REGA0,f		;2's complement
	comf	REGA1,f
	comf	REGA2,f
	comf	REGA3,f
	incfsz	REGA0,f
	goto	nega1
	incfsz	REGA1,f
	goto	nega1
	incfsz	REGA2,f
	goto	nega1
	incf	REGA3,f
nega1
	incf	MTEMP,f		;flip sign flag
	addwf	REGA3,w		;Return carry set if -2147483648
	return


;Check sign of REGB and convert negative to positive
;Used by multiply, divide

absb	rlf	REGB3,w
	skpc
	return			;Positive

;Negate REGB
;Used by absb, subtract, multiply, divide

negateb	movf	REGB3,w		;Save sign in w
	andlw	0x80

	comf	REGB0,f		;2's complement
	comf	REGB1,f
	comf	REGB2,f
	comf	REGB3,f
	incfsz	REGB0,f
	goto	negb1
	incfsz	REGB1,f
	goto	negb1
	incfsz	REGB2,f
	goto	negb1
	incf	REGB3,f
negb1
	incf	MTEMP,f		;flip sign flag
	addwf	REGB3,w		;Return carry set if -2147483648
	return


;Shift left REGA and REGC
;Used by multiply, divide, round

slac	rlf	REGA0,f
	rlf	REGA1,f
	rlf	REGA2,f
	rlf	REGA3,f
slc	rlf	REGC0,f
	rlf	REGC1,f
	rlf	REGC2,f
	rlf	REGC3,f
	return


;Set all digits to 0
;Used by bin2dec

clrdig	clrf	DSIGN
	clrf	DIGIT1
	clrf	DIGIT2
	clrf	DIGIT3
	clrf	DIGIT4
	clrf	DIGIT5
	clrf	DIGIT6
	clrf	DIGIT7
	clrf	DIGIT8
	clrf	DIGIT9
	clrf	DIGIT10
	return

ON 20050109@11:53:54 PM at page: http://techref.massmind.org/techref/microchip/math/32bmath-ph.htm# James Newton[JMN-EFP-786] edited the page. Difference: http://techref.massmind.org/techref/diff.asp?url=H:\techref\microchip\math\32bmath-ph.htm&version=3 ON 20050109@11:54:46 PM at page: http://techref.massmind.org/techref/microchip/math/32bmath-ph.htm# James Newton[JMN-EFP-786] edited the page. Difference: http://techref.massmind.org/techref/diff.asp?url=H:\techref\microchip\math\32bmath-ph.htm&version=4 ON 20050109@11:58:34 PM at page: http://techref.massmind.org/techref/microchip/math/32bmath-ph.htm# James Newton[JMN-EFP-786] edited the page. Difference: http://techref.massmind.org/techref/diff.asp?url=H:\techref\microchip\math\32bmath-ph.htm&version=5 ON 20050110@12:16:58 AM at page: http://www.piclist.com/techref/microchip/math/basic.htm#38362.0117824074 James Newton[JMN-EFP-786] Says ftp://ftp.epemag.wimborne.co.uk/pub/PICS/PICtricks/Floating_Point/Floating Point.zip Floating point library and format conversion tools ON 20050110@12:17:49 AM at page: http://www.piclist.com/techref/microchip/math/basic.htm# James Newton[JMN-EFP-786] edited the page. Difference: http://www.piclist.com/techref/diff.asp?url=H:\techref\microchip\math\basic.htm&version=6 ON 20050130@10:01:14 AM at page: http://www.piclist.com/techref/microchip/math/medfilsort-mc.htm#38382.4175231481 [louisn-iafrica-] Says I had great trouble with unstable adc values and this code helped a great deal, but it was not the final answer. I finaly averaged 16 median values to get a very stable result. With a 4MHz PIC it takes quite some time, but the result was worth it.