/*-------------------------------------------------------
DISTINCTION TASK QUESTION1
STUDENT ID:103495874
SARAH SALEEM
-----------------------------------------------------------
*/
#include "U8glib.h"
U8GLIB_SSD1306_128X64 u8g; // create an instant of OLED display
int hour, minute, second; //value of hours,minutes,seconds that will be printed on the oled
String user_entered_time;//the time from the serial will be stored in this
int alarm_min, alarm_sec; //to store the value of the time when alarm needs to start buzzing
int button = 19, buzzer = 8; //initialising the pin for push button and buzzer
unsigned long start_button, stop_button; //the millis() value when the button was pressed and when it was released will be stored
int h, m, s, msecond; //storing the value of hours, minute, seconds and milliseconds for stopwatch
unsigned long start_stopwatch, elapsed_time; //to store the time when the stopwatch started and the elapsed time
volatile bool time_flag;
volatile float time; //the time for which the push button has been pressed will be stored in this
volatile int lastState = HIGH;
bool is_stopwatch = 0, is_alarm = 0, set_stopwatch, stop_stopwatch, reset_stopwatch;
int count_stopwatch = 0, count_alarm = 0; //to store the amount of times the button has been pressed during the ararm and stopwatch mode
void setup() {
Serial.begin(115200);
u8g.setFont(u8g_font_courB18); // set the font for text
Serial.println(">Enter the time you want your clock to set to");
Serial.println(">>please add the time accroding to the example below ");
Serial.println(">>>if u want to write 10hours 5minutes and 3seconds write 100503");
while (Serial.available() == 0) {}
user_entered_time = Serial.readString();
//Serial.println((user_entered_time.substring(4, 6)).toInt());
//hours are the first two characters, minutes are the third and forth
//and seconds are fifth and sixth character of the user entered time
//therefore we split the user entered string using .substring function according to the indexes mentioned above and convert it to int
hour = (user_entered_time.substring(0, 2)).toInt();
minute = (user_entered_time.substring(2, 4)).toInt();
second = (user_entered_time.substring(4, 6)).toInt();
cli();//stop interrupts
//set timer1 interrupt at 1Hz
TCCR1A = 0;// set entire TCCR1A register to 0
TCCR1B = 0;// same for TCCR1B
TCNT1 = 0;//initialize counter value to 0
// set compare match register for 1hz increments
OCR1A = 15624;// = (16*10^6) / (1*1024) - 1 (must be <65536)
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS12 and CS10 bits for 1024 prescaler
TCCR1B |= (1 << CS12) | (1 << CS10);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
sei();//allow interrupts
//declaring the button pin as input pullup and using change interrupt
//the change interrept will be triggered everytime when the button is pressed or released
pinMode(button, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(button), timer, CHANGE);
Serial.println();
Serial.println(">Press the button for more than 3 sec but less than 6sec to switch between stopwatch and digital clock");
Serial.println(">When it is a stopwatch:- ");
Serial.println(" >pressing the button for the first time will start it");
Serial.println(" >pressing the button second time will stop it");
Serial.println(" >pressing the button third time will reset it");
Serial.println(" >After it's resetted pressing the button in same pattern will start stop and reset it");
Serial.println();
Serial.println(">Press the button for more than 6seconds to enable the alarm");
Serial.println(">When it is in alarm mode pressing the button once will add 15 seconds to the alarm time");
Serial.println(">So if you want alarm to buzz after 1 minute of selecting the alarm mode press the button 4 times");
}
void loop() {
//using time_flag to make sure that for one button press mode_select function is triggered just once
if (time_flag == 1) {
mode_select(time);
}
time_flag = 0;
//making time flag=0 once the mode select function has been triggered once for one button press
if (is_alarm == 1) {
alarm();
}
else if (is_stopwatch == 0) {
digital_clock();
}
else if (is_stopwatch == 1) {
stop_watch();
}
}
ISR(TIMER1_COMPA_vect) {
//as this interrupt will be triggered every second the value of second will increment
//everytime this is triggered
second++;
if (second > 60) {
minute++;
second = 0;
if (minute > 60) {
minute = 0;
hour++;
if (hour > 24) {
hour = 0;
}
}
}
}
void timer() { //to find out the amount of time the button has been pressed
int value = digitalRead(button);
if (lastState != value) {
lastState = value;
if (value == LOW) {
start_button = millis(); //the time when the button is pressed
Serial.println("pressed");
}
else if (value == HIGH) {
Serial.println("released");
stop_button = millis(); //the time when the button is released
time = (stop_button - start_button) / 1000.f; //subtracting the release time from the press time and fividing it with 1000 to obtain value in seconds
Serial.println("time");
Serial.println(time);
time_flag = 1; //time flag is one to indicate that the button has been preesed, and a mode should be selected based on the amount of time for which it has been pressed
}
}
}
void mode_select(float time) {
if (time >= 3 && time < 6) {
//if the amount of time for which the button has been pressed is greater than 3 sec but less than 6 sec
//then the mode will change from stopwatch to digital clock or digital clock to stopwatch
is_stopwatch = !is_stopwatch;
if (is_stopwatch) {
reset_stopwatch = 1;
set_stopwatch = 0;
stop_stopwatch = 0;
count_stopwatch = 0;
}
}
else if (time >= 6) {
//if the button has been pressed for more than 6sec then the alarm mode will be selected
is_alarm = !is_alarm;
alarm_sec = second;
alarm_min = minute;
if (is_alarm) {
Serial.println("now alarm");
}
}
else if (is_stopwatch == 1 && time < 3) {
count_stopwatch++;//incrementing the value of count everytime button is pressed during stopwatch mode
//during the stopwatch mode when the button is pressed first the stopwatch starts
//when the buton will be pressed 2nd time the stopwatch stops
//and when pressed third time it will reset
//after reseting when the button is pressed again it will start, stop reset again in similar pattern
if (count_stopwatch == 1) {
//when the stopwatch is started the value of set_stopwatch will be set to 1
//and the millis() value when it started will be stored
set_stopwatch = 1;
stop_stopwatch = 0;
reset_stopwatch = 0;
start_stopwatch = millis();
}
else if (count_stopwatch == 2) {
//when the stopwatch is stopped the value of stop_stopwatch will be made 1
stop_stopwatch = 1;
reset_stopwatch = 0;
set_stopwatch = 0;
}
else if (count_stopwatch == 3) {
//and when it is resetted the value of reset_stopwatch will be one
reset_stopwatch = 1;
set_stopwatch = 0;
stop_stopwatch = 0;
//the couunt will be set to zero
count_stopwatch = 0;
}
}
else if (is_alarm == 1 && time < 3) {
count_alarm++;//incrementing the value of count everytime button is pressed during alarm mode
alarm_sec = 15 + alarm_sec; //with every button press the seconds will increment by 15
Serial.println(alarm_sec);
if (alarm_sec > 60) {
alarm_min = 1 + alarm_min;
alarm_sec = 0;
}
}
}
void alarm() {
//when the actual time equals to them for which the alarm has been set the alrm with buzz
if (alarm_min == minute && alarm_sec == second && count_alarm >= 1) {
tone(buzzer, 300, 6000);
}
//display the time for which the alarm has been set
OLED_display(hour, alarm_min, alarm_sec, 0, "Alarm is set for");
}
void stop_watch() {
if (set_stopwatch == 1 && stop_stopwatch == 0) {
//doing the following calculations to find the elapsed time when the stopwatch is started
//and not stopped
elapsed_time = millis() - start_stopwatch;
unsigned long over;
h = int(elapsed_time / 3600000);
over = elapsed_time % 3600000;
m = int(over / 60000);
over = over % 60000;
s = int(over / 1000);
msecond = over % 100;
}
else if (reset_stopwatch == 1) {
//setting the value of hours seconds and milliseconds to zero when it is resetted
h = 0;
m = 0;
s = 0;
msecond = 0;
}
OLED_display(h, m, s, msecond, "Stop watch");
}
void digital_clock() {
OLED_display(hour, minute, second, 0, "Digital clock");
}
void OLED_display(int hours, int minutes, int seconds, int mseconds, String text) {
u8g.firstPage(); //marks the beginning of the picture loop.
do {
u8g.setColorIndex(1);// set the colour to white
u8g.setFont(u8g_font_courB18);
//hours
if (hours < 10) {
u8g.setPrintPos(0, 61);
u8g.print("0");
u8g.setPrintPos(14, 61);
u8g.print(hours);
}
else {
u8g.setPrintPos(0, 61);
u8g.print(hours);
}
u8g.setPrintPos(25, 61);
u8g.print(":");
//minutes
if (minutes < 10) {
u8g.setPrintPos(35, 61);
u8g.print("0");
u8g.setPrintPos(49, 61);
u8g.print(minutes);
}
else {
u8g.setPrintPos(35, 61);
u8g.print(minutes);
}
u8g.setPrintPos(60, 61);
u8g.print(":");
//seconds
if (seconds < 10) {
u8g.setPrintPos(72, 61);
u8g.print("0");
u8g.setPrintPos(84, 61);
u8g.print(seconds);
}
else {
u8g.setPrintPos(72, 61);
u8g.print(seconds);
}
if (is_stopwatch == 1) { //print milliseconds only for stopwatch
//milli seconds
u8g.setFont(u8g_font_courB14);
u8g.setPrintPos(97, 61);
u8g.print(":");
if (mseconds < 10) {
u8g.setPrintPos(107, 61);
u8g.print("0");
u8g.setPrintPos(116, 61);
u8g.print(mseconds);
}
else {
u8g.setPrintPos(107, 61);
u8g.print(mseconds);
}
}
u8g.setFont(u8g_font_7x13);
u8g.setPrintPos(0, 20);
u8g.print(text);
} while (u8g.nextPage()); //end of picture loop
}