Bit Manipulation: Creating Bitmasks

Creating a bitmask for a specific bit is as simple as starting with a bitstring of 0’s and flipping the desired bit. So for a bitmask for Bit 0, it is as simple as starting with 00000000 (for an 8-bit bitmask), then flipping the 0th bit, resulting in 00000001. Although this starts off as simple for shorter bitstrings, it’s easy to make mistakes when working with larger bitstrings. For instance, it may be difficult to create a bitmask for Bit 22 of a 32-bit bitstring using this method without possibly making errors.

There is, however, a simpler method. Notice that the bitmask for Bit 1 is 00000010, which is equivalent to the decimal number 2, which is also 2^1. Similarly, the bitmask for Bit 2 is 00000100 = 4 = 2^2. The bitmask for Bit 3 is 00001000 = 8 = 2^3, and the pattern continues. Notice that the bitmask for a Bit n is the binary equivalent to 2^n. Recall that if you have an unsigned binary number and you logical shift it to the left, it is the same as multiplying that binary number by 2. If you logical shift it to the left twice, it is the same as multiplying by 4, or 2^2. Similarly, the logical shift to the left three times is the same as multiplying by 8, or 2^3. Notice that doing a logical shift left n times is the same as multiplying that number by 2^n. Thus, we can use the left shift operation in order to create bitmasks. Let’s start with making a bitmask for Bit 0. The bitmask is 00000001 = 1 = 2^0 = 1 << 0. To get the bitmask for Bit 1, which is 2, we need to multiply 1 by 2. In other words, 1 << 1 gives the bitmask for Bit 1. To get the bitmask for Bit 22, which is 2^22, we need to multiply 1 by 2^22, or 1 << 22. In summary, creating bitmask in C for a Bit n is as simple as 1 << n.

In the driverlib provided for MSP432, single-bit masks are defined as macros that you can readily use. See the below image. BIT0 is the macro that all the bits are 0 except at bit index 0. The first 16 bitmasks are defined as BIT* where * is the hex digit representing the index of the single bit that is 1 in the bitmask. For indices larger than 15, you need to use BIT(x) format where x is the index. For example, BIT(25) is the bitmask that all bits are 0 except for index 25.

You can also create bitmasks that control multiple bits. Using the eight LEDs example once more, say the bitstring is 10100110, and you wanted to turn on LED #3 and #4. While you could turn them on one at a time, a more efficient approach would be to turn them on simultaneously. In other words, we can bitwise OR the LED bitstring with 00011000, leading to 10100110 | 00011000 = 10111110. Notice that 00011000 is a combination of the bitmasks for Bits 3 and 4. In other words, 00011000 = 00010000 | 00001000. So, in order to combine bitmasks, use a bitwise OR operation. Let’s say you wanted to turn off LED #2 and #7. Combining the bitmasks for those LEDs gives you 00000100 | 10000000 = 10000100. Bitwise ANDing the LED bitstring with the complement of this combined bitmask gives you 10111110 & ~10000100 = 10111110 & 01111011 = 00111010. 

In many cases, we are interested to create a bitmask for several adjacent bits. For example, let us say we are interested to LED #3, #4, #5, and #6. There are 4 '1's in this mask that start from position Bit 3 and go up. This is similar to having the binary number 00001111 and shifting it 3 times, which gives us 01111000 .This means we can create a mask by putting as many '1's as the mask needs at the left-most side of the bitstring and then shifting it as many times as the lowest bit position of the mask.