Pages: [1] 2   Go Down
Author Topic: If statement - checking only the first 5 MSB's.  (Read 601 times)
0 Members and 1 Guest are viewing this topic.
UK
Offline Offline
God Member
*****
Karma: 1
Posts: 530
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
 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:
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!
« Last Edit: February 07, 2013, 10:57:46 am by jtw11 » Logged

Offline Offline
Edison Member
*
Karma: 32
Posts: 1394
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Central MN, USA
Offline Offline
Tesla Member
***
Karma: 72
Posts: 7175
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
« Last Edit: February 07, 2013, 02:32:58 pm by liudr » Logged


SF Bay Area (USA)
Offline Offline
Tesla Member
***
Karma: 124
Posts: 6654
Strongly opinionated, but not official!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12579
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Edison Member
*
Karma: 64
Posts: 2465
Now, More Than Ever
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
}
Logged

"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?"

Offline Offline
Edison Member
*
Karma: 32
Posts: 1394
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Offline Offline
Edison Member
*
Karma: 32
Posts: 1394
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Runaway Pancake:
Neither proposed solution modifies ident_reg_contents.

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

Logged

Offline Offline
Edison Member
*
Karma: 64
Posts: 2465
Now, More Than Ever
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

if ((ident_reg_contents >= B01100000) && (ident_reg_contents <= B01100111))
{
  do this stuff
}
« Last Edit: February 07, 2013, 02:17:04 pm by Runaway Pancake » Logged

"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?"

Offline Offline
Edison Member
*
Karma: 32
Posts: 1394
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Offline Offline
Edison Member
*
Karma: 64
Posts: 2465
Now, More Than Ever
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Then I guess I'm in the right place!
Logged

"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?"

Central MN, USA
Offline Offline
Tesla Member
***
Karma: 72
Posts: 7175
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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


Offline Offline
Edison Member
*
Karma: 32
Posts: 1394
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

UK
Offline Offline
God Member
*****
Karma: 1
Posts: 530
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
if (ident_reg_contents & B11111000) == B01100000)
« Last Edit: February 07, 2013, 06:54:31 pm by jtw11 » Logged

North Queensland, Australia
Online Online
Edison Member
*
Karma: 66
Posts: 2113
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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
Logged


Pages: [1] 2   Go Up
Jump to: