]> www.fi.muni.cz Git - openparking.git/blob - firmware/firmware.c
LEDs moved to the final destination.
[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 "modbus.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 // hold_regs[0] is unit ID
16 #define thresholds      (hold_regs+1)
17 #define led1_sensors    (hold_regs[13])
18 #define led2_sensors    (hold_regs[14])
19
20 #define led_bitmap      (hold_regs[MB_N_HOLD_REGS_EEPROM])
21 #define distances       (hold_regs+MB_N_HOLD_REGS_EEPROM+1)
22 #define free_bitmap     (hold_regs[MB_N_HOLD_REGS_EEPROM+13])
23 #define err_bitmap      (hold_regs[MB_N_HOLD_REGS_EEPROM+14])
24
25 static void pull_trigger(uint8_t trig)
26 {
27         switch (trig) {
28         case 0: PORTD |= _BV(PD7); _delay_us(10); PORTD &= ~_BV(PD7); break;
29         case 1: PORTB |= _BV(PB4); _delay_us(10); PORTB &= ~_BV(PB4); break;
30         case 2: PORTC |= _BV(PC4); _delay_us(10); PORTC &= ~_BV(PC4); break;
31         }
32 }
33
34 static uint16_t get_pin(uint8_t trig)
35 {
36         switch (trig) {
37         case 0: return (PIND & 0x78) >> 3;
38         case 1: return PINB & 0x0F;
39         default: return PINC & 0x0F;
40         }
41 }
42
43 static void do_measurement(unsigned char trig)
44 {
45         uint16_t starttimes[N_TRIG_SENSORS], starttime;
46         uint8_t to_start = (1 << N_TRIG_SENSORS) - 1;
47         uint8_t to_measure = 0, i;
48
49         pull_trigger(trig);
50
51         starttime = TCNT1;
52
53         while (to_start || to_measure) {
54                 uint8_t bits = 0;
55                 uint16_t now = TCNT1;
56
57                 if (now-starttime >= TIMEOUT)
58                         break;
59
60                 bits = get_pin(trig);
61
62                 for (i = 0; i < N_TRIG_SENSORS; i++) {
63                         uint8_t mask = 1 << i;
64
65                         if ((to_start & mask) && (bits & mask)) {
66                                 // echo start
67                                 starttimes[i] = now;
68                                 to_start &= ~mask;
69                                 to_measure |= mask;
70                         } else if ((to_measure & mask) && !(bits & mask)) {
71                                 // echo end
72                                 to_measure &= ~mask;
73                                 distances[trig*N_TRIG_SENSORS + i]
74                                         = now - starttimes[i];
75                         }
76                 }
77         }
78
79         for (i = 0; i < N_TRIG_SENSORS; i++)
80                 if (to_start & (1 << i))
81                         distances[trig*N_TRIG_SENSORS + i] = -1;
82                 else if (to_measure & (1 << i))
83                         distances[trig*N_TRIG_SENSORS + i] = 0;
84 }
85
86 static void do_measurements()
87 {
88         uint8_t trig;
89
90         for (trig = 0; trig < N_TRIGGERS; trig++) {
91                 do_measurement(trig);
92                 _delay_ms(200);
93         }
94 }
95
96 static void led_set(uint8_t led, uint8_t state)
97 {
98         if (led == 0) {
99                 if (state) {
100                         PORTC |= _BV(PC5);
101                         led_bitmap |= 1;
102                 } else {
103                         PORTC &= ~_BV(PC5);
104                         led_bitmap &= ~1;
105                 }
106         } else {
107                 if (state) {
108                         PORTB |= _BV(PB5);
109                         led_bitmap |= 2;
110                 } else {
111                         PORTB &= ~_BV(PB5);
112                         led_bitmap &= ~2;
113                 }
114         }
115 }
116
117 static void eval_bitmaps()
118 {
119         uint16_t free_b = 0, err_b = 0, mask;
120         uint8_t i;
121
122         for (i = 0; i < N_SENSORS; i++) {
123                 mask = 1 << i;
124
125                 if (thresholds[i]) {
126                         if (distances[i] == -1 || distances[i] == 0) {
127                                 err_b |= mask;
128                         } else if (distances[i] > thresholds[i]) {
129                                 free_b |= mask;
130                         }
131                 }
132         }
133
134         free_bitmap = free_b;
135         err_bitmap  = err_b;
136
137         if (led1_sensors) {
138                 if (led1_sensors & free_bitmap) {
139                         led_set(0, 1);
140                 } else {
141                         led_set(0, 0);
142                 }
143         }
144
145         if (led2_sensors) {
146                 if (led2_sensors & free_bitmap) {
147                         led_set(1, 1);
148                 } else {
149                         led_set(1, 0);
150                 }
151         }
152 }
153
154 uint8_t hold_reg_is_valid(uint16_t reg, uint16_t val)
155 {
156         if (reg == MB_HOLD_REGS_BASE) 
157                 return val > 0 && val <= 247;
158
159         return 1;
160 }
161
162 int main()
163 {
164         modbus_init(0);
165
166         // output pins
167         DDRD |= _BV(PD7); // Trig D
168         DDRB |= _BV(PB4) | _BV(PB5); // Trig B, LED 2
169         DDRC |= _BV(PC4) | _BV(PC5); // Trig C, LED 1
170
171         // set up the timer
172         TCCR1A = 0;
173         TCCR1B = _BV(CS12)|_BV(CS10); // CLK/1024
174
175         // enable interrupts
176         sei();
177
178         while(1) {
179                 uint8_t trig;
180                 for (trig = 0; trig < N_TRIGGERS; trig++) {
181                         uint16_t now;
182                         do_measurement(trig);
183                         now = TCNT1;
184                         while (TCNT1-now < 200)
185                                 modbus_poll();
186                 }
187
188                 eval_bitmaps();
189 //              led_set(0,
190 //                      distances[4] > 100 || distances[11] > 100);
191         }
192 }
193