Search code examples
c#bit-manipulationboolean-logicbitmaskboolean-operations

Which logical operations can I use to ignore irrelevant bits when masking?


Context

Let's say that I have a system model which comprises of 8 Boolean variables. Together, they comprise a byte that may expresses the 128 state permutations of my system. Let this byte be stateByte, whereby each bit is one of my variables.

Now, suppose I have some enumerable states, such as:

public enum States
{
    READY     = 0b_0000_0001
    OPERATING = 0b_0100_0000
    FAULT     = 0b_1000_0000
}

If it were that each of the States were discrete, I could easily determine States currentState = (States)stateByte, however my problem is:

My states are only each dependent on a subset of specific bits, not the entire byte. Specifically, there are some bits that are irrelevant depending on the state. To use pseudo notation, I have the scenario below where x notates an irrelevant bit:

public enum States
{
    READY     = 0b_0000_0001 // Exactly this permutation
    OPERATING = 0b_0100_0000 // Exactly this permutation
    FAULT     = 0b_1xxx_xxxx // Only bit 7 need be high to determine a fault
}

Question

How can I use logical, bitwise operators (masking) in order to enumerate states from only relevant bits?

Further Context

For those sticklers for detail who would question why I am trying to do this or why I cannot simply use thresholds, please see below the full state table of the hardware I am integrating:

enter image description here


Solution

  • You could use the binary and operator & to mask values, such as to only include certain bits:

    0b_1xxx_xxxx & 0b_1000_0000 = 0b_1000_0000
    0b_1xxx_xxxx & (1 << 7)     = 0b_1000_0000
    0b_1xxx_xxxx & States.Fault = 0b_1000_0000
    

    If you want to access certain bits often you could write an extension method like this:

    public static boolean GetBit(this byte bitmask, int index) =>
        ((bitmask >> index) & 1) != 0;
    
    0b_1xxx_xxxx.GetBit(7) = true
    

    If you want to check multiple bits at once, you can use a pattern that matches all bits you want to check and compare them with another pattern containing all "correct" bits and 0s everywhere else:

       0b_x0xx_1000
     & 0b_0100_1111  // Only look at bits 0-3 and 6
    == 0b_0000_1000  // Check that bit 6 is 0, 3 is 1 and 0-2 are 0
                     // Other bits are 0 due to the logical and