Lettura Encoder generando interrupt e tramite stati finiti

Non c'è un po' troppa roba in quella funzione di interrupt?... Addirittura ci sono una dozzina di digitalRead!
Per evitare i rimbalzi basta leggere la sequenza Gray che esce dall'encoder!

In un verso:
00
01
11
10
00

Nel verso opposto:
00
10
11
01
00

Se fa 00-01-11 è stato ruotato in un verso; se fa 00-10-11 è stato ruotato nell'altro.

Questo è il blocchetto di codice che uso abitualmente:

int E; // Risultato della routine encoder(): 1, -1, 0.
byte S; // Lettura dei due valori dell'encoder.
byte So;// Lettura precedente dell'encoder.
int X; // Usato in encoder() per evitare letture multiple.

void encoder()
{
//              PD 76543210
// S=3-PIND      &B00000011; Gli I/O 0 e 1 sono PD0 e PD1, perciò non devo scorrere a destra.
// S=3-(PIND>>3) &B00000011; Serviva per l'encoder su PD3 e PD4.
// S=3-((PIND>>4)&B00000011); // Gli I/O 4 e 5 erano PD4 e PD5, perciò dovevo scorrere a destra di 4 bit.
S=3-((PIND>>2)   &B00000011); // Uso PD2 e PD3, quindi scorro a destra di 2 bit per farli diventare 0 e 1. 
// Il valore binario di S rappresenta A e B. Il centrale dell'encoder è a massa, quindi faccio complemento a 3 (11).  
S^=S>>1; // Faccio XOR (^) fra S (gray) e il suo bit 1, facendolo scorrere a Dx: AB XOR A,
         // ottenendo un binario che per ogni scatto fa 0-1-2-3-0 oppure 0-3-2-1-0.
E=0;
if (S!=So && S==0) X=0;
if (X==0)
  {
  if (So==1&&S==2)
    {E=1; X=1;
    // Bip();
    }
  if (So==3&&S==2)
    {E=-1; X=1;
    // Bip();
    }
  if (S==0)
    {E=0; X=0;}
  So=S;  
  }
}

Sì, si potrebbe ottimizzare un po'...

int E; // Risultato della routine encoder(): 1, -1, 0.
byte S; // Lettura dei due valori dell'encoder.
byte So;// Lettura precedente dell'encoder.
int X; // Usato in encoder() per evitare letture multiple.

void encoder()
{
//              PD 76543210
// S=3-PIND      &B00000011; Gli I/O 0 e 1 sono PD0 e PD1, perciò non devo scorrere a destra.
// S=3-(PIND>>3) &B00000011; Serviva per l'encoder su PD3 e PD4.
// S=3-((PIND>>4)&B00000011); // Gli I/O 4 e 5 erano PD4 e PD5, perciò dovevo scorrere a destra di 4 bit.
S=3-((PIND>>2)   &B00000011); // Uso PD2 e PD3, quindi scorro a destra di 2 bit per farli diventare 0 e 1. 
// Il valore binario di S rappresenta A e B. Il centrale dell'encoder è a massa, quindi faccio complemento a 3 (11).  
S^=S>>1; // Faccio XOR (^) fra S (gray) e il suo bit 1, facendolo scorrere a Dx: AB XOR A,
         // ottenendo un binario che per ogni scatto fa 0-1-2-3-0 oppure 0-3-2-1-0.
E=0;
if (S!=So && S==0)
  {
  X=0;
  if (S==2)
    {     
    X=1;
    if (So==1)
      {
      E=1;
      // Bip();
      }
    else if (So==3)
      {
      E=-1;
      // Bip();
      }
    }
  else if (S==0)
    {
    E=0;
    X=0;
    }
  So=S;  
  }
}

Solitamente non uso l'interrupt, perché il loop è abbastanza veloce oppure faccio le impostazioni in un while apposito, che attende la pressione del pulsante.