PIC Microcontoller Radix Math Method

Binary to BCD unpacked 16 bit to 5 digit

From: John Payson via Scott Dattalo

see http://www.dattalo.com/technical/software/pic/bcd.txt for notes on how this works. Plan on a headache. <GRIN>
[ed: quick guess at speed is that about 200 instructions will be executed and 50 bytes + 7 registers used]

;Takes hex number in NumH:NumL  Returns decimal in ;TenK:Thou:Hund:Tens:Ones
;written by John Payson

;input
;=A3*163 + A2*162 + A1*161 + A0*160
;=A3*4096 + A2*256 + A1*16 + A0
NumH	equ	AD3M	;A3*16+A2
NumL	equ	AD3L	;A1*16+A0
;share variables
;=B4*104 + B3*103 + B2*102 + B1*101 + B0*100
;=B4*10000 + B3*1000 + B2*100 + B1*10 + B0
TenK	equ	LOOPER	;B4
Thou	equ	D2	;B3
Hund	equ	D1	;B2
Tens	equ	R2	;B1
Ones	equ	R1	;B0

	mov	W, <>NumH	;w  = A2*16+A3
	and	W, #$0F	;w  = A3		*** PERSONALLY, I'D REPLACE THESE 2
;*** WARNING: ADDLW was expanded in three instructions! Check if previous instruction is a skip instruction. 
;        addlw   $F0	;w  = A3-16	*** LINES WITH "IORLW 11110000B" -AW
	mov	Hack, W
	mov	W, #$F0	;w  = A3-16	*** LINES WITH "IORLW 11110000B" -AW
	add	W, Hack
	mov	Thou, W	;B3 = A3-16
	add	Thou, W	;B3 = 2*(A3-16) = 2A3 - 32
;*** WARNING: ADDLW was expanded in three instructions! Check if previous instruction is a skip instruction. 
;        addlw   $E2	;w  = A3-16 - 30 = A3-46
	mov	Hack, W
	mov	W, #$E2	;w  = A3-16 - 30 = A3-46
	add	W, Hack
	mov	Hund, W	;B2 = A3-46
;*** WARNING: ADDLW was expanded in three instructions! Check if previous instruction is a skip instruction. 
;        addlw   $32	;w  = A3-46 + 50 = A3+4
	mov	Hack, W
	mov	W, #$32	;w  = A3-46 + 50 = A3+4
	add	W, Hack
	mov	Ones, W	;B0 = A3+4

	mov	W, NumH	;w  = A3*16+A2
	and	W, #$0F	;w  = A2
	add	Hund, W	;B2 = A3-46 + A2 = A3+A2-46
	add	Hund, W	;B2 = A3+A2-46  + A2 = A3+2A2-46
	add	Ones, W	;B0 = A3+4 + A2 = A3+A2+4
;*** WARNING: ADDLW was expanded in three instructions! Check if previous instruction is a skip instruction. 
;        addlw   $E9	;w  = A2 - 23
	mov	Hack, W
	mov	W, #$E9	;w  = A2 - 23
	add	W, Hack
	mov	Tens, W	;B1 = A2-23
	add	Tens, W	;B1 = 2*(A2-23)
	add	Tens, W	;B1 = 3*(A2-23) = 3A2-69 (Doh! thanks NG)

	mov	W, <>NumL	;w  = A0*16+A1
	and	W, #$0F	;w  = A1
	add	Tens, W	;B1 = 3A2-69 + A1 = 3A2+A1-69 range -69...-9
	add	Ones, W	;B0 = A3+A2+4 + A1 = A3+A2+A1+4 and Carry = 0 (thanks NG)

	rl	Tens	;B1 = 2*(3A2+A1-69) + C = 6A2+2A1-138 and Carry is now 1 as tens register had to be negitive
	rl	Ones	;B0 = 2*(A3+A2+A1+4) + C = 2A3+2A2+2A1+9 (+9 not +8 due to the carry from prev line, Thanks NG)
	not	Ones	;B0 = ~(2A3+2A2+2A1+9) = -2A3-2A2-2A1-10 (ones complement plus 1 is twos complement. Thanks SD)
;;Nikolai Golovchenko [golovchenko at MAIL.RU] says: comf can be regarded like:
;;	not	Ones
;;	inc	Ones
;;	dec	Ones
;;First two instructions make up negation. So,
;;Ones  = -1 * Ones - 1
;;      = - 2 * (A3 + A2 + A1) - 9 - 1
;;      = - 2 * (A3 + A2 + A1) - 10
	rl	Ones	;B0 = 2*(-2A3-2A2-2A1-10) = -4A3-4A2-4A1-20

	mov	W, NumL	;w  = A1*16+A0
	and	W, #$0F	;w  = A0
	add	Ones, W	;B0 = -4A3-4A2-4A1-20 + A0 = A0-4(A3+A2+A1)-20 range -215...-5 Carry=0
	rl	Thou	;B3 = 2*(2A3 - 32) = 4A3 - 64

	mov	W, #$07	;w  = 7
	mov	TenK, W	;B4 = 7

;B0 = A0-4(A3+A2+A1)-20	;-5...-200
;B1 = 6A2+2A1-138	;-18...-138
;B2 = A3+2A2-46		;-1...-46
;B3 = 4A3-64		;-4...-64
;B4 = 7			;7
; At this point, the original number is
; equal to TenK*10000+Thou*1000+Hund*100+Tens*10+Ones
; if those entities are regarded as two's compliment
; binary.  To be precise, all of them are negative
; except TenK.  Now the number needs to be normal-
; ized, but this can all be done with simple byte
; arithmetic.

	mov	W, #$0A	;w  = 10
Lb1:			;do
	add	Ones, W	; B0 += 10
	dec	Tens	; B1 -= 1
	sb	3.0
	;skip no carry
	jmp	Lb1	; while B0 < 0
	;jmp carry
Lb2:			;do
	add	Tens, W	; B1 += 10
	dec	Hund	; B2 -= 1
	sb	3.0
	jmp	Lb2	; while B1 < 0
Lb3:			;do
	add	Hund, W	; B2 += 10
	dec	Thou	; B3 -= 1
	sb	3.0
	jmp	Lb3	; while B2 < 0
Lb4:			;do
	add	Thou, W	; B3 += 10
	dec	TenK	; B4 -= 1
	sb	3.0
	jmp	Lb4	; while B3 < 0

	retw	#0