]> www.fi.muni.cz Git - openparking.git/blob - firmware/firmware.c
Preliminary modbus rtu implementation.
[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 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         modbus_init();
108
109         // output pins
110         DDRD |= _BV(PD7); // Trig D
111         DDRB |= _BV(PB4) | _BV(PB5); // Trig B, LED 2
112         DDRC |= _BV(PC4) | _BV(PC5); // Trig C, LED 1
113         // temporary LED
114         DDRD |= _BV(PD4);
115
116         // set up the timer
117         TCCR1A = 0;
118         TCCR1B = _BV(CS12)|_BV(CS10); // CLK/1024
119
120         // enable interrupts
121         sei();
122
123         while(1) {
124                 // do_measurements();
125                 modbus_poll();
126                 led_set(0,
127                         distances[4] > 100 || distances[11] > 100);
128         }
129 }
130