#include <LiquidCrystal_I2C.h>
#include <Adafruit_NeoPixel.h>

// Rotary Encoder Pins
#define pinRotCLK 2
#define pinRotDT 3
#define pinRotBTN 4

// Button Pin
#define pinBTN 5

// Led Strip Pin
#define pinLED 6

// Ultrasonic Sensor
#define pinUsTrig 11
#define pinUsEcho 12

// Lcd Screen Pin
// I2C => SDA A4
// I2C => SCL A5
LiquidCrystal_I2C lcdScreen(0x27, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display

int counter = 0;
int currentStateCLK;
int lastStateCLK;
String currentDir = "";
unsigned long lastButtonPress = 0;


// How many NeoledStrip are attached to the Arduino?
#define NUMPIXELS      25

// When we setup the NeoPixel library, we tell it how many ledStrip, and which pin to use to send signals.
// Note that for older NeoPixel strips you might need to change the third parameter--see the strandTest
// example for more information on possible values.
Adafruit_NeoPixel ledStrip = Adafruit_NeoPixel(NUMPIXELS, pinLED, NEO_GRB + NEO_KHZ400);

void setup() {

  // Set encoder pins as inputs
  pinMode(pinRotCLK, INPUT);
  pinMode(pinRotDT, INPUT);
  pinMode(pinRotBTN, INPUT_PULLUP);
  
  // Set red button pin as input
  pinMode(pinBTN, INPUT_PULLUP);

  // Set Ultrasonic Sensor
  pinMode(pinUsTrig, OUTPUT);
  digitalWrite(pinUsTrig, LOW);
  pinMode(pinUsEcho, INPUT);
  
   // Setup Serial Monitor
  Serial.begin(9600);

  // init lcd display
  lcdScreen.init();
  lcdScreen.backlight();
  lcdScreen.setCursor(0, 0);
  lcdScreen.print(" Ludometre MS56 ");
  
  // This initializes the NeoPixel library.
  ledStrip.begin(); 

  // Read the initial state of pinRotCLK
  lastStateCLK = digitalRead(pinRotCLK);
}

void loop() {

  // Read the current state of pinRotCLK
  currentStateCLK = digitalRead(pinRotCLK);

  // If last and current state of pinRotCLK are different, then pulse occurred
  // React to only 1 state change to avoid double count
  if (currentStateCLK != lastStateCLK  && currentStateCLK == 1) {

    // If the pinRotDT state is different than the pinRotCLK state then
    // the encoder is rotating CCW so decrement
    if (digitalRead(pinRotDT) == currentStateCLK) {
      counter --;
      if (counter <= 0) counter = 0;
      currentDir = "CCW";
    } else {
      // Encoder is rotating CW so increment
      counter ++;
      if (counter >= 24) counter = 24;
      currentDir = "CW";
    }

    Serial.print("Direction: ");
    Serial.print(currentDir);
    Serial.print(" | Counter: ");
    Serial.println(counter);

    ledStrip.clear();
    for (int i=0 ; i <= counter ; i++){
      ledStrip.setPixelColor(i, ledStrip.Color(0, 255, 0));
    }
    ledStrip.show();

  }

  // Remember last pinRotCLK state
  lastStateCLK = currentStateCLK;

  // Read the button state
  int btnState = digitalRead(pinRotBTN);

  //If we detect LOW signal, button is pressed
  if (btnState == LOW) {
    //if 50ms have passed since last LOW pulse, it means that the
    //button has been pressed, released and pressed again
    if (millis() - lastButtonPress > 50) {
      Serial.println("Button pressed!");
      ledStrip.setPixelColor(counter, ledStrip.Color(255, 0, 0));
      ledStrip.show();
    }
  }
  // Read the button state
  int btnRed = digitalRead(pinBTN);

  //If we detect LOW signal, button is pressed
  if (btnRed == LOW) {
    //if 50ms have passed since last LOW pulse, it means that the
    //button has been pressed, released and pressed again
    if (millis() - lastButtonPress > 50) {
      Serial.println("Button pressed!");
      ledStrip.setPixelColor(counter, ledStrip.Color(0, 0, 255));
      ledStrip.show();
      mesure();
    }

    // Remember last button press event
    lastButtonPress = millis();
  }

  // Put in a slight delay to help debounce the reading
  delay(1);
}

float mesure(){
  float duration, distance;

  for (int i=1; i<=10; i++){
    digitalWrite(pinUsTrig, HIGH);
    delayMicroseconds(10); 
    digitalWrite(pinUsTrig, LOW);
    duration = pulseIn(pinUsEcho, HIGH);
    distance += ((duration / 29.41) / 2);
    Serial.println(distance);
  }
  lcdScreen.setCursor(0, 1);
  lcdScreen.print(distance/10);
  return (distance / 10);
}