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