This is my encoder routine for AVR. 2 lines of C code logic (more if you want to make it verbose).
Just add a counter and serial routines.
/*
* Rotary encoder handler.
*
* This assumes wiper is ground, and 2 outputs are on PB0 and PB1.
*
* More info: http://www.buxtronix.net/2011/10/rotary-encoders-done-properly.html
*/
const char ttable[6][4] = {
{0x3 , 0x2, 0x1, 0x0}, {0x83, 0x0, 0x1, 0x0},
{0x43, 0x2, 0x0, 0x0}, {0x3 , 0x5, 0x4, 0x0},
{0x3 , 0x3, 0x4, 0x40}, {0x3 , 0x5, 0x3, 0x80}
};
volatile char state = 0;
void rotary_init() {
DIRB = 0x0; // PortB is input
PORTB = 0x3; // Weak pullup on PB0/PB1.
}
/* Read input pins and process for events. Call this either from a
* loop or an interrupt (eg pin change or timer).
*
* Returns 0 on no event, otherwise 0x80 or 0x40 depending on the direction.
*/
char rotary_process() {
state = ttable[state & 0xf][PORTB & 0x3];
return (state & 0xc0);
}