#include <LiquidCrystal.h> /* LCD Library */
#include <avr/wdt.h> /* watch dog timer functions */
//button press checker
#define PD2ON 0x04 /* 0000 0100 WATCH DOG BUTTON */
#define PD3ON 0x08 /* 0000 1000 STOP BUTTON */
#define PD4ON 0x10 /* 0001 0000 COUNT_DOWN BUTTON */
#define PD5ON 0x20 /* 0010 0000 COUNT_UP BUTTON */
#define wdt_reset() __asm__ __volatile__ ("wdr")
const int rs = 12, en = 11, d4 = 10, d5 = 8, d6 = 7, d7 = 6;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
// list of prohibited libraries
bool upCheck = false; /* check if button 1 is clicked */
bool downCheck = false; /* check if button 2 is clicked */
bool stopCheck = false; /* check if button 3 is clicked */
bool lcdState = true; /* check if the lcd is available */
bool wdState = false; /* check if button 4 is clicked */
float timer = 0.0; /* time value */
float mills = 1562.5; /* initial millisecond value */
unsigned int wdtValue = 0; /* wdt value */
int stateValue;
String state[] = {"STOP ", "COUNT_DOWN", "COUNT_UP"};
void setup() {
// Set up Timer1
Serial.begin(9600);
lcd.begin(16, 2);
lcd.print("STOP");
lcd.setCursor(0, 1);
lcd.print("00.0s");
lcd.setCursor(6, 1);
lcd.print("wait:000ms");
DDRD &= ~0xC3;
noInterrupts(); // Disable all interrupts
TCCR1A = 0; // Reset Timer/Counter Control Register (TCCR1A) register
TCCR1B = 0; // Reset Timer/Counter Control Register (TCCR1B) register
// Set the prescaler to 1024
TCCR1B |= 0x05;
// Set the compare match value for 1s
OCR1A = mills; //(15625 ≒ 1s / (1 / (16MHz / 1024)))
// Set the Clear Timer on Compare(CTC) mode
TCCR1B |= (1 << WGM12);
// Enable Timer1 compare match A interrupt
TIMSK1 |= (1 << OCIE1A);
interrupts(); // Enable all interrupts
wdt_disable();
delay(500);
wdt_enable(WDTO_250MS);
}
void loop() {
// put your main code here, to run repeatedly:
lcd.setCursor(0, 0);
lcd.print(state[stateValue]);
lcd.setCursor(0, 1);
if (timer <= 9.99) {
lcd.print(0);
}
lcd.print(timer, 1);
lcd.print("s wait:");
lcd.setCursor(11, 1);
if (wdtValue <= 1 ) {
lcd.print(0);
}
delay(60 * wdtValue);
if (wdtValue < 250) {
lcd.print(60 * wdtValue);
}
wdt_reset();
}
ISR(WDT_vect) {
OCR1A = mills;
wdtValue = 0;
timer = 0.0;
stateValue = 0;
}
// Timer1 compare match A interrupt service routine
ISR(TIMER1_COMPA_vect) {
int wdtState;
static int lastWdtState = PIND & 0x04;
//if button press
if (PIND & PD5ON && lcdState == true) { /* count up button press */
upCheck = true;
downCheck = false;
stopCheck = false;
} else if (PIND & PD4ON && lcdState == true) { /* count down button press */
downCheck = true;
upCheck = false;
stopCheck = false;
} else if (PIND & PD3ON && lcdState == false) { /* stop button press */
lcdState = true;
stopCheck = true;
} else if (PIND & PD3ON && lcdState == true) { /* stop button press again */
timer = 0.0;
} else if (PIND & 0x04) { /* watch dog button press again */
wdtState = (PIND & 0x04);
if (lastWdtState == wdtState) {
//nothing will happen
} else {
if (wdtState < 250) {
wdtValue++;
}
lastWdtState = wdtState;
}
} else {
lastWdtState = wdtState;
}
//button funtion
if (upCheck == true && stopCheck == false) { /* COUNT_UP */
timer += 0.1; /* timer increase */
lcdState = false;
if (timer >= 20.0) { /* if timer goes to 20 */
timer = 20.0;
stateValue = 0;
lcdState = true;
} else { /* else COUNT_UP */
stateValue = 2;
}
} else if (downCheck == true && stopCheck == false) { /* COUNT_DOWN */
timer -= 0.1; /* timer decrease */
lcdState = false;
if (timer <= 0.0) { /* if timer goes to 0 */
timer = 0.0;
stateValue = 0;
lcdState = true;
} else { /* else COUNT_DOWN */
stateValue = 1;
}
} else if (stopCheck == true) { /* STOP */
stateValue = 0;
}
}