#include <avr/interrupt.h>
#include <avr/io.h>
#include <stdint.h>
static volatile enum states {
GREEN_NORTH,
BLINKING_NORTH_ON_1,
BLINKING_NORTH_OFF_1,
BLINKING_NORTH_ON_2,
BLINKING_NORTH_OFF_2,
BLINKING_NORTH_ON_3,
BLINKING_NORTH_OFF_3,
YELLOW_NORTH,
GREEN_SOUTH,
BLINKING_SOUTH_ON_1,
BLINKING_SOUTH_OFF_1,
BLINKING_SOUTH_ON_2,
BLINKING_SOUTH_OFF_2,
BLINKING_SOUTH_ON_3,
BLINKING_SOUTH_OFF_3,
YELLOW_SOUTH,
GREEN_EAST,
BLINKING_EAST_ON_1,
BLINKING_EAST_OFF_1,
BLINKING_EAST_ON_2,
BLINKING_EAST_OFF_2,
BLINKING_EAST_ON_3,
BLINKING_EAST_OFF_3,
YELLOW_EAST,
GREEN_WEST,
BLINKING_WEST_ON_1,
BLINKING_WEST_OFF_1,
BLINKING_WEST_ON_2,
BLINKING_WEST_OFF_2,
BLINKING_WEST_ON_3,
BLINKING_WEST_OFF_3,
YELLOW_WEST,
} current_state;
enum { TCNT0_MAX = 250, TCNT0_START = 256 - TCNT0_MAX };
enum { ON_MS = 10000, BLINK_MS = 500, YELLOW_MS = 3000 };
static const volatile uint32_t ticks = (1e-3 * (((double) F_CPU / 8.0) / ((double) TCNT0_MAX))) + 0.5;
static volatile uint32_t t = 0;
static volatile uint32_t overflows = 0;
static void set_north_green_led(void) {
PORTA |= _BV(PA0);
}
static void set_north_yellow_led(void) {
PORTA |= _BV(PA1);
}
static void set_north_red_led(void) {
PORTA |= _BV(PA2);
}
static void reset_north_green_led(void) {
PORTA &= ~(_BV(PA0));
}
static void reset_north_yellow_led(void) {
PORTA &= ~(_BV(PA1));
}
static void reset_north_red_led(void) {
PORTA &= ~(_BV(PA2));
}
static void set_south_green_led(void) {
PORTA |= _BV(PA3);
}
static void set_south_yellow_led(void) {
PORTA |= _BV(PA4);
}
static void set_south_red_led(void) {
PORTA |= _BV(PA5);
}
static void reset_south_green_led(void) {
PORTA &= ~(_BV(PA3));
}
static void reset_south_yellow_led(void) {
PORTA &= ~(_BV(PA4));
}
static void reset_south_red_led(void) {
PORTA &= ~(_BV(PA5));
}
static void set_east_green_led(void) {
PORTA |= _BV(PA6);
}
static void set_east_yellow_led(void) {
PORTA |= _BV(PA7);
}
static void set_east_red_led(void) {
PORTB |= _BV(PB0);
}
static void reset_east_green_led(void) {
PORTA &= ~(_BV(PA6));
}
static void reset_east_yellow_led(void) {
PORTA &= ~(_BV(PA7));
}
static void reset_east_red_led(void) {
PORTB &= ~(_BV(PB0));
}
static void set_west_green_led(void) {
PORTB |= _BV(PB1);
}
static void set_west_yellow_led(void) {
PORTB |= _BV(PB2);
}
static void set_west_red_led(void) {
PORTB |= _BV(PB3);
}
static void reset_west_green_led(void) {
PORTB &= ~(_BV(PB1));
}
static void reset_west_yellow_led(void) {
PORTB &= ~(_BV(PB2));
}
static void reset_west_red_led(void) {
PORTB &= ~(_BV(PB3));
}
static void set_north_off(void) {
reset_north_green_led();
reset_north_yellow_led();
reset_north_red_led();
}
static void set_north_green(void) {
set_north_green_led();
reset_north_yellow_led();
reset_north_red_led();
}
static void set_north_yellow(void) {
reset_north_green_led();
set_north_yellow_led();
reset_north_red_led();
}
static void set_north_red(void) {
reset_north_green_led();
reset_north_yellow_led();
set_north_red_led();
}
static void set_south_off(void) {
reset_south_green_led();
reset_south_yellow_led();
reset_south_red_led();
}
static void set_south_green(void) {
set_south_green_led();
reset_south_yellow_led();
reset_south_red_led();
}
static void set_south_yellow(void) {
reset_south_green_led();
set_south_yellow_led();
reset_south_red_led();
}
static void set_south_red(void) {
reset_south_green_led();
reset_south_yellow_led();
set_south_red_led();
}
static void set_east_off(void) {
reset_east_green_led();
reset_east_yellow_led();
reset_east_red_led();
}
static void set_east_green(void) {
set_east_green_led();
reset_east_yellow_led();
reset_east_red_led();
}
static void set_east_yellow(void) {
reset_east_green_led();
set_east_yellow_led();
reset_east_red_led();
}
static void set_east_red(void) {
reset_east_green_led();
reset_east_yellow_led();
set_east_red_led();
}
static void set_west_off(void) {
reset_west_green_led();
reset_west_yellow_led();
reset_west_red_led();
}
static void set_west_green(void) {
set_west_green_led();
reset_west_yellow_led();
reset_west_red_led();
}
static void set_west_yellow(void) {
reset_west_green_led();
set_west_yellow_led();
reset_west_red_led();
}
static void set_west_red(void) {
reset_west_green_led();
reset_west_yellow_led();
set_west_red_led();
}
static void wait_ms(uint32_t seconds) {
t = seconds;
TCCR0 |= (_BV(CS01));
TCNT0 = TCNT0_START;
}
static void next_state(void) {
current_state = (current_state != YELLOW_WEST ? current_state + 1 : 0);
}
ISR(TIMER0_OVF_vect) {
if (++overflows >= ticks * t) {
switch (current_state) {
case GREEN_NORTH:
wait_ms(BLINK_MS);
break;
case BLINKING_NORTH_ON_1:
wait_ms(BLINK_MS);
break;
case BLINKING_NORTH_OFF_1:
wait_ms(BLINK_MS);
break;
case BLINKING_NORTH_ON_2:
wait_ms(BLINK_MS);
break;
case BLINKING_NORTH_OFF_2:
wait_ms(BLINK_MS);
break;
case BLINKING_NORTH_ON_3:
wait_ms(BLINK_MS);
break;
case BLINKING_NORTH_OFF_3:
wait_ms(YELLOW_MS);
break;
case YELLOW_NORTH:
wait_ms(ON_MS);
break;
case GREEN_SOUTH:
wait_ms(BLINK_MS);
break;
case BLINKING_SOUTH_ON_1:
wait_ms(BLINK_MS);
break;
case BLINKING_SOUTH_OFF_1:
wait_ms(BLINK_MS);
break;
case BLINKING_SOUTH_ON_2:
wait_ms(BLINK_MS);
break;
case BLINKING_SOUTH_OFF_2:
wait_ms(BLINK_MS);
break;
case BLINKING_SOUTH_ON_3:
wait_ms(BLINK_MS);
break;
case BLINKING_SOUTH_OFF_3:
wait_ms(YELLOW_MS);
break;
case YELLOW_SOUTH:
wait_ms(ON_MS);
break;
case GREEN_EAST:
wait_ms(BLINK_MS);
break;
case BLINKING_EAST_ON_1:
wait_ms(BLINK_MS);
break;
case BLINKING_EAST_OFF_1:
wait_ms(BLINK_MS);
break;
case BLINKING_EAST_ON_2:
wait_ms(BLINK_MS);
break;
case BLINKING_EAST_OFF_2:
wait_ms(BLINK_MS);
break;
case BLINKING_EAST_ON_3:
wait_ms(BLINK_MS);
break;
case BLINKING_EAST_OFF_3:
wait_ms(YELLOW_MS);
break;
case YELLOW_EAST:
wait_ms(ON_MS);
break;
case GREEN_WEST:
wait_ms(BLINK_MS);
break;
case BLINKING_WEST_ON_1:
wait_ms(BLINK_MS);
break;
case BLINKING_WEST_OFF_1:
wait_ms(BLINK_MS);
break;
case BLINKING_WEST_ON_2:
wait_ms(BLINK_MS);
break;
case BLINKING_WEST_OFF_2:
wait_ms(BLINK_MS);
break;
case BLINKING_WEST_ON_3:
wait_ms(BLINK_MS);
break;
case BLINKING_WEST_OFF_3:
wait_ms(YELLOW_MS);
break;
case YELLOW_WEST:
wait_ms(ON_MS);
break;
default:
break;
}
overflows = 0;
next_state();
}
TCNT0 = TCNT0_START;
}
static void initialize_io_registers(void) {
DDRA = 0xff;
DDRB |= (_BV(PB0) | _BV(PB1) | _BV(PB2) | _BV(PB3));
}
static void initialize_interrupt_registers(void) {
TIMSK |= (_BV(TOIE0));
sei();
}
static void initialize_start_state(void) {
current_state = GREEN_NORTH;
wait_ms(ON_MS);
}
int main(void) {
initialize_io_registers();
initialize_interrupt_registers();
initialize_start_state();
for (;;) {
switch (current_state) {
case GREEN_NORTH:
set_north_green();
set_south_red();
set_east_red();
set_west_red();
break;
case BLINKING_NORTH_ON_1:
set_north_green();
set_south_red();
set_east_red();
set_west_red();
break;
case BLINKING_NORTH_OFF_1:
set_north_off();
set_south_red();
set_east_red();
set_west_red();
break;
case BLINKING_NORTH_ON_2:
set_north_green();
set_south_red();
set_east_red();
set_west_red();
break;
case BLINKING_NORTH_OFF_2:
set_north_off();
set_south_red();
set_east_red();
set_west_red();
break;
case BLINKING_NORTH_ON_3:
set_north_green();
set_south_red();
set_east_red();
set_west_red();
break;
case BLINKING_NORTH_OFF_3:
set_north_off();
set_south_red();
set_east_red();
set_west_red();
break;
case YELLOW_NORTH:
set_north_yellow();
set_south_red();
set_east_red();
set_west_red();
break;
case GREEN_SOUTH:
set_north_red();
set_south_green();
set_east_red();
set_west_red();
break;
case BLINKING_SOUTH_ON_1:
set_north_red();
set_south_green();
set_east_red();
set_west_red();
break;
case BLINKING_SOUTH_OFF_1:
set_north_red();
set_south_off();
set_east_red();
set_west_red();
break;
case BLINKING_SOUTH_ON_2:
set_north_red();
set_south_green();
set_east_red();
set_west_red();
break;
case BLINKING_SOUTH_OFF_2:
set_north_red();
set_south_off();
set_east_red();
set_west_red();
break;
case BLINKING_SOUTH_ON_3:
set_north_red();
set_south_green();
set_east_red();
set_west_red();
break;
case BLINKING_SOUTH_OFF_3:
set_north_red();
set_south_off();
set_east_red();
set_west_red();
break;
case YELLOW_SOUTH:
set_north_red();
set_south_yellow();
set_east_red();
set_west_red();
break;
case GREEN_EAST:
set_north_red();
set_south_red();
set_east_green();
set_west_red();
break;
case BLINKING_EAST_ON_1:
set_north_red();
set_south_red();
set_east_green();
set_west_red();
break;
case BLINKING_EAST_OFF_1:
set_north_red();
set_south_red();
set_east_off();
set_west_red();
break;
case BLINKING_EAST_ON_2:
set_north_red();
set_south_red();
set_east_green();
set_west_red();
break;
case BLINKING_EAST_OFF_2:
set_north_red();
set_south_red();
set_east_off();
set_west_red();
break;
case BLINKING_EAST_ON_3:
set_north_red();
set_south_red();
set_east_green();
set_west_red();
break;
case BLINKING_EAST_OFF_3:
set_north_red();
set_south_red();
set_east_off();
set_west_red();
break;
case YELLOW_EAST:
set_north_red();
set_south_red();
set_east_yellow();
set_west_red();
break;
case GREEN_WEST:
set_north_red();
set_south_red();
set_east_red();
set_west_green();
break;
case BLINKING_WEST_ON_1:
set_north_red();
set_south_red();
set_east_red();
set_west_green();
break;
case BLINKING_WEST_OFF_1:
set_north_red();
set_south_red();
set_east_red();
set_west_off();
break;
case BLINKING_WEST_ON_2:
set_north_red();
set_south_red();
set_east_red();
set_west_green();
break;
case BLINKING_WEST_OFF_2:
set_north_red();
set_south_red();
set_east_red();
set_west_off();
break;
case BLINKING_WEST_ON_3:
set_north_red();
set_south_red();
set_east_red();
set_west_green();
break;
case BLINKING_WEST_OFF_3:
set_north_red();
set_south_red();
set_east_red();
set_west_off();
break;
case YELLOW_WEST:
set_north_red();
set_south_red();
set_east_red();
set_west_yellow();
break;
default:
break;
}
}
return 0;
}