This is a loose translation and simplification of what I have done with other mcu's, minus the interrupt usage. I had a 16F1619 in a curiosity board and an encoder laying nearby, so I created something to test. The idea is that you detect any change on one pin and record the state of the other at that point. When both recorded states are 0 an increment/decrement took place.
Normally interrupts are doing the work in the background- one pins edge interrupts (both) are enabled, the isr takes care of the rest of the details as below and enables the other pin edge interrupts. You use the 'bouncy' pin to get you to the interrupt where the stable pin can be read, and that stable pin now has its edge interrupt enabled.
Seems to work pretty good for me anyway (human interaction), plus its very simple code.
//16F1619
#include <xc.h>
#include <stdbool.h>
#include <stdint.h>
//4 leds on curiosity low pin count dev board
//led D4=A5, D5=A1, D6=A2, D7=C5
//led chaser moved by encoder, encoder also determines direction
static void ledSet(uint8_t v){
TRISA5 = 0, TRISA1 = 0, TRISA2 = 0, TRISC5 = 0;
//v is bit position 0-3
v = (uint8_t)(1<<(v&3)); //compiler complains, so cast
LATA5 = v & 1 ? 1 : 0; //compiler does not these bits as bool and there is no implicit conversion, so need 1/0
LATA1 = v & 2 ? 1 : 0;
LATA2 = v & 4 ? 1 : 0;
LATC5 = v & 8 ? 1 : 0;
}
int main(){
OSCCONbits.IRCF = 0b1101; //default is 500khz MF, set to 4MHz HF
//RC1=encoderA, RC2=encoderB
ANSC1 = 0, ANSC2 = 0; //analog input off, digital on, already set to input out of reset
nWPUEN = 0; //global enable weak pullups
WPUC1 = 1, WPUC2 = 1; //enable pullups of AB pins
ledSet( 0 ); //init leds
bool a = 1, b = 1;
uint8_t count = 0; //value for leds (0-3, other bits ignored)
while(1){
while( a == RC1 ){} //wait for A to change
b = RC2; //get B state
if( a==0 && b==0 ){ ledSet( ++count ); }
while( b == RC2 ){} //wait for B to change
a = RC1; //get A state
if( a==0 && b==0 ){ ledSet( --count ); }
}
}