08a3ae1e24c40755e3bded22182a1c39ca02687d
[fw/altos] / src / teleballoon-v1.1 / 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; 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 #ifndef AO_FLIGHT_TEST
19 #include "ao.h"
20 #endif
21
22 #ifndef HAS_ACCEL
23 #error Please define HAS_ACCEL
24 #endif
25
26 #ifndef HAS_GPS
27 #error Please define HAS_GPS
28 #endif
29
30 #ifndef HAS_USB
31 #error Please define HAS_USB
32 #endif
33
34 /* Main flight thread. */
35
36 __pdata enum ao_flight_state    ao_flight_state;        /* current flight state */
37
38 __pdata uint8_t                 ao_flight_force_idle;
39
40 void
41 ao_flight(void)
42 {
43         ao_sample_init();
44         ao_flight_state = ao_flight_startup;
45         for (;;) {
46
47                 /*
48                  * Process ADC samples, just looping
49                  * until the sensors are calibrated.
50                  */
51                 if (!ao_sample())
52                         continue;
53
54                 switch (ao_flight_state) {
55                 case ao_flight_startup:
56
57                         /* Check to see what mode we should go to.
58                          *  - Invalid mode if accel cal appears to be out
59                          *  - pad mode if we're upright,
60                          *  - idle mode otherwise
61                          */
62 #if HAS_ACCEL
63                         if (ao_config.accel_plus_g == 0 ||
64                             ao_config.accel_minus_g == 0 ||
65                             ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP ||
66                             ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP)
67                         {
68                                 /* Detected an accel value outside -1.5g to 1.5g
69                                  * (or uncalibrated values), so we go into invalid mode
70                                  */
71                                 ao_flight_state = ao_flight_invalid;
72
73                                 /* Turn on packet system in invalid mode on TeleMetrum */
74                                 ao_packet_slave_start();
75                         } else
76 #endif
77                                 if (!ao_flight_force_idle
78 #if HAS_ACCEL
79                                     && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP
80 #endif
81                                         )
82                         {
83                                 /* Set pad mode - we can fly! */
84                                 ao_flight_state = ao_flight_pad;
85 #if HAS_USB
86                                 /* Disable the USB controller in flight mode
87                                  * to save power
88                                  */
89                                 ao_usb_disable();
90 #endif
91
92 #if !HAS_ACCEL
93                                 /* Disable packet mode in pad state on TeleMini */
94                                 ao_packet_slave_stop();
95 #endif
96
97                                 /* Turn on telemetry system */
98                                 ao_rdf_set(1);
99                                 ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_BALLOON);
100
101                                 /* signal successful initialization by turning off the LED */
102                                 ao_led_off(AO_LED_RED);
103                         } else {
104                                 /* Set idle mode */
105                                 ao_flight_state = ao_flight_idle;
106  
107 #if HAS_ACCEL
108                                 /* Turn on packet system in idle mode on TeleMetrum */
109                                 ao_packet_slave_start();
110 #endif
111
112                                 /* signal successful initialization by turning off the LED */
113                                 ao_led_off(AO_LED_RED);
114                         }
115                         /* wakeup threads due to state change */
116                         ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
117
118                         break;
119                 case ao_flight_pad:
120
121                         /* pad to coast:
122                          *
123                          * barometer: > 20m vertical motion
124                          */
125                         if (ao_height > AO_M_TO_HEIGHT(20))
126                         {
127                                 ao_flight_state = ao_flight_drogue;
128
129                                 /* start logging data */
130                                 ao_log_start();
131
132 #if HAS_GPS
133                                 /* Record current GPS position by waking up GPS log tasks */
134                                 ao_wakeup(&ao_gps_data);
135                                 ao_wakeup(&ao_gps_tracking_data);
136 #endif
137
138                                 ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
139                         }
140                         break;
141                 case ao_flight_drogue:
142                         break;
143                         
144                 }
145         }
146 }
147
148 static __xdata struct ao_task   flight_task;
149
150 void
151 ao_flight_init(void)
152 {
153         ao_flight_state = ao_flight_startup;
154         ao_add_task(&flight_task, ao_flight, "flight");
155 }