strat db + avoid
[aversive.git] / projects / microb2010 / mainboard / sensor.c
1 /*
2  *  Copyright Droids Corporation (2009)
3  *  Olivier MATZ <zer0@droids-corp.org>
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  *  Revision : $Id: sensor.c,v 1.8 2009-11-08 17:24:33 zer0 Exp $
20  *
21  */
22
23 #include <stdlib.h>
24
25 #include <aversive.h>
26 #include <aversive/error.h>
27
28 #include <adc.h>
29 #include <scheduler.h>
30 #include <ax12.h>
31 #include <pwm_ng.h>
32
33 #include <pid.h>
34 #include <quadramp.h>
35 #include <control_system_manager.h>
36 #include <trajectory_manager.h>
37 #include <vect_base.h>
38 #include <lines.h>
39 #include <polygon.h>
40 #include <obstacle_avoidance.h>
41 #include <blocking_detection_manager.h>
42 #include <robot_system.h>
43 #include <position_manager.h>
44
45 #include <parse.h>
46 #include <rdline.h>
47
48 #include "main.h"
49 #include "sensor.h"
50
51 #ifndef HOST_VERSION
52
53 /************ ADC */
54
55 struct adc_infos {
56         uint16_t config;
57         int16_t value;
58         int16_t prev_val;
59         int16_t (*filter)(struct adc_infos *, int16_t);
60 };
61
62 /* reach 90% of the value in 4 samples */
63 int16_t rii_light(struct adc_infos *adc, int16_t val)
64 {
65         adc->prev_val = val + (int32_t)adc->prev_val / 2;
66         return adc->prev_val / 2;
67 }
68
69 /* reach 90% of the value in 8 samples */
70 int16_t rii_medium(struct adc_infos *adc, int16_t val)
71 {
72         adc->prev_val = val + ((int32_t)adc->prev_val * 3) / 4;
73         return adc->prev_val / 4;
74 }
75
76 /* reach 90% of the value in 16 samples */
77 int16_t rii_strong(struct adc_infos *adc, int16_t val)
78 {
79         adc->prev_val = val + ((int32_t)adc->prev_val * 7) / 8;
80         return adc->prev_val / 8;
81 }
82
83
84 #define ADC_CONF(x) ( ADC_REF_AVCC | ADC_MODE_INT | MUX_ADC##x )
85
86 /* define which ADC to poll, see in sensor.h */
87 static struct adc_infos adc_infos[ADC_MAX] = {
88         [ADC_CSENSE1] = { .config = ADC_CONF(0), .filter = rii_medium },
89         [ADC_CSENSE2] = { .config = ADC_CONF(1), .filter = rii_medium },
90         [ADC_CSENSE3] = { .config = ADC_CONF(2), .filter = rii_medium },
91         [ADC_CSENSE4] = { .config = ADC_CONF(3), .filter = rii_medium },
92         [ADC_BATTERY1] = { .config = ADC_CONF(8), .filter = rii_strong },
93         [ADC_BATTERY2] = { .config = ADC_CONF(9), .filter = rii_strong },
94
95         /* add adc on "cap" pins if needed */
96 /*      [ADC_CAP1] = { .config = ADC_CONF(10) }, */
97 /*      [ADC_CAP2] = { .config = ADC_CONF(11) }, */
98 /*      [ADC_CAP3] = { .config = ADC_CONF(12) }, */
99 /*      [ADC_CAP4] = { .config = ADC_CONF(13) }, */
100 };
101
102 static void adc_event(int16_t result);
103
104 /* called every 10 ms, see init below */
105 static void do_adc(void *dummy)
106 {
107         /* launch first conversion */
108         adc_launch(adc_infos[0].config);
109 }
110
111 static void adc_event(int16_t result)
112 {
113         static uint8_t i = 0;
114
115         /* filter value if needed */
116         if (adc_infos[i].filter)
117                 adc_infos[i].value = adc_infos[i].filter(&adc_infos[i],
118                                                          result);
119         else
120                 adc_infos[i].value = result;
121
122         i ++;
123         if (i >= ADC_MAX)
124                 i = 0;
125         else
126                 adc_launch(adc_infos[i].config);
127 }
128 #endif /* !HOST_VERSION */
129
130 int16_t sensor_get_adc(uint8_t i)
131 {
132 #ifdef HOST_VERSION
133         return 0;
134 #else
135         int16_t tmp;
136         uint8_t flags;
137
138         IRQ_LOCK(flags);
139         tmp = adc_infos[i].value;
140         IRQ_UNLOCK(flags);
141         return tmp;
142 #endif
143 }
144
145 /************ boolean sensors */
146
147 #ifndef HOST_VERSION
148 struct sensor_filter {
149         uint8_t filter;
150         uint8_t prev;
151         uint8_t thres_off;
152         uint8_t thres_on;
153         uint8_t cpt;
154         uint8_t invert;
155 };
156
157 /* pullup mapping:
158  * CAP 1,5,6,7,8
159  */
160 static struct sensor_filter sensor_filter[SENSOR_MAX] = {
161         [S_CAP1] = { 1, 0, 0, 1, 0, 0 }, /* 0 */
162         [S_CAP2] = { 1, 0, 0, 1, 0, 0 }, /* 1 */
163         [S_LFRONT] = { 1, 0, 0, 1, 0, 1 },    /* 2 */
164         [S_RFRONT] = { 1, 0, 0, 1, 0, 1 },    /* 3 */
165         [S_START_SWITCH] = { 10, 0, 3, 7, 0, 0 },  /* 4 */
166         [S_DISP_LEFT] = { 1, 0, 0, 1, 0, 1 },  /* 5 */
167         [S_RCOB_WHITE] = { 1, 0, 0, 1, 0, 0 }, /* 6 */
168         [S_LCOB_WHITE] = { 1, 0, 0, 1, 0, 0 }, /* 7 */
169         [S_RESERVED1] = { 10, 0, 3, 7, 0, 0 }, /* 8 */
170         [S_RESERVED2] = { 10, 0, 3, 7, 0, 0 }, /* 9 */
171         [S_RESERVED3] = { 1, 0, 0, 1, 0, 0 }, /* 10 */
172         [S_RESERVED4] = { 1, 0, 0, 1, 0, 0 }, /* 11 */
173         [S_RESERVED5] = { 1, 0, 0, 1, 0, 0 }, /* 12 */
174         [S_RESERVED6] = { 1, 0, 0, 1, 0, 0 }, /* 13 */
175         [S_RESERVED7] = { 1, 0, 0, 1, 0, 0 }, /* 14 */
176         [S_RESERVED8] = { 1, 0, 0, 1, 0, 0 }, /* 15 */
177 };
178 #endif /* !HOST_VERSION */
179
180 /* value of filtered sensors */
181 static uint16_t sensor_filtered = 0;
182
183 /* sensor mapping :
184  * 0-3:  PORTK 2->5 (cap1 -> cap4) (adc10 -> adc13)
185  * 4-5:  PORTL 0->1 (cap5 -> cap6)
186  * 6-7:  PORTE 3->4 (cap7 -> cap8)
187  * 8-15: reserved
188  */
189
190 uint16_t sensor_get_all(void)
191 {
192         uint16_t tmp;
193         uint8_t flags;
194         IRQ_LOCK(flags);
195         tmp = sensor_filtered;
196         IRQ_UNLOCK(flags);
197         return tmp;
198 }
199
200 uint8_t sensor_get(uint8_t i)
201 {
202 #ifdef HOST_VERSION
203         return 0;
204 #else
205         uint16_t tmp = sensor_get_all();
206         return (tmp & _BV(i));
207 #endif
208 }
209
210 #ifndef HOST_VERSION
211 /* get the physical value of pins */
212 static uint16_t sensor_read(void)
213 {
214         uint16_t tmp = 0;
215         tmp |= (uint16_t)((PINK & (_BV(2)|_BV(3)|_BV(4)|_BV(5))) >> 2) << 0;
216         tmp |= (uint16_t)((PINL & (_BV(0)|_BV(1))) >> 0) << 4;
217         tmp |= (uint16_t)((PINE & (_BV(3)|_BV(4))) >> 3) << 6;
218         /* add reserved sensors here */
219         return tmp;
220 }
221
222 /* called every 10 ms, see init below */
223 static void do_boolean_sensors(void *dummy)
224 {
225         uint8_t i;
226         uint8_t flags;
227         uint16_t sensor = sensor_read();
228         uint16_t tmp = 0;
229
230         for (i=0; i<SENSOR_MAX; i++) {
231                 if ((1 << i) & sensor) {
232                         if (sensor_filter[i].cpt < sensor_filter[i].filter)
233                                 sensor_filter[i].cpt++;
234                         if (sensor_filter[i].cpt >= sensor_filter[i].thres_on)
235                                 sensor_filter[i].prev = 1;
236                 }
237                 else {
238                         if (sensor_filter[i].cpt > 0)
239                                 sensor_filter[i].cpt--;
240                         if (sensor_filter[i].cpt <= sensor_filter[i].thres_off)
241                                 sensor_filter[i].prev = 0;
242                 }
243
244                 if (sensor_filter[i].prev) {
245                         tmp |= (1UL << i);
246                 }
247         }
248         IRQ_LOCK(flags);
249         sensor_filtered = tmp;
250         IRQ_UNLOCK(flags);
251 }
252 #endif /* !HOST_VERSION */
253
254 /* virtual obstacle */
255
256 #define DISABLE_CPT_MAX 200
257 static uint8_t disable = 0; /* used to disable obstacle detection
258                            * during some time */
259
260 /* called every 10 ms */
261 void
262 sensor_obstacle_update(void)
263 {
264         if (disable > 0) {
265                 disable --;
266                 if (disable == 0)
267                         DEBUG(E_USER_STRAT, "re-enable sensor");
268         }
269 }
270
271 void sensor_obstacle_disable(void)
272 {
273         DEBUG(E_USER_STRAT, "disable sensor");
274         disable = DISABLE_CPT_MAX;
275 }
276
277 void sensor_obstacle_enable(void)
278 {
279         disable = 0;
280 }
281
282 uint8_t sensor_obstacle_is_disabled(void)
283 {
284         return disable;
285 }
286
287
288 /************ global sensor init */
289
290 #ifndef HOST_VERSION
291 /* called every 10 ms, see init below */
292 static void do_sensors(void *dummy)
293 {
294         do_adc(NULL);
295         do_boolean_sensors(NULL);
296         sensor_obstacle_update();
297 }
298 #endif
299
300 void sensor_init(void)
301 {
302 #ifdef HOST_VERSION
303         return;
304 #else
305         adc_init();
306         adc_register_event(adc_event);
307         /* CS EVENT */
308         scheduler_add_periodical_event_priority(do_sensors, NULL,
309                                                 10000L / SCHEDULER_UNIT,
310                                                 ADC_PRIO);
311 #endif
312 }
313