#include <avr/io.h>
#include <avr/interrupt.h>

#define RED_PIN 2
#define YELLOW_PIN 4
#define GREEN_PIN 7
#define PED_RED_PIN 5
#define PED_GREEN_PIN 6
#define BUTTON_PIN 3 

volatile uint8_t traffic_state = 0;
volatile uint16_t timer_count = 0;

void traffic_red_on() { PORTD |= (1 << RED_PIN); }         
void traffic_red_off() { PORTD &= ~(1 << RED_PIN); }       
void traffic_yellow_on() { PORTD |= (1 << YELLOW_PIN); }   
void traffic_yellow_off() { PORTD &= ~(1 << YELLOW_PIN); } 
void traffic_green_on() { PORTD |= (1 << GREEN_PIN); }   
void traffic_green_off() { PORTD &= ~(1 << GREEN_PIN); } 

void ped_red_on() { PORTD |= (1 << PED_RED_PIN); }      
void ped_red_off() { PORTD &= ~(1 << PED_RED_PIN); }    
void ped_green_on() { PORTD |= (1 << PED_GREEN_PIN); }  
void ped_green_off() { PORTD &= ~(1 << PED_GREEN_PIN); }

void all_lights_off() {
    traffic_red_off();
    traffic_yellow_off();
    traffic_green_off();
    ped_red_off();
    ped_green_off();
} // Turn off all lights

void set_traffic_green() {
    all_lights_off();
    traffic_green_on();
    ped_red_on();
} // Set traffic light to green, pedestrian to red

void set_traffic_yellow() {
    all_lights_off();
    traffic_yellow_on();
    ped_red_on();
} // Set traffic light to yellow, pedestrian to red

void set_traffic_red() {
    all_lights_off();
    traffic_red_on();
    ped_green_on();
} // Set traffic light to red, pedestrian to green

void update_lights() {
    switch(traffic_state) {
        case 0: set_traffic_green(); break;
        case 1: set_traffic_yellow(); break;
        case 2: set_traffic_red(); break;
    }
} // Update lights based on current state

void advance_traffic_state() {
    traffic_state = (traffic_state + 1) % 3;
    update_lights();
} // Advance to the next traffic state and update lights

void handle_pedestrian_button() {
    traffic_state = 2;  
    timer_count = 0;    
    update_lights();
} // Handle button press by setting state to RED and resetting timer

ISR(TIMER1_COMPA_vect) {
    timer_count++;
    if (timer_count >= 400) { 
        timer_count = 0;
        advance_traffic_state();
    }
} // Timer interrupt to advance traffic state

ISR(INT1_vect) {
    static unsigned long last_interrupt_time = 0;
    unsigned long interrupt_time = millis();
    if (interrupt_time - last_interrupt_time > 200) {  
        handle_pedestrian_button();
    } // This is debounce

    last_interrupt_time = interrupt_time;
} // Interrupt to handle pedestrian button press

void timer1_init() {
    TCCR1A = 0;
    TCCR1B = (1 << WGM12) | (1 << CS11) | (1 << CS10); 
    OCR1A = 2499;  
    TIMSK1 = (1 << OCIE1A);  
} // Initialize Timer1 for periodic interrupts

void button_interrupt_init() {
    EICRA |= (1 << ISC10) | (1 << ISC11);
    EIMSK |= (1 << INT1);   
} // Initialize external interrupt for button

void setup_pins() {
    DDRD |= (1 << RED_PIN) | (1 << YELLOW_PIN) | (1 << GREEN_PIN) | (1 << PED_RED_PIN) | (1 << PED_GREEN_PIN);
    DDRD &= ~(1 << BUTTON_PIN);
    PORTD |= (1 << BUTTON_PIN);
} // Set up pins for LEDs and button

void setup() {
    setup_pins();
    timer1_init();
    button_interrupt_init();
    sei();  
    update_lights();
    Serial.begin(9600);
} // Initialize everything and start serial communication

void print_debug_info() {
    Serial.print("State: ");
    Serial.print(traffic_state);
    Serial.print(", Time: ");
    Serial.print(timer_count);
    Serial.print(", Button: ");
    Serial.println(digitalRead(BUTTON_PIN) ? "Released" : "Pressed");
} // Print debug information to serial monitor

void loop() {
    print_debug_info();
    delay(100); 
} // Main loop to print debug info and delay