 ## 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
;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   0x0F     ;w  = A3		*** PERSONALLY, I'D REPLACE THESE 2
addlw   0xF0	;w  = A3-16	*** LINES WITH "IORLW b'11110000B' " -AW
movwf   Thou	;B3 = A3-16
addwf   Thou,f	;B3 = 2*(A3-16) = 2A3 - 32
addlw   .226	;w  = A3-16 - 30 = A3-46
movwf   Hund	;B2 = A3-46
addlw   .50	;w  = A3-46 + 50 = A3+4
movwf   Ones	;B0 = A3+4

movf    NumH,w	;w  = A3*16+A2
andlw   0x0F	;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   .233	;w  = A2 - 23
movwf   Tens	;B1 = A2-23
addwf   Tens,f	;B1 = 3*(A2-23) = 3A2-69 (Doh! thanks NG)

swapf   NumL,w	;w  = A0*16+A1
andlw   0x0F	;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   0x0F	;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   0x07	;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   .10	;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

```

Archive:

• Re "adapted to work on the 18F series"

i also found that you have to change "rlf" opcode to "rlcf" for the 18F..

thanks for the code.. works great!+
• /techref/microchip/math/radix/b2bu-16b5d.htm omg Nice!!!!! Gz very very thx =) run Perfect+
• Perfect, thank you all!
+
• /techref/postbot.asp?by=time&id=piclist/2008/08/12/174135a A version adapted to work on the 18F series+

• If you convert this routine to work with PIC18, invert addition and decrement instruction in normalization code. Replace `btfss 3,0` by `btfss STATUS, C, ACCESS`

Original code :
` addwf Ones,f ; B0 += 10`
` decf Tens,f ; B1 -= 1`
` btfss 3,0`

Modified code :
` decf Tens,f ; B1 -= 1`
` addwf Ones,f ; B0 += 10`
` btfss STATUS, C, ACCESS`

Do it for all digits...+

• http://www.dattalo.com/technical/software/pic/bcd.txt Scott Dattalo's analysis of John Payson's code:
```
If you have a 4 digit hexadecimal number, it may be written as

N = a_3*16^3 + a_2*16^2 + a_1*16 + a_0

where a_i, i=0,1,2,3 are the four hexadecimal digits. If you
wish to convert this to decimal, then you need to express N as

N = b_4*10^4 + b_3*10^3 + b_2*10^2 + b_1*10 + b_0

Where b_j, j=0,1,2,3,4 are the five decimal digits.
The reason there are 5 digits in the decimal representation
is because the maximum four digit hexadecimal number (0xffff)
requires 5 decimal digits (65535). Now the goal is to find
a set of equations that allow the b_j's to be expressed in
terms of the a_i's. There are infinitely many ways to do this.
Here are two of probably the simplest expressions.
First, expand the 16^i's and then collect all coefficients
of the 10^j's:

N = a_3*4096 + a_2*256 + a_1*16 + a_0
= a_3*4*10^3  + a_2*2*10^2 + (a_3*9 + a_2*5 + a_1)*10 +
6*(a_3 + a_2 + a_1) + a_0

This gives us five equations:

b_0 = 6*(a_3 + a_2 + a_1) + a_0
b_1 = a_3*9 + a_2*5 + a_1
b_2 = 2*a_2
b_3 = 4*a_3
b_4 = 0

Which as John says, must be "normalized". Normalization in
this context means we need to reduce the b_j's such that
0 <= b_j <= 9

In other words we need to find:

c_0 = b_0 mod 10

b_1 = (b_1 + (b_0 - c_0)/10)
c_1 =  b_1 mod 10

b_2 = (b_2 + (b_1 - c_1)/10)
c_2 = b_2 mod 10

b_3 = (b_3 + (b_2 - c_2)/10)
c_3 = b_3 mod 10

c_4 = (b_4 + (b_3 - c_3)/10) mod 10
= (b_2 - c_2)/10

Division by 10 can be done quite efficiently (as was shown
in another thread several months ago). However, it does require
a significant amount of code space compared to say repeated
subtractions. Unfortunately, there can be very many subtractions
that are required. For example, b_1 could be as large as 15*16,
or 240. 10 would have to be subtracted 24 times if you wish to
compute 240 mod 10. I presume John realized this inefficiency
and thus sought to express N so that repeated subtractions
could be used and that the total number of subtractions are
minimized. This leads to the next way that N can be expressed:

N = a_3*(4100 - 4) + a_2*(260 - 4) + a_1*(20-4) + a_0
= 4*a_3*10^3 + (a_3 + 2*a_2)*10^2 + (6*a_2 + 2*a_1)*10 +
a_0 - 4*(a_3 + a_2 + a_1)

This gives five new equations for the b_j's.

b_0 = a_0 - 4*(a_3 + a_2 + a_1)
b_1 = 6*a_2 + 2*a_1
b_2 = a_3 + 2*a_2
b_3 = 4*a_3
b_4 = 0

However, these equations are still not conducive to the
repeated subtraction algorithm, at least the way John has
done it. In other words, it is possible to pre-condition
each of the b_j's so that they are less than zero. Then
the repeated subtractions can simultaneously perform the
"mod 10" and "/10" operations shown above. Consider the
equation b_0 for example,

b_0 = a_0 - 4*(a_3 + a_2 + a_1)

Since each a_i must satisfy:  0 <= a_i <= 15, then b_0
ranges:

-60 <= b_0 <= 15

We can make b_0 negative by subtracting any number greater than
15. A logical choice is 20. This is because if we subtract 20
from b_0, we can add 2 to b_1 to keep the net result the same.
The reason we add "2" can be seen:

b_1*10 + b_0 = b_1*10 + b_0 + 20 - 20
= (b_1 + 2)*10 + b_0 - 20

Carrying this concept out for the rest of the b_i's we have.

b_0 = a_0 - 4*(a_3 + a_2 + a_1) - 20
b_1 = 6*a_2 + 2*a_1 + 2 - 140
= 6*a_2 + 2*a_1 - 138
b_2 = a_3 + 2*a_2 + 14 - 60
= a_3 + 2*a_2 - 46
b_3 = 4*a_3 + 6 - 70
= 4*a_3 - 64
b_4 = 0 + 7
= 7

And if you look at John's code closely, you will see this is
how he has expressed the b_j's.

```
+

Code:

• ```I reworked the second part of the code (normalizing B0..B4) for a PIC18.
Normalization is done by division and modulo operations which are done by mul.
The modified conversion runs in constant time and it is about 74 cycles faster than John Payson's normalization routine (average based on all conversions from 0..ffff).
It takes about 15-20 more lines of code. There are no additional requirements to the original code (no temporary vars or so). It works for pic18 family featuring the "mul" opcode. Thanks to all contributors and the smart explanation of the original code.

movlw   0x07    ;w  = 7
movwf   TenK    ;B4 = 7

; Now the number needs to be normal-
; ized, but this can all be done with simple byte
; arithmetic.

;****  use original code up to here  ****
;****  modified normalization start here  ****

comf    Ones, w  ;w = -(B0+1)                  ; range (w) 5..199
mullw   h'CD'
movf    PRODH, w
mullw   h'20'    ;PRODH = -(B0+1) / 10
incf    PRODH, w
subwf   Tens     ;B1 = B1 - (-(B0+1)/10 + 1)   ; range -18..-138 -(1..20) = -19..-158
mullw   d'10'
movf    PRODL, w
addwf   Ones     ;B0 = B0 + 10*(-(B0+1)/10 + 1) = B0 mod 10

comf    Tens, w  ;w = -(B1+1)                  ; range (w) 18..157
mullw   h'CD'
movf    PRODH, w
mullw   h'20'    ;PRODH = -(B1+1) / 10
incf    PRODH, w
subwf   Hund     ;B2 = B2 - (-(B1+1)/10 + 1)   ; range -1..-46 -(2..16) = -3..-62
mullw   d'10'
movf    PRODL, w
addwf   Tens     ;B1 = B1 + 10*(-(B1+1)/10 + 1) = B1 mod 10

comf    Hund, w  ;w = -(B2+1)                  ; range (w) 2..61
mullw   h'1A'    ;PRODH = -(B2+1) / 10
incf    PRODH, w
subwf   Thou     ;B3 = B3 - (-(B2+1)/10 + 1)   ; range -4..-64 -(1..7) = -5..-71
mullw   d'10'
movf    PRODL, w
addwf   Hund     ;B2 = B2 + 10*(-(B2+1)/10 + 1) = B2 mod 10

comf    Thou, w  ;w = -(B3+1)                  ; range (w) 4..70
mullw   h'CD'
movf    PRODH, w
mullw   h'20'    ;PRODH = -(B3+1) / 10
incf    PRODH, w
subwf   TenK     ;B4 = B4 - (-(B3+1)/10 + 1)
mullw   d'10'
movf    PRODL, w
addwf   Thou     ;B3 = B3 + 10*(-(B3+1)/10 + 1) = B3 mod 10

return

```
+

 file: /Techref/microchip/math/radix/b2bu-16b5d.htm, 14KB, , updated: 2020/4/3 11:04, local time: 2023/2/5 22:56, TOP NEW HELP FIND:  3.235.186.94:LOG IN

 ©2023 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! PIC Microcontoller Radix Math Method Binary to BCD unpacked 16 bit to 5 digit

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.

Attn spammers: All posts are reviewed before being made visible to anyone other than the poster.
 Did you find what you needed? "No. I'm looking for: " "No. Take me to the search page." "No. Take me to the top so I can drill down by catagory" "No. I'm willing to pay for help, please refer me to a qualified consultant" PICList 2023 contributors: o List host: MIT, Site host massmind.org, Top posters @none found - Page Editors: James Newton, David Cary, and YOU! * Roman Black of Black Robotics donates from sales of Linistep stepper controller kits. * Ashley Roll of Digital Nemesis donates from sales of RCL-1 RS232 to TTL converters. * Monthly Subscribers: Gregg Rew. on-going support is MOST appreciated! * Contributors: Richard Seriani, Sr.

.