#include <LiquidCrystal.h>
#include <EEPROM.h>
#include "custom_chrs.h"
#include "A_variables.h"
#include "Set_interrupt.h"
#define hrs_btn_pin 6
#define lock_btn_pin 7
#define mins_btn_pin 8
#define buzzer_pin 9
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // initialize lcd object
void setup()
{
Serial.begin(9600);
delay(1000);
pinMode(hrs_btn_pin, INPUT_PULLUP); // Define pins connected to hrs, mins and lock buttons as inputs
pinMode(mins_btn_pin, INPUT_PULLUP); // " "
pinMode(lock_btn_pin, INPUT_PULLUP); // " "
pinMode(buzzer_pin, OUTPUT); // Define buzzer pin (9) as output
pinMode(LED_BUILTIN, OUTPUT); // Define LED_BUILTIN pin 13 as output
lcd.createChar(0, lock_icon); // Create custom character (locked icon)
lcd.createChar(1, ulock_icon); // Create custom character (unlocked icon)
lcd.createChar(2, dn_icon); // Create custom character (locked icon)
lcd.createChar(3, up_icon); // Create custom character (unlocked icon)
lcd.createChar(4, block_icon); // Create custom character (block icon)
lcd.begin(16, 2); // Initialize LCD display
lcd.noDisplay();delay(200);
lcd.display();
randomSeed(analogRead(0));
//read_EEPROM_data(); // Import saved EEPROM data (device state at last power down or reset)
//if(DEBUG) {debug_EEPROM_data();} // Display imported data on LCD at startup in debug mode
Switch_Mode(0);
ICON = UNL_ICON; // Set Status and lock icon on display according to MODE
switch(MODE)
{
case 0:STATUS = UNLOCKED ;break;
case 1:STATUS = SET_TIME ;break;
case 2:STATUS = LOCKING ;break;
case 3:STATUS = LOCKED;ICON = LOC_ICON ;break;
}
set_1sec_interrupt();
}
void loop()
{ // Read buttons
hrs_btn_state = digitalRead(hrs_btn_pin); // Read Hrs btn state
mins_btn_state = digitalRead(mins_btn_pin); // Read Mins btn state
lock_btn_state = digitalRead(lock_btn_pin); // Read Lock btn state
delay(100);
UpdateLCD();
switch(MODE)
{
// MODE 0-------------------------------------------------------------------------------------------------------------------------------------------
case 0: // INITIAL (IDLE) MODE : [Lock button sends unlock pulse | hrs or mins updates their count by 1 and switches to MODE 1] | Set random time
if(hrs_btn_state == 0 && hrs_btn_pr != 0) // Hours button pressed
{
delay(50);
mins_btn_state = digitalRead(mins_btn_pin); // Read Mins btn while Hrs btn is pressed
if(mins_btn_state == 0){Set_Random_Time();break;} // If HRS and MINS button pressed, set random time and switch to MODE 2
hrs_btn_pressed = millis(); // Remember time hrs button has been pressed
buzz(1,50,100,beep_hi_pitch); // Short beep on button press
hrs_count += 1; // Increase hours count
Switch_Mode(1); // Switch to MODE 1
delay(50);
}
else if(mins_btn_state == 0 && mins_btn_pr != 0) // Minutes button was pressed
{
delay(50);
hrs_btn_state = digitalRead(hrs_btn_pin); // Read Hrs btn while Mins btn is pressed
if(hrs_btn_state == 0){Set_Random_Time();break;} // If HRS and MINS button pressed, set random time and switch to MODE 2
mins_btn_pressed = millis(); // Remember time mins button has been pressed
buzz(1,50,100,beep_hi_pitch); // Short beep on button press
mins_count += 1; // Increase mins count
Switch_Mode(1); // Switch to MODE 1
delay(50);
}
if(lock_btn_state == 0 && lock_btn_pr != 0) // Lock button pressed in MODE 0 sends unlock pulse
{
lock_btn_pressed = millis(); // Remember time lock button has been pressed
UnlockPulse();
}
if((millis() - lock_btn_pressed) > 3000 && lock_btn_state == 0 && lock_btn_pr == 0) //LONG PRESS ON LOCK BUTTON
{
buzz(2,50,100,beep_hi_pitch); // Short double beep on long button press
if(countdown){STATUS = COUNT_UP;} // Toggle STATUS between counting up and counting down
else {STATUS = COUNT_DOWN;}
countdown = !countdown; // Toggle countdown
UpdateLCD(); // Update LCD
delay(2000);
STATUS = UNLOCKED; // Restore STATUS
}
hrs_btn_pr = hrs_btn_state; // Remember button states
mins_btn_pr = mins_btn_state; // " "
lock_btn_pr = lock_btn_state; // " "
break;
// MODE 1-------------------------------------------------------------------------------------------------------------------------------------------
case 1: // SET MODE [Lock button released after being pressed switches to MODE 2 | hrs or mins update their count by 1 or start Auto-increment]1
M1_idle_timer--;
if(M1_idle_timer == 0 && M1_delay) // M1 timer routine
{
buzz(1,50,100,beep_hi_pitch); // Short beep
Switch_Mode(0); // Switch to MODE 0
break;
}
if(unlock_pulse) // Send unlock pulse if countdown just ended
{
lcd.clear(); // Clear display
UnlockPulse(); // Send unlock pulse
unlock_pulse = false; // Clear unlock pulse trigger
}
if(hrs_btn_state == 0 && hrs_btn_pr != 0) // Hours button pressed
{
hrs_btn_pressed = millis(); // Remember time hrs button has been pressed
buzz(1,50,100,beep_hi_pitch); // Short beep on button press
hrs_count += 1; // Increase hours count
M1_idle_timer = M1_idle_value;
delay(50);
}
else if(mins_btn_state == 0 && mins_btn_pr != 0) // Minutes button pressed
{
mins_btn_pressed = millis(); // Remember time mins button has been pressed
buzz(1,50,100,beep_hi_pitch); // Short beep on button press
mins_count += 1; // Increase mins count
M1_idle_timer = M1_idle_value;
delay(50);
}
else if((millis() - mins_btn_pressed) > 1000 && mins_btn_state == 0 && mins_btn_pr == 0) // Start auto-increment after 1s if mins button is held down
{
mins_count += 1; // Auto increment mins count
if(mins_count > 99){mins_count = 99;} // Maximum mins value is 99
M1_idle_timer = M1_idle_value;
delay(150);
}
else if((millis() - hrs_btn_pressed) > 1000 && hrs_btn_state == 0 && hrs_btn_pr == 0) // Start auto-increment after 1s if hrs button is held down
{
hrs_count += 1; // Auto-increment hrs count
if(hrs_count > 99){mins_count = 99;} // Maximum hrs value is 99
M1_idle_timer = M1_idle_value;
delay(150);
}
if(lock_btn_state == 0 && lock_btn_pr == 1){lock_btn_pr = 0;} // Lock button pressed
if(lock_btn_state == 1 && lock_btn_pr == 0) // Lock button released
{
lock_btn_pr = lock_btn_state; // Switch to MODE 2 on Lock button release
Switch_Mode(2); // Switch to MODE 1
}
hrs_btn_pr = hrs_btn_state; // Remember button states
mins_btn_pr = mins_btn_state; // " "
delay(20);
break;
// MODE 2---------------------------------------------------------------------------------------------------------------------------------------------
case 2: // M2_secs_cdwn (5) seconds COUNTDOWN to LOCK MODE [Lock button cancels lock sequence | hrs or mins updates have no effect]
i = 0;j = 0; // Initialize loop indexes
while (i < M2_secs_cdwn) //(20ms delay * 50 = roughly 1sec/j loop * 5j loops = 5secs)
{
buzz(1,100,0,beep_hi_pitch); // Beep on countdown step
lcd.setCursor(i+8, 0);lcd.print(">"); // Countdown animation
while(j < 50) // Nested loops allow multiple rapid readings of lock button during countdown
{
lock_btn_state = digitalRead(lock_btn_pin); // Read Lock button
if(lock_btn_state == 0 && lock_btn_pr != 0) // Lock button pressed during countdown: cancels lock sequence and switches to MODE 0
{
buzz(3,50,100,beep_hi_pitch); // Triple beep on cancel lock sequence
Switch_Mode(0); // Switch to MODE 0
i = M2_secs_cdwn; // Terminate enclosing (i) loop
lock_btn_pr = lock_btn_state; // Remember lock button state
break; // Terminate interior (j) loop
}
delay(20);j++; // 20ms delay / Increment j
}
j = 0;i++; // Reset j / Increment i
}
if(MODE != 0) // No action was taken during Lock sequence countdown (sequence was not cancelled)
{
buzz(1,500,0,beep_hi_pitch); // Long beep
Switch_Mode(3); // Switch to MODE 3
}
hrs_btn_pr = hrs_btn_state; // Remember button states
mins_btn_pr = mins_btn_state; // " "
break;
// MODE 3---------------------------------------------------------------------------------------------------------------------------------------------
case 3:
if(hrs_btn_state == 0 && hrs_btn_pr != 0){blinkDisplay();}
if(mins_btn_state == 0 && mins_btn_pr != 0){blinkDisplay();}
if(lock_btn_state == 0 && lock_btn_pr != 0){blinkDisplay();}
if(countdown && secs_count <= 5 && mins_count == 0 && hrs_count == 0) // Audible sequence matching animation during the last 5 seconds of the countdown
{
buzz(1,150,0,beep_hi_pitch);
}
if(!countdown && secs_count >= 55 && mins_count == mem_mins-1 && hrs_count == mem_hrs) // Audible sequence with animation during last 5 secs of countdown
{
buzz(1,150,0,beep_hi_pitch);
}
delay(20);
hrs_btn_pr = hrs_btn_state;
mins_btn_pr = mins_btn_state;
lock_btn_pr = lock_btn_state;
break;
}// End switch MODE
}// End void loop