Go Down

Topic: working with bitwise (Read 1 time) previous topic - next topic

Wazzled

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

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

Coding Badly


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.

Morris Dovey

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

Code: [Select]
   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.
There's always a better way!

Wazzled

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?

Morris Dovey

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

Code: [Select]
     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.
There's always a better way!

Go Up