Getting Bitwise with JavaScript

I’ve been spending a perhaps-excessive amount of time these last couple of weeks playing with my Arduino Uno. I got the Arduino bug after following along with Rick Waldron’s progress with Johnny Five, a library that lets you communicate with an Arduino using JavaScript. Johnny Five means that I can make LEDs light up without learning C, and this makes me very happy.

At Rick’s suggestion, I began my journey with the SparkFun Inventor’s Kit, which includes lots of simple components like LEDs, sensors, and other goodies. It also comes with little sheets of paper that illustrate how to set up different circuits.

IMG_1158

I worked through several of these, using Johnny Five instead of the included C++ code, and things were going swimmingly until I got to a circuit that included a shift register.

A shift register is an integrated circuit. You “shift” binary data to it, one 0 or 1 at a time, and it stores that data in memory until you tell it to send the data to its output pins. The one that comes with the inventor’s kit can hold a whopping eight bits of data at a time; that is, a combination of eight 0s or 1s. In Arduino land, each of those 0s and 1s can be used to turn things off and on; say, a motor, or an LED.

At the time, Johnny Five didn’t include an API for working with a shift register; if I was going to get it working, I was going to have to learn how to send those bits myself. Here, then, is what I learned; whether you’re interested in playing with Arduinos or not, it’s a hopefully gentle introduction to bitwise operations in JavaScript.

Part 1: Learning to Count

Bitwise operators let us work with and manipulate a binary representation of a number. Bitwise operators treat their operands as 32-bit numbers, but for the sake of this conversation, we’ll just work with 8 binary digits, or bits.

For example, here’s the binary representation of the base 10 number 9:

00001001

The right-most digit is the 1’s digit; the next digit is the 2’s; the next digit is the 4’s, then the 8’s, etc. So, the binary number above represents one 8 and one 1, for a total of 9. Eight binary digits can be used to represent any number between 0 and 255.

So. Knowing that 0s and 1s can light up LEDs, and knowing that we can count from 0 to 255 using combinations of eight 0s and 1s, how can we count from 0 to 255 on eight LEDs?

Iterating over the numbers 0 through 255 is easy enough, so let’s think about how we’d send the number 9. Since its binary representation is 00001001, we want to tell the first four LEDs to be off, the fifth LED to be on, the next two LEDs to be off, and the last LED to be on. We could do this by translating 9 into an array of 0s and 1s:

function numToBinaryArray( num ) {
  var bin = num.toString(2);
  if (bin.length < 8) {
    bin = '0000000'.split('').slice( 0, 8 - bin.length ).join('') + bin;
  }
  return bin.split('').map(Number);
}

var arrayOfBits = numToBinaryArray( 9 );
// [ 0, 0, 0, 0, 1, 0, 0, 1 ]

arrayOfBits.forEach(function(bit, index) {
  lights[index].send(bit);
});

If all we wanted to do was count numbers with LEDs, we could leave this code as-is, and move on to building robots or something. But there’s actually a shorter, more efficient way to write this code, and understanding it opens up a world of possibilities:

var index, bitMask;
var num = 9;

for (bitMask = 128, index = 0; bitMask > 0; bitmask >>= 1, index++) {
  lights[index].send( ( bitMask & num ) ? 1 : 0 );
}

This code uses two bitwise operators, >>= and &, to accomplish the same thing as the previous example. What’s going on?

First, the for loop starts with a value of 128 for the variable bitMask. Inside the for loop, we take that value and use it to do a binary AND operation with the number we’re trying to display (9). Let’s look at the binary representation of those two numbers next to each other:

10000000        // 128
00001001        // 9

A binary AND of these two numbers looks at each digit in each number. If a digit is 1 in both numbers, then that digit will be set to 1 in the result. In the case of 128 and 9, there are no cases where a given digit is 1 in both numbers. Here’s what happens when we binary AND these two numbers:

  10000000      // 128
& 00001001      // 9
----------
  00000000      // 0

What does this tell us? It’s the first iteration of the for loop, and we’re using the value of bitMask & num to figure out whether to send a 0 or a 1 to the first LED. Because the return value of the & operation is falsy, we decide to send 0; the first LED is turned off, and we move on to the next iteration of the for loop.

In the “final expression” of our for loop – the expression that’s evaluated at the end of each iteration – we see bitMask >>= 1, index++. We’ve seen operators similar to >>= before – think of += – so you can probably guess that we’re altering the value of the bitMask variable, which was initially set as 128. What’s the >> part of the operator, then? It’s shifting the bits in our bitMask variable one position to the right. So, whereas the binary representation of bitMask was:

10000000

… after we shift its bits one position to the right, the new binary representation of bitMask is:

01000000

Inside the for loop, we’ll use this new value for the binary AND with the number we’re trying to send, and the result will tell us that the second LED shouldn’t be turned on, either.

We continue this pattern, turning on a single bit at a time from left to right in the bitMask variable. We do a binary AND with the bitMask and the target value to determine whether to turn on the LED that corresponds to that bit.

  10000000 // 128
& 00001001 // 9
----------
  00000000 // 0     -- falsy, so LED 0 is OFF

  01000000 // 64
& 00001001 // 9
----------
  00000000 // 0     -- falsy, so LED 1 is OFF

  00100000 // 32
& 00001001 // 9
----------
  00000000 // 0     -- falsy, so LED 2 is OFF

  00010000 // 16
& 00001001 // 9
----------
  00000000 // 0     -- falsy, so LED 3 is OFF

  00001000 // 8
& 00001001 // 9
----------
  00001000 // 8    -- truthy, so LED 4 is ON

  00000100 // 4
& 00001001 // 9
----------
  00000000 // 0    -- falsy, so LED 5 is OFF

  00000010 // 2
& 00001001 // 9
----------
  00000000 // 0    -- falsy, so LED 6 is OFF

  00000001 // 1
& 00001001 // 9
----------
  00000001 // 1    -- truthy, so LED 7 is ON

Throw in the iteration from 0 to 255, a timeout, and some Johnny Five code, and we end up with this:

Part 2: Learning to Write

If all we wanted to do was count from 0 to 255 in blinking lights, then the best we can say about bitwise operators is that they save us a few lines. A few days after I got the LEDs blinking, I saw this code for making a two-line liquid crystal display (LCD) work with Johnny Five.

This code was using an array-based approach for sending bits, but from my experience with the LEDs and the shift register, I thought that a bitwise approach might make more sense. Over the course of a few days of working with Andreas Haugstrup and Rick to develop a full API for LCDs in Johnny Five, I got to understand bitwise operations a whole lot better.

As you can imagine, an LCD is a lot more complex than an LED. Instead of simply turning it on or off, you tell it what to do – which character to display next, whether to show the cursor, whether to blink the cursor, where to write the next character – by sending a number between 0 and 255 as eight bits of data. Sound familiar?

Indeed, we already know from the LED example how to send a number between 0 and 255 as eight bits of data. The standard set of ASCII characters take up the numbers 32-127, but that leaves us the numbers 0-31 and 128-255 for commands.

Some of the commands we need to send to our LCD are actually combinations of instructions. For example, if we want to position the cursor somewhere on the LCD, we need to send a single command that says both “we want to position the cursor” and “this is where we want to put it.” Unlike in JavaScript, we can only send a single argument: a number between 0 and 255. The bitwise OR operator, |, provides a way to send several pieces of information in that single number.

Let’s look at the Johnny Five method that sets the cursor position:

LCD.prototype.setCursor = function( col, row ) {
  var rowOffsets = [ 0x00, 0x40, 0x14, 0x54 ];
  this.command( LCD.SETDDRAMADDR | ( rowOffsets[ row ] + col ) );

  return this;
};

(If you need a refresher on hexadecimal numbers like 0x00, you’re probably not alone.)

The bitwise OR operator looks at the binary representation of two numbers and returns a number that represents the bits that are “on” in either of the two numbers.

For example, consider again the numbers 9 and 128. If you look at the setCursor method above, the value 9 is what we’d end up with for rowOffsets[ row ] + col if we wanted to position the cursor in the first row (0x00) at the 10th column. The value of LCD.SETDDRAMADDR happens to be 0x80, which is 128. In binary, these two numbers look like this:

When we combine these two values using |, we arrive at a single number that we can send as a command to the LCD to tell it to put the cursor in the tenth column of the first row:

  10000000  // 128 (LCD.SETDDRAMADDR)
| 00001001  // 9 (row 0 + col 9, eg. 0x00 + 9)
__________________
  10001001  // 137

We can send other numbers to put the cursor elsewhere, to make the cursor blink, to turn the LCD on and off, and, most importantly, to write characters to the screen. Understanding and using bitwise operators makes all of it quite straightforward – much moreso than with an array-based approach – and after a few days of work, Johnny Five now supports the same LCD features as the C-based API.

More Bitwise Fun

The Mozilla Developer Network has incredible documentation about all of the bitwise operators, and more discussion and examples of how they can be used.

If you’ve ever wondered why you can do ~myArray.indexOf(targetVal) and get a useful boolean, pay special attention to the discussion of the bitwise NOT operator ~, which flips the bits of the binary representation of a number, and to the discussion of signed 32-bit integers, where you’ll learn that -1 is represented in binary as 32 1’s in a row. Flipping the binary bits of -1 (the value returned by indexOf when an item is not found in an array) returns 0, a falsy value. Flipping the bits of any value that indicates an item was found in an array will return a truthy value.

Want to learn more about how LCDs work? Read all about LCD addressing – that is, how the chip that controls an LCD interprets the binary commands it receives.

Finally, I’ve put together a JSBin that simulates the fun you can have with LEDs and bitwise operators. It’s a fun way to see some of what we’ve covered in this post without having to wire up an Arduino:

JS Bin

That said: if you like JavaScript, you should get an Arduino, and you should build things with Johnny Five. Rick said it best with his initial encouragement to me: as people who make things on computer screens all day, it’s incredibly cool the first time you make an LED light up in the real world. I haven’t had this much fun with JavaScript – or poked in so many of its nooks and crannies – in a long time.

This entry was posted by Rebecca Murphey (@rmurphey) on August 08, 2012 in JavaScript, johnny-five and Feature.

Comments

Author

This entry was posted by Rebecca Murphey (@rmurphey) on August 08, 2012 in JavaScript, johnny-five and Feature.

Recent from this Author

Related Posts