/*

KY-040 Schema:

Encoder GND to Arduino GND
Encoder + to Arduino 5V
Encoder SW (Switch) to Arduino digital pin 2
Encoder DT (Direction of Turn) to Arduino digital pin 3
Encoder CLK (Click) to Arduino digital pin 4

KY-040 has 30 positions per revolution

Comms at 115200 Bauds

*/


// Based on:
// https://docs.arduino.cc/built-in-examples/digital/Debounce
// https://create.arduino.cc/projecthub/vandenbrande/arduino-rotary-encoder-simple-example-ky-040-b78752

#define CLK 4
#define DT 3
#define SW 2
#define buttonDebounceDelay 50
#define baudRate 115200


int ignoreUntil = millis();

#define DEBUG 1
#ifdef DEBUG == 1
//#define debugTime if ((millis() - lastMillis) > 500) Serial.println(); Serial.print(millis()); lastMillis = millis();
#define debugTime Serial.print(millis()); Serial.print(F(" - "));
#define debug(x) Serial.print(x)
#define debugLn(x) Serial.println(x)
#define debugS(x) Serial.print(F(x))
#define debugSLn(x) Serial.println(F(x))
#else
#define debugTime
#define debug(x) 
#define debugLn(x)
#define debugS(x) 
#define debugSLn(x) 
#endif

#define BIT(n,i) (n>>i&1)

int RotPosition = 0;
int currentSwitchState;
int lastSwitchState;
int lastRotationValue = -1;
int position = 0;
int lastCLK = 1;
int lastDT = 1;
boolean buttonDown;
boolean skipNextClick = true;

unsigned long lastButtonDebounceTime = 0;
unsigned long lastRotationalValueDebounceTime = 0;

void setup() {
  Serial.begin(baudRate);
  Serial.println("**** Starting");
  DDRD = 0x011100000;
  pinMode(SW, INPUT_PULLUP);
 
  // Read the initial button state
  int pinState = PIND;
  lastSwitchState =  BIT(pinState,SW);
  buttonDown = lastSwitchState == LOW;
  currentSwitchState = lastSwitchState;
  lastRotationValue = BIT(pinState,CLK);
}


void loop() {

  // Debounce & read push button

   int portValue = PIND;

  int instantSwitchState = BIT(portValue,SW);
  if (instantSwitchState != lastSwitchState) {
    lastButtonDebounceTime = millis();
  }

  if ((millis() - lastButtonDebounceTime) > buttonDebounceDelay) {

    if (instantSwitchState != currentSwitchState) {
      currentSwitchState = instantSwitchState;
      buttonDown = currentSwitchState == LOW;
      //debugSLn("");
      debugLn(buttonDown ? "Button Down" : "Button Up");
    }
  }
  lastSwitchState = instantSwitchState;

  // Read rotary encoder

  int clkValue = BIT(portValue,CLK);
  int dtValue = BIT(portValue,DT);

    if ((dtValue != lastDT) && (clkValue != lastCLK)) {
      debugTime;
      debugS("CLK ");
      debug(clkValue);
      debugS(" DT ");
      debugLn(dtValue);
      if ((clkValue != lastCLK) && (clkValue == 0)) {
        debugLn((lastDT != clkValue) ? "Clockwise" : "Counterclockwise");
        position += (lastDT != clkValue) ? 1 : -1;
        debugS("Position: ");
        debugLn(position);
      }
      lastCLK = clkValue;
      lastDT = dtValue;
      
   }

}