47b69e25bb747d1b81981194fd29ee2f983034d7
[fw/altos] / src / kernel / ao_balloon.c
1 /*
2  * Copyright © 2009 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 #ifndef AO_FLIGHT_TEST
20 #include "ao.h"
21 #endif
22
23 #ifndef HAS_ACCEL
24 #error Please define HAS_ACCEL
25 #endif
26
27 #ifndef HAS_GPS
28 #error Please define HAS_GPS
29 #endif
30
31 #ifndef HAS_USB
32 #error Please define HAS_USB
33 #endif
34
35 #if HAS_SENSOR_ERRORS
36 /* Any sensor can set this to mark the flight computer as 'broken' */
37 __xdata uint8_t                 ao_sensor_errors;
38 #endif
39
40 __pdata uint16_t                ao_motor_number;        /* number of motors burned so far */
41
42 /* Main flight thread. */
43
44 __pdata enum ao_flight_state    ao_flight_state;        /* current flight state */
45
46 __pdata uint8_t                 ao_flight_force_idle;
47
48 void
49 ao_flight(void)
50 {
51         ao_sample_init();
52         ao_flight_state = ao_flight_startup;
53         for (;;) {
54
55                 /*
56                  * Process ADC samples, just looping
57                  * until the sensors are calibrated.
58                  */
59                 if (!ao_sample())
60                         continue;
61
62                 switch (ao_flight_state) {
63                 case ao_flight_startup:
64
65                         /* Check to see what mode we should go to.
66                          *  - Invalid mode if accel cal appears to be out
67                          *  - pad mode if we're upright,
68                          *  - idle mode otherwise
69                          */
70                         if (!ao_flight_force_idle)
71                         {
72                                 /* Set pad mode - we can fly! */
73                                 ao_flight_state = ao_flight_pad;
74 #if HAS_USB
75                                 /* Disable the USB controller in flight mode
76                                  * to save power
77                                  */
78                                 if (!ao_usb_running)
79                                         ao_usb_disable();
80 #endif
81
82                                 /* Disable packet mode in pad state */
83                                 ao_packet_slave_stop();
84
85                                 /* Turn on telemetry system */
86                                 ao_rdf_set(1);
87                                 ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_BALLOON);
88
89                                 /* signal successful initialization by turning off the LED */
90                                 ao_led_off(AO_LED_RED);
91                         } else {
92                                 /* Set idle mode */
93                                 ao_flight_state = ao_flight_idle;
94  
95                                 /* signal successful initialization by turning off the LED */
96                                 ao_led_off(AO_LED_RED);
97                         }
98                         /* wakeup threads due to state change */
99                         ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
100
101                         break;
102                 case ao_flight_pad:
103
104                         /* pad to coast:
105                          *
106                          * barometer: > 20m vertical motion
107                          */
108                         if (ao_height > AO_M_TO_HEIGHT(20))
109                         {
110                                 ao_flight_state = ao_flight_drogue;
111
112                                 /* start logging data */
113                                 ao_log_start();
114
115 #if HAS_GPS
116                                 /* Record current GPS position by waking up GPS log tasks */
117                                 ao_gps_new = AO_GPS_NEW_DATA | AO_GPS_NEW_TRACKING;
118                                 ao_wakeup(&ao_gps_new);
119 #endif
120
121                                 ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
122                         }
123                         break;
124                 default:
125                         break;
126                 }
127         }
128 }
129
130 static __xdata struct ao_task   flight_task;
131
132 void
133 ao_flight_init(void)
134 {
135         ao_flight_state = ao_flight_startup;
136         ao_add_task(&flight_task, ao_flight, "flight");
137 }