Searching \ for 'Binary to BCD' 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=binary+bcd
Search entire site for: 'Binary to BCD'.

Truncated match.
PICList Thread
'Binary to BCD'
1997\03\03@211117 by John Dammeyer

flavicon
face
In comp.arch.embedded a discussion went on, for a while, about the merits of
assembler verses C.
Don Yuniskis posted this little gem as an example of an efficient 16 bit
Binary to
4 digit Binary Coded Decimal routine.

Don wrote:
-->>
Here's one version of a binary-decimal conversion routine.
Call with r.hl having binary value; returns 4 digit packed BCD
in r.de -- I neglected the fifth digit  :-(  It can be
rewritten to preserve that extra digit.  To produce ASCII,
obviously you can append a code fragment to add '0' to each
unpacked digit.

BinDec: LD B,16         ;7
       LD DE,0         ;10

Loop:   ADD HL,HL       ;11

       LD A,E          ;4
       ADC A,A         ;4
       DAA             ;4
       LD E,A          ;4

       LD A,D          ;4
       ADC A,A         ;4
       DAA             ;4
       LD D,A          ;4

       DJNZ Loop       ;13/8

       RET             ;10
<<--

I wrote:
Of course it only works if the processor has a
DAA instruction.  (Decimal Adjust Accumulator).  I mentioned at the time
that both the PIC
and the 68HC05 don't have a DAA instruction and so his routine wouldn't
work.  To date I
have been using the slower 16 bit to 5 digit algo. that uses the divide and
makes use of
the location that holds the remainder after a divide.   It uses three bytes
of RAM and
calls the divide routine.  Not a big deal if 16 bit divide is used elsewhere
and has to
be part of the application anyway.

-->>
unsigned long
ubcd(void) {
 unsigned long ulResult;  // Working result and arg.
 unsigned int i;        // loop counter

   ulResult = 0;

   for (i=0; i<16; i+=4) {
       ulArg = ulArg / 10;           // get rid of LS Digit
       long_q <<= i;        // put remainder in correct position.
       ulResult |= long_q;    // add to result
   }

   return ulResult;           // packed BCD.
};
<<--


However the penalty in using the divide is fairly high as it shifts through
the 16 bit
quotient 16 times.  Don's routine looked attractive as it also walks through
the 16 bit
binary value but only once, not five times.

So I have cloned the DAA instruction
and rewritten his routine to also generate 5 digits instead of 4.  It's
written in C and
before anyone has a heart failure be aware that I wrote it in Assembler
first.  Then
re-wrote it in C in a way that simulated as much of my assembler as
possible.  This makes
it easier to shove it around in the source file without worrying about page
bits etc.
Assembler would be a few bytes smaller where the C compiler generates
redundant code.

The goto is there to allow this routine to be replicated three times instead
of being
used as a subroutine.  Why?  Because the 16C57 only has a two level stack.

BTW,  Dag Bakken  should note that I do indeed take advantage of the type of
code
generated by the compiler when I:

"argument + 0x66;  // set C,DC flags with trial add."

I still believe that a compiler should not even generate code for this but
the MPC does
and I take advantage of it.  It could 'break' in the future though with a
new compiler release which is why I really don't like doing it. <grin>


//  Decimal Adjust Accumulator simulation
//  Argument is the value to decimal adjust.
//  Must be called immediately after addition in order to not lose
//  status of CARRY and DIGIT CARRY bits in status register.
// ie:  a hidden argument is the status register.

unsigned char
DAA(unsigned char argument) {
   Flags.DAA_FLAG = 0;      // Flag for doing code twice.
   Flags.Carry = STATUS.C;  // Mustn't clear if already set.

   while (1) {              // this could be a label that we goto.
       DAA_VALUE = 0;   // Clear DAA adder.

       // Now custruct DAA adder
       if (STATUS.DC) {     // if a Half carry occured then make BCD
           DAA_VALUE = 6;   // by adding 6 lower digit.
       };
       if (STATUS.C) {         // If a full carry occured make BCD digit by
           DAA_VALUE |= 0x60;  // adding 6 to upper digit.
       };

       // If digits overflowed from addition
       // we now make them BCD again.
       argument += DAA_VALUE;  // DAA_VALUE can be 0x00, 0x06, 0x66

       if (Flags.DAA_FLAG)  // We do above code twice.
           goto DONE_DAA;   // This is how we get out.
       Flags.DAA_FLAG = 1;

       // Secondly test if BCD digits are in 'A'..'F' range byt a trial add.
       argument + 0x66;    // set flags with trial add.
   };
DONE_DAA:
   // Carry might be already be 1 so we cannot just assign passed parameter
CARRY flag
   // which might have been zero.
   if (Flags.Carry) STATUS.C = 1;
   return(argument);
};

unsigned char de0,de1,de2;
int counter;
unsigned long hl;

// Binary to Decimal Conversion routine  16bit to 5 digit.
// Parameter is passed in global var. 'hl' and is cleared when complete.
// result is in 'de0,de1,de2' where 'de0' is least sig digits.
// Uses 8 bit counter to walk through binary number.
void
BinDec() {
   de0 = 0;       // Clear result accumulator.
   de1 = 0;
   de2 = 0;
   counter = 16;  // All 16 bits of argument.
   do {
       hl <<= 1;  // Put MSb into Carry.

       // Now if we had a ADC instruction this part wouldn't be needed.
       WREG = 0;
       if (STATUS.C)
           WREG = 1;
       // Simulate the Add with carry operation.
       // At first glance it appears like a RLF would do the same thing but
       // we need the STATUS.DC set if there is a digit overflow.
       // 68HC05 does have ADC instruction.
       de0 += de0 + WREG;
       // After addition do a decimal adjust.
       de0 = DAA(de0);

       // if there was an overflow from the previous addition add it into
       // the next BCD digits.
       WREG = 0;
       if (STATUS.C)
           WREG = 1;
       de1 += de1 + WREG;
       de1 = DAA(de1);

       WREG = 0;
       if (STATUS.C)
           WREG = 1;
       de2 += de2 + WREG;
       de2 = DAA(de2);

   } while (--counter);
};

Finally I do welcome all input.  Especially if someone can improve on the
speed/space of this one.

Cheers,

John.
Pioneers are the ones, face down in the mud,
with arrows in their backs.
Automation Artisans Inc.      Ph. 1-250-544-4950
PO Box 20002                  Fax 1-250-544-4954
Sidney, BC CANADA V8L 5C9

1997\03\04@004247 by Steve Hardy

flavicon
face
{Quote hidden}

Hmmm... suspiciously like Z80 code, even down to the clock cycle
counts, no?


> Finally I do welcome all input.  Especially if someone can improve on the
> speed/space of this one.


DAA is a bit tekno for this task.  My philosophy when it comes to
binary to decimal decoding is that decimal is almost always used
by humans (or printers) and hence speed is not an overriding concern.
I would go for the most compact code.  Successive subtraction of
powers of ten would be my first choice.  Actual division is
certainly unnecessary.  Converting an unsigned 16-bit number to
5-digit decimal requires a maximum of 27 2-byte subtractions,
20 1-byte subtractions and 5 additions.

Yes of course there are much smarter ways, but this is easy to
understand and can be implemented fairly easily (even on a PIC).

Now I realise there are always exceptions, but if you find yourself
requiring more than a few decimal conversions per second, then rethink
the application because no human can read that fast.

Regards,
SJH
Canberra, Australia

1997\03\04@030036 by John Dammeyer

flavicon
face
At 04:41 PM 04/03/1997 EST, you wrote:
{Quote hidden}

Yup!
{Quote hidden}

Please do post it.  ie: Put your opcodes down as evidence.

>
>Yes of course there are much smarter ways, but this is easy to
>understand and can be implemented fairly easily (even on a PIC).
>
>Now I realise there are always exceptions, but if you find yourself
>requiring more than a few decimal conversions per second, then rethink
>the application because no human can read that fast.

Well,  the 16C57 doesn't have interrupts.  I need to service I/O  quite
frequently.  I can't afford to spend a large amount of time in a subroutine
- including divide.  The above algo.  lends itself nicely to an iterative
approach.

ie: Using a flag, enter the routine, shift and calculate, leave the routine.
Do this 16 times and then set another flag that a different routine can use
as a conversion complete signal.  If tiem wasn't an object here or I was
using a PIC/8HC05 with interrupt support for time critical I'd stay with the
divide algo.  Short, simple, easy to follow as long as the 16 bit divide was
needed elsewhere.

Reagrds,

John


Pioneers are the ones, face down in the mud,
with arrows in their backs.
Automation Artisans Inc.      Ph. 1-250-544-4950
PO Box 20002                  Fax 1-250-544-4954
Sidney, BC CANADA V8L 5C9

1997\03\04@095515 by Andy Kunz

flavicon
face
>
>BinDec: LD B,16         ;7
>        LD DE,0         ;10
>
>Loop:   ADD HL,HL       ;11
>
>        LD A,E          ;4
>        ADC A,A         ;4
>        DAA             ;4
>        LD E,A          ;4
>
>        LD A,D          ;4
>        ADC A,A         ;4
>        DAA             ;4
>        LD D,A          ;4
>
>        DJNZ Loop       ;13/8
>
>        RET             ;10

Ah, Z-80, my first, true love.  And in Zilog mnemonics, no less!

Andy
==================================================================
Andy Kunz - Montana Design - 409 S 6th St - Phillipsburg, NJ 08865
         Hardware & Software for Industry & R/C Hobbies
       "Go fast, turn right, and keep the wet side down!"
==================================================================

1997\03\04@191430 by Steve Hardy

flavicon
face
> From: John Dammeyer <johndspamKILLspamISLANDNET.COM>
> >[cut]
> >DAA is a bit tekno for this task.  My philosophy when it comes to
> >binary to decimal decoding is that decimal is almost always used
> >by humans (or printers) and hence speed is not an overriding concern.
> >I would go for the most compact code.  Successive subtraction of
> >powers of ten would be my first choice.  Actual division is
> >certainly unnecessary.  Converting an unsigned 16-bit number to
> >5-digit decimal requires a maximum of 27 2-byte subtractions,
> >20 1-byte subtractions and 5 additions.
>
> Please do post it.  ie: Put your opcodes down as evidence.

So you want me to put my code where my mouth is?  Well I've never
needed to actually do this (let alone on a '57, since I've always
used the '74 and '84).  Time does not permit me to give a real
implementation so you will have to be satisfied with pseudo C-code.
This code would translate in a fairly straightforward way into
16C57 code.  Obviously, some of the code could be 'commoned'.
Contrary to my previous post this will take a worst case, for
conversion of the number 5999x, of 26 2-byte subs, 10 1-byte subs,
3 2-byte adds and 2 1-byte adds -- not counting the digit increments.
The subtractions could be replaced by additions of -ve numbers if
that makes it easier.

The conversion procedure is broken up into very small bites so
that your non-interrupt-capable processor will have only a small
latency between checking for I/O etc.



enum state { start, finish, sub10k, sub1k, sub100, sub10 }
int binary
int divisor
char digit[5]

void bin2dec()
{
 switch (state)
 {
   case start:
     state = sub10k
     digit[0] = digit[1] = ... = digit[4] = '0'
     divisor = 10000
     return
   case sub10k:
     binary -= divisor
     if (binary < 0) [i.e. MSB of binary changed from 0 to 1]
     {
       binary += divisor
       state = sub1k
       divisor = 1000
     }
     else
       digit[0]++
     return
   case sub1k:
     binary -= divisor
     if (binary < 0)
     {
       binary += divisor
       state = sub100
       divisor = 100
     }
     else
       digit[1]++
     return
   case sub100:
     binary -= divisor
     if (binary < 0)
     {
       binary += divisor
       state = sub10
       divisor = 10
     }
     else
       digit[2]++
     return
   case sub10:
     binary -= divisor [S.B. - single byte op]
     if (binary < 0)
     {
       binary += divisor [S.B.]
       state = finish
       digit[4] += binary [S.B.]
     }
     else
       digit[3]++
     return
 }
}


main()
{
 ...
 binary = [binary value to decode]
 state = start
 while (state != finish)
 {
   bin2dec()
   [do something else e.g. service I/O]
 }

 print("decimal = %c%c%c%c%c", digit[0], digit[1], ..., digit[4])

}


Regards,
SJH
Canberra, Australia

1997\03\05@040521 by John Dammeyer

flavicon
face
At 11:12 AM 05/03/1997 EST, you wrote:
>> From: John Dammeyer <.....johndKILLspamspam.....ISLANDNET.COM>
<snip>

>The conversion procedure is broken up into very small bites so
>that your non-interrupt-capable processor will have only a small
>latency between checking for I/O etc.

I'll take a crack at it but I won't use the switch.  The extra code penalty
without the ability to use a jump table on a PIC is much too high.  This is
not meant as a criticism as I realize you whipped this out on the fly.  The
cost of walking down to 'case sub10:' nine times in a switch statement is
expensive.  I am not sure that this is actually any faster (or smaller) than
the DAA method. And yes,  negative constants are usually better.

I'll post the result when I'm done and like your example I'll make it small
bite capable.  BTW,  to be fair you need to pack the result;   mine was.
8-).  Or else I need to unpack mine 8-(.

Cheers,

John
Pioneers are the ones, face down in the mud,
with arrows in their backs.
Automation Artisans Inc.      Ph. 1-250-544-4950
PO Box 20002                  Fax 1-250-544-4954
Sidney, BC CANADA V8L 5C9

1997\03\05@052040 by Andrew Warren

face
flavicon
face
John Dammeyer <EraseMEPICLISTspam_OUTspamTakeThisOuTMITVMA.MIT.EDU> wrote:

> The extra code penalty without the ability to use a jump table on a
> PIC is much too high.

   John:

   Jump tables are trivially easy (and fast) on the PIC:

       MOVF    STATE,W         ;switch (state)
       ADDWF   PCL             ;{
                               ;
       GOTO    CASE0           ;    case 0: ....
       GOTO    CASE1           ;    case 1: ....
       GOTO    CASE2           ;    case 2: ....
       etc...                  ;}

   On some parts, you need to do a little fiddling with the PCLATH
   register, but I'm sure you get the idea.

> I'll post the result when I'm done and like your example I'll make
> it small bite capable.  BTW,  to be fair you need to pack the
> result;   mine was. 8-).  Or else I need to unpack mine 8-(.

   If you can deal with an unpacked result, just use the excellent
   routine that John Payson posted here a few months ago.  It's
   extremely fast, easily broken-up into small pieces, and it takes
   very little code space.

   Since John has inexplicably decided not to end this binary-to-BCD
   thread by reposting it, I will (repost it, that is... Feel free
   to continue the thread):

-------------------------------------------------------------------

;
; Binary-to-BCD.  Written by John Payson.
;
; Enter with 16-bit binary number in NumH:NumL.
; Exits with BCD equivalent in TenK:Thou:Hund:Tens:Ones.
;

       org     $0010   ;Start of user files for 16c84

NumH:   ds      1
NumL:   ds      1
TenK:   ds      1
Thou:   ds      1
Hund:   ds      1
Tens:   ds      1
Ones:   ds      1

Convert:                        ; Takes number in NumH:NumL
                               ; Returns decimal in
                               ; TenK:Thou:Hund:Tens:Ones
       swapf   NumH,w
       andlw   $0F             ;*** PERSONALLY, I'D REPLACE THESE 2
       addlw   $F0             ;*** LINES WITH "IORLW 11110000B" -AW
       movwf   Thou
       addwf   Thou,f
       addlw   $E2
       movwf   Hund
       addlw   $32
       movwf   Ones

       movf    NumH,w
       andlw   $0F
       addwf   Hund,f
       addwf   Hund,f
       addwf   Ones,f
       addlw   $E9
       movwf   Tens
       addwf   Tens,f
       addwf   Tens,f

       swapf   NumL,w
       andlw   $0F
       addwf   Tens,f
       addwf   Ones,f

       rlf     Tens,f
       rlf     Ones,f
       comf    Ones,f
       rlf     Ones,f

       movf    NumL,w
       andlw   $0F
       addwf   Ones,f
       rlf     Thou,f

       movlw   $07
       movwf   TenK

                       ; 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                             ; Ten
Lb1:
       addwf   Ones,f
       decf    Tens,f
       btfss   3,0
        goto   Lb1
Lb2:
       addwf   Tens,f
       decf    Hund,f
       btfss   3,0
        goto   Lb2
Lb3:
       addwf   Hund,f
       decf    Thou,f
       btfss   3,0
        goto   Lb3
Lb4:
       addwf   Thou,f
       decf    TenK,f
       btfss   3,0
        goto   Lb4

       retlw   0
-------------------------------------------------------------------

   -Andy

=== Andrew Warren - fastfwdspamspam_OUTix.netcom.com
=== Fast Forward Engineering - Vista, California
===
=== Custodian of the PICLIST Fund -- For more info, see:
=== www.geocities.com/SiliconValley/2499/fund.html

1997\03\05@174655 by John Dammeyer

flavicon
face
At 02:27 AM 05/03/1997 -0800, you wrote:
>John Dammeyer <@spam@PICLISTKILLspamspamMITVMA.MIT.EDU> wrote:
>
>> The extra code penalty without the ability to use a jump table on a
>> PIC is much too high.
>
>    John:
>
>    Jump tables are trivially easy (and fast) on the PIC:
>
>        MOVF    STATE,W         ;switch (state)
>        ADDWF   PCL             ;{
>                                ;
>        GOTO    CASE0           ;    case 0: ....
>        GOTO    CASE1           ;    case 1: ....
>        GOTO    CASE2           ;    case 2: ....
>        etc...                  ;}
>
>    On some parts, you need to do a little fiddling with the PCLATH
>    register, but I'm sure you get the idea.

True.  In assembler this is a snap as long as it all fits in the one page.
If it doesn't then
there can be a second level of indirect jumps.  In either case a combination
of assembler and C would make Case Statements more efficient.

eg:
   Jump tables are trivially easy (and fast) on the PIC when
   jump tables are placed in the same page.

       MOVF    STATE,W         ;switch (state)
       ADDWF   PCL             ;{
                               ;
       GOTO    _CASE0           ;    case 0: ....
       GOTO    _CASE1           ;    case 1: ....
       GOTO    _CASE2           ;    case 2: ....

_CASE0:
       BSF    STATUS,PA0
       BCF    STATUS,PA1
       GOTO   CASE0
_CASE1:
etc...


There is just more administration needed to keep all this organized.  It
would be nice it the C compiler gave me the option to have this type of case
statement.
{Quote hidden}

As promised.  Here is the C version of Steve Hardy's binary to BCD routine.
I've modified it to handle 16 bit unsigned integers.  It can be called from
within the mainline polling loop so that the processor isn't tied down to
doing conversions.


What is interesting is the speed and code size is much smaller than the DAA
simulation; kudos to Steve for the idea.  I've also taken advantage of
having access to the Carry flag to let it handle 16 bit unsigned 16 bit
ints.  With the exception of a few places where the compiler adds redundent
PA0,PA1 bit setting for GOTO support the code generated isn't much slower or
bigger than what would be generated by directly doing this in assembler.
The most interesting part is the time taken to do each little bit - about 43
clocks on average.  At 20MHz this is only 8.2 uSec and may be the best
technique to avoid impacting the polling of other I/O.

Size of DAA simulation method       94 instructions
Execution speed for 59,999 (0xEA5F)  -> 2798 clocks

Size of DECIMAL SUBTRACTION method  86 instructions
Execution speed                      -> 1575 clocks
Average execution time for each call ->   43 clocks

Size of BCD using 16 bit division   57 instructions
Execution speed                      -> 2543 clocks.

I have not included the 16/16 divide as I assume it would be used elsewhere
in the application.

Conclusions so far...

If you need 16 bit divide anyway and speed isn't a problem use the inelegant
divide technique; it's easy to understand and document and IMHO a well
documented and easy to understand program is part of a correctly functioning
program.

If you need speed and space ... use Steve Hardy's successive subtraction
method.  It could be made faster by doing doing all the conversion in one
time rather than in bits.

As for John Payson's method.  Haven't gotton to it yet.  But the assembler
version obviously takes 50 instructions.  How much time is spent in the
loops?  Don't know yet.  It will probably be the fastest and the smallest;
understanding how it works may be more difficult.


Now I must stop having fun get back to real work.  8-)

Cheers

John.


-->>
// Default for compiler is set to 8 bit ints and 16 bit longs.
bits bcdFlags;
#define COMPLETE bcdFlags.0

int digit[5];
unsigned long binary;
unsigned long divisor;
int digitNumber;

unsigned int
bin2dec () {
   if (COMPLETE) {
       digit[0] = 0;  // LSDigit
       digit[1] = 0;
       digit[2] = 0;
       digit[3] = 0;
       digit[4] = 0;  // MSdigit
       COMPLETE = 0;
       digitNumber = 4;
       divisor = 10000;
   }
   else {
       binary -= divisor;
       if (!STATUS.C) {
           binary +=divisor;
           if (--digitNumber == 0) {
               COMPLETE = 1;
               digit[digitNumber] = binary;
           }
           else {
               if (digitNumber == 3)
                   divisor = 1000;
               else if (digitNumber == 2)
                   divisor = 100;
               else
                   divisor = 10;
           }
       }
       else {
           digit[digitNumber]++;
       };
   };
   return COMPLETE;
}

main() {
   COMPLETE = 1;   // Signal that bin2dec() may convert a new value.
   binary = 0;     // force to known value.
   while (1) {

       if (bin2dec()) {          // returns TRUE if conversion complete.
           Display_BCD_Data();   // Put on LCD or LED display.
           // Now get new data to display.
           binary = CreateNewBinaryValueToDisplay();
       };

       // Do other real time processing every 10 uSeconds or so with a 20MHz
       // processor.
   }
}
<<--
Pioneers are the ones, face down in the mud,
with arrows in their backs.
Automation Artisans Inc.      Ph. 1-250-544-4950
PO Box 20002                  Fax 1-250-544-4954
Sidney, BC CANADA V8L 5C9

1997\03\05@183315 by sdattalo

face
flavicon
face
John Dammeyer wrote:
>

>
> As for John Payson's method.  Haven't gotton to it yet.  But the assembler
> version obviously takes 50 instructions.  How much time is spent in the
> loops?  Don't know yet.  It will probably be the fastest and the smallest;
> understanding how it works may be more difficult.

Well, according to Bob Fehrenbach timing analysis:
  (NB: 49 program memory locations.  Executes in
  153 to 198 clock cycles (worst case I could find)  BF)

And according to my dissection (which I posted last November) in
response to a challenge from John:

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.


Scott

PS The jury is out...

1997\03\06@100304 by Site Y

picon face
 There is a borderline elegant routine for Binary to BCD conversion in
Appendix H of AN-526, which can be found in the Microchip Embedded
Control Handbook, 1995 editon.  The original version of this appeared to
the best of my knowledge in the General Instrument PIC Applications
Manual, August 1980 (Note: no typo... 1 9 8 0)

 The routine as presented by GI/Microchip can be further optimized by
about 5 instructions and 100 or so cycles.  It can also be incorporated
into a divide routine (if you happen to need to convert the output of a
binary divide to BCD) for even greater instruction/execution economy.

Site Y


'Binary to BCD'
1998\02\28@191401 by Bill Kennedy
flavicon
face
Anyone have any subs that convert a 12 bit binary serial input to 4 BCD
numbers that are possibly stored in registers to send out to to
displays?

thanks in advance for any suggestions


'Binary to BCD'
1998\03\02@051214 by Peter Baines
flavicon
face
Bill, Try this code. I have used it in a recent project. I hope it helps

Peter.

;
***************************************************************************
; ASSIGN LABELS TO THE VARIOUS (RAM) DATA FILE REGISTERS USED
;
***************************************************************************
R0              RES     1               ; DECIMAL STORE FOR 1S DIGIT
R1              RES     1               ; DECIMAL STORE FOR 10S DIGIT
R2              RES     1               ; DECIMAL STORE FOR 100S DIGIT

DIGIT1          RES     1               ; STORE FOR RIGHT DISPLAY DATA
DIGIT2          RES     1               ; STORE FOR R/MIDDLE DISPLAY DATA
DIGIT3          RES     1               ; STORE FOR L/MIDDLE DISPLAY DATA
DIGIT4          RES     1               ; STORE FOR LEFT DISPLAY DATA

; *******************************************************
; * BCD CONVERSION
; *******************************************************
B2_BCD  MOVFW   COUNTER_LOW
       MOVWF   IPBUFFL
       MOVFW   COUNTER_HIGH
       MOVWF   IPBUFFH
       BCF     STATUS,CARRY            ; NOW CONVERT THE 16 BIT NUMBER
       MOVLW   16                      ; INTO 5 BCD CHARACTERS - THE UPPER BCD
       MOVWF   COUNT1                  ; IS NOT DISPLAYED BUT HAS BEEN LEFT IN
       CLRF    R0                      ; FOR FUTURE USE
       CLRF    R1
       CLRF    R2

LOOP16  RLF     IPBUFFL,F               ; COUNT BUFFER LOW BYTE
       RLF     IPBUFFH,F               ; COUNT BUFFER HIGH BYTE
       RLF     R2,F
       RLF     R1,F
       RLF     R0,F
       DECFSZ  COUNT1,F                ;DECRIMENT AND SKIP IF ZERO
       GOTO    ADJDEC
       GOTO    BCDCON

ADJDEC  MOVLW   R2
       MOVWF   FSR
       CALL    ADJBCD
       MOVLW   R1
       MOVWF   FSR
       CALL    ADJBCD
       MOVLW   R0
       MOVWF   FSR
       CALL    ADJBCD
       GOTO    LOOP16
BCDCON                          ; CONVERT THE 4 BCD DIGITS INTO THE CORRECT
       SWAPF   R1,W            ; FORMAT FOR THE LED BIT PATTEN.
       ANDLW   0FH                     ; STRIP UPPER BITS
       CALL    GETCHAR
       MOVWF   DIGIT4
       MOVFW   R1
       ANDLW   0FH                     ; STRIP UPPER BITS
       CALL    GETCHAR
       MOVWF   DIGIT3
       SWAPF   R2,W
       ANDLW   0FH                     ; STRIP UPPER BITS
       CALL    GETCHAR
       MOVWF   DIGIT2
       MOVFW   R2
       ANDLW   0FH                     ; STRIP UPPER BITS
       CALL    GETCHAR
       MOVWF   DIGIT1
       RETURN

;***************************************************************************
**
; ADJUST FOR BCD
;***************************************************************************
**
ADJBCD  MOVLW   3
       ADDWF   0,W
       MOVWF   TEMP
       BTFSC   TEMP,3                  ; TEST IF RESULT > 7
       MOVWF   0
       MOVLW   30H
       ADDWF   0,W
       MOVWF   TEMP
       BTFSC   TEMP,7                  ; TEST IF RESULT > 7
       MOVWF   0                       ; SAVE AS MSD
       RETLW   0

;***************************************************************************
**
; GET A DISPLAY CHARACTER BIT PATTERN BY CONVERTING 'W' TO DISPLAY CODE
;***************************************************************************
**
GETCHAR
       ADDWF   PC,F            ; USE 'W' AS AN OFFSET FOR 'PC'
       RETLW   B'00111111'     ; RETURN WITH "0" DISPLAY CODE
       RETLW   B'00000110'     ; RETURN WITH "1" DISPLAY CODE
       RETLW   B'01011011'     ; RETURN WITH "2" DISPLAY CODE
       RETLW   B'01001111'     ; RETURN WITH "3" DISPLAY CODE
       RETLW   B'01100110'     ; RETURN WITH "4" DISPLAY CODE
       RETLW   B'01101101'     ; RETURN WITH "5" DISPLAY CODE
       RETLW   B'01111101'     ; RETURN WITH "6" DISPLAY CODE
       RETLW   B'00000111'     ; RETURN WITH "7" DISPLAY CODE
       RETLW   B'01111111'     ; RETURN WITH "8" DISPLAY CODE
       RETLW   B'01100111'     ; RETURN WITH "9" DISPLAY CODE
       RETLW   B'01110111'     ; RETURN WITH "A" DISPLAY CODE
       RETLW   B'01111100'     ; RETURN WITH "B" DISPLAY CODE
       RETLW   B'00111001'     ; RETURN WITH "C" DISPLAY CODE
       RETLW   B'01011110'     ; RETURN WITH "D" DISPLAY CODE
       RETLW   B'01111001'     ; RETURN WITH "E" DISPLAY CODE
       RETLW   B'01110001'     ; RETURN WITH "F" DISPLAY CODE





====================================
Remember .... Every Silver Lining
Has It's Cloud
====================================
Mailto:KILLspamefocKILLspamspamcyberstop.net


'Binary to BCD'
1998\10\14@205851 by Sean Breheny
face picon face
Hi all,

I am trying to do 16 bit binary to BCD conversion and it is becomming much
more complicated than I had initially anticipated. As far as I can see,
there are only two ways to accomplish it:

1) Integer Division by 10 (and using the remainders as the resultant digits)

2) Using a lookup table for each resultant digit to find the "contribution"
from each bit of the input number (i.e., for the hundreds digit, bits 0
thru 6 contribute zero, but bit 7 adds 100, bit 8 adds 200, bit 9 adds 500,
so you add up each of these contributions, modulo ten, and place the result
as the hundreds digit, and carry over what's left to the next digit's
contribution).


Both of these take up considerable code and register space (for method one,
I'd need a 16bit division by ten routine as well as several pairs of 8bit
file regs, for method 2 I'd need about 40 words of lookup space in addition
to some code).

Can someone provide a sanity check? Is there something I'm not seeing?

I realize that there is probably boilerplate code out there for this, and I
may ultimately resort to that, but for now, I only want to borrow ideas
from it at most, I want to write this code for its educational value.

Thanks,

Sean

+-------------------------------+
| Sean Breheny                  |
| Amateur Radio Callsign: KA3YXM|
| Electrical Engineering Student|
+-------------------------------+
Save lives, please look at http://www.all.org
Personal page: http://www.people.cornell.edu/pages/shb7
RemoveMEshb7TakeThisOuTspamcornell.edu  Phone(USA): (607) 253-0315 ICQ #: 3329174

1998\10\14@211107 by Lee Jones

flavicon
face
> I am trying to do 16 bit binary to BCD conversion and it is becomming
> much more complicated than I had initially anticipated. As far as I
> can see, there are only two ways to accomplish it:

> 1) Integer Division by 10 (remainders [are] digits)

> 2) Using a lookup table for each resultant digit to find the
> "contribution" from each bit of the input number


How about:

3) repeated subtraction of 10000, 1000, 100, 10; remainder is
  1s digit.  You do need a 16-bit subtract routine.

                                               Lee Jones

1998\10\14@214503 by Sean Breheny

face picon face
Hi Lee,

Thanks for the idea. I'll give it a try and see how it compares in size and
resources. It certainly looks better.

Sean

At 06:08 PM 10/14/98 -0700, you wrote:
>> I am trying to do 16 bit binary to BCD conversion and it is becomming
>> much more complicated than I had initially anticipated. As far as I
>> can see, there are only two ways to accomplish it:

[SNIP]

>How about:
>
>3) repeated subtraction of 10000, 1000, 100, 10; remainder is
>   1s digit.  You do need a 16-bit subtract routine.
>
>                                                Lee Jones
>
+-------------------------------+
| Sean Breheny                  |
| Amateur Radio Callsign: KA3YXM|
| Electrical Engineering Student|
+-------------------------------+
Save lives, please look at http://www.all.org
Personal page: http://www.people.cornell.edu/pages/shb7
spamBeGoneshb7spamBeGonespamcornell.edu  Phone(USA): (607) 253-0315 ICQ #: 3329174

1998\10\14@215311 by Sean Breheny

face picon face
Lee and everyone else,

Yup. That is much easier. I don't know why, but when I was trying to come
up with a way to do this, that method seemed to have way too many
subtractions in it, but it actually has a maximum of 7+6+6+4+6=29 total 16
bit subtractions for the entire 16 bit conversion.

Thanks again,

Sean


At 06:08 PM 10/14/98 -0700, you wrote:
{Quote hidden}

+-------------------------------+
| Sean Breheny                  |
| Amateur Radio Callsign: KA3YXM|
| Electrical Engineering Student|
+-------------------------------+
Save lives, please look at http://www.all.org
Personal page: http://www.people.cornell.edu/pages/shb7
TakeThisOuTshb7EraseMEspamspam_OUTcornell.edu  Phone(USA): (607) 253-0315 ICQ #: 3329174

1998\10\14@215502 by Dwayne Reid

flavicon
face
>I am trying to do 16 bit binary to BCD conversion and it is becomming much
>more complicated than I had initially anticipated. As far as I can see,
>there are only two ways to accomplish it:
>
>1) Integer Division by 10 (and using the remainders as the resultant digits)
>
>2) Using a lookup table for each resultant digit to find the "contribution"
>from each bit of the input number (i.e., for the hundreds digit, bits 0
>thru 6 contribute zero, but bit 7 adds 100, bit 8 adds 200, bit 9 adds 500,
>so you add up each of these contributions, modulo ten, and place the result
>as the hundreds digit, and carry over what's left to the next digit's
>contribution).

Try door number 3:

   save number into reg
   clrf 10ks
   clrf 1ks
   clrf 100s
   clrf 10s
   clrf 1s


loop1
   subtract .10000,W (use appropriate routine: make sure it preserves C)
   skpc                ;note result is in W
     goto  sub_1k      ;underflow?
   movwf   reg         ;nope, so save new value
   incf    10ks        ;increment 10 thousands register
   goto loop1          ;do it again

sub_1k
   subtract .1000

I'm sure you can see where this is going . . .

It takes a while (6 loops max for 10ks, 10 loops max for the each of the
other loops) but doesn't take too much space.  Otherwise, look for Johm
Payson's neat routine that does it faster (much faster!) AND in less space!

Hope this helps.

dwayne





Dwayne Reid   <RemoveMEdwaynerspamTakeThisOuTplanet.eon.net>
Trinity Electronics Systems Ltd    Edmonton, AB, CANADA
(403) 489-3199 voice     (403) 487-6397 fax

1998\10\14@220540 by Sean Breheny

face picon face
[SNIP]

>Lee and everyone else,
>
>Yup. That is much easier. I don't know why, but when I was trying to come
up with a way to do >this, that method seemed to have way too many
subtractions in it, but it actually has a >maximum >of 7+6+6+4+6=29 total
16 bit subtractions for the entire 16 bit conversion.

OOPS. That should have said 6+10+10+10+10=46.

Sean



+-------------------------------+
| Sean Breheny                  |
| Amateur Radio Callsign: KA3YXM|
| Electrical Engineering Student|
+-------------------------------+
Save lives, please look at http://www.all.org
Personal page: http://www.people.cornell.edu/pages/shb7
shb7EraseMEspam.....cornell.edu  Phone(USA): (607) 253-0315 ICQ #: 3329174

1998\10\15@011650 by Sean Breheny

face picon face
Hi Duane and everyone else,

This binary to BCD conversion is really beginning to show me how little I
know about binary arithmetic! My additional question is below:

At 09:55 PM 10/14/98 -0400, you wrote:
>loop1
>    subtract .10000,W (use appropriate routine: make sure it preserves C)
>    skpc                ;note result is in W
>      goto  sub_1k      ;underflow?
>    movwf   reg         ;nope, so save new value
>    incf    10ks        ;increment 10 thousands register
>    goto loop1          ;do it again

Well, I understand what you are saying, and if I write a BASIC program in
QBASIC to do this, it works fine (using the built-in subtract routine).

However, now I am trying to port this to my PIC and I am having problems
writing a subtract routine:

Here's what I tried:

>>>>CODE STARTS HERE

; SUB16
; Does AB-CD -> AB
; Destroys A,B,W,Carry,DigitCarry
; Returns A,B,Carry

rA      equ     0x0C
rB      equ     0x0D
rC      equ     0x0E
rD      equ     0x0F

main    call sub16
main2   goto main2

sub16   movf rD,W       ;Do B-D -> B
       subwf rB,F
       movlw 1 ;Do the borrow from A if needed
       skpc
       subwf rA,F
       movf rC,W       ;Do A-C -> A
       subwf rA,F
       return          ;Done
       END


>>>>CODE ENDS HERE

When I simulate this, the result seems to be correct. However, the carry
out does not follow the rules required to be used in the above routine
provided by Duane. The reason for this is that the last subtraction (subwf
rA,F), considers rA to be a positive number, regardless of its MSB (this
doesn't affect the answer, but it does affect the carry). I could make the
routine more complicated and make a carry out which follows the criteria
needed for the routine, but why not just use the MSB of the output to tell
if it is positive or negative?
Also, what SHOULD the carry out be for such a subtract routine? If you
simply execute SUBWF A,F and A contains a negative number and W contains a
small positive number, the PIC will call the output positive ( nBORROW = 1
). Should my routine do the same if fed a negative number in AB? I realize
that it doesn't really matter for the BCD conversion application, but I
just want to understand how to write a general 16 bit subtract routine.

Thanks,

Sean

+-------------------------------+
| Sean Breheny                  |
| Amateur Radio Callsign: KA3YXM|
| Electrical Engineering Student|
+-------------------------------+
Save lives, please look at http://www.all.org
Personal page: http://www.people.cornell.edu/pages/shb7
EraseMEshb7spamcornell.edu  Phone(USA): (607) 253-0315 ICQ #: 3329174

1998\10\15@012117 by Sean Breheny

face picon face
OOPS AGAIN! I must be very tired. Sorry, Dwayne. I TOTALLY mispelled your
name in that last message.

Sean


+-------------------------------+
| Sean Breheny                  |
| Amateur Radio Callsign: KA3YXM|
| Electrical Engineering Student|
+-------------------------------+
Save lives, please look at http://www.all.org
Personal page: http://www.people.cornell.edu/pages/shb7
RemoveMEshb7EraseMEspamEraseMEcornell.edu  Phone(USA): (607) 253-0315 ICQ #: 3329174

1998\10\15@014352 by Sean Breheny

face picon face
I think I found my mistake.

This is what the subtract routine should look like:

sub16   movf rD,W       ;do B-D -> B
       subwf rB,F
       movf rC,W       ;load C into W
       skpc            ;add one to W to do borrow if needed
       addlw 1
       subwf rA,F      ;Do A-C -> A
       return

This preserves the carry by combining the borrow and the final subtraction
into one subwf

Thanks for all your help and I'll probably be back with more questions,

Sean


+-------------------------------+
| Sean Breheny                  |
| Amateur Radio Callsign: KA3YXM|
| Electrical Engineering Student|
+-------------------------------+
Save lives, please look at http://www.all.org
Personal page: http://www.people.cornell.edu/pages/shb7
RemoveMEshb7spam_OUTspamKILLspamcornell.edu  Phone(USA): (607) 253-0315 ICQ #: 3329174

1998\10\15@014609 by Tony Nixon

flavicon
picon face
Sean Breheny wrote:
> Also, what SHOULD the carry out be for such a subtract routine?

A - B

if B = A then C = 1, Z = 1
if B < A then C = 1, Z = 0
if B > A then C = 0, Z = 0

--
Best regards

Tony

Multimedia 16F84 Beginners PIC Tools.
**New Improved PicNPost**

http://www.picnpoke.com
Email RemoveMEpicnpokeTakeThisOuTspamspamcdi.com.au

1998\10\15@015425 by Sean Breheny

face picon face
Hi Tony,

At 03:42 PM 10/15/98 +1000, you wrote:
>Sean Breheny wrote:
>> Also, what SHOULD the carry out be for such a subtract routine?
>
>A - B
>
>if B = A then C = 1, Z = 1
>if B < A then C = 1, Z = 0
>if B > A then C = 0, Z = 0
>

Yes, of course, I understand that, but my point is "how do we tell if B>A
or B<A"? I ask this because we are considering A to be an unsigned number
and B to be signed. We can consider them both to be signed, and the result
doesnt change, but should the carry then be different, since for A=-1 B =
2, B is really greater than A, but when we feed the two's complement
numbers into our routine, we would get "A=0xFF B=0x02" and it would
conclude that A>B.

Sean


+-------------------------------+
| Sean Breheny                  |
| Amateur Radio Callsign: KA3YXM|
| Electrical Engineering Student|
+-------------------------------+
Save lives, please look at http://www.all.org
Personal page: http://www.people.cornell.edu/pages/shb7
EraseMEshb7spamspamspamBeGonecornell.edu  Phone(USA): (607) 253-0315 ICQ #: 3329174

1998\10\15@020252 by William Chops Westfield

face picon face
   that method seemed to have way too many subtractions in it, but
   it actually has a maximum of 7+6+6+4+6=29 total 16 bit
   subtractions for the entire 16 bit conversion.

Ok, how did you get that sum?  I get something like 35
subtractions (which still isn't that bad) for 59999...  I guess
the last 10 subtracts are only 8-bit, and an additional 10
subtracts are an 8 bit quantity from a 16 bit value.

BillW

1998\10\15@021748 by Sean Breheny

face picon face
Hi Bill,

At 11:00 PM 10/14/98 PDT, you wrote:
>    that method seemed to have way too many subtractions in it, but
>    it actually has a maximum of 7+6+6+4+6=29 total 16 bit
>    subtractions for the entire 16 bit conversion.
>
>Ok, how did you get that sum?  I get something like 35
>subtractions (which still isn't that bad) for 59999...  I guess
>the last 10 subtracts are only 8-bit, and an additional 10
>subtracts are an 8 bit quantity from a 16 bit value.

Yeah, you're right. I goofed that one totally. I was thinking that 65535
would yield the maximum number of subtractions. There must be a time delay
between me-the list-and you because I already sent out a message attempting
to correct what I had said before. I got 46 in that message, but that was
counting every subtraction as a 16-bit subtraction, and it was counting
subtractions for the ones  place as well!! So, it should be (if I can trust
my brain now!) 6+10+10=26 16-bit subtractions and then 10 more 8-bit ones
(for the tens place and the ones remainder).

WOW! I really have to check my math before I post to 1600 people!

Thanks for the correction,

Sean

>
>BillW
>
+-------------------------------+
| Sean Breheny                  |
| Amateur Radio Callsign: KA3YXM|
| Electrical Engineering Student|
+-------------------------------+
Save lives, please look at http://www.all.org
Personal page: http://www.people.cornell.edu/pages/shb7
RemoveMEshb7KILLspamspamcornell.edu  Phone(USA): (607) 253-0315 ICQ #: 3329174

1998\10\15@031041 by Tony Nixon

flavicon
picon face
Sean Breheny wrote:
> I ask this because we are considering A to be an unsigned number
> and B to be signed.

It would obviously get tricky if one number was signed and the other
not. The signed value can never be more than half the value of the
unsigned value, assuming the same bit length. Therefore, if the MSB of
the unsigned number = 1, then it will be the larger value. If the MSB of
the signed value is negative, then it will always be the lower value. If
both numbers are positive, with number A MSB = 0, then you would need to
test for the larger of the 2 positive values.

--
Best regards

Tony

Multimedia 16F84 Beginners PIC Tools.
**New Improved PicNPost**

http://www.picnpoke.com
Email picnpokeSTOPspamspamspam_OUTcdi.com.au

1998\10\15@042208 by N Steenkamp

flavicon
picon face
Hi,

> Lee and everyone else,
>
> Yup. That is much easier. I don't know why, but when I was trying to come
> up with a way to do this, that method seemed to have way too many
> subtractions in it, but it actually has a maximum of 7+6+6+4+6=29 total 16
> bit subtractions for the entire 16 bit conversion.
>
> Thanks again,
>
> Sean
>

[snip]

> >3) repeated subtraction of 10000, 1000, 100, 10; remainder is
> >   1s digit.  You do need a 16-bit subtract routine.
> >

I usually use the plain old divide by 10 and get the remainder method.
The routine is small (16 words, including the Z flag stuff at the end)
and it executes reasonably fast (about 185 cycles).  I doubt if 30+
16 bit subtractions would be significantly faster or smaller (if any).
The divide routine also scales extremely easy - A small increase in
size for every byte and an almost linear increase in execution time.  The
only drawback of the divide scheme is that you receive your digits from
right to left and not left to right.



;=========================================================================
;Divide the 16 bit number in TempNum by 10 and store the result
;in TempNum and the remainder in Temp.  If the quotient and the
;remainder is 0, the Z flag is set.  This is usefull for leading 0
;suppression.
;=========================================================================
Div10:
       movlw   16
       movwf   C1                      ;Repeat for 16 bits
       clrf    Temp
Div10Loop:
       rlf     TempNum, W
       rlf     TempNum+1, F
       rlf     Temp, F                 ;Move MSB of Number into Temp
       movlw   10
       subwf   Temp, W                 ;Does 10 go in?
       btfsc   STATUS, C
        movwf   Temp                   ;If so, update remainder
       rlf     TempNum, F              ;If 10 went in, shift in a 1, if
                                       ;not shift in a 0
       decfsz  C1, F
        goto   Div10Loop               ;Repeat for all bits

       movf    TempNum, W              ;Test if Quotient is 0
       iorwf   TempNum+1, W            ;Test if Quotient is 0
       iorwf   Temp, W                 ;Test if Remainder is also 0
       return


Niki

1998\10\15@123045 by Harold Hallikainen

picon face
       I haven't looked at this closely, but how about for a 16 bit
binary, do 16 bit tests and 16 appropriate BCD additions (using the DC
flag)?


Harold




Harold Hallikainen
spamBeGoneharoldSTOPspamspamEraseMEhallikainen.com
Hallikainen & Friends, Inc.
See the FCC Rules at http://hallikainen.com/FccRules and comments filed
in LPFM proceeding at http://hallikainen.com/lpfm


___________________________________________________________________
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\10\15@132246 by Sean Breheny

face picon face
Hi Harold,

At 12:29 PM 10/15/98 EDT, you wrote:
>        I haven't looked at this closely, but how about for a 16 bit
>binary, do 16 bit tests and 16 appropriate BCD additions (using the DC
>flag)?

This is basically a more refined version of what I was talking about in
option #2 of my original message. This is probably faster than the
subtraction method, but it requires more space since it needs a lookup
table for the values to be added for each bit. There are ways to calculate
the values other than a lookup table, but I think that they would take even
more space.

Thanks,

Sean


{Quote hidden}

+-------------------------------+
| Sean Breheny                  |
| Amateur Radio Callsign: KA3YXM|
| Electrical Engineering Student|
+-------------------------------+
Save lives, please look at http://www.all.org
Personal page: http://www.people.cornell.edu/pages/shb7
EraseMEshb7spamEraseMEcornell.edu  Phone(USA): (607) 253-0315 ICQ #: 3329174

1998\10\20@114138 by John Payson

flavicon
face
part 0 1361 bytes
|It takes a while (6 loops max for 10ks, 10 loops max for the each of the
|other loops) but doesn't take too much space.  Otherwise, look for Johm
|Payson's neat routine that does it faster (much faster!) AND in less space!

Thanks for the plug.  I'm sure one of the Andys around here will
post my routine (who was the brilliant guy who commented the thing
far better than I could have done?)  Anyway, on a related note, I
was writing a program on an 8x51 clone (ducking) and needed to
display some 32-bit numbers; in some cases I needed a straight
integer output while in others I needed to display an integer # of
miliseconds in h:mm:ss.mmm format.  The techniques I used to do the
conversion may be of interest, though they were optimized to use the
8x51's DIV/MUL instructions: all divides and multiplies are by
constants, so table-lookup should be quite feasible.  I'll need to
clean the algorithm up if anyone is to understand it, so I'll post
it later.

For quick mod'ing by 10 or 6 of large numbers, there's a little
trick which may also be helpful: add up all the nybbles of the
number except the least-significant nybble, multiply that sum by
six, then add the least-significant nybble and mod by 10 or 6.
Since some quick-and-dirty divide-by-10 or divide-by-6 routines
don't report a remainder the quick mod'ing routine can be quite
handy at times.

1998\10\20@135847 by Scott Dattalo

face
flavicon
face
On Tue, 20 Oct 1998, John Payson wrote:

>
> |It takes a while (6 loops max for 10ks, 10 loops max for the each of the
> |other loops) but doesn't take too much space.  Otherwise, look for Johm
> |Payson's neat routine that does it faster (much faster!) AND in less space!
>
> Thanks for the plug.  I'm sure one of the Andys around here will
> post my routine (who was the brilliant guy who commented the thing
> far better than I could have done?)

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

I would've posted the URL earlier, but the obligatory 3 month
non-repeating BCD thread time had not been exceeded. Sigh.

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