#include <avr/io.h>
#include <util/delay.h>
#include <stddef.h>
#include <stdint.h>
#define ARRAY_SIZE(a) (sizeof (a) / sizeof *(a))
static const struct traffic_light {
const struct led {
volatile uint8_t *port;
uint8_t pin;
} red, amber, green;
} lights[] = {
{{&PORTA, _BV(PA0)}, {&PORTA, _BV(PA1)}, {&PORTA, _BV(PA2)}},
{{&PORTA, _BV(PA3)}, {&PORTA, _BV(PA4)}, {&PORTA, _BV(PA5)}},
{{&PORTA, _BV(PA6)}, {&PORTA, _BV(PA7)}, {&PORTB, _BV(PB0)}},
{{&PORTB, _BV(PB1)}, {&PORTB, _BV(PB2)}, {&PORTB, _BV(PB3)}},
}, *light = lights;
#define NEXT_LIGHT (light - lights < (ptrdiff_t) (ARRAY_SIZE(lights) - 1u) \
? light + 1u \
: lights)
typedef void (led_state)(const struct led *);
void set(const struct led *led) { *(led->port) |= led->pin; }
void reset(const struct led *led) { *(led->port) &= ~(led->pin); }
void light_state(led_state *f, led_state *g, led_state *h) {
f(&light->red);
g(&light->amber);
h(&light->green);
}
void light_off(void) { light_state(&reset, &reset, &reset); }
void light_red(void) { light_state(&set, &reset, &reset); }
void light_amber(void) { light_state(&reset, &set, &reset); }
void light_green(void) { light_state(&reset, &reset, &set); }
int main(void) {
DDRA = 0xffu;
DDRB |= 0x0fu;
PORTA = 0b01001100;
PORTB = 0b00000010;
for (;; light = NEXT_LIGHT) {
light_green();
_delay_ms(10000);
for (size_t i = 0u; i < 3u; ++i) {
light_off();
_delay_ms(500);
light_green();
_delay_ms(500);
}
light_off();
_delay_ms(500);
light_amber();
_delay_ms(3000);
light_red();
}
return 0;
}
I2luY2x1ZGUgPGF2ci9pby5oPgojaW5jbHVkZSA8dXRpbC9kZWxheS5oPgoKI2luY2x1ZGUgPHN0ZGRlZi5oPgojaW5jbHVkZSA8c3RkaW50Lmg+CgojZGVmaW5lIEFSUkFZX1NJWkUoYSkgKHNpemVvZiAoYSkgLyBzaXplb2YgKihhKSkKCnN0YXRpYyBjb25zdCBzdHJ1Y3QgdHJhZmZpY19saWdodCB7CiAgY29uc3Qgc3RydWN0IGxlZCB7CiAgICB2b2xhdGlsZSB1aW50OF90ICpwb3J0OwogICAgdWludDhfdCBwaW47CiAgfSByZWQsIGFtYmVyLCBncmVlbjsKfSBsaWdodHNbXSA9IHsKICB7eyZQT1JUQSwgX0JWKFBBMCl9LCB7JlBPUlRBLCBfQlYoUEExKX0sIHsmUE9SVEEsIF9CVihQQTIpfX0sCiAge3smUE9SVEEsIF9CVihQQTMpfSwgeyZQT1JUQSwgX0JWKFBBNCl9LCB7JlBPUlRBLCBfQlYoUEE1KX19LAogIHt7JlBPUlRBLCBfQlYoUEE2KX0sIHsmUE9SVEEsIF9CVihQQTcpfSwgeyZQT1JUQiwgX0JWKFBCMCl9fSwKICB7eyZQT1JUQiwgX0JWKFBCMSl9LCB7JlBPUlRCLCBfQlYoUEIyKX0sIHsmUE9SVEIsIF9CVihQQjMpfX0sCn0sICpsaWdodCA9IGxpZ2h0czsKCiNkZWZpbmUgTkVYVF9MSUdIVCAobGlnaHQgLSBsaWdodHMgPCAocHRyZGlmZl90KSAoQVJSQVlfU0laRShsaWdodHMpIC0gMXUpIFwKICA/IGxpZ2h0ICsgMXUgXAogIDogbGlnaHRzKQoKdHlwZWRlZiB2b2lkIChsZWRfc3RhdGUpKGNvbnN0IHN0cnVjdCBsZWQgKik7Cgp2b2lkIHNldChjb25zdCBzdHJ1Y3QgbGVkICpsZWQpIHsgKihsZWQtPnBvcnQpIHw9IGxlZC0+cGluOyB9CnZvaWQgcmVzZXQoY29uc3Qgc3RydWN0IGxlZCAqbGVkKSB7ICoobGVkLT5wb3J0KSAmPSB+KGxlZC0+cGluKTsgfQoKdm9pZCBsaWdodF9zdGF0ZShsZWRfc3RhdGUgKmYsIGxlZF9zdGF0ZSAqZywgbGVkX3N0YXRlICpoKSB7CiAgZigmbGlnaHQtPnJlZCk7CiAgZygmbGlnaHQtPmFtYmVyKTsKICBoKCZsaWdodC0+Z3JlZW4pOwp9Cgp2b2lkIGxpZ2h0X29mZih2b2lkKSB7IGxpZ2h0X3N0YXRlKCZyZXNldCwgJnJlc2V0LCAmcmVzZXQpOyB9CnZvaWQgbGlnaHRfcmVkKHZvaWQpIHsgbGlnaHRfc3RhdGUoJnNldCwgJnJlc2V0LCAmcmVzZXQpOyB9CnZvaWQgbGlnaHRfYW1iZXIodm9pZCkgeyBsaWdodF9zdGF0ZSgmcmVzZXQsICZzZXQsICZyZXNldCk7IH0Kdm9pZCBsaWdodF9ncmVlbih2b2lkKSB7IGxpZ2h0X3N0YXRlKCZyZXNldCwgJnJlc2V0LCAmc2V0KTsgfQoKaW50IG1haW4odm9pZCkgewogIEREUkEgPSAweGZmdTsKICBERFJCIHw9IDB4MGZ1OwogIFBPUlRBID0gMGIwMTAwMTEwMDsKICBQT1JUQiA9IDBiMDAwMDAwMTA7CiAgZm9yICg7OyBsaWdodCA9IE5FWFRfTElHSFQpIHsKICAgIGxpZ2h0X2dyZWVuKCk7CiAgICBfZGVsYXlfbXMoMTAwMDApOwogICAgZm9yIChzaXplX3QgaSA9IDB1OyBpIDwgM3U7ICsraSkgewogICAgICBsaWdodF9vZmYoKTsKICAgICAgX2RlbGF5X21zKDUwMCk7CiAgICAgIGxpZ2h0X2dyZWVuKCk7CiAgICAgIF9kZWxheV9tcyg1MDApOwogICAgfQogICAgbGlnaHRfb2ZmKCk7CiAgICBfZGVsYXlfbXMoNTAwKTsKICAgIGxpZ2h0X2FtYmVyKCk7CiAgICBfZGVsYXlfbXMoMzAwMCk7CiAgICBsaWdodF9yZWQoKTsKICB9CiAgcmV0dXJuIDA7Cn0K