Searching \ for '3 Byte Binary to BCD Conversion' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/index.htm?key=byte+binary+bcd
Search entire site for: '3 Byte Binary to BCD Conversion'.

Truncated match.
PICList Thread
'3 Byte Binary to BCD Conversion'
1998\08\23@143940 by Ron Stone

picon face
Hi -- Does anyone have an assembler routine or algorithm for this?  I have one b
ased on subtraction of 10X
constants but I was wondering if there is something more efficient?  Microchip h
as one in their application
notes but it's only good for 2 bytes.  Also, what happened to the searchable arc
hives that used to be at
iversoft.com?  Please respond direct.  Thanks.

Ron

1998\08\23@155804 by Mike Keitz

picon face
On Sun, 23 Aug 1998 14:36:59 -0700 Ron Stone <spam_OUTastoneTakeThisOuTspamEROLS.COM> writes:
>Hi -- Does anyone have an assembler routine or algorithm for this?  I
>have one based on subtraction of 10X
>constants but I was wondering if there is something more efficient?
>Microchip has one in their application
>notes but it's only good for 2 bytes.

The "BCD multiply by 2" routine presented in the application note is good
for large numbers.  It is easy to expand it to more bytes.  Increase the
loop count to 24 (24 bits in 3 bytes), add another rotate so all 3 bytes
of the binary number are rotated, and add more BCD digits and calls to
adjbcd.

Another method is to repeatedly divide by 10, using the remainders as BCD
digits.  It takes longer but may save on code space if you already have a
suitable divison routine in the program for some other purpose.



_____________________________________________________________________
You don't need to buy Internet access to use free Internet e-mail.
Get completely free e-mail from Juno at http://www.juno.com
Or call Juno at (800) 654-JUNO [654-5866]

1998\08\24@101609 by Fehrenbach, Robert J

flavicon
face
Ron Stone wrote:

Hi -- Does anyone have an assembler routine or algorithm for this

Here is a four byte version.  If this doesn't fit your need, compare
this to the two byte version and you should be able to figure out how to
make the modifications for three bytes.

;Binary - BCD   32 bits  (Full Range)
   ;Input in buff_4|buff_3|buff_2|buff_1,
   ;
   ;Converts to packed bcd in temp_a, temp_b, temp_c, temp_d and temp_e
   ;with the MSD temp_a.

   ;Handles full range:  ff ff ff ff -> 4,294,967,295

   ;Also uses temp_f and count.

   ;2940 cycles including call and return.
   ;Bob Fehrenbach

bin2bcd:
  bcf     STATUS, C
  movlw   32
  movwf   count
  clrf    temp_a
  clrf    temp_b
  clrf    temp_c
  clrf    temp_d
  clrf    temp_e

bin2bcd_loop:
  rlf     buff_1, f
  rlf     buff_2, f
  rlf     buff_3, f
  rlf     buff_4, f
  rlf     temp_e, f
  rlf     temp_d, f
  rlf     temp_c, f
  rlf     temp_b, f
  rlf     temp_a, f

  decfsz  count, f
  goto    adj_dec
  goto    done

adj_dec:
  movlw   temp_e
  movwf   FSR
  call    adj_bcd

  movlw   temp_d
  movwf   FSR
  call    adj_bcd

  movlw   temp_c
  movwf   FSR
  call    adj_bcd

  movlw   temp_b
  movwf   FSR
  call    adj_bcd

  movlw   temp_a
  movwf   FSR
  call    adj_bcd

  goto    bin2bcd_loop

adj_bcd:
  movlw   h'3'            ;alternative adj_bcd from Mike Keitz
  addwf   INDF, w         ;Does not use temp_d
  movwf   temp_f          ; movlw   h'33'   ;Possible correction value.
  btfsc   temp_f, 3       ; addwf   INDF,f  ;Add to low and high
nybbles
  movwf   INDF            ; btfsc   INDF,3
  movlw   h'30'           ; andlw   h'f0'   ;Low result >7 . OK (take
the 3 out)
  addwf   INDF, w         ; btfsc   INDF,7
  movwf   temp_f          ; andlw   h'0f'   ;Hi > 7 OK.
  btfsc   temp_f, 7       ; subwf   INDF,f  ;any results <=7, subtract
back.
  movwf   INDF
  return

done:
  return

1998\08\24@115721 by Fehrenbach, Robert J

flavicon
face
Ron Stone wrote:
Hi-Does anyone have an assembler routine or algorithm for this

Here is a four byte version.  If this doesn't fit your need, compare
this to the two byte version and you should be able to figure out how to
make the modifications for three bytes.
;Binary - BCD   32 bits  (Full Range)
       ;Input in buff_4|buff_3|buff_2|buff_1,
   ;
       ;Converts to packed bcd in temp_a, temp_b, temp_c, temp_d and
temp_e ;with the MSD temp_a.
       ;Handles full range:  ff ff ff ff -> 4,294,967,295
       ;Also uses temp_f and count.
       ;2940 cycles including call and return.
       ;Bob Fehrenbach

bin2bcd:
  bcf     STATUS, C
  movlw   32
  movwf   count
  clrf    temp_a
  clrf    temp_b
  clrf    temp_c
  clrf    temp_d
  clrf    temp_e

bin2bcd_loop:
  rlf     buff_1, f
  rlf     buff_2, f
  rlf     buff_3, f
  rlf     buff_4, f
  rlf     temp_e, f
  rlf     temp_d, f
  rlf     temp_c, f
  rlf     temp_b, f
  rlf     temp_a, f

  decfsz  count, f
  goto    adj_dec
  goto    done

adj_dec:
  movlw   temp_e
  movwf   FSR
  call    adj_bcd

  movlw   temp_d
  movwf   FSR
  call    adj_bcd

  movlw   temp_c
  movwf   FSR
  call    adj_bcd

  movlw   temp_b
  movwf   FSR
  call    adj_bcd

  movlw   temp_a
  movwf   FSR
  call    adj_bcd

  goto    bin2bcd_loop

adj_bcd:
  movlw   h'3'            ;alternative adj_bcd from Mike Keitz
  addwf   INDF, w         ;Does not use temp_d
  movwf   temp_f          ; movlw   h'33'   ;Possible correction value.
  btfsc   temp_f, 3       ; addwf   INDF,f  ;Add to low and high
nybbles
  movwf   INDF            ; btfsc   INDF,3
  movlw   h'30'           ; andlw   h'f0'   ;Low result >7 . OK (take
the 3 out)
  addwf   INDF, w         ; btfsc   INDF,7
  movwf   temp_f          ; andlw   h'0f'   ;Hi > 7 OK.
  btfsc   temp_f, 7       ; subwf   INDF,f  ;any results <=7, subtract
back.
       movwf   INDF
       return

done:
       return

1998\08\24@124643 by Dmitry Kiryashov

flavicon
face
Bob Fehrenbach wrote:

;.........
adj_dec:
   movlw   temp_e
   call    adj_bcd

   movlw   temp_d
   call    adj_bcd

   movlw   temp_c
   call    adj_bcd

   movlw   temp_b
   call    adj_bcd

   movlw   temp_a
   call    adj_bcd
;.........

adj_bcd:
   movwf   FSR

;    movlw   h'03'           ;alternative adj_bcd from Mike Keitz
;    addwf   INDF, w         ;Does not use temp_d
;    movwf   temp_f          ; movlw   h'33'   ;Possible correction
value.
;    btfsc   temp_f, 3       ; addwf   INDF,f  ;Add to low and high
nybbles
;    movwf   INDF            ; btfsc   INDF,3

   movlw   h'03'
   addwf   INDF, f
   btfss   INDF, 3
   subwf   INDF, f

Is it not the same ?


;    movlw   h'30'           ; andlw   h'f0'   ;Low result >7 . OK (take
the 3 out)
;    addwf   INDF, w         ; btfsc   INDF,7
;    movwf   temp_f          ; andlw   h'0f'   ;Hi > 7 OK.
;    btfsc   temp_f, 7       ; subwf   INDF,f  ;any results <=7,
subtract
;    movwf   INDF
;
;    return

The same suggestion.

This will save 5*2*32. = 320 clocks and 4+2=6 words of program memory.
And one data cell too ;-)

WBR Dmitry.

1998\08\24@131121 by lilel

flavicon
face
> Ron Stone wrote:
>
> Hi -- Does anyone have an assembler routine or algorithm for this


Another Post replied that you could repeatedly divide by 10 (actually
POWERS of 10) and do a BIN to BCD conversion, if you needed to have a
divide routine around anyway.  I do, so I started working on this.

I need a 2 byte (actually, the data in this number will be less than
999 decimal)  number converted to 3 byte BCD, not packed BCD.
Later, I will need to scale this number (probably by scaling the 2
byte BIN, it's easier)  because it represents a Fahrenheit
temperature and I need to read out in Centigrade sometimes. So I'll
probably need a divide routine.

I started messing around with Divide routines today.
There is a DBL_DIVS routine in Microchip AN526.  It has a note in the
header that the Numerator must be greater than the Denominator.  I
checked this out, and it actually seems to give errors when the
Numerator is EQUAL to the denominator as well (I didn't check all
cases...)

Yuck:

  'd103 divided by 'd100 gives Zero remainder 3 not 1
remainder 3

Double Yuck:

'd100 divided by 'd100 gives zero remainder 100  not 1 remainder
zero.

Anybody got a better routine?  I'm looking for a code-efficient (not
straight-line) double precision divide routine that will handle all
cases.


-- Lawrence Lile

    "The ideal design has zero parts"  -
           (attributed to Harold Hallikainen)

Download AutoCad blocks for electrical drafting at:
http://home1.gte.net/llile/index.htm

1998\08\24@135000 by Scott Dattalo

face
flavicon
face
Lawrence Lile wrote:

> Anybody got a better routine?  I'm looking for a code-efficient (not
> straight-line) double precision divide routine that will handle all
> cases.

Sigh... I guess it's time to mention Payson's 'Wonderful Binary to BCD
routine' again. Shall I post it again? On second thought, let me throw
it out on a web page.

(10 minutes later) there:

http://www.interstice.com/~sdattalo/technical/software/pic/bcd.txt


Scott

1998\08\24@150151 by Mike Keitz

picon face
On Mon, 24 Aug 1998 20:42:40 +0400 Dmitry Kiryashov <.....zewsKILLspamspam@spam@AHA.RU> writes:
>Bob Fehrenbach wrote:
>

>;    movlw   h'03'           ;alternative adj_bcd from Mike Keitz

Thanks for the credit, but the code has gotten so unformatted that I
can't follow it too well.  Let me summarize, since this particular
routine comes up every few months.

We are looking at the 'adjbcd' process, which is part of the "BCD
multiply by 2" binary to BCD routine.  What it does is prepare a packed
BCD number so that shifting it left will multiply it by 2.  This should
be done by adding 3 to each digit unless the digit is less than 5 (in
which case adding 3 will leave the result less than 8):

Digit   Adjusted digit  Shifted adjusted digit
0       0               0
1       1               2
2       2               4
3       3               6
4       4               8
5       8               0 carry 1
6       9               2 carry 1
7       A               4 carry 1
8       B               6 carry 1
9       C               8 carry 1

Original Microchip (not optimized):

       movlw   h'03'           ;Adjust the low digit by adding
3
       addwf   INDF,w
       movwf   tmp_f           ;Store result here for bit
test.
       btfsc   tmp_f,3         ;If result < 8, don't change.
       movwf   INDF            ;Store the optimized result.

       movlw   h'30'           ;Same process on high digit.
       addwf   INDF,w
       movwf   tmp_f
       btfsc   tmp_f,7
       movwf   INDF

Dimitry suggests:
       movlw   h'03'           ;Adjust the low digit.
       addwf   INDF,f
       btfss   INDF,3          ;If result >= 8, keep.
       subwf   INDF,f          ;Otherwise, de-adjust back.
       movlw   h'30'           ;Same for high digit.
       addwf   INDF,f
       btfss   INDF,7
       subwf   INDF,f

My optimized routine:
       movlw   h'33'
       addwf   INDF,f          ;Adjust both digits.
       btfsc   INDF,3          ;Low digit <8, adjust back.
       andlw   h'f0'           ;Keep the low digit (could use
movlw h'30')
       btfsc   INDF,7          ;Hi digit <8, adjust back.
       andlw   h'0f'           ;Keep the high digit (by
subtracting 0).
       subwf   INDF,f          ;Adjust digit(s) back if still
3 in W.

So, pick your poison.  They all work.

Most everyone picked up the optimization of putting the store index value
to FSR *inside* the adjbcd routine.  For only a few (4 or 6) BCD digits,
consider in-lining the adjbcd routine and using direct addressing.  For a
large number of BCD digits, write a loop to increment FSR and do adjbcd
repeatedly.  If someone can come up with a way to combine the shifting
and adjusting (keeping  a proper carry of course), that could further
save space on large numbers.

_____________________________________________________________________
You don't need to buy Internet access to use free Internet e-mail.
Get completely free e-mail from Juno at http://www.juno.com
Or call Juno at (800) 654-JUNO [654-5866]

1998\08\24@150159 by Mike Keitz

picon face
On Mon, 24 Aug 1998 12:08:31 +0000 Lawrence Lile <lilelspamKILLspamtoastmaster.com>
writes:
>> Ron Stone wrote:
>>
>> Hi -- Does anyone have an assembler routine or algorithm for this
>
>
>Another Post replied that you could repeatedly divide by 10 (actually
>POWERS of 10) and do a BIN to BCD conversion, if you needed to have a
>divide routine around anyway.  I do, so I started working on this.

No, you divide by 10 every time.  The remainders are the BCD digits, but
you get them in reverse order.

For example, consider 936.

936 div 10 = 93 remainder 6
93 div 10 =   9 remainder 3
9 div 10  =   0 remainder 9

If you want a variable length result, you can stop when the divide result
is zero.  Or do the process a fixed number of times, and the result will
have leading zero digits since 0 div 10 = 0 remainder 0.

Put the remainders in order and you have 9 3 6.  If you're displaying on
an HD44780 LCD screen, you can set it to move the cursor from right to
left, and write the digits as they are computed.  Otherwise you'd
probably need to save them in RAM for output in the usual left to right
order.

Since the division is always be 10 a simple long division routine can be
implemented with just a single byte subtract and test.

_____________________________________________________________________
You don't need to buy Internet access to use free Internet e-mail.
Get completely free e-mail from Juno at http://www.juno.com
Or call Juno at (800) 654-JUNO [654-5866]

1998\08\24@232016 by Dmitry Kiryashov

flavicon
face
Mike Keitz wrote:

> My optimized routine:
>         movlw   h'33'
>         addwf   INDF,f          ;Adjust both digits.
>         btfsc   INDF,3          ;Low digit <8, adjust back.
>         andlw   h'f0'           ;Keep the low digit (could use movlw h'30')
>         btfsc   INDF,7          ;Hi digit <8, adjust back.
>         andlw   h'0f'           ;Keep the high digit (by subtracting 0).
>         subwf   INDF,f          ;Adjust digit(s) back if still 3 in W.

Excellent solution. ;-)

WBR Dmitry.

1998\08\25@032559 by Dmitry Kiryashov

flavicon
face
Hello Mike Keitz.

You gave me another idea how to optimize code.
Just idea not been tested.

;       buff_1234 values will be corrupted.
;       9 + (12 + 6 + 11 + 11)*31 + 9 + 4 = 1262 clc
;       48 words of program memory

bin2bcd:
       clrf    count
       bsf     count,5         ;32.
       clrf    temp_a
       clrf    temp_b
       clrf    temp_c
       clrf    temp_d
       clrf    temp_e

       goto    bin2bcd_loop

adj_dec:
       movlw   0x33
       addwf   temp_e,f
       addwf   temp_d,f
       addwf   temp_c,f
       addwf   temp_b,f
       addwf   temp_a,f

       movlw   0x03
       btfss   temp_e,3
       subwf   temp_e,f
       btfss   temp_d,3
       subwf   temp_d,f
       btfss   temp_c,3
       subwf   temp_c,f
       btfss   temp_b,3
       subwf   temp_b,f
       btfss   temp_a,3
       subwf   temp_a,f

       movlw   0x30
       btfss   temp_e,7
       subwf   temp_e,f
       btfss   temp_d,7
       subwf   temp_d,f
       btfss   temp_c,7
       subwf   temp_c,f
       btfss   temp_b,7
       subwf   temp_b,f
       btfss   temp_a,7
       subwf   temp_a,f

bin2bcd_loop:
       rlf     buff_1,f
       rlf     buff_2,f
       rlf     buff_3,f
       rlf     buff_4,f
       rlf     temp_e,f
       rlf     temp_d,f
       rlf     temp_c,f
       rlf     temp_b,f
       rlf     temp_a,f

       decfsz  count, f
       goto    adj_dec

       return


;       3 bytes variant will require:
;       8 + (10 + 5 + 9 + 9)*23 + 7 + 4 = 778 clc
;       40 words of program memory


WBR Dmitry.

1998\08\25@104619 by Mike Keitz

picon face
On Tue, 25 Aug 1998 11:23:07 +0400 Dmitry Kiryashov <.....zewsKILLspamspam.....AHA.RU> writes:

>You gave me another idea how to optimize code.
>Just idea not been tested.

It looks like it will work.  Probably about the best it can be done in
terms of speed (other than unrolling the loop entirely).

>;       buff_1234 values will be corrupted.

If you'd like the binary value to remain the same after conversion, make
it shift in a circle like this:

       rlf     buff_4,w        ;<-- Add this instr, picks up high
bit.
       rlf     buff_1,f
       rlf     buff_2,f
       rlf     buff_3,f
       rlf     buff_4,f
       rlf     temp_e,f
 etc.

After 32 loops, the value in buff will have shifted all the way around,
so it would be the same as at the start.  The cost is one more
instruction which is executed 32 times.


>        clrf    count
>        bsf     count,5         ;32.

Cute, but movlw/movwf is the same performance and a lot easier to
understand.


_____________________________________________________________________
You don't need to buy Internet access to use free Internet e-mail.
Get completely free e-mail from Juno at http://www.juno.com
Or call Juno at (800) 654-JUNO [654-5866]

More... (looser matching)
- Last day of these posts
- In 1998 , 1999 only
- Today
- New search...