diff options
| -rw-r--r-- | ao-tools/ao-dumplog/ao-dumplog.c | 95 | ||||
| -rw-r--r-- | ao-tools/ao-postflight/ao-postflight.c | 18 | ||||
| -rw-r--r-- | ao-tools/ao-view/Makefile.am | 1 | ||||
| -rw-r--r-- | ao-tools/ao-view/aoview.glade | 101 | ||||
| -rw-r--r-- | ao-tools/ao-view/aoview.h | 11 | ||||
| -rw-r--r-- | ao-tools/ao-view/aoview_channel.c | 90 | ||||
| -rw-r--r-- | ao-tools/ao-view/aoview_flite.c | 10 | ||||
| -rw-r--r-- | ao-tools/ao-view/aoview_main.c | 2 | ||||
| -rw-r--r-- | ao-tools/ao-view/aoview_monitor.c | 12 | ||||
| -rw-r--r-- | src/ao_usb.c | 53 | 
10 files changed, 362 insertions, 31 deletions
| diff --git a/ao-tools/ao-dumplog/ao-dumplog.c b/ao-tools/ao-dumplog/ao-dumplog.c index b930f0e5..158a445b 100644 --- a/ao-tools/ao-dumplog/ao-dumplog.c +++ b/ao-tools/ao-dumplog/ao-dumplog.c @@ -37,6 +37,30 @@ static void usage(char *program)  	exit(1);  } +static uint8_t +log_checksum(int d[8]) +{ +	uint8_t	sum = 0x5a; +	int	i; + +	for (i = 0; i < 8; i++) +		sum += (uint8_t) d[i]; +	return -sum; +} + +static const char *state_names[] = { +	"startup", +	"idle", +	"pad", +	"boost", +	"fast", +	"coast", +	"drogue", +	"main", +	"landed", +	"invalid" +}; +  int  main (int argc, char **argv)  { @@ -50,6 +74,12 @@ main (int argc, char **argv)  	int		serial_number;  	char		cmd;  	int		tick, a, b; +	int		block; +	int		addr; +	int		received_addr; +	int		data[8]; +	int		done; +	int		column;  	while ((c = getopt_long(argc, argv, "T:D:", options, NULL)) != -1) {  		switch (c) { @@ -74,12 +104,10 @@ main (int argc, char **argv)  	if (!cc)  		exit(1);  	/* send a 'version' command followed by a 'log' command */ -	cc_usb_printf(cc, "v\nl\n"); +	cc_usb_printf(cc, "v\n");  	out = NULL;  	for (;;) {  		cc_usb_getline(cc, line, sizeof (line)); -		if (!strcmp (line, "end")) -			break;  		if (sscanf(line, "serial-number %u", &serial_number) == 1) {  			filename = cc_make_filename(serial_number, "eeprom");  			out = fopen (filename, "w"); @@ -87,16 +115,65 @@ main (int argc, char **argv)  				perror(filename);  			}  			fprintf (out, "%s\n", line); -		} else if (sscanf(line, "%c %x %x %x", &cmd, &tick, &a, &b) == 4) { -			if (out) { -				fprintf(out, "%s\n", line); -				if (cmd == 'S' && a == 8) { -					fclose(out); -					out = NULL; +		} +		if (!strncmp(line, "software-version", 16)) +			break; +	} +	if (!out) { +		fprintf(stderr, "no serial number found\n"); +		cc_usb_close(cc); +		exit(1); +	} +	printf ("Serial number: %d\n", serial_number); +	printf ("File name:     %s\n", filename); +	done = 0; +	column = 0; +	for (block = 0; !done && block < 511; block++) { +		cc_usb_printf(cc, "e %x\n", block); +		if (column == 64) { +			putchar('\n'); +			column = 0; +		} +		putchar('.'); fflush(stdout); column++; +		for (addr = 0; addr < 0x100;) { +			cc_usb_getline(cc, line, sizeof (line)); +			if (sscanf(line, "00%x %x %x %x %x %x %x %x %x", +					  &received_addr, +					  &data[0], &data[1], &data[2], &data[3], +					  &data[4], &data[5], &data[6], &data[7]) == 9) +			{ +				if (received_addr != addr) +					fprintf(stderr, "data out of sync at 0x%x\n", +						block * 256 + received_addr); + +				if (log_checksum(data) != 0) +					fprintf (stderr, "invalid checksum at 0x%x\n", +						 block * 256 + received_addr); + +				cmd = data[0]; +				tick = data[2] + (data[3] << 8); +				a = data[4] + (data[5] << 8); +				b = data[6] + (data[7] << 8); +				if (cmd == 'S' && a <= 8) { +					if (column) putchar('\n'); +					printf("%s\n", state_names[a]); +					column = 0; +				} +				if (out) { +					fprintf(out, "%c %4x %4x %4x\n", +						cmd, tick, a, b); +					if (cmd == 'S' && a == 8) { +						fclose(out); +						out = NULL; +						done = 1; +					}  				} +				addr += 8;  			}  		}  	} +	if (column) +		putchar('\n');  	if (out)  		fclose (out);  	cc_usb_close(cc); diff --git a/ao-tools/ao-postflight/ao-postflight.c b/ao-tools/ao-postflight/ao-postflight.c index 6418521e..cc9f64b4 100644 --- a/ao-tools/ao-postflight/ao-postflight.c +++ b/ao-tools/ao-postflight/ao-postflight.c @@ -313,14 +313,30 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, FI  		}  	}  	if (gps_file) { +		int	j = 0;  		fprintf(gps_file, "%9s %12s %12s %12s\n",  			"time", "lat", "lon", "alt");  		for (i = 0; i < f->gps.num; i++) { -			fprintf(gps_file, "%12.7f %12.7f %12.7f %12.7f\n", +			int	nsat = 0; +			int	k; +			while (j < f->gps.numsats - 1) { +				if (f->gps.sats[j].sat[0].time <= f->gps.data[i].time && +				    f->gps.data[i].time < f->gps.sats[j+1].sat[0].time) +					break; +				j++; +			} +			fprintf(gps_file, "%12.7f %12.7f %12.7f %12.7f",  				(f->gps.data[i].time - boost_start) / 100.0,  				f->gps.data[i].lat,  				f->gps.data[i].lon,  				f->gps.data[i].alt); +			nsat = 0; +			for (k = 0; k < f->gps.sats[j].nsat; k++) { +				fprintf (gps_file, " %12.7f", (double) f->gps.sats[j].sat[k].c_n); +				if (f->gps.sats[j].sat[k].state == 0xbf) +					nsat++; +			} +			fprintf(gps_file, " %d\n", nsat);  		}  	}  	if (cooked && plot_name) { diff --git a/ao-tools/ao-view/Makefile.am b/ao-tools/ao-view/Makefile.am index 7b274a40..7a288417 100644 --- a/ao-tools/ao-view/Makefile.am +++ b/ao-tools/ao-view/Makefile.am @@ -25,6 +25,7 @@ ao_view_SOURCES = \  	aoview_replay.c \  	aoview_label.c \  	aoview_flite.c \ +	aoview_channel.c \  	aoview.h  BUILT_SOURCES = aoview_glade.h diff --git a/ao-tools/ao-view/aoview.glade b/ao-tools/ao-view/aoview.glade index 9a746110..c302ad0d 100644 --- a/ao-tools/ao-view/aoview.glade +++ b/ao-tools/ao-view/aoview.glade @@ -258,6 +258,107 @@                </widget>              </child>              <child> +              <widget class="GtkMenuItem" id="channel_menu_item"> +                <property name="visible">True</property> +                <property name="label" translatable="yes">_Channel</property> +                <property name="use_underline">True</property> +                <child> +                  <widget class="GtkMenu" id="menu7"> +                    <property name="visible">True</property> +                    <child> +                      <widget class="GtkRadioMenuItem" id="channel_0"> +                        <property name="visible">True</property> +                        <property name="label" translatable="yes">Channel 0 (434.550MHz)</property> +                        <property name="use_underline">True</property> +                        <property name="draw_as_radio">True</property> +                      </widget> +                    </child> +                    <child> +                      <widget class="GtkRadioMenuItem" id="channel_1"> +                        <property name="visible">True</property> +                        <property name="label" translatable="yes">Channel 1 (434.650MHz)</property> +                        <property name="use_underline">True</property> +                        <property name="draw_as_radio">True</property> +                        <property name="group">channel_0</property> +                      </widget> +                    </child> +                    <child> +                      <widget class="GtkRadioMenuItem" id="channel_2"> +                        <property name="visible">True</property> +                        <property name="label" translatable="yes">Channel 2 (434.750MHz)</property> +                        <property name="use_underline">True</property> +                        <property name="draw_as_radio">True</property> +                        <property name="group">channel_0</property> +                      </widget> +                    </child> +                    <child> +                      <widget class="GtkRadioMenuItem" id="channel_3"> +                        <property name="visible">True</property> +                        <property name="label" translatable="yes">Channel 3 (434.850MHz)</property> +                        <property name="use_underline">True</property> +                        <property name="draw_as_radio">True</property> +                        <property name="group">channel_0</property> +                      </widget> +                    </child> +                    <child> +                      <widget class="GtkRadioMenuItem" id="channel_4"> +                        <property name="visible">True</property> +                        <property name="label" translatable="yes">Channel 4 (434.950MHz)</property> +                        <property name="use_underline">True</property> +                        <property name="draw_as_radio">True</property> +                        <property name="group">channel_0</property> +                      </widget> +                    </child> +                    <child> +                      <widget class="GtkRadioMenuItem" id="channel_5"> +                        <property name="visible">True</property> +                        <property name="label" translatable="yes">Channel 5 (435.050MHz)</property> +                        <property name="use_underline">True</property> +                        <property name="draw_as_radio">True</property> +                        <property name="group">channel_0</property> +                      </widget> +                    </child> +                    <child> +                      <widget class="GtkRadioMenuItem" id="channel_6"> +                        <property name="visible">True</property> +                        <property name="label" translatable="yes">Channel 6 (435.150MHz)</property> +                        <property name="use_underline">True</property> +                        <property name="draw_as_radio">True</property> +                        <property name="group">channel_0</property> +                      </widget> +                    </child> +                    <child> +                      <widget class="GtkRadioMenuItem" id="channel_7"> +                        <property name="visible">True</property> +                        <property name="label" translatable="yes">Channel 7 (435.250MHz)</property> +                        <property name="use_underline">True</property> +                        <property name="draw_as_radio">True</property> +                        <property name="group">channel_0</property> +                      </widget> +                    </child> +                    <child> +                      <widget class="GtkRadioMenuItem" id="channel_8"> +                        <property name="visible">True</property> +                        <property name="label" translatable="yes">Channel 8 (435.350MHz)</property> +                        <property name="use_underline">True</property> +                        <property name="draw_as_radio">True</property> +                        <property name="group">channel_0</property> +                      </widget> +                    </child> +                    <child> +                      <widget class="GtkRadioMenuItem" id="channel_9"> +                        <property name="visible">True</property> +                        <property name="label" translatable="yes">Channel 9 (435.450MHz)</property> +                        <property name="use_underline">True</property> +                        <property name="draw_as_radio">True</property> +                        <property name="group">channel_0</property> +                      </widget> +                    </child> +                  </widget> +                </child> +              </widget> +            </child> +            <child>                <widget class="GtkMenuItem" id="menuitem4">                  <property name="visible">True</property>                  <property name="label" translatable="yes">_Help</property> diff --git a/ao-tools/ao-view/aoview.h b/ao-tools/ao-view/aoview.h index 6a4753ac..c582159c 100644 --- a/ao-tools/ao-view/aoview.h +++ b/ao-tools/ao-view/aoview.h @@ -169,6 +169,9 @@ gboolean  aoview_monitor_parse(const char *line);  void +aoview_monitor_set_channel(int channel); + +void  aoview_monitor_reset(void);  struct aoview_serial * @@ -320,4 +323,12 @@ aoview_flite_stop(void);  extern char *aoview_tty; +/* aoview_channel.c */ + +int +aoview_channel_current(void); + +void +aoview_channel_init(GladeXML *xml); +  #endif /* _AOVIEW_H_ */ diff --git a/ao-tools/ao-view/aoview_channel.c b/ao-tools/ao-view/aoview_channel.c new file mode 100644 index 00000000..959173ca --- /dev/null +++ b/ao-tools/ao-view/aoview_channel.c @@ -0,0 +1,90 @@ +/* + * Copyright © 2009 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "aoview.h" + + +#define NUM_CHANNEL	10 + +static GtkRadioMenuItem *channel_item[NUM_CHANNEL]; + +int +aoview_channel_current(void) +{ +	int	c; + +	for (c = 0; c < NUM_CHANNEL; c++) +		if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(channel_item[c]))) +			return c; +	return -1; +} + +static void +aoview_channel_notify(int channel) +{ +	if (0 <= channel && channel < NUM_CHANNEL) +		gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(channel_item[channel]), TRUE); +} + +#define ALTOS_CHANNEL_PATH	"/apps/aoview/channel" + +static void +aoview_channel_change(GtkWidget *widget, gpointer data) +{ +	gboolean	enabled = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)); +	int		c = (int) data; +	GConfClient	*gconf_client; +	GError		*error; + +	if (enabled) { +		aoview_monitor_set_channel(c); +		gconf_client = gconf_client_get_default(); +		gconf_client_set_int(gconf_client, ALTOS_CHANNEL_PATH, c, &error); +	} +} + +void +aoview_channel_init(GladeXML *xml) +{ +	int	c; +	GConfClient	*gconf_client; + +	for (c = 0; c < NUM_CHANNEL; c++) { +		char	name[32]; + +		sprintf(name, "channel_%d", c); +		channel_item[c] = GTK_RADIO_MENU_ITEM(glade_xml_get_widget(xml, name)); +		assert(channel_item[c]); +		g_signal_connect(G_OBJECT(channel_item[c]), "toggled", +				 G_CALLBACK(aoview_channel_change), +				 (gpointer) c); +	} +	gconf_client = gconf_client_get_default(); +	c = 0; +	if (gconf_client) +	{ +		GError	*error; + +		error = NULL; +		c = gconf_client_get_int(gconf_client, +					 ALTOS_CHANNEL_PATH, +					 &error); +		if (error) +			c = 0; +	} +	aoview_channel_notify(c); +} diff --git a/ao-tools/ao-view/aoview_flite.c b/ao-tools/ao-view/aoview_flite.c index e1b75898..bc702b0f 100644 --- a/ao-tools/ao-view/aoview_flite.c +++ b/ao-tools/ao-view/aoview_flite.c @@ -42,12 +42,10 @@ aoview_flite_task(gpointer data)  	err = snd_pcm_open(&alsa_handle, "default",  			   SND_PCM_STREAM_PLAYBACK, 0); -	if (err >= 0) -	{ -		if (err < 0) { -			snd_pcm_close(alsa_handle); -			alsa_handle = 0; -		} +	if (err < 0) { +		fprintf(stderr, "alsa open failed %s\n", +			strerror(-err)); +		alsa_handle = NULL;  	}  	rate = 0;  	channels = 0; diff --git a/ao-tools/ao-view/aoview_main.c b/ao-tools/ao-view/aoview_main.c index 64c1c027..714bee9a 100644 --- a/ao-tools/ao-view/aoview_main.c +++ b/ao-tools/ao-view/aoview_main.c @@ -86,6 +86,8 @@ int main(int argc, char **argv)  	aoview_voice_init(xml); +	aoview_channel_init(xml); +  	aoview_dev_dialog_init(xml);  	aoview_state_init(xml); diff --git a/ao-tools/ao-view/aoview_monitor.c b/ao-tools/ao-view/aoview_monitor.c index 8564014b..48e20320 100644 --- a/ao-tools/ao-view/aoview_monitor.c +++ b/ao-tools/ao-view/aoview_monitor.c @@ -82,6 +82,7 @@ aoview_monitor_parse(const char *input_line)  	char line_buf[8192], *line;  	struct aodata	data;  	int	tracking_pos; +	int channel;  	/* avoid smashing our input parameter */  	strncpy (line_buf, input_line, sizeof (line_buf)-1); @@ -214,15 +215,26 @@ aoview_monitor_callback(gpointer user_data,  	}  } +void +aoview_monitor_set_channel(int channel) +{ +	if (monitor_serial) +		aoview_serial_printf(monitor_serial, "c r %d\n", channel); +} +  gboolean  aoview_monitor_connect(char *tty)  { +	int	channel;  	aoview_monitor_disconnect();  	monitor_serial = aoview_serial_open(tty);  	if (!monitor_serial)  		return FALSE;  	aoview_table_clear();  	aoview_state_reset(); +	channel = aoview_channel_current(); +	if (channel >= 0) +		aoview_monitor_set_channel(channel);  	aoview_serial_set_callback(monitor_serial,  				   aoview_monitor_callback);  	return TRUE; diff --git a/src/ao_usb.c b/src/ao_usb.c index 99f0715b..22665725 100644 --- a/src/ao_usb.c +++ b/src/ao_usb.c @@ -21,6 +21,7 @@  struct ao_task __xdata ao_usb_task;  static __xdata uint16_t	ao_usb_in_bytes; +static __xdata uint16_t ao_usb_in_bytes_last;  static __xdata uint16_t	ao_usb_out_bytes;  static __xdata uint8_t	ao_usb_iif;  static __xdata uint8_t	ao_usb_running; @@ -321,13 +322,40 @@ ao_usb_ep0(void)  	}  } +/* Wait for a free IN buffer */ +static void +ao_usb_in_wait(void) +{ +	for (;;) { +		USBINDEX = AO_USB_IN_EP; +		if ((USBCSIL & USBCSIL_INPKT_RDY) == 0) +			break; +		ao_sleep(&ao_usb_in_bytes); +	} +} + +/* Send the current IN packet */ +static void +ao_usb_in_send(void) +{ +	USBINDEX = AO_USB_IN_EP; +	USBCSIL |= USBCSIL_INPKT_RDY; +	ao_usb_in_bytes_last = ao_usb_in_bytes; +	ao_usb_in_bytes = 0; +} +  void  ao_usb_flush(void) __critical  { -	if (ao_usb_in_bytes) { -		USBINDEX = AO_USB_IN_EP; -		USBCSIL |= USBCSIL_INPKT_RDY; -		ao_usb_in_bytes = 0; +	if (!ao_usb_running) +		return; + +	/* If there are pending bytes, or if the last packet was full, +	 * send another IN packet +	 */ +	if (ao_usb_in_bytes || (ao_usb_in_bytes_last == AO_USB_IN_SIZE)) { +		ao_usb_in_wait(); +		ao_usb_in_send();  	}  } @@ -336,18 +364,13 @@ ao_usb_putchar(char c) __critical  {  	if (!ao_usb_running)  		return; -	for (;;) { -		USBINDEX = AO_USB_IN_EP; -		if ((USBCSIL & USBCSIL_INPKT_RDY) == 0) -			break; -		ao_sleep(&ao_usb_in_bytes); -	} + +	ao_usb_in_wait(); + +	/* Queue a byte, sending the packet when full */  	USBFIFO[AO_USB_IN_EP << 1] = c; -	if (++ao_usb_in_bytes == AO_USB_IN_SIZE) { -		USBINDEX = AO_USB_IN_EP; -		USBCSIL |= USBCSIL_INPKT_RDY; -		ao_usb_in_bytes = 0; -	} +	if (++ao_usb_in_bytes == AO_USB_IN_SIZE) +		ao_usb_in_send();  }  char | 
