Go Down

Topic: If statement - checking only the first 5 MSB's. (Read 757 times) previous topic - next topic

jtw11

Feb 07, 2013, 04:54 pm Last Edit: Feb 07, 2013, 04:57 pm by jtw11 Reason: 1
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.

Code: [Select]
 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?

Code: [Select]
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!

KeithRB

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

liudr

#2
Feb 07, 2013, 06:23 pm Last Edit: Feb 07, 2013, 08:32 pm by liudr Reason: 1
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.

westfw

Quote
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...

PeterH


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.
I only provide help via the forum - please do not contact me for private consultancy.

Runaway Pancake

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
}
"Hello, I must be going..."
"You gotta fight -- for your right -- to party!"
Don't react - Read.
"Who is like unto the beast? who is able to make war with him?"

KeithRB

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

KeithRB

Runaway Pancake:
Neither proposed solution modifies ident_reg_contents.

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


Runaway Pancake

#8
Feb 07, 2013, 08:08 pm Last Edit: Feb 07, 2013, 08:17 pm by Runaway Pancake Reason: 1
If it gets shiftedright/left then it gets modified, yes?

if ((ident_reg_contents >= B01100000) && (ident_reg_contents <= B01100111))
{
 do this stuff
}
"Hello, I must be going..."
"You gotta fight -- for your right -- to party!"
Don't react - Read.
"Who is like unto the beast? who is able to make war with him?"

KeithRB

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.

Runaway Pancake

"Hello, I must be going..."
"You gotta fight -- for your right -- to party!"
Don't react - Read.
"Who is like unto the beast? who is able to make war with him?"

liudr


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.

KeithRB

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

jtw11

#13
Feb 08, 2013, 12:49 am Last Edit: Feb 08, 2013, 12:54 am by jtw11 Reason: 1
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 &?

Code: [Select]
if (ident_reg_contents & B11111000) == B01100000)

pYro_65

I've posted this around the place a few times, but here is a portable binary constant generator: http://arduino.cc/forum/index.php/topic,93201.msg700368.html#msg700368

It allows binary constants separated every 8 bits.

Code: [Select]
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

Go Up