#include <avr/interrupt.h>
#include <avr/io.h>
#include <stddef.h>
#include <stdint.h>
static const struct traffic_light {
struct traffic_light_led {
volatile uint8_t *port;
uint8_t pin;
} green, amber, red;
} traffic_lights[] = {
/* North traffic lights */
{
/* Green Light */
{&PORTA, PA0},
/* Amber Light */
{&PORTA, PA1},
/* Red Light */
{&PORTA, PA2}
},
/* South traffic lights */
{
/* Green Light */
{&PORTA, PA3},
/* Amber light */
{&PORTA, PA4},
/* Red Light */
{&PORTA, PA5}
},
/* East traffic lights */
{
/* Green Light */
{&PORTA, PA6},
/* Amber Light */
{&PORTA, PA7},
/* Red Light */
{&PORTB, PB0}
},
/* West traffic lights */
{
/* Green Light */
{&PORTB, PB1},
/* Amber Light */
{&PORTB, PB2},
/* Red Light */
{&PORTB, PB3}
},
};
static void set_traffic_light_led(const struct traffic_light_led *led) {
*(led->port) |= _BV(led->pin);
}
static void reset_traffic_light_led(const struct traffic_light_led *led) {
*(led->port) &= ~(_BV(led->pin));
}
static void set_traffic_light_green(const struct traffic_light *light) {
set_traffic_light_led(&light->green);
reset_traffic_light_led(&light->amber);
reset_traffic_light_led(&light->red);
}
static void set_traffic_light_amber(const struct traffic_light *light) {
reset_traffic_light_led(&light->green);
set_traffic_light_led(&light->amber);
reset_traffic_light_led(&light->red);
}
static void set_traffic_light_red(const struct traffic_light *light) {
reset_traffic_light_led(&light->green);
reset_traffic_light_led(&light->amber);
set_traffic_light_led(&light->red);
}
static void reset_traffic_light(const struct traffic_light *light) {
reset_traffic_light_led(&light->green);
reset_traffic_light_led(&light->amber);
reset_traffic_light_led(&light->red);
}
typedef void (output_state)(const struct traffic_light *);
#define s_off &reset_traffic_light
#define s_green &set_traffic_light_green
#define s_amber &set_traffic_light_amber
#define s_red &set_traffic_light_red
#define ARRAY_SIZE(a) (sizeof (a) / sizeof (*a))
static output_state * const output_states[] = {
s_green, s_off, s_green, s_off, s_green, s_off, s_green, s_off, s_amber,
s_red, s_red, s_red, s_red, s_red, s_red, s_red, s_red, s_red,
s_red, s_red, s_red, s_red, s_red, s_red, s_red, s_red, s_red,
s_red, s_red, s_red, s_red, s_red, s_red, s_red, s_red, s_red
};
#undef s_red
#undef s_amber
#undef s_green
#undef s_off
enum { TCNT0_MAX = 250, TCNT0_START = 256 - TCNT0_MAX };
static volatile size_t ticks_per_ms = (1e-3 * (((double) F_CPU / 8.0) / ((double) TCNT0_MAX))) + 0.5;
static volatile size_t ovf = 0;
/* State transition times in milliseconds */
enum { GREEN_MS = 10000u, BLINK_MS = 500u, AMBER_MS = 3000u };
static const size_t times[] = {
GREEN_MS, BLINK_MS, BLINK_MS,
BLINK_MS, BLINK_MS, BLINK_MS,
BLINK_MS, BLINK_MS, AMBER_MS
};
static volatile size_t current_time = 0;
static volatile size_t ms = 5000u;
static volatile size_t current_states[] = {
/* North traffic lights start state */
0u,
/* South traffic lights start state */
27u,
/* East traffic lights start state */
18u,
/* West traffic lights start state */
9u
};
static void run_states(void) {
for (size_t i = 0; i < ARRAY_SIZE(current_states); ++i) {
output_states[current_states[i]](&traffic_lights[i]);
}
}
static void next_states(void) {
for (size_t i = 0; i < ARRAY_SIZE(current_states); ++i) {
if (current_states[i] != ARRAY_SIZE(current_states) - 1) {
++current_states[i];
} else {
current_states[i] = 0;
}
}
}
static void next_times(void) {
if (current_time != ARRAY_SIZE(times) - 1) {
++current_time;
} else {
current_time = 0;
}
ms = times[current_time];
TCNT0 = TCNT0_START;
}
ISR(TIMER0_OVF_vect) {
if (++ovf >= ticks_per_ms * ms) {
next_states();
next_times();
run_states();
}
}
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) {
run_states();
ms = times[current_time];
TCCR0 |= (_BV(CS01));
TCNT0 = TCNT0_START;
}
int main(void) {
initialize_io_registers();
initialize_interrupt_registers();
initialize_start_state();
for (;;);
return 0;
}
I2luY2x1ZGUgPGF2ci9pbnRlcnJ1cHQuaD4KI2luY2x1ZGUgPGF2ci9pby5oPgoKI2luY2x1ZGUgPHN0ZGRlZi5oPgojaW5jbHVkZSA8c3RkaW50Lmg+CgpzdGF0aWMgY29uc3Qgc3RydWN0IHRyYWZmaWNfbGlnaHQgewogIHN0cnVjdCB0cmFmZmljX2xpZ2h0X2xlZCB7CiAgICB2b2xhdGlsZSB1aW50OF90ICpwb3J0OwogICAgdWludDhfdCBwaW47CiAgfSBncmVlbiwgYW1iZXIsIHJlZDsKfSB0cmFmZmljX2xpZ2h0c1tdID0gewogIC8qIE5vcnRoIHRyYWZmaWMgbGlnaHRzICovCiAgewogICAgLyogR3JlZW4gTGlnaHQgKi8KICAgIHsmUE9SVEEsIFBBMH0sCiAgICAvKiBBbWJlciBMaWdodCAqLwogICAgeyZQT1JUQSwgUEExfSwKICAgIC8qIFJlZCBMaWdodCAqLwogICAgeyZQT1JUQSwgUEEyfQogIH0sCiAgLyogU291dGggdHJhZmZpYyBsaWdodHMgKi8KICB7CiAgICAvKiBHcmVlbiBMaWdodCAqLwogICAgeyZQT1JUQSwgUEEzfSwKICAgIC8qIEFtYmVyIGxpZ2h0ICovCiAgICB7JlBPUlRBLCBQQTR9LAogICAgLyogUmVkIExpZ2h0ICovCiAgICB7JlBPUlRBLCBQQTV9CiAgfSwKICAvKiBFYXN0IHRyYWZmaWMgbGlnaHRzICovCiAgewogICAgLyogR3JlZW4gTGlnaHQgKi8KICAgIHsmUE9SVEEsIFBBNn0sCiAgICAvKiBBbWJlciBMaWdodCAqLwogICAgeyZQT1JUQSwgUEE3fSwKICAgIC8qIFJlZCBMaWdodCAqLwogICAgeyZQT1JUQiwgUEIwfQogIH0sCiAgLyogV2VzdCB0cmFmZmljIGxpZ2h0cyAqLwogIHsKICAgIC8qIEdyZWVuIExpZ2h0ICovCiAgICB7JlBPUlRCLCBQQjF9LAogICAgLyogQW1iZXIgTGlnaHQgKi8KICAgIHsmUE9SVEIsIFBCMn0sCiAgICAvKiBSZWQgTGlnaHQgKi8KICAgIHsmUE9SVEIsIFBCM30KICB9LAp9OwoKc3RhdGljIHZvaWQgc2V0X3RyYWZmaWNfbGlnaHRfbGVkKGNvbnN0IHN0cnVjdCB0cmFmZmljX2xpZ2h0X2xlZCAqbGVkKSB7CiAgKihsZWQtPnBvcnQpIHw9IF9CVihsZWQtPnBpbik7Cn0KCnN0YXRpYyB2b2lkIHJlc2V0X3RyYWZmaWNfbGlnaHRfbGVkKGNvbnN0IHN0cnVjdCB0cmFmZmljX2xpZ2h0X2xlZCAqbGVkKSB7CiAgKihsZWQtPnBvcnQpICY9IH4oX0JWKGxlZC0+cGluKSk7Cn0KCnN0YXRpYyB2b2lkIHNldF90cmFmZmljX2xpZ2h0X2dyZWVuKGNvbnN0IHN0cnVjdCB0cmFmZmljX2xpZ2h0ICpsaWdodCkgewogIHNldF90cmFmZmljX2xpZ2h0X2xlZCgmbGlnaHQtPmdyZWVuKTsKICByZXNldF90cmFmZmljX2xpZ2h0X2xlZCgmbGlnaHQtPmFtYmVyKTsKICByZXNldF90cmFmZmljX2xpZ2h0X2xlZCgmbGlnaHQtPnJlZCk7Cn0KCnN0YXRpYyB2b2lkIHNldF90cmFmZmljX2xpZ2h0X2FtYmVyKGNvbnN0IHN0cnVjdCB0cmFmZmljX2xpZ2h0ICpsaWdodCkgewogIHJlc2V0X3RyYWZmaWNfbGlnaHRfbGVkKCZsaWdodC0+Z3JlZW4pOwogIHNldF90cmFmZmljX2xpZ2h0X2xlZCgmbGlnaHQtPmFtYmVyKTsKICByZXNldF90cmFmZmljX2xpZ2h0X2xlZCgmbGlnaHQtPnJlZCk7Cn0KCnN0YXRpYyB2b2lkIHNldF90cmFmZmljX2xpZ2h0X3JlZChjb25zdCBzdHJ1Y3QgdHJhZmZpY19saWdodCAqbGlnaHQpIHsKICByZXNldF90cmFmZmljX2xpZ2h0X2xlZCgmbGlnaHQtPmdyZWVuKTsKICByZXNldF90cmFmZmljX2xpZ2h0X2xlZCgmbGlnaHQtPmFtYmVyKTsKICBzZXRfdHJhZmZpY19saWdodF9sZWQoJmxpZ2h0LT5yZWQpOwp9CgpzdGF0aWMgdm9pZCByZXNldF90cmFmZmljX2xpZ2h0KGNvbnN0IHN0cnVjdCB0cmFmZmljX2xpZ2h0ICpsaWdodCkgewogIHJlc2V0X3RyYWZmaWNfbGlnaHRfbGVkKCZsaWdodC0+Z3JlZW4pOwogIHJlc2V0X3RyYWZmaWNfbGlnaHRfbGVkKCZsaWdodC0+YW1iZXIpOwogIHJlc2V0X3RyYWZmaWNfbGlnaHRfbGVkKCZsaWdodC0+cmVkKTsKfQoKdHlwZWRlZiB2b2lkIChvdXRwdXRfc3RhdGUpKGNvbnN0IHN0cnVjdCB0cmFmZmljX2xpZ2h0ICopOwojZGVmaW5lIHNfb2ZmICAgICZyZXNldF90cmFmZmljX2xpZ2h0CiNkZWZpbmUgc19ncmVlbiAgJnNldF90cmFmZmljX2xpZ2h0X2dyZWVuCiNkZWZpbmUgc19hbWJlciAgJnNldF90cmFmZmljX2xpZ2h0X2FtYmVyCiNkZWZpbmUgc19yZWQgICAgJnNldF90cmFmZmljX2xpZ2h0X3JlZAoKI2RlZmluZSBBUlJBWV9TSVpFKGEpIChzaXplb2YgKGEpIC8gc2l6ZW9mICgqYSkpCgpzdGF0aWMgb3V0cHV0X3N0YXRlICogY29uc3Qgb3V0cHV0X3N0YXRlc1tdID0gewogIHNfZ3JlZW4sIHNfb2ZmLCBzX2dyZWVuLCBzX29mZiwgc19ncmVlbiwgc19vZmYsIHNfZ3JlZW4sIHNfb2ZmLCBzX2FtYmVyLAogIHNfcmVkLCAgIHNfcmVkLCBzX3JlZCwgICBzX3JlZCwgc19yZWQsICAgc19yZWQsIHNfcmVkLCAgIHNfcmVkLCBzX3JlZCwKICBzX3JlZCwgICBzX3JlZCwgc19yZWQsICAgc19yZWQsIHNfcmVkLCAgIHNfcmVkLCBzX3JlZCwgICBzX3JlZCwgc19yZWQsCiAgc19yZWQsICAgc19yZWQsIHNfcmVkLCAgIHNfcmVkLCBzX3JlZCwgICBzX3JlZCwgc19yZWQsICAgc19yZWQsIHNfcmVkCn07CgojdW5kZWYgc19yZWQKI3VuZGVmIHNfYW1iZXIKI3VuZGVmIHNfZ3JlZW4KI3VuZGVmIHNfb2ZmCgplbnVtIHsgVENOVDBfTUFYID0gMjUwLCBUQ05UMF9TVEFSVCA9IDI1NiAtIFRDTlQwX01BWCB9OwoKc3RhdGljIHZvbGF0aWxlIHNpemVfdCB0aWNrc19wZXJfbXMgPSAoMWUtMyAqICgoKGRvdWJsZSkgRl9DUFUgLyA4LjApIC8gKChkb3VibGUpIFRDTlQwX01BWCkpKSArIDAuNTsKc3RhdGljIHZvbGF0aWxlIHNpemVfdCBvdmYgPSAwOwoKLyogU3RhdGUgdHJhbnNpdGlvbiB0aW1lcyBpbiBtaWxsaXNlY29uZHMgKi8KZW51bSB7IEdSRUVOX01TID0gMTAwMDB1LCBCTElOS19NUyA9IDUwMHUsIEFNQkVSX01TID0gMzAwMHUgfTsKCnN0YXRpYyBjb25zdCBzaXplX3QgdGltZXNbXSA9IHsKICBHUkVFTl9NUywgQkxJTktfTVMsIEJMSU5LX01TLAogIEJMSU5LX01TLCBCTElOS19NUywgQkxJTktfTVMsCiAgQkxJTktfTVMsIEJMSU5LX01TLCBBTUJFUl9NUwp9OwoKc3RhdGljIHZvbGF0aWxlIHNpemVfdCBjdXJyZW50X3RpbWUgPSAwOwpzdGF0aWMgdm9sYXRpbGUgc2l6ZV90IG1zID0gNTAwMHU7CgpzdGF0aWMgdm9sYXRpbGUgc2l6ZV90IGN1cnJlbnRfc3RhdGVzW10gPSB7CiAgLyogTm9ydGggdHJhZmZpYyBsaWdodHMgc3RhcnQgc3RhdGUgKi8KICAwdSwKCiAgLyogU291dGggdHJhZmZpYyBsaWdodHMgc3RhcnQgc3RhdGUgKi8KICAyN3UsCgogIC8qIEVhc3QgdHJhZmZpYyBsaWdodHMgc3RhcnQgc3RhdGUgKi8KICAxOHUsCgogIC8qIFdlc3QgdHJhZmZpYyBsaWdodHMgc3RhcnQgc3RhdGUgKi8KICA5dQp9OwoKc3RhdGljIHZvaWQgcnVuX3N0YXRlcyh2b2lkKSB7CiAgZm9yIChzaXplX3QgaSA9IDA7IGkgPCBBUlJBWV9TSVpFKGN1cnJlbnRfc3RhdGVzKTsgKytpKSB7CiAgICBvdXRwdXRfc3RhdGVzW2N1cnJlbnRfc3RhdGVzW2ldXSgmdHJhZmZpY19saWdodHNbaV0pOwogIH0KfQoKc3RhdGljIHZvaWQgbmV4dF9zdGF0ZXModm9pZCkgewogIGZvciAoc2l6ZV90IGkgPSAwOyBpIDwgQVJSQVlfU0laRShjdXJyZW50X3N0YXRlcyk7ICsraSkgewogICAgaWYgKGN1cnJlbnRfc3RhdGVzW2ldICE9IEFSUkFZX1NJWkUoY3VycmVudF9zdGF0ZXMpIC0gMSkgewogICAgICArK2N1cnJlbnRfc3RhdGVzW2ldOwogICAgfSBlbHNlIHsKICAgICAgY3VycmVudF9zdGF0ZXNbaV0gPSAwOwogICAgfQogIH0KfQoKc3RhdGljIHZvaWQgbmV4dF90aW1lcyh2b2lkKSB7CiAgaWYgKGN1cnJlbnRfdGltZSAhPSBBUlJBWV9TSVpFKHRpbWVzKSAtIDEpIHsKICAgICsrY3VycmVudF90aW1lOwogIH0gZWxzZSB7CiAgICBjdXJyZW50X3RpbWUgPSAwOwogIH0KICBtcyA9IHRpbWVzW2N1cnJlbnRfdGltZV07CiAgVENOVDAgPSBUQ05UMF9TVEFSVDsKfQoKSVNSKFRJTUVSMF9PVkZfdmVjdCkgewogIGlmICgrK292ZiA+PSB0aWNrc19wZXJfbXMgKiBtcykgewogICAgbmV4dF9zdGF0ZXMoKTsKICAgIG5leHRfdGltZXMoKTsKICAgIHJ1bl9zdGF0ZXMoKTsKICB9Cn0KCnN0YXRpYyB2b2lkIGluaXRpYWxpemVfaW9fcmVnaXN0ZXJzKHZvaWQpIHsKICBERFJBID0gMHhmZjsKICBERFJCIHw9IChfQlYoUEIwKSB8IF9CVihQQjEpIHwgX0JWKFBCMikgfCBfQlYoUEIzKSk7Cn0KCnN0YXRpYyB2b2lkIGluaXRpYWxpemVfaW50ZXJydXB0X3JlZ2lzdGVycyh2b2lkKSB7CiAgVElNU0sgfD0gKF9CVihUT0lFMCkpOwogIHNlaSgpOwp9CgpzdGF0aWMgdm9pZCBpbml0aWFsaXplX3N0YXJ0X3N0YXRlKHZvaWQpIHsKICBydW5fc3RhdGVzKCk7CiAgbXMgPSB0aW1lc1tjdXJyZW50X3RpbWVdOwogIFRDQ1IwIHw9IChfQlYoQ1MwMSkpOwogIFRDTlQwID0gVENOVDBfU1RBUlQ7Cn0KCmludCBtYWluKHZvaWQpIHsKICBpbml0aWFsaXplX2lvX3JlZ2lzdGVycygpOwogIGluaXRpYWxpemVfaW50ZXJydXB0X3JlZ2lzdGVycygpOwogIGluaXRpYWxpemVfc3RhcnRfc3RhdGUoKTsKICBmb3IgKDs7KTsKICByZXR1cm4gMDsKfQo=