#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
constexpr auto LED1 = 7;
constexpr auto LED2 = 6;
constexpr auto LED3 = 5;
constexpr auto BTN = 2;
int leds[] = {LED1, LED2, LED3};
int ledCount = sizeof(leds) / sizeof(leds[0]);
bool sequenceActive = true;
unsigned long lastUpdate = 0;
int currentLed = 1;
int lastLed = 0;
const unsigned long interval = 400;
volatile bool stopFlag = false;
unsigned long lastDebounceTime = 0; // debounce time
const unsigned long debounceDelay = 10; // debounce delay (ms)
volatile unsigned long systemMillis = 0; // custom millis counter
void setup() {
Serial.println("setup");
// Configure LEDs as output
DDRD |= (1 << LED1) | (1 << LED2) | (1 << LED3);
// Configure button pin as input with pull-up resistor
DDRD &= ~(1 << BTN);
PORTD |= (1 << BTN);
// Configure Timer1 to simulate millis
TCCR1A = 0;
TCCR1B = (1 << WGM12) | (1 << CS11) | (1 << CS10); // CTC mode, prescaler 64
OCR1A = 249; // 1 ms with 16MHz clock
TIMSK1 = (1 << OCIE1A); // Enable Timer1 compare interrupt
// Enable external interrupt on BTN (assuming it corresponds to INT0)
EICRA |= (1 << ISC11); // Trigger on falling edge
EIMSK |= (1 << INT0); // Enable INT0 interrupt
sei(); // Enable global interrupts
// Enable watchdog timer with a 1-second timeout
wdt_enable(WDTO_1S);
}
// Custom millis function to simulate Arduino's millis()
unsigned long customMillis() {
unsigned long millisCopy;
// cli();
millisCopy = systemMillis;
// sei();
return millisCopy;
}
void loop() {
if (stopFlag)
return;
wdt_reset();
unsigned long currentMillis = customMillis();
if (currentMillis - lastUpdate >= interval) {
PORTD &= ~(1 << leds[lastLed]); // Turn off the previous LED
currentLed++;
if (currentLed >= ledCount)
currentLed = 0;
PORTD |= (1 << leds[currentLed]); // Turn on the current LED
lastUpdate = customMillis();
lastLed = currentLed;
}
}
// ISR for Timer1 compare match to update millis counter
ISR(TIMER1_COMPA_vect) {
systemMillis++;
}
// External interrupt ISR for button press
ISR(INT0_vect) {
unsigned long debounceMillis = customMillis();
if (debounceMillis - lastDebounceTime > debounceDelay) {
stopFlag = true;
lastDebounceTime = debounceMillis;
}
}