I'm confused with bitmasks

Asked by At

I am using IAR embedded workbench and C. I would like to create a mask and decide whether next bit for transmit is 1 or 0.

I tried this but didn't work

int transmit(int signal, int number_of_bits)
{

    int mask;
    for (int i = 0; i < number_of_bits; i++)
    {
        mask = pow(2,number_of_bits-1-i)
        if ((signal & mask) == 0) // bit '0'
        {
            transmit0();
        }
        else // bit '1'
        {
            transmit1();
        }
    }
}

And I tried this, it tranmits 0001 but i'm trying to transmit 1000 (vice versa)

int transmit(int signal, int number_of_bits)
{

    int mask;
    for (int i = 0; i < number_of_bits; i++)
    {
        mask = (1 << i);
        if ((signal & mask) == 0) // bit '0'
        {
            transmit0();
        }
        else // bit '1'
        {
            transmit1();
        }
    }
}

2 Answers

0
E. van Putten On Best Solutions

Here mask is the variable that will always contain a "power of 2" value. The goal is to only have one bit set in the mask at all times. This mask is used to test each bit in "isolation".

In combination with the logical AND-function, you can see it as a filter that gives you only the value that particular bit corresponds to or nothing (zero).

Remember that the value of a binary word with only one bit set always corresponds to a power 2 value by definition. So after the test of a single bit you will see either zero or a power of 2 value.

Let's look at some practical values while the program is running (assuming 8 bits). So in the for loop, this is what the value of mask looks like over time:

00000001
00000010
00000100
00001000
00010000
...

Note: you can also go into the reverse direction, for instance if the receiver wants to see the highest bit first and the lowest last. Don't know what is needed here, but just so you know. If you want to go in reverse, you initialize mask with (1 << (num_bits-1)) then go one step to the right every time in the loop itself mask >>= 1).

Every mask value is bitwise AND-ed (& operator) with the input value signal to "filter" out that one particular bit we're interested in.

Remember: the outcome of this AND operation is still multiple bits -- not a single bit, so we can't look for a value of 1 (we'd also have to test for the cases 2, 4, 8 ... etc.).

Example, so let's say all the bits are on, then the logical AND output will look like this:

00000001 AND 11111111 = 00000001
00000010 AND 11111111 = 00000010
00000100 AND 11111111 = 00000100
00001000 AND 11111111 = 00001000
00010000 AND 11111111 = 00010000
...

Note how the outcome follows the mask in this case. Although the values differ every time, you know that when you got something nonzero, the bit you are testing must be high!

And if all the bits are off you will see this:

00000001 AND 00000000 = 00000000
00000010 AND 00000000 = 00000000
00000100 AND 00000000 = 00000000
00001000 AND 00000000 = 00000000
00010000 AND 00000000 = 00000000

You will note it's easier to check if the result is zero. That means the bit was off. It's also why the code only checks for a value of zero, it knows the bit is 1 in all the other cases!

Now the trick is to get the correct mask value. What you want is shift a bit value of 1 left to the correct place. So if you start testing for bit 4 for instance, you'd shift 1 four places to the left and you will get (00010000 binary).

For this we use the bit shift left operator <<.

As others have already said, ^ unfortunately does something completely different (XOR), which adds to the whole confusion.

0
Marcus Vinicius Pompeu On

As noticed by @L.F., ^ is NOT a power operator, alas <<, the bitwise shift operator, does the trick.