// Program written by Dan Hostler, August 2020.
// Feel free to use   as you need to.
// PayPal donations appreciated at [email protected]




//   LIBRARIES. (PLEASE INSTALL THESE LIBRARIES IF YOU HAVE NOT YET)
#include <Wire.h>                // deals with I2C connections
#include <LiquidCrystal_I2C.h>  //   activates the LCD I2C library
#include <Keypad.h>             // activates the   Keypad library




// VARIABLES FOR THE 8-NUMBER PASSWORD INPUT DATA
#define   Password_Length 5                  // Amount of digits plus one null character   (8 + 1 = 9) defines password length
char userInput[Password_Length];             //   This variable will store the user input in a string
char Master[Password_Length]   = "1234";   // This variable holds the correct password that the user string   must match, change as needed
char customKey;                              //   This variable holds key input of every key pressed
byte pressCount = 0;                         //   This variable holds a counter for the amount of times the keys were pressed




//   KEYPAD CONFIGURATION (PLEASE MODIFY THIS SECTION IF YOUR KEYPAD WIRING IS DIFFERENT   FROM BELOW)
const byte ROWS = 4; // Constants for row and 
const byte COLS   = 3; // column size of your keypad.

char twelveKeys[ROWS][COLS] =                     //   Physical layout of the keypad being used in this program
{ 
    {'1', '2', '3'}, 
    {'4', '5', '6'},
    {'7', '8', '9'},
    {'C', '0', 'E'} //   C = CLEAR, E = ENTER
};

byte rowPins[ROWS] = {9, 8, 7, 6};  // Defines   how rowPins are connected on the Arduino to the keypad: 9 = R1, 8 = R2, 7 = R3,   6 = R4
byte colPins[COLS] = {5, 4, 3};     // Defines how colPins are connected   on the Arduino to the keypad: 5 = C1, 4 = C2, 3 = C3, 2 = C2 (if you have a 4x4   keypad) 




// OBJECT CONFIGURATIONS
Keypad customKeypad = Keypad(makeKeymap(twelveKeys),   rowPins, colPins, ROWS, COLS); // Creates keypad "object"
LiquidCrystal_I2C   lcd(0x27, 16, 2);                                                 // Creates LCD   "object" (I2C address, rows, columns)




// PROGRAM SETUP
void   setup() {

  // LCD Initialization
  lcd.backlight(); 
  lcd.init();
   lcd.clear();

  Serial.begin(9600); // Must be 9600
  Serial.println("Hello Arduino\n");
}




// MAIN PROGRAM LOOP
void loop() {

  Serial.println(pressCount);


   lcd.setCursor(0,0);
  lcd.print(" Type Password:");                                       //   One space is offset to center the text on the LCD
  customKey = customKeypad.waitForKey();                               // Program will halt here until a key is pushed

   if (customKey != NO_KEY && customKey != 'C' && customKey != 'E')    // If the   user presses the number keys, the data is entered
  {
  userInput[pressCount]   = customKey;                                  // Password string is being collected   by the userInput variable
  lcd.setCursor(pressCount + 4, 1);                                   //   Four is added to pressCount to center the input on the LCD
  lcd.print(customKey);                                                      // Asterisks are printed for   confidentiality 
  pressCount++;                                                       //   Key press count will roll over until 8 digits are entered
  }
   
  if (pressCount == 4)         // Once 8 digits   are entered, the function to check the password string is called up and
  {                            //   both the character and string data are sent to the function.
  lcd.clear();
   waitHere();                  
  }

}


// THIS FUNCTION CHECKS   THE PASSWORD STRING
void waitHere(){
  Serial.println(pressCount);
  

  lcd.setCursor(0,0);
  lcd.print("Type Password:"); 
  lcd.setCursor(0,1);
  lcd.print(Master);                    //   Password data is hidden as asterisks for confidentiality purposes and
                                                //   is offset by 4 spaces to center the input on the LCD
                                                 
   customKey = customKeypad.waitForKey();        // Program will halt here until   a key is pushed
  
  if (customKey != NO_KEY && customKey == 'E')  // The   ENTER button is pushed and the password goes through the routine.
  if (pressCount == 4)
  {
  lcd.clear();
   lcd.setCursor(0,0);
    if (!strcmp(userInput, Master))             // The   user input string is matched up with the Master password string and matches up
     {                                           // running the routine to grant   access before returning back to the beginning.
    lcd.setCursor(5,0);
    lcd.print("**WIN**");
    lcd.setCursor(0,1);
    lcd.print("---------------");
    delay(5000);
     clearData(); 
    }
    else if (strcmp(userInput, Master))         //   The user input string is matched up with the Master password string and does not   match up
    {                                           // running the routine   to deny access before returning back to the beginning.
    lcd.setCursor(0,0);
     lcd.print("ACCESS DENIED.");
    delay(2000);
    clearData(); 
     }
  }

  if (customKey != NO_KEY && customKey == 'C')  // If the CLEAR   button is pushed, the data is cleared and the program starts over.
  {
  lcd.clear();
   clearData(); 
  }
  
  if (customKey != NO_KEY && customKey == '0')  //   This numberical button has no purpose and does nothing when pressed.
  {
   waitHere();
  }

  if (customKey != NO_KEY && customKey == '1')  // This   numberical button has no purpose and does nothing when pressed.
  {
  waitHere();
   }

  if (customKey != NO_KEY && customKey == '2')  // This numberical button   has no purpose and does nothing when pressed.
  {
  waitHere();
  }

   if (customKey != NO_KEY && customKey == '3')  // This numberical button has no   purpose and does nothing when pressed.
  {
  waitHere();
  }

  if   (customKey != NO_KEY && customKey == '4')  // This numberical button has no purpose   and does nothing when pressed.
  {
  waitHere();
  }

  if (customKey   != NO_KEY && customKey == '5')  // This numberical button has no purpose and does   nothing when pressed.
  {
  waitHere();
  }

  if (customKey != NO_KEY   && customKey == '6')  // This numberical button has no purpose and does nothing   when pressed.
  {
  waitHere();
  }

  if (customKey != NO_KEY &&   customKey == '7')  // This numberical button has no purpose and does nothing when   pressed.
  {
  waitHere();
  }

  if (customKey != NO_KEY && customKey   == '8')  // This numberical button has no purpose and does nothing when pressed.
   {
  waitHere();
  }

  if (customKey != NO_KEY && customKey == '9')   // This numberical button has no purpose and does nothing when pressed.
  {
   waitHere();
  }
  
}




// OPTIONAL FUNCTIONS TO USE   IN CASE YOU WISH TO EXPAND OUT YOUR PROGRAM
//void accessGranted(){
//  
//}
//
//void   accessDenied(){
//  
//}




// CLEARS THE ARRAY DATA, STARTS   PROGRAM ALL OVER AGAIN
void clearData() {  
  while (pressCount != 0) 
   {
  userInput[pressCount--] = 0;    // Clears out the user input data, both   digit and string data are reset to zero.
  }
  setup();                        //   Returns program back to the beginning
}

void clearData2() {  
  while (pressCount != 0) 
   {
  userInput[pressCount--] = 0;    // Clears out the user input data, both   digit and string data are reset to zero.
  }                        //   Returns program back to the beginning
}