What is wrong with my bit math?

Im trying to compare two pin inputs using port manipulation, this code works like it should,

 if (bitRead(PIND, 3) == bitRead(PIND, 4))
   {
      iEncoderCounter++;
   } 
  else 
   {
      iEncoderCounter--;
   }

Ive read about 15 different articles and books, trying to figure out bit math and how to write the above code without using bitRead, none of my code using bit masking works

 if ((PIND & (1<<3)) == (PIND & (1<<4)))
   {
      iEncoderCounter++;
   } 
  else 
   {
      iEncoderCounter--;
   }

or

 if ((PIND & B00000100) == (PIND & B00001000))
   {
      iEncoderCounter++;
   } 
  else 
   {
      iEncoderCounter--;
   }

What am I doing wrong here, logically all the bitmath makes sense to me so why is it breaking my code when Iuse it and not bitRead??

try to put

if (bitRead(PIND, 3) >= (bitRead(PIND, 4)) {
(iEncoderCounter, HIGH)
}
else {
(iEncoderCounter, LOW)
}
and if it didn't work with you…
i can't give you more help :~

rwgast:
Im trying to compare two pin inputs using port manipulation, this code works like it should,

 if (bitRead(PIND, 3) == bitRead(PIND, 4))

{
      iEncoderCounter++;
   }
  else
   {
      iEncoderCounter--;
   }




Ive read about 15 different articles and books, trying to figure out bit math and how to write the above code without using bitRead, none of my code using bit masking works



if ((PIND & (1<<3)) == (PIND & (1<<4)))
   {
      iEncoderCounter++;
   }
  else
   {
      iEncoderCounter--;
   }

One problem with that. The first AND operation will either return 0 or 0b1000 and the second AND operation will either return 0 or 0b10000. 0b1000 != 0b10000. You would need to use bitwise AND (like you have) to get either a false (zero) or a true (not-zero) and then a boolean XNOR (or is that NXOR?). Negated exclusive or will return true only when the operands are either both true or both false (which follows the logic of the bit you are trying to emulate). I don't know the C++ syntax for XNOR.

I suppose you could do (((PIND & (1<<3))>>3) == ((PIND & (1<<4))>>4)) or (((PIND & (1<<3)) && 1) == ((PIND & (1<<4)) && 1)), but both seem a bit kludgy. Though... bitRead() might actually be doing the second suggestion there... I'm too lazy to look up bitRead() in the header now (I think it is in Arduino.h). I did a few weeks ago and saw that it was a #define macro (read: pre-compilation source code substitution) and did it's magic with shifting, but I don't recall the details now.

rwgast:
or

 if ((PIND & B00000100) == (PIND & B00001000))

{
      iEncoderCounter++;
   }
  else
   {
      iEncoderCounter--;
   }

Two issues here. The first issue is the same as the one above. But the other issue here is both shifting and bitRead() (like arrays) start indexing with zero. Bit location 0 is 0b00000001, bit location 1 is 0b00000010, etc.

rwgast:
What am I doing wrong here, logically all the bitmath makes sense to me so why is it breaking my code when Iuse it and not bitRead??

Clear as mud? :wink:

Try:

 if ( (PIND && (1<<3) ) && ( PIND && (1<<4) )  
   {
      iEncoderCounter++;
   } 
  else 
   {
      iEncoderCounter--;
   }

I bet you are wondering why.

Well,
( PIND & ( 1 << 3 ) will return 0 or 8
( PIND & ( 1 << 4 ) will return 0 or 16
Any of ( 8 == 0), (16 == 0), (8 == 16) will always return false

( PIND && ( 1 << 3 ) ) will return true or false
( PIND && ( 1 << 4 ) ) will return true or false
false && false == false
true && false == false
false && true == false
true && true == true

Oh, and as Sembazuru pointed out, remember that the lowest order bit is 0

lar3ry:
Try:

 if ( (PIND && (1<<3) ) && ( PIND && (1<<4) )  

{
     iEncoderCounter++;
  }
 else
  {
     iEncoderCounter--;
  }



I bet you are wondering why.

Well,
( PIND & ( 1 << 3 ) will return 0 or 8
( PIND & ( 1 << 4 ) will return 0 or 16
Any of ( 8 == 0), (16 == 0), (8 == 16) will always return false

( PIND && ( 1 << 3 ) ) will return true or false
( PIND && ( 1 << 4 ) ) will return true or false
false && false == false
true && false == false
false && true == false
true && true == true

Oh, and as **Sembazuru** pointed out, remember that the lowest order bit is 0

No. Think about it.

 if ( (PIND & (1<<3) ) && ( PIND & (1<<4) )

my proposal, make it more explicit. Now there are two real bool expressions instead of bytes interpreted as bools.

  if ( ((PIND & (1<<3)) == (1<<3) )   ==     (( PIND & (1<<4)) == (1<<4))

other posibility

  byte x = (PIND >> 3) & 0x03;    // separate the two bits
  if (x == 0x00 || x == 0x03) ...// check two valid values

updated typo

Another way (done in boolean for clarity)...

if ((PIND && B00001100) == (B00001100))

what is the exact requirement?

if (the 2 bits are equal)
or
if (the 2 bits are both 1)

Riva:
Another way (done in boolean for clarity)...

if ((PIND && B00001100) == (B00001100))

Really? After the posts above you... (Hint: the condition will never be true.)

The way to test bits for equality is XOR:

  byte port = PIND & 0x18 ; //read just the two bits of interest, simultaneously
  port ^= (port >> 1) ; // XOR them together
  if ((port & 0x08) == 0)  // test the relevant bit
  {
    ..

Or if you want to compare disparate bits without shifting and combining:

  if (((PIND & 0x08) == 0) == ((PIND & 0x10) == 0)))

But that reads PIND twice so its not simultaneous, should that matter

The joys of cut and paste & poor C++ skills. I can visualize in assembler but failed to properly convert to C++. Hopefully correct this time unless PIND needs to be copied into a register first.

if ((PIND & B00001100) == B00001100)

AWOL:
No. Think about it.

 if ( (PIND & (1<<3) ) && ( PIND & (1<<4) )

Arrgh! I had initially written it this way, then somehow convinced myself that I needed the extra &&s.

MarkT:
But that reads PIND twice so its not simultaneous, should that matter

very good argument
+1

robtillaart:
what is the exact requirement?

if (the 2 bits are equal)
or
if (the 2 bits are both 1)

This is a very relevant question that has yet to be answered by the OP. His first example that he was trying to replicate is the "if (the 2 bits are equal)" logic. Which is why I replied the way I did with trying get the effect of a negated exclusive or for the logical operator since C++ doesn't seem to have an XOR logical operator. But, not sure if that is really what he wants.

Most of the responses here are assuming the desired test is "if (the 2 bits are both 1)". Very subtle (but important) distinction.

I wonder if an explicit cast to datatype boolean would work for the "if (the 2 bids are equal)" logic. For example, would (((boolean)(x & (1<<3))) == ((boolean)(x & (1<<4)))) evaluate to true if both either x == 0b00011000 or x == 0b00000000? (Argh... parentheses counting is tedious without IDE help... I think I have it right...)

Sembazuru:

robtillaart:
what is the exact requirement?

if (the 2 bits are equal)
or
if (the 2 bits are both 1)

This is a very relevant question that has yet to be answered by the OP. His first example that he was trying to replicate is the "if (the 2 bits are equal)" logic. Which is why I replied the way I did with trying get the effect of a negated exclusive or for the logical operator since C++ doesn't seem to have an XOR logical operator. But, not sure if that is really what he wants.

Most of the responses here are assuming the desired test is "if (the 2 bits are both 1)". Very subtle (but important) distinction.

I wonder if an explicit cast to datatype boolean would work for the "if (the 2 bids are equal)" logic. For example, would (((boolean)(x & (1<<3))) == ((boolean)(x & (1<<4)))) evaluate to true if both either x == 0b00011000 or x == 0b00000000? (Argh... parentheses counting is tedious without IDE help... I think I have it right...)

What's the point of the boolean casts?

AWOL:

Sembazuru:
<... trim ...>

I wonder if an explicit cast to datatype boolean would work for the "if (the 2 bids are equal)" logic. For example, would (((boolean)(x & (1<<3))) == ((boolean)(x & (1<<4)))) evaluate to true if both either x == 0b00011000 or x == 0b00000000? (Argh... parentheses counting is tedious without IDE help... I think I have it right...)

What's the point of the boolean casts?

An attempt to convert a numeric value to a boolean true/false. In my first response to this thread I essentially did the same thing by (bitmask result) && 1, but thought that if casting to a boolean datatype did the same thing that the cast might result in better self-documenting code. Then again, bringing in the definition of "better" to the debate is just asking for a holy war... :wink:

An attempt to convert a numeric value to a boolean true/false.

In C, just about anything is a boolean - no attempt/conversion necessary.

AWOL:

An attempt to convert a numeric value to a boolean true/false.

In C, just about anything is a boolean - no attempt/conversion necessary.

Well, also in C 8 == true, 16 == true, and true == true. But 8 != 16 and the exercise seems to want to get this truth table:

[u]x | y  | result[/u]
0 | 0  | true
8 | 0  | false
0 | 16 | false
8 | 16 | true

So my (completely untested) thought experiment was to suggest (boolan)x == (boolean)y instead of (x && 1) == (y && 1) thinking (possibly erroneously) that the boolean cast would be more clearly show of the intent of the algorithm no matter the actual implementation by the compiler.

Well, also in C 8 == true, 16 == true, and true == true.

Strictly speaking, 8 is not false, and 16 is not false.
So I think de Morgan says that
!false == !false
So, all's right with the world

AWOL:

Well, also in C 8 == true, 16 == true, and true == true.

Strictly speaking, 8 is not false, and 16 is not false.
So I think de Morgan says that
!false == !false
So, all's right with the world

I'm starting to think we are getting a bit off topic here... But I'll bite.

One (well, at least I, so it might just be my problem) normally expects the == logical operator to follow the transitive law of logic and mathematics. Normally if a == b and b == c then a == c when following the transitive law. But when working with the concept of false and !false (instead of true for accuracy) in C we start traipsing into the land of intransitivity. So, if a is in the set of !false and b is in the set of !false we can't assume that a == b just because they both reside in the same set.

The exercise here is to try to force an intransitive relation into a transitive relation because there is no XOR logical operator in C that I can find (granted, I only went as far as checking on cplusplus.com).