Today I’d like to go into bit manipulation, ehm, *a bit*…

You need bit manipulation when you’re dealing with the individual bits in a byte, such as on the I/O ports of an ATmega, for example.

First the *easy* approach – use these predefined macros from the Arduino library:

**bit(N)**returns an integer with the N’th bit set to 1**bitRead(X,N)**– returns the N-th bit of X as 0 or 1**bitWrite(X,N,B)**– sets Nth bit of X to B (0 or 1)**bitSet(X,N)**– sets the Nth bit of X to 1**bitClear(X,N)**– sets the Nth bit of X to 0

This is why you might see code such as the following:

```
bitSet(WDTCSR, WDIE);
```

This means: “set the Watchdog Interrupt Enable to 1 in the Watchdog Timer Control Register”. The WDTCSR and WDIE terms are predefined constants. WDIE is 6, for example.

Note that some of these routines can be written in terms of the others, i.e.

- bitSet(X,N)
*is the same as*bitWrite(X,N,1) - bitClear(X,N)
*is the same as*bitWrite(X,N,0)

*But what does it all mean?*

Well, let’s dive in. First make sure that you are comfortable with “bit shifting”. The expression “bit(3)” is the same as “1 << 3”, which in turn is the same as doubling the value 1 three times, i.e. the value *eight*. So “bit(0)” is 1 doubled zero times (i.e. 1) and “bit(7)” is 1 doubled 7 times, i.e. 128. Bytes have 8 bits numbered 0 to 7, so all you need for (byte-sized) hardware registers is to remember that bits 0..7 map to (specific!) integers with values 1 to 128.

Setting a bit, is like *OR-ing* the bit with the rest of the value. The following statements are all identical:

```
WDTCSR = WDTCSR | bit(WDIE);
WDTCSR = WDTCSR | (1 << WDIE);
WDTCSR = WDTCSR | (1 << 6);
WDTCSR = WDTCSR | 0b1000000;
WDTCSR = WDTCSR | 0x40;
WDTCSR = WDTCSR | 64;
```

This, in turn, can be abbreviated in C as:

```
WDTCSR |= bit(WDIE);
WDTCSR |= (1 << WDIE);
WDTCSR |= (1 << 6);
etc...
```

Or you could write:

```
bitSet(WDTCSR, WDIE);
```

It’s all the same. So *OR-ing* is about *setting* bits (to 1).

Likewise, *AND-ing* is about *not clearing* bits (to 0). Whoa, that’s confusing. This expression returns a value which is what X was, but *only* for bit N:

```
X & bit(N);
```

So this will change X to a value with all bits *except* bit N set to zero:

```
X = X & bit(N);
```

To put it differently: X will lose its original bits, except bit N, which will be left alone. All the bits are set to zero, *except* bit N.

Usually, you want the opposite, setting *only* bit N to zero. That too is accomplished with *AND-ing*, but you have to flip all the 0’s to 1 and all the 1’s to 0 first. Hang in there, it’s a slightly longer story. This sets bit N to zero:

```
X = X & ~ bit(N);
```

Let’s examine what’s going on here. First, “bit(N)” is a value with *only* the Nth bit set. Now, “~ bit(N)” is a value with all the bits flipped around (“~” is called the *complement* operator in C), so that’s a value with all *but* the Nth bit set. Everything is 1, but bit N is 0.

Now we can tackle the expression “X & ~ bit(N)”. Since *AND-ing* is about “not clearing bits”, that means that the result of this expression is all the bits of X unchanged where “~ bit(N)” was one, which is almost everywhere. The only bit that differs is bit N – it is zero in “~ bit(N)”, therefore that particular bit will “not not clear …” (a double negation!): it *will* be cleared (to 0) in the result.

Finally, we replace X by that result. So X will change in precisely one bit: bit N. That bit will be cleared to zero, the rest is not affected. In short: we’ve cleared bit N.

*Confused?*

Well, that’s why the bit/bitSet/etc macro definitions were introduced. These expressions are all identical:

```
X = X & ~ bit(N);
X = X & ~ (1 << N);
if (X & bit(N)) X = X - bit(N);
bitClear(X, N);
```

That last one is clearest by far, because it conveys the actual operation with a well-chosen name: clear bit N, leave the rest alone.

*So why would anyone ever choose to use anything but the bit/bitRead/etc routines?*

Many reasons. Habit, perhaps. Coming from another environment which doesn’t have these macros. Being so used to this bit-manipulation that the use of words doesn’t really look any clearer. Whatever…

But another more important reason is that you can’t do everything with these bit/bitSet/bitClear routines. Sometimes you just have to go to the raw code. Such as when you need to set multiple bits at once, or flip bits. That’s why the ATmega datasheet has examples like these:

```
WDTCSR |= (1<<WDCE) | (1<<WDE);
```

By now, you should be able to decode such a statement. It’s the same as:

```
WDTCSR |= bit(WDCE) | bit(WDE);
```

In other words:

```
WDTCSR = WDTCSR | bit(WDCE) | bit(WDE);
```

Which in turn is *almost* the same as these two statements together:

```
WDTCSR |= bit(WDCE);
WDTCSR |= bit(WDE);
```

That in turn, can be written as these two lines:

```
bitSet(WDTCSR, WDCE);
bitSet(WDTCSR, WDE);
```

Much clearer, right? Except… *it’s not 100% identical!*

The problem is a hardware issue: timing. The above two statements will set both bits, but *not at the same time!* For hardware register settings, that difference can be important. There is a fraction of a microsecond between the WDCE bit being set and the WDE bit being set. Unfortunately, in some cases that causes real problems – your code won’t work as expected.

Tomorrow, I’ll continue on this topic, but it’ll be a bit more fun, because there will be *LEDs* involved!

*(Please ignore the cable on the left, I snatched the above picture from this post)*

**Update** – see this excellent Wikipedia article for more details about bitwise operations.

Good article JCW! Things might get even more clear if you would show what happens to the actual bits when using a bitwise operation on it.

26 August 2010at2pmAh – good point. But I’ll leave that to this inimitable Wikipedia article.

26 August 2010at4pm