#include <stdio.h>
#include <stdlib.h>
#define F_CPU 14745600
#include <avr/io.h>
#include <avr/interrupt.h>
#include "../libnerdkits/delay.h"
// these 2 for serial
#include <avr/pgmspace.h>
#include "../libnerdkits/uart.h"
#include "max7219.c"
#include "ds1302.c"
#define CE PD4 // PIN connected to CE
#define IO PD3 // PIN connected to PD3
#define SCLK PD2 // PIN connected to PD2
//volatile unsigned char b10;
//volatile unsigned char bpm;
volatile int16_t the_time;
volatile char sec_s;
volatile char sec_t;
volatile char min_s;
volatile char min_t;
volatile char hr_s;
volatile char hr_t;
void realtimeclock_setup() {
TCCR0B = (1<<CS01) | (1<<CS00);
TIMSK0 = (1<<TOIE0);
}
SIGNAL(SIG_OVERFLOW0) { // interupt to run 100 times per second.
the_time++;
}
void display_current_time(char on) { // read time from ds1302 then update max7219.
min_s = read_minutes(1);
min_t = read_minutes(10);
hr_s = read_hours(1);
hr_t = read_hours(10);
if (on) { // if set to on, turn on colon between hr/min
min_t |= (1<<7);
hr_s |= (1<<7);
}
display(1,hr_t); // pass info to max chip to update display
display(2,hr_s);
display(3,min_t);
display(4,min_s);
}
int main() {
volatile uint8_t tmp; // int all vars here
volatile int tmp2;
volatile uint8_t button1;
volatile uint8_t button2;
volatile uint8_t button3;
volatile uint8_t mode[3];
volatile int8_t allow_adjust;
volatile int16_t counter;
volatile char blink_sep;
//mode[0] = 0;
mode[2] = 0;
// set pins to be used as buttons
DDRD &= ~(1<<PD7); // set pin as input
PORTD |= (1<<PD7); // enable pull up resistor
DDRD &= ~(1<<PD6); // set pin as input
PORTD |= (1<<PD6); // enable pull up resistor
DDRD &= ~(1<<PD5); // set pin as input
PORTD |= (1<<PD5); // enable pull up resistor
//init uart and create stream
uart_init();
FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
stdin = stdout = &uart_stream;
rtc_init(); // init ds1302 rtc chip
realtimeclock_setup(); // setup interupt
sei(); // enable interupts
max7219_init(); // init max7219 chip
//check bit stored in ram of ds1302, if its missing assume clock has been reset.
min_s = read_minutes(1);
min_s = min_s + (read_minutes(10) * 10);
write_minutes(min_s);
write_seconds(1);
//turn on trickle charger
trickle();
while(1) {
button1 = (PIND & (1<<PD7)) >> PD7; // update button status
//printf_P(PSTR("1 : %u "), button1);
while (!button1) { // while button is pressed
button1 = (PIND & (1<<PD7)); // update button status
if ((!tmp) && (!mode[2])) {
mode[0]++;
tmp = 1;
}
button1 = (PIND & (1<<PD7)); // update button status
if (button1) { // filter glitches, if its off wait 2ms then reread the button
delay_ms(2); // its probably the cheap switches im using but as they approach being on they would switch on and off very fast a few times
button1 = (PIND & (1<<PD7)); // update button status
}
}
button2 = (PIND & (1<<PD6)) >> PD6; // update button status
while (!button2) { // while button is pressed
if ((!tmp) && (!mode[2])) {
if (mode[0] == 0) mode[0] = 3;
mode[0]--;
tmp = 1;
}
button2 = (PIND & (1<<PD6)); // update button status
if (button2) { // filter glitches, if its off wait 2ms then reread the button
delay_ms(2); // its probably the cheap switches im using but as they approach being on they would switch on and off very fast a few times
button2 = (PIND & (1<<PD6)); // update button status
}
}
button3 = (PIND & (1<<PD5));
while (!button3) { // detect if change mode button has been pressed
button3 = (PIND & (1<<PD5));
if (mode[0] == 2) {
tmp2 = 1;
mode[2] = 1;
}
if (button3) { // filter glitches, if its off wait 2ms then reread the button
delay_ms(2); // its probably the cheap switches im using but as they approach being on they would switch on and off very fast a few times
button3 = (PIND & (1<<PD5)); // update button status
}
}
tmp = 0;
switch(mode[0]) {
case 0: // check and update display with time
if (the_time > 100) { // every second run the below
blink_sep++;
the_time = 0;
display_current_time(1);
}
if (blink_sep == 5) {
}
break;
case 1: // show temp
display(1,3);
display(2,5);
display(3,37); // '
display(4,13); // c
break;
case 2:
if (!mode[2]) {
display(1,29); // s
display(2,16); // e
display(3,30); // t
display(4,100); //
}
char b_pressed = 0;
while (mode[2]) { // set selected
button1 = (PIND & (1<<PD7)); // update button status
button2 = (PIND & (1<<PD6)); // update button status
button3 = (PIND & (1<<PD5)); // update button status
if ((!button1) && (!b_pressed)) {
b_pressed = 1; // let rest of code a button has been pressed, avoids a few things happening twice
delay_ms(2);
mode[2]++;
}
if ((!button2) && (!b_pressed)) {
b_pressed = 1;
delay_ms(2);
mode[2]--;
}
if (mode[2] > 3) mode[2] = 1;
if (mode[2] < 1) mode[2] = 3;
if ((button1) && (button2)) {
b_pressed = 0;
}
while (!button3) {
b_pressed = 2; // set var for code below
button3 = (PIND & (1<<PD5)); // update button status
if (button3) {
delay_ms(2);
button3 = (PIND & (1<<PD5)); // update button status
}
}
if ((!button1) || (!button2) || (tmp2)) { // if a change mode button was pressed update display
tmp2 = 0;
switch(mode[2]) {
case 1:
display(1,29); // s
display(2,16); // e
display(3,30); // t
display(4,30); // t
break;
case 2:
display(1,29); // s
display(2,16); // e
display(3,30); // t
display(4,1); // 1
break;
case 3:
display(1,29); // s
display(2,16); // e
display(3,30); // t
display(4,2); // 2
break;
}
}
if (b_pressed == 2) {
tmp = 1;
if (mode[2] == 1) { // if on sett and button 3 is pressed, enter set time mode
counter = 0;
the_time = 0;
char on = 1;
char tmp2;
display_current_time(1);
while(tmp) { // enter set time mode
button1 = (PIND & (1<<PD7)); // update button status
button2 = (PIND & (1<<PD6)); // update button status
button3 = (PIND & (1<<PD5)); // update button status
if (the_time > 300) { // make min or hr flash to show which one is being set
if (!on) { // this if statment will show min/hr selection by flashing
if (mode[2] == 1) {
display(3,100); // 100 = blank
display(4,100);
} else {
display(1,100);
display(2,100);
}
on = 1;
} else {
if (mode[2] == 1) {
display(4,min_s);
display(3,min_t);
} else {
display(2,hr_s);
display(1,hr_t);
}
on = 0;
}
the_time = 0;
}
// if button 1 pressed cycle up
while ((!button1) || (!button2)) { // while button up/down is pressed inc/dec
if (!counter) {
counter = 1; // to make this if statment true only once
if (mode[2] == 1) { // modify minutes
tmp2 = read_minutes(1);
tmp2 = tmp2 + (read_minutes(10) * 10);
if (!button1) tmp2++; // adjust the time depending on button pressed
else tmp2--;
if (tmp2 > 59) tmp2 = 0; // cycle mins
if (tmp2 < 0) tmp2 = 59; // cycle mins
display(4,(tmp2 % 10));// update display
display(3,(tmp2 / 10));
} else { // modify hours
tmp2 = read_hours(1);
tmp2 = tmp2 + (read_hours(10) * 10);
if (!button1) tmp2++; // adjust the time depending on button pressed
else tmp2--;
if (tmp2 > 23) tmp2 = 0; // cycle mins
if (tmp2 < 0) tmp2 = 23; // cycle mins
display(2,(tmp2 % 10));// update display
display(1,(tmp2 / 10));
}
the_time = 0;
}
if (the_time > 500) {
if (mode[2] == 1) { // modify minutes
the_time = 450;
if (!button1) tmp2++; // adjust the time depending on button pressed
else tmp2--;
if (tmp2 > 59) tmp2 = 0; // cycle mins
if (tmp2 < 0) tmp2 = 59; // cycle mins
display(4,(tmp2 % 10));// update display
display(3,(tmp2 / 10));
} else{
if (!button1) tmp2++; // adjust the time depending on button pressed
else tmp2--;
if (tmp2 > 23) tmp2 = 0; // cycle mins
if (tmp2 < 0) tmp2 = 23; // cycle mins
display(2,(tmp2 % 10));// update display
display(1,(tmp2 / 10));
}
}
button1 = (PIND & (1<<PD7)); // update button status
button2 = (PIND & (1<<PD6)); // update button status
if ((button1) || (button2)) { // filter glitches, if its off wait 2ms then reread the button
delay_ms(2); // its probably the cheap switches im using but as they approach being on they would switch on and off very fast a few times
button1 = (PIND & (1<<PD7)); // update button status
button2 = (PIND & (1<<PD6)); // update button status
}
}
if (counter) {
if (mode[2] == 1) {
write_minutes(tmp2); // update clock
min_s = tmp2 % 10;
min_t = tmp2 / 10;
} else {
write_hours(tmp2);
hr_s = tmp2 % 10;
hr_t = tmp2 / 10;
}
tmp2 = 0;
counter = 0;
}
// if button 3 pressed change from min-hr and then back to time
while (!button3) {
if ((!tmp2) && (mode[2] == 1)) {
tmp2 = 1;
mode[2]++;
}
if ((!tmp2) && (mode[2] == 2)) { // after setting hours go back to displaying the time
tmp = 0;
tmp2 = 1;
mode[2] = 0;
mode[0] = 0;
the_time = 100; // so time is updated straight away
}
button3 = (PIND & (1<<PD5)); // update button status
if (button3) { // filter glitches, if its off wait 2ms then reread the button
delay_ms(2); // its probably the cheap switches im using but as they approach being on they would switch on and off very fast a few times
button3 = (PIND & (1<<PD5)); // update button status
}
}
tmp2 = 0;
} // end of while(tmp)
}
}
}
break;
default:
mode[0] = 0;
the_time = 100; // so clock will sync straight away
}
} // end of while(1);
return 0;
} // end of main()