24.Bit Binary to BCD conversion

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

24.Bit Binary to BCD conversion

11,238 Views
Truk
Contributor I
does anyone know an application note where a fast conversion routine is descibed?
regard,
Truk
Labels (1)
0 Kudos
Reply
13 Replies

3,185 Views
Nouchi
Senior Contributor II
Hello,

This is what you was looking for ?:

Code:
/* binary to 6 digits BCD */unsigned long bin2Bcd(unsigned long dataBin){unsigned long dataBcd=0;  dataBcd =  (dataBin / 100000) * 1048576;  dataBin %= 100000;  dataBcd |= (dataBin / 10000) * 65536;  dataBin %= 10000;  dataBcd |= (dataBin / 1000) * 4096;  dataBin %= 1000;  dataBcd |= (dataBin / 100) * 256;  dataBin %= 100;  dataBcd |= (dataBin / 10) * 16;  dataBcd |= dataBin % 10;  return(dataBcd);}
but maybe this isn't fast enough ?

Emmanuel,


0 Kudos
Reply

3,185 Views
Truk
Contributor I
Thank you Emmanuel,
but all the math takes mseconds on my 9S08AW16 with 8MHz-Bus. My RTC-loop (with RTI) is only 1ms.
I am searching for an iteration which takes less than 500usec.
regards,
Truk
 
0 Kudos
Reply

3,185 Views
bigmac
Specialist III
Hello Truk,
 
With a maximum of 4000 bus cycles to play with for a 24-bit conversion, I think you will probably need to use a very tight assembly routine.  Have you tried a Google search for potential mathematical procedures?
 
I have previously done a conversion for a 16-bit value by commencing with a decimal value of 10,000, and counting the number times this may be subtracted from the initial value until under-flow occurs, and then adding back once so the remainder is positive.  This is then repeated for values of 1,000, 100 and 10.
 
However, for a 24-bit conversion, you would firstly need to do a 24-bit compare to determine the MS digit (0 or 1), followed by 24-bit subtraction sequences for decimal values of 1,000,000 and 100,000.  I am not sure whether the conversion could be completed within your 4000 cycle limit using this method.
 
Regards,
Mac
 

Message Edited by bigmac on 2006-11-0112:54 AM

0 Kudos
Reply

3,185 Views
bigmac
Specialist III
Hello again Truk,
 
I did manage to find a reference to a serial conversion method, and was able to derive the following assembly code -
 
***************************************************************
* 24-BIT BINARY TO BCD CONVERSION
* On entry, 3-byte register VAL contains the value to be
* converted.
* On exit, 4-byte register RESULT contains the BCD value,
* packed 2-digits per byte.
***************************************************************
 
BCD_CONV:LDX    #24            ; Bit count
         CLR    RESULT+3
         CLR    RESULT+2
         CLR    RESULT+1
         CLR    RESULT
BC1:     LDA    RESULT+3
         JSR    BCD_ADJ        ; Adjust for BCD conversion
         STA    RESULT+3
         LDA    RESULT+2
         JSR    BCD_ADJ        ; Adjust for BCD conversion
         STA    RESULT+2
         LDA    RESULT+1
         JSR    BCD_ADJ        ; Adjust for BCD conversion
         STA    RESULT+1
         LDA    RESULT
         JSR    BCD_ADJ        ; Adjust for BCD conversion
         STA    RESULT
         LSL    VAL+2
         ROL    VAL+1
         ROL    VAL
         ROL    RESULT+3
         ROL    RESULT+2
         ROL    RESULT+1
         ROL    RESULT
         DBNZX  BC1            ; Loop for next bit
         RTS
 
***************************************************************
* ADJUST FOR BCD CONVERSION
* On entry, ACC = byte value to be adjusted
* On exit, ACC = adjusted value (2 BCD digits)
***************************************************************
 
BCD_ADJ: TSTA
         BEQ    BA1            ; Exit if zero
         PSHA
 
         ; Process lower nybble
         AND    #$0F
         CMP    #5
         BLO    *+4            ; Skip next if <5
         ADD    #3
         PSHA
 
         ; Process upper nybble
         LDA    2,SP           ; Initial byte value
         NSA
         AND    #$0F
         CMP    #5
         BLO    *+4            ; Skip next if <5
         ADD    #3
         NSA
         ORA    1,SP           ; Combine nybbles
         AIS    #2             ; Adjust stack pointer
BA1:     RTS
 
The number of bus cycles does depend, to some extent, on the value to be converted.  The maximum value seems to be approximately 4500 cycles (563 us) based on preliminary tests using full chip simulation, which is marginally greater than your maximum limit.
 
Regards,
Mac
 

Message Edited by bigmac on 2006-11-0107:12 AM

0 Kudos
Reply

3,185 Views
bigmac
Specialist III
Hello Truk,
 
I have now optimized the code of my previous posting to save some bus cycles.  The attached assembly code now seems to require slightly less than 4000 cycles maximum to execute, which would be closer to your target requirement.  Note that I have done all my tests using HC908 simulation, rather than HC9S08.  There will be some differences for the number of bus cycles.
 
Regards,
Mac
 
0 Kudos
Reply

3,185 Views
Truk
Contributor I
Hi MAC,
re my last answer. In the meantime I have tested the routine. I test before enter the routine if the value ist greater than 999'999 in binary.
The routine needs only 768 bus cycles for convert 7ffff to packed BCD (worst case).
The routine needs 134 Byte of code and can easy adapted to the needs of bit to convert.
With binay values until FFFFFF the table needs 4 columns of PBCD-values in the table, the shift is 4 times and ADD_BCD 1 adc longer.
regards
Truk
 
 
 
Code:
; Condition: The table UW_TBL_BinBCD musst be placed in a; 256-Byte-Page (no Change of MSB); INPUT: (H:X) = Pntr. MSB binary valueBIN20_BCD: clr TMP6   ;BCD-Reg =0 clr TMP5   ; clr TMP4   ; ; BIN20 -> BCD6-Convert.BCD6: lda ,x   ; sta TMP1   ; lda 1,x   ; sta TMP2   ; lda 2,x   ; sta TMP3   ; ldx #4   ;BCD61: rol TMP3   ;4-times shift rol TMP2   ;(20 instead of 24-Bits) rol TMP1   ; dbnzx BCD61   ; ldhx #(BinBCD_TOP-1) ; bra BCDL3BCDL1: aix #-3   ;BCDL2: cpx #LOW (BinBCD_Bot) ; bpl BCDL3   ; clc    ; rtsBCDL3: rol TMP3   ; rol TMP2   ; rol TMP1   ; bcc BCDL1ADD_BCD: lda ,x   ; add TMP6   ; daa    ; sta TMP6   ; decx    ; lda ,x   ; adc TMP5   ; daa    ; sta TMP5   ; decx    ; lda ,x   ; adc TMP4   ; daa    ; sta TMP4   ; decx    ; bcs BCDovf  ; bra BCDL2   ; BCDovf: sec rtsUW_TBL_BinBCD:BinBCD_Bot: equ * DC.B $00,$00,$01   ;Bit0 DC.B $00,$00,$02   ; DC.B $00,$00,$04   ; DC.B $00,$00,$08   ;Bit3 DC.B $00,$00,$16   ; DC.B $00,$00,$32   ; DC.B $00,$00,$64   ; DC.B $00,$01,$28   ;Bit7 DC.B $00,$02,$54   ; DC.B $00,$05,$12   ; DC.B $00,$10,$24   ; DC.B $00,$20,$48   ;Bit11  DC.B $00,$40,$96   ; DC.B $00,$81,$92   ; DC.B $01,$63,$84   ; DC.B $03,$27,$68   ;Bit15 DC.B $06,$55,$36   ; DC.B $13,$10,$72   ; DC.B $26,$21,$44   ; DC.B $52,$42,$88   ;Bit19BinBCD_TOP: equ *   ;

 
0 Kudos
Reply

3,185 Views
DustyStew
Contributor V
That is a fascinating algorithm, though I cannot claim to understand how it works!

I'm presently working on a conversion that uses DIV. The gist of it is to divide the 24 bit number by 100. This is quite fast, using DIV since the divisor is one byte, I reckon about 75 cycles. Then convert the remainder (which will be between 0 and 99) to BCD. Then store that BCD byte into the buffer. You need to address the output buffer in reverse, starting with the least significant byte.

Going from 0-99 to BCD can be done with a lookup table (100 bytes of FLASH for the table, I reckon 6 cycles to do the lookup), or by dividing by 10, then packing the quotient and remainder.

Here's a 0-99 binary-to-BCD conversion, which takes 21 cycles

;*** on entry, A= binary $00 to $63
ldhx #10
div
nsa
pshh
ora 1,SP
pulh
;*** on exit, A= BCD $00 to $99

It looks like this algorithm should do a binary-to-BCD conversion on a 24 bit number in between 500 and 600 cycles.
0 Kudos
Reply

3,185 Views
bigmac
Specialist III
Hello DS,
 
I have adapted your concept in the attached code, resulting in a code size of 61 bytes (no lookup table required).  For the HC08, the execution cycles would actually be 276 cycles, with slightly greater for HCS08.
 
Inlining the division sub-routines would reduce to 235 cycles, with increased code size to 74 bytes.
 
Regards,
Mac
 
0 Kudos
Reply

3,185 Views
DustyStew
Contributor V
Hey Mac

Nice work. I am still doing a double take...how did he do that?

One place where I can see I erred is that the X register is not changed by DIV. I was reloading it before each DIV.

From what I can see, you have nailed i. I can't see any way to optimize that, aside from inline code as you have mentioned.

Cheers
Dust
0 Kudos
Reply

3,185 Views
bigmac
Specialist III
Hello Truk,
 
I have noticed that your routine seems to give a minor error of -2 for very many of the values that I tested, and the correct result for other values.  For example, $7FFFF gave me a result of 524285, rather than the expected 524287.  I do not know the cause.
 
In two places I changed the ROL instruction to a LSL instruction,applicable to the LS byte position only, because the initial state of the carry flag appeared to be undefined, but this had no effect on the error.
 
For the HC908, the maximum cycles needed was at least 1187 for many of the values tested.  The value of $7FFF did not necessarily appear to be a worst case. 
 
Regards,
Mac
 
0 Kudos
Reply

3,185 Views
bigmac
Specialist III
Hello Truk,
 
I did find the source of the previously noted error - the table values for bit-8 should be $00,$02,$56 rather than $00,$02,$54.  So any binary value for which this bit was set would have shown the error.
 
I have now tested your routine when extended to 24 bits.  For the HC908, I get variation between 550 and 1654 cycles, depending on the number of 1's.  Comparing your method and my previous attempt, I think the main reason for the significantly lower number of cycles is the use of the DAA instruction.  With the shift (multiply by two) method that I used, I could not get this instruction to work properly - some results were OK, but many were incorrect.
 
Regards,
Mac
 
0 Kudos
Reply

3,185 Views
Truk
Contributor I
Hi Mac,
thank you for all your help again and for finding my typing error. In the short testing for principal function I had only tested 3 numbers and I had overlook the mistake.
Regards from the cloudy Switzerland,
Truk
0 Kudos
Reply

3,185 Views
Truk
Contributor I
Thank you Mac for all your help!!
I am testing today a method with lookup table also. It needs some flash memory, but should be very fast.
I have seen the idea in a teaching site on the net.
As soon as I have tested the routine I will put it on the tread.
so long!
Truk
 
0 Kudos
Reply