/*CPU speed is defined so delay functions can work*/
#define F_CPU 4000000UL
#include <util/delay.h>
/*AVR interrupt library*/
#include <avr/io.h>
#include <avr/interrupt.h>
/*Initial state is RESET*/
unsigned char state=1;
unsigned char display=0;
/*Send out the appropriate number digit for output*/
unsigned char display7seg(unsigned char num);
/*The show() function switches the different segments*/
void show(unsigned char hrs, unsigned char min, unsigned char sec);
/*Initializing minute and second variables*/
unsigned char hours = 12;
unsigned char minutes=58;
unsigned char seconds=58;
unsigned char alarm_hour = 0;
unsigned char alarm_minutes = 0;
unsigned char alarm_seconds = 0;
/*Functions which control the different states*/
void run_state(void);
void set_state(void);
void reset_state(void);
void alarm_state(void);
/*The button_check() function polls PIND for button press*/
void button_check_state(void);
void button_check_setTime(void);
void button_check_setAlarm(void);
/* Declaration of Timer ISR*/
ISR(TIMER1_COMPA_vect);
/* functions to change clock values*/
void set_clock_minutes(void);
void set_clock_hours(void);
/* function to change alarm values*/
void set_alarm_minutes(void);
void set_alarm_hours(void);
/* sound buzzer when alarm conditions are met*/
void alarm(void);
int main(void)
{
/* Make PORTB output*/
DDRB = 0xFF;
/*Make PD4, PD5,PD6 output to switch 7 segs and PD0 for buzzer*/
DDRD = 0b01110001;
/*Enable pull-up resistors on PD1, PD2 and PD3*/
PORTD = 0b0001110;
/*Enable Global Interrupts*/
sei();
while (1)
{
/*show clock values*/
show(hours, minutes, seconds);
button_check_state();
/*Runs the appropriate function given the state*/
switch (state)
{
case 1:
/*Run*/
run_state();
break;
case 2:
/*Set clock*/
set_state();
break;
case 3:
/*Reset clock*/
reset_state();
break;
case 4:
/*alarm*/
alarm_state();
}
}
return 0;
}
void show(unsigned char hrs, unsigned char min, unsigned char sec){
/*Segment to display hours*/
/*Display number in TENS position*/
if (hrs < 10)
{
PORTB = display7seg(111);// blank out zeros
PORTD = 0b01011110;
_delay_us(100);
}
else
{
PORTB = display7seg(hrs/10);
PORTD = 0b01011110;
_delay_us(100);
}
/*Display number in ONES position*/
PORTB=display7seg(hrs % 10);
PORTD = 0b00011110;
_delay_us(50);
/*Segment to display minutes*/
/*Display number in TENS position*/
PORTB=display7seg(min/10);
PORTD = 0b01101110;
_delay_us(50);
/*Display number in ONES position*/
PORTB=display7seg(min % 10);
PORTD = 0b00101110;
_delay_us(50);
/*Segment to display seconds*/
/*Display number in TENS position*/
PORTB=display7seg(sec/10);
PORTD = 0b01001110;
_delay_us(50);
/*Display number in ONES position*/
PORTB=display7seg(sec % 10);
PORTD = 0b00001110;
_delay_us(50);
void run_state(void)
{
show(hours, minutes, seconds);
/*Timer 1 is configured and started*/
TCCR1B=(1<<CS12|1<<WGM12);
/*Put appropriate value for OCR1A*/
OCR1A= 1953;
/*Output Compare Interrupt Enabled*/
TIMSK=(1<<OCIE1A);
state = 1;
show(hours, minutes, seconds);
//check if clock value equals alarm
alarm();
void set_state(void)
{
/*stop timer*/
TCCR1B=0;
while(state == 2)
{
// while in set state determine which button is pressed
button_check_setTime();
show(hours, minutes, seconds);
}
void reset_state(void)
{
//stop timer and set clock to default values
TCCR1B = 0;
hours = 12;
minutes = 0;
seconds = 0;
state = 1;
show(hours, minutes, seconds);
void alarm_state()
{
while (state == 4)
{
// check which button is pressed while in the alarm state
button_check_setAlarm();
show(alarm_hour, alarm_minutes, alarm_seconds);
}
}
void button_check_state(void)
{
/*Test if the switch on PD1 is pressed (set time)*/
if (!(PIND & 0b00000010))
{
/*De-bounce pressed switch */
_delay_ms(50);
state = 2;
}
/* Test if the switch on PD2 (reset clock to 12:00) is pressed */
if (!(PIND & 0b00000100))
{
_delay_ms(50);
/*De-bounce pressed switch */
state = 3;
}
/*if PD3 pressed (set alarm) clock*/
if (!(PIND & 0b00001000))
{
_delay_ms(150);
/*De-bounce pressed switch */
state = 4;
}
void button_check_setTime(void)
{
if (!(PIND & 0b00000010))
{
/*De-bounce pressed switch */
_delay_ms(50);
//if switch on PD1 is pressed set state to 1 (run state)
state = 1;
}
if (!(PIND & 0b00000100))
{
/*De-bounce pressed switch */
_delay_ms(50);
// if switch on PD2 is pressed increment clock minutes
set_clock_minutes();
}
if (!(PIND & 0b00001000))
{
/*De-bounce pressed switch */
_delay_ms(50);
// if switch on PD3 is pressed increment clock hours
set_clock_hours();
}
void button_check_setAlarm()
{
if (!(PIND & 0b00001000))
{
_delay_ms(50);
//if switch on PD3 is pressed set state to 1 (run state)
state = 1;
}
if (!(PIND & 0b00000010))
{
_delay_ms(150);
// if switch on PD3 is pressed increment clock hours
set_alarm_hours();
}
if (!(PIND & 0b00000100))
{
_delay_ms(150);
// if switch on PD3 is pressed increment clock hours
set_alarm_minutes();
}
}
void set_clock_hours()
{
if (hours == 12)
{
hours = 1; // ensures that hour is within range
}
else
{
hours++;
}
}
void set_clock_minutes()
{
if (minutes == 59)
{
minutes = 0;// ensure that minute is within range
}
else
{
minutes++;
}
}
void set_alarm_hours()
{
if (alarm_hour == 12)
{
alarm_hour = 0;// ensures that hour is within range
}
else
{
alarm_hour++;
}
}
void set_alarm_minutes()
{
if (alarm_minutes == 59)
{
alarm_minutes = 0;// ensure that minute is within range
}
else
{
alarm_minutes++;
}
}
ISR (TIMER1_COMPA_vect)
{
if (seconds==59)
{
seconds=0;
if (minutes==59)
{
minutes=0;
if (hours == 12)
{
hours = 1;
}
else
{
hours++;
}
}
else
{
minutes++;
}
}
else
{
seconds++;
}
}
void alarm()
{
if ((hours == alarm_hour) && (minutes == alarm_minutes))
{
//if alarm minutes and hours equals clock minutes and hour activate buzzer
with output 1 to PD0
PORTD = 0b00001111;
}
else
{
//if alarm criterea not met do not activate buzzer
PORTD = 0b00001110;
}
}
unsigned char display7seg(unsigned char num)
{
switch (num)
{
case 0:
display = 0b00111111;
break;
case 1:
display = 0b00000110;
break;
case 2:
display = 0b01011011;
break;
case 3:
display = 0b01001111;
break;
case 4:
display = 0b01100110;
break;
case 5:
display = 0b01101101;
break;
case 6:
display = 0b01111101;
break;
case 7:
display = 0b00000111;
break;
case 8:
display = 0b01111111;
break;
case 9:
display = 0b01100111;
break;
case 111: // special case used to blank zeros
display = 0b00000000;// use to blank out zeros
break;
}
return display;
}