/*
   https://www.circuitstate.com/tutorials/interfacing-incremental-rotary-encoder-with-arduino/

   
   add: debouncing

*/

int pulseCount; // Rotation step count
int SIG_A = 0; // Pin A output
int SIG_B = 0; // Pin B output
int lastSIG_A = 0; // Last state of SIG_A
int lastSIG_B = 0; // Last state of SIG_B
int Pin_A = 27; // Interrupt pin (digital) for A (change your pins here)
int Pin_B = 14; // Interrupt pin (digital) for B

const unsigned long lamaTunda = 5;


void setup() {
  SIG_B = digitalRead (Pin_B); // Current state of B
  SIG_A = (SIG_B > 0) ? 0 : 1; // Let them be different
  // Attach iterrupt for state change, not rising or falling edges
  attachInterrupt (digitalPinToInterrupt (Pin_A), A_CHANGE, CHANGE);
  Serial.begin (9600);
}

void loop() {
  // Does nothing here. Add your code here.
  delay(2000); //Penting untuk menaruh delay ini untuk menghemat...
  //...sumber daya prosesor web app Wokwi.
}

void A_CHANGE() { // Interrupt Service Routine (ISR)
  detachInterrupt (0); // Important

  static unsigned long lastInterruptTime = 0;

  unsigned long interruptTime = millis();

  // If interrupts come faster than 5ms, assume it's a bounce and ignore
  if (interruptTime - lastInterruptTime > lamaTunda) {
    SIG_A = digitalRead (Pin_A); // Read state of A
    SIG_B = digitalRead (Pin_B); // Read state of B

    if ((SIG_B == SIG_A) && (lastSIG_B != SIG_B)) {
      pulseCount--; // Counter-clockwise rotation
      lastSIG_B = SIG_B;
      Serial.print (pulseCount);
      Serial.println (" - Reverse");
    }

    else if ((SIG_B != SIG_A) && (lastSIG_B == SIG_B)) {
      pulseCount++; // Clockwise rotation
      lastSIG_B = SIG_B > 0 ? 0 : 1; // Save last state of B
      Serial.print (pulseCount);
      Serial.println (" - Forward");
    }
    attachInterrupt (digitalPinToInterrupt (Pin_A), A_CHANGE, CHANGE);
  }
}