Question

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.

Was it helpful?

Solution

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);

OTHER TIPS

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.

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)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top