PIC Microcontroller 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

	swapf	NumH,w	;w  = A2*16+A3
        andlw   $0F     ;w  = A3		*** PERSONALLY, I'D REPLACE THESE 2
        addlw   $F0	;w  = A3-16	*** LINES WITH "IORLW 11110000B" -AW
        movwf   Thou	;B3 = A3-16
        addwf   Thou,f	;B3 = 2*(A3-16) = 2A3 - 32
        addlw   $E2	;w  = A3-16 - 30 = A3-46
        movwf   Hund	;B2 = A3-46
        addlw   $32	;w  = A3-46 + 50 = A3+4
        movwf   Ones	;B0 = A3+4

        movf    NumH,w	;w  = A3*16+A2
        andlw   $0F	;w  = A2
        addwf   Hund,f	;B2 = A3-46 + A2 = A3+A2-46
        addwf   Hund,f	;B2 = A3+A2-46  + A2 = A3+2A2-46
        addwf   Ones,f	;B0 = A3+4 + A2 = A3+A2+4
        addlw   $E9	;w  = A2 - 23
        movwf   Tens	;B1 = A2-23
        addwf   Tens,f	;B1 = 2*(A2-23)
        addwf   Tens,f	;B1 = 3*(A2-23) = 3A2-69 (Doh! thanks NG)

        swapf   NumL,w	;w  = A0*16+A1
        andlw   $0F	;w  = A1
        addwf   Tens,f	;B1 = 3A2-69 + A1 = 3A2+A1-69 range -69...-9
        addwf   Ones,f	;B0 = A3+A2+4 + A1 = A3+A2+A1+4 and Carry = 0 (thanks NG)

        rlf     Tens,f	;B1 = 2*(3A2+A1-69) + C = 6A2+2A1-138 and Carry is now 1 as tens register had to be negitive
        rlf     Ones,f	;B0 = 2*(A3+A2+A1+4) + C = 2A3+2A2+2A1+9 (+9 not +8 due to the carry from prev line, Thanks NG)
        comf    Ones,f	;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:
;;      comf Ones, f
;;      incf Ones, f
;;      decf Ones, f
;;First two instructions make up negation. So,
;;Ones  = -1 * Ones - 1 
;;      = - 2 * (A3 + A2 + A1) - 9 - 1 
;;      = - 2 * (A3 + A2 + A1) - 10
        rlf     Ones,f	;B0 = 2*(-2A3-2A2-2A1-10) = -4A3-4A2-4A1-20

        movf    NumL,w	;w  = A1*16+A0
        andlw   $0F	;w  = A0
        addwf   Ones,f	;B0 = -4A3-4A2-4A1-20 + A0 = A0-4(A3+A2+A1)-20 range -215...-5 Carry=0
        rlf     Thou,f	;B3 = 2*(2A3 - 32) = 4A3 - 64

        movlw   $07	;w  = 7
        movwf   TenK	;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.

        movlw   $0A	;w  = 10
Lb1:			;do
        addwf   Ones,f	; B0 += 10
        decf    Tens,f	; B1 -= 1
        btfss   3,0
	;skip no carry
         goto   Lb1	; while B0 < 0
	;jmp carry
Lb2:			;do
        addwf   Tens,f	; B1 += 10
        decf    Hund,f	; B2 -= 1
        btfss   3,0
         goto   Lb2	; while B1 < 0
Lb3:			;do
        addwf   Hund,f	; B2 += 10
        decf    Thou,f	; B3 -= 1
        btfss   3,0
         goto   Lb3	; while B2 < 0
Lb4:			;do
        addwf   Thou,f	; B3 += 10
        decf    TenK,f	; B4 -= 1
        btfss   3,0
         goto   Lb4	; while B3 < 0

        retlw   0