Search code examples
cbit-manipulationmotordriver

Bitwise rotate right of 4-bit value


I'm currently trying to control a stepper motor using simple full steps. This means that I'm currently outputting a sequence of values like this:

1000
0100
0010
0001

I thought an easy way to do this was just take my 4-bit value and after each step, perform a rotate right operation. "Code" obviously isn't following any kind of syntax, it's simply there to illustrate my thoughts:

step = 1000;
//Looping
Motor_Out(step)
//Rotate my step variable right by 1 bit
Rotate_Right(step, 1)

My problem is that there obviously isn't any 4-bit simple data types that I can use for this, and if I use an 8-bit unsigned int I will eventually rotate the 1 off to the MSB, which means the 4-bit value I'm actually interested in, will turn into 0000 for a few steps.

I've read that you can use structs and bit-fields to solve this, but the majority of things I read from this is telling me that it's a very bad idea.


Solution

  • The arithmetic for this is simple enough that it will always be faster than the table approach:

    constexpr unsigned rotate_right_4bit ( unsigned value )
    {
        return ( value >> 1 ) | ( ( value << 3 ) & 15 );
    }
    

    This turns into 5 lines of branch-free x86 assembly:

    lea     eax, [0+rdi*8]
    shr     edi
    and     eax, 15
    or      eax, edi
    ret
    

    Or, alternatively, if you actually like to see the indexes {3, 2, 1, 0}, then you can split them up into 2 functions, one that "increments" the index, and the other that actually computes the value:

    constexpr unsigned decrement_mod4 ( unsigned index )
    {
        return ( index - 1 ) & 3;
    }
    
    constexpr unsigned project ( unsigned index )
    {
        return 1u << index;
    }