Add igniters and update flight control algorithm
[fw/altos] / ao_ignite.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 #include "ao.h"
19
20 #define AO_IGNITER_DROGUE       P2_3
21 #define AO_IGNITER_MAIN         P2_4
22
23 /* XXX test these values with real igniters */
24 #define AO_IGNITER_OPEN         100
25 #define AO_IGNITER_CLOSED       20000
26 #define AO_IGNITER_FIRE_TIME    AO_MS_TO_TICKS(50)
27 #define AO_IGNITER_CHARGE_TIME  AO_MS_TO_TICKS(200)
28
29 struct ao_ignition {
30         uint8_t request;
31         uint8_t fired;
32         uint8_t firing;
33 };
34
35 __xdata struct ao_ignition ao_ignition[2];
36
37 void
38 ao_ignite(enum ao_igniter igniter) __critical
39 {
40         ao_ignition[igniter].request = 1;
41         ao_wakeup(&ao_ignition[0]);
42 }
43
44 enum ao_igniter_status
45 ao_igniter_status(enum ao_igniter igniter)
46 {
47         __xdata struct ao_adc adc;
48         __xdata int16_t value;
49         __xdata uint8_t request, firing, fired;
50
51         __critical {
52                 ao_adc_sleep();
53                 ao_adc_get(&adc);
54                 request = ao_ignition[igniter].request;
55                 fired = ao_ignition[igniter].fired;
56                 firing = ao_ignition[igniter].firing;
57         }
58         if (firing || (request && !fired))
59                 return ao_igniter_active;
60
61         value = (AO_IGNITER_CLOSED>>1);
62         switch (igniter) {
63         case ao_igniter_drogue:
64                 value = adc.sense_d;
65                 break;
66         case ao_igniter_main:
67                 value = adc.sense_m;
68                 break;
69         }
70         if (value < AO_IGNITER_OPEN)
71                 return ao_igniter_open;
72         else if (value > AO_IGNITER_CLOSED)
73                 return ao_igniter_ready;
74         else
75                 return ao_igniter_unknown;
76 }
77
78 void
79 ao_igniter_fire(enum ao_igniter igniter) __critical
80 {
81         ao_ignition[igniter].firing = 1;
82         switch (igniter) {
83         case ao_igniter_drogue:
84                 AO_IGNITER_DROGUE = 1;
85                 ao_delay(AO_IGNITER_FIRE_TIME);
86                 AO_IGNITER_DROGUE = 0;
87                 break;
88         case ao_igniter_main:
89                 AO_IGNITER_MAIN = 1;
90                 ao_delay(AO_IGNITER_FIRE_TIME);
91                 AO_IGNITER_MAIN = 0;
92                 break;
93         }
94         ao_ignition[igniter].firing = 0;
95 }
96
97 void
98 ao_igniter(void)
99 {
100         __xdata enum ao_ignter igniter;
101         __xdata enum ao_igniter_status status;
102
103         for (;;) {
104                 ao_sleep(&ao_ignition);
105                 for (igniter = ao_igniter_drogue; igniter <= ao_igniter_main; igniter++) {
106                         if (ao_ignition[igniter].request && !ao_ignition[igniter].fired) {
107                                 ao_igniter_fire(igniter);
108                                 ao_delay(AO_IGNITER_CHARGE_TIME);
109                                 status = ao_igniter_status(igniter);
110                                 if (status == ao_igniter_open)
111                                         ao_ignition[igniter].fired = 1;
112                         }
113                 }
114         }
115 }
116
117 __xdata struct ao_task ao_igniter_task;
118
119 void
120 ao_igniter_init(void)
121 {
122         ao_add_task(&ao_igniter_task, ao_igniter, "igniter");
123 }