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