/*
  RC Car lap timer with code borrowed heavily from Debounce!
  Tom Goff Sept 2023
  Feel free to share
*/

// constants won't change. They're used here to set pin numbers:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 20, 4); // set the LCD address to 0x27 for a 16 chars and 2 line display

const int buttonPin = 10;    // the number of the pushbutton pin
const int buttonPin2 = 11;   // the number of the pushbutton pin
const int ledPin = 13;       // the number of the LED pin

// Variables will change:
int ledState = LOW;          // the current state of the output pin
int readingState;             // the current reading from the input pin
int lastReadingState = LOW;   // the previous reading from the input pin
int analogVal;               // value read from the LDR
int analogThresh = 900;      //Threshold value to turn on / off timer
bool reading;               
unsigned long pre = 0;        
long interval  = 98;
int ms = 0, sec = 0, minute = 0;
int buzzCnt;
bool buzzBit;

// the following variables are unsigned longs because the time, measured in
// milliseconds, will quickly become a bigger number than can be stored in an int.
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 80;    // the debounce time; increase if the output flickers


void setup() {
  Serial.begin(9600);
  lcd.init();                      // initialize the lcd
  lcd.init();
  // Print a message to the LCD on ititialisation
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("00");
  lcd.print(":");
  lcd.print("00");
  lcd.print(":");
  lcd.print("00");
  lcd.setCursor(0, 1);
  lcd.print("RC LAP TIMER");

  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(buttonPin2, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);

  // set initial LED state
  digitalWrite(ledPin, ledState);
  //  attachInterrupt(digitalPinToInterrupt(buttonPin), restart, FALLING);
}

void loop() {
  
  // The if statement below is to reset the laptimer
  if (digitalRead(buttonPin) == LOW) {
    ledState = 0;
    ms = 0, sec = 0, minute = 0;
    lcd.setCursor(0, 0);
    lcd.print("00");
    lcd.print(":");
    lcd.print("00");
    lcd.print(":");
    lcd.print("00");
  }

  analogVal = analogRead(A1); // read the state of the light sensor and then convert it into a switch:
  bool pin2Val = digitalRead(buttonPin2);
  Serial.println (analogVal);

  if ((analogVal < analogThresh) || (pin2Val == HIGH)) {
    reading = 0;
  }
  
  if ((analogVal > analogThresh) || (pin2Val == LOW)) {
    reading = 1;
  }

  // check to see if either the theshold value has been changed or the start / stop button has been pressed.
  if (reading != lastReadingState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer than the debounce
    // delay, so take it as the actual current state:

    // check if the reading state has changed:
    if (reading != readingState) {
      buzzCnt++;
      if (buzzCnt % 2 ==0){
             tone(8, 1000, 200);
      }

      readingState = reading;

      // only toggle the LED if the new button state is HIGH
      if (readingState == HIGH) {
        ledState = !ledState;
      }
    }
  }

  // set the LED:
  digitalWrite(ledPin, ledState);


  // save the reading. Next time through the loop, it'll be the lastButtonState:
  lastReadingState = reading;
  if (ledState == 1) {
    timePrint();

  }
  Serial.println(ledState);
  digitalRead (buttonPin);

}

// function to print current time to LCD Screen
void timePrint() {

  unsigned long curr = millis();
  Serial.println("in time loop");
  if (curr - pre > interval) {
    pre = curr;
    ms++;
    if (ms == 10) {
      sec++;
      ms = 0;
    }
    if (sec == 60) {
      sec = 0;
      minute++;
    }
    lcd.setCursor(0, 0);
    if (minute < 10)  lcd.print("0");
    lcd.print(minute);
    lcd.print(":");
    if (sec < 10)  lcd.print("0");
    lcd.print(sec);
    lcd.print(":");
    lcd.print(ms);
    
  }
}
