altos/test: Adjust CRC error rate after FEC fix
[fw/altos] / src / kernel / ao_microflight.c
1 /*
2  * Copyright © 2013 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18
19 #ifndef AO_FLIGHT_TEST
20 #include <ao.h>
21 #endif
22 #include <ao_micropeak.h>
23 #include <ao_log_micro.h>
24
25 uint32_t        pa;
26 uint32_t        pa_ground;
27 uint32_t        pa_ground_next;
28 uint32_t        pa_min;
29
30 static void
31 ao_microsample(void)
32 {
33         ao_pa_get();
34         ao_microkalman_predict();
35         ao_microkalman_correct();
36 }
37
38 #define NUM_PA_HIST     (GROUND_AVG)
39
40 #define SKIP_PA_HIST(i,j)       (((i) + (j)) & (NUM_PA_HIST - 1))
41
42 static uint32_t pa_hist[NUM_PA_HIST];
43
44 void
45 ao_microflight(void)
46 {
47         int16_t         sample_count;
48         int16_t         log_count;
49         AO_TICK_TYPE    time;
50         uint32_t        pa_interval_min, pa_interval_max;
51         int32_t         pa_diff;
52         uint8_t         h;
53         uint8_t         i;
54         uint8_t         accel_lock = 0;
55         uint32_t        pa_sum = 0;
56
57         /* Wait for motion, averaging values to get ground pressure */
58
59         time = ao_time();
60         ao_pa_get();
61         ao_microkalman_init();
62         pa_ground_next = pa_ground = pa;
63         sample_count = 0;
64         h = 0;
65         for (;;) {
66                 time += SAMPLE_SLEEP;
67 #if BOOST_DETECT
68                 if ((sample_count & 0x1f) == 0)
69                         ao_led_on(AO_LED_REPORT);
70 #endif
71                 ao_delay_until(time);
72                 ao_microsample();
73 #if BOOST_DETECT
74                 if ((sample_count & 0x1f) == 0)
75                         ao_led_off(AO_LED_REPORT);
76 #endif
77                 pa_hist[h] = pa;
78                 h = SKIP_PA_HIST(h,1);
79                 pa_diff = (int32_t) (pa_ground - ao_pa);
80
81 #if BOOST_DETECT
82                 /* Check for a significant pressure change */
83                 if (pa_diff > BOOST_DETECT)
84                         break;
85 #endif
86
87                 if (sample_count < GROUND_AVG * 2) {
88                         if (sample_count < GROUND_AVG)
89                                 pa_sum += pa;
90                         ++sample_count;
91                 } else {
92                         pa_ground = pa_ground_next;
93                         pa_ground_next = pa_sum >> GROUND_AVG_SHIFT;
94                         pa_sum = 0;
95                         sample_count = 0;
96 #if !BOOST_DETECT
97                         break;
98 #endif
99                 }
100         }
101
102         /* Go back and find the last sample close to the ground */
103         pa_min = pa_ground - LAND_DETECT;
104         for (i = SKIP_PA_HIST(h,-2); i != SKIP_PA_HIST(h,2); i = SKIP_PA_HIST(i,-2)) {
105                 if (pa_hist[i] >= pa_min)
106                         break;
107         }
108
109         /* Log the remaining samples so we get a complete history since leaving the ground */
110 #if LOG_INTERVAL < NUM_PA_HIST
111         for (; i != h; i = SKIP_PA_HIST(i,2))
112 #endif
113         {
114                 pa = pa_hist[i];
115                 ao_log_micro_data();
116         }
117
118         /* Now sit around until the pressure is stable again and record the max */
119
120         sample_count = 0;
121         log_count = 0;
122         pa_min = ao_pa;
123         pa_interval_min = ao_pa;
124         pa_interval_max = ao_pa;
125         for (;;) {
126                 time += SAMPLE_SLEEP;
127                 ao_delay_until(time);
128                 if ((sample_count & 3) == 0)
129                         ao_led_on(AO_LED_REPORT);
130                 ao_microsample();
131                 if ((sample_count & 3) == 0)
132                         ao_led_off(AO_LED_REPORT);
133                 if (log_count == LOG_INTERVAL - 1) {
134                         ao_log_micro_data();
135                         log_count = 0;
136                 } else
137                         log_count++;
138
139                 /* If accelerating upwards, don't look for min pressure */
140                 if (ao_pa_accel < ACCEL_LOCK_PA)
141                         accel_lock = ACCEL_LOCK_TIME;
142                 else if (accel_lock)
143                         --accel_lock;
144                 else if (ao_pa < pa_min)
145                         pa_min = ao_pa;
146
147                 if (sample_count == (GROUND_AVG - 1)) {
148                         pa_diff = (int32_t) (pa_interval_max - pa_interval_min);
149
150                         /* Check to see if the pressure is now stable */
151                         if (pa_diff < LAND_DETECT)
152                                 break;
153                         sample_count = 0;
154                         pa_interval_min = ao_pa;
155                         pa_interval_max = ao_pa;
156                 } else {
157                         if (ao_pa < pa_interval_min)
158                                 pa_interval_min = ao_pa;
159                         if (ao_pa > pa_interval_max)
160                                 pa_interval_max = ao_pa;
161                         ++sample_count;
162                 }
163         }
164 }