fork download
  1. #include <avr/interrupt.h>
  2. #include <avr/io.h>
  3.  
  4. #include <stddef.h>
  5. #include <stdint.h>
  6.  
  7. static const struct traffic_light {
  8. struct traffic_light_led {
  9. volatile uint8_t *port;
  10. uint8_t pin;
  11. } green, amber, red;
  12. } traffic_lights[] = {
  13. /* North traffic lights */
  14. {
  15. /* Green Light */
  16. {&PORTA, PA0},
  17. /* Amber Light */
  18. {&PORTA, PA1},
  19. /* Red Light */
  20. {&PORTA, PA2}
  21. },
  22. /* South traffic lights */
  23. {
  24. /* Green Light */
  25. {&PORTA, PA3},
  26. /* Amber light */
  27. {&PORTA, PA4},
  28. /* Red Light */
  29. {&PORTA, PA5}
  30. },
  31. /* East traffic lights */
  32. {
  33. /* Green Light */
  34. {&PORTA, PA6},
  35. /* Amber Light */
  36. {&PORTA, PA7},
  37. /* Red Light */
  38. {&PORTB, PB0}
  39. },
  40. /* West traffic lights */
  41. {
  42. /* Green Light */
  43. {&PORTB, PB1},
  44. /* Amber Light */
  45. {&PORTB, PB2},
  46. /* Red Light */
  47. {&PORTB, PB3}
  48. },
  49. };
  50.  
  51. static void set_traffic_light_led(const struct traffic_light_led *led) {
  52. *(led->port) |= _BV(led->pin);
  53. }
  54.  
  55. static void reset_traffic_light_led(const struct traffic_light_led *led) {
  56. *(led->port) &= ~(_BV(led->pin));
  57. }
  58.  
  59. static void set_traffic_light_green(const struct traffic_light *light) {
  60. set_traffic_light_led(&light->green);
  61. reset_traffic_light_led(&light->amber);
  62. reset_traffic_light_led(&light->red);
  63. }
  64.  
  65. static void set_traffic_light_amber(const struct traffic_light *light) {
  66. reset_traffic_light_led(&light->green);
  67. set_traffic_light_led(&light->amber);
  68. reset_traffic_light_led(&light->red);
  69. }
  70.  
  71. static void set_traffic_light_red(const struct traffic_light *light) {
  72. reset_traffic_light_led(&light->green);
  73. reset_traffic_light_led(&light->amber);
  74. set_traffic_light_led(&light->red);
  75. }
  76.  
  77. static void reset_traffic_light(const struct traffic_light *light) {
  78. reset_traffic_light_led(&light->green);
  79. reset_traffic_light_led(&light->amber);
  80. reset_traffic_light_led(&light->red);
  81. }
  82.  
  83. typedef void (output_state)(const struct traffic_light *);
  84. #define s_off &reset_traffic_light
  85. #define s_green &set_traffic_light_green
  86. #define s_amber &set_traffic_light_amber
  87. #define s_red &set_traffic_light_red
  88.  
  89. #define ARRAY_SIZE(a) (sizeof (a) / sizeof (*a))
  90.  
  91. static output_state * const output_states[] = {
  92. s_green, s_off, s_green, s_off, s_green, s_off, s_green, s_off, s_amber,
  93. s_red, s_red, s_red, s_red, s_red, s_red, s_red, s_red, s_red,
  94. s_red, s_red, s_red, s_red, s_red, s_red, s_red, s_red, s_red,
  95. s_red, s_red, s_red, s_red, s_red, s_red, s_red, s_red, s_red
  96. };
  97.  
  98. #undef s_red
  99. #undef s_amber
  100. #undef s_green
  101. #undef s_off
  102.  
  103. enum { TCNT0_MAX = 250, TCNT0_START = 256 - TCNT0_MAX };
  104.  
  105. static volatile size_t ticks_per_ms = (1e-3 * (((double) F_CPU / 8.0) / ((double) TCNT0_MAX))) + 0.5;
  106. static volatile size_t ovf = 0;
  107.  
  108. /* State transition times in milliseconds */
  109. enum { GREEN_MS = 10000u, BLINK_MS = 500u, AMBER_MS = 3000u };
  110.  
  111. static const size_t times[] = {
  112. GREEN_MS, BLINK_MS, BLINK_MS,
  113. BLINK_MS, BLINK_MS, BLINK_MS,
  114. BLINK_MS, BLINK_MS, AMBER_MS
  115. };
  116.  
  117. static volatile size_t current_time = 0;
  118. static volatile size_t ms = 5000u;
  119.  
  120. static volatile size_t current_states[] = {
  121. /* North traffic lights start state */
  122. 0u,
  123.  
  124. /* South traffic lights start state */
  125. 27u,
  126.  
  127. /* East traffic lights start state */
  128. 18u,
  129.  
  130. /* West traffic lights start state */
  131. 9u
  132. };
  133.  
  134. static void run_states(void) {
  135. for (size_t i = 0; i < ARRAY_SIZE(current_states); ++i) {
  136. output_states[current_states[i]](&traffic_lights[i]);
  137. }
  138. }
  139.  
  140. static void next_states(void) {
  141. for (size_t i = 0; i < ARRAY_SIZE(current_states); ++i) {
  142. if (current_states[i] != ARRAY_SIZE(current_states) - 1) {
  143. ++current_states[i];
  144. } else {
  145. current_states[i] = 0;
  146. }
  147. }
  148. }
  149.  
  150. static void next_times(void) {
  151. if (current_time != ARRAY_SIZE(times) - 1) {
  152. ++current_time;
  153. } else {
  154. current_time = 0;
  155. }
  156. ms = times[current_time];
  157. TCNT0 = TCNT0_START;
  158. }
  159.  
  160. ISR(TIMER0_OVF_vect) {
  161. if (++ovf >= ticks_per_ms * ms) {
  162. next_states();
  163. next_times();
  164. run_states();
  165. }
  166. }
  167.  
  168. static void initialize_io_registers(void) {
  169. DDRA = 0xff;
  170. DDRB |= (_BV(PB0) | _BV(PB1) | _BV(PB2) | _BV(PB3));
  171. }
  172.  
  173. static void initialize_interrupt_registers(void) {
  174. TIMSK |= (_BV(TOIE0));
  175. sei();
  176. }
  177.  
  178. static void initialize_start_state(void) {
  179. run_states();
  180. ms = times[current_time];
  181. TCCR0 |= (_BV(CS01));
  182. TCNT0 = TCNT0_START;
  183. }
  184.  
  185. int main(void) {
  186. initialize_io_registers();
  187. initialize_interrupt_registers();
  188. initialize_start_state();
  189. for (;;);
  190. return 0;
  191. }
  192.  
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty