Decoding a quadrature encoder just isn’t that difficult

I was shown some truly horrifying code that reported to decode a quadrature shaft encoder. It was just mind bogglingly stupifying that someone would go to that much work to write something so utterly horrible. Here’s the way that I think of them.

A quadrature shaft encoder looks like a 2-bit Gray code counter. Instead of counting up in binary in the usual way, it goes up changing exactly one bit at a time. So, what are the four possibilities?

00
01
11
10
...repeats to 00

Let’s imagine that you had a previous reading for the shaft encoder, and now you notice that some new value can be read. The new value is another two bits. That makes the total of 16 possibilities. There are four 16 bit combinations that indicate a clockwise rotation, and four that indicate a counter clockwise rotation. The rest are “impossible” states, or states where the input didn’t change. You can
just write out the table.

OLD NEW CW  CCW
00  00  0   0 
00  01  1   0 
00  11  0   0 
00  10  0   1
01  00  0   1 
01  01  0   0
01  11  1   0 
01  10  0   0
11  00  0   0
11  01  0   1
11  11  0   0
11  10  1   0
10  00  1   0
10  01  0   0
10  11  0   1
10  10  0   0

You can convert this into code any of a number of ways: switch statements, table lookup, you could minimize the logical instructions using a Karnaugh map… whatever floats your boat. I’d probably just go with a switch statement, something that looks like this (assume OLD and NEW are integers holding the two 8 bit values):


int
cw(int o, int n)
{
    switch (o) {
    case 0:
       return n == 1 ;
    case 1:
       return n == 3 ;
    case 3:
       return n == 2 ;
    case 2:
       return n == 0 ;
    }
}

And similarly for ccw.

It ain’t rocket science.

Addendum: It’s pretty easy to create the delta too (-1 if ccw, +1 if cw, else 0)


int
delta(int o, int n)
{
    switch (o) {
    case 0:
       return (n == 1) - (n == 2) ;
    case 1:
       return (n == 3) - (n == 0) ;
    case 3:
       return (n == 2) - (n == 1) ;
    case 2:
       return (n == 0) - (n == 3) ;
    }
}