Our program starts by getting input for the time and date. After this it stays in a main loop which polls for button presses. A press of the set button causes the program to jump to the beginning and get input for the time and date again. If the alarm set button is pressed, a subroutine is called which gets input for the alarm time and turns the alarm on. If the alarm on/off button is pressed, the alarm is turned on or off.
The timing for the clock is kept using the timer 2 overflow interrupt. Timer 2 is set up to use an external clock input, a 32.768 KHz crystal. The prescale of timer 2 is 128 which causes the timer 2 interrupt to be entered every one second. The code for changing the time and date once the clock is running is done inside this interrupt. Also, the alarm buzzer and blinking second led are controlled here.
The seconds are incremented every time the timer 2 interrupt is entered. If they equal 60, they are reset to zero. Every time the seconds reach 60, the minutes are incremented and are reset to zero when they reach 60. The hours are incremented when the minutes reach 60 and are reset when they reach 24. The days are incremented when the hours are reset to zero. The days reset to 1 when they reach the maximum date for the month. This date can be 31, 30, 29, or 28 depending on the month and year. There is a leap year check if the month is February.
The alarm is turned on in the timer 2 interrupt. The alarm on flag is checked at the end of the interrupt, and if it is set, the time is compared to the time of the alarm. If they are equal the alarm will be sounded for five seconds or until the alarm on/off button is pressed (whichever happens first). Also, the blinking seconds led is reversed in the interrupt. A feature of the alarm clock is that when the alarm is buzzing, the bliking seconds led stays lit.
The timer zero overflow interrupt is entered every millisecond. It is used for a millisecond delay function for the lcd display and for the button debounce routine which is called every thirty milliseconds when looking for a button press.
The output to the led and the lcd is refreshed every 30 milliseconds with the current time and date. The data for the time and date to be placed on their respective displays are calculated in similar ways. The number of tens and ones in the hours, minutes, months, days, and years are calculated. For the date, a 0x30 is added to every digit to convert them to ascii values. The date is then put on the display with slashes in between the numbers. After the number of tens and ones in the minutes and hours are calculated, they are put onto the led display one digit at a time. Eight bits are sent to the led. The lower four bits are the binary value of the digit displayed. The first four bits select the digit to be displayed and are logic low. A zero in any of the first four bits means that the, first, second, third, and/or fourth digit will be display. Each digit is lit up on the display for four milliseconds.
All of the button presses are debounced using a four state debounce routine. The states switch every thirty milliseconds which is the amount of time between every debounce call. The keyboard scanner is called at each state switch. State 1 checks if the button is pressed. If it is, it sets press to zero and stays in state 1. If it is not pressed, it sets maybe to button and goes to state 2. State 2 checks if button still equals maybe. If not, it goes to state 1. If yes, it sets press to button and goes to state 3. State three checks if button equals press. If yes, it stays in state 3. If no, of goes to state 4. State 4 also checks if button equals press. If it does, the state goes back to 3. If not, press is set to zero and the state goes back to 1.