b49c9dba256a5383cbef56bf2e4d72ebfc2e123a
[fw/altos] / src / drivers / ao_lco_cmd.c
1 /*
2  * Copyright © 2012 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_pad.h>
20 #include <ao_lco_cmd.h>
21 #include <ao_radio_cmac.h>
22
23 static __xdata struct ao_pad_command    command;
24 static __xdata struct ao_pad_query      query;
25 static __pdata uint16_t launch_box;
26 static __pdata uint8_t  launch_channels;
27 static __pdata uint16_t tick_offset;
28
29 static void
30 launch_args(void) __reentrant
31 {
32         ao_cmd_decimal();
33         launch_box = ao_cmd_lex_i;
34         ao_cmd_hex();
35         launch_channels = ao_cmd_lex_i;
36 }
37
38 static int8_t
39 launch_query(void)
40 {
41         uint8_t i;
42         int8_t  r = AO_RADIO_CMAC_OK;
43
44         tick_offset = ao_time();
45         for (i = 0; i < 10; i++) {
46                 printf ("."); flush();
47                 command.tick = ao_time();
48                 command.box = launch_box;
49                 command.cmd = AO_LAUNCH_QUERY;
50                 command.channels = launch_channels;
51                 ao_radio_cmac_send(&command, sizeof (command));
52                 r = ao_radio_cmac_recv(&query, sizeof (query), AO_MS_TO_TICKS(500));
53                 if (r == AO_RADIO_CMAC_OK)
54                         break;
55         }
56         tick_offset -= query.tick;
57         printf("\n"); flush();
58         return r;
59 }
60
61 static void
62 launch_report_cmd(void) __reentrant
63 {
64         int8_t          r;
65         uint8_t         c;
66
67         launch_args();
68         if (ao_cmd_status != ao_cmd_success)
69                 return;
70         r = launch_query();
71         switch (r) {
72         case AO_RADIO_CMAC_OK:
73                 switch (query.arm_status) {
74                 case ao_igniter_ready:
75                 case ao_igniter_active:
76                         printf ("Armed: ");
77                         break;
78                 default:
79                         printf("Disarmed: ");
80                 }
81                 for (c = 0; c < AO_PAD_MAX_CHANNELS; c++) {
82                         if (query.channels & (1 << c)) {
83                                 printf (" pad %d ", c);
84                                 switch (query.igniter_status[c]) {
85                                 default:
86                                         printf("unknown, ");
87                                         break;
88                                 case AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN:
89                                         printf("bad-open, ");
90                                         break;
91                                 case AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN:
92                                         printf("good-igniter, ");
93                                         break;
94                                 case AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED:
95                                         printf("bad-closed, ");
96                                         break;
97                                 }
98                         }
99                 }
100                 printf("Rssi: %d\n", ao_radio_cmac_rssi);
101                 break;
102         default:
103                 printf("Error %d\n", r);
104                 break;
105         }
106 }
107
108 static void
109 launch_arm(void) __reentrant
110 {
111         command.tick = ao_time() - tick_offset;
112         command.box = launch_box;
113         command.cmd = AO_LAUNCH_ARM;
114         command.channels = launch_channels;
115         ao_radio_cmac_send(&command, sizeof (command));
116 }
117
118 static void
119 launch_ignite(void) __reentrant
120 {
121         command.tick = ao_time() - tick_offset;
122         command.box = launch_box;
123         command.cmd = AO_LAUNCH_FIRE;
124         command.channels = 0;
125         ao_radio_cmac_send(&command, sizeof (command));
126 }
127
128 static void
129 launch_fire_cmd(void) __reentrant
130 {
131         static __xdata struct ao_pad_command    command;
132         uint8_t         secs;
133         uint8_t         i;
134         int8_t          r;
135
136         launch_args();
137         ao_cmd_decimal();
138         secs = ao_cmd_lex_i;
139         if (ao_cmd_status != ao_cmd_success)
140                 return;
141         r = launch_query();
142         if (r != AO_RADIO_CMAC_OK) {
143                 printf("query failed %d\n", r);
144                 return;
145         }
146
147         for (i = 0; i < 4; i++) {
148                 printf("arm %d\n", i); flush();
149                 launch_arm();
150         }
151
152         secs = secs * 10 - 5;
153         if (secs > 100)
154                 secs = 100;
155         for (i = 0; i < secs; i++) {
156                 printf("fire %d\n", i); flush();
157                 launch_ignite();
158                 ao_delay(AO_MS_TO_TICKS(100));
159         }
160 }
161
162 static void
163 launch_arm_cmd(void) __reentrant
164 {
165         uint8_t i;
166         int8_t  r;
167         launch_args();
168         r = launch_query();
169         if (r != AO_RADIO_CMAC_OK) {
170                 printf("query failed %d\n", r);
171                 return;
172         }
173         for (i = 0; i < 4; i++)
174                 launch_arm();
175 }
176
177 static void
178 launch_ignite_cmd(void) __reentrant
179 {
180         uint8_t i;
181         launch_args();
182         for (i = 0; i < 4; i++)
183                 launch_ignite();
184 }
185
186 static __code struct ao_cmds ao_lco_cmds[] = {
187         { launch_report_cmd,    "l <box> <channel>\0Get remote launch status" },
188         { launch_fire_cmd,      "F <box> <channel> <secs>\0Fire remote igniter" },
189         { launch_arm_cmd,       "a <box> <channel>\0Arm remote igniter" },
190         { launch_ignite_cmd,    "i <box> <channel>\0Pulse remote igniter" },
191         { 0, NULL },
192 };
193
194 void
195 ao_lco_cmd_init(void)
196 {
197         ao_cmd_register(&ao_lco_cmds[0]);
198 }