]> www.fi.muni.cz Git - openparking.git/blob - firmware/firmware.c
Directory layout
[openparking.git] / firmware / firmware.c
1 #include <avr/io.h>
2 #include <avr/interrupt.h>
3 #include <util/delay.h>
4 #include <stdio.h>
5 #include "rs485.h"
6
7 #define TIMEOUT 0x2FF
8
9 #define N_TRIGGERS 3
10 #define N_SENSORS 12
11 #define N_TRIG_SENSORS 4
12
13 static int16_t distances[N_SENSORS];
14
15 static void pull_trigger(uint8_t trig)
16 {
17         switch (trig) {
18         case 0: PORTD |= _BV(PD7); _delay_us(10); PORTD &= ~_BV(PD7); break;
19         case 1: PORTB |= _BV(PB4); _delay_us(10); PORTB &= ~_BV(PB4); break;
20         case 2: PORTC |= _BV(PC4); _delay_us(10); PORTC &= ~_BV(PC4); break;
21         }
22 }
23
24 static uint16_t get_pin(uint8_t trig)
25 {
26         switch (trig) {
27         case 0: return (PIND & 0x78) >> 3;
28         case 1: return PINB & 0x0F;
29         default: return PINC & 0x0F;
30         }
31 }
32
33 static void do_measurement(unsigned char trig)
34 {
35         uint16_t starttimes[N_TRIG_SENSORS], starttime;
36         uint8_t to_start = (1 << N_TRIG_SENSORS) - 1;
37         uint8_t to_measure = 0, i;
38
39         pull_trigger(trig);
40
41         starttime = TCNT1;
42
43         while (to_start || to_measure) {
44                 uint8_t bits = 0;
45                 uint16_t now = TCNT1;
46
47                 if (now-starttime >= TIMEOUT)
48                         break;
49
50                 bits = get_pin(trig);
51
52                 for (i = 0; i < N_TRIG_SENSORS; i++) {
53                         uint8_t mask = 1 << i;
54
55                         if ((to_start & mask) && (bits & mask)) {
56                                 // echo start
57                                 starttimes[i] = now;
58                                 to_start &= ~mask;
59                                 to_measure |= mask;
60                         } else if ((to_measure & mask) && !(bits & mask)) {
61                                 // echo end
62                                 to_measure &= ~mask;
63                                 distances[trig*N_TRIG_SENSORS + i]
64                                         = now - starttimes[i];
65                         }
66                 }
67         }
68
69         for (i = 0; i < N_TRIG_SENSORS; i++)
70                 if (to_start & (1 << i))
71                         distances[trig*N_TRIG_SENSORS + i] = -1;
72                 else if (to_measure & (1 << i))
73                         distances[trig*N_TRIG_SENSORS + i] = 0;
74 }
75
76 static void do_measurements()
77 {
78         uint8_t trig;
79
80         for (trig = 0; trig < N_TRIGGERS; trig++) {
81                 do_measurement(trig);
82                 _delay_ms(200);
83         }
84 }
85
86 static void led_set(uint8_t led, uint8_t state)
87 {
88         if (led == 0) {
89                 if (state) {
90                         PORTD |= _BV(PD4);
91                         // PORTC |= _BV(PC5);
92                 } else {
93                         PORTD &= ~_BV(PD4);
94                         // PORTC &= ~_BV(PC5);
95                 }
96         } else {
97                 if (state) {
98                         PORTB |= _BV(PB5);
99                 } else {
100                         PORTB &= ~_BV(PB5);
101                 }
102         }
103 }
104
105 int main()
106 {
107         char obuf[120];
108
109         rs485_init();
110
111         // output pins
112         DDRD |= _BV(PD7); // Trig D
113         DDRB |= _BV(PB4) | _BV(PB5); // Trig B, LED 2
114         DDRC |= _BV(PC4) | _BV(PC5); // Trig C, LED 1
115         // temporary LED
116         DDRD |= _BV(PD4);
117
118         // set up the timer
119         TCCR1A = 0;
120         TCCR1B = _BV(CS12)|_BV(CS10); // CLK/1024
121
122         // enable interrupts
123         sei();
124
125         while(1) {
126                 do_measurements();
127
128                 sprintf(obuf, "%3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d\r\n",
129                         distances[0], distances[1], distances[2],
130                         distances[3], distances[4], distances[5],
131                         distances[6], distances[7], distances[8],
132                         distances[9], distances[10], distances[11]);
133
134                 rs485_send(obuf);
135                 led_set(0,
136                         distances[4] > 100 || distances[11] > 100);
137         }
138 }
139