altos: Debugging TBT issues -- check pin configuration after boot
[fw/altos] / src / ao_log_tiny.c
1 /*
2  * Copyright © 2011 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 #include "ao.h"
19
20 static __data uint16_t  ao_log_tiny_interval;
21
22 #define AO_LOG_TINY_INTERVAL_DEFAULT    AO_MS_TO_TICKS(1000)
23 #if USE_FAST_ASCENT_LOG
24 #define AO_LOG_TINY_INTERVAL_ASCENT     AO_MS_TO_TICKS(100)
25 #define AO_PAD_RING     8
26 #else
27 #define AO_LOG_TINY_INTERVAL_ASCENT     AO_LOG_TINY_INTERVAL_DEFAULT
28 #define AO_PAD_RING     2
29 #endif
30
31 void
32 ao_log_tiny_set_interval(uint16_t ticks)
33 {
34         ao_log_tiny_interval = ticks;
35 }
36
37
38 static void ao_log_tiny_data(uint16_t d)
39 {
40         if (ao_log_current_pos >= ao_log_end_pos && ao_log_running)
41                 ao_log_stop();
42         if (ao_log_running) {
43                 ao_storage_write(ao_log_current_pos, DATA_TO_XDATA(&d), 2);
44                 ao_log_current_pos += 2;
45         }
46 }
47
48 static __xdata uint16_t ao_log_pad_ring[AO_PAD_RING];
49 static __pdata uint8_t ao_log_pad_ring_pos;
50
51 #define ao_pad_ring_next(n)     (((n) + 1) & (AO_PAD_RING - 1))
52
53 static void ao_log_tiny_queue(uint16_t d)
54 {
55         ao_log_pad_ring[ao_log_pad_ring_pos] = d;
56         ao_log_pad_ring_pos = ao_pad_ring_next(ao_log_pad_ring_pos);
57 }
58
59 static void ao_log_tiny_start(void)
60 {
61         uint8_t         p;
62         uint16_t        d;
63
64         ao_log_tiny_data(ao_flight_number);
65         ao_log_tiny_data(ao_ground_pres);
66         p = ao_log_pad_ring_pos;
67         do {
68                 d = ao_log_pad_ring[p];
69                 /*
70                  * ignore unwritten slots
71                  */
72                 if (d)
73                         ao_log_tiny_data(d);
74                 p = ao_pad_ring_next(p);
75         } while (p != ao_log_pad_ring_pos);
76 }
77
78 void
79 ao_log(void)
80 {
81         uint16_t                last_time;
82         uint16_t                now;
83         enum ao_flight_state    ao_log_tiny_state;
84         int32_t                 sum;
85         int16_t                 count;
86         uint8_t                 ao_log_adc;
87         uint8_t                 ao_log_started = 0;
88
89         ao_storage_setup();
90
91         ao_log_scan();
92
93         ao_log_tiny_state = ao_flight_invalid;
94         ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT;
95         sum = 0;
96         count = 0;
97         ao_log_adc = ao_sample_adc;
98         last_time = ao_time();
99         for (;;) {
100
101                 /*
102                  * Add in pending sample data
103                  */
104                 ao_sleep(DATA_TO_XDATA(&ao_sample_adc));
105                 while (ao_log_adc != ao_sample_adc) {
106                         sum += ao_adc_ring[ao_log_adc].pres;
107                         count++;
108                         ao_log_adc = ao_adc_ring_next(ao_log_adc);
109                 }
110                 if (ao_log_running) {
111                         if (!ao_log_started) {
112                                 ao_log_tiny_start();
113                                 ao_log_started = 1;
114                         }
115                         if (ao_flight_state != ao_log_tiny_state) {
116                                 ao_log_tiny_data(ao_flight_state | 0x8000);
117                                 ao_log_tiny_state = ao_flight_state;
118                                 ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_DEFAULT;
119 #if AO_LOG_TINY_INTERVAL_ASCENT != AO_LOG_TINY_INTERVAL_DEFAULT
120                                 if (ao_log_tiny_state <= ao_flight_coast)
121                                         ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT;
122 #endif
123                                 if (ao_log_tiny_state == ao_flight_landed)
124                                         ao_log_stop();
125                         }
126                 }
127
128                 /* Stop logging when told to */
129                 if (!ao_log_running && ao_log_started)
130                         ao_exit();
131
132                 /*
133                  * Write out the sample when finished
134                  */
135                 now = ao_time();
136                 if ((int16_t) (now - (last_time + ao_log_tiny_interval)) >= 0 && count) {
137                         count = sum / count;
138                         if (ao_log_started)
139                                 ao_log_tiny_data(count);
140                         else
141                                 ao_log_tiny_queue(count);
142                         sum = 0;
143                         count = 0;
144                         last_time = now;
145                 }
146         }
147 }
148
149 uint16_t
150 ao_log_flight(uint8_t slot)
151 {
152         static __xdata uint16_t flight;
153
154         (void) slot;
155         ao_storage_read(0, &flight, 2);
156         if (flight == 0xffff)
157                 flight = 0;
158         return flight;
159 }