#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 10, 9, 8, 7);

// Input & Button Logic
const int numOfInputs = 4;
const int inputPins[numOfInputs] = {5, 4, 3, 2};
int inputState[numOfInputs];
int lastInputState[numOfInputs] = {LOW, LOW, LOW, LOW};
long lastDebounceTime[numOfInputs] = {0, 0, 0, 0};
long debounceDelay = 50; // Increase debounce delay for better stability

// LCD Menu Logic
const int numOfScreens = 5;
int currentScreen = 0;
String screens[numOfScreens][2] = {
  {"Motor Extruder", "Rpm"}, 
  {"Motor Penarik", "Rpm"}, 
  {"Motor Pengarah", "Rpm"},
  {"Motor Penggulung", "Rpm"}, 
  {"Fan", "Secs"}
};
float parameters[numOfScreens];
bool screenChanged = true; // Flag to check if screen needs update

// Timing for parameter change
long lastParameterChangeTime[numOfInputs - 2] = {0, 0}; // Separate timing for increase/decrease
long parameterChangeInterval = 125; // 1 second interval

void setup() {
  for (int i = 0; i < numOfInputs; i++) {
    pinMode(inputPins[i], INPUT);
    digitalWrite(inputPins[i], HIGH); // pull-up 20k
  }
  // Serial.begin(9600);
  lcd.begin(16, 2);
  printScreen(); // Initial screen display
}

void loop() {
  setInputFlags();
  resolveInputFlags();
}

void setInputFlags() {
  for (int i = 0; i < numOfInputs; i++) {
    int reading = digitalRead(inputPins[i]);
    if (reading != lastInputState[i]) {
      lastDebounceTime[i] = millis();
    }
    if ((millis() - lastDebounceTime[i]) > debounceDelay) {
      if (reading != inputState[i]) {
        inputState[i] = reading;
        if (inputState[i] == HIGH) {
          inputAction(i);
        }
      }
    }
    lastInputState[i] = reading;
  }
}

void resolveInputFlags() {
  unsigned long currentMillis = millis();
  for (int i = 2; i < numOfInputs; i++) {
    if (inputState[i] == LOW) { // Check if button is held down
      if (currentMillis - lastParameterChangeTime[i - 2] >= parameterChangeInterval) {
        parameterChange(i - 2); // Adjust parameter continuously every 1 second
        lastParameterChangeTime[i - 2] = currentMillis; // Reset the timer
      }
    }
  }
  if (screenChanged) {
    printScreen(); // Update screen only if there are changes
    screenChanged = false; // Reset flag after updating
  }
}

void inputAction(int input) {
  if (input == 0) {
    if (currentScreen == 0) {
      currentScreen = numOfScreens - 1;
    } else {
      currentScreen --;
    }
    screenChanged = true; // Set flag to update screen
  } else if (input == 1) {
    if (currentScreen == numOfScreens - 1) {
      currentScreen = 0;
    } else {
      currentScreen ++;
    }
    screenChanged = true; // Set flag to update screen
  }
}

void parameterChange(int key) {
  if (key == 0) {
    parameters[currentScreen]+=0.05;
  } else if (key == 1) {
    parameters[currentScreen]-=0.05;
  }
  screenChanged = true; // Set flag to update screen
}

void printScreen() {
  lcd.clear();
  lcd.print(screens[currentScreen][0]);
  lcd.setCursor(0, 1);
  lcd.print(parameters[currentScreen]);
  lcd.print(" ");
  lcd.print(screens[currentScreen][1]);
}
uno:A5.2
uno:A4.2
uno:AREF
uno:GND.1
uno:13
uno:12
uno:11
uno:10
uno:9
uno:8
uno:7
uno:6
uno:5
uno:4
uno:3
uno:2
uno:1
uno:0
uno:IOREF
uno:RESET
uno:3.3V
uno:5V
uno:GND.2
uno:GND.3
uno:VIN
uno:A0
uno:A1
uno:A2
uno:A3
uno:A4
uno:A5
lcd:VSS
lcd:VDD
lcd:V0
lcd:RS
lcd:RW
lcd:E
lcd:D0
lcd:D1
lcd:D2
lcd:D3
lcd:D4
lcd:D5
lcd:D6
lcd:D7
lcd:A
lcd:K
r1:1
r1:2
btn1:1.l
btn1:2.l
btn1:1.r
btn1:2.r
btn2:1.l
btn2:2.l
btn2:1.r
btn2:2.r
btn3:1.l
btn3:2.l
btn3:1.r
btn3:2.r
btn4:1.l
btn4:2.l
btn4:1.r
btn4:2.r