Matteou, mi piacerebbe capire come mai vuoi eseguire tutto quel codice sotto interrupt ma senza commenti, scusami, non riesco a seguirlo.
Una prima considerazione che faccio è che io non farei mai una routine di interrupt così complicata e soprattutto così lunga. L'nterrupt per definizione deve essere una singola azione che non può essere ritardata dal resto del codice. Nell'applicaizone specifica del ELS l'interrupt deve essere la lettura dell'encoder che, come output, deve avere un incremento o un decremento di passo. Tutto il resto non è prioritario e deve essere eseguito al di fuori della routine di interrupt.
Altra cosa che non capisco è perché vuoi tenere sotto interrupt un solo canale dell'encoder e leggere l'altro in polling (anche se questo non è un polling ma un semplice controllo) solo per determinare la direzione. Tra l'altro, così facendo, sfrutti solo la risoluzione nominale dei passi e non x4. Cioè in pratica stai facendo fare al micro quello che normalmente si fa fare esternamente ad un flip-flop, ovvero una logica a stati hardware che costa niente ed è molto più veloce di un codice.... non mi pare molto efficiente.
Ragiona sul fatto che la routine di interruppt ti serve solo per intercettare il passo dell'encoder istantaneamente, tutto il resto è conseguenza di quel passo ma non dovrebbe essere fatto nella routine di interrupt.
Questa è la mia, con i tempi di esecuzione stimati (il calcolo fatto usando il clock di arduino micros() o millis() non è molto affidabile)
Codice:
void InterruptEncoderFilettatura()
{
static byte prev_encoder; //definizione di variabile byte (1 ciclo di clock: 62,5 nanosecondi)
byte port; //definizione di variabile byte (1 ciclo di clock: 62,5 nanosecondi)
port = PIND & B00001100; //and logico tra due byte e trasferimento indiretto (3 cicli di clock: 187,5 nanosecondi)
port |= prev_encoder; //or logico tra due byte e trasferimento indiretto (3 cicli di clock: 187,5 nanosecondi)
steps += encoder[port]; //addizione tra due valori e trasferimento indiretto (3 cicli di clock: 187,5 nanosecondi)
absolute_encoder_steps += encoder[port]; //addizione tra due valori e trasferimento indiretto (3 cicli di clock: 187,5 nanosecondi)
port >>= 2; //shift a destra di due posizioni (2 cicli di clock: 125 nanosecondi)
prev_encoder = port; // load indiretto di 1 byte (2 cicli di clock: 125 nanosecondi)
step_flag = true; // cambio di stato logico di variabile boolean (1 ciclo di clock: 62,5 nanosecondi)
} //END of the Interrupt Service Routine
I calcoli sono stimati tenendo conto del clock di Arduino UNO a 16Mhz (62,5ns a ciclo)
In totale sono 1187,5 ns. Ovvero 1,1875 us.
Stiamo larghi e consideriamo anche il tempo di chiamata e push/pop dallo stack, direi che in 2us facciamo tutto comodamente.
Mi pare strano che la tua impieghi solo 4us, anche considerando che se fai operazioni tra variabili a 16 bit impieghi molti più cicli.