f022923027edfcc17bfe42e44f75ed182cc2b1ee
[fw/altos] / src / kernel / ao_tracker.c
1 /*
2  * Copyright © 2014 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 #include <ao_flight.h>
20 #include <ao_log.h>
21 #include <ao_log_gps.h>
22 #include <ao_distance.h>
23 #include <ao_tracker.h>
24 #include <ao_exti.h>
25
26 static uint8_t          ao_tracker_force_telem;
27
28 #if HAS_USB_CONNECT
29 static inline uint8_t
30 ao_usb_connected(void)
31 {
32         return ao_gpio_get(AO_USB_CONNECT_PORT, AO_USB_CONNECT_PIN, AO_USB_CONNECT) != 0;
33 }
34 #else
35 #define ao_usb_connected()      1
36 #endif
37
38 static int32_t  last_log_latitude, last_log_longitude;
39 static int16_t  last_log_altitude;
40 static uint8_t  unmoving;
41 static uint8_t  log_started;
42 static struct ao_telemetry_location gps_data;
43 static uint8_t  tracker_running;
44 static uint16_t tracker_interval;
45
46 static void
47 ao_tracker(void)
48 {
49         uint8_t new;
50         int32_t ground_distance;
51         int16_t height;
52         uint16_t gps_tick;
53         uint8_t new_tracker_running;
54
55 #if HAS_ADC
56         ao_timer_set_adc_interval(100);
57 #endif
58
59 #if !HAS_USB_CONNECT
60         ao_tracker_force_telem = 1;
61 #endif
62         ao_log_scan();
63         ao_log_start();
64
65         ao_rdf_set(1);
66
67         tracker_interval = ao_config.tracker_interval;
68         ao_gps_set_rate(tracker_interval);
69
70         for (;;) {
71
72                 /** Wait for new GPS data
73                  */
74                 while (!(new = ao_gps_new))
75                         ao_sleep(&ao_gps_new);
76                 ao_mutex_get(&ao_gps_mutex);
77                 gps_data = ao_gps_data;
78                 gps_tick = ao_gps_tick;
79                 ao_gps_new = 0;
80                 ao_mutex_put(&ao_gps_mutex);
81
82                 new_tracker_running = ao_tracker_force_telem || !ao_usb_connected();
83
84                 if (ao_config.tracker_interval != tracker_interval) {
85                         tracker_interval = ao_config.tracker_interval;
86                         ao_gps_set_rate(tracker_interval);
87
88                         /* force telemetry interval to be reset */
89                         tracker_running = 0;
90                 }
91
92                 if (new_tracker_running && !tracker_running) {
93                         ao_telemetry_set_interval(AO_SEC_TO_TICKS(tracker_interval));
94                         ao_log_start();
95                 } else if (!new_tracker_running && tracker_running) {
96                         ao_telemetry_set_interval(0);
97                         ao_log_stop();
98                 }
99
100                 tracker_running = new_tracker_running;
101
102                 if (!tracker_running)
103                         continue;
104
105                 if (new & AO_GPS_NEW_DATA) {
106                         if ((gps_data.flags & (AO_GPS_VALID|AO_GPS_COURSE_VALID)) ==
107                             (AO_GPS_VALID|AO_GPS_COURSE_VALID))
108                         {
109                                 if (log_started) {
110                                         ground_distance = ao_distance(gps_data.latitude, gps_data.longitude,
111                                                                       last_log_latitude, last_log_longitude);
112                                         height = last_log_altitude - gps_data.altitude;
113                                         if (height < 0)
114                                                 height = -height;
115                                         if (ground_distance <= ao_config.tracker_motion &&
116                                             height <= ao_config.tracker_motion)
117                                         {
118                                                 if (unmoving < AO_TRACKER_MOTION_COUNT)
119                                                         unmoving++;
120                                         } else
121                                                 unmoving = 0;
122                                 }
123                         } else {
124                                 if (!log_started)
125                                         continue;
126                                 if (unmoving < AO_TRACKER_MOTION_COUNT)
127                                         unmoving++;
128                         }
129
130                         if (unmoving < AO_TRACKER_MOTION_COUNT) {
131                                 if (!log_started) {
132                                         ao_log_gps_flight();
133                                         log_started = 1;
134                                 }
135                                 ao_log_gps_data(gps_tick, &gps_data);
136                                 last_log_latitude = gps_data.latitude;
137                                 last_log_longitude = gps_data.longitude;
138                                 last_log_altitude = gps_data.altitude;
139                         }
140                 }
141         }
142 }
143
144 static struct ao_task ao_tracker_task;
145
146 static void
147 ao_tracker_set_telem(void)
148 {
149         uint8_t telem;
150         ao_cmd_hex();
151         telem = ao_cmd_lex_i;
152         if (ao_cmd_status == ao_cmd_success)
153                 ao_tracker_force_telem = telem;
154         ao_cmd_status = ao_cmd_success;
155         printf ("flight: %d\n", ao_flight_number);
156         printf ("force_telem: %d\n", ao_tracker_force_telem);
157         printf ("log_started: %d\n", log_started);
158         printf ("unmoving: %d\n", unmoving);
159         printf ("latitude: %ld\n", (long) gps_data.latitude);
160         printf ("longitude: %ld\n", (long) gps_data.longitude);
161         printf ("altitude: %d\n", gps_data.altitude);
162         printf ("log_running: %d\n", ao_log_running);
163         printf ("log_start_pos: %ld\n", (long) ao_log_start_pos);
164         printf ("log_cur_pos: %ld\n", (long) ao_log_current_pos);
165         printf ("log_end_pos: %ld\n", (long) ao_log_end_pos);
166 }
167
168 static const struct ao_cmds ao_tracker_cmds[] = {
169         { ao_tracker_set_telem, "t <d>\0Set telem on USB" },
170         { 0, NULL },
171 };
172
173 void
174 ao_tracker_init(void)
175 {
176 #if HAS_USB_CONNECT
177         ao_enable_input(AO_USB_CONNECT_PORT, AO_USB_CONNECT_PIN, 0);
178 #endif
179         ao_cmd_register(&ao_tracker_cmds[0]);
180         ao_add_task(&ao_tracker_task, ao_tracker, "tracker");
181 }