Bit Twiddling - The Basics - Make: AVR Programming (2014)

Make: AVR Programming (2014)

Part I. The Basics

Chapter 4. Bit Twiddling

Cylon Eyes and More

In this chapter we’ll make a cylon-eye-type LED back-and-forth scanner. Everyone needs one. Scanning lights were the only thing, besides maybe menace, that gave the cylons their personality. Would KITT have been half as useful to David Hasselhoff without his scrolling red lights? I think not. And now you can build your very own.

But I won’t lie to you. We’re building cylon eyes in order to learn a fundamental concept in microcontroller-specific programming: how to flip individual bits on and off inside a hardware register. And while that may not sound sexy, you’ll be using the ideas from this chapter in every AVR or microcontroller project you ever make from here on out. Flipping bits is just that important in embedded devices.

If you don’t believe me yet, think back on how we turned on LED3. We wrote something like:

PORTB = 0b00001000;

And that worked, as long as we knew for sure that we wanted all of the other LEDs turned off. But what if you need to turn on or off a particular LED without disturbing any of the others? Bitwise logical operations—“bit twiddling”—lets us modify any one bit out of the register byte without having to think explicitly about the others. Because we’ll be setting bits in registers to configure nearly every aspect of the AVR hardware, we’ll get a lot of mileage out of this investment.

WHAT YOU NEED

In this chapter, in addition to the basic kit, you will need:

§ The eight LEDs and their resistors that you hooked up in Chapter 3.

§ That’s it. Well, it wouldn’t hurt to have your thinking cap on, because we’re going to be using a bunch of bitwise binary logic.

Because this chapter is mostly theory, let’s get the project up and running so you have something pretty to look at. Assuming that you still have all the LEDs hooked up as in Chapter 3, all you have to do is enter the cylonEyes directory, open up cylonEyes.c in your editor, and run make to compile the firmware and upload it to the chip.

If you have trouble uploading the program to the chip, please double-check the ISP connectors according to Figure 3-4 and make sure you’ve got the MOSFET set up right. If in doubt about the MOSFET part of the circuit, go back to the wire between the top ground rail to the bottom ground rail to double-check that’s the problem.

Working Through the Code: Cylon Eyes

You got it running? Great! Now let’s look at the code in Example 4-1 and see what makes it tick. Essentially, it’s the same as with the one-LED blinker code, only instead of switching on and off only one of the bits in the PORTB register, we can toggle eight of them.

Example 4-1. cylonEyes.c listing

/* Cylon Eyes */

// ------- Preamble -------- //

#include <avr/io.h> /* Defines pins, ports, etc */

#include <util/delay.h> /* Functions to waste time */

#define DELAYTIME 85 /* milliseconds */

#define LED_PORT PORTB

#define LED_PIN PINB

#define LED_DDR DDRB

int main(void) {

// -------- Inits --------- //

uint8_t i;

LED_DDR = 0xff; /* Data Direction Register B:

all set up for output */

// ------ Event loop ------ //

while (1) {

while (i < 7) {

LED_PORT = (1 << i); /* illuminate only i'th pin */

_delay_ms(DELAYTIME); /* wait */

i = i + 1; /* move to the next LED */

}

while (i > 0) {

LED_PORT = (1 << i); /* illuminate only i'th pin */

_delay_ms(DELAYTIME); /* wait */

i = i - 1; /* move to the previous LED */

}

} /* End event loop */

return (0);

}

You should recognize the general form of the code from blinkLED.c. In fact, the only big differences are that we have loops inside our event loop, and we have the cryptic PORTB = (1 << i); statement—our first introduction to bit twiddling! Before we get on to the main course, though, I’ll introduce our first #define statement (C Asides: #defines). Feel free to skim through if you’re already comfortable with C.

C ASIDES: #DEFINES

#define statements improve code readability and portability by defining human-friendly synonyms for constants or code fragments. For instance, in a setup with only one LED like our blinkLED.c, I’ll usually define LED as a synonym for a particular pin on the AVR (PB0) partly to remind myself how to hook up the circuit, but also partly to make it easy to change later.

For instance, if you were reproducing the blinkLED.c code, but you’d like to physically wire the LED to pin PB5, you could go through the code and change every occurrence of PB0 to PB5. If instead, as here, you define the LED pin at the top of the code, something like #define LED PB0 and then consistently only use LED in the main body, you’ll only have to change PB0 to PB5 in the one place where it’s defined, right up at the top of your code or in a suitably named include file. Defining your hardware layout makes it easier to modify later, and makes your code easier to read. (What was hooked up to PB0 again?)

Definitions are handled by the preprocessor, which goes through your code and essentially does a search-and-replace for all your defines before handing the result off to the compiler. Because #define statements are simple substitutions made by the preprocessor, they’re not variables, take up no memory in the AVR, and can’t be changed from within your code. To keep from forgetting their special nature, the names of defines are usually written in ALL_CAPS_SEPARATED_WITH_UNDERSCORES. This makes defines stand out in your code, and reminds you that they’re constants.

In addition to user-defined defines, if you look in the avr/io.h file that we include in all our example codes, you’ll find that there’s a #define for every hardware register that’s listed in the datasheet. These definitions point in turn to the correct memory locations of the AVR’s hardware registers.

This is a more general pattern in AVR C: a lot of the low-level details of the layout and configuration of the chip (like what locations in memory are hardware registers) are provided for you in #define statements, and the names are a vaguely helpful mnemonic for something that’s written in the datasheet.

For now, you can think of defines as handy shortcuts for keeping track of values that you might later like to change or would like to make more clear. Using defines for pin-layouts also makes your code flexible across different hardware setups, and helps remind you later which pin your accelerometer was hooked up to. Good use of defines is a good practice.

Bit Twiddling and Cylon Eyes

Looking back briefly at how we implemented blinkLED.c and even povToy.c, you’ll see that the code turns on and off the bit that controls our LED quite directly: PORTB = 0b0000001;. We could make a cylon eyes animation in the same way. To make the traditional back-and-forth scanner, we hook up eight LEDs to the same port, and light them up one at a time, moving from right to left and left to right. Our naive code might look something like this:

DDRB = 0b11111111; // enable all pins for output

while(1){

PORTB = 0b00000001; // set the 0th pin in PORT B high

_delay_ms(100);

PORTB = 0b00000010; // set the 1st pin in PORT B high

_delay_ms(100);

PORTB = 0b00000100; // set the 2nd pin in PORT B high

(etc.)

...

}

As you can see, that’s going to involve a lot of typing, and in the end the code is going to be difficult to maintain, tweak, and extend. So we’re going to need a better way. Enter bit twiddling! The C programming language allows the user to access bits individually, and the AVR libc (the microcontroller-specific library routines) helps even more, but it’s going to take a little getting used to.

Bit Shifting

Wouldn’t it be nice, instead of having to write out 0b00001000, if we could just say “give me a number with a 1 in bit number three”? (If you thought that one was in bit number four, see Bits, Numbering, and Significance.) That way we could code our cylon eyes by incrementing or decrementing a variable and then putting a 1 in the corresponding bit’s place.

It turns out that the technique known as bit shifting will do exactly that for us. You’re going to be surprised at how often we use bit shifting in microprocessor-style C code.

BITS, NUMBERING, AND SIGNIFICANCE

A byte is made up of eight bits, and the AVR chip organizes its pins for purposes of input and output in banks of eight. Coincidence? Not at all! It makes our lives easier.

But something that unsettles newcomers to C is its zero-indexing convention. That is, when you count in C you don’t start counting with 1, but with 0. Counting eight elements looks like this: 0,1,2,3,4,5,6,7.

That’s why, when we hook up eight LEDs to our AVR chip, you’re going to have to think of the first one as “LED Number Zero” in your head. And the AVR chip designers are in on the zero-indexed conspiracy as well. Our first LED will be hooked up to pin PB0. The eighth LED, which I want you to call “LED7,” connects to PB7. If you think of it any other way, you’ll get confused.

Zero-indexing is natural if you think of everything in terms of a base location and an offset, which is why it’s done in C. If the hardware register for Port B is at a given location in memory (byte number five in the mega168, as it turns out), then the location of the first pin is at byte five plus zero bits. The second pin (PB1) is located at byte five plus one bit, etc.

If you can just remember to think of the first LED as “LED Number Zero” or “The LED at PORTB + 0” then you’re on your way. You’ll also see how this fits naturally with the way we’re going to access single bits through bit shifting later on.

We’ll be representing numbers in binary in most-significant-bit-first order. Now this isn’t strange: when you say “three hundred and twenty one”, you’re also working in most-significant-bit-first order, right? But it can sometimes be confusing for people to see the first bit, bit 0, all the way on the far right of the number, rather than right up front. Just remember that it represents a number, and we usually write numbers with the most-important digits up front. 321 is 3 × 102 + 2 × 101 + 1 × 100, just like 0b11001 is 1 × 24 + 1 × 23 + 1 × 20.

So when you look at a port of eight pins in the datasheet, or when you write to the hardware register, you’ll want to remember which end is which. And when you’re naming your eight LEDs as they’re laid out in a row, to avoid confusion you’re going to want to call them LED7, LED6, LED5, …, LED0, with LED7 on the left side and LED0 on the right (see below).

Bit shifts have the effect of rolling all the bits’ n positions to the left or right, depending on your command. Bits that fall off either end just disappear, and any new bits added are all zeros. The C language instruction for shifting all the bits in a number to the left or right is << or >>, respectively. Now let’s see how they’re used.

image with no caption

Bit shift examples:

0b00001110 >> 3

= 0b00000001 (Three new zeros were added to the left,

and the bits on the right just rolled off the edge.)

0b00001110 << 2

= 0b00111000 (Two new bits, both zeros, are rolled in from the right.)

What this means to you as a programmer is that if you want a single 1 bit in position number three, say, you can start off with the number that has a 1 bit in position zero, and roll it to the left three spaces.

The bit-shift roll:

1 = 0b00000001

(1 << 0) = 0b00000001

(1 << 1) = 0b00000010

...

(1 << 3) = 0b00001000

...

(1 << 7) = 0b10000000

Take a minute to make sure you’ve got the logic of the bit-shift roll down. It’s a standard idiom in microcontroller coding, and you’ll be using it in nearly every program you write. Any time you want to set the nth bit to a 1, you’ll shift the value 1 over to the left n times.

Now you’re starting to see how the cylon eyes work: start off with the number 1, roll the bit one position, and then write that to an output hardware register, rinse, and repeat. Shift bits left until you end up at LED7, then switch to shifting bits right until you hit LED0.

So before we leave this section, let’s recap the meat of the cylon eyes code. Make sure that it makes sense to you, because we’ll be using the bit-shift roll extensively from here on out:

while(i < 7){

LED_PORT = (1 << i); /* illuminate only i'th pin */

_delay_ms(DELAYTIME); /* wait */

i = i + 1; /* increase shift amount */

}

while(i > 0){

LED_PORT = (1 << i); /* illuminate only i'th pin */

_delay_ms(DELAYTIME); /* wait */

i = i - 1; /* decrease shift amount */

}

There are two while loops, driving the variable i up to seven and back down to zero. Inside each loop there is a delay, which is fairly self-explanatory. All the action that matters is in the LED_PORT = (1 << i); command. We want a binary number with a 1 in theith place, which will turn on only the ith LED in our series. We implement it by starting with a 1 in the zeroth position and rolling it over i times to the left.

Advanced Bit Twiddling: Above and Beyond Cylon Eyes

So that’s all there is to making cylon eyes: just shifting a bit to the left or right as appropriate, and waiting. But what if we wanted to make an even more interesting pattern? Multiple lights on at once? Or random toggling? Or maybe we just need to control one bit out of a byte, without changing any of the others.

The serious limitation in the preceding code is that each time through the while() loop, we’re writing a whole byte to the LED port. This works in cylon eyes because we know that we’d only like one LED on at a time. But what about the case where we’ve already got a few LEDs lit up, and we’d like to add another? Say just LED1? If we wrote LED_PORT = (1<<1);, we’d turn on LED1 all right, but in the process, we’ll have turned off all the rest.

In this section, we’re going to learn some essential bit-twiddling techniques that will allow us to manipulate single bits easily without clobbering the rest of the contents of the register. Think of each byte in the AVR’s hardware registers as being a row of eight little switches; in this section, we’re going to use bitwise logic functions to set or toggle each switch individually without modifying the rest.

THE _BV() MACRO

Bit shifting is so common in AVR programming that there’s even a macro defined that gets included with io.h: it’s called _BV() and stands for “bit value.”

Before 2006, this macro used to be called BV(), and it used to be used quite commonly. Sometime around 2007, it got renamed to _BV(), where the underscore indicates that it’s intended for internal use within the avr-libc libraries, because it isn’t part of official Standard C.

The _BV() macro is just our bit-shift roll in disguise. In fact, it’s even defined as:

`#define _BV(bit) (1 << (bit))`

So should you use _BV(2) or (1 << 2)? Well, they end up being exactly the same thing once the preprocessor has done its text replacing, so it’s just a matter of style. You’ll definitely see code written both ways, so I want you to be able to read both.

There are a couple of arguments for the use of _BV(). If you saw (1 << 2) and were new to microcontroller programming, you might have to think for a while about what the purpose of the “1” was—is it a numerical value to be treated like a number, or is it just the simplest way of representing a 1 in a single bit? So the first argument for _BV()is that it does read a little more clearly in code. On the other hand, the bit-shift roll is so common in microcontroller C and assembly code that the _BV() doesn’t really gain much in readability after you’ve been at it a few months.

Secondly, many old AVR programmers are used to having the macro around, and they wrote a bunch of code with BV() in it, and it’s trivial to find-replace all their code to read _BV()—people also use _BV() because they’re used to it.

The arguments against _BV() basically boil down to it not being Standard C. If you want to compile your code on some other platform to test it out, for instance, it probably won’t have the _BV() macro already defined.

So what if you like the clarity of BV() as a macro, but also want to keep your code maximally portable? Define BV() yourself! It’s easy and hardly costs anything. If you define it yourself in your code, you won’t have to worry about your code being portable, because it’ll be right there. In the sidebar Bit Twiddling for the Impatient, I’ve listed an example with a bunch of bit-shifting macros that I routinely include in my own code.

In the interest of teaching you standard microcontroller-style C I’ll use (1 << 3) in the code most of the time. If you can read code written this way, you can read anything; this idiom is used across microcontroller families and compilers. But in your own code, feel free to use the built-in _BV() macro, or better still, define your own.

Even if you’ve programmed C since you were seven years old, it’s quite possible that you haven’t spent much time on bit-level manipulations. If you’ve ever learned a little bit about logic, digital or otherwise, the bitwise operators will seem familiar to you, but the context may be brand new. For some of you, this is all going to be brand new. Hold on to your hats.

Bitwise logical operators take full bytes as their input. They do logical operations on those bytes one bit at a time, hence the name. This makes the bitwise operators an absolutely perfect match for manipulating the individual bits inside a register byte.

To give you a bit of the flavor, the bitwise operator NOT takes each bit in the byte and toggles, or flips, it. A 1 becomes a 0, and a 0 becomes a 1: 10001110 turns into 01110001. The operation happens all at once inside the AVR chip, but you can think of it as reading bit 0 and then writing the logical opposite to bit 0 of the result byte. This same operation repeats seven more times, bitwise, for each bit in the byte.

There are four bitwise logical operators in total, so let’s work through each with an example. I find it helpful to think of the two input bytes stacked on top of each other so that the bits being compared are aligned vertically. Work through the following sidebar and make sure that you see how the logical operation is being applied, bitwise down the columns, to get the final result.

BITWISE LOGICAL OPERATORS

OR (|)

For each bit position, a bitwise OR returns 1 if either bit in the comparison is 1. OR returns a 1 if this bit is 1 or that bit is 1. OR returns 0 only when both bits are 0:

1010

| 1100

= 1110

AND (&)

Bitwise AND compares two bits and returns 1 only if both of the bits are 1. If either of the bits are 0, AND returns 0:

1010

& 1100

= 1000

XOR (^)

XOR (or “exclusive or”) returns 1 if only one of the two bits compared is a 1. If both bits are 1 or if both bits are 0, XOR returns 0:

1010

^ 1100

= 0110

NOT (~)

NOT takes all the bits and flips their logical sense—each 1 becomes a 0 and each 0 becomes a 1. It’s also the only logical operator that takes only one input:

~ 1100

= 0011

Bitwise logic definitions are all well and good, and you may have seen all this already. It’s how bitwise logic is used in microcontroller coding that’s interesting, especially when combined with the side effects of setting, clearing, and testing bits in hardware registers. In short, we care about twiddling bits inside bytes a lot more in AVR programming than in most other computer programming, because bitwise logic allows us to configure the AVR’s internal hardware and to read and write from and to individual pins.

STUPID BITWISE TRICKS

As a quick demo of the utility of bitwise logical operators, you can convert the Cylon Eyes demo into Inverse-Video Cylon Eyes with the NOT operator. Just replace each:

LED_PORT = (1 << i);

with:

LED_PORT = ~(1 << i);

Every LED that was previously on will be off, and vice versa.

For a different display that uses tools you’ll learn in the remainder of this section, change the first LED_PORT line into LED_PORT |= (1 << i); and the second into LED_PORT &= ~(1 << i); See what you get!

So let’s get down to the business at hand: manipulating individual bits within a byte. For concreteness, take the eight LEDs and suppose that we already have a few LEDs lit: LEDs zero, one, six, and seven. If we looked at the value currently stored in PORTB, it would read 0b11000011. Now say we want to turn on and off LED2 without changing the states of any of the other LEDs. Or maybe we want to turn on or off LEDs two and four at the same time. How can we do this?

Setting Bits with OR

For our first trick, let’s learn how to set an individual bit in a register, leaving all the other bits as they were. Thinking back on the bitwise logical operators, let’s revisit the way the OR operator works. In particular, let’s think about ORing some bit with either a fixed 0 or a fixed 1.

Consider ORing a bit with zero. If you OR a 1 with a 0, the result is 1. If you OR a 0 with a 0, the result is 0. That is, ORing a bit with 0 doesn’t change the initial logical bit at all. But ORing with a 1 always yields a 1. This behavior lays the groundwork for using OR to turn bits on using bitmasks:

OR with 0:

0 | 0 -> 0

1 | 0 -> 1

OR with 1:

0 | 1 -> 1

1 | 1 -> 1

A bitmask is just a normal old byte, but we’re thinking of it as being made up of ones and zeros in particular places that we specify rather than representing a numerical value. We use a bitmask, along with a bitwise logical operator, to change some bits in a target byte.

I like to think of bitmasks almost like stencils used for spray painting. You cut away parts of the stencil where you want to change (paint) the underlying surface, and you leave the stencil intact where you don’t want paint to go.

In particular, if we want to turn on some bits in PORTB while leaving the others untouched, we’ll create a bitmask with ones in the bit locations we’d like turned on. This works because a one ORed with anything will return a one. So we read in PORTB and OR it with the bitmask. The result should be the unaltered contents of PORTB everywhere that we had a zero, and ones everywhere our bitmask had a one. If we write this back out to PORTB, we’re set—PORTB has all its old bits intact, except those where there was a 1 in the bitmask have been turned on. I’ve worked this all through in detail in Example 4-2.

Example 4-2. Using OR to set bits

If LED2 is initially off:

PORTB : 0b11000011 // the current LED state

(1 << 2) = 0b00000100 // the LED we want to turn on

| = 0b11000111 // hooray!

LED2 is turned on, and none of the others are changed.

If LED2 is initially on:

PORTB : 0b11000111 // the current LED state

(1 << 2) = 0b00000100 // the LED we want to turn on

| = 0b11000111 // hooray!

LED2 is still on, and none of the others are changed.

We can also set multiple bits at once. All we have to do is create a bitmask with the two bits (say LED2 and LED4) that we’d like to turn on. Since:

0b00010100 // the desired bitmask

= (0b00000100 | 0b00010000)

= ( (1 << 2) | (1 << 4) )

then:

PORTB = 0b11000011 // the current LED state

((1 << 2) | (1 << 4)) = 0b00010100 // bits two and four

| = 0b11010111 // turned both on!

We’ve just seen how to get a copy of the byte currently in PORTB, and how to turn on LED2 and LED4 using OR and a bitmask. That gives us a new byte, which we just write out to PORTB, and we’re done:

PORTB = PORTB | (1 << 2);

This type of operation is so common that there’s a shorthand for it in C:

PORTB |= (1 << 2);

Either way you write it, the code ends up the same after compilation, so pick a style that makes you happy. Both of them have the effect of turning on LED2 and leaving the other bits as they were.

Toggling Bits with XOR

Now imagine that you want to flip a bit or two. You don’t really care if it’s on or off right now, you just want it in the other state, whatever that is. Imagine that you want to blink LED2 while leaving the rest of the LEDs unchanged. To do this, you’d toggle the bit that corresponds to LED2, delay a while, and then toggle it again, etc. To toggle a bit, you’ll use a bitmask and the XOR operator.

Let’s look at XOR again. If you XOR any bit with a fixed 0, you get a 1 if that bit is a 1 and a 0 if that bit is 0. (Remember, this is the “exclusive” or and is only true if one or the other is true, but not both.) So XORing with a zero gives you the input back again.

If you XOR with a 1, what happens? Starting with a 0 and XORing 1 returns a 1, and starting with a 1 and XORing 1 yields 0. XORing with a 1 seems a good way to toggle bits!

XOR with 0:

0 ^ 0 -> 0

1 ^ 0 -> 1

XOR with 1:

0 ^ 1 -> 1

1 ^ 1 -> 0

As we did with OR for setting bits, we’ll make a bitmask with a 1 where we want to toggle a bit and zeros everywhere else. To toggle a bit in a register, we XOR the current register value with the bitmask, and write it back into the register. Boom. For more detail, seeExample 4-3.

Example 4-3. Using XOR to toggle a bit

If LED2 is initially off:

PORTB : 0b11000011 // the current LED state

(1 << 2) = 0b00000100 // bitmask LED2

| = 0b11000111 // LED2 bit flipped on

After the XOR, LED2 is turned on, and none of the others are changed.

And if LED2 is initially on:

PORTB : 0b11000111 // the current LED state

(1 << 2) = 0b00000100 // bitmask LED2

| = 0b11000011 // LED2 bit flipped off

After the XOR, LED2 is turned off, and none of the others are changed.

So to toggle a bit, we create a bitmask for the bit we’d like to toggle, XOR it with the contents of our register, and write the result back out to the register. In one line:

PORTB = PORTB ^ (1 << 2);

or:

PORTB ^= (1 << 2);

for short. You can, of course, toggle more than one bit at once with something like:

PORTB ^= ((1 << 2) | (1 << 4));

Clearing a Bit with AND and NOT

Clearing a bit (setting it to zero) is just inconvenient, but you’ll have to do it so often that you’ll eventually find it second nature. So far, we’ve used OR to set bits and XOR to toggle them. You may not be entirely surprised that we’re going to use AND to clear bits. Let’s run through the usual analysis.

If we AND any bit with 0, the result is guaranteed to be 0. There’s no way they can both be 1 if one of them was a 0 to start with. This is how we’ll turn bits off:

AND with 0:

0 & 0 -> 0

1 & 0 -> 0

AND with 1:

0 & 1 -> 0

1 & 1 -> 1

This suggests using a bitmask with AND to turn bits off. The bitmask we’ll have to use should have a 1 where we want to keep the old data and a 0 where we want to clear a bit. That is, to turn off LED2, we’ll use an AND bitmask that looks like 0b11111011.

But wait a minute! That bitmask is the exact opposite of the bitmasks we’ve used before—it has ones where the others had zeros and vice versa. There’s a million stupid ways to create such a mask, but the easy way is to first create the mask with a 1 where we want it, and then use NOT to flip all the bits.

So to make a bitmask to turn off LED2, we’ll first shift a 1 over into the right spot and then NOT the whole mask:

(1 << 2) -> 0b00000100

~(1 << 2) -> 0b11111011

Now we AND that with the original value and we’re home free. I work through all of the steps for you in Example 4-4.

Example 4-4. Using AND and NOT to clear a bit

If LED2 is initially off:

PORTB = 0b11000011

~(1 << 2) = 0b11111011

& = 0b11000011

LED2 stays off, and none of the others are changed.

And if LED2 is initially on:

PORTB = 0b11000111

~(1 << 2) = 0b11111011

& = 0b11000011

LED2 is turned off, and none of the others are changed.

Reassigning to PORTB and writing these as one-liners, we get:

PORTB = PORTB & ~(1 << 2);

or:

PORTB &= ~(1 <<2);

And as with the other examples, you can of course turn off multiple bits in one statement:

PORTB &= ~((1 << 2) | (1 << 4));

being careful with the NOT outside the parentheses, because you want to have two zeros in your bitmask.

Showing Off

Now that we’ve got all this bit-level manipulation under our belts, let’s make some demo code to show off a little bit. Being able to set, clear, and toggle individual bits allows a little more flexibility than cylon eyes code had, and it should give you enough basis to start experimenting. Let’s work through Example 4-5.

Example 4-5. showingOffBits.c listing

/* Showing off some patterns to practice our bit-twiddling */

// ------- Preamble -------- //

#include <avr/io.h>

#include <util/delay.h>

#include <avr/power.h>

#define DELAYTIME 85 /* milliseconds */

#define LED_PORT PORTB

#define LED_DDR DDRB

int main(void) {

clock_prescale_set(clock_div_8);

uint8_t i;

uint8_t repetitions;

uint8_t whichLED;

uint16_t randomNumber = 0x1234;

// -------- Inits --------- //

LED_DDR = 0xff; /* all LEDs configured for output */

// ------ Event loop ------ //

while (1) {

/* Go Left */

for (i = 0; i < 8; i++) {

LED_PORT |= (1 << i); /* turn on the i'th pin */

_delay_ms(DELAYTIME); /* wait */

}

for (i = 0; i < 8; i++) {

LED_PORT &= ~(1 << i); /* turn off the i'th pin */

_delay_ms(DELAYTIME); /* wait */

}

_delay_ms(5 * DELAYTIME); /* pause */

/* Go Right */

for (i = 7; i < 255; i--) {

LED_PORT |= (1 << i); /* turn on the i'th pin */

_delay_ms(DELAYTIME); /* wait */

}

for (i = 7; i < 255; i--) {

LED_PORT &= ~(1 << i); /* turn off the i'th pin */

_delay_ms(DELAYTIME); /* wait */

}

_delay_ms(5 * DELAYTIME); /* pause */

/* Toggle "random" bits for a while */

for (repetitions = 0; repetitions < 75; repetitions++) {

/* "random" number generator */

randomNumber = 2053 * randomNumber + 13849;

/* low three bits from high byte */

whichLED = (randomNumber >> 8) & 0b00000111;

LED_PORT ^= (1 << whichLED); /* toggle our LED */

_delay_ms(DELAYTIME);

}

LED_PORT = 0; /* all LEDs off */

_delay_ms(5 * DELAYTIME); /* pause */

} /* End event loop */

return (0); /* This line is never reached */

}

Reading down from the top, I include the standard avr/io.h file, which includes all the DDR and PORT macros and AVR part definitions, and then the delay utilities. Next, a delay time and the pinouts are defined in case you want to play around with them later on.

Down in the main() routine, there’s not much to do for initialization. A few variables that we’ll be needing are defined, and then the DDRB is configured for output on all of the pins. (0xFF is 255 in hexadecimal, and is equivalent to 0b11111111.)

The event loop (while(1){...) is divided into three different “animations”: one that turns on all the LEDs starting from LED0, and then turns them all off starting from LED0; one that does the same thing in reverse; and one that “randomly” toggles individual LEDs on and off.

The “go left” routine is a lot like cylon eyes, except that it doesn’t turn off any LEDs until they’re all on, and it uses a for() loop. Turning on each LED one at a time, without turning them back off, ends up with all eight LEDs on. The next for() loop in the “go left” section turns off the LEDs one at a time, from right to left. This makes it look like a block of LEDs, eight wide, passes through our viewing range.

FOR LOOPS

You’ll be seeing a lot more for() loops in this book, but this one’s the first one. So make sure you know what’s going on inside the loop’s parentheses.

First, a loop variable is initialized (i=0). Then a test is done on that variable (i<8). If the test is true, the rest of the code in curly brackets is run. If not, the loop is over and the code moves on. Finally, each time it’s done with a loop, the third argument in the for() parentheses is run. In our case, we’re adding one (i++) to the variable.

The “go right” code is a little bit more interesting, and here’s a potential trap when coding for microcontrollers. Conceptually, it’s easiest to think of starting with i=7 and subtracting one until it’s reached zero. The problem with this is how we test for the end condition. We want to run the for loop when i=0 and turn off LED0.

If you set up the loop like this:

for (i=7; i>0; i--){}

it will stop as soon as i is zero, so it will never set or unset LED0. You might try to fix this by comparing with a greater-than-or-equal-to:

for (i=7; i>=0; i--){}

then you end up with a surprising infinite loop! The reason for this gotcha is that i is defined as an unsigned integer, which counts from 0 to 255—it’s only defined for positive numbers. When you subtract one from zero, it rolls back around to the maximum value, which is 255 in the 8-bit case. This means the condition i>=0; is always true.

BIT TWIDDLING FOR THE IMPATIENT

In summary, here’s a recap of the three important bit-twiddling operations. Let’s say you’re trying to write bit i in byte BYTE:

Set a bit

BYTE |= (1 << i);

Clear a bit

BYTE &= ~(1 << i);

Toggle a bit

BYTE ^= (1 << i);

Of course, you can substitute more complicated bit shifts in for the parentheses. For instance, if you want to set bits i and j, use BYTE |= ((1<<i)|(1<<j));.

It’s “hardcore” to do the bit shifting and negation stuff by hand, and this book’s code is also written in that style because I think it’s good for you, like doing situps or drinking wheatgrass juice. In the end, you will have to read other people’s code, and they will do bitwise operations this way. You can’t escape it, so you might as well get used to it—it’s part of the language idiom.

But on days when you’re not feeling hardcore, you can also define some macros to do the same thing, and this can make your code more easily readable. If you’d like to take this path, these will do the trick:

#define BV(bit) (1 << bit)

#define setBit(byte, bit) (byte |= BV(bit))

#define clearBit(byte, bit) (byte &= ~BV(bit))

#define toggleBit(byte, bit) (byte ^= BV(bit))

The main limitation of the macros is that they can only change one bit at a time, while the standard method can accept any kind of bitmask, but this rarely makes any practical difference except to how it reads in your code. In the rare cases that you need to flip four bits or more really quickly or really frequently, you’ll get it done faster the hardcore way. Anyway, in my opinion, it’s good to have options.

Because we want the for loop to run when i is 0, and then stop afterwards when i equals 255, we can test for i < 255, which is exactly what the code, as written, does.

Finally, have a brief look at the “random toggling” section of the code. The “random number” isn’t really random at all, but it looks pretty close, so it is good enough. You can see how I used bit-masking to take a 16-bit random number and turn it into a number in the range zero to seven, to match up with our LED numbers. You’ll end up seeing these tricks again, so I’ll at least introduce them here.

First, we convert the 16-bit randomNumber variable into an 8-bit number by bit shifting the randomNumber over eight times: whichLED = (randomNumber >> 8);. This keeps the most significant eight bits, which are the most “random” using this quick-and-dirty algorithm.

Next, we need to limit the random number to the range zero through seven. And what’s the largest number you can count to with three bits? Seven. So the trick is to keep only the lowest three bits, zeroing out the upper five. And the quickest and easiest way to do this is using AND and a bitmask: whichLED = whichLED & 0b00000111;. Now our variable whichLED will be in the range of the number of LEDs we actually have.

Finally, if whichLED contains a number like zero or three or seven, all that’s left for us to do is use XOR and a bit-shift roll to toggle the randomly selected bit. Voila! A random blinker, powered by bit twiddling.

Summary

You learned a lot about bit twiddling in this chapter, so we should probably recap. Last chapter you saw how to set up the data-direction registers to enable any given pin for output, and then how writing a logical one or zero to the same bit number in another register set the output voltage on that pin to 5 V or 0 V, respectively.

And because digital output is all about controlling individual bits, you dove head-first into more advanced bit twiddling. First, using the bit-shift roll, you saw how to get a one bit in any given position. Then you saw how to use the various bitwise logical operations (OR,XOR, AND, and NOT) to set, toggle, or clear bits in a byte singly or in groups. Here, I also introduced the idea of a bitmask that’s used with the logical operations to tweak specific bits singly or together:

Set a bit

BYTE |= (1 << i);

Clear a bit

BYTE &= ~(1 << i);

Toggle a bit

BYTE ^= (1 << i);

And that’s a lot of bit twiddling for one chapter, but the groundwork we’ve laid here will serve you throughout the rest of the book and for the rest of your life with microcontrollers.