#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>

// Define the I2C LCD object
LiquidCrystal_I2C lcd(0x27, 20, 4);  // I2C address may vary, adjust if necessary

// Define the keypad layout
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {9, 8, 7, 6};     // Connect to the row pinouts of the keypad
byte colPins[COLS] = {5, 4, 3, 2};     // Connect to the column pinouts of the keypad
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

// Variables
int menuState = 0;     // Current menu state
int selection = 0;     // Current selected option
bool stopped = 0;  // Flag to indicate if it's stopped
int releasePin = 13;
int awarePin = 12;
const int pressureSensorPin = A0;     // Pinul pentru senzorul de presiune (A0)
const int outputPin = 11;            // Pinul pentru tensiunea de ieșire
const int pressureRange = 2500;      // Plaja de presiuni (milibari) - 0 până la 2500
const int pressureStep = 10;         // Creșterea presiunii la fiecare jumătate de secundă (10 milibari)
const int pressureDifference = 0;  // Diferența de presiune pentru oprire (200 milibari)


void setup() {
  lcd.init();   // Initialize the LCD
  lcd.backlight();
  lcd.setCursor(5,1);
  lcd.print("Pressure");
  lcd.setCursor(4,2);
  lcd.print("Tester v1.0");
  delay(2000);
  updateMenu();
  pinMode(outputPin, OUTPUT);
  pinMode(releasePin, OUTPUT);
  pinMode(awarePin, OUTPUT);

  digitalWrite(releasePin, LOW);
  digitalWrite(awarePin, LOW);
  analogWrite(outputPin ,LOW);
}

void loop() {
   pinMode(releasePin, OUTPUT);
  char key = keypad.getKey();  // Read the keypad input

  if (key != NO_KEY) {
    // Handle key press
    switch (key) {
      case 'A':
        upKeyPressed();
        break;
      case 'B':
        downKeyPressed();
        break;
      case 'C':
        enterKeyPressed();
        break;
      case 'D':
        dKeyPressed();
        break;
      default:
        break;
    }
  }
}

void upKeyPressed() {
  if (menuState == 0) {
    if (selection > 0) {
      selection--;
      updateMenu();
    }
  }
}

void downKeyPressed() {
  if (menuState == 0) {
    if (selection < 1) {
      selection++;
      updateMenu();
    }
  }
}

void enterKeyPressed() {
  if (menuState == 0) {
    switch (selection) {
      case 0:
        lcd.clear();
        lcd.print("Manual Input:");
        manual_input();    // Apelăm funcția pentru "manual input"
        // Perform action for Manual Input
        //ActionLedon();
        break;
      case 1:
        lcd.clear();
        lcd.print("Burst Test:");
        burstTest();
        // Perform action for Burst Test
        //ActionLedon();
        break;
      default:
        break;
    }
    menuState = 1;  // Change menu state to indicate selection made
  }
}

void dKeyPressed() {
  if (menuState ==1) {
    if (stopped==0){ 
      lcd.clear();
      lcd.setCursor(4,0);
      lcd.print(" Test Ended ");
      lcd.setCursor(2,1);
      // Perform action for stop
      ActionLedon();
      stopped = 1;
     
    } else{
      lcd.clear();
      stopped = 0;
      updateMenu();
      menuState=0;
      ActionLedOff();
    
    }
  }
}
//====================================== burst test==================================
void burstTest() {
  lcd.clear();
  lcd.print("Burst Test:");

  int currentPressure = 0;
  int lastPressureValue = 0;  // Variabilă pentru a memora ultima valoare a presiunii înainte de cădere
  stopped = false;

  while (currentPressure <= pressureRange && !stopped) {
    // Setează tensiunea de ieșire în funcție de presiunea curentă
    int outputVoltage = map(currentPressure, 0, pressureRange, 0, 255);
    analogWrite(outputPin, outputVoltage);
    digitalWrite(awarePin, HIGH);

    // Citește valoarea senzorului de presiune (A0)
    int sensorValue = analogRead(pressureSensorPin);

    // Calculează valoarea presiunii în milibari
    int pressureValue = map(sensorValue, 0, 1024, 0, pressureRange);

    // Afișează valoarea presiunii pe LCD
    lcd.setCursor(0, 1);
    lcd.print("Pressure: ");
    lcd.print(pressureValue);
    lcd.print(" mBar");

    // Verifică dacă a avut loc o cădere bruscă de presiune
    if (lastPressureValue > 0 && abs(pressureValue - lastPressureValue) >= pressureDifference) {
      stopped = true;
    }

    // Actualizează ultima valoare a presiunii
    lastPressureValue = pressureValue;

    // Așteaptă 0.5 secunde pentru următoarea iterație
    delay(500);

    // Crește valoarea presiunii pentru următoarea iterație
    currentPressure += pressureStep;
  }

  // Oprește tensiunea de ieșire
  analogWrite(outputPin, LOW);
  digitalWrite(awarePin, LOW);
  digitalWrite(releasePin, HIGH);
  delay(500);
  digitalWrite(releasePin,LOW);


  if (stopped) {
    lcd.clear();
    lcd.setCursor(2, 0);
    lcd.print("Pressure drop!");
    lcd.setCursor(2, 1);
    lcd.print("Last pressure: ");
    lcd.setCursor(4,2);
    lcd.print(lastPressureValue) and lcd.print(" mBar");
  } else {
    lcd.setCursor(0, 2);
    lcd.print("Test completed!");
  }

  //delay(2000);

  // Revine la meniul principal
  stopped = false;
  //updateMenu();
 // menuState = 0;
}



void updateMenu() {
  lcd.clear();
  lcd.print("Menu:");
  lcd.setCursor(0, 1);
  if (selection == 0) {
    lcd.print("> Manual Input");
    lcd.setCursor(0, 2);
    lcd.print("  Burst Test");
  } else {
    lcd.print("  Manual Input");
    lcd.setCursor(0, 2);
    lcd.print("> Burst Test");
  }
}

//====================== manual input=====================================
void manual_input() {
  lcd.clear();
  lcd.print("Insert pressure:");

  int inputValue = 0;
  bool inputCompleted = false;
  bool testCompleted = false;

  while (!inputCompleted) {
    char key = keypad.getKey();

    if (key != NO_KEY) {
      if (key >= '0' && key <= '9') {
        // Actualizează valoarea introdusă pe baza tastelor numerice
        inputValue = inputValue * 10 + (key - '0');
        inputValue = constrain(inputValue, 1, 2500,0 , 5); // Asigură că valoarea se încadrează în plajă
        lcd.setCursor(0, 1);
        lcd.print("Input P:      ");  // Curățăm spațiul pentru a afișa valoarea introdusă
        lcd.setCursor(9, 1);
        lcd.print(inputValue);
        lcd.print(" mBar");
      } else if (key == 'C') {
        // La apăsarea tastei C, pornim tensiunea de ieșire și ieșim din bucla de introducere manuală
        analogWrite(outputPin, inputValue);
        //analogWrite(Led_1,HIGH);
        inputCompleted = true;
      } else if (key == 'D') {
        // La apăsarea tastei D, ieșim din bucla de introducere manuală și pornim afișarea testului finalizat
        inputCompleted = true;
        testCompleted = true;
      }
    }
  }

  // Testul rulează până când se apasă tasta D
  while (!testCompleted) {
    // Citește valoarea senzorului de presiune (A0)
    int sensorValue = analogRead(pressureSensorPin);

    // Calculează valoarea presiunii în milibari
    int pressureValue = map(sensorValue, 0, 1024, 5, 2500);

    // Afișează valorile presiunii pe LCD
    lcd.setCursor(0, 2);
    lcd.print("P. Read:     ");
    lcd.setCursor(10, 2);
    lcd.print(pressureValue);
    lcd.print(" mBar");

    lcd.setCursor(0, 1);
    lcd.print("Input P:     ");
    lcd.setCursor(9, 1);
    lcd.print(inputValue);
    lcd.print(" mBar");

    // Oprește tensiunea de ieșire dacă presiunea a ajuns la valoarea dorită
    if (pressureValue >= inputValue) {
      //digitalWrite(outputPin, LOW);
      lcd.setCursor(0, 3);
      //lcd.print("Test completed!");
    }
     delay(15000);
    if (pressureValue > inputValue){
       //delay(3000);
      lcd.setCursor(0,3);
      lcd.print("--=Test Fail!!=--");
      
    }

    if (pressureValue<inputValue){
      lcd.setCursor(0,3);
      lcd.print("--=Test Fail!!=--");
      
    }
    if (pressureValue == inputValue){
      lcd.setCursor(0,3);
      lcd.print("--=Test Pass!!=--");
    }
    digitalWrite(releasePin, LOW);
    analogWrite(outputPin, 0);
    break;
    
  
    // Verifică dacă a fost apăsată tasta D pentru a ieși din test
    if (keypad.getKey() == 'D') {
      testCompleted = true;
      dKeyPressed();
      menuState = 0;
    }
  } 
}

void ActionLedon(){
 digitalWrite(releasePin, HIGH);
 //delay(600000);
}

void ActionLedOff(){
  digitalWrite(releasePin, LOW);
}
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
keypad:R1
keypad:R2
keypad:R3
keypad:R4
keypad:C1
keypad:C2
keypad:C3
keypad:C4
lcd1:GND
lcd1:VCC
lcd1:SDA
lcd1:SCL
led1:A
led1:C
led2:A
led2:C
pot1:GND
pot1:SIG
pot1:VCC
led3:A
led3:C