#include <LiquidCrystal.h>
#include <avr/io.h>
#include <avr/interrupt.h>
// Initialize the LCD (update pins as needed)
LiquidCrystal lcd(12, 11, 10, 8, 7, 6);
// Pin definitions
const int buttonCountUpPin = 5; // PD5
const int buttonCountDownPin = 4; // PD4
const int buttonStopResetPin = 3; // PD3
// State definitions
enum State {
STOP,
COUNT_UP,
COUNT_DOWN
};
// Global variables
volatile State currentState = STOP;
volatile float countValue = 0.0;
// Timer setup function
void setupTimer() {
TCCR1A = 0; // Clear control register A
TCCR1B = 0; // Clear control register B
TCCR1B |= (1 << WGM12); // Set CTC mode
TCCR1B |= (1 << CS12); // Set prescaler to 256
OCR1A = 625; // Set compare value for 1 second (16MHz/256)
TIMSK1 |= (1 << OCIE1A); // Enable compare interrupt
}
ISR(TIMER1_COMPA_vect) {
if (currentState == COUNT_UP) {
countValue += 1.0; // Increment count
if (countValue >= 20.0) {
currentState = STOP; // Stop at 20 seconds
}
} else if (currentState == COUNT_DOWN) {
countValue -= 1.0; // Decrement count
if (countValue <= 0.0) {
currentState = STOP; // Stop at 0 seconds
countValue = 0.0; // Ensure countValue does not go negative
}
}
}
void setup() {
// Set up LCD
lcd.begin(16, 2);
lcd.print("Status: STOP");
lcd.setCursor(0, 1);
lcd.print("Count: 0.0 s");
// Set up button pins as inputs (using direct port manipulation)
DDRD &= ~((1 << buttonCountUpPin) | (1 << buttonCountDownPin) | (1 << buttonStopResetPin)); // Set pins as input
PORTD |= (1 << buttonCountUpPin) | (1 << buttonCountDownPin) | (1 << buttonStopResetPin); // Enable pull-up resistors
// Set up timer
setupTimer();
sei(); // Enable global interrupts
}
void loop() {
// Read button states
bool buttonCountUp = !(PIND & (1 << buttonCountUpPin));
bool buttonCountDown = !(PIND & (1 << buttonCountDownPin));
bool buttonStopReset = !(PIND & (1 << buttonStopResetPin));
// Button handling
if (buttonCountUp && currentState == STOP) {
currentState = COUNT_UP;
delay(200); // Debounce delay
}
else if (buttonCountDown && currentState == STOP) {
currentState = COUNT_DOWN;
countValue = 20.0; // Start from 20 seconds
delay(200); // Debounce delay
}
else if (buttonStopReset) {
if (currentState == COUNT_UP || currentState == COUNT_DOWN) {
currentState = STOP;
}
else if (currentState == STOP) {
countValue = 0.0; // Reset count
}
delay(200); // Debounce delay
}
// Update the LCD
updateLCD();
}
void updateLCD() {
lcd.clear();
// Display current state
switch (currentState) {
case STOP:
lcd.print("Status: STOP");
break;
case COUNT_UP:
lcd.print("Status: COUNT_UP");
break;
case COUNT_DOWN:
lcd.print("Status: COUNT_DOWN");
break;
}
// Display count value
lcd.setCursor(0, 1);
lcd.print("Count: ");
lcd.print(countValue, 1); // One decimal place
lcd.print(" s");
}