0

This isn't a regular "binary to bcd" question, in fact, I'm not really sure what to call the thing I'm trying to do!

There is a single byte in an embedded device that stores the numbers 1 through 7 (for days of the week) in the following format:

00000001 = 1
00000010 = 2
00000100 = 3
00001000 = 4
00010000 = 5
00100000 = 6
01000000 = 7

I want to read this byte, and convert its contents (1 through 7) into BCD, but I'm not sure how to do this.

I know I could just brute-force it with a series of if statements:

if(byte == B00000001) 
{
    answer = 1; 
}
else
if(byte == B00000010) 
{
    answer = 2; 
}

and so on, but I think there could be a better way. This data is stored in a single register on a real time clock. I'm getting this byte by performing an I2C read, and I read it into a byte in my program. The datasheet for this real-time clock specifies that this particular register is formatted as I have outlined above.

mcleod_ideafix
  • 11,128
  • 2
  • 24
  • 32
user3211203
  • 3
  • 1
  • 3

3 Answers3

3

You can use a lookup table...

/* this is only needed once, if lut is global or static */
unsigned char lut[65];
lut[1]=1;
lut[2]=2;
lut[4]=3;
lut[8]=4;
lut[16]=5;
lut[32]=6;
lut[64]=7;

...
...
...

/* Perform the conversion */
answer = lut[byte];

Or you can even use some math...

answer = 1 + log(byte)/log(2);
mcleod_ideafix
  • 11,128
  • 2
  • 24
  • 32
  • I hadn't even though of using logarithms! This looks like it'll be the easiest to implement, thanks! – user3211203 Jan 19 '14 at 02:29
  • On second thought, since I am working on an embedded system, speed is quite important. Do you know which of the methods you list above would be faster for an 8 bit 16MHz processor to accomplish? I have a feeling that calculating 2 logarithms and a division will take longer than the look-up table – user3211203 Jan 19 '14 at 02:42
  • @user3211203 have a look at the link I left on your question. It's about the fastest way of calculating base-2 integer logarithms. – Mark Ransom Jan 19 '14 at 04:04
  • @user3211203 : undoubtely, the first (LUT) approach. You can have your LUT in code memory, which is usually larger than data memory. If you initialize it in the declaration, it will be ready just from the first clock cycle. To use it, it's just a code memory read using an index, which may take a few cycles (about 4-5 cycles on a 8051-class microcontroller) – mcleod_ideafix Jan 19 '14 at 12:13
2

If this is being compiled on an ARM processor, you can simply do this:

result = 31 - __CLZ(number);

Assuming number is a 32-bit one-hot > 0.

pableiros
  • 14,932
  • 12
  • 99
  • 105
Carlos
  • 21
  • 1
0

You can make use of bitwise and modulo operations to do this efficiently without needing to create a large array

for (int answer = 1; (byte % 2) == 0; ++answer) {
    byte >>= 1;
}

(I know this was an old question, I just wanted to share because this was a high Google result for me)

nathanscain
  • 121
  • 5