If statement - checking only the first 5 MSB's.

Hi all,

I would like an if statement of mine to check a binary value, and of course do something depending on its condition. However, I'm only interested in the first five bits. Currently, I've got the following - and the device ID I'm expecting is 01100110, however - the final three bits will sometimes change.

The following works, but it's not quite elegant - as if for example I received back B10000000, the code would print comms successful, when that is in this case an invalid identity byte.

  if (ident_reg_contents != B00000000)
  {
    Serial.println("");
    Serial.println("");
    Serial.println("SPI comms successful!");
    Serial.print("CJ125 Device ID - ");
    Serial.println(ident_reg_contents, BIN);
  }
  else 
  {
    Serial.println("SPI comms failed!");
  }

How can I write the statement so it would read as following - where the last three bits marked as x don't matter, so the statement just checks that the identity register contains a byte that starts with 01100, and doesn't care about the last three bits?

if (ident_reg_contents == B01100xxx)
  {
    Serial.println("");
    Serial.println("");
    Serial.println("SPI comms successful!");
    Serial.print("CJ125 Device ID - ");
    Serial.println(ident_reg_contents, BIN);
  }
  else 
  {
    Serial.println("SPI comms failed!");
  }

Many thanks in advance!

if ( (ident_reg_contents & 0B11111000) == 0B01100000)

equally efficient (or not):

if ((ident_reg_contents>>3)==B1100) // Do something

This is to shift the entire byte 3 bits to the right so you only have the high 5 bits.

Notice, there is not supposed to be a zero before the B. Added the zero and it still compiles. I guess 0B and 0b are equally valid.

there is not supposed to be a zero before the B.

It depends. 0bXXXXX is a gcc extension for binary constants.
BXXXX are macros defined in one of the files included by the arduino IDE.
So 0bxx is more portable to other gcc uses (for instance, Atmel Studio), while Bxxxx is more portable to random other compilers (assuming you copy over the correct .h file...)

I'm inclined to believe that the shift is less efficient, since a 3bit shift is at least three instructions. But the compiler might be smart enough to generate similar code for the case where constants are involved...

liudr:
Notice, there is not supposed to be a zero before the B.

The Arduino has some defined constants for binary values or various sizes such as B01100000. While this defines the commonly-used values such as all 8-bit and 16-bit numbers, it doesn't support all possible values.

The compiler used by the Arduino IDE already supports arbitrary binary literal values so that the Arduino's B01100000 is equivalent to 0b01100000. Unless you are planning to use a different compiler I can't see any advantage to using the Arduino defined constants over using the compiler-supported literal values.

declare another variable, test_byte
so that the contents of ident_reg_contents aren't altered (assuming that's undesirable)

test byte = ident_reg_contents;
if ((test_byte &= B11111000) == B01100000) // B11111000 mask
{
do this stuff
}

The shift might not be portable depending on whether the variable is signed or un-signed.

Runaway Pancake:
Neither proposed solution modifies ident_reg_contents.

In fact, the compiler would probably optimise away your temporary variable.

If it gets shiftedright/left then it gets modified, yes?

if ((ident_reg_contents >= B01100000) && (ident_reg_contents <= B01100111))
{
do this stuff
}

No, only the temporary value in the register gets changed. The only way to change the value of the variable is an actual assignment: =, +=, -=, et al.

Really, this is programming 101.

Then I guess I'm in the right place!

KeithRB:
The shift might not be portable depending on whether the variable is signed or un-signed.

You're right. I didn't think of that.

Of course, portability is not generally the number one concern for someone writing code for Arduino! 8^)

Hi all,

Thanks for all the replies so far. That gives me some solutions to work with.

Regarding portability with other microcontroller platforms, that's not an issue for me. This is just a very small piece of code from a code spanning many, many pages that will eventually be dealt with in Atmel Studio - so I'll be changing all the Bxxxxxx to 0bxxxxxxxx to support that.

Whilst I understand the shifting solution, I"m not entirely sure of the solution that takes the following form; could anybody enlighten me as to what is going on? Especially with regards to the &?

if (ident_reg_contents & B11111000) == B01100000)

I've posted this around the place a few times, but here is a portable binary constant generator: A little something I would like to share. - Programming Questions - Arduino Forum

It allows binary constants separated every 8 bits.

uint8_t u_6 = B8(00000110);  //6

uint16_t u_AABB = B16( 10101010, 10111011 ); //43707

uint32_t u_AABBCCDD = B32( 10101010, 10111011, 11001100, 11011101 ); //2864434397

'&' is the bitwise and operator. It compares each bit in each operand and outputs a result according to the following truth table:

Inputs Output
0 0 0
0 1 0
1 0 0
1 1 1

So '&' only outputs a 1 if both inputs are 1. This lets us create a "mask"
B11111000 & ident_reg_contents will return the value of the corresponding bit in ident_reg-contents when the mask is 1 and return 0 where the mask is 0. Since we do not care about the last 3 bits, setting them to zero will allow us to use a constant to compare.

Ah of course, the same as manipulating data direction registers with bitwise operations for example. Not too sure why I didn't spot that.

Thank you!