working with bitwise

Hi, in a reply by Nick Gammon on this thread http://arduino.cc/forum/index.php/topic,100085.0.html he uses

void showbin (const byte c)
  {
  for (int i = 7; i >= 0; i--)
    Serial.write ((c >> i) & 1 | '0');
  Serial.println ();
  }

could someone please explain what exactly is happening bitwise in the call to Serial.write?

Thanks

Assume c is 1001 0010 in binary. The first pass through the for-loop...

i =7

((c >> i) & 1 | '0') --> The zero character ('0') can also be interpreted as the byte value 0x30 or a bit value of 00110000. I'll use the bit value until the end.

((10010010 >> 7) & 1 | 00110000) --> The double greater-than is a bit shift to the right. The bits in c are shifted 7 bits to the right. We're left with the left-most bit...

((00000001) & 1 | 00110000) --> The ampersand is a bitwise-and. If both bits are one the result is one otherwise the result is zero...

(00000001 | 00110000) --> The bar is a bitwise-or. If either bit is a one the result is one otherwise the result is zero...

00110001 --> Which is also 0x31. Which is also '1'. The character '1' is sent to the serial port.

i = 6

((c >> i) & 1 | '0')

((10010010 >> 6) & 1 | 00110000)

((00000010) & 1 | 00110000)

(00000000 | 00110000)

00110000 --> Which is also 0x30. Which is also '0'. The character '0' is sent to the serial port.

i = 0

((c >> i) & 1 | '0')

((10010010 >> 0) & 1 | 00110000) --> Shifting by zero bits results in the same value...

((10010010) & 1 | 00110000)

(00000000 | 00110000)

00110000 --> Which is also 0x30. Which is also '0'. The character '0' is sent to the serial port.

Sure - I'm going to make more variables to make it easy to follow:

   unsigned char a = c >> i;   // moves the bit of interest into the rightmost position
   unsigned char b = a & 1;    // resets all bits except the rightmost
   unsigned char d = b | '0';  // converts the value (0 or 1) to a character '0' or '1'
   Serial.write(d);            // writes the character to the Serial connection

Nick's way of writing this avoids the need for the intermediate variables.

I can see whats happening in most of it now but still not sure what bits are being compared by:

((00000001) & 1 | 00110000)

The OR operation seems to be the last performed so ignoring that leaves 00000001 & 1

how does that reset all the bits except the rightmost?

The AND operation (&) result one only when both operands are 1, and zero otherwise:

     XXXXXXXM
   & 00000001
     --------
     0000000M

so that whatever M is (0 or 1) in the first operand, it will appear in the same position in the result, and all other bits of the result will be zeros.

Sorry for not getting this but what is the second operand?

I get one of them is 00000001 that we got from the bitwise right shift, but what are we comparing this too for the AND. Why is the other side of the AND a 1, im expecting that to be another byte.

EDIT: Wow it's 04:10 maybe thats the problem lol.

what are we comparing this too for the AND

There is no compairing going on, these are digital logical operations on the bit level. You are ANDing the value on the right with the result of what has been evaluated to the left of it.

LOL Nick must be working up to the IOCCC.

I might have used Serial.println(c, BIN);

Actually I think it is a very good exercise, though! XD

How can we do an AND without comparing two bit patterns?

11001100 & 01010101 = 01000100 comparing both bit patterns and if its a 1 in both its a 1 in the result.

The AND operand is use to isolate a bit or multiple bits. A useful technique.

11001100 & 01010101 = 01000100 comparing both bit patterns and if its a 1 in both its a 1 in the result.

Here you trying to do : 1100 1100 AND Gate & 0101 0101 A B Out


0100 0100 0 0 0 0 1 0 1 0 0 1 1 1

Now Let OR : 1100 1100 OR Gate | 0101 0101 A B Out


1101 1101 0 0 0 0 1 1 1 0 1 1 1 1

AND will isolate the bits you want. And OR simply "placed" the bits.

How can we do an AND without comparing two bit patterns

We do not compair the bit patterns we perform a function with them. You do not say a subtraction is a result of compairing two bit patterns.

In computing terms a compair is an operation that involves subtracting two values and doing nothing with the result but leaving the status register bit flags to reflect the result. In C this is done by the == operation

Ok so, I think I've been getting the binary wrong. I thought binary went from left to right like

1 2 4 8 16 32 64 128 I'm now thinking this is wrong and its right to left.

If its right to left, that means to keep say the second and sixth(left to right) bit in the following I would AND it with 68

0*111 01*11 & 68 0100 0100

please let that be right

I thought binary went from left to right like

No, like decimal and hexadecimal, the powers of the base decrease left to right.

So does that mean my above example is right?

No - powers increase from right to left:

27+26+25+24+23+22+21+20

For a typical number : 123 567 123

How do you read it ? The same goes for a binary number or Hex number

0100 0111 1100 ED34 8905 FABC

So binary goes: 128 64 32 16 8 4 2 1

That gives decimal 119 a binary value of 0111 0111. To isolate the two right-most bits I would AND with decimal 3 which has a binary value of 0000 0011

Example 1. 0111 0111 & 3 results in 0000 0011

Example 2. 0101 1101 & 3 results in 0000 0001

Yes that is right. :)

Thank goodness for that, bet your all happy now lol. If I wasnt so short on money, I'd paypal all that helped a beer.

:)

Thank goodness for that, bet your all happy now lol. If I wasnt so short on money, I'd paypal all that helped a beer.

Why don't you raise a glass to everyone who helped - then you'll really be Wazzled. :grin: