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