2 * Copyright © 2011 Keith Packard <keithp@keithp.com>
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.
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.
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.
27 static const struct option options[] = {
28 { .name = "tty", .has_arg = 1, .val = 'T' },
29 { .name = "device", .has_arg = 1, .val = 'D' },
30 { .name = "frequency", .has_arg = 1, .val = 'F' },
31 { .name = "realtime", .has_arg = 0, .val = 'R' },
35 static void usage(char *program)
37 fprintf(stderr, "usage: %s [--tty <tty-name>] [--device <device-name>] [--frequency <kHz>] [--realtime] file.telem ...\n", program);
41 #define bool(b) ((b) ? "true" : "false")
43 struct ao_telem_list {
44 struct ao_telem_list *next;
45 union ao_telemetry_all telem;
48 static struct ao_telem_list *telem_list, **telem_last;
51 trim_telem(uint16_t time)
53 while (telem_list && (int16_t) (time - telem_list->telem.generic.tick) > 0) {
54 struct ao_telem_list *next = telem_list->next;
59 telem_last = &telem_list;
63 add_telem(union ao_telemetry_all *telem)
65 struct ao_telem_list *new = malloc (sizeof (struct ao_telem_list));
66 trim_telem((uint16_t) (telem->generic.tick - 20 * 100));
70 telem_last = &new->next;
73 static enum ao_flight_state cur_state = ao_flight_invalid;
74 static enum ao_flight_state last_state = ao_flight_invalid;
76 static enum ao_flight_state
77 packet_state(union ao_telemetry_all *telem)
79 switch (telem->generic.type) {
80 case AO_TELEMETRY_SENSOR_TELEMETRUM:
81 case AO_TELEMETRY_SENSOR_TELEMINI:
82 case AO_TELEMETRY_SENSOR_TELENANO:
83 cur_state = telem->sensor.state;
85 case AO_TELEMETRY_MEGA_DATA:
86 cur_state = telem->mega_data.state;
92 static const char *state_names[] = {
106 send_telem(struct cc_usb *cc, union ao_telemetry_all *telem)
108 int rssi = (int8_t) telem->generic.rssi / 2 - 74;
113 if (cur_state != last_state) {
114 if (0 <= cur_state && cur_state < sizeof(state_names) / sizeof (state_names[0]))
115 printf ("%s\n", state_names[cur_state]);
116 last_state = cur_state;
118 cc_usb_printf(cc, "S 20\n");
119 b = (uint8_t *) telem;
120 for (i = 0; i < 0x20; i++)
121 cc_usb_printf(cc, "%02x", b[i]);
126 do_delay(uint16_t now, uint16_t then)
128 int16_t delay = (int16_t) (now - then);
130 if (delay > 0 && delay < 1000)
131 usleep(delay * 10 * 1000);
135 send_queued(struct cc_usb *cc, int pause)
137 struct ao_telem_list *next;
142 if (started && pause)
143 do_delay(telem_list->telem.generic.tick, tick);
144 tick = telem_list->telem.generic.tick;
146 send_telem(cc, &telem_list->telem);
148 next = telem_list->next;
156 main (int argc, char **argv)
172 while ((c = getopt_long(argc, argv, "RT:D:F:", options, NULL)) != -1) {
191 tty = cc_usbdevs_find_by_arg(device, "TeleDongle");
193 tty = getenv("ALTOS_TTY");
196 cc = cc_usb_open(tty);
200 cc_usb_printf(cc, "m 0\n");
201 cc_usb_printf(cc, "F %d\n", freq);
202 for (i = optind; i < argc; i++) {
203 file = fopen(argv[i], "r");
211 while (fgets(line, sizeof (line), file)) {
212 union ao_telemetry_all telem;
214 if (cc_telemetry_parse(line, &telem)) {
216 * Skip packets with CRC errors.
218 if ((telem.generic.status & (1 << 7)) == 0)
222 do_delay(telem.generic.tick, last_tick);
223 last_tick = telem.generic.tick;
224 send_telem(cc, &telem);
227 if (packet_state(&telem) > ao_flight_pad) {
229 last_tick = send_queued(cc, realtime);