AdaEncoder: a library for use with simple quadrature encoders

Thanks, vasquo. Anyway, your post prompted me to create some test code, and I hope to use this to ensure the integrity of the library in the future... (this works for v. 0.7beta and above only, but the basic algorithm applies to 0.5 as well)

// Version 1.0: OO version

#include <ByteBuffer.h>
#include <digitalWriteFast.h>
#include <ooPinChangeInt.h> // necessary otherwise we get undefined reference errors.
#define DEBUG
#ifdef DEBUG
ByteBuffer printBuffer(200);
#endif
#define SWINTR_DEBUG // To debug using software interrupts on your two pins, define this.
                    // Then in your sketch, set your pins as outputs.  Initialize them as you
                    // desire, attach an interrupt, then the interrupt code will be called.
                    // CAUTION: Make sure you do NOT have any switches connected to those outputs,
                    // or you may end up frying your ATmega328!
#include <AdaEncoder.h>

/*
I like to keep this diagram around so I know which Arduino pin
is part of which port.
                  +-\/-+
            PC6  1|    |28  PC5 (AI 5)
      (D 0) PD0  2|    |27  PC4 (AI 4)
      (D 1) PD1  3|    |26  PC3 (AI 3)
      (D 2) PD2  4|    |25  PC2 (AI 2)
 PWM+ (D 3) PD3  5|    |24  PC1 (AI 1)
      (D 4) PD4  6|    |23  PC0 (AI 0)
            VCC  7|    |22  GND
            GND  8|    |21  AREF
            PB6  9|    |20  AVCC
            PB7 10|    |19  PB5 (D 13)
 PWM+ (D 5) PD5 11|    |18  PB4 (D 12)
 PWM+ (D 6) PD6 12|    |17  PB3 (D 11) PWM
      (D 7) PD7 13|    |16  PB2 (D 10) PWM
      (D 8) PB0 14|    |15  PB1 (D 9) PWM
                  +----+*/
// An encoder for every port
#define ENCD_a 2
#define ENCD_b 3
#define ENCC_a A3
#define ENCC_b A4
#define ENCB_a 9
#define ENCB_b 10

AdaEncoder encoderD = AdaEncoder('d', ENCD_a, ENCD_b);
AdaEncoder encoderC = AdaEncoder('c', ENCC_a, ENCC_b);
AdaEncoder encoderB = AdaEncoder('b', ENCB_a, ENCB_b);

int8_t clicks=0;
char id=0;

void setup()
{
  Serial.begin(115200); Serial.println("---------------------------------------");
  Serial.println("AdaEncoder test. Assumes detent position is 1,1 (pin a, pin b).");
  Serial.println("Encoder states: 11->01->00->10->11 (== CCW 1 click)");
  volatile uint8_t portmask0=PCMSK0;
  volatile uint8_t portmask1=PCMSK1;
  volatile uint8_t portmask2=PCMSK2;
  PCMSK0=0; PCMSK1=0; PCMSK2=0; // turn off PinChange interrupts for a minnit
  pinMode(ENCB_a, OUTPUT); pinMode(ENCB_b, OUTPUT);
  digitalWriteFast2(ENCB_a, HIGH); digitalWriteFast2(ENCB_b, HIGH);
  pinMode(ENCC_a, OUTPUT); pinMode(ENCC_b, OUTPUT);
  digitalWriteFast2(ENCC_a, HIGH); digitalWriteFast2(ENCC_b, HIGH);
  pinMode(ENCD_a, OUTPUT); pinMode(ENCD_b, OUTPUT);
  digitalWriteFast2(ENCD_a, HIGH); digitalWriteFast2(ENCD_b, HIGH);
  PCMSK0=portmask0; // interrupts back on.
  PCMSK1=portmask1;
  PCMSK2=portmask2;
}

void changeEncoder(uint8_t pin) {
  if (digitalReadFast2(pin)) { digitalWriteFast2(pin, LOW); }
  else digitalWriteFast2(pin, HIGH);
}

void printEncoderState(uint8_t pina, uint8_t pinb) {
  Serial.print(digitalReadFast2(pina), DEC);
  Serial.println(digitalReadFast2(pinb), DEC);
}

void loop() 
{
  char inChar, outChar;
  // 00 -> 10 -> 11 -> 01 -> 00
  if(Serial.available()) {
    inChar=(Serial.read()); // get command from serial input
    switch (inChar) {
    case '1':
        Serial.print("B-a "); changeEncoder(ENCB_a); printEncoderState(ENCB_a, ENCB_b);
      break;
    case '2':
        Serial.print("B-b "); changeEncoder(ENCB_b); printEncoderState(ENCB_a, ENCB_b);
      break;
    case '5':
        Serial.print("C-a "); changeEncoder(ENCC_a); printEncoderState(ENCC_a, ENCC_b);
      break;
    case '6':
        Serial.print("C-b "); changeEncoder(ENCC_b); printEncoderState(ENCC_a, ENCC_b);
      break;
      case '9':
        Serial.print("D-a "); changeEncoder(ENCD_a); printEncoderState(ENCD_a, ENCD_b);
      break;
      case '0':
        Serial.print("D-b "); changeEncoder(ENCD_b); printEncoderState(ENCD_a, ENCD_b);
      break;
    }
  }
  while ((outChar=(char)printBuffer.get()) != 0) Serial.print(outChar);
  AdaEncoder *thisEncoder=NULL;
  thisEncoder=AdaEncoder::genie();
  if (thisEncoder != NULL) {
    Serial.print(thisEncoder->getID()); Serial.print(':');
    clicks=thisEncoder->query();
    if (clicks != 0) { Serial.print("Clicks: "); Serial.print(clicks, DEC); }
    if (clicks > 0) {
      Serial.println(" CW");
    }
    if (clicks < 0) {
       Serial.println(" CCW");
    }
  }
}

...If I then hit a sequence of numbers in the Monitor screen, I can then demonstrate that the library behaves as expected.

For example, if I hit the following sequence, I simulate switch bounce on the two pins and it registers "CCW" exactly when I expect it:

Number	Output
Typed	
1	B-a 01
1	B-a 11
1	B-a 01
1	B-a 11
1	B-a 01
2	B-b 00
2	B-b 01
2	B-b 00
2	B-b 01
2	B-b 00
1	B-a 10
1	B-a 00
1	B-a 10
1	B-a 00
1	B-a 10
2	B-b 11
 	b:Clicks: -1 CCW