// 11Sep2022 - v0.1

#include <Adafruit_Fingerprint.h>
#include <Adafruit_GFX.h>       // include Adafruit graphics library
#include <Adafruit_ILI9341.h>   // include Adafruit ILI9341 TFT library
#include <Servo.h>

SoftwareSerial mySerial(2, 3);
Servo ServoMotor;

char Incoming_value = '1';      //Initialized variable to store recieved data
int Door_stat = 1 , Bypass_stat = 1,  Servo_position = 0;
uint8_t p;

unsigned long previousMillis_Waiting = 0;
unsigned long currentMillis_Waiting ;

#define RELAY_PIN            4
#define ACCESS_DELAY         3000         // Keep lock unlocked for 3 seconds 
#define DOOR_SW              A5           // Door status to check if the door is really open or closed
#define BYPASS_BIOMETRIC     A4           // To bypass biometric switch / remote switch for manual unlock
#define SERVO_PIN            A3


#define TFT_CS    10      // TFT CS  pin is connected to arduino pin 10
#define TFT_RST   9       // TFT RST pin is connected to arduino pin 9
#define TFT_DC    8       // TFT DC  pin is connected to arduino pin 8

// initialize library
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);

void setup() {

  // Uncomment to enable fingerprint scanner
  // Setup_fingerprint_sensor();
 

  // Begin the Serial at 9600 Baud
  Serial.begin(9600);

  pinMode(DOOR_SW, INPUT_PULLUP);
  pinMode(BYPASS_BIOMETRIC, INPUT_PULLUP);
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, HIGH);   // Switch off relay initially. Relay is LOW level triggered relay so we need to write HIGH.
  ServoMotor.attach(SERVO_PIN);
  ServoMotor.write(0);             // Locked position

  tft.begin();
  tft.fillScreen(ILI9341_BLACK);
  //tft_diagnostics();
  tft.setRotation(1);

  boot_screen();
  delay(3000);

  tft.fillScreen(ILI9341_BLACK);
}

void loop() {

  Door_stat = digitalRead(DOOR_SW);
  Bypass_stat = digitalRead(BYPASS_BIOMETRIC);

  tft.setTextColor(ILI9341_GREEN, ILI9341_BLACK);

  // Door closed
  if (Door_stat == 1)
  {

    tft.setCursor(20, 200);
    tft.setTextSize(3);

    tft.print("Status: Closed");

  }

  // Door opened
  if (Door_stat == 0)
  {
    tft.setCursor(20, 200);
    tft.setTextSize(3);

    tft.print("Status: Opened");
    currentMillis_Waiting = millis();
    if (currentMillis_Waiting - previousMillis_Waiting > 10000)
    {
      previousMillis_Waiting = currentMillis_Waiting;

      tft.setCursor(20, 75);
      tft.setTextSize(4);
      tft.setTextColor(ILI9341_YELLOW);
      tft.print("Door opened");
      
    }

  }

  if (Serial.available() > 0)
  {
    Incoming_value = Serial.read();
    Serial.print(Incoming_value);
    Serial.print("\n");
  }

     if (Incoming_value == '1' && Bypass_stat == 1)
    {   
      p = finger.fingerSearch();

        if (p == FINGERPRINT_NOTFOUND)
        {
          Serial.println("Did not find a match");
          tft.setCursor(0, 75);
          tft.setTextSize(4);
          tft.setTextColor(ILI9341_RED, ILI9341_BLACK);
          tft.print(" Not Match   ");
        }

//        if (p == FINGERPRINT_PACKETRECIEVEERR)
//        {
//          Serial.println("Communication error");
//          tft.setCursor(0, 75);
//          tft.setTextSize(4);
//          tft.setTextColor(ILI9341_RED, ILI9341_BLACK);
//          tft.print("    ERROR   ");
//        }
        
      currentMillis_Waiting = millis();
      if (currentMillis_Waiting - previousMillis_Waiting > ACCESS_DELAY)
      {
        previousMillis_Waiting = currentMillis_Waiting;
       
       
        tft.setCursor(0, 75);
        tft.setTextSize(4);
        tft.setTextColor(ILI9341_YELLOW, ILI9341_BLACK);
        tft.print("              ");

        digitalWrite(RELAY_PIN, HIGH);
        ServoMotor.write(0);                    // Locked position
      }
    }

    // Make sure the door is closed
    else if ((Incoming_value == '0' || Bypass_stat == 0 || p == FINGERPRINT_OK)  && Door_stat == 1)
    {
      Serial.println("Door unlocked...");  
      tft.setCursor(0, 75);
      tft.setTextSize(4);
      tft.setTextColor(ILI9341_YELLOW, ILI9341_BLACK);
      tft.print("Door unlocked");

      digitalWrite(RELAY_PIN, LOW);
      ServoMotor.write(180);                    // Unlock position
    }

//  delay(50);            //Add some delay before next scan.

  
}

void boot_screen()
{
  //  320*240
  //  --------------------
  //  -     BIOMETRIC    -
  //  -       DOOR       -
  //  -      LOCKING     -
  //  -      SYSTEM      -
  //  --------------------

  tft.setTextColor(ILI9341_WHITE);  tft.setTextSize(5);
  tft.setCursor(15, 25);
  tft.println("BIOMETRIC");
  tft.setCursor(90, 75);
  tft.println("DOOR");
  tft.setCursor(45, 125);
  tft.println("LOCKING");
  tft.setCursor(60, 175);
  tft.println("SYSTEM");

}

void tft_diagnostics()
{
  // read diagnostics (optional but can help debug problems)
  uint8_t x = tft.readcommand8(ILI9341_RDMODE);
  Serial.print("Display Power Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDMADCTL);
  Serial.print("MADCTL Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDPIXFMT);
  Serial.print("Pixel Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDIMGFMT);
  Serial.print("Image Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDSELFDIAG);
  Serial.print("Self Diagnostic: 0x"); Serial.println(x, HEX);
}

void Setup_fingerprint_sensor()
{

  // set the data rate for the sensor serial port
  finger.begin(57600);
  delay(5);
  if (finger.verifyPassword()) {
    Serial.println("Found fingerprint sensor!");
  } else {
    Serial.println("Did not find fingerprint sensor :(");
    while (1) {
      delay(1);
    }
  }
}