// Pines del encoder
const int pinA = 2;
const int pinB = 3;

// Variables para almacenar el conteo de pulsos
volatile long pulseCount = 0;
volatile int lastEncoded = 3;

void setup() {
  // Configurar los pines del encoder como entradas
  pinMode(pinA, INPUT);
  pinMode(pinB, INPUT);

  // Habilitar las resistencias de pull-up internas
  digitalWrite(pinA, HIGH);
  digitalWrite(pinB, HIGH);

  // Adjuntar interrupciones a los pines del encoder
  attachInterrupt(digitalPinToInterrupt(pinA), updateEncoder, CHANGE);
  attachInterrupt(digitalPinToInterrupt(pinB), updateEncoder, CHANGE);

  // Iniciar la comunicación serie para monitorear los datos
  Serial.begin(9600);
}

void loop() {
  // Imprimir el conteo de pulsos
  Serial.println(pulseCount/4);
  delay(100);
}

void updateEncoder() {
  
  // Leer los estados de los pines del encoder
  int MSB = digitalRead(pinA); // MSB = Most Significant Bit
  int LSB = digitalRead(pinB); // LSB = Least Significant Bit

  // Combinar los estados de los pines en un solo número
  int encoded = (MSB << 1) | LSB;
  int sum = (lastEncoded << 2) | encoded;

  // Determinar la dirección del giro y actualizar el conteo de pulsos
  if (sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) pulseCount++;
  if (sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) pulseCount--;

  // Actualizar el valor del último estado leído
  lastEncoded = encoded;
}