diff options
| -rw-r--r-- | altosui/AltosConfigData.java | 109 | ||||
| -rw-r--r-- | altosui/AltosEepromBlock.java | 82 | ||||
| -rw-r--r-- | altosui/AltosEepromDownload.java | 230 | ||||
| -rw-r--r-- | altosui/AltosEepromRecord.java | 47 | ||||
| -rw-r--r-- | altosui/Makefile.am | 2 | 
5 files changed, 318 insertions, 152 deletions
diff --git a/altosui/AltosConfigData.java b/altosui/AltosConfigData.java new file mode 100644 index 00000000..8c32ed86 --- /dev/null +++ b/altosui/AltosConfigData.java @@ -0,0 +1,109 @@ +/* + * Copyright © 2011 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.*; + +import libaltosJNI.*; + +public class AltosConfigData implements Iterable<String> { + +	/* Version information */ +	String	manufacturer; +	String	product; +	String	version; +	int	serial; + +	/* Strings returned */ +	LinkedList<String>	lines; + +	/* Config information */ +	int	config_major; +	int	config_minor; +	int	main_deploy; +	int	apogee_delay; +	int	radio_channel; +	String	callsign; +	int	accel_cal_plus, accel_cal_minus; +	int	radio_calibration; +	int	flight_log_max; + + +	static String get_string(String line, String label) throws  ParseException { +		if (line.startsWith(label)) { +			String	quoted = line.substring(label.length()).trim(); + +			if (quoted.startsWith("\"")) +				quoted = quoted.substring(1); +			if (quoted.endsWith("\"")) +				quoted = quoted.substring(0,quoted.length()-1); +			return quoted; +		} +		throw new ParseException("mismatch", 0); +	} + +	static int get_int(String line, String label) throws NumberFormatException, ParseException { +		if (line.startsWith(label)) { +			String tail = line.substring(label.length()).trim(); +			String[] tokens = tail.split("\\s+"); +			if (tokens.length > 0) +				return  Integer.parseInt(tokens[0]); +		} +		throw new ParseException("mismatch", 0); +	} + +	public Iterator<String> iterator() { +		return lines.iterator(); +	} + +	public AltosConfigData(AltosSerial serial_line) throws InterruptedException, TimeoutException { +		serial_line.printf("c s\nv\n"); +		lines = new LinkedList<String>(); +		for (;;) { +			String line = serial_line.get_reply(5000); +			if (line == null) +				throw new TimeoutException(); +			if (line.contains("Syntax error")) +				continue; +			lines.add(line); +			try { serial = get_int(line, "serial-number"); } catch (Exception e) {} +			try { main_deploy = get_int(line, "Main deploy:"); } catch (Exception e) {} +			try { apogee_delay = get_int(line, "Apogee delay:"); } catch (Exception e) {} +			try { radio_channel = get_int(line, "Radio channel:"); } catch (Exception e) {} +			try { radio_calibration = get_int(line, "Radio cal:"); } catch (Exception e) {} +			try { flight_log_max = get_int(line, "Max flight log:"); } catch (Exception e) {} +			try { callsign = get_string(line, "Callsign:"); } catch (Exception e) {} +			try { version = get_string(line,"software-version"); } catch (Exception e) {} +			try { product = get_string(line,"product"); } catch (Exception e) {} + +			/* signals the end of the version info */ +			if (line.startsWith("software-version")) +				break; +		} +	} + +}
\ No newline at end of file diff --git a/altosui/AltosEepromBlock.java b/altosui/AltosEepromBlock.java new file mode 100644 index 00000000..0c1a4a92 --- /dev/null +++ b/altosui/AltosEepromBlock.java @@ -0,0 +1,82 @@ +/* + * Copyright © 2011 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.*; +import java.lang.reflect.Array; + +import libaltosJNI.*; + +public class AltosEepromBlock extends ArrayList<AltosEepromRecord> { +	boolean	has_flight; +	int	flight; +	boolean	has_state; +	int	state; +	boolean	has_date; +	int	year, month, day; + +	public AltosEepromBlock (AltosSerial serial_line, int block) throws TimeoutException, InterruptedException { +		int	addr; +		boolean	done = false; + +		has_flight = false; +		has_state = false; +		has_date = false; +		serial_line.printf("e %x\n", block); +		for (addr = 0; !done && addr < 0x100;) { +			try { +				AltosEepromRecord r = new AltosEepromRecord(serial_line, block * 256 + addr); + +				if (r.cmd == Altos.AO_LOG_FLIGHT) { +					flight = r.b; +					has_flight = true; +				} + +				/* Monitor state transitions to update display */ +				if (r.cmd == Altos.AO_LOG_STATE && r.a <= Altos.ao_flight_landed) { +					if (!has_state || r.a > state) { +						state = r.a; +						has_state = true; +					} +				} + +				if (r.cmd == Altos.AO_LOG_GPS_DATE) { +					year = 2000 + (r.a & 0xff); +					month = (r.a >> 8) & 0xff; +					day = (r.b & 0xff); +					has_date = true; +				} + +				if (r.cmd == Altos.AO_LOG_STATE && r.a == Altos.ao_flight_landed) +					done = true; +				add(addr / 8, r); +			} catch (ParseException pe) { +			} +			addr += 8; +		} +	} +}
\ No newline at end of file diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index e5ff766c..9a748710 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -32,182 +32,105 @@ import libaltosJNI.*;  public class AltosEepromDownload implements Runnable { -	static final String[] state_names = { -		"startup", -		"idle", -		"pad", -		"boost", -		"fast", -		"coast", -		"drogue", -		"main", -		"landed", -		"invalid", -	}; - -	int[] ParseHex(String line) { -		String[] tokens = line.split("\\s+"); -		int[] array = new int[tokens.length]; - -		for (int i = 0; i < tokens.length; i++) -			try { -				array[i] = Integer.parseInt(tokens[i], 16); -			} catch (NumberFormatException ne) { -				return null; -			} -		return array; -	} - -	int checksum(int[] line) { -		int	csum = 0x5a; -		for (int i = 1; i < line.length; i++) -			csum += line[i]; -		return csum & 0xff; -	} - -	void FlushPending(FileWriter file, LinkedList<String> pending) throws IOException { -		while (!pending.isEmpty()) { -			file.write(pending.remove()); -		} -	} -  	JFrame			frame;  	AltosDevice		device;  	AltosSerial		serial_line;  	boolean			remote;  	Thread			eeprom_thread;  	AltosEepromMonitor	monitor; +	int			serial = 0; +	int			flight = 0; +	int			year = 0, month = 0, day = 0; +	boolean			want_file = false; +	FileWriter		eeprom_file = null; +	LinkedList<String>	eeprom_pending = new LinkedList<String>(); +	AltosConfigData		config_data; + +	private void FlushPending() throws IOException { +		for (String s : config_data) { +			eeprom_file.write(s); +			eeprom_file.write('\n'); +		} -	void CaptureLog() throws IOException, InterruptedException, TimeoutException { -		int			serial = 0; -		int			block, state_block = 0; -		int			addr; -		int			flight = 0; -		int			year = 0, month = 0, day = 0; -		int			state = 0; -		boolean			done = false; -		boolean			want_file = false; -		boolean			any_valid; -		FileWriter		eeprom_file = null; -		AltosFile		eeprom_name; -		LinkedList<String>	eeprom_pending = new LinkedList<String>(); - -		serial_line.printf("\nc s\nv\n"); - -		/* Pull the serial number out of the version information */ +		for (String s : eeprom_pending) +			eeprom_file.write(s); +	} -		for (;;) { -			String	line = serial_line.get_reply(5000); +	private void CheckFile(boolean force) throws IOException { +		if (eeprom_file != null) +			return; +		if (force || (flight != 0 && want_file)) { +			AltosFile		eeprom_name; +			if (year != 0 && month != 0 && day != 0) +				eeprom_name = new AltosFile(year, month, day, serial, flight, "eeprom"); +			else +				eeprom_name = new AltosFile(serial, flight, "eeprom"); -			if (line == null) -				throw new TimeoutException(); -			if (line.startsWith("serial-number")) { -				try { -					serial = Integer.parseInt(line.substring(13).trim()); -				} catch (NumberFormatException ne) { -					serial = 0; -				} +			eeprom_file = new FileWriter(eeprom_name); +			if (eeprom_file != null) { +				monitor.set_file(eeprom_name.getName()); +				FlushPending(); +				eeprom_pending = null;  			} +		} +	} -			eeprom_pending.add(String.format("%s\n", line)); +	void CaptureLog(int start_block, int end_block) throws IOException, InterruptedException, TimeoutException { +		int			block, state_block = 0; +		int			state = 0; +		boolean			done = false; +		int			record; -			/* signals the end of the version info */ -			if (line.startsWith("software-version")) -				break; -		} +		config_data = new AltosConfigData(serial_line); +		serial = config_data.serial;  		if (serial == 0)  			throw new IOException("no serial number found");  		monitor.set_serial(serial);  		/* Now scan the eeprom, reading blocks of data and converting to .eeprom file form */ -		state = 0; state_block = 0; -		for (block = 0; !done && block < 511; block++) { -			serial_line.printf("e %x\n", block); -			any_valid = false; -			monitor.set_value(state_names[state], state, block - state_block); -			for (addr = 0; addr < 0x100;) { -				String	line = serial_line.get_reply(5000); -				if (line == null) -					throw new TimeoutException(); -				int[] values = ParseHex(line); - -				if (values == null) { -					System.out.printf("invalid line: %s\n", line); -					continue; -				} else if (values[0] != addr) { -					System.out.printf("data address out of sync at 0x%x\n", -							  block * 256 + values[0]); -				} else if (checksum(values) != 0) { -					System.out.printf("invalid checksum at 0x%x\n", -							  block * 256 + values[0]); -				} else { -					any_valid = true; -					int	cmd = values[1]; -					int	tick = values[3] + (values[4] << 8); -					int	a = values[5] + (values[6] << 8); -					int	b = values[7] + (values[8] << 8); +		state = 0; state_block = start_block; +		for (block = start_block; !done && block < end_block; block++) { +			monitor.set_value(Altos.state_to_string[state], state, block - state_block); -					if (cmd == Altos.AO_LOG_FLIGHT) { -						flight = b; -						monitor.set_flight(flight); -					} - -					/* Monitor state transitions to update display */ -					if (cmd == Altos.AO_LOG_STATE && a <= Altos.ao_flight_landed) { -						if (a > Altos.ao_flight_pad) -							want_file = true; -						if (a > state) -							state_block = block; -						state = a; -					} +			AltosEepromBlock	eeblock = new AltosEepromBlock(serial_line, block); +			if (eeblock.has_flight) { +				flight = eeblock.flight; +				monitor.set_flight(flight); +			} +			if (eeblock.has_date) { +				year = eeblock.year; +				month = eeblock.month; +				day = eeblock.day; +				want_file = true; +			} -					if (cmd == Altos.AO_LOG_GPS_DATE) { -						year = 2000 + (a & 0xff); -						month = (a >> 8) & 0xff; -						day = (b & 0xff); -						want_file = true; -					} +			if (eeblock.size() == 0 || +			    eeblock.has_state && eeblock.state == Altos.ao_flight_landed) +					done = true; -					if (eeprom_file == null) { -						if (serial != 0 && flight != 0 && want_file) { -							if (year != 0 && month != 0 && day != 0) -								eeprom_name = new AltosFile(year, month, day, serial, flight, "eeprom"); -							else -								eeprom_name = new AltosFile(serial, flight, "eeprom"); +			/* Monitor state transitions to update display */ +			if (eeblock.has_state) { +				if (eeblock.state > Altos.ao_flight_pad) +					want_file = true; +				if (eeblock.state > state) +					state = eeblock.state; +			} -							monitor.set_file(eeprom_name.getName()); -							eeprom_file = new FileWriter(eeprom_name); -							if (eeprom_file != null) { -								FlushPending(eeprom_file, eeprom_pending); -								eeprom_pending = null; -							} -						} -					} +			CheckFile(true); -					String log_line = String.format("%c %4x %4x %4x\n", -									cmd, tick, a, b); -					if (eeprom_file != null) -						eeprom_file.write(log_line); -					else -						eeprom_pending.add(log_line); +			for (record = 0; record < eeblock.size(); record++) { +				AltosEepromRecord r = eeblock.get(record); -					if (cmd == Altos.AO_LOG_STATE && a == Altos.ao_flight_landed) { -						done = true; -					} -				} -				addr += 8; -			} -			if (!any_valid) -				done = true; -		} -		if (eeprom_file == null) { -			eeprom_name = new AltosFile(serial,flight,"eeprom"); -			eeprom_file = new FileWriter(eeprom_name); -			if (eeprom_file != null) { -				FlushPending(eeprom_file, eeprom_pending); +				String log_line = String.format("%c %4x %4x %4x\n", +								r.cmd, r.tick, r.a, r.b); +				if (eeprom_file != null) +					eeprom_file.write(log_line); +				else +					eeprom_pending.add(log_line);  			}  		} +		CheckFile(true);  		if (eeprom_file != null) {  			eeprom_file.flush();  			eeprom_file.close(); @@ -235,6 +158,8 @@ public class AltosEepromDownload implements Runnable {  		SwingUtilities.invokeLater(r);  	} +	int	start_block, end_block; +  	public void run () {  		if (remote) {  			serial_line.set_radio(); @@ -243,7 +168,7 @@ public class AltosEepromDownload implements Runnable {  		}  		try { -			CaptureLog(); +			CaptureLog(start_block, end_block);  		} catch (IOException ee) {  			show_error (device.toShortString(),  				    ee.getLocalizedMessage()); @@ -271,6 +196,7 @@ public class AltosEepromDownload implements Runnable {  				serial_line = new AltosSerial(device);  				if (!device.matchProduct(AltosDevice.product_telemetrum))  					remote = true; +  				monitor = new AltosEepromMonitor(frame, Altos.ao_flight_boost, Altos.ao_flight_landed);  				monitor.addActionListener(new ActionListener() {  						public void actionPerformed(ActionEvent e) { @@ -280,6 +206,8 @@ public class AltosEepromDownload implements Runnable {  					});  				eeprom_thread = new Thread(this); +				start_block = 0; +				end_block = 0xfff;  				eeprom_thread.start();  			} catch (FileNotFoundException ee) {  				JOptionPane.showMessageDialog(frame, diff --git a/altosui/AltosEepromRecord.java b/altosui/AltosEepromRecord.java index 5a673817..e61a7159 100644 --- a/altosui/AltosEepromRecord.java +++ b/altosui/AltosEepromRecord.java @@ -26,7 +26,9 @@ import java.io.*;  import java.util.*;  import java.text.*;  import java.util.prefs.*; -import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.*; + +import libaltosJNI.*;  public class AltosEepromRecord {  	public int	cmd; @@ -36,6 +38,49 @@ public class AltosEepromRecord {  	public String	data;  	public boolean	tick_valid; +	int[] ParseHex(String line) { +		String[] tokens = line.split("\\s+"); +		int[] array = new int[tokens.length]; + +		for (int i = 0; i < tokens.length; i++) +			try { +				array[i] = Integer.parseInt(tokens[i], 16); +			} catch (NumberFormatException ne) { +				return null; +			} +		return array; +	} + +	int checksum(int[] line) { +		int	csum = 0x5a; +		for (int i = 1; i < line.length; i++) +			csum += line[i]; +		return csum & 0xff; +	} + +	public AltosEepromRecord (AltosSerial serial_line, int addr) +		throws TimeoutException, ParseException, InterruptedException { +		String	line = serial_line.get_reply(5000); +		if (line == null) +			throw new TimeoutException(); +		int[] values = ParseHex(line); + +		if (values == null) +			throw new ParseException(String.format("invalid line %s", line), 0); +		if (values[0] != (addr & 0xff)) +			throw new ParseException(String.format("data address out of sync at 0x%x", +							       addr), 0); +		if (checksum(values) != 0) +			throw new ParseException(String.format("invalid checksum at 0x%x", addr), 0); + +		cmd = values[1]; +		tick = values[3] + (values[4] << 8); +		a = values[5] + (values[6] << 8); +		b = values[7] + (values[8] << 8); +		data = null; +		tick_valid = true; +	} +  	public AltosEepromRecord (String line) {  		tick_valid = false;  		tick = 0; diff --git a/altosui/Makefile.am b/altosui/Makefile.am index e2ff55af..8cdd64cc 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -15,6 +15,7 @@ altosui_JAVA = \  	AltosAscent.java \  	AltosChannelMenu.java \  	AltosConfig.java \ +	AltosConfigData.java \  	AltosConfigUI.java \  	AltosConfigureUI.java \  	AltosConvert.java \ @@ -26,6 +27,7 @@ altosui_JAVA = \  	AltosDeviceDialog.java \  	AltosDevice.java \  	AltosDisplayThread.java \ +	AltosEepromBlock.java \  	AltosEepromDownload.java \  	AltosEepromMonitor.java \  	AltosEepromIterable.java \  | 
