//--------------------------------- Include Libraries----------------------------------
#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"
#include "HX711.h" //memasukan library HX711
//--------------------------------- Include Libraries----------------------------------

//--------------------------------- Define and Constant--------------------------------
const int backButton    = 16;       //16
const int selectButton  = 17;       //17
const int upButton      = 18;       //18
const int downButton    = 19;       //19
#define TFT_DC 48
#define TFT_CS 53
#define TFT_MOSI 51
#define TFT_CLK 52
#define TFT_MISO 50
#define TFT_RST 49
#define TFT_RST  -1  // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);

HX711 scale; // HX711(DT,SCK)
HX711 scale2;
HX711 scale3;
HX711 scale4;

float calibration_factor = 7050; // nilai kalibrasi (sesuaikan dari hasil nilai percobaan program sebelumnya yaitu program kalibrasi)
float calibration_factor2 = 7050;
float calibration_factor3 = 7050;
float calibration_factor4 = 7050;

int IRSensor = 6;
int IRSensor2 = 7;
int IRSensor3 = 8;
int IRSensor4 = 9;

int valvepin = 2;
int valvepin2 = 3;
int valvepin3 = 4;
int valvepin4 = 5;

unsigned long prevMillis = 0;
//--------------------------------- Define and Constant--------------------------------

//--------------------------------- Global Variable------------------------------------
int MenuX = 0;
int MenuY = 0;

bool backButtonActive = false;
bool selectButtonActive = false;
bool upButtonActive = false;
bool downButtonActive = false;


//--------------------------------- Global Variable------------------------------------

//--------------------------------- User Defined Fucntion Stage 1----------------------
void KeyUpdate(bool back, bool select, bool up, bool dw, int yback, int yselect) {
  if (back) {
    if (backButtonActive) {
      MenuX--;
      MenuY = yback;
    }
  }
  if (select) {
    if (selectButtonActive) {
      MenuX++;
      MenuY = yselect;
    }
  }
  if (up) {
    if (upButtonActive) {
      MenuY--;
    }
  }
  if (dw) {
    if (downButtonActive) {
      MenuY++;
    }
  }
}



void DisplayUpdate() {
  if (MenuX == 0) {
    tft.fillScreen(ILI9341_BLACK);
    tft.setTextColor(ILI9341_BLACK);
    tft.fillRect(0, 100, 250, 40, ILI9341_GREEN);
    tft.setCursor(10, 93 + 20);
    (MenuY == 0) ? tft.print("> AUTOMATIC") : tft.print("AUTOMATIC");
    tft.fillRect(0, 150, 250, 40, ILI9341_GREEN);
    tft.setCursor(10, 145 + 20);
    (MenuY == 1) ? tft.print("> MANUAL") : tft.print("MANUAL");
    tft.fillRect(0, 200, 250, 40, ILI9341_GREEN);
    tft.setCursor(10, 193 + 20);
    (MenuY == 2) ? tft.print("> CALIBRATION") : tft.print("CALIBRATION");
  }

  if (MenuX == 1 && MenuY == 0) {
    tft.fillScreen(ILI9341_BLACK);
    tft.setTextColor(ILI9341_WHITE);
    tft.setCursor(63, 0 + 20);
    tft.print("AUTOMATIC");

    tft.setTextColor(ILI9341_BLACK);
    tft.fillRect(35, 50, 80, 40, ILI9341_GREEN);
    tft.setCursor(65, 43 + 20);
    tft.print("ON");

    tft.fillRect(124, 50, 80, 40, ILI9341_RED);
    tft.setCursor(150, 43 + 20);
    tft.print("OFF");
  }
  if (MenuX == 1 && MenuY == 1) {
    tft.fillScreen(ILI9341_BLACK);
    tft.setTextColor(ILI9341_WHITE);
    tft.setCursor(84, 0 + 20);
    tft.print("MANUAL");

    tft.setTextColor(ILI9341_BLACK);
    tft.fillRect(35, 50, 169, 40, ILI9341_BLUE);
    tft.setCursor(83, 43 + 20);
    tft.print("VALVE 1");
    tft.fillRect(35, 100, 80, 40, ILI9341_GREEN);
    tft.setCursor(65, 93 + 20);
    tft.print("ON");
    tft.fillRect(124, 100, 80, 40, ILI9341_RED);
    tft.setCursor(150, 93 + 20);
    tft.print("OFF");

    tft.fillRect(35, 150, 169, 40, ILI9341_GREEN);
    tft.setCursor(83, 143 + 20);
    tft.print("VALVE 2");
    tft.fillRect(35, 200, 80, 40, ILI9341_GREEN);
    tft.setCursor(65, 193 + 20);
    tft.print("ON");
    tft.fillRect(124, 200, 80, 40, ILI9341_RED);
    tft.setCursor(150, 193 + 20);
    tft.print("OFF");

  }
  if (MenuX == 1 && MenuY == 2) {
    tft.fillScreen(ILI9341_BLACK);

    tft.setTextColor(ILI9341_WHITE);
    tft.setCursor(84, 0 + 20);
    tft.print("MANUAL");

    tft.setTextColor(ILI9341_BLACK);
    tft.fillRect(35, 50, 169, 40, ILI9341_GREEN);
    tft.setCursor(83, 43 + 20);
    tft.print("VALVE 3");
    tft.fillRect(35, 100, 80, 40, ILI9341_GREEN);
    tft.setCursor(65, 93 + 20);
    tft.print("ON");
    tft.fillRect(124, 100, 80, 40, ILI9341_RED);
    tft.setCursor(150, 93 + 20);
    tft.print("OFF");

    tft.fillRect(35, 150, 169, 40, ILI9341_BLUE);
    tft.setCursor(83, 143 + 20);
    tft.print("VALVE 4");
    tft.fillRect(35, 200, 80, 40, ILI9341_GREEN);
    tft.setCursor(65, 193 + 20);
    tft.print("ON");
    tft.fillRect(124, 200, 80, 40, ILI9341_RED);
    tft.setCursor(150, 193 + 20);
    tft.print("OFF");

  }

  if (MenuX == 1 && MenuY >= 3 && MenuY <= 6) {
    //tft.fillScreen(ILI9341_BLACK);
    tft.setTextColor(ILI9341_WHITE);
    tft.setCursor(53, 0 + 20);
    tft.print("CALIBRATION");
    tft.setTextColor(ILI9341_BLACK);
    tft.fillRect(0, 55, 250, 40, ILI9341_GREEN);
    tft.setCursor(10, 50 + 20);
    (MenuY == 3) ? tft.print("> TIMBANGAN 1") : tft.print("TIMBANGAN 1");
    tft.fillRect(0, 105, 250, 40, ILI9341_GREEN);
    tft.setCursor(10, 100 + 20);
    (MenuY == 4) ? tft.print("> TIMBANGAN 2") : tft.print("TIMBANGAN 2");
    tft.fillRect(0, 155, 250, 40, ILI9341_GREEN);
    tft.setCursor(10, 150 + 20);
    (MenuY == 5) ? tft.print("> TIMBANGAN 3") : tft.print("TIMBANGAN 3");
    tft.fillRect(0, 205, 250, 40, ILI9341_GREEN);
    tft.setCursor(10, 200 + 20);
    (MenuY == 6) ? tft.print("> TIMBANGAN 4") : tft.print("TIMBANGAN 4");
  }


  if (MenuX == 2 && MenuY >= 0 && MenuY <= 2) {
    tft.fillScreen(ILI9341_BLACK);
    tft.setTextColor(ILI9341_WHITE);
    tft.setCursor(53, 0 + 20);
    tft.print("TIMBANGAN 1");

    tft.setTextColor(ILI9341_BLACK);
    tft.fillRect(0, 55, 250, 40, ILI9341_GREEN);
    tft.setCursor(10, 50 + 20);
    (MenuY == 0) ? tft.print("> BATAS 1") : tft.print("BATAS 1");

    tft.fillRect(0, 105, 250, 40, ILI9341_GREEN);
    tft.setCursor(10, 100 + 20);
    (MenuY == 1) ? tft.print("> BATAS 2") : tft.print("BATAS 2");

    tft.fillRect(0, 155, 250, 40, ILI9341_GREEN);
    tft.setCursor(10, 150 + 20);
    (MenuY == 2) ? tft.print("> CALIBRATION") : tft.print("CALIBRATION");

  }


  if (MenuX == 2 && MenuY >= 3 && MenuY <= 5) {
    tft.fillScreen(ILI9341_BLACK);
    tft.setTextColor(ILI9341_WHITE);
    tft.setCursor(53, 0 + 20);
    tft.print("TIMBANGAN 2");

    tft.setTextColor(ILI9341_BLACK);
    tft.fillRect(0, 55, 250, 40, ILI9341_GREEN);
    tft.setCursor(10, 50 + 20);
    (MenuY == 3) ? tft.print("> BATAS 1") : tft.print("BATAS 1");

    tft.fillRect(0, 105, 250, 40, ILI9341_GREEN);
    tft.setCursor(10, 100 + 20);
    (MenuY == 4) ? tft.print("> BATAS 2") : tft.print("BATAS 2");

    tft.fillRect(0, 155, 250, 40, ILI9341_GREEN);
    tft.setCursor(10, 150 + 20);
    (MenuY == 5) ? tft.print("> CALIBRATION") : tft.print("CALIBRATION");

  }

  if (MenuX == 2 && MenuY >= 6 && MenuY <= 8) {
    tft.fillScreen(ILI9341_BLACK);
    tft.setTextColor(ILI9341_WHITE);
    tft.setCursor(53, 0 + 20);
    tft.print("TIMBANGAN 3");

    tft.setTextColor(ILI9341_BLACK);
    tft.fillRect(0, 55, 250, 40, ILI9341_GREEN);
    tft.setCursor(10, 50 + 20);
    (MenuY == 6) ? tft.print("> BATAS 1") : tft.print("BATAS 1");

    tft.fillRect(0, 105, 250, 40, ILI9341_GREEN);
    tft.setCursor(10, 100 + 20);
    (MenuY == 7) ? tft.print("> BATAS 2") : tft.print("BATAS 2");

    tft.fillRect(0, 155, 250, 40, ILI9341_GREEN);
    tft.setCursor(10, 150 + 20);
    (MenuY == 8) ? tft.print("> CALIBRATION") : tft.print("CALIBRATION");

  }


  if (MenuX == 2 && MenuY >= 9 && MenuY <= 11) {
    tft.fillScreen(ILI9341_BLACK);
    tft.setTextColor(ILI9341_WHITE);
    tft.setCursor(53, 0 + 20);
    tft.print("TIMBANGAN 4");

    tft.setTextColor(ILI9341_BLACK);
    tft.fillRect(0, 55, 250, 40, ILI9341_GREEN);
    tft.setCursor(10, 50 + 20);
    (MenuY == 9) ? tft.print("> BATAS 1") : tft.print("BATAS 1");

    tft.fillRect(0, 105, 250, 40, ILI9341_GREEN);
    tft.setCursor(10, 100 + 20);
    (MenuY == 10) ? tft.print("> BATAS 2") : tft.print("BATAS 2");

    tft.fillRect(0, 155, 250, 40, ILI9341_GREEN);
    tft.setCursor(10, 150 + 20);
    (MenuY == 11) ? tft.print("> CALIBRATION") : tft.print("CALIBRATION");

  }

}//to Display by location
//--------------------------------- User Defined Fucntion Stage 1----------------------

//--------------------------------- User Defined Fucntion Stage 2----------------------
void ButtonUpdate () {
  switch (MenuX) {
    case 0:
      switch (MenuY) {
        case 0: //automatic
          KeyUpdate(false, true, false, true, 0, 0);
          break;
        case 1: //manual
          KeyUpdate(false, true, true, true, 0, 1);
          break;
        case 2: //calibartion
          KeyUpdate(false, true, true, false, 0, 3);
          break;
      }
      break;
    case 1:
      switch (MenuY) {
        case 0: //automatic selection
          KeyUpdate(true, false, false, false, 0, 0);
          break;
        case 1: // Manual OP Valve 1 dan 2
          KeyUpdate(true, true, false, true, 0, 0);
          break;
        case 2: // Manual OP Valve 3 dan 4
          KeyUpdate(true, true, true, false, 0, 0);
          break;
        case 3: //Timbangan 1
          KeyUpdate(true, true, false, true, 0, 0);
          break;
        case 4: //Timbangan 2
          KeyUpdate(true, true, true, true, 0, 3);
          break;
        case 5: //Timbangan 3
          KeyUpdate(true, true, true, true, 0, 6);
          break;
        case 6: //Timbangan 4
          KeyUpdate(true, true, true, true, 0, 9);

          break;
      }
      break;
    case 2:
      switch (MenuY) {
        case 0:
          KeyUpdate(true, true, false, true, 3, 0);
          break;
        case 1:
          KeyUpdate(true, true, true, true, 3, 0);
          break;
        case 2:
          KeyUpdate(true, true, true, true, 3, 0);
          break;
        case 3:
          KeyUpdate(true, true, true, true, 3, 0);
          break;
        case 4:
          KeyUpdate(true, true, true, true, 3, 0);
          break;
        case 5:
          KeyUpdate(true, true, true, true, 3, 0);
          break;
        case 6:
          KeyUpdate(true, true, true, true, 3, 0);
          break;
        case 7:
          KeyUpdate(true, true, true, true, 3, 0);
          break;
        case 8:
          KeyUpdate(true, true, true, true, 3, 0);
          break;
        case 9:
          KeyUpdate(true, true, true, true, 3, 0);
          break;
        case 10:
          KeyUpdate(true, true, true, true, 3, 0);
          break;
        case 11:
          KeyUpdate(true, true, true, true, 3, 0);
          break;
      }
      break;
  }

  backButtonActive = false;
  selectButtonActive = false;
  upButtonActive = false;
  downButtonActive = false;
  DisplayUpdate();
  Serial.print(MenuX);
  Serial.print(" ");
  Serial.println(MenuY);
}//what button DO
//--------------------------------- User Defined Fucntion Stage 2----------------------

//--------------------------------- User Defined Fucntion Stage 3----------------------
void HWUpdate() {
  if (!digitalRead(backButton)) {
    backButtonActive = true;
    ButtonUpdate ();
    //below two line to avoid bouncing
    delay(100);
    while (!digitalRead(backButton));
  }
  if (!digitalRead(selectButton)) {
    selectButtonActive = true;
    ButtonUpdate ();
    //below two line to avoid bouncing
    delay(100);
    while (!digitalRead(selectButton));
  }
  if (!digitalRead(upButton)) {
    upButtonActive = true;
    ButtonUpdate ();
    //below two line to avoid bouncing
    delay(100);
    while (!digitalRead(upButton));
  }
  if (!digitalRead(downButton)) {
    downButtonActive = true;
    ButtonUpdate ();
    //below two line to avoid bouncing
    delay(100);
    while (!digitalRead(downButton));
  }
}//to get button state
//--------------------------------- User Defined Fucntion Stage 3----------------------


//--------------------------------- Setup----------------------------------------------
void setup() {
  //Initialize TFT LCD
  tft.begin();
  Serial.begin(9600);

  Serial.println("Memulai program kalibrasi pada sensor berat");
  Serial.println("Pastikan tidak ada beban diatas sensor");
  delay(5000);

  scale.begin(A0, A1);
  scale2.begin(A2, A3);
  scale3.begin(A4, A5);
  scale4.begin(A6, A7);

  pinMode(IRSensor, INPUT);
  pinMode(IRSensor2, INPUT);
  pinMode(IRSensor3, INPUT);
  pinMode(IRSensor4, INPUT);

  pinMode(valvepin, OUTPUT);
  digitalWrite(valvepin, LOW);
  pinMode(valvepin2, OUTPUT);
  digitalWrite(valvepin2, LOW);
  pinMode(valvepin3, OUTPUT);
  digitalWrite(valvepin3, LOW);
  pinMode(valvepin4, OUTPUT);
  digitalWrite(valvepin4, LOW);

  pinMode(upButton, INPUT_PULLUP);
  pinMode(downButton, INPUT_PULLUP);
  pinMode(selectButton, INPUT_PULLUP);
  pinMode(backButton, INPUT_PULLUP);

  scale.set_scale();
  scale2.set_scale();
  scale3.set_scale();
  scale4.set_scale();

  scale.tare(); // auto zero / mengenolkan pembacaan berat
  scale2.tare();
  scale3.tare();
  scale4.tare();

  long zero_factor = scale.read_average(); // membaca nilai output sensor saat tidak ada beban
  long zero_factor2 = scale2.read_average();
  long zero_factor3 = scale3.read_average();
  long zero_factor4 = scale4.read_average();

  tft.setTextSize(2);
  DisplayUpdate();

}
//--------------------------------- Setup----------------------------------------------

//--------------------------------- Loop-----------------------------------------------
void loop() {
  HWUpdate();
}
//--------------------------------- Loop-----------------------------------------------

//--------------------------------- Note-----------------------------------------------
/*


*/
//--------------------------------- Note-----------------------------------------------
mega:SCL
mega:SDA
mega:AREF
mega:GND.1
mega:13
mega:12
mega:11
mega:10
mega:9
mega:8
mega:7
mega:6
mega:5
mega:4
mega:3
mega:2
mega:1
mega:0
mega:14
mega:15
mega:16
mega:17
mega:18
mega:19
mega:20
mega:21
mega:5V.1
mega:5V.2
mega:22
mega:23
mega:24
mega:25
mega:26
mega:27
mega:28
mega:29
mega:30
mega:31
mega:32
mega:33
mega:34
mega:35
mega:36
mega:37
mega:38
mega:39
mega:40
mega:41
mega:42
mega:43
mega:44
mega:45
mega:46
mega:47
mega:48
mega:49
mega:50
mega:51
mega:52
mega:53
mega:GND.4
mega:GND.5
mega:IOREF
mega:RESET
mega:3.3V
mega:5V
mega:GND.2
mega:GND.3
mega:VIN
mega:A0
mega:A1
mega:A2
mega:A3
mega:A4
mega:A5
mega:A6
mega:A7
mega:A8
mega:A9
mega:A10
mega:A11
mega:A12
mega:A13
mega:A14
mega:A15
lcd1:VCC
lcd1:GND
lcd1:CS
lcd1:RST
lcd1:D/C
lcd1:MOSI
lcd1:SCK
lcd1:LED
lcd1:MISO
btn1:1.l
btn1:2.l
btn1:1.r
btn1:2.r
gnd1:GND
gnd2:GND
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
cell1:VCC
cell1:DT
cell1:SCK
cell1:GND
cell2:VCC
cell2:DT
cell2:SCK
cell2:GND
cell3:VCC
cell3:DT
cell3:SCK
cell3:GND
cell4:VCC
cell4:DT
cell4:SCK
cell4:GND
NOCOMNCVCCGNDINLED1PWRRelay Module
relay1:VCC
relay1:GND
relay1:IN
relay1:NC
relay1:COM
relay1:NO
gnd3:GND
vcc1:VCC
vcc2:VCC
gnd4:GND
vcc3:VCC
gnd5:GND
vcc4:VCC
gnd6:GND
vcc5:VCC
NOCOMNCVCCGNDINLED1PWRRelay Module
relay2:VCC
relay2:GND
relay2:IN
relay2:NC
relay2:COM
relay2:NO
NOCOMNCVCCGNDINLED1PWRRelay Module
relay3:VCC
relay3:GND
relay3:IN
relay3:NC
relay3:COM
relay3:NO
NOCOMNCVCCGNDINLED1PWRRelay Module
relay4:VCC
relay4:GND
relay4:IN
relay4:NC
relay4:COM
relay4:NO
vcc6:VCC
gnd7:GND
ir1:GND
ir1:VCC
ir1:DAT
ir2:GND
ir2:VCC
ir2:DAT
ir3:GND
ir3:VCC
ir3:DAT
ir4:GND
ir4:VCC
ir4:DAT
gnd9:GND
vcc7:VCC