diff options
34 files changed, 779 insertions, 232 deletions
| diff --git a/ao-tools/altosui/Altos.java b/ao-tools/altosui/Altos.java index 53359e23..07bd01ae 100644 --- a/ao-tools/altosui/Altos.java +++ b/ao-tools/altosui/Altos.java @@ -114,4 +114,90 @@ public class Altos {  	static final int AO_GPS_DATE_VALID = (1 << 6);  	static final int AO_GPS_NUM_SAT_SHIFT = 0;  	static final int AO_GPS_NUM_SAT_MASK = 0xf; + +	static boolean isspace(int c) { +		switch (c) { +		case ' ': +		case '\t': +			return true; +		} +		return false; +	} + +	static boolean ishex(int c) { +		if ('0' <= c && c <= '9') +			return true; +		if ('a' <= c && c <= 'f') +			return true; +		if ('A' <= c && c <= 'F') +			return true; +		return false; +	} + +	static boolean ishex(String s) { +		for (int i = 0; i < s.length(); i++) +			if (!ishex(s.charAt(i))) +				return false; +		return true; +	} + +	static int fromhex(int c) { +		if ('0' <= c && c <= '9') +			return c - '0'; +		if ('a' <= c && c <= 'f') +			return c - 'a' + 10; +		if ('A' <= c && c <= 'F') +			return c - 'A' + 10; +		return -1; +	} + +	static int fromhex(String s) throws NumberFormatException { +		int c, v = 0; +		for (int i = 0; i < s.length(); i++) { +			c = s.charAt(i); +			if (!ishex(c)) { +				if (i == 0) +					throw new NumberFormatException(String.format("invalid hex \"%s\"", s)); +				return v; +			} +			v = v * 16 + fromhex(c); +		} +		return v; +	} + +	static boolean isdec(int c) { +		if ('0' <= c && c <= '9') +			return true; +		return false; +	} + +	static boolean isdec(String s) { +		for (int i = 0; i < s.length(); i++) +			if (!isdec(s.charAt(i))) +				return false; +		return true; +	} + +	static int fromdec(int c) { +		if ('0' <= c && c <= '9') +			return c - '0'; +		return -1; +	} + +	static int fromdec(String s) throws NumberFormatException { +		int c, v = 0; +		int sign = 1; +		for (int i = 0; i < s.length(); i++) { +			c = s.charAt(i); +			if (i == 0 && c == '-') { +				sign = -1; +			} else if (!isdec(c)) { +				if (i == 0) +					throw new NumberFormatException(String.format("invalid number \"%s\"", s)); +				return v; +			} else +				v = v * 10 + fromdec(c); +		} +		return v * sign; +	}  } diff --git a/ao-tools/altosui/AltosCSV.java b/ao-tools/altosui/AltosCSV.java index 24936758..db50e7a2 100644 --- a/ao-tools/altosui/AltosCSV.java +++ b/ao-tools/altosui/AltosCSV.java @@ -19,12 +19,20 @@ package altosui;  import java.lang.*;  import java.io.*; +import java.text.*; +import java.util.*; +  import altosui.AltosRecord; +import altosui.AltosReader;  public class AltosCSV { -	File		name; -	PrintStream	out; -	boolean		header_written; +	File			name; +	PrintStream		out; +	boolean			header_written; +	boolean			seen_boost; +	int			boost_tick; +	LinkedList<AltosRecord>	pad_records; +	AltosState		state;  	static final int ALTOS_CSV_VERSION = 1; @@ -36,6 +44,7 @@ public class AltosCSV {  	 *	flight number  	 *	callsign  	 *	time (seconds since boost) +	 *	rssi  	 *  	 * Flight status  	 *	state @@ -45,6 +54,7 @@ public class AltosCSV {  	 *	acceleration (m/s²)  	 *	pressure (mBar)  	 *	altitude (m) +	 *	height (m)  	 *	accelerometer speed (m/s)  	 *	barometer speed (m/s)  	 *	temp (°C) @@ -65,6 +75,8 @@ public class AltosCSV {  	 *	hour (0-23)  	 *	minute (0-59)  	 *	second (0-59) +	 *	from_pad_dist (m) +	 *	from_pad_dir (deg true)  	 *  	 * GPS Sat data  	 *	hdop @@ -72,12 +84,14 @@ public class AltosCSV {  	 */  	void write_general_header() { -		out.printf("version serial flight call time"); +		out.printf("version serial flight call time rssi");  	}  	void write_general(AltosRecord record) { -		out.printf("%s,%d,%d,%s,%d", -			   record.version, record.serial, record.flight, record.callsign, record.tick); +		out.printf("%s,%d,%d,%s,%8.2f,%4d", +			   record.version, record.serial, record.flight, record.callsign, +			   (double) record.time, +			   record.rssi);  	}  	void write_flight_header() { @@ -85,31 +99,135 @@ public class AltosCSV {  	}  	void write_flight(AltosRecord record) { -		out.printf("%d,%s", record.state, record.state()); +		out.printf("%d,%8s", record.state, record.state()); +	} + +	void write_basic_header() { +		out.printf("acceleration pressure altitude height accel_speed baro_speed temperature battery_voltage drogue_voltage main_voltage"); +	} + +	void write_basic(AltosRecord record) { +		out.printf("%8.2f,%10.2f,%8.2f,%8.2f,%8.2f,%8.2f,%5.1f,%5.2f,%5.2f,%5.2f", +			   record.acceleration(), +			   record.pressure(), +			   record.altitude(), +			   record.height(), +			   record.accel_speed(), +			   state.baro_speed, +			   record.temperature(), +			   record.battery_voltage(), +			   record.drogue_voltage(), +			   record.main_voltage()); +	} + +	void write_gps_header() { +		out.printf("connected locked nsat latitude longitude altitude year month day hour minute second pad_dist pad_dir"); +	} + +	void write_gps(AltosRecord record) { +		AltosGPS	gps = record.gps; +		if (gps == null) +			gps = new AltosGPS(); + +		AltosGreatCircle from_pad = state.from_pad; +		if (from_pad == null) +			from_pad = new AltosGreatCircle(); + +		out.printf("%2d,%2d,%3d,%12.7f,%12.7f,%6d,%5d,%3d,%3d,%3d,%3d,%3d,%9.0f,%4.0f", +			   gps.connected?1:0, +			   gps.locked?1:0, +			   gps.nsat, +			   gps.lat, +			   gps.lon, +			   gps.alt, +			   gps.year, +			   gps.month, +			   gps.day, +			   gps.hour, +			   gps.minute, +			   gps.second, +			   from_pad.distance, +			   from_pad.bearing);  	}  	void write_header() {  		out.printf("# "); write_general_header();  		out.printf(" "); write_flight_header(); +		out.printf(" "); write_basic_header(); +		out.printf(" "); write_gps_header(); +		out.printf ("\n"); +	} + +	void write_one(AltosRecord record) { +		state = new AltosState(record, state); +		write_general(record); out.printf(","); +		write_flight(record); out.printf(","); +		write_basic(record); out.printf(","); +		write_gps(record);  		out.printf ("\n");  	} +	void flush_pad() { +		while (!pad_records.isEmpty()) { +			write_one (pad_records.remove()); +		} +	} +  	public void write(AltosRecord record) {  		if (!header_written) {  			write_header();  			header_written = true;  		} -		write_general(record); out.printf(","); -		write_flight(record); -		out.printf ("\n"); +		if (!seen_boost) { +			if (record.state >= Altos.ao_flight_boost) { +				seen_boost = true; +				boost_tick = record.tick; +				flush_pad(); +			} +		} +		if (seen_boost) +			write_one(record); +		else +			pad_records.add(record);  	}  	public PrintStream out() {  		return out;  	} +	public void close() { +		if (!pad_records.isEmpty()) { +			boost_tick = pad_records.element().tick; +			flush_pad(); +		} +		out.close(); +	} + +	public void write(AltosReader reader) { +		AltosRecord	record; + +		reader.write_comments(out()); +		try { +			for (;;) { +				record = reader.read(); +				if (record == null) +					break; +				write(record); +			} +		} catch (IOException ie) { +			System.out.printf("IOException\n"); +		} catch (ParseException pe) { +			System.out.printf("ParseException %s\n", pe.getMessage()); +		} +	} +  	public AltosCSV(File in_name) throws FileNotFoundException {  		name = in_name;  		out = new PrintStream(name); +		pad_records = new LinkedList<AltosRecord>(); +	} + +	public AltosCSV(String in_string) throws FileNotFoundException { +		this(new File(in_string));  	}  } diff --git a/ao-tools/altosui/AltosCSVUI.java b/ao-tools/altosui/AltosCSVUI.java new file mode 100644 index 00000000..2d812361 --- /dev/null +++ b/ao-tools/altosui/AltosCSVUI.java @@ -0,0 +1,83 @@ +/* + * Copyright © 2010 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. + */ + +package altosui; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import javax.swing.table.*; +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.LinkedBlockingQueue; + +import altosui.AltosLogfileChooser; +import altosui.AltosCSV; + +public class AltosCSVUI +	extends JDialog +	implements Runnable, ActionListener +{ +	JFrame		frame; +	Thread		thread; +	AltosReader	reader; +	AltosCSV	writer; + +	public void run() { +		AltosLogfileChooser	chooser; + +		chooser = new AltosLogfileChooser(frame); +		reader = chooser.runDialog(); +		if (reader == null) +			return; +		JFileChooser	csv_chooser; + +		File file = chooser.file(); +		String path = file.getPath(); +		int dot = path.lastIndexOf("."); +		if (dot >= 0) +			path = path.substring(0,dot); +		path = path.concat(".csv"); +		csv_chooser = new JFileChooser(path); +		int ret = csv_chooser.showSaveDialog(frame); +		if (ret == JFileChooser.APPROVE_OPTION) { +			try { +				writer = new AltosCSV(csv_chooser.getSelectedFile()); +			} catch (FileNotFoundException ee) { +				JOptionPane.showMessageDialog(frame, +							      file.getName(), +							      "Cannot open file", +							      JOptionPane.ERROR_MESSAGE); +			} +			writer.write(reader); +			reader.close(); +			writer.close(); +		} +	} + +	public void actionPerformed(ActionEvent e) { +	} + +	public AltosCSVUI(JFrame in_frame) { +		frame = in_frame; +		thread = new Thread(this); +		thread.start(); +	} +} diff --git a/ao-tools/altosui/AltosDebug.java b/ao-tools/altosui/AltosDebug.java index 83ea5bcb..ca2e5a90 100644 --- a/ao-tools/altosui/AltosDebug.java +++ b/ao-tools/altosui/AltosDebug.java @@ -58,46 +58,12 @@ public class AltosDebug extends AltosSerial {  	public static final byte GET_CHIP_ID =		0x68; -	static boolean ishex(int c) { -		if ('0' <= c && c <= '9') -			return true; -		if ('a' <= c && c <= 'f') -			return true; -		if ('A' <= c && c <= 'F') -			return true; -		return false; -	} - -	static boolean ishex(String s) { -		for (int i = 0; i < s.length(); i++) -			if (!ishex(s.charAt(i))) -				return false; -		return true; -	} -	static boolean isspace(int c) { -		switch (c) { -		case ' ': -		case '\t': -			return true; -		} -		return false; -	} - -	static int fromhex(int c) { -		if ('0' <= c && c <= '9') -			return c - '0'; -		if ('a' <= c && c <= 'f') -			return c - 'a' + 10; -		if ('A' <= c && c <= 'F') -			return c - 'A' + 10; -		return -1; -	} -  	boolean	debug_mode;  	void ensure_debug_mode() {  		if (!debug_mode) { -			printf("D\n"); +			printf("m 0\nD\n"); +			flush_reply();  			debug_mode = true;  		}  	} @@ -144,14 +110,14 @@ public class AltosDebug extends AltosSerial {  		int start = 0;  		while (i < length) {  			String	line = get_reply().trim(); -			if (!ishex(line) || line.length() % 2 != 0) +			if (!Altos.ishex(line) || line.length() % 2 != 0)  				throw new IOException(  					String.format  					("Invalid reply \"%s\"", line));  			int this_time = line.length() / 2;  			for (int j = 0; j < this_time; j++) -				data[start + j] = (byte) ((fromhex(line.charAt(j*2)) << 4) + -						  fromhex(line.charAt(j*2+1))); +				data[start + j] = (byte) ((Altos.fromhex(line.charAt(j*2)) << 4) + +						  Altos.fromhex(line.charAt(j*2+1)));  			start += this_time;  			i += this_time;  		} @@ -198,7 +164,7 @@ public class AltosDebug extends AltosSerial {  			String line = get_reply().trim();  			String tokens[] = line.split("\\s+");  			for (int j = 0; j < tokens.length; j++) { -				if (!ishex(tokens[j]) || +				if (!Altos.ishex(tokens[j]) ||  				    tokens[j].length() != 2)  					throw new IOException(  						String.format diff --git a/ao-tools/altosui/AltosEepromReader.java b/ao-tools/altosui/AltosEepromReader.java index c29fd90b..3f2d4c62 100644 --- a/ao-tools/altosui/AltosEepromReader.java +++ b/ao-tools/altosui/AltosEepromReader.java @@ -133,8 +133,6 @@ public class AltosEepromReader extends AltosReader {  					ground_pres += state.pres;  					state.ground_pres = (int) (ground_pres / n_pad_samples);  					state.flight_pres = state.ground_pres; -					System.out.printf("ground pressure %d altitude %f\n", -							  record.b, state.altitude());  					ground_accel += state.accel;  					state.ground_accel = (int) (ground_accel / n_pad_samples);  					state.flight_accel = state.ground_accel; @@ -156,7 +154,6 @@ public class AltosEepromReader extends AltosReader {  				seen |= seen_deploy;  				break;  			case Altos.AO_LOG_STATE: -				System.out.printf("state %d\n", record.a);  				state.state = record.a;  				break;  			case Altos.AO_LOG_GPS_TIME: @@ -218,6 +215,7 @@ public class AltosEepromReader extends AltosReader {  			case Altos.AO_LOG_PRODUCT:  				break;  			case Altos.AO_LOG_SERIAL_NUMBER: +				state.serial = record.a;  				break;  			case Altos.AO_LOG_SOFTWARE_VERSION:  				break; @@ -228,6 +226,7 @@ public class AltosEepromReader extends AltosReader {  	public void write_comments(PrintStream out) {  		Iterator<AltosOrderedRecord>	iterator = records.iterator(); +		out.printf("# Comments\n");  		while (iterator.hasNext()) {  			AltosOrderedRecord	record = iterator.next();  			switch (record.cmd) { @@ -250,7 +249,7 @@ public class AltosEepromReader extends AltosReader {  				out.printf ("# Accel cal: %d %d\n", record.a, record.b);  				break;  			case Altos.AO_LOG_RADIO_CAL: -				out.printf ("# Radio cal: %d %d\n", record.a); +				out.printf ("# Radio cal: %d\n", record.a);  				break;  			case Altos.AO_LOG_MANUFACTURER:  				out.printf ("# Manufacturer: %s\n", record.data); @@ -296,10 +295,10 @@ public class AltosEepromReader extends AltosReader {  					break;  				tick = record.tick;  				if (!saw_boost && record.cmd == Altos.AO_LOG_STATE && -				    record.a == Altos.ao_flight_boost) +				    record.a >= Altos.ao_flight_boost)  				{  					saw_boost = true; -					boost_tick = state.tick; +					boost_tick = tick;  				}  				records.add(record);  			} diff --git a/ao-tools/altosui/AltosFlash.java b/ao-tools/altosui/AltosFlash.java index 0f92d6e7..b7018555 100644 --- a/ao-tools/altosui/AltosFlash.java +++ b/ao-tools/altosui/AltosFlash.java @@ -247,6 +247,7 @@ public class AltosFlash {  		int flash_addr = image.address;  		int image_start = 0; +		action("start", 0);  		action(0, image.data.length);  		while (remain > 0 && !aborted) {  			int this_time = remain; @@ -314,6 +315,8 @@ public class AltosFlash {  	}  	public AltosRomconfig romconfig() { +		if (!check_rom_config()) +			return null;  		return rom_config;  	} diff --git a/ao-tools/altosui/AltosFlashUI.java b/ao-tools/altosui/AltosFlashUI.java index 0c2041e3..73a97a6b 100644 --- a/ao-tools/altosui/AltosFlashUI.java +++ b/ao-tools/altosui/AltosFlashUI.java @@ -57,8 +57,10 @@ public class AltosFlashUI  		} else {  			String	cmd = e.getActionCommand();  			if (cmd.equals("done")) -				dispose(); -			else { +				; +			else if (cmd.equals("start")) { +				setVisible(true); +			} else {  				pbar.setValue(e.getID());  				pbar.setString(cmd);  			} @@ -70,14 +72,15 @@ public class AltosFlashUI  		flash.addActionListener(this);  		try {  			flash.open(); -			if (!flash.check_rom_config()) { -				AltosRomconfigUI romconfig_ui = new AltosRomconfigUI (frame); -				romconfig_ui.showDialog(); -				AltosRomconfig romconfig = romconfig_ui.romconfig(); -				if (romconfig == null) -					return; -				flash.set_romconfig(romconfig); -			} +			AltosRomconfigUI romconfig_ui = new AltosRomconfigUI (frame); + +			romconfig_ui.set(flash.romconfig()); +			romconfig_ui.showDialog(); + +			AltosRomconfig romconfig = romconfig_ui.romconfig(); +			if (romconfig == null || !romconfig.valid()) +				return; +			flash.set_romconfig(romconfig);  			serial_value.setText(String.format("%d",  							   flash.romconfig().serial_number));  			file_value.setText(file.toString()); @@ -88,15 +91,14 @@ public class AltosFlashUI  						      "Cannot open image",  						      file.toString(),  						      JOptionPane.ERROR_MESSAGE); -			return;  		} catch (IOException e) {  			JOptionPane.showMessageDialog(frame,  						      e.getMessage(),  						      file.toString(),  						      JOptionPane.ERROR_MESSAGE); -			return;  		} catch (InterruptedException ie) {  		} +		dispose();  	}  	public void abort() { diff --git a/ao-tools/altosui/AltosGPS.java b/ao-tools/altosui/AltosGPS.java index b3ee67e8..acb6fb2c 100644 --- a/ao-tools/altosui/AltosGPS.java +++ b/ao-tools/altosui/AltosGPS.java @@ -52,14 +52,16 @@ public class AltosGPS {  	AltosGPSSat[] cc_gps_sat;	/* tracking data */ -	void ParseGPSTime(String date, String time) throws ParseException { +	void ParseGPSDate(String date) throws ParseException {  		String[] ymd = date.split("-");  		if (ymd.length != 3)  			throw new ParseException("error parsing GPS date " + date + " got " + ymd.length, 0);  		year = AltosParse.parse_int(ymd[0]);  		month = AltosParse.parse_int(ymd[1]);  		day = AltosParse.parse_int(ymd[2]); +	} +	void ParseGPSTime(String time) throws ParseException {  		String[] hms = time.split(":");  		if (hms.length != 3)  			throw new ParseException("Error parsing GPS time " + time + " got " + hms.length, 0); @@ -73,7 +75,7 @@ public class AltosGPS {  		hour = minute = second = 0;  	} -	public AltosGPS(String[] words, int i) throws ParseException { +	public AltosGPS(String[] words, int i, int version) throws ParseException {  		AltosParse.word(words[i++], "GPS");  		nsat = AltosParse.parse_int(words[i++]);  		AltosParse.word(words[i++], "sat"); @@ -92,32 +94,44 @@ public class AltosGPS {  			locked = true;  			connected = true; -			ParseGPSTime(words[i], words[i+1]); i += 2; +			if (version > 1) +				ParseGPSDate(words[i++]); +			else +				year = month = day = 0; +			ParseGPSTime(words[i++]);  			lat = AltosParse.parse_coord(words[i++]);  			lon = AltosParse.parse_coord(words[i++]); -			alt = AltosParse.parse_int(AltosParse.strip_suffix(words[i++], "m")); -			ground_speed = AltosParse.parse_double(AltosParse.strip_suffix(words[i++], "m/s(H)")); -			course = AltosParse.parse_int(AltosParse.strip_suffix(words[i++], "°")); -			climb_rate = AltosParse.parse_double(AltosParse.strip_suffix(words[i++], "m/s(V)")); -			hdop = AltosParse.parse_double(AltosParse.strip_suffix(words[i++], "(hdop)")); -			h_error = AltosParse.parse_int(AltosParse.strip_suffix(words[i++], "(herr)")); -			v_error = AltosParse.parse_int(AltosParse.strip_suffix(words[i++], "(verr)")); +			alt = AltosParse.parse_int(words[i++]); +			if (version > 1 || (i < words.length && !words[i].equals("SAT"))) { +				ground_speed = AltosParse.parse_double(AltosParse.strip_suffix(words[i++], "m/s(H)")); +				course = AltosParse.parse_int(words[i++]); +				climb_rate = AltosParse.parse_double(AltosParse.strip_suffix(words[i++], "m/s(V)")); +				hdop = AltosParse.parse_double(AltosParse.strip_suffix(words[i++], "(hdop)")); +				h_error = AltosParse.parse_int(words[i++]); +				v_error = AltosParse.parse_int(words[i++]); +			}  		} else {  			i++;  		} -		AltosParse.word(words[i++], "SAT"); -		int tracking_channels = 0; -		if (words[i].equals("not-connected")) -			tracking_channels = 0; -		else -			tracking_channels = AltosParse.parse_int(words[i]); -		i++; -		cc_gps_sat = new AltosGPS.AltosGPSSat[tracking_channels]; -		for (int chan = 0; chan < tracking_channels; chan++) { -			cc_gps_sat[chan] = new AltosGPS.AltosGPSSat(); -			cc_gps_sat[chan].svid = AltosParse.parse_int(words[i++]); -			cc_gps_sat[chan].c_n0 = AltosParse.parse_int(words[i++]); -		} +		if (i < words.length) { +			AltosParse.word(words[i++], "SAT"); +			int tracking_channels = 0; +			if (words[i].equals("not-connected")) +				tracking_channels = 0; +			else +				tracking_channels = AltosParse.parse_int(words[i]); +			i++; +			cc_gps_sat = new AltosGPS.AltosGPSSat[tracking_channels]; +			for (int chan = 0; chan < tracking_channels; chan++) { +				cc_gps_sat[chan] = new AltosGPS.AltosGPSSat(); +				cc_gps_sat[chan].svid = AltosParse.parse_int(words[i++]); +				/* Older versions included SiRF status bits */ +				if (version < 2) +					i++; +				cc_gps_sat[chan].c_n0 = AltosParse.parse_int(words[i++]); +			} +		} else +			cc_gps_sat = new AltosGPS.AltosGPSSat[0];  	}  	public void set_latitude(int in_lat) { @@ -172,6 +186,7 @@ public class AltosGPS {  		nsat = old.nsat;  		locked = old.locked;  		connected = old.connected; +		date_valid = old.date_valid;  		lat = old.lat;		/* degrees (+N -S) */  		lon = old.lon;		/* degrees (+E -W) */  		alt = old.alt;		/* m */ diff --git a/ao-tools/altosui/AltosGreatCircle.java b/ao-tools/altosui/AltosGreatCircle.java index 878da03e..07c02c16 100644 --- a/ao-tools/altosui/AltosGreatCircle.java +++ b/ao-tools/altosui/AltosGreatCircle.java @@ -17,6 +17,8 @@  package altosui; +import altosui.AltosGPS; +  import java.lang.Math;  public class AltosGreatCircle { @@ -28,8 +30,8 @@ public class AltosGreatCircle {  	static final double rad = Math.PI / 180;  	static final double earth_radius = 6371.2 * 1000;	/* in meters */ -	AltosGreatCircle (double start_lat, double start_lon, -			  double end_lat, double end_lon) +	public AltosGreatCircle (double start_lat, double start_lon, +				 double end_lat, double end_lon)  	{  		double lat1 = rad * start_lat;  		double lon1 = rad * -start_lon; @@ -63,4 +65,13 @@ public class AltosGreatCircle {  		distance = d * earth_radius;  		bearing = course * 180/Math.PI;  	} + +	public AltosGreatCircle(AltosGPS start, AltosGPS end) { +		this(start.lat, start.lon, end.lat, end.lon); +	} + +	public AltosGreatCircle() { +		distance = 0; +		bearing = 0; +	}  } diff --git a/ao-tools/altosui/AltosLogfileChooser.java b/ao-tools/altosui/AltosLogfileChooser.java new file mode 100644 index 00000000..36b51de6 --- /dev/null +++ b/ao-tools/altosui/AltosLogfileChooser.java @@ -0,0 +1,83 @@ +/* + * Copyright © 2010 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. + */ + +package altosui; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import javax.swing.table.*; +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; + +import altosui.AltosPreferences; +import altosui.AltosReader; +import altosui.AltosEepromReader; +import altosui.AltosTelemetryReader; + +public class AltosLogfileChooser extends JFileChooser { +	JFrame	frame; +	String	filename; +	File	file; + +	public String filename() { +		return filename; +	} + +	public File file() { +		return file; +	} + +	public AltosReader runDialog() { +		int	ret; + +		ret = showOpenDialog(frame); +		if (ret == APPROVE_OPTION) { +			file = getSelectedFile(); +			if (file == null) +				return null; +			filename = file.getName(); +			try { +				FileInputStream in; + +				in = new FileInputStream(file); +				if (filename.endsWith("eeprom")) +					return new AltosEepromReader(in); +				else +					return new AltosTelemetryReader(in); +			} catch (FileNotFoundException fe) { +				JOptionPane.showMessageDialog(frame, +							      filename, +							      "Cannot open file", +							      JOptionPane.ERROR_MESSAGE); +			} +		} +		return null; +	} + +	public AltosLogfileChooser(JFrame in_frame) { +		frame = in_frame; +		setDialogTitle("Select Flight Record File"); +		setFileFilter(new FileNameExtensionFilter("Flight data file", +							  "eeprom", +							  "telem")); +		setCurrentDirectory(AltosPreferences.logdir()); +	} +}
\ No newline at end of file diff --git a/ao-tools/altosui/AltosParse.java b/ao-tools/altosui/AltosParse.java index a60dc694..4d82de78 100644 --- a/ao-tools/altosui/AltosParse.java +++ b/ao-tools/altosui/AltosParse.java @@ -20,10 +20,16 @@ package altosui;  import java.text.*;  import java.lang.*; +import altosui.Altos; +  public class AltosParse { +	static boolean isdigit(char c) { +		return '0' <= c && c <= '9'; +	} +  	static int parse_int(String v) throws ParseException {  		try { -			return Integer.parseInt(v); +			return Altos.fromdec(v);  		} catch (NumberFormatException e) {  			throw new ParseException("error parsing int " + v, 0);  		} @@ -31,7 +37,7 @@ public class AltosParse {  	static int parse_hex(String v) throws ParseException {  		try { -			return Integer.parseInt(v, 16); +			return Altos.fromhex(v);  		} catch (NumberFormatException e) {  			throw new ParseException("error parsing hex " + v, 0);  		} diff --git a/ao-tools/altosui/AltosReader.java b/ao-tools/altosui/AltosReader.java index 81779e2b..5be8795d 100644 --- a/ao-tools/altosui/AltosReader.java +++ b/ao-tools/altosui/AltosReader.java @@ -25,4 +25,6 @@ import altosui.AltosRecord;  public class AltosReader {  	public AltosRecord read() throws IOException, ParseException { return null; } +	public void close() { } +	public void write_comments(PrintStream out) { }  } diff --git a/ao-tools/altosui/AltosRomconfig.java b/ao-tools/altosui/AltosRomconfig.java index 844da7c4..8c9cb27a 100644 --- a/ao-tools/altosui/AltosRomconfig.java +++ b/ao-tools/altosui/AltosRomconfig.java @@ -47,14 +47,57 @@ public class AltosRomconfig {  		}  	} +	static void put_string(String value, byte[] bytes, int start) { +		for (int i = 0; i < value.length(); i++) +			bytes[start + i] = (byte) value.charAt(i); +	} + +	static final int AO_USB_DESC_STRING	= 3; + +	static void put_usb_serial(int value, byte[] bytes, int start) { +		int offset = start + 0xa; +		int string_num = 0; +		System.out.printf("Put usb serial %d\n", value); + +		while (offset < bytes.length && bytes[offset] != 0) { +			if (bytes[offset + 1] == AO_USB_DESC_STRING) { +				++string_num; +				if (string_num == 4) +					break; +			} +			offset += ((int) bytes[offset]) & 0xff; +		} +		System.out.printf("offset %d content %d\n", +				  offset, bytes[offset]); +		if (offset >= bytes.length || bytes[offset] == 0) +			return; +		int len = ((((int) bytes[offset]) & 0xff) - 2) / 2; +		String fmt = String.format("%%0%dd", len); +		System.out.printf("existing serial length %d format %s\n", len, fmt); + +		String s = String.format(fmt, value); +		if (s.length() != len) { +			System.out.printf("weird usb length issue %s isn't %d\n", +					  s, len); +			return; +		} +		for (int i = 0; i < len; i++) { +			bytes[offset + 2 + i*2] = (byte) s.charAt(i); +			bytes[offset + 2 + i*2+1] = 0; +		} +	} +  	public AltosRomconfig(byte[] bytes, int offset) {  		version = get_int(bytes, offset + 0, 2);  		check = get_int(bytes, offset + 2, 2); +		System.out.printf("version %d check %d\n", version, check);  		if (check == (~version & 0xffff)) {  			switch (version) { +			case 2:  			case 1:  				serial_number = get_int(bytes, offset + 4, 2);  				radio_calibration = get_int(bytes, offset + 6, 4); +				System.out.printf("serial %d cal %d\n", serial_number, radio_calibration);  				valid = true;  				break;  			} @@ -77,6 +120,8 @@ public class AltosRomconfig {  			throw new IOException("image does not contain existing rom config");  		switch (existing.version) { +		case 2: +			put_usb_serial(serial_number, bytes, offset);  		case 1:  			put_int(serial_number, bytes, offset + 4, 2);  			put_int(radio_calibration, bytes, offset + 6, 4); @@ -86,7 +131,9 @@ public class AltosRomconfig {  	public void write (AltosHexfile hexfile) throws IOException {  		write(hexfile.data, 0xa0 - hexfile.address); -		new AltosRomconfig(hexfile); +		AltosRomconfig check = new AltosRomconfig(hexfile); +		if (!check.valid()) +			throw new IOException("writing new rom config failed\n");  	}  	public AltosRomconfig(int in_serial_number, int in_radio_calibration) { diff --git a/ao-tools/altosui/AltosRomconfigUI.java b/ao-tools/altosui/AltosRomconfigUI.java index 21c34ef4..bc511865 100644 --- a/ao-tools/altosui/AltosRomconfigUI.java +++ b/ao-tools/altosui/AltosRomconfigUI.java @@ -143,12 +143,31 @@ public class AltosRomconfigUI  		return Integer.parseInt(serial_value.getText());  	} +	void set_serial(int serial) { +		serial_value.setText(String.format("%d", serial)); +	} +  	int radio_calibration() {  		return Integer.parseInt(radio_calibration_value.getText());  	} +	void set_radio_calibration(int calibration) { +		radio_calibration_value.setText(String.format("%d", calibration)); +	} + +	public void set(AltosRomconfig config) { +		if (config != null && config.valid()) { +			set_serial(config.serial_number); +			set_radio_calibration(config.radio_calibration); +		} +	} +  	public AltosRomconfig romconfig() { -		return new AltosRomconfig(serial(), radio_calibration()); +		try { +			return new AltosRomconfig(serial(), radio_calibration()); +		} catch (NumberFormatException ne) { +			return null; +		}  	}  	public AltosRomconfig showDialog() { diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index d02e25a9..5b47960f 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -45,6 +45,8 @@ public class AltosSerial implements Runnable {  	LinkedBlockingQueue<String> reply_queue;  	Thread input_thread;  	String line; +	byte[] line_bytes; +	int line_count;  	public void run () {  		int c; @@ -60,18 +62,36 @@ public class AltosSerial implements Runnable {  					continue;  				synchronized(this) {  					if (c == '\n') { -						if (line != "") { +						if (line_count != 0) { +							try { +								line = new String(line_bytes, 0, line_count, "UTF-8"); +							} catch (UnsupportedEncodingException ue) { +								line = ""; +								for (int i = 0; i < line_count; i++) +									line = line + line_bytes[i]; +							}  							if (line.startsWith("VERSION")) {  								for (int e = 0; e < monitors.size(); e++) {  									LinkedBlockingQueue<String> q = monitors.get(e);  									q.put(line);  								} -							} else +							} else { +//								System.out.printf("GOT: %s\n", line);  								reply_queue.put(line); +							} +							line_count = 0;  							line = "";  						}  					} else { -						line = line + (char) c; +						if (line_bytes == null) { +							line_bytes = new byte[256]; +						} else if (line_count == line_bytes.length) { +							byte[] new_line_bytes = new byte[line_count * 2]; +							System.arraycopy(line_bytes, 0, new_line_bytes, 0, line_count); +							line_bytes = new_line_bytes; +						} +						line_bytes[line_count] = (byte) c; +						line_count++;  					}  				}  			} @@ -80,6 +100,11 @@ public class AltosSerial implements Runnable {  	}  	public void flush_reply() { +		libaltos.altos_flush(altos); +		try { +			Thread.sleep(100); +		} catch (InterruptedException ie) { +		}  		reply_queue.clear();  	} @@ -132,6 +157,7 @@ public class AltosSerial implements Runnable {  	}  	public void print(String data) { +//h		System.out.printf("\"%s\" ", data);  		for (int i = 0; i < data.length(); i++)  			putc(data.charAt(i));  	} diff --git a/ao-tools/altosui/AltosState.java b/ao-tools/altosui/AltosState.java index deeb4c77..c13dfe68 100644 --- a/ao-tools/altosui/AltosState.java +++ b/ao-tools/altosui/AltosState.java @@ -124,11 +124,6 @@ public class AltosState {  		}  		if (state == Altos.ao_flight_pad) { -			if (data.gps == null) -				System.out.printf("on pad, gps null\n"); -			else -				System.out.printf ("on pad gps lat %f lon %f locked %d nsat %d\n", -						   data.gps.lat, data.gps.lon, data.gps.locked ? 1 : 0, data.gps.nsat);  			if (data.gps != null && data.gps.locked && data.gps.nsat >= 4) {  				npad++;  				if (npad > 1) { diff --git a/ao-tools/altosui/AltosTelemetry.java b/ao-tools/altosui/AltosTelemetry.java index af29b8c0..bc62690b 100644 --- a/ao-tools/altosui/AltosTelemetry.java +++ b/ao-tools/altosui/AltosTelemetry.java @@ -57,8 +57,12 @@ public class AltosTelemetry extends AltosRecord {  		String[] words = line.split("\\s+");  		int	i = 0; -		AltosParse.word (words[i++], "VERSION"); -		version = AltosParse.parse_int(words[i++]); +		if (words[i].equals("CALL")) { +			version = 0; +		} else { +			AltosParse.word (words[i++], "VERSION"); +			version = AltosParse.parse_int(words[i++]); +		}  		AltosParse.word (words[i++], "CALL");  		callsign = words[i++]; @@ -66,12 +70,19 @@ public class AltosTelemetry extends AltosRecord {  		AltosParse.word (words[i++], "SERIAL");  		serial = AltosParse.parse_int(words[i++]); -		AltosParse.word (words[i++], "FLIGHT"); -		flight = AltosParse.parse_int(words[i++]); +		if (version >= 2) { +			AltosParse.word (words[i++], "FLIGHT"); +			flight = AltosParse.parse_int(words[i++]); +		} else +			flight = 0;  		AltosParse.word(words[i++], "RSSI");  		rssi = AltosParse.parse_int(words[i++]); +		/* Older telemetry data had mis-computed RSSI value */ +		if (version <= 2) +			rssi = (rssi + 74) / 2 - 74; +  		AltosParse.word(words[i++], "STATUS");  		status = AltosParse.parse_hex(words[i++]); @@ -113,12 +124,17 @@ public class AltosTelemetry extends AltosRecord {  		AltosParse.word(words[i++], "gp:");  		ground_pres = AltosParse.parse_int(words[i++]); -		AltosParse.word(words[i++], "a+:"); -		accel_plus_g = AltosParse.parse_int(words[i++]); +		if (version >= 1) { +			AltosParse.word(words[i++], "a+:"); +			accel_plus_g = AltosParse.parse_int(words[i++]); -		AltosParse.word(words[i++], "a-:"); -		accel_minus_g = AltosParse.parse_int(words[i++]); +			AltosParse.word(words[i++], "a-:"); +			accel_minus_g = AltosParse.parse_int(words[i++]); +		} else { +			accel_plus_g = ground_accel; +			accel_minus_g = ground_accel + 530; +		} -		gps = new AltosGPS(words, i); +		gps = new AltosGPS(words, i, version);  	}  } diff --git a/ao-tools/altosui/AltosTelemetryReader.java b/ao-tools/altosui/AltosTelemetryReader.java index f1f6788c..a3402f9c 100644 --- a/ao-tools/altosui/AltosTelemetryReader.java +++ b/ao-tools/altosui/AltosTelemetryReader.java @@ -47,20 +47,25 @@ public class AltosTelemetryReader extends AltosReader {  		try {  			for (;;) {  				String line = AltosRecord.gets(input); -				if (line == null) +				if (line == null) {  					break; -				AltosTelemetry record = new AltosTelemetry(line); -				if (record == null) -					break; -				if (!saw_boost && record.state >= Altos.ao_flight_boost) -				{ -					saw_boost = true; -					boost_tick = record.tick;  				} -				records.add(record); +				try { +					AltosTelemetry record = new AltosTelemetry(line); +					if (record == null) +						break; +					if (!saw_boost && record.state >= Altos.ao_flight_boost) +					{ +						saw_boost = true; +						boost_tick = record.tick; +					} +					records.add(record); +				} catch (ParseException pe) { +					System.out.printf("parse exception %s\n", pe.getMessage()); +				}  			}  		} catch (IOException io) { -		} catch (ParseException pe) { +			System.out.printf("io exception\n");  		}  		record_iterator = records.iterator();  		try { diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 9fd47ea7..4f3b5dde 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -42,6 +42,8 @@ import altosui.AltosFlightStatusTableModel;  import altosui.AltosFlightInfoTableModel;  import altosui.AltosChannelMenu;  import altosui.AltosFlashUI; +import altosui.AltosLogfileChooser; +import altosui.AltosCSVUI;  import libaltosJNI.*; @@ -529,33 +531,12 @@ public class AltosUI extends JFrame {  	 * Replay a flight from telemetry data  	 */  	private void Replay() { -		JFileChooser	logfile_chooser = new JFileChooser(); - -		logfile_chooser.setDialogTitle("Select Flight Record File"); -		logfile_chooser.setFileFilter(new FileNameExtensionFilter("Flight data file", "eeprom", "telem")); -		logfile_chooser.setCurrentDirectory(AltosPreferences.logdir()); -		int returnVal = logfile_chooser.showOpenDialog(AltosUI.this); - -		if (returnVal == JFileChooser.APPROVE_OPTION) { -			File file = logfile_chooser.getSelectedFile(); -			if (file == null) -				System.out.println("No file selected?"); -			String	filename = file.getName(); -			try { -				FileInputStream	replay = new FileInputStream(file); -				DisplayThread	thread; -				if (filename.endsWith("eeprom")) -				    thread = new ReplayEepromThread(replay, filename); -				else -				    thread = new ReplayTelemetryThread(replay, filename); -				run_display(thread); -			} catch (FileNotFoundException ee) { -				JOptionPane.showMessageDialog(AltosUI.this, -							      filename, -							      "Cannot open telemetry file", -							      JOptionPane.ERROR_MESSAGE); -			} -		} +		AltosLogfileChooser chooser = new AltosLogfileChooser( +			AltosUI.this); +		AltosReader reader = chooser.runDialog(); +		if (reader != null) +			run_display(new ReplayThread(reader, +						     chooser.filename()));  	}  	/* Connect to TeleMetrum, either directly or through @@ -565,6 +546,14 @@ public class AltosUI extends JFrame {  		new AltosEepromDownload(AltosUI.this);  	} +	/* Load a flight log file and write out a CSV file containing +	 * all of the data in standard units +	 */ + +	private void ExportData() { +		new AltosCSVUI(AltosUI.this); +	} +  	/* Create the AltosUI menus  	 */  	private void createMenu() { @@ -603,6 +592,14 @@ public class AltosUI extends JFrame {  				});  			menu.add(item); +			item = new JMenuItem("Export Data",KeyEvent.VK_F); +			item.addActionListener(new ActionListener() { +					public void actionPerformed(ActionEvent e) { +						ExportData(); +					} +				}); +			menu.add(item); +  			item = new JMenuItem("Quit",KeyEvent.VK_Q);  			item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q,  								   ActionEvent.CTRL_MASK)); @@ -722,8 +719,67 @@ public class AltosUI extends JFrame {  		this.setJMenuBar(menubar);  	} + +	static String replace_extension(String input, String extension) { +		int dot = input.lastIndexOf("."); +		if (dot > 0) +			input = input.substring(0,dot); +		return input.concat(extension); +	} + +	static AltosReader open_logfile(String filename) { +		File file = new File (filename); +		try { +			FileInputStream in; + +			in = new FileInputStream(file); +			if (filename.endsWith("eeprom")) +				return new AltosEepromReader(in); +			else +				return new AltosTelemetryReader(in); +		} catch (FileNotFoundException fe) { +			System.out.printf("Cannot open '%s'\n", filename); +			return null; +		} +	} + +	static AltosCSV open_csv(String filename) { +		File file = new File (filename); +		try { +			return new AltosCSV(file); +		} catch (FileNotFoundException fe) { +			System.out.printf("Cannot open '%s'\n", filename); +			return null; +		} +	} + +	static void process_file(String input) { +		String output = replace_extension(input,".csv"); +		if (input.equals(output)) { +			System.out.printf("Not processing '%s'\n", input); +			return; +		} +		System.out.printf("Processing \"%s\" to \"%s\"\n", input, output); +		AltosReader reader = open_logfile(input); +		if (reader == null) +			return; +		AltosCSV writer = open_csv(output); +		if (writer == null) +			return; +		writer.write(reader); +		reader.close(); +		writer.close(); +	} +  	public static void main(final String[] args) { -		AltosUI altosui = new AltosUI(); -		altosui.setVisible(true); + +		/* Handle batch-mode */ +		if (args.length > 0) { +			for (int i = 0; i < args.length; i++) +				process_file(args[i]); +		} else { +			AltosUI altosui = new AltosUI(); +			altosui.setVisible(true); +		}  	}  }
\ No newline at end of file diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index d4d3ee7a..d3ecb889 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -8,6 +8,7 @@ CLASSFILES=\  	AltosConfigUI.class \  	AltosConvert.class \  	AltosCSV.class \ +	AltosCSVUI.class \  	AltosDebug.class \  	AltosEepromDownload.class \  	AltosEepromMonitor.class \ @@ -22,6 +23,7 @@ CLASSFILES=\  	AltosGreatCircle.class \  	AltosHexfile.class \  	AltosLog.class \ +	AltosLogfileChooser.class \  	AltosParse.class \  	AltosPreferences.class \  	AltosRecord.class \ diff --git a/src/Makefile.proto b/src/Makefile.proto index 8bc8b0e1..59a3b8a6 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -214,9 +214,11 @@ all: ../$(PROG)  ../altitude.h: make-altitude  	nickle $< > $@ -ao_product.h: ao-make-product.5c +ao_product.h: ao-make-product.5c always  	$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ +always: +  ao_product.rel: ao_product.c ao_product.h  	$(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< @@ -79,7 +79,7 @@ ao_alarm(uint16_t delay);  /* Yield the processor to another task */  void -ao_yield(void) _naked; +ao_yield(void) __naked;  /* Add a task to the run queue */  void @@ -139,7 +139,7 @@ ao_timer_set_adc_interval(uint8_t interval) __critical;  /* Timer interrupt */  void -ao_timer_isr(void) interrupt 9; +ao_timer_isr(void) __interrupt 9;  /* Initialize the timer */  void @@ -198,7 +198,7 @@ ao_adc_get(__xdata struct ao_adc *packet);  /* The A/D interrupt handler */  void -ao_adc_isr(void) interrupt 1; +ao_adc_isr(void) __interrupt 1;  /* Initialize the A/D converter */  void @@ -293,12 +293,13 @@ ao_led_init(uint8_t enable);   * ao_romconfig.c   */ -#define AO_ROMCONFIG_VERSION	1 +#define AO_ROMCONFIG_VERSION	2  extern __code __at (0x00a0) uint16_t ao_romconfig_version;  extern __code __at (0x00a2) uint16_t ao_romconfig_check;  extern __code __at (0x00a4) uint16_t ao_serial_number;  extern __code __at (0x00a6) uint32_t ao_radio_cal; +extern __code __at (0x00aa) uint8_t ao_usb_descriptors [];  /*   * ao_usb.c @@ -324,7 +325,7 @@ ao_usb_flush(void);  /* USB interrupt handler */  void -ao_usb_isr(void) interrupt 6; +ao_usb_isr(void) __interrupt 6;  /* Enable the USB controller */  void @@ -424,7 +425,7 @@ ao_dma_abort(uint8_t id);  /* DMA interrupt routine */  void -ao_dma_isr(void) interrupt 8; +ao_dma_isr(void) __interrupt 8;  /*   * ao_mutex.c @@ -563,6 +564,7 @@ struct ao_log_record {  			uint8_t		year;  			uint8_t		month;  			uint8_t		day; +			uint8_t		extra;  		} gps_date;  		struct {  			uint16_t	d0; @@ -572,7 +574,7 @@ struct ao_log_record {  };  /* Write a record to the eeprom log */ -void +uint8_t  ao_log_data(__xdata struct ao_log_record *log) __reentrant;  /* Flush the log */ @@ -720,10 +722,10 @@ ao_dbg_init(void);  #if HAS_SERIAL_1  void -ao_serial_rx1_isr(void) interrupt 3; +ao_serial_rx1_isr(void) __interrupt 3;  void -ao_serial_tx1_isr(void) interrupt 14; +ao_serial_tx1_isr(void) __interrupt 14;  char  ao_serial_getchar(void) __critical; @@ -859,7 +861,7 @@ extern __xdata uint8_t ao_radio_done;  extern __xdata uint8_t ao_radio_mutex;  void -ao_radio_general_isr(void) interrupt 16; +ao_radio_general_isr(void) __interrupt 16;  void  ao_radio_get(void); @@ -1008,7 +1010,7 @@ ao_rssi_init(uint8_t rssi_led);   * each instance of a product   */ -extern const uint8_t ao_usb_descriptors []; +extern __code __at(0x00aa) uint8_t ao_usb_descriptors [];  extern const char ao_version[];  extern const char ao_manufacturer[];  extern const char ao_product[]; diff --git a/src/ao_adc.c b/src/ao_adc.c index 50f96848..49d2519e 100644 --- a/src/ao_adc.c +++ b/src/ao_adc.c @@ -41,7 +41,7 @@ ao_adc_get(__xdata struct ao_adc *packet)  }  void -ao_adc_isr(void) interrupt 1 +ao_adc_isr(void) __interrupt 1  {  	uint8_t sequence;  	uint8_t	__xdata *a; diff --git a/src/ao_cmd.c b/src/ao_cmd.c index 4a68fba4..a54a2316 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -263,13 +263,12 @@ ao_cmd_register(__code struct ao_cmds *cmds)  }  void -ao_cmd(void *parameters) +ao_cmd(void)  {  	__xdata char	c;  	__xdata uint8_t cmd, cmds;  	__code struct ao_cmds * __xdata cs;  	void (*__xdata func)(void); -	(void) parameters;  	lex_echo = 1;  	for (;;) { diff --git a/src/ao_dma.c b/src/ao_dma.c index 110138b5..946666ab 100644 --- a/src/ao_dma.c +++ b/src/ao_dma.c @@ -112,7 +112,7 @@ ao_dma_abort(uint8_t id)  }  void -ao_dma_isr(void) interrupt 8 +ao_dma_isr(void) __interrupt 8  {  	uint8_t id, mask; diff --git a/src/ao_gps_report.c b/src/ao_gps_report.c index cceb79ff..7abc93f5 100644 --- a/src/ao_gps_report.c +++ b/src/ao_gps_report.c @@ -51,12 +51,12 @@ ao_gps_report(void)  		gps_log.u.gps_altitude.unused = 0xffff;  		ao_log_data(&gps_log);  		if (!date_reported && (gps_data.flags & AO_GPS_DATE_VALID)) { -			date_reported = 1;  			gps_log.type = AO_LOG_GPS_DATE;  			gps_log.u.gps_date.year = gps_data.year;  			gps_log.u.gps_date.month = gps_data.month;  			gps_log.u.gps_date.day = gps_data.day; -			ao_log_data(&gps_log); +			gps_log.u.gps_date.extra = 0; +			date_reported = ao_log_data(&gps_log);  		}  	}  } diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index ae8c7ef7..c822f7fa 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -422,6 +422,7 @@ gps_dump(void) __reentrant  	printf ("Time: %02d:%02d:%02d\n", ao_gps_data.hour, ao_gps_data.minute, ao_gps_data.second);  	printf ("Lat/Lon: %ld %ld\n", ao_gps_data.latitude, ao_gps_data.longitude);  	printf ("Alt: %d\n", ao_gps_data.altitude); +	printf ("Flags: 0x%x\n", ao_gps_data.flags);  	ao_mutex_put(&ao_gps_mutex);  } diff --git a/src/ao_log.c b/src/ao_log.c index d550d408..18bdb8c8 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -33,14 +33,16 @@ ao_log_csum(__xdata uint8_t *b) __reentrant  	return -sum;  } -void +uint8_t  ao_log_data(__xdata struct ao_log_record *log) __reentrant  { +	uint8_t wrote = 0;  	/* set checksum */  	log->csum = 0;  	log->csum = ao_log_csum((__xdata uint8_t *) log);  	ao_mutex_get(&ao_log_mutex); {  		if (ao_log_running) { +			wrote = 1;  			ao_ee_write(ao_log_current_pos,  				    (uint8_t *) log,  				    sizeof (struct ao_log_record)); @@ -51,6 +53,7 @@ ao_log_data(__xdata struct ao_log_record *log) __reentrant  				ao_log_running = 0;  		}  	} ao_mutex_put(&ao_log_mutex); +	return wrote;  }  void diff --git a/src/ao_product.c b/src/ao_product.c index f0eb4c07..82d6298f 100644 --- a/src/ao_product.c +++ b/src/ao_product.c @@ -28,7 +28,7 @@ const char ao_product[] = AO_iProduct_STRING;  #define LE_WORD(x)    ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8))  /* USB descriptors in one giant block of bytes */ -const uint8_t ao_usb_descriptors [] = +__code __at(0x00aa) uint8_t ao_usb_descriptors [] =  {  	/* Device descriptor */  	0x12, diff --git a/src/ao_radio.c b/src/ao_radio.c index 0849349e..f4a9d3b2 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -275,7 +275,7 @@ __xdata uint8_t ao_radio_done;  __xdata uint8_t ao_radio_mutex;  void -ao_radio_general_isr(void) interrupt 16 +ao_radio_general_isr(void) __interrupt 16  {  	S1CON &= ~0x03;  	if (RFIF & RFIF_IM_TIMEOUT) { diff --git a/src/ao_serial.c b/src/ao_serial.c index 3f103766..a48734c2 100644 --- a/src/ao_serial.c +++ b/src/ao_serial.c @@ -21,7 +21,7 @@ volatile __xdata struct ao_fifo	ao_usart1_rx_fifo;  volatile __xdata struct ao_fifo	ao_usart1_tx_fifo;  void -ao_serial_rx1_isr(void) interrupt 3 +ao_serial_rx1_isr(void) __interrupt 3  {  	if (!ao_fifo_full(ao_usart1_rx_fifo))  		ao_fifo_insert(ao_usart1_rx_fifo, U1DBUF); @@ -42,7 +42,7 @@ ao_serial_tx1_start(void)  }  void -ao_serial_tx1_isr(void) interrupt 14 +ao_serial_tx1_isr(void) __interrupt 14  {  	UTX1IF = 0;  	ao_serial_tx1_started = 0; diff --git a/src/ao_timer.c b/src/ao_timer.c index d1731475..c977fbc8 100644 --- a/src/ao_timer.c +++ b/src/ao_timer.c @@ -41,7 +41,7 @@ volatile __data uint8_t	ao_adc_interval = 1;  volatile __data uint8_t	ao_adc_count;  #endif -void ao_timer_isr(void) interrupt 9 +void ao_timer_isr(void) __interrupt 9  {  	++ao_tick_count;  #if HAS_ADC diff --git a/src/ao_usb.c b/src/ao_usb.c index f6e0fcf9..b55130f2 100644 --- a/src/ao_usb.c +++ b/src/ao_usb.c @@ -43,7 +43,7 @@ ao_usb_set_interrupts(void)   * so when we hook that up, fix this   */  void -ao_usb_isr(void) interrupt 6 +ao_usb_isr(void) __interrupt 6  {  	USBIF = 0;  	ao_usb_iif |= USBIIF; diff --git a/src/cc1111.h b/src/cc1111.h index e8302df2..20ed052a 100644 --- a/src/cc1111.h +++ b/src/cc1111.h @@ -40,16 +40,16 @@  #include <cc1110.h>  #include <stdint.h> -sfr at 0xA8 IEN0;		/* Interrupt Enable 0 Register */ +sfr __at 0xA8 IEN0;		/* Interrupt Enable 0 Register */ -sbit at 0xA8 RFTXRXIE;		/* RF TX/RX done interrupt enable */ -sbit at 0xA9 ADCIE;		/* ADC interrupt enable */ -sbit at 0xAA URX0IE;		/* USART0 RX interrupt enable */ -sbit at 0xAB URX1IE;		/* USART1 RX interrupt enable (shared with I2S RX) */ -sbit at 0xAB I2SRXIE;		/* I2S RX interrupt enable (shared with USART1 RX) */ -sbit at 0xAC ENCIE;		/* AES encryption/decryption interrupt enable */ -sbit at 0xAD STIE;		/* Sleep Timer interrupt enable */ -sbit at 0xAF EA;		/* Enable All */ +sbit __at 0xA8 RFTXRXIE;	/* RF TX/RX done interrupt enable */ +sbit __at 0xA9 ADCIE;		/* ADC interrupt enable */ +sbit __at 0xAA URX0IE;		/* USART0 RX interrupt enable */ +sbit __at 0xAB URX1IE;		/* USART1 RX interrupt enable (shared with I2S RX) */ +sbit __at 0xAB I2SRXIE;		/* I2S RX interrupt enable (shared with USART1 RX) */ +sbit __at 0xAC ENCIE;		/* AES encryption/decryption interrupt enable */ +sbit __at 0xAD STIE;		/* Sleep Timer interrupt enable */ +sbit __at 0xAF EA;		/* Enable All */  #define IEN0_EA			(1 << 7)  #define IEN0_STIE		(1 << 5) @@ -60,7 +60,7 @@ sbit at 0xAF EA;		/* Enable All */  #define IEN0_ADCIE		(1 << 1)  #define IEN0_RFTXRXIE		(1 << 0) -sfr at 0xB8 IEN1;		/* Interrupt Enable 1 Register */ +sfr __at 0xB8 IEN1;		/* Interrupt Enable 1 Register */  #define IEN1_P0IE		(1 << 5)	/* Port 0 interrupt enable */  #define IEN1_T4IE		(1 << 4)	/* Timer 4 interrupt enable */ @@ -70,7 +70,7 @@ sfr at 0xB8 IEN1;		/* Interrupt Enable 1 Register */  #define IEN1_DMAIE		(1 << 0)	/* DMA transfer interrupt enable */  /* IEN2 */ -sfr at 0x9A IEN2;		/* Interrupt Enable 2 Register */ +sfr __at 0x9A IEN2;		/* Interrupt Enable 2 Register */  #define IEN2_WDTIE		(1 << 5)	/* Watchdog timer interrupt enable */  #define IEN2_P1IE		(1 << 4)	/* Port 1 interrupt enable */ @@ -82,7 +82,7 @@ sfr at 0x9A IEN2;		/* Interrupt Enable 2 Register */  #define IEN2_RFIE		(1 << 0)	/* RF general interrupt enable */  /* CLKCON 0xC6 */ -sfr at 0xC6 CLKCON;		/* Clock Control */ +sfr __at 0xC6 CLKCON;		/* Clock Control */  #define CLKCON_OSC32K_RC	(1 << 7)  #define CLKCON_OSC32K_XTAL	(0 << 7) @@ -126,20 +126,20 @@ sfr at 0xC6 CLKCON;		/* Clock Control */  #define SLEEP_MODE_MASK		(3 << 0)  /* PCON 0x87 */ -sfr at 0x87 PCON;		/* Power Mode Control Register */ +sfr __at 0x87 PCON;		/* Power Mode Control Register */  #define PCON_IDLE		(1 << 0)  /*   * TCON   */ -sfr at 0x88 TCON;	/* CPU Interrupt Flag 1 */ +sfr __at 0x88 TCON;		/* CPU Interrupt Flag 1 */ -sbit at 0x8F URX1IF;	/* USART1 RX interrupt flag. Automatically cleared */ -sbit at 0x8F I2SRXIF;	/* I2S RX interrupt flag. Automatically cleared */ -sbit at 0x8D ADCIF;	/* ADC interrupt flag. Automatically cleared */ -sbit at 0x8B URX0IF;	/* USART0 RX interrupt flag. Automatically cleared */ -sbit at 0x89 RFTXRXIF;	/* RF TX/RX complete interrupt flag. Automatically cleared */ +sbit __at 0x8F URX1IF;		/* USART1 RX interrupt flag. Automatically cleared */ +sbit __at 0x8F I2SRXIF;		/* I2S RX interrupt flag. Automatically cleared */ +sbit __at 0x8D ADCIF;		/* ADC interrupt flag. Automatically cleared */ +sbit __at 0x8B URX0IF;		/* USART0 RX interrupt flag. Automatically cleared */ +sbit __at 0x89 RFTXRXIF;	/* RF TX/RX complete interrupt flag. Automatically cleared */  #define TCON_URX1IF	(1 << 7)  #define TCON_I2SRXIF	(1 << 7) @@ -150,10 +150,10 @@ sbit at 0x89 RFTXRXIF;	/* RF TX/RX complete interrupt flag. Automatically cleare  /*   * S0CON   */ -sfr at 0x98 S0CON;	/* CPU Interrupt Flag 2 */ +sfr __at 0x98 S0CON;	/* CPU Interrupt Flag 2 */ -sbit at 0x98 ENCIF_0;	/* AES interrupt 0. */ -sbit at 0x99 ENCIF_1;	/* AES interrupt 1. */ +sbit __at 0x98 ENCIF_0;	/* AES interrupt 0. */ +sbit __at 0x99 ENCIF_1;	/* AES interrupt 1. */  #define S0CON_ENCIF_1	(1 << 1)  #define S0CON_ENCIF_0	(1 << 0) @@ -161,7 +161,7 @@ sbit at 0x99 ENCIF_1;	/* AES interrupt 1. */  /*   * S1CON   */ -sfr at 0x9B S1CON;	/* CPU Interrupt Flag 3 */ +sfr __at 0x9B S1CON;	/* CPU Interrupt Flag 3 */  #define S1CON_RFIF_1	(1 << 1)  #define S1CON_RFIF_0	(1 << 0) @@ -169,15 +169,15 @@ sfr at 0x9B S1CON;	/* CPU Interrupt Flag 3 */  /*   * IRCON   */ -sfr at 0xC0 IRCON;	/* CPU Interrupt Flag 4 */ +sfr __at 0xC0 IRCON;	/* CPU Interrupt Flag 4 */ -sbit at 0xC0 DMAIF;	/* DMA complete interrupt flag */ -sbit at 0xC1 T1IF;	/* Timer 1 interrupt flag. Automatically cleared */ -sbit at 0xC2 T2IF;	/* Timer 2 interrupt flag. Automatically cleared */ -sbit at 0xC3 T3IF;	/* Timer 3 interrupt flag. Automatically cleared */ -sbit at 0xC4 T4IF;	/* Timer 4 interrupt flag. Automatically cleared */ -sbit at 0xC5 P0IF;	/* Port0 interrupt flag */ -sbit at 0xC7 STIF;	/* Sleep Timer interrupt flag */ +sbit __at 0xC0 DMAIF;	/* DMA complete interrupt flag */ +sbit __at 0xC1 T1IF;	/* Timer 1 interrupt flag. Automatically cleared */ +sbit __at 0xC2 T2IF;	/* Timer 2 interrupt flag. Automatically cleared */ +sbit __at 0xC3 T3IF;	/* Timer 3 interrupt flag. Automatically cleared */ +sbit __at 0xC4 T4IF;	/* Timer 4 interrupt flag. Automatically cleared */ +sbit __at 0xC5 P0IF;	/* Port0 interrupt flag */ +sbit __at 0xC7 STIF;	/* Sleep Timer interrupt flag */  #define IRCON_DMAIF	(1 << 0)	/* DMA complete interrupt flag */  #define IRCON_T1IF	(1 << 1)	/* Timer 1 interrupt flag. Automatically cleared */ @@ -190,15 +190,15 @@ sbit at 0xC7 STIF;	/* Sleep Timer interrupt flag */  /*   * IRCON2   */ -sfr at 0xE8 IRCON2;	/* CPU Interrupt Flag 5 */ +sfr __at 0xE8 IRCON2;	/* CPU Interrupt Flag 5 */ -sbit at 0xE8 USBIF;	/* USB interrupt flag (shared with Port2) */ -sbit at 0xE8 P2IF;	/* Port2 interrupt flag (shared with USB) */ -sbit at 0xE9 UTX0IF;	/* USART0 TX interrupt flag */ -sbit at 0xEA UTX1IF;	/* USART1 TX interrupt flag (shared with I2S TX) */ -sbit at 0xEA I2STXIF;	/* I2S TX interrupt flag (shared with USART1 TX) */ -sbit at 0xEB P1IF;	/* Port1 interrupt flag */ -sbit at 0xEC WDTIF;	/* Watchdog timer interrupt flag */ +sbit __at 0xE8 USBIF;	/* USB interrupt flag (shared with Port2) */ +sbit __at 0xE8 P2IF;	/* Port2 interrupt flag (shared with USB) */ +sbit __at 0xE9 UTX0IF;	/* USART0 TX interrupt flag */ +sbit __at 0xEA UTX1IF;	/* USART1 TX interrupt flag (shared with I2S TX) */ +sbit __at 0xEA I2STXIF;	/* I2S TX interrupt flag (shared with USART1 TX) */ +sbit __at 0xEB P1IF;	/* Port1 interrupt flag */ +sbit __at 0xEC WDTIF;	/* Watchdog timer interrupt flag */  #define IRCON2_USBIF	(1 << 0)	/* USB interrupt flag (shared with Port2) */  #define IRCON2_P2IF	(1 << 0)	/* Port2 interrupt flag (shared with USB) */ @@ -225,8 +225,8 @@ sbit at 0xEC WDTIF;	/* Watchdog timer interrupt flag */   * Priority = (IP1 << 1) | IP0. Higher priority interrupts served first   */ -sfr at 0xB9 IP1;	/* Interrupt Priority 1 */ -sfr at 0xA9 IP0;	/* Interrupt Priority 0 */ +sfr __at 0xB9 IP1;	/* Interrupt Priority 1 */ +sfr __at 0xA9 IP0;	/* Interrupt Priority 0 */  #define IP1_IPG5	(1 << 5)  #define IP1_IPG4	(1 << 4) @@ -286,13 +286,13 @@ sfr at 0xA9 IP0;	/* Interrupt Priority 0 */   */  /* Timer count */ -sfr at 0xCA T3CNT; -sfr at 0xEA T4CNT; +sfr __at 0xCA T3CNT; +sfr __at 0xEA T4CNT;  /* Timer control */ -sfr at 0xCB T3CTL; -sfr at 0xEB T4CTL; +sfr __at 0xCB T3CTL; +sfr __at 0xEB T4CTL;  #define TxCTL_DIV_1		(0 << 5)  #define TxCTL_DIV_2		(1 << 5) @@ -312,10 +312,10 @@ sfr at 0xEB T4CTL;  /* Timer 4 channel 0 compare control */ -sfr at 0xCC T3CCTL0; -sfr at 0xCE T3CCTL1; -sfr at 0xEC T4CCTL0; -sfr at 0xEE T4CCTL1; +sfr __at 0xCC T3CCTL0; +sfr __at 0xCE T3CCTL1; +sfr __at 0xEC T4CCTL0; +sfr __at 0xEE T4CCTL1;  #define TxCCTLy_IM			(1 << 6)  #define TxCCTLy_CMP_SET			(0 << 3) @@ -328,16 +328,16 @@ sfr at 0xEE T4CCTL1;  #define TxCCTLy_CMP_MODE_ENABLE		(1 << 2)  /* Timer compare value */ -sfr at 0xCD T3CC0; -sfr at 0xCF T3CC1; -sfr at 0xED T4CC0; -sfr at 0xEF T4CC1; +sfr __at 0xCD T3CC0; +sfr __at 0xCF T3CC1; +sfr __at 0xED T4CC0; +sfr __at 0xEF T4CC1;  /*   * Peripheral control   */ -sfr at 0xf1 PERCFG; +sfr __at 0xf1 PERCFG;  #define PERCFG_T1CFG_ALT_1      (0 << 6)  #define PERCFG_T1CFG_ALT_2      (1 << 6)  #define PERCFG_T1CFG_ALT_MASK   (1 << 6) | 
