Move altosui to the top level, placing libaltos inside it.
authorKeith Packard <keithp@keithp.com>
Wed, 24 Nov 2010 22:57:57 +0000 (14:57 -0800)
committerKeith Packard <keithp@keithp.com>
Wed, 24 Nov 2010 23:09:05 +0000 (15:09 -0800)
Signed-off-by: Keith Packard <keithp@keithp.com>
204 files changed:
altosui/.gitignore [new file with mode: 0644]
altosui/AltOS Package Configuration.pmdoc/01altosui-contents.xml [new file with mode: 0644]
altosui/AltOS Package Configuration.pmdoc/01altosui.xml [new file with mode: 0644]
altosui/AltOS Package Configuration.pmdoc/index.xml [new file with mode: 0644]
altosui/Altos.java [new file with mode: 0644]
altosui/AltosAscent.java [new file with mode: 0644]
altosui/AltosCRCException.java [new file with mode: 0644]
altosui/AltosCSV.java [new file with mode: 0644]
altosui/AltosCSVUI.java [new file with mode: 0644]
altosui/AltosChannelMenu.java [new file with mode: 0644]
altosui/AltosConfig.java [new file with mode: 0644]
altosui/AltosConfigUI.java [new file with mode: 0644]
altosui/AltosConfigureUI.java [new file with mode: 0644]
altosui/AltosConvert.java [new file with mode: 0644]
altosui/AltosDataChooser.java [new file with mode: 0644]
altosui/AltosDataPoint.java [new file with mode: 0644]
altosui/AltosDataPointReader.java [new file with mode: 0644]
altosui/AltosDebug.java [new file with mode: 0644]
altosui/AltosDescent.java [new file with mode: 0644]
altosui/AltosDevice.java [new file with mode: 0644]
altosui/AltosDeviceDialog.java [new file with mode: 0644]
altosui/AltosDisplayThread.java [new file with mode: 0644]
altosui/AltosEepromDownload.java [new file with mode: 0644]
altosui/AltosEepromIterable.java [new file with mode: 0644]
altosui/AltosEepromMonitor.java [new file with mode: 0644]
altosui/AltosEepromRecord.java [new file with mode: 0644]
altosui/AltosFile.java [new file with mode: 0644]
altosui/AltosFlash.java [new file with mode: 0644]
altosui/AltosFlashUI.java [new file with mode: 0644]
altosui/AltosFlightDisplay.java [new file with mode: 0644]
altosui/AltosFlightInfoTableModel.java [new file with mode: 0644]
altosui/AltosFlightReader.java [new file with mode: 0644]
altosui/AltosFlightStatus.java [new file with mode: 0644]
altosui/AltosFlightStatusTableModel.java [new file with mode: 0644]
altosui/AltosFlightUI.java [new file with mode: 0644]
altosui/AltosGPS.java [new file with mode: 0644]
altosui/AltosGraph.java [new file with mode: 0644]
altosui/AltosGraphTime.java [new file with mode: 0644]
altosui/AltosGraphUI.java [new file with mode: 0644]
altosui/AltosGreatCircle.java [new file with mode: 0644]
altosui/AltosHexfile.java [new file with mode: 0644]
altosui/AltosIgnite.java [new file with mode: 0644]
altosui/AltosIgniteUI.java [new file with mode: 0644]
altosui/AltosInfoTable.java [new file with mode: 0644]
altosui/AltosKML.java [new file with mode: 0644]
altosui/AltosLanded.java [new file with mode: 0644]
altosui/AltosLed.java [new file with mode: 0644]
altosui/AltosLights.java [new file with mode: 0644]
altosui/AltosLine.java [new file with mode: 0644]
altosui/AltosLog.java [new file with mode: 0644]
altosui/AltosPad.java [new file with mode: 0644]
altosui/AltosParse.java [new file with mode: 0644]
altosui/AltosPreferences.java [new file with mode: 0644]
altosui/AltosReader.java [new file with mode: 0644]
altosui/AltosRecord.java [new file with mode: 0644]
altosui/AltosRecordIterable.java [new file with mode: 0644]
altosui/AltosReplayReader.java [new file with mode: 0644]
altosui/AltosRomconfig.java [new file with mode: 0644]
altosui/AltosRomconfigUI.java [new file with mode: 0644]
altosui/AltosSerial.java [new file with mode: 0644]
altosui/AltosSerialInUseException.java [new file with mode: 0644]
altosui/AltosSerialMonitor.java [new file with mode: 0644]
altosui/AltosSiteMap.java [new file with mode: 0644]
altosui/AltosSiteMapCache.java [new file with mode: 0644]
altosui/AltosSiteMapTile.java [new file with mode: 0644]
altosui/AltosState.java [new file with mode: 0644]
altosui/AltosTelemetry.java [new file with mode: 0644]
altosui/AltosTelemetryIterable.java [new file with mode: 0644]
altosui/AltosTelemetryReader.java [new file with mode: 0644]
altosui/AltosUI.app/Contents/Info.plist [new file with mode: 0644]
altosui/AltosUI.app/Contents/MacOS/JavaApplicationStub [new file with mode: 0755]
altosui/AltosUI.app/Contents/PkgInfo [new file with mode: 0644]
altosui/AltosUI.app/Contents/Resources/AltosUIIcon.icns [new file with mode: 0644]
altosui/AltosUI.java [new file with mode: 0644]
altosui/AltosVoice.java [new file with mode: 0644]
altosui/AltosWriter.java [new file with mode: 0644]
altosui/GrabNDrag.java [new file with mode: 0644]
altosui/Instdrv/NSIS/Contrib/InstDrv/Example.nsi [new file with mode: 0644]
altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv-Test.exe [new file with mode: 0644]
altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.c [new file with mode: 0644]
altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsp [new file with mode: 0644]
altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsw [new file with mode: 0644]
altosui/Instdrv/NSIS/Contrib/InstDrv/Readme.txt [new file with mode: 0644]
altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.inf [new file with mode: 0644]
altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.sys [new file with mode: 0644]
altosui/Instdrv/NSIS/Plugins/InstDrv.dll [new file with mode: 0644]
altosui/Makefile-standalone [new file with mode: 0644]
altosui/Makefile.am [new file with mode: 0644]
altosui/altos-windows.nsi [new file with mode: 0644]
altosui/altosui-fat [new file with mode: 0755]
altosui/altosui.1 [new file with mode: 0644]
altosui/altusmetrum.jpg [new file with mode: 0644]
altosui/libaltos/.gitignore [new file with mode: 0644]
altosui/libaltos/Makefile-standalone [new file with mode: 0644]
altosui/libaltos/Makefile.am [new file with mode: 0644]
altosui/libaltos/altos.dll [new file with mode: 0755]
altosui/libaltos/cjnitest.c [new file with mode: 0644]
altosui/libaltos/libaltos.c [new file with mode: 0644]
altosui/libaltos/libaltos.dylib [new file with mode: 0755]
altosui/libaltos/libaltos.h [new file with mode: 0644]
altosui/libaltos/libaltos.i0 [new file with mode: 0644]
ao-tools/Makefile.am
ao-tools/altosui/.gitignore [deleted file]
ao-tools/altosui/AltOS Package Configuration.pmdoc/01altosui-contents.xml [deleted file]
ao-tools/altosui/AltOS Package Configuration.pmdoc/01altosui.xml [deleted file]
ao-tools/altosui/AltOS Package Configuration.pmdoc/index.xml [deleted file]
ao-tools/altosui/Altos.java [deleted file]
ao-tools/altosui/AltosAscent.java [deleted file]
ao-tools/altosui/AltosCRCException.java [deleted file]
ao-tools/altosui/AltosCSV.java [deleted file]
ao-tools/altosui/AltosCSVUI.java [deleted file]
ao-tools/altosui/AltosChannelMenu.java [deleted file]
ao-tools/altosui/AltosConfig.java [deleted file]
ao-tools/altosui/AltosConfigUI.java [deleted file]
ao-tools/altosui/AltosConfigureUI.java [deleted file]
ao-tools/altosui/AltosConvert.java [deleted file]
ao-tools/altosui/AltosDataChooser.java [deleted file]
ao-tools/altosui/AltosDataPoint.java [deleted file]
ao-tools/altosui/AltosDataPointReader.java [deleted file]
ao-tools/altosui/AltosDebug.java [deleted file]
ao-tools/altosui/AltosDescent.java [deleted file]
ao-tools/altosui/AltosDevice.java [deleted file]
ao-tools/altosui/AltosDeviceDialog.java [deleted file]
ao-tools/altosui/AltosDisplayThread.java [deleted file]
ao-tools/altosui/AltosEepromDownload.java [deleted file]
ao-tools/altosui/AltosEepromIterable.java [deleted file]
ao-tools/altosui/AltosEepromMonitor.java [deleted file]
ao-tools/altosui/AltosEepromRecord.java [deleted file]
ao-tools/altosui/AltosFile.java [deleted file]
ao-tools/altosui/AltosFlash.java [deleted file]
ao-tools/altosui/AltosFlashUI.java [deleted file]
ao-tools/altosui/AltosFlightDisplay.java [deleted file]
ao-tools/altosui/AltosFlightInfoTableModel.java [deleted file]
ao-tools/altosui/AltosFlightReader.java [deleted file]
ao-tools/altosui/AltosFlightStatus.java [deleted file]
ao-tools/altosui/AltosFlightStatusTableModel.java [deleted file]
ao-tools/altosui/AltosFlightUI.java [deleted file]
ao-tools/altosui/AltosGPS.java [deleted file]
ao-tools/altosui/AltosGraph.java [deleted file]
ao-tools/altosui/AltosGraphTime.java [deleted file]
ao-tools/altosui/AltosGraphUI.java [deleted file]
ao-tools/altosui/AltosGreatCircle.java [deleted file]
ao-tools/altosui/AltosHexfile.java [deleted file]
ao-tools/altosui/AltosIgnite.java [deleted file]
ao-tools/altosui/AltosIgniteUI.java [deleted file]
ao-tools/altosui/AltosInfoTable.java [deleted file]
ao-tools/altosui/AltosKML.java [deleted file]
ao-tools/altosui/AltosLanded.java [deleted file]
ao-tools/altosui/AltosLed.java [deleted file]
ao-tools/altosui/AltosLights.java [deleted file]
ao-tools/altosui/AltosLine.java [deleted file]
ao-tools/altosui/AltosLog.java [deleted file]
ao-tools/altosui/AltosPad.java [deleted file]
ao-tools/altosui/AltosParse.java [deleted file]
ao-tools/altosui/AltosPreferences.java [deleted file]
ao-tools/altosui/AltosReader.java [deleted file]
ao-tools/altosui/AltosRecord.java [deleted file]
ao-tools/altosui/AltosRecordIterable.java [deleted file]
ao-tools/altosui/AltosReplayReader.java [deleted file]
ao-tools/altosui/AltosRomconfig.java [deleted file]
ao-tools/altosui/AltosRomconfigUI.java [deleted file]
ao-tools/altosui/AltosSerial.java [deleted file]
ao-tools/altosui/AltosSerialInUseException.java [deleted file]
ao-tools/altosui/AltosSerialMonitor.java [deleted file]
ao-tools/altosui/AltosSiteMap.java [deleted file]
ao-tools/altosui/AltosSiteMapCache.java [deleted file]
ao-tools/altosui/AltosSiteMapTile.java [deleted file]
ao-tools/altosui/AltosState.java [deleted file]
ao-tools/altosui/AltosTelemetry.java [deleted file]
ao-tools/altosui/AltosTelemetryIterable.java [deleted file]
ao-tools/altosui/AltosTelemetryReader.java [deleted file]
ao-tools/altosui/AltosUI.app/Contents/Info.plist [deleted file]
ao-tools/altosui/AltosUI.app/Contents/MacOS/JavaApplicationStub [deleted file]
ao-tools/altosui/AltosUI.app/Contents/PkgInfo [deleted file]
ao-tools/altosui/AltosUI.app/Contents/Resources/AltosUIIcon.icns [deleted file]
ao-tools/altosui/AltosUI.java [deleted file]
ao-tools/altosui/AltosVoice.java [deleted file]
ao-tools/altosui/AltosWriter.java [deleted file]
ao-tools/altosui/GrabNDrag.java [deleted file]
ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/Example.nsi [deleted file]
ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv-Test.exe [deleted file]
ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.c [deleted file]
ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsp [deleted file]
ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsw [deleted file]
ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/Readme.txt [deleted file]
ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.inf [deleted file]
ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.sys [deleted file]
ao-tools/altosui/Instdrv/NSIS/Plugins/InstDrv.dll [deleted file]
ao-tools/altosui/Makefile-standalone [deleted file]
ao-tools/altosui/Makefile.am [deleted file]
ao-tools/altosui/altos-windows.nsi [deleted file]
ao-tools/altosui/altosui-fat [deleted file]
ao-tools/altosui/altosui.1 [deleted file]
ao-tools/altosui/altusmetrum.jpg [deleted file]
ao-tools/libaltos/.gitignore [deleted file]
ao-tools/libaltos/Makefile-standalone [deleted file]
ao-tools/libaltos/Makefile.am [deleted file]
ao-tools/libaltos/altos.dll [deleted file]
ao-tools/libaltos/cjnitest.c [deleted file]
ao-tools/libaltos/libaltos.c [deleted file]
ao-tools/libaltos/libaltos.dylib [deleted file]
ao-tools/libaltos/libaltos.h [deleted file]
ao-tools/libaltos/libaltos.i0 [deleted file]
configure.ac

diff --git a/altosui/.gitignore b/altosui/.gitignore
new file mode 100644 (file)
index 0000000..89be1d5
--- /dev/null
@@ -0,0 +1,19 @@
+windows/
+linux/
+macosx/
+fat/
+Manifest.txt
+Manifest-fat.txt
+libaltosJNI
+classes
+altosui
+altosui-test
+classaltosui.stamp
+Altos-Linux-*.tar.bz2
+Altos-Mac-*.zip
+Altos-Windows-*.exe
+*.dll
+*.dylib
+*.so
+*.jar
+*.class
diff --git a/altosui/AltOS Package Configuration.pmdoc/01altosui-contents.xml b/altosui/AltOS Package Configuration.pmdoc/01altosui-contents.xml
new file mode 100644 (file)
index 0000000..18e00fe
--- /dev/null
@@ -0,0 +1 @@
+<pkg-contents spec="1.12"><f n="AltosUI.app" o="keithp" g="keithp" p="16877" pt="/Users/keithp/altos/ao-tools/altosui/AltosUI.app" m="false" t="file"><f n="Contents" o="keithp" g="keithp" p="16877"><f n="Info.plist" o="keithp" g="keithp" p="33188"/><f n="MacOS" o="keithp" g="keithp" p="16877"><f n="JavaApplicationStub" o="keithp" g="keithp" p="33133"/></f><f n="PkgInfo" o="keithp" g="keithp" p="33188"/><f n="Resources" o="keithp" g="keithp" p="16877"><f n="AltosUIIcon.icns" o="keithp" g="keithp" p="33188"/><f n="Java" o="keithp" g="keithp" p="16877"/></f></f></f></pkg-contents>
\ No newline at end of file
diff --git a/altosui/AltOS Package Configuration.pmdoc/01altosui.xml b/altosui/AltOS Package Configuration.pmdoc/01altosui.xml
new file mode 100644 (file)
index 0000000..6170931
--- /dev/null
@@ -0,0 +1 @@
+<pkgref spec="1.12" uuid="C5762664-2F26-4536-94C4-56F0FBC08D1A"><config><identifier>org.altusmetrum.altosUi.AltosUI.pkg</identifier><version>0.7</version><description></description><post-install type="none"/><installFrom relative="true" mod="true">AltosUI.app</installFrom><installTo mod="true" relocatable="true">/Applications/AltosUI.app</installTo><flags><followSymbolicLinks/></flags><packageStore type="internal"></packageStore><mod>installTo.path</mod><mod>installFrom.isRelativeType</mod><mod>version</mod><mod>parent</mod><mod>requireAuthorization</mod><mod>installTo</mod></config><contents><file-list>01altosui-contents.xml</file-list><filter>/CVS$</filter><filter>/\.svn$</filter><filter>/\.cvsignore$</filter><filter>/\.cvspass$</filter><filter>/\.DS_Store$</filter></contents></pkgref>
\ No newline at end of file
diff --git a/altosui/AltOS Package Configuration.pmdoc/index.xml b/altosui/AltOS Package Configuration.pmdoc/index.xml
new file mode 100644 (file)
index 0000000..fabe54a
--- /dev/null
@@ -0,0 +1 @@
+<pkmkdoc spec="1.12"><properties><title>AltOS UI</title><build>/Users/keithp/altos/ao-tools/altosui/AltosUI.pkg</build><organization>org.altusmetrum</organization><userSees ui="both"/><min-target os="3"/><domain system="true" user="true"/></properties><distribution><versions min-spec="1.000000"/><scripts></scripts></distribution><description>Install AltOS User Interface</description><contents><choice title="AltosUI" id="choice0" starts_selected="true" starts_enabled="true" starts_hidden="false"><pkgref id="org.altusmetrum.altosUi.AltosUI.pkg"/></choice></contents><resources bg-scale="tofit" bg-align="center"><locale lang="en"><resource relative="true" mod="true" type="background">altusmetrum.jpg</resource></locale></resources><flags/><item type="file">01altosui.xml</item><mod>properties.anywhereDomain</mod><mod>properties.title</mod><mod>properties.customizeOption</mod><mod>description</mod><mod>properties.userDomain</mod><mod>properties.systemDomain</mod></pkmkdoc>
\ No newline at end of file
diff --git a/altosui/Altos.java b/altosui/Altos.java
new file mode 100644 (file)
index 0000000..8ee94e0
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * 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.util.*;
+import java.text.*;
+
+public class Altos {
+       /* EEProm command letters */
+       static final int AO_LOG_FLIGHT = 'F';
+       static final int AO_LOG_SENSOR = 'A';
+       static final int AO_LOG_TEMP_VOLT = 'T';
+       static final int AO_LOG_DEPLOY = 'D';
+       static final int AO_LOG_STATE = 'S';
+       static final int AO_LOG_GPS_TIME = 'G';
+       static final int AO_LOG_GPS_LAT = 'N';
+       static final int AO_LOG_GPS_LON = 'W';
+       static final int AO_LOG_GPS_ALT = 'H';
+       static final int AO_LOG_GPS_SAT = 'V';
+       static final int AO_LOG_GPS_DATE = 'Y';
+
+       /* Added for header fields in eeprom files */
+       static final int AO_LOG_CONFIG_VERSION = 1000;
+       static final int AO_LOG_MAIN_DEPLOY = 1001;
+       static final int AO_LOG_APOGEE_DELAY = 1002;
+       static final int AO_LOG_RADIO_CHANNEL = 1003;
+       static final int AO_LOG_CALLSIGN = 1004;
+       static final int AO_LOG_ACCEL_CAL = 1005;
+       static final int AO_LOG_RADIO_CAL = 1006;
+       static final int AO_LOG_MANUFACTURER = 1007;
+       static final int AO_LOG_PRODUCT = 1008;
+       static final int AO_LOG_SERIAL_NUMBER = 1009;
+       static final int AO_LOG_SOFTWARE_VERSION = 1010;
+
+       /* Added to flag invalid records */
+       static final int AO_LOG_INVALID = -1;
+
+       /* Flight state numbers and names */
+       static final int ao_flight_startup = 0;
+       static final int ao_flight_idle = 1;
+       static final int ao_flight_pad = 2;
+       static final int ao_flight_boost = 3;
+       static final int ao_flight_fast = 4;
+       static final int ao_flight_coast = 5;
+       static final int ao_flight_drogue = 6;
+       static final int ao_flight_main = 7;
+       static final int ao_flight_landed = 8;
+       static final int ao_flight_invalid = 9;
+
+       static HashMap<String,Integer>  string_to_state = new HashMap<String,Integer>();
+
+       static boolean map_initialized = false;
+
+       static final int tab_elt_pad = 5;
+
+       static final Font label_font = new Font("Dialog", Font.PLAIN, 22);
+       static final Font value_font = new Font("Monospaced", Font.PLAIN, 22);
+       static final Font status_font = new Font("SansSerif", Font.BOLD, 24);
+
+       static final int text_width = 16;
+
+       static void initialize_map()
+       {
+               string_to_state.put("startup", ao_flight_startup);
+               string_to_state.put("idle", ao_flight_idle);
+               string_to_state.put("pad", ao_flight_pad);
+               string_to_state.put("boost", ao_flight_boost);
+               string_to_state.put("fast", ao_flight_fast);
+               string_to_state.put("coast", ao_flight_coast);
+               string_to_state.put("drogue", ao_flight_drogue);
+               string_to_state.put("main", ao_flight_main);
+               string_to_state.put("landed", ao_flight_landed);
+               string_to_state.put("invalid", ao_flight_invalid);
+               map_initialized = true;
+       }
+
+       static String[] state_to_string = {
+               "startup",
+               "idle",
+               "pad",
+               "boost",
+               "fast",
+               "coast",
+               "drogue",
+               "main",
+               "landed",
+               "invalid",
+       };
+
+       static public int state(String state) {
+               if (!map_initialized)
+                       initialize_map();
+               if (string_to_state.containsKey(state))
+                       return string_to_state.get(state);
+               return ao_flight_invalid;
+       }
+
+       static public String state_name(int state) {
+               if (state < 0 || state_to_string.length <= state)
+                       return "invalid";
+               return state_to_string[state];
+       }
+
+       static final int AO_GPS_VALID = (1 << 4);
+       static final int AO_GPS_RUNNING = (1 << 5);
+       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;
+       }
+
+       static String replace_extension(String input, String extension) {
+               int dot = input.lastIndexOf(".");
+               if (dot > 0)
+                       input = input.substring(0,dot);
+               return input.concat(extension);
+       }
+}
diff --git a/altosui/AltosAscent.java b/altosui/AltosAscent.java
new file mode 100644 (file)
index 0000000..64bdcf3
--- /dev/null
@@ -0,0 +1,335 @@
+/*
+ * 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;
+
+public class AltosAscent extends JComponent implements AltosFlightDisplay {
+       GridBagLayout   layout;
+
+       public class AscentStatus {
+               JLabel          label;
+               JTextField      value;
+               AltosLights     lights;
+
+               void show(AltosState state, int crc_errors) {}
+               void reset() {
+                       value.setText("");
+                       lights.set(false);
+               }
+
+               public AscentStatus (GridBagLayout layout, int y, String text) {
+                       GridBagConstraints      c = new GridBagConstraints();
+                       c.weighty = 1;
+
+                       lights = new AltosLights();
+                       c.gridx = 0; c.gridy = y;
+                       c.anchor = GridBagConstraints.CENTER;
+                       c.fill = GridBagConstraints.VERTICAL;
+                       c.weightx = 0;
+                       layout.setConstraints(lights, c);
+                       add(lights);
+
+                       label = new JLabel(text);
+                       label.setFont(Altos.label_font);
+                       label.setHorizontalAlignment(SwingConstants.LEFT);
+                       c.gridx = 1; c.gridy = y;
+                       c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
+                       c.anchor = GridBagConstraints.WEST;
+                       c.fill = GridBagConstraints.VERTICAL;
+                       c.weightx = 0;
+                       layout.setConstraints(label, c);
+                       add(label);
+
+                       value = new JTextField(Altos.text_width);
+                       value.setFont(Altos.value_font);
+                       value.setHorizontalAlignment(SwingConstants.RIGHT);
+                       c.gridx = 2; c.gridy = y;
+                       c.gridwidth = 2;
+                       c.anchor = GridBagConstraints.WEST;
+                       c.fill = GridBagConstraints.BOTH;
+                       c.weightx = 1;
+                       layout.setConstraints(value, c);
+                       add(value);
+
+               }
+       }
+
+       public class AscentValue {
+               JLabel          label;
+               JTextField      value;
+               void show(AltosState state, int crc_errors) {}
+
+               void reset() {
+                       value.setText("");
+               }
+               public AscentValue (GridBagLayout layout, int y, String text) {
+                       GridBagConstraints      c = new GridBagConstraints();
+                       c.weighty = 1;
+
+                       label = new JLabel(text);
+                       label.setFont(Altos.label_font);
+                       label.setHorizontalAlignment(SwingConstants.LEFT);
+                       c.gridx = 1; c.gridy = y;
+                       c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
+                       c.anchor = GridBagConstraints.WEST;
+                       c.fill = GridBagConstraints.VERTICAL;
+                       c.weightx = 0;
+                       layout.setConstraints(label, c);
+                       add(label);
+
+                       value = new JTextField(Altos.text_width);
+                       value.setFont(Altos.value_font);
+                       value.setHorizontalAlignment(SwingConstants.RIGHT);
+                       c.gridx = 2; c.gridy = y;
+                       c.anchor = GridBagConstraints.WEST;
+                       c.fill = GridBagConstraints.BOTH;
+                       c.gridwidth = 2;
+                       c.weightx = 1;
+                       layout.setConstraints(value, c);
+                       add(value);
+               }
+       }
+
+       public class AscentValueHold {
+               JLabel          label;
+               JTextField      value;
+               JTextField      max_value;
+               double          max;
+
+               void show(AltosState state, int crc_errors) {}
+
+               void reset() {
+                       value.setText("");
+                       max_value.setText("");
+                       max = 0;
+               }
+
+               void show(String format, double v) {
+                       value.setText(String.format(format, v));
+                       if (v > max) {
+                               max_value.setText(String.format(format, v));
+                               max = v;
+                       }
+               }
+               public AscentValueHold (GridBagLayout layout, int y, String text) {
+                       GridBagConstraints      c = new GridBagConstraints();
+                       c.weighty = 1;
+
+                       label = new JLabel(text);
+                       label.setFont(Altos.label_font);
+                       label.setHorizontalAlignment(SwingConstants.LEFT);
+                       c.gridx = 1; c.gridy = y;
+                       c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
+                       c.anchor = GridBagConstraints.WEST;
+                       c.fill = GridBagConstraints.VERTICAL;
+                       c.weightx = 0;
+                       layout.setConstraints(label, c);
+                       add(label);
+
+                       value = new JTextField(Altos.text_width);
+                       value.setFont(Altos.value_font);
+                       value.setHorizontalAlignment(SwingConstants.RIGHT);
+                       c.gridx = 2; c.gridy = y;
+                       c.anchor = GridBagConstraints.EAST;
+                       c.fill = GridBagConstraints.BOTH;
+                       c.weightx = 1;
+                       layout.setConstraints(value, c);
+                       add(value);
+
+                       max_value = new JTextField(Altos.text_width);
+                       max_value.setFont(Altos.value_font);
+                       max_value.setHorizontalAlignment(SwingConstants.RIGHT);
+                       c.gridx = 3; c.gridy = y;
+                       c.anchor = GridBagConstraints.EAST;
+                       c.fill = GridBagConstraints.BOTH;
+                       c.weightx = 1;
+                       layout.setConstraints(max_value, c);
+                       add(max_value);
+               }
+       }
+
+
+       class Height extends AscentValueHold {
+               void show (AltosState state, int crc_errors) {
+                       show("%6.0f m", state.height);
+               }
+               public Height (GridBagLayout layout, int y) {
+                       super (layout, y, "Height");
+               }
+       }
+
+       Height  height;
+
+       class Speed extends AscentValueHold {
+               void show (AltosState state, int crc_errors) {
+                       double speed = state.speed;
+                       if (!state.ascent)
+                               speed = state.baro_speed;
+                       show("%6.0f m/s", speed);
+               }
+               public Speed (GridBagLayout layout, int y) {
+                       super (layout, y, "Speed");
+               }
+       }
+
+       Speed   speed;
+
+       class Accel extends AscentValueHold {
+               void show (AltosState state, int crc_errors) {
+                       show("%6.0f m/s²", state.acceleration);
+               }
+               public Accel (GridBagLayout layout, int y) {
+                       super (layout, y, "Acceleration");
+               }
+       }
+
+       Accel   accel;
+
+       String pos(double p, String pos, String neg) {
+               String  h = pos;
+               if (p < 0) {
+                       h = neg;
+                       p = -p;
+               }
+               int deg = (int) Math.floor(p);
+               double min = (p - Math.floor(p)) * 60.0;
+               return String.format("%s %4d° %9.6f", h, deg, min);
+       }
+
+       class Apogee extends AscentStatus {
+               void show (AltosState state, int crc_errors) {
+                       value.setText(String.format("%4.2f V", state.drogue_sense));
+                       lights.set(state.drogue_sense > 3.2);
+               }
+               public Apogee (GridBagLayout layout, int y) {
+                       super(layout, y, "Apogee Igniter Voltage");
+               }
+       }
+
+       Apogee apogee;
+
+       class Main extends AscentStatus {
+               void show (AltosState state, int crc_errors) {
+                       value.setText(String.format("%4.2f V", state.main_sense));
+                       lights.set(state.main_sense > 3.2);
+               }
+               public Main (GridBagLayout layout, int y) {
+                       super(layout, y, "Main Igniter Voltage");
+               }
+       }
+
+       Main main;
+
+       class Lat extends AscentValue {
+               void show (AltosState state, int crc_errors) {
+                       if (state.gps != null)
+                               value.setText(pos(state.gps.lat,"N", "S"));
+                       else
+                               value.setText("???");
+               }
+               public Lat (GridBagLayout layout, int y) {
+                       super (layout, y, "Latitude");
+               }
+       }
+
+       Lat lat;
+
+       class Lon extends AscentValue {
+               void show (AltosState state, int crc_errors) {
+                       if (state.gps != null)
+                               value.setText(pos(state.gps.lon,"E", "W"));
+                       else
+                               value.setText("???");
+               }
+               public Lon (GridBagLayout layout, int y) {
+                       super (layout, y, "Longitude");
+               }
+       }
+
+       Lon lon;
+
+       public void reset() {
+               lat.reset();
+               lon.reset();
+               main.reset();
+               apogee.reset();
+               height.reset();
+               speed.reset();
+               accel.reset();
+       }
+
+       public void show(AltosState state, int crc_errors) {
+               lat.show(state, crc_errors);
+               lon.show(state, crc_errors);
+               height.show(state, crc_errors);
+               main.show(state, crc_errors);
+               apogee.show(state, crc_errors);
+               speed.show(state, crc_errors);
+               accel.show(state, crc_errors);
+       }
+
+       public void labels(GridBagLayout layout, int y) {
+               GridBagConstraints      c;
+               JLabel                  cur, max;
+
+               cur = new JLabel("Current");
+               cur.setFont(Altos.label_font);
+               c = new GridBagConstraints();
+               c.gridx = 2; c.gridy = y;
+               c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
+               layout.setConstraints(cur, c);
+               add(cur);
+
+               max = new JLabel("Maximum");
+               max.setFont(Altos.label_font);
+               c.gridx = 3; c.gridy = y;
+               layout.setConstraints(max, c);
+               add(max);
+       }
+
+       public AltosAscent() {
+               layout = new GridBagLayout();
+
+               setLayout(layout);
+
+               /* Elements in ascent display:
+                *
+                * lat
+                * lon
+                * height
+                */
+               labels(layout, 0);
+               height = new Height(layout, 1);
+               speed = new Speed(layout, 2);
+               accel = new Accel(layout, 3);
+               lat = new Lat(layout, 4);
+               lon = new Lon(layout, 5);
+               apogee = new Apogee(layout, 6);
+               main = new Main(layout, 7);
+       }
+}
diff --git a/altosui/AltosCRCException.java b/altosui/AltosCRCException.java
new file mode 100644 (file)
index 0000000..4a529bc
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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;
+
+public class AltosCRCException extends Exception {
+       public int rssi;
+
+       public AltosCRCException (int in_rssi) {
+               rssi = in_rssi;
+       }
+}
diff --git a/altosui/AltosCSV.java b/altosui/AltosCSV.java
new file mode 100644 (file)
index 0000000..df98b2b
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * 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.lang.*;
+import java.io.*;
+import java.text.*;
+import java.util.*;
+
+public class AltosCSV implements AltosWriter {
+       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 = 2;
+
+       /* Version 2 format:
+        *
+        * General info
+        *      version number
+        *      serial number
+        *      flight number
+        *      callsign
+        *      time (seconds since boost)
+        *      rssi
+        *      link quality
+        *
+        * Flight status
+        *      state
+        *      state name
+        *
+        * Basic sensors
+        *      acceleration (m/s²)
+        *      pressure (mBar)
+        *      altitude (m)
+        *      height (m)
+        *      accelerometer speed (m/s)
+        *      barometer speed (m/s)
+        *      temp (°C)
+        *      battery (V)
+        *      drogue (V)
+        *      main (V)
+        *
+        * GPS data
+        *      connected (1/0)
+        *      locked (1/0)
+        *      nsat (used for solution)
+        *      latitude (°)
+        *      longitude (°)
+        *      altitude (m)
+        *      year (e.g. 2010)
+        *      month (1-12)
+        *      day (1-31)
+        *      hour (0-23)
+        *      minute (0-59)
+        *      second (0-59)
+        *      from_pad_dist (m)
+        *      from_pad_azimuth (deg true)
+        *      from_pad_range (m)
+        *      from_pad_elevation (deg from horizon)
+        *      hdop
+        *
+        * GPS Sat data
+        *      C/N0 data for all 32 valid SDIDs
+        */
+
+       void write_general_header() {
+               out.printf("version,serial,flight,call,time,rssi,lqi");
+       }
+
+       void write_general(AltosRecord record) {
+               out.printf("%s, %d, %d, %s, %8.2f, %4d, %3d",
+                          ALTOS_CSV_VERSION, record.serial, record.flight, record.callsign,
+                          (double) record.time,
+                          record.rssi,
+                          record.status & 0x7f);
+       }
+
+       void write_flight_header() {
+               out.printf("state,state_name");
+       }
+
+       void write_flight(AltosRecord record) {
+               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.raw_pressure(),
+                          record.raw_altitude(),
+                          record.raw_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_range,pad_az,pad_el,hdop");
+       }
+
+       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,%9.0f,%4.0f,%4.0f,%6.1f",
+                          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,
+                          state.range,
+                          from_pad.bearing,
+                          state.elevation,
+                          gps.hdop);
+       }
+
+       void write_gps_sat_header() {
+               for(int i = 1; i <= 32; i++) {
+                       out.printf("sat%02d", i);
+                       if (i != 32)
+                               out.printf(",");
+               }
+       }
+
+       void write_gps_sat(AltosRecord record) {
+               AltosGPS        gps = record.gps;
+               for(int i = 1; i <= 32; i++) {
+                       int     c_n0 = 0;
+                       if (gps != null && gps.cc_gps_sat != null) {
+                               for(int j = 0; j < gps.cc_gps_sat.length; j++)
+                                       if (gps.cc_gps_sat[j].svid == i) {
+                                               c_n0 = gps.cc_gps_sat[j].c_n0;
+                                               break;
+                                       }
+                       }
+                       out.printf ("%3d", c_n0);
+                       if (i != 32)
+                               out.printf(",");
+               }
+       }
+
+       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(","); write_gps_sat_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(",");
+               write_gps_sat(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;
+               }
+               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(AltosRecordIterable iterable) {
+               iterable.write_comments(out());
+               for (AltosRecord r : iterable)
+                       write(r);
+       }
+
+       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/altosui/AltosCSVUI.java b/altosui/AltosCSVUI.java
new file mode 100644 (file)
index 0000000..e1b6002
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * 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;
+
+public class AltosCSVUI
+       extends JDialog
+       implements ActionListener
+{
+       JFileChooser            csv_chooser;
+       JPanel                  accessory;
+       JComboBox               combo_box;
+       AltosRecordIterable     iterable;
+       AltosWriter             writer;
+
+       static String[]         combo_box_items = { "Comma Separated Values (.CSV)", "Googleearth Data (.KML)" };
+
+       void set_default_file() {
+               File    current = csv_chooser.getSelectedFile();
+               String  current_name = current.getName();
+               String  new_name = null;
+               String  selected = (String) combo_box.getSelectedItem();
+
+               if (selected.contains("CSV"))
+                       new_name = Altos.replace_extension(current_name, ".csv");
+               else if (selected.contains("KML"))
+                       new_name = Altos.replace_extension(current_name, ".kml");
+               if (new_name != null)
+                       csv_chooser.setSelectedFile(new File(new_name));
+       }
+
+       public void actionPerformed(ActionEvent e) {
+               if (e.getActionCommand().equals("comboBoxChanged"))
+                       set_default_file();
+       }
+
+       public AltosCSVUI(JFrame frame, AltosRecordIterable in_iterable, File source_file) {
+               iterable = in_iterable;
+               csv_chooser = new JFileChooser(source_file);
+
+               accessory = new JPanel();
+               accessory.setLayout(new GridBagLayout());
+
+               GridBagConstraints      c = new GridBagConstraints();
+               c.fill = GridBagConstraints.NONE;
+               c.weightx = 1;
+               c.weighty = 0;
+               c.insets = new Insets (4, 4, 4, 4);
+
+               JLabel accessory_label = new JLabel("Export File Type");
+               c.gridx = 0;
+               c.gridy = 0;
+               accessory.add(accessory_label, c);
+
+               combo_box = new JComboBox(combo_box_items);
+               combo_box.addActionListener(this);
+               c.gridx = 0;
+               c.gridy = 1;
+               accessory.add(combo_box, c);
+
+               csv_chooser.setAccessory(accessory);
+               csv_chooser.setSelectedFile(source_file);
+               set_default_file();
+               int ret = csv_chooser.showSaveDialog(frame);
+               if (ret == JFileChooser.APPROVE_OPTION) {
+                       File file = csv_chooser.getSelectedFile();
+                       String type = (String) combo_box.getSelectedItem();
+                       try {
+                               if (type.contains("CSV"))
+                                       writer = new AltosCSV(file);
+                               else
+                                       writer = new AltosKML(file);
+                               writer.write(iterable);
+                               writer.close();
+                       } catch (FileNotFoundException ee) {
+                               JOptionPane.showMessageDialog(frame,
+                                                             file.getName(),
+                                                             "Cannot open file",
+                                                             JOptionPane.ERROR_MESSAGE);
+                       }
+               }
+       }
+}
diff --git a/altosui/AltosChannelMenu.java b/altosui/AltosChannelMenu.java
new file mode 100644 (file)
index 0000000..abbb86f
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * 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;
+
+public class AltosChannelMenu extends JComboBox implements ActionListener {
+       int                             channel;
+
+       public AltosChannelMenu(int current_channel) {
+
+               channel = current_channel;
+
+               for (int c = 0; c <= 9; c++)
+                       addItem(String.format("Channel %1d (%7.3fMHz)", c, 434.550 + c * 0.1));
+               setSelectedIndex(channel);
+               setMaximumRowCount(10);
+       }
+
+}
diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java
new file mode 100644 (file)
index 0000000..1c42870
--- /dev/null
@@ -0,0 +1,295 @@
+/*
+ * 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.*;
+
+import libaltosJNI.*;
+
+public class AltosConfig implements Runnable, ActionListener {
+
+       class int_ref {
+               int     value;
+
+               public int get() {
+                       return value;
+               }
+               public void set(int i) {
+                       value = i;
+               }
+               public int_ref(int i) {
+                       value = i;
+               }
+       }
+
+       class string_ref {
+               String  value;
+
+               public String get() {
+                       return value;
+               }
+               public void set(String i) {
+                       value = i;
+               }
+               public string_ref(String i) {
+                       value = i;
+               }
+       }
+
+       JFrame          owner;
+       AltosDevice     device;
+       AltosSerial     serial_line;
+       boolean         remote;
+       Thread          config_thread;
+       int_ref         serial;
+       int_ref         main_deploy;
+       int_ref         apogee_delay;
+       int_ref         radio_channel;
+       int_ref         radio_calibration;
+       string_ref      version;
+       string_ref      product;
+       string_ref      callsign;
+       AltosConfigUI   config_ui;
+       boolean         serial_started;
+
+       boolean get_int(String line, String label, int_ref x) {
+               if (line.startsWith(label)) {
+                       try {
+                               String tail = line.substring(label.length()).trim();
+                               String[] tokens = tail.split("\\s+");
+                               if (tokens.length > 0) {
+                                       int     i = Integer.parseInt(tokens[0]);
+                                       x.set(i);
+                                       return true;
+                               }
+                       } catch (NumberFormatException ne) {
+                       }
+               }
+               return false;
+       }
+
+       boolean get_string(String line, String label, string_ref s) {
+               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);
+                       s.set(quoted);
+                       return true;
+               } else {
+                       return false;
+               }
+       }
+
+       void start_serial() throws InterruptedException {
+               serial_started = true;
+               if (remote) {
+                       serial_line.set_radio();
+                       serial_line.printf("p\nE 0\n");
+                       serial_line.flush_input();
+               }
+       }
+
+       void stop_serial() throws InterruptedException {
+               if (!serial_started)
+                       return;
+               serial_started = false;
+               if (remote) {
+                       serial_line.printf("~");
+                       serial_line.flush_output();
+               }
+       }
+
+       void get_data() throws InterruptedException, TimeoutException {
+               try {
+                       start_serial();
+                       serial_line.printf("c s\nv\n");
+                       for (;;) {
+                               String line = serial_line.get_reply(5000);
+                               if (line == null)
+                                       throw new TimeoutException();
+                               get_int(line, "serial-number", serial);
+                               get_int(line, "Main deploy:", main_deploy);
+                               get_int(line, "Apogee delay:", apogee_delay);
+                               get_int(line, "Radio channel:", radio_channel);
+                               get_int(line, "Radio cal:", radio_calibration);
+                               get_string(line, "Callsign:", callsign);
+                               get_string(line,"software-version", version);
+                               get_string(line,"product", product);
+
+                               /* signals the end of the version info */
+                               if (line.startsWith("software-version"))
+                                       break;
+                       }
+               } finally {
+                       stop_serial();
+               }
+       }
+
+       void init_ui () throws InterruptedException, TimeoutException {
+               config_ui = new AltosConfigUI(owner, remote);
+               config_ui.addActionListener(this);
+               set_ui();
+       }
+
+       void abort() {
+               JOptionPane.showMessageDialog(owner,
+                                             String.format("Connection to \"%s\" failed",
+                                                           device.toShortString()),
+                                             "Connection Failed",
+                                             JOptionPane.ERROR_MESSAGE);
+               try {
+                       stop_serial();
+               } catch (InterruptedException ie) {
+               }
+               serial_line.close();
+               serial_line = null;
+       }
+
+       void set_ui() throws InterruptedException, TimeoutException {
+               if (serial_line != null)
+                       get_data();
+               config_ui.set_serial(serial.get());
+               config_ui.set_product(product.get());
+               config_ui.set_version(version.get());
+               config_ui.set_main_deploy(main_deploy.get());
+               config_ui.set_apogee_delay(apogee_delay.get());
+               config_ui.set_radio_channel(radio_channel.get());
+               config_ui.set_radio_calibration(radio_calibration.get());
+               config_ui.set_callsign(callsign.get());
+               config_ui.set_clean();
+       }
+
+       void run_dialog() {
+       }
+
+       void save_data() {
+               main_deploy.set(config_ui.main_deploy());
+               apogee_delay.set(config_ui.apogee_delay());
+               radio_channel.set(config_ui.radio_channel());
+               radio_calibration.set(config_ui.radio_calibration());
+               callsign.set(config_ui.callsign());
+               try {
+                       start_serial();
+                       serial_line.printf("c m %d\n", main_deploy.get());
+                       serial_line.printf("c d %d\n", apogee_delay.get());
+                       if (!remote) {
+                               serial_line.printf("c r %d\n", radio_channel.get());
+                               serial_line.printf("c f %d\n", radio_calibration.get());
+                       }
+                       serial_line.printf("c c %s\n", callsign.get());
+                       serial_line.printf("c w\n");
+               } catch (InterruptedException ie) {
+               } finally {
+                       try {
+                               stop_serial();
+                       } catch (InterruptedException ie) {
+                       }
+               }
+       }
+
+       public void actionPerformed(ActionEvent e) {
+               String  cmd = e.getActionCommand();
+               try {
+                       if (cmd.equals("Save")) {
+                               save_data();
+                               set_ui();
+                       } else if (cmd.equals("Reset")) {
+                               set_ui();
+                       } else if (cmd.equals("Reboot")) {
+                               if (serial_line != null) {
+                                       start_serial();
+                                       serial_line.printf("r eboot\n");
+                                       serial_line.flush_output();
+                                       stop_serial();
+                                       serial_line.close();
+                               }
+                       } else if (cmd.equals("Close")) {
+                               if (serial_line != null)
+                                       serial_line.close();
+                       }
+               } catch (InterruptedException ie) {
+                       abort();
+               } catch (TimeoutException te) {
+                       abort();
+               }
+       }
+
+       public void run () {
+               try {
+                       init_ui();
+                       config_ui.make_visible();
+               } catch (InterruptedException ie) {
+                       abort();
+               } catch (TimeoutException te) {
+                       abort();
+               }
+       }
+
+       public AltosConfig(JFrame given_owner) {
+               owner = given_owner;
+
+               serial = new int_ref(0);
+               main_deploy = new int_ref(250);
+               apogee_delay = new int_ref(0);
+               radio_channel = new int_ref(0);
+               radio_calibration = new int_ref(1186611);
+               callsign = new string_ref("N0CALL");
+               version = new string_ref("unknown");
+               product = new string_ref("unknown");
+
+               device = AltosDeviceDialog.show(owner, AltosDevice.product_any);
+               if (device != null) {
+                       try {
+                               serial_line = new AltosSerial(device);
+                               if (!device.matchProduct(AltosDevice.product_telemetrum))
+                                       remote = true;
+                               config_thread = new Thread(this);
+                               config_thread.start();
+                       } catch (FileNotFoundException ee) {
+                               JOptionPane.showMessageDialog(owner,
+                                                             String.format("Cannot open device \"%s\"",
+                                                                           device.toShortString()),
+                                                             "Cannot open target device",
+                                                             JOptionPane.ERROR_MESSAGE);
+                       } catch (AltosSerialInUseException si) {
+                               JOptionPane.showMessageDialog(owner,
+                                                             String.format("Device \"%s\" already in use",
+                                                                           device.toShortString()),
+                                                             "Device in use",
+                                                             JOptionPane.ERROR_MESSAGE);
+                       } catch (IOException ee) {
+                               JOptionPane.showMessageDialog(owner,
+                                                             device.toShortString(),
+                                                             ee.getLocalizedMessage(),
+                                                             JOptionPane.ERROR_MESSAGE);
+                       }
+               }
+       }
+}
\ No newline at end of file
diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java
new file mode 100644 (file)
index 0000000..cfa5d7b
--- /dev/null
@@ -0,0 +1,466 @@
+/*
+ * 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 javax.swing.event.*;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.util.prefs.*;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import libaltosJNI.*;
+
+public class AltosConfigUI
+       extends JDialog
+       implements ActionListener, ItemListener, DocumentListener
+{
+
+       Container       pane;
+       Box             box;
+       JLabel          product_label;
+       JLabel          version_label;
+       JLabel          serial_label;
+       JLabel          main_deploy_label;
+       JLabel          apogee_delay_label;
+       JLabel          radio_channel_label;
+       JLabel          radio_calibration_label;
+       JLabel          callsign_label;
+
+       public boolean          dirty;
+
+       JFrame          owner;
+       JLabel          product_value;
+       JLabel          version_value;
+       JLabel          serial_value;
+       JComboBox       main_deploy_value;
+       JComboBox       apogee_delay_value;
+       JComboBox       radio_channel_value;
+       JTextField      radio_calibration_value;
+       JTextField      callsign_value;
+
+       JButton         save;
+       JButton         reset;
+       JButton         reboot;
+       JButton         close;
+
+       ActionListener  listener;
+
+       static String[] main_deploy_values = {
+               "100", "150", "200", "250", "300", "350",
+               "400", "450", "500"
+       };
+
+       static String[] apogee_delay_values = {
+               "0", "1", "2", "3", "4", "5"
+       };
+
+       static String[] radio_channel_values = new String[10];
+               {
+                       for (int i = 0; i <= 9; i++)
+                               radio_channel_values[i] = String.format("Channel %1d (%7.3fMHz)",
+                                                                       i, 434.550 + i * 0.1);
+               }
+
+       /* A window listener to catch closing events and tell the config code */
+       class ConfigListener extends WindowAdapter {
+               AltosConfigUI   ui;
+
+               public ConfigListener(AltosConfigUI this_ui) {
+                       ui = this_ui;
+               }
+
+               public void windowClosing(WindowEvent e) {
+                       ui.actionPerformed(new ActionEvent(e.getSource(),
+                                                          ActionEvent.ACTION_PERFORMED,
+                                                          "Close"));
+               }
+       }
+
+       /* Build the UI using a grid bag */
+       public AltosConfigUI(JFrame in_owner, boolean remote) {
+               super (in_owner, "Configure TeleMetrum", false);
+
+               owner = in_owner;
+               GridBagConstraints c;
+
+               Insets il = new Insets(4,4,4,4);
+               Insets ir = new Insets(4,4,4,4);
+
+               pane = getContentPane();
+               pane.setLayout(new GridBagLayout());
+
+               /* Product */
+               c = new GridBagConstraints();
+               c.gridx = 0; c.gridy = 0;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = il;
+               product_label = new JLabel("Product:");
+               pane.add(product_label, c);
+
+               c = new GridBagConstraints();
+               c.gridx = 4; c.gridy = 0;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.weightx = 1;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = ir;
+               product_value = new JLabel("");
+               pane.add(product_value, c);
+
+               /* Version */
+               c = new GridBagConstraints();
+               c.gridx = 0; c.gridy = 1;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = il;
+               c.ipady = 5;
+               version_label = new JLabel("Software version:");
+               pane.add(version_label, c);
+
+               c = new GridBagConstraints();
+               c.gridx = 4; c.gridy = 1;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.weightx = 1;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = ir;
+               c.ipady = 5;
+               version_value = new JLabel("");
+               pane.add(version_value, c);
+
+               /* Serial */
+               c = new GridBagConstraints();
+               c.gridx = 0; c.gridy = 2;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = il;
+               c.ipady = 5;
+               serial_label = new JLabel("Serial:");
+               pane.add(serial_label, c);
+
+               c = new GridBagConstraints();
+               c.gridx = 4; c.gridy = 2;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.weightx = 1;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = ir;
+               c.ipady = 5;
+               serial_value = new JLabel("");
+               pane.add(serial_value, c);
+
+               /* Main deploy */
+               c = new GridBagConstraints();
+               c.gridx = 0; c.gridy = 3;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = il;
+               c.ipady = 5;
+               main_deploy_label = new JLabel("Main Deploy Altitude(m):");
+               pane.add(main_deploy_label, c);
+
+               c = new GridBagConstraints();
+               c.gridx = 4; c.gridy = 3;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.weightx = 1;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = ir;
+               c.ipady = 5;
+               main_deploy_value = new JComboBox(main_deploy_values);
+               main_deploy_value.setEditable(true);
+               main_deploy_value.addItemListener(this);
+               pane.add(main_deploy_value, c);
+
+               /* Apogee delay */
+               c = new GridBagConstraints();
+               c.gridx = 0; c.gridy = 4;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = il;
+               c.ipady = 5;
+               apogee_delay_label = new JLabel("Apogee Delay(s):");
+               pane.add(apogee_delay_label, c);
+
+               c = new GridBagConstraints();
+               c.gridx = 4; c.gridy = 4;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.weightx = 1;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = ir;
+               c.ipady = 5;
+               apogee_delay_value = new JComboBox(apogee_delay_values);
+               apogee_delay_value.setEditable(true);
+               apogee_delay_value.addItemListener(this);
+               pane.add(apogee_delay_value, c);
+
+               /* Radio channel */
+               c = new GridBagConstraints();
+               c.gridx = 0; c.gridy = 5;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = il;
+               c.ipady = 5;
+               radio_channel_label = new JLabel("Radio Channel:");
+               pane.add(radio_channel_label, c);
+
+               c = new GridBagConstraints();
+               c.gridx = 4; c.gridy = 5;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.weightx = 1;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = ir;
+               c.ipady = 5;
+               radio_channel_value = new JComboBox(radio_channel_values);
+               radio_channel_value.setEditable(false);
+               radio_channel_value.addItemListener(this);
+               if (remote)
+                       radio_channel_value.setEnabled(false);
+               pane.add(radio_channel_value, c);
+
+               /* Radio Calibration */
+               c = new GridBagConstraints();
+               c.gridx = 0; c.gridy = 6;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = il;
+               c.ipady = 5;
+               radio_calibration_label = new JLabel("RF Calibration:");
+               pane.add(radio_calibration_label, c);
+
+               c = new GridBagConstraints();
+               c.gridx = 4; c.gridy = 6;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.weightx = 1;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = ir;
+               c.ipady = 5;
+               radio_calibration_value = new JTextField(String.format("%d", 1186611));
+               radio_calibration_value.getDocument().addDocumentListener(this);
+               if (remote)
+                       radio_calibration_value.setEnabled(false);
+               pane.add(radio_calibration_value, c);
+
+               /* Callsign */
+               c = new GridBagConstraints();
+               c.gridx = 0; c.gridy = 7;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = il;
+               c.ipady = 5;
+               callsign_label = new JLabel("Callsign:");
+               pane.add(callsign_label, c);
+
+               c = new GridBagConstraints();
+               c.gridx = 4; c.gridy = 7;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.weightx = 1;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = ir;
+               c.ipady = 5;
+               callsign_value = new JTextField(AltosPreferences.callsign());
+               callsign_value.getDocument().addDocumentListener(this);
+               pane.add(callsign_value, c);
+
+               /* Buttons */
+               c = new GridBagConstraints();
+               c.gridx = 0; c.gridy = 8;
+               c.gridwidth = 2;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = il;
+               save = new JButton("Save");
+               pane.add(save, c);
+               save.addActionListener(this);
+               save.setActionCommand("Save");
+
+               c = new GridBagConstraints();
+               c.gridx = 2; c.gridy = 8;
+               c.gridwidth = 2;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.CENTER;
+               c.insets = il;
+               reset = new JButton("Reset");
+               pane.add(reset, c);
+               reset.addActionListener(this);
+               reset.setActionCommand("Reset");
+
+               c = new GridBagConstraints();
+               c.gridx = 4; c.gridy = 8;
+               c.gridwidth = 2;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.CENTER;
+               c.insets = il;
+               reboot = new JButton("Reboot");
+               pane.add(reboot, c);
+               reboot.addActionListener(this);
+               reboot.setActionCommand("Reboot");
+
+               c = new GridBagConstraints();
+               c.gridx = 6; c.gridy = 8;
+               c.gridwidth = 2;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.LINE_END;
+               c.insets = il;
+               close = new JButton("Close");
+               pane.add(close, c);
+               close.addActionListener(this);
+               close.setActionCommand("Close");
+
+               addWindowListener(new ConfigListener(this));
+       }
+
+       /* Once the initial values are set, the config code will show the dialog */
+       public void make_visible() {
+               pack();
+               setLocationRelativeTo(owner);
+               setVisible(true);
+       }
+
+       /* If any values have been changed, confirm before closing */
+       public boolean check_dirty(String operation) {
+               if (dirty) {
+                       Object[] options = { String.format("%s anyway", operation), "Keep editing" };
+                       int i;
+                       i = JOptionPane.showOptionDialog(this,
+                                                        String.format("Configuration modified. %s anyway?", operation),
+                                                        "Configuration Modified",
+                                                        JOptionPane.DEFAULT_OPTION,
+                                                        JOptionPane.WARNING_MESSAGE,
+                                                        null, options, options[1]);
+                       if (i != 0)
+                               return false;
+               }
+               return true;
+       }
+
+       /* Listen for events from our buttons */
+       public void actionPerformed(ActionEvent e) {
+               String  cmd = e.getActionCommand();
+
+               if (cmd.equals("Close") || cmd.equals("Reboot"))
+                       if (!check_dirty(cmd))
+                               return;
+               listener.actionPerformed(e);
+               if (cmd.equals("Close") || cmd.equals("Reboot")) {
+                       setVisible(false);
+                       dispose();
+               }
+               dirty = false;
+       }
+
+       /* ItemListener interface method */
+       public void itemStateChanged(ItemEvent e) {
+               dirty = true;
+       }
+
+       /* DocumentListener interface methods */
+       public void changedUpdate(DocumentEvent e) {
+               dirty = true;
+       }
+
+       public void insertUpdate(DocumentEvent e) {
+               dirty = true;
+       }
+
+       public void removeUpdate(DocumentEvent e) {
+               dirty = true;
+       }
+
+       /* Let the config code hook on a listener */
+       public void addActionListener(ActionListener l) {
+               listener = l;
+       }
+
+       /* set and get all of the dialog values */
+       public void set_product(String product) {
+               product_value.setText(product);
+       }
+
+       public void set_version(String version) {
+               version_value.setText(version);
+       }
+
+       public void set_serial(int serial) {
+               serial_value.setText(String.format("%d", serial));
+       }
+
+       public void set_main_deploy(int new_main_deploy) {
+               main_deploy_value.setSelectedItem(Integer.toString(new_main_deploy));
+       }
+
+       public int main_deploy() {
+               return Integer.parseInt(main_deploy_value.getSelectedItem().toString());
+       }
+
+       public void set_apogee_delay(int new_apogee_delay) {
+               apogee_delay_value.setSelectedItem(Integer.toString(new_apogee_delay));
+       }
+
+       public int apogee_delay() {
+               return Integer.parseInt(apogee_delay_value.getSelectedItem().toString());
+       }
+
+       public void set_radio_channel(int new_radio_channel) {
+               radio_channel_value.setSelectedIndex(new_radio_channel);
+       }
+
+       public int radio_channel() {
+               return radio_channel_value.getSelectedIndex();
+       }
+
+       public void set_radio_calibration(int new_radio_calibration) {
+               radio_calibration_value.setText(String.format("%d", new_radio_calibration));
+       }
+
+       public int radio_calibration() {
+               return Integer.parseInt(radio_calibration_value.getText());
+       }
+
+       public void set_callsign(String new_callsign) {
+               callsign_value.setText(new_callsign);
+       }
+
+       public String callsign() {
+               return callsign_value.getText();
+       }
+
+       public void set_clean() {
+               dirty = false;
+       }
+
+ }
\ No newline at end of file
diff --git a/altosui/AltosConfigureUI.java b/altosui/AltosConfigureUI.java
new file mode 100644 (file)
index 0000000..153c59f
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * 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 javax.swing.event.*;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.util.prefs.*;
+import java.util.concurrent.LinkedBlockingQueue;
+
+public class AltosConfigureUI
+       extends JDialog
+       implements DocumentListener
+{
+       JFrame          owner;
+       AltosVoice      voice;
+       Container       pane;
+
+       JRadioButton    enable_voice;
+       JButton         test_voice;
+       JButton         close;
+
+       JButton         configure_log;
+       JTextField      log_directory;
+
+       JLabel          callsign_label;
+       JTextField      callsign_value;
+
+       /* DocumentListener interface methods */
+       public void changedUpdate(DocumentEvent e) {
+               AltosPreferences.set_callsign(callsign_value.getText());
+       }
+
+       public void insertUpdate(DocumentEvent e) {
+               changedUpdate(e);
+       }
+
+       public void removeUpdate(DocumentEvent e) {
+               changedUpdate(e);
+       }
+
+       public AltosConfigureUI(JFrame in_owner, AltosVoice in_voice) {
+               super(in_owner, "Configure AltosUI", false);
+
+               GridBagConstraints      c;
+
+               Insets insets = new Insets(4, 4, 4, 4);
+
+               owner = in_owner;
+               voice = in_voice;
+               pane = getContentPane();
+               pane.setLayout(new GridBagLayout());
+
+               c = new GridBagConstraints();
+               c.insets = insets;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.WEST;
+
+               /* Nice label at the top */
+               c.gridx = 0;
+               c.gridy = 0;
+               c.gridwidth = 3;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.CENTER;
+               pane.add(new JLabel ("Configure AltOS UI"), c);
+
+               /* Voice settings */
+               c.gridx = 0;
+               c.gridy = 1;
+               c.gridwidth = 1;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.WEST;
+               pane.add(new JLabel("Voice"), c);
+
+               enable_voice = new JRadioButton("Enable", AltosPreferences.voice());
+               enable_voice.addActionListener(new ActionListener() {
+                               public void actionPerformed(ActionEvent e) {
+                                       JRadioButton item = (JRadioButton) e.getSource();
+                                       boolean enabled = item.isSelected();
+                                       AltosPreferences.set_voice(enabled);
+                                       if (enabled)
+                                               voice.speak_always("Enable voice.");
+                                       else
+                                               voice.speak_always("Disable voice.");
+                               }
+                       });
+               c.gridx = 1;
+               c.gridy = 1;
+               c.gridwidth = 1;
+               c.weightx = 1;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.WEST;
+               pane.add(enable_voice, c);
+
+               c.gridx = 2;
+               c.gridy = 1;
+               c.gridwidth = 1;
+               c.weightx = 1;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.EAST;
+               test_voice = new JButton("Test Voice");
+               test_voice.addActionListener(new ActionListener() {
+                               public void actionPerformed(ActionEvent e) {
+                                       voice.speak("That's one small step for man; one giant leap for mankind.");
+                               }
+                       });
+               pane.add(test_voice, c);
+
+               /* Log directory settings */
+               c.gridx = 0;
+               c.gridy = 2;
+               c.gridwidth = 1;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.WEST;
+               pane.add(new JLabel("Log Directory"), c);
+
+               configure_log = new JButton(AltosPreferences.logdir().getPath());
+               configure_log.addActionListener(new ActionListener() {
+                               public void actionPerformed(ActionEvent e) {
+                                       AltosPreferences.ConfigureLog();
+                                       configure_log.setText(AltosPreferences.logdir().getPath());
+                               }
+                       });
+               c.gridx = 1;
+               c.gridy = 2;
+               c.gridwidth = 2;
+               c.fill = GridBagConstraints.BOTH;
+               c.anchor = GridBagConstraints.WEST;
+               pane.add(configure_log, c);
+
+               /* Callsign setting */
+               c.gridx = 0;
+               c.gridy = 3;
+               c.gridwidth = 1;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.WEST;
+               pane.add(new JLabel("Callsign"), c);
+
+               callsign_value = new JTextField(AltosPreferences.callsign());
+               callsign_value.getDocument().addDocumentListener(this);
+               c.gridx = 1;
+               c.gridy = 3;
+               c.gridwidth = 2;
+               c.fill = GridBagConstraints.BOTH;
+               c.anchor = GridBagConstraints.WEST;
+               pane.add(callsign_value, c);
+
+               /* And a close button at the bottom */
+               close = new JButton("Close");
+               close.addActionListener(new ActionListener() {
+                               public void actionPerformed(ActionEvent e) {
+                                       setVisible(false);
+                               }
+                       });
+               c.gridx = 0;
+               c.gridy = 4;
+               c.gridwidth = 3;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.CENTER;
+               pane.add(close, c);
+
+               pack();
+               setLocationRelativeTo(owner);
+               setVisible(true);
+       }
+}
diff --git a/altosui/AltosConvert.java b/altosui/AltosConvert.java
new file mode 100644 (file)
index 0000000..8cc1df2
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * 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.
+ */
+
+/*
+ * Sensor data conversion functions
+ */
+package altosui;
+
+public class AltosConvert {
+       /*
+        * Pressure Sensor Model, version 1.1
+        *
+        * written by Holly Grimes
+        *
+        * Uses the International Standard Atmosphere as described in
+        *   "A Quick Derivation relating altitude to air pressure" (version 1.03)
+        *    from the Portland State Aerospace Society, except that the atmosphere
+        *    is divided into layers with each layer having a different lapse rate.
+        *
+        * Lapse rate data for each layer was obtained from Wikipedia on Sept. 1, 2007
+        *    at site <http://en.wikipedia.org/wiki/International_Standard_Atmosphere
+        *
+        * Height measurements use the local tangent plane.  The postive z-direction is up.
+        *
+        * All measurements are given in SI units (Kelvin, Pascal, meter, meters/second^2).
+        *   The lapse rate is given in Kelvin/meter, the gas constant for air is given
+        *   in Joules/(kilogram-Kelvin).
+        */
+
+       static final double GRAVITATIONAL_ACCELERATION = -9.80665;
+       static final double AIR_GAS_CONSTANT            = 287.053;
+       static final double NUMBER_OF_LAYERS            = 7;
+       static final double MAXIMUM_ALTITUDE            = 84852.0;
+       static final double MINIMUM_PRESSURE            = 0.3734;
+       static final double LAYER0_BASE_TEMPERATURE     = 288.15;
+       static final double LAYER0_BASE_PRESSURE        = 101325;
+
+       /* lapse rate and base altitude for each layer in the atmosphere */
+       static final double[] lapse_rate = {
+               -0.0065, 0.0, 0.001, 0.0028, 0.0, -0.0028, -0.002
+       };
+
+       static final int[] base_altitude = {
+               0, 11000, 20000, 32000, 47000, 51000, 71000
+       };
+
+       /* outputs atmospheric pressure associated with the given altitude.
+        * altitudes are measured with respect to the mean sea level
+        */
+       static double
+       altitude_to_pressure(double altitude)
+       {
+               double base_temperature = LAYER0_BASE_TEMPERATURE;
+               double base_pressure = LAYER0_BASE_PRESSURE;
+
+               double pressure;
+               double base; /* base for function to determine pressure */
+               double exponent; /* exponent for function to determine pressure */
+               int layer_number; /* identifies layer in the atmosphere */
+               double delta_z; /* difference between two altitudes */
+
+               if (altitude > MAXIMUM_ALTITUDE) /* FIX ME: use sensor data to improve model */
+                       return 0;
+
+               /* calculate the base temperature and pressure for the atmospheric layer
+                  associated with the inputted altitude */
+               for(layer_number = 0; layer_number < NUMBER_OF_LAYERS - 1 && altitude > base_altitude[layer_number + 1]; layer_number++) {
+                       delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number];
+                       if (lapse_rate[layer_number] == 0.0) {
+                               exponent = GRAVITATIONAL_ACCELERATION * delta_z
+                                       / AIR_GAS_CONSTANT / base_temperature;
+                               base_pressure *= Math.exp(exponent);
+                       }
+                       else {
+                               base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0;
+                               exponent = GRAVITATIONAL_ACCELERATION /
+                                       (AIR_GAS_CONSTANT * lapse_rate[layer_number]);
+                               base_pressure *= Math.pow(base, exponent);
+                       }
+                       base_temperature += delta_z * lapse_rate[layer_number];
+               }
+
+               /* calculate the pressure at the inputted altitude */
+               delta_z = altitude - base_altitude[layer_number];
+               if (lapse_rate[layer_number] == 0.0) {
+                       exponent = GRAVITATIONAL_ACCELERATION * delta_z
+                               / AIR_GAS_CONSTANT / base_temperature;
+                       pressure = base_pressure * Math.exp(exponent);
+               }
+               else {
+                       base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0;
+                       exponent = GRAVITATIONAL_ACCELERATION /
+                               (AIR_GAS_CONSTANT * lapse_rate[layer_number]);
+                       pressure = base_pressure * Math.pow(base, exponent);
+               }
+
+               return pressure;
+       }
+
+
+/* outputs the altitude associated with the given pressure. the altitude
+   returned is measured with respect to the mean sea level */
+       static double
+       pressure_to_altitude(double pressure)
+       {
+
+               double next_base_temperature = LAYER0_BASE_TEMPERATURE;
+               double next_base_pressure = LAYER0_BASE_PRESSURE;
+
+               double altitude;
+               double base_pressure;
+               double base_temperature;
+               double base; /* base for function to determine base pressure of next layer */
+               double exponent; /* exponent for function to determine base pressure
+                                   of next layer */
+               double coefficient;
+               int layer_number; /* identifies layer in the atmosphere */
+               int delta_z; /* difference between two altitudes */
+
+               if (pressure < 0)  /* illegal pressure */
+                       return -1;
+               if (pressure < MINIMUM_PRESSURE) /* FIX ME: use sensor data to improve model */
+                       return MAXIMUM_ALTITUDE;
+
+               /* calculate the base temperature and pressure for the atmospheric layer
+                  associated with the inputted pressure. */
+               layer_number = -1;
+               do {
+                       layer_number++;
+                       base_pressure = next_base_pressure;
+                       base_temperature = next_base_temperature;
+                       delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number];
+                       if (lapse_rate[layer_number] == 0.0) {
+                               exponent = GRAVITATIONAL_ACCELERATION * delta_z
+                                       / AIR_GAS_CONSTANT / base_temperature;
+                               next_base_pressure *= Math.exp(exponent);
+                       }
+                       else {
+                               base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0;
+                               exponent = GRAVITATIONAL_ACCELERATION /
+                                       (AIR_GAS_CONSTANT * lapse_rate[layer_number]);
+                               next_base_pressure *= Math.pow(base, exponent);
+                       }
+                       next_base_temperature += delta_z * lapse_rate[layer_number];
+               }
+               while(layer_number < NUMBER_OF_LAYERS - 1 && pressure < next_base_pressure);
+
+               /* calculate the altitude associated with the inputted pressure */
+               if (lapse_rate[layer_number] == 0.0) {
+                       coefficient = (AIR_GAS_CONSTANT / GRAVITATIONAL_ACCELERATION)
+                               * base_temperature;
+                       altitude = base_altitude[layer_number]
+                               + coefficient * Math.log(pressure / base_pressure);
+               }
+               else {
+                       base = pressure / base_pressure;
+                       exponent = AIR_GAS_CONSTANT * lapse_rate[layer_number]
+                               / GRAVITATIONAL_ACCELERATION;
+                       coefficient = base_temperature / lapse_rate[layer_number];
+                       altitude = base_altitude[layer_number]
+                               + coefficient * (Math.pow(base, exponent) - 1);
+               }
+
+               return altitude;
+       }
+
+       static double
+       cc_battery_to_voltage(double battery)
+       {
+               return battery / 32767.0 * 5.0;
+       }
+
+       static double
+       cc_ignitor_to_voltage(double ignite)
+       {
+               return ignite / 32767 * 15.0;
+       }
+}
diff --git a/altosui/AltosDataChooser.java b/altosui/AltosDataChooser.java
new file mode 100644 (file)
index 0000000..15de05c
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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.*;
+
+public class AltosDataChooser extends JFileChooser {
+       JFrame  frame;
+       String  filename;
+       File    file;
+
+       public String filename() {
+               return filename;
+       }
+
+       public File file() {
+               return file;
+       }
+
+       public AltosRecordIterable runDialog() {
+               int     ret;
+
+               ret = showOpenDialog(frame);
+               if (ret == APPROVE_OPTION) {
+                       file = getSelectedFile();
+                       if (file == null)
+                               return null;
+                       filename = file.getName();
+                       try {
+                               if (filename.endsWith("eeprom")) {
+                                       FileInputStream in = new FileInputStream(file);
+                                       return new AltosEepromIterable(in);
+                               } else if (filename.endsWith("telem")) {
+                                       FileInputStream in = new FileInputStream(file);
+                                       return new AltosTelemetryIterable(in);
+                               } else {
+                                       throw new FileNotFoundException();
+                               }
+                       } catch (FileNotFoundException fe) {
+                               JOptionPane.showMessageDialog(frame,
+                                                             filename,
+                                                             "Cannot open file",
+                                                             JOptionPane.ERROR_MESSAGE);
+                       }
+               }
+               return null;
+       }
+
+       public AltosDataChooser(JFrame in_frame) {
+               frame = in_frame;
+               setDialogTitle("Select Flight Record File");
+               setFileFilter(new FileNameExtensionFilter("Flight data file",
+                                                         "telem", "eeprom"));
+               setCurrentDirectory(AltosPreferences.logdir());
+       }
+}
diff --git a/altosui/AltosDataPoint.java b/altosui/AltosDataPoint.java
new file mode 100644 (file)
index 0000000..66313e0
--- /dev/null
@@ -0,0 +1,29 @@
+
+// Copyright (c) 2010 Anthony Towns
+// GPL v2 or later
+
+package altosui;
+
+interface AltosDataPoint {
+    int version();
+    int serial();
+    int flight();
+    String callsign();
+    double time();
+    double rssi();
+
+    int state();
+    String state_name();
+
+    double acceleration();
+    double pressure();
+    double altitude();
+    double height();
+    double accel_speed();
+    double baro_speed();
+    double temperature();
+    double battery_voltage();
+    double drogue_voltage();
+    double main_voltage();
+}
+
diff --git a/altosui/AltosDataPointReader.java b/altosui/AltosDataPointReader.java
new file mode 100644 (file)
index 0000000..7704310
--- /dev/null
@@ -0,0 +1,72 @@
+
+// Copyright (c) 2010 Anthony Towns
+// GPL v2 or later
+
+package altosui;
+
+import java.io.IOException;
+import java.text.ParseException;
+import java.lang.UnsupportedOperationException;
+import java.util.NoSuchElementException;
+import java.util.Iterator;
+
+class AltosDataPointReader implements Iterable<AltosDataPoint> {
+    Iterator<AltosRecord> iter;
+    AltosState state;
+    AltosRecord record;
+
+    public AltosDataPointReader(Iterable<AltosRecord> reader) {
+        this.iter = reader.iterator();
+        this.state = null;
+    }
+
+    private void read_next_record() 
+        throws NoSuchElementException
+    {
+        record = iter.next();
+        state = new AltosState(record, state);
+    }
+
+    private AltosDataPoint current_dp() {
+        assert this.record != null;
+        
+        return new AltosDataPoint() {
+            public int version() { return record.version; }
+            public int serial() { return record.serial; }
+            public int flight() { return record.flight; }
+            public String callsign() { return record.callsign; }
+            public double time() { return record.time; }
+            public double rssi() { return record.rssi; }
+
+            public int state() { return record.state; }
+            public String state_name() { return record.state(); }
+
+            public double acceleration() { return record.acceleration(); }
+            public double pressure() { return record.raw_pressure(); }
+            public double altitude() { return record.raw_altitude(); }
+            public double height() { return record.raw_height(); }
+            public double accel_speed() { return record.accel_speed(); }
+            public double baro_speed() { return state.baro_speed; }
+            public double temperature() { return record.temperature(); }
+            public double battery_voltage() { return record.battery_voltage(); }
+            public double drogue_voltage() { return record.drogue_voltage(); }
+            public double main_voltage() { return record.main_voltage(); }
+        };
+    }
+
+    public Iterator<AltosDataPoint> iterator() {
+        return new Iterator<AltosDataPoint>() {
+            public void remove() { 
+                throw new UnsupportedOperationException(); 
+            }
+            public boolean hasNext() {
+                return iter.hasNext();
+            }
+            public AltosDataPoint next() {
+                read_next_record();
+                return current_dp();
+            }
+        };
+    }
+}
+
diff --git a/altosui/AltosDebug.java b/altosui/AltosDebug.java
new file mode 100644 (file)
index 0000000..8d435b6
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ * 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.lang.*;
+import java.io.*;
+import java.util.concurrent.*;
+import java.util.*;
+
+import libaltosJNI.*;
+
+public class AltosDebug extends AltosSerial {
+
+       public static final byte WR_CONFIG =            0x1d;
+       public static final byte RD_CONFIG =            0x24;
+       public static final byte CONFIG_TIMERS_OFF =            (1 << 3);
+       public static final byte CONFIG_DMA_PAUSE =             (1 << 2);
+       public static final byte CONFIG_TIMER_SUSPEND =         (1 << 1);
+       public static final byte SET_FLASH_INFO_PAGE =          (1 << 0);
+
+       public static final byte GET_PC =               0x28;
+       public static final byte READ_STATUS =          0x34;
+       public static final byte STATUS_CHIP_ERASE_DONE =       (byte) (1 << 7);
+       public static final byte STATUS_PCON_IDLE =             (1 << 6);
+       public static final byte STATUS_CPU_HALTED =            (1 << 5);
+       public static final byte STATUS_POWER_MODE_0 =          (1 << 4);
+       public static final byte STATUS_HALT_STATUS =           (1 << 3);
+       public static final byte STATUS_DEBUG_LOCKED =          (1 << 2);
+       public static final byte STATUS_OSCILLATOR_STABLE =     (1 << 1);
+       public static final byte STATUS_STACK_OVERFLOW =        (1 << 0);
+
+       public static final byte SET_HW_BRKPNT =        0x3b;
+       public static byte       HW_BRKPNT_N(byte n)    { return (byte) ((n) << 3); }
+       public static final byte HW_BRKPNT_N_MASK =             (0x3 << 3);
+       public static final byte HW_BRKPNT_ENABLE =             (1 << 2);
+
+       public static final byte HALT =                 0x44;
+       public static final byte RESUME =               0x4c;
+       public static       byte DEBUG_INSTR(byte n)    { return (byte) (0x54|(n)); }
+       public static final byte STEP_INSTR =           0x5c;
+       public static        byte STEP_REPLACE(byte n)  { return  (byte) (0x64|(n)); }
+       public static final byte GET_CHIP_ID =          0x68;
+
+
+       boolean debug_mode;
+
+       void ensure_debug_mode() {
+               if (!debug_mode) {
+                       printf("D\n");
+                       flush_input();
+                       debug_mode = true;
+               }
+       }
+
+       void dump_memory(String header, int address, byte[] bytes, int start, int len) {
+               System.out.printf("%s\n", header);
+               for (int j = 0; j < len; j++) {
+                       if ((j & 15) == 0) {
+                               if (j != 0)
+                                       System.out.printf("\n");
+                               System.out.printf ("%04x:", address + j);
+                       }
+                       System.out.printf(" %02x", bytes[start + j]);
+               }
+               System.out.printf("\n");
+       }
+
+       /*
+        * Write target memory
+        */
+       public void write_memory(int address, byte[] bytes, int start, int len) {
+               ensure_debug_mode();
+//             dump_memory("write_memory", address, bytes, start, len);
+               printf("O %x %x\n", len, address);
+               for (int i = 0; i < len; i++)
+                       printf("%02x", bytes[start + i]);
+       }
+
+       public void write_memory(int address, byte[] bytes) {
+               write_memory(address, bytes, 0, bytes.length);
+       }
+
+       /*
+        * Read target memory
+        */
+       public byte[] read_memory(int address, int length)
+               throws IOException, InterruptedException {
+               byte[]  data = new byte[length];
+
+               flush_input();
+               ensure_debug_mode();
+               printf("I %x %x\n", length, address);
+               int i = 0;
+               int start = 0;
+               while (i < length) {
+                       String  line = get_reply().trim();
+                       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) ((Altos.fromhex(line.charAt(j*2)) << 4) +
+                                                 Altos.fromhex(line.charAt(j*2+1)));
+                       start += this_time;
+                       i += this_time;
+               }
+//             dump_memory("read_memory", address, data, 0, length);
+
+               return data;
+       }
+
+       /*
+        * Write raw bytes to the debug link using the 'P' command
+        */
+       public void write_bytes(byte[] bytes) throws IOException {
+               int i = 0;
+               ensure_debug_mode();
+               while (i < bytes.length) {
+                       int this_time = bytes.length - i;
+                       if (this_time > 8)
+                               this_time = 0;
+                       printf("P");
+                       for (int j = 0; j < this_time; j++)
+                               printf(" %02x", bytes[i+j]);
+                       printf("\n");
+                       i += this_time;
+               }
+       }
+
+       public void write_byte(byte b) throws IOException {
+               byte[] bytes = { b };
+               write_bytes(bytes);
+       }
+
+       /*
+        * Read raw bytes from the debug link using the 'G' command
+        */
+       public byte[] read_bytes(int length)
+               throws IOException, InterruptedException {
+
+               flush_input();
+               ensure_debug_mode();
+               printf("G %x\n", length);
+               int i = 0;
+               byte[] data = new byte[length];
+               while (i < length) {
+                       String line = get_reply().trim();
+                       String tokens[] = line.split("\\s+");
+                       for (int j = 0; j < tokens.length; j++) {
+                               if (!Altos.ishex(tokens[j]) ||
+                                   tokens[j].length() != 2)
+                                       throw new IOException(
+                                               String.format
+                                               ("Invalid read_bytes reply \"%s\"", line));
+                               try {
+                                       data[i + j] = (byte) Integer.parseInt(tokens[j], 16);
+                               } catch (NumberFormatException ne) {
+                                       throw new IOException(
+                                               String.format
+                                               ("Invalid read_bytes reply \"%s\"", line));
+                               }
+                       }
+                       i += tokens.length;
+               }
+               return data;
+       }
+
+       public byte read_byte() throws IOException, InterruptedException {
+               return read_bytes(1)[0];
+       }
+
+       public byte debug_instr(byte[] instruction) throws IOException, InterruptedException {
+               byte[] command = new byte[1 + instruction.length];
+               command[0] = DEBUG_INSTR((byte) instruction.length);
+               for (int i = 0; i < instruction.length; i++)
+                       command[i+1] = instruction[i];
+               write_bytes(command);
+               return read_byte();
+       }
+
+       public byte resume() throws IOException, InterruptedException {
+               write_byte(RESUME);
+               return read_byte();
+       }
+
+       public int read_uint16() throws IOException, InterruptedException {
+               byte[] d = read_bytes(2);
+               return ((int) (d[0] & 0xff) << 8) | (d[1] & 0xff);
+       }
+
+       public int read_uint8()  throws IOException, InterruptedException {
+               byte[] d = read_bytes(1);
+               return (int) (d[0] & 0xff);
+       }
+
+       public int get_chip_id() throws IOException, InterruptedException {
+               write_byte(GET_CHIP_ID);
+               return read_uint16();
+       }
+
+       public int get_pc() throws IOException, InterruptedException {
+               write_byte(GET_PC);
+               return read_uint16();
+       }
+
+       public byte read_status() throws IOException, InterruptedException {
+               write_byte(READ_STATUS);
+               return read_byte();
+       }
+
+       static final byte LJMP                  = 0x02;
+
+       public void set_pc(int pc) throws IOException, InterruptedException {
+               byte high = (byte) (pc >> 8);
+               byte low = (byte) pc;
+               byte[] jump_mem = { LJMP, high, low };
+               debug_instr(jump_mem);
+       }
+
+       public boolean check_connection() throws IOException, InterruptedException {
+               byte reply = read_status();
+               if ((reply & STATUS_CHIP_ERASE_DONE) == 0)
+                       return false;
+               if ((reply & STATUS_PCON_IDLE) != 0)
+                       return false;
+               if ((reply & STATUS_POWER_MODE_0) == 0)
+                       return false;
+               return true;
+       }
+
+       public AltosRomconfig romconfig() {
+               try {
+                       byte[] bytes = read_memory(0xa0, 10);
+                       return new AltosRomconfig(bytes, 0);
+               } catch (IOException ie) {
+               } catch (InterruptedException ie) {
+               }
+               return new AltosRomconfig();
+       }
+
+       /*
+        * Reset target
+        */
+       public void reset() {
+               printf ("R\n");
+       }
+
+       public AltosDebug (AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException {
+               super(in_device);
+       }
+}
\ No newline at end of file
diff --git a/altosui/AltosDescent.java b/altosui/AltosDescent.java
new file mode 100644 (file)
index 0000000..16ccd45
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * 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;
+
+public class AltosDescent extends JComponent implements AltosFlightDisplay {
+       GridBagLayout   layout;
+
+       public abstract class DescentStatus {
+               JLabel          label;
+               JTextField      value;
+               AltosLights     lights;
+
+               abstract void show(AltosState state, int crc_errors);
+               void reset() {
+                       value.setText("");
+                       lights.set(false);
+               }
+
+               public DescentStatus (GridBagLayout layout, int y, String text) {
+                       GridBagConstraints      c = new GridBagConstraints();
+                       c.weighty = 1;
+
+                       lights = new AltosLights();
+                       c.gridx = 0; c.gridy = y;
+                       c.anchor = GridBagConstraints.CENTER;
+                       c.fill = GridBagConstraints.VERTICAL;
+                       c.weightx = 0;
+                       layout.setConstraints(lights, c);
+                       add(lights);
+
+                       label = new JLabel(text);
+                       label.setFont(Altos.label_font);
+                       label.setHorizontalAlignment(SwingConstants.LEFT);
+                       c.gridx = 1; c.gridy = y;
+                       c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
+                       c.anchor = GridBagConstraints.WEST;
+                       c.fill = GridBagConstraints.VERTICAL;
+                       c.gridwidth = 3;
+                       c.weightx = 0;
+                       layout.setConstraints(label, c);
+                       add(label);
+
+                       value = new JTextField(Altos.text_width);
+                       value.setFont(Altos.value_font);
+                       value.setHorizontalAlignment(SwingConstants.RIGHT);
+                       c.gridx = 4; c.gridy = y;
+                       c.gridwidth = 1;
+                       c.anchor = GridBagConstraints.WEST;
+                       c.fill = GridBagConstraints.BOTH;
+                       c.weightx = 1;
+                       layout.setConstraints(value, c);
+                       add(value);
+
+               }
+       }
+
+       public abstract class DescentValue {
+               JLabel          label;
+               JTextField      value;
+
+               void reset() {
+                       value.setText("");
+               }
+
+               abstract void show(AltosState state, int crc_errors);
+
+               void show(String format, double v) {
+                       value.setText(String.format(format, v));
+               }
+
+               void show(String v) {
+                       value.setText(v);
+               }
+
+               public DescentValue (GridBagLayout layout, int x, int y, String text) {
+                       GridBagConstraints      c = new GridBagConstraints();
+                       c.weighty = 1;
+
+                       label = new JLabel(text);
+                       label.setFont(Altos.label_font);
+                       label.setHorizontalAlignment(SwingConstants.LEFT);
+                       c.gridx = x + 1; c.gridy = y;
+                       c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
+                       c.anchor = GridBagConstraints.WEST;
+                       c.fill = GridBagConstraints.VERTICAL;
+                       c.weightx = 0;
+                       add(label, c);
+
+                       value = new JTextField(Altos.text_width);
+                       value.setFont(Altos.value_font);
+                       value.setHorizontalAlignment(SwingConstants.RIGHT);
+                       c.gridx = x + 2; c.gridy = y;
+                       c.gridwidth = 1;
+                       c.anchor = GridBagConstraints.WEST;
+                       c.fill = GridBagConstraints.BOTH;
+                       c.weightx = 1;
+                       add(value, c);
+               }
+       }
+
+       public abstract class DescentDualValue {
+               JLabel          label;
+               JTextField      value1;
+               JTextField      value2;
+
+               void reset() {
+                       value1.setText("");
+                       value2.setText("");
+               }
+
+               abstract void show(AltosState state, int crc_errors);
+               void show(String v1, String v2) {
+                       value1.setText(v1);
+                       value2.setText(v2);
+               }
+               void show(String f1, double v1, String f2, double v2) {
+                       value1.setText(String.format(f1, v1));
+                       value2.setText(String.format(f2, v2));
+               }
+
+               public DescentDualValue (GridBagLayout layout, int x, int y, String text) {
+                       GridBagConstraints      c = new GridBagConstraints();
+                       c.weighty = 1;
+
+                       label = new JLabel(text);
+                       label.setFont(Altos.label_font);
+                       label.setHorizontalAlignment(SwingConstants.LEFT);
+                       c.gridx = x + 1; c.gridy = y;
+                       c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
+                       c.anchor = GridBagConstraints.WEST;
+                       c.fill = GridBagConstraints.VERTICAL;
+                       c.weightx = 0;
+                       layout.setConstraints(label, c);
+                       add(label);
+
+                       value1 = new JTextField(Altos.text_width);
+                       value1.setFont(Altos.value_font);
+                       value1.setHorizontalAlignment(SwingConstants.RIGHT);
+                       c.gridx = x + 2; c.gridy = y;
+                       c.anchor = GridBagConstraints.WEST;
+                       c.fill = GridBagConstraints.BOTH;
+                       c.weightx = 1;
+                       layout.setConstraints(value1, c);
+                       add(value1);
+
+                       value2 = new JTextField(Altos.text_width);
+                       value2.setFont(Altos.value_font);
+                       value2.setHorizontalAlignment(SwingConstants.RIGHT);
+                       c.gridx = x + 4; c.gridy = y;
+                       c.anchor = GridBagConstraints.WEST;
+                       c.fill = GridBagConstraints.BOTH;
+                       c.weightx = 1;
+                       c.gridwidth = 1;
+                       layout.setConstraints(value2, c);
+                       add(value2);
+               }
+       }
+
+       class Height extends DescentValue {
+               void show (AltosState state, int crc_errors) {
+                       show("%6.0f m", state.height);
+               }
+               public Height (GridBagLayout layout, int x, int y) {
+                       super (layout, x, y, "Height");
+               }
+       }
+
+       Height  height;
+
+       class Speed extends DescentValue {
+               void show (AltosState state, int crc_errors) {
+                       double speed = state.speed;
+                       if (!state.ascent)
+                               speed = state.baro_speed;
+                       show("%6.0f m/s", speed);
+               }
+               public Speed (GridBagLayout layout, int x, int y) {
+                       super (layout, x, y, "Speed");
+               }
+       }
+
+       Speed   speed;
+
+       String pos(double p, String pos, String neg) {
+               String  h = pos;
+               if (p < 0) {
+                       h = neg;
+                       p = -p;
+               }
+               int deg = (int) Math.floor(p);
+               double min = (p - Math.floor(p)) * 60.0;
+               return String.format("%s %d° %9.6f", h, deg, min);
+       }
+
+       class Lat extends DescentValue {
+               void show (AltosState state, int crc_errors) {
+                       if (state.gps != null)
+                               show(pos(state.gps.lat,"N", "S"));
+                       else
+                               show("???");
+               }
+               public Lat (GridBagLayout layout, int x, int y) {
+                       super (layout, x, y, "Latitude");
+               }
+       }
+
+       Lat lat;
+
+       class Lon extends DescentValue {
+               void show (AltosState state, int crc_errors) {
+                       if (state.gps != null)
+                               show(pos(state.gps.lon,"W", "E"));
+                       else
+                               show("???");
+               }
+               public Lon (GridBagLayout layout, int x, int y) {
+                       super (layout, x, y, "Longitude");
+               }
+       }
+
+       Lon lon;
+
+       class Apogee extends DescentStatus {
+               void show (AltosState state, int crc_errors) {
+                       value.setText(String.format("%4.2f V", state.drogue_sense));
+                       lights.set(state.drogue_sense > 3.2);
+               }
+               public Apogee (GridBagLayout layout, int y) {
+                       super(layout, y, "Apogee Igniter Voltage");
+               }
+       }
+
+       Apogee apogee;
+
+       class Main extends DescentStatus {
+               void show (AltosState state, int crc_errors) {
+                       value.setText(String.format("%4.2f V", state.main_sense));
+                       lights.set(state.main_sense > 3.2);
+               }
+               public Main (GridBagLayout layout, int y) {
+                       super(layout, y, "Main Igniter Voltage");
+               }
+       }
+
+       Main main;
+
+       class Bearing extends DescentDualValue {
+               void show (AltosState state, int crc_errors) {
+                       if (state.from_pad != null) {
+                               show( String.format("%3.0f°", state.from_pad.bearing),
+                                     state.from_pad.bearing_words(
+                                             AltosGreatCircle.BEARING_LONG));
+                       } else {
+                               show("???", "???");
+                       }
+               }
+               public Bearing (GridBagLayout layout, int x, int y) {
+                       super (layout, x, y, "Bearing");
+               }
+       }
+
+       Bearing bearing;
+
+       class Range extends DescentValue {
+               void show (AltosState state, int crc_errors) {
+                       show("%6.0f m", state.range);
+               }
+               public Range (GridBagLayout layout, int x, int y) {
+                       super (layout, x, y, "Range");
+               }
+       }
+
+       Range range;
+
+       class Elevation extends DescentValue {
+               void show (AltosState state, int crc_errors) {
+                       show("%3.0f°", state.elevation);
+               }
+               public Elevation (GridBagLayout layout, int x, int y) {
+                       super (layout, x, y, "Elevation");
+               }
+       }
+
+       Elevation elevation;
+
+       public void reset() {
+               lat.reset();
+               lon.reset();
+               height.reset();
+               speed.reset();
+               bearing.reset();
+               range.reset();
+               elevation.reset();
+               main.reset();
+               apogee.reset();
+       }
+
+       public void show(AltosState state, int crc_errors) {
+               height.show(state, crc_errors);
+               speed.show(state, crc_errors);
+               bearing.show(state, crc_errors);
+               range.show(state, crc_errors);
+               elevation.show(state, crc_errors);
+               lat.show(state, crc_errors);
+               lon.show(state, crc_errors);
+               main.show(state, crc_errors);
+               apogee.show(state, crc_errors);
+       }
+
+       public AltosDescent() {
+               layout = new GridBagLayout();
+
+               setLayout(layout);
+
+               /* Elements in descent display */
+               speed = new Speed(layout, 0, 0);
+               height = new Height(layout, 2, 0);
+               elevation = new Elevation(layout, 0, 1);
+               range = new Range(layout, 2, 1);
+               bearing = new Bearing(layout, 0, 2);
+               lat = new Lat(layout, 0, 3);
+               lon = new Lon(layout, 2, 3);
+
+               apogee = new Apogee(layout, 4);
+               main = new Main(layout, 5);
+       }
+}
diff --git a/altosui/AltosDevice.java b/altosui/AltosDevice.java
new file mode 100644 (file)
index 0000000..f0fda57
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * 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.lang.*;
+import java.util.*;
+import libaltosJNI.*;
+
+public class AltosDevice extends altos_device {
+
+       static public boolean initialized = false;
+       static public boolean loaded_library = false;
+
+       public static boolean load_library() {
+               if (!initialized) {
+                       try {
+                               System.loadLibrary("altos");
+                               libaltos.altos_init();
+                               loaded_library = true;
+                       } catch (UnsatisfiedLinkError e) {
+                               loaded_library = false;
+                       }
+                       initialized = true;
+               }
+               return loaded_library;
+       }
+
+       static int usb_vendor_altusmetrum() {
+               if (load_library())
+                       return libaltosConstants.USB_VENDOR_ALTUSMETRUM;
+               return 0x000a;
+       }
+
+       static int usb_product_altusmetrum() {
+               if (load_library())
+                       return libaltosConstants.USB_PRODUCT_ALTUSMETRUM;
+               return 0x000a;
+       }
+
+       static int usb_product_altusmetrum_min() {
+               if (load_library())
+                       return libaltosConstants.USB_PRODUCT_ALTUSMETRUM_MIN;
+               return 0x000a;
+       }
+
+       static int usb_product_altusmetrum_max() {
+               if (load_library())
+                       return libaltosConstants.USB_PRODUCT_ALTUSMETRUM_MAX;
+               return 0x000d;
+       }
+
+       static int usb_product_telemetrum() {
+               if (load_library())
+                       return libaltosConstants.USB_PRODUCT_TELEMETRUM;
+               return 0x000b;
+       }
+
+       static int usb_product_teledongle() {
+               if (load_library())
+                       return libaltosConstants.USB_PRODUCT_TELEDONGLE;
+               return 0x000c;
+       }
+
+       static int usb_product_teleterra() {
+               if (load_library())
+                       return libaltosConstants.USB_PRODUCT_TELETERRA;
+               return 0x000d;
+       }
+
+       public final static int vendor_altusmetrum = usb_vendor_altusmetrum();
+       public final static int product_altusmetrum = usb_product_altusmetrum();
+       public final static int product_telemetrum = usb_product_telemetrum();
+       public final static int product_teledongle = usb_product_teledongle();
+       public final static int product_teleterra = usb_product_teleterra();
+       public final static int product_altusmetrum_min = usb_product_altusmetrum_min();
+       public final static int product_altusmetrum_max = usb_product_altusmetrum_max();
+
+
+       public final static int product_any = 0x10000;
+       public final static int product_basestation = 0x10000 + 1;
+
+       public String toString() {
+               String  name = getName();
+               if (name == null)
+                       name = "Altus Metrum";
+               return String.format("%-20.20s %4d %s",
+                                    getName(), getSerial(), getPath());
+       }
+
+       public String toShortString() {
+               String  name = getName();
+               if (name == null)
+                       name = "Altus Metrum";
+               return String.format("%s %d %s",
+                                    name, getSerial(), getPath());
+
+       }
+
+       public boolean isAltusMetrum() {
+               if (getVendor() != vendor_altusmetrum)
+                       return false;
+               if (getProduct() < product_altusmetrum_min)
+                       return false;
+               if (getProduct() > product_altusmetrum_max)
+                       return false;
+               return true;
+       }
+
+       public boolean matchProduct(int want_product) {
+
+               if (!isAltusMetrum())
+                       return false;
+
+               if (want_product == product_any)
+                       return true;
+
+               if (want_product == product_basestation)
+                       return matchProduct(product_teledongle) || matchProduct(product_teleterra);
+
+               int have_product = getProduct();
+
+               if (have_product == product_altusmetrum)        /* old devices match any request */
+                       return true;
+
+               if (want_product == have_product)
+                       return true;
+
+               return false;
+       }
+
+       static AltosDevice[] list(int product) {
+               if (!load_library())
+                       return null;
+
+               SWIGTYPE_p_altos_list list = libaltos.altos_list_start();
+
+               ArrayList<AltosDevice> device_list = new ArrayList<AltosDevice>();
+               if (list != null) {
+                       SWIGTYPE_p_altos_file file;
+
+                       for (;;) {
+                               AltosDevice device = new AltosDevice();
+                               if (libaltos.altos_list_next(list, device) == 0)
+                                       break;
+                               if (device.matchProduct(product))
+                                       device_list.add(device);
+                       }
+                       libaltos.altos_list_finish(list);
+               }
+
+               AltosDevice[] devices = new AltosDevice[device_list.size()];
+               for (int i = 0; i < device_list.size(); i++)
+                       devices[i] = device_list.get(i);
+               return devices;
+       }
+}
\ No newline at end of file
diff --git a/altosui/AltosDeviceDialog.java b/altosui/AltosDeviceDialog.java
new file mode 100644 (file)
index 0000000..2966ad1
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * 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.lang.*;
+import java.util.*;
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.*;
+import libaltosJNI.libaltos;
+import libaltosJNI.altos_device;
+import libaltosJNI.SWIGTYPE_p_altos_file;
+import libaltosJNI.SWIGTYPE_p_altos_list;
+
+public class AltosDeviceDialog extends JDialog implements ActionListener {
+
+       private static AltosDeviceDialog        dialog;
+       private static AltosDevice              value = null;
+       private JList                           list;
+
+       public static AltosDevice show (Component frameComp, int product) {
+
+               Frame frame = JOptionPane.getFrameForComponent(frameComp);
+               AltosDevice[]   devices;
+               devices = AltosDevice.list(product);
+
+               if (devices != null && devices.length > 0) {
+                       value = null;
+                       dialog = new AltosDeviceDialog(frame, frameComp,
+                                                      devices,
+                                                      devices[0]);
+
+                       dialog.setVisible(true);
+                       return value;
+               } else {
+                       /* check for missing altos JNI library, which
+                        * will put up its own error dialog
+                        */
+                       if (AltosUI.load_library(frame)) {
+                               JOptionPane.showMessageDialog(frame,
+                                                             "No AltOS devices available",
+                                                             "No AltOS devices",
+                                                             JOptionPane.ERROR_MESSAGE);
+                       }
+                       return null;
+               }
+       }
+
+       private AltosDeviceDialog (Frame frame, Component location,
+                                  AltosDevice[] devices,
+                                  AltosDevice initial) {
+               super(frame, "Device Selection", true);
+
+               value = null;
+
+               JButton cancelButton = new JButton("Cancel");
+               cancelButton.addActionListener(this);
+
+               final JButton selectButton = new JButton("Select");
+               selectButton.setActionCommand("select");
+               selectButton.addActionListener(this);
+               getRootPane().setDefaultButton(selectButton);
+
+               list = new JList(devices) {
+                               //Subclass JList to workaround bug 4832765, which can cause the
+                               //scroll pane to not let the user easily scroll up to the beginning
+                               //of the list.  An alternative would be to set the unitIncrement
+                               //of the JScrollBar to a fixed value. You wouldn't get the nice
+                               //aligned scrolling, but it should work.
+                               public int getScrollableUnitIncrement(Rectangle visibleRect,
+                                                                     int orientation,
+                                                                     int direction) {
+                                       int row;
+                                       if (orientation == SwingConstants.VERTICAL &&
+                                           direction < 0 && (row = getFirstVisibleIndex()) != -1) {
+                                               Rectangle r = getCellBounds(row, row);
+                                               if ((r.y == visibleRect.y) && (row != 0))  {
+                                                       Point loc = r.getLocation();
+                                                       loc.y--;
+                                                       int prevIndex = locationToIndex(loc);
+                                                       Rectangle prevR = getCellBounds(prevIndex, prevIndex);
+
+                                                       if (prevR == null || prevR.y >= r.y) {
+                                                               return 0;
+                                                       }
+                                                       return prevR.height;
+                                               }
+                                       }
+                                       return super.getScrollableUnitIncrement(
+                                               visibleRect, orientation, direction);
+                               }
+                       };
+
+               list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+               list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
+               list.setVisibleRowCount(-1);
+               list.addMouseListener(new MouseAdapter() {
+                                public void mouseClicked(MouseEvent e) {
+                                        if (e.getClickCount() == 2) {
+                                                selectButton.doClick(); //emulate button click
+                                        }
+                                }
+                       });
+               JScrollPane listScroller = new JScrollPane(list);
+               listScroller.setPreferredSize(new Dimension(400, 80));
+               listScroller.setAlignmentX(LEFT_ALIGNMENT);
+
+               //Create a container so that we can add a title around
+               //the scroll pane.  Can't add a title directly to the
+               //scroll pane because its background would be white.
+               //Lay out the label and scroll pane from top to bottom.
+               JPanel listPane = new JPanel();
+               listPane.setLayout(new BoxLayout(listPane, BoxLayout.PAGE_AXIS));
+
+               JLabel label = new JLabel("Select Device");
+               label.setLabelFor(list);
+               listPane.add(label);
+               listPane.add(Box.createRigidArea(new Dimension(0,5)));
+               listPane.add(listScroller);
+               listPane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
+
+               //Lay out the buttons from left to right.
+               JPanel buttonPane = new JPanel();
+               buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS));
+               buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
+               buttonPane.add(Box.createHorizontalGlue());
+               buttonPane.add(cancelButton);
+               buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
+               buttonPane.add(selectButton);
+
+               //Put everything together, using the content pane's BorderLayout.
+               Container contentPane = getContentPane();
+               contentPane.add(listPane, BorderLayout.CENTER);
+               contentPane.add(buttonPane, BorderLayout.PAGE_END);
+
+               //Initialize values.
+               list.setSelectedValue(initial, true);
+               pack();
+               setLocationRelativeTo(location);
+       }
+
+       //Handle clicks on the Set and Cancel buttons.
+       public void actionPerformed(ActionEvent e) {
+               if ("select".equals(e.getActionCommand()))
+                       AltosDeviceDialog.value = (AltosDevice)(list.getSelectedValue());
+               AltosDeviceDialog.dialog.setVisible(false);
+       }
+
+}
diff --git a/altosui/AltosDisplayThread.java b/altosui/AltosDisplayThread.java
new file mode 100644 (file)
index 0000000..3e71913
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * 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;
+
+public class AltosDisplayThread extends Thread {
+
+       Frame                   parent;
+       IdleThread              idle_thread;
+       AltosVoice              voice;
+       String                  name;
+       AltosFlightReader       reader;
+       int                     crc_errors;
+       AltosFlightDisplay      display;
+
+       synchronized void show(AltosState state, int crc_errors) {
+               if (state != null)
+                       display.show(state, crc_errors);
+       }
+
+       class IdleThread extends Thread {
+
+               boolean started;
+               private AltosState state;
+               int     reported_landing;
+               int     report_interval;
+               long    report_time;
+
+               public synchronized void report(boolean last) {
+                       if (state == null)
+                               return;
+
+                       /* reset the landing count once we hear about a new flight */
+                       if (state.state < Altos.ao_flight_drogue)
+                               reported_landing = 0;
+
+                       /* Shut up once the rocket is on the ground */
+                       if (reported_landing > 2) {
+                               return;
+                       }
+
+                       /* If the rocket isn't on the pad, then report height */
+                       if (Altos.ao_flight_drogue <= state.state &&
+                           state.state < Altos.ao_flight_landed &&
+                           state.range >= 0)
+                       {
+                               voice.speak("Height %d, bearing %s %d, elevation %d, range %d.\n",
+                                           (int) (state.height + 0.5),
+                        state.from_pad.bearing_words(
+                            AltosGreatCircle.BEARING_VOICE),
+                                           (int) (state.from_pad.bearing + 0.5),
+                                           (int) (state.elevation + 0.5),
+                                           (int) (state.range + 0.5));
+                       } else if (state.state > Altos.ao_flight_pad) {
+                               voice.speak("%d meters", (int) (state.height + 0.5));
+                       } else {
+                               reported_landing = 0;
+                       }
+
+                       /* If the rocket is coming down, check to see if it has landed;
+                        * either we've got a landed report or we haven't heard from it in
+                        * a long time
+                        */
+                       if (state.state >= Altos.ao_flight_drogue &&
+                           (last ||
+                            System.currentTimeMillis() - state.report_time >= 15000 ||
+                            state.state == Altos.ao_flight_landed))
+                       {
+                               if (Math.abs(state.baro_speed) < 20 && state.height < 100)
+                                       voice.speak("rocket landed safely");
+                               else
+                                       voice.speak("rocket may have crashed");
+                               if (state.from_pad != null)
+                                       voice.speak("Bearing %d degrees, range %d meters.",
+                                                   (int) (state.from_pad.bearing + 0.5),
+                                                   (int) (state.from_pad.distance + 0.5));
+                               ++reported_landing;
+                               if (state.state != Altos.ao_flight_landed) {
+                                       state.state = Altos.ao_flight_landed;
+                                       show(state, 0);
+                               }
+                       }
+               }
+
+               long now () {
+                       return System.currentTimeMillis();
+               }
+
+               void set_report_time() {
+                       report_time = now() + report_interval;
+               }
+
+               public void run () {
+                       try {
+                               for (;;) {
+                                       set_report_time();
+                                       for (;;) {
+                                               voice.drain();
+                                               synchronized (this) {
+                                                       long    sleep_time = report_time - now();
+                                                       if (sleep_time <= 0)
+                                                               break;
+                                                       wait(sleep_time);
+                                               }
+                                       }
+                                       report(false);
+                               }
+                       } catch (InterruptedException ie) {
+                               try {
+                                       voice.drain();
+                               } catch (InterruptedException iie) { }
+                       }
+               }
+
+               public synchronized void notice(AltosState new_state, boolean spoken) {
+                       AltosState old_state = state;
+                       state = new_state;
+                       if (!started && state.state > Altos.ao_flight_pad) {
+                               started = true;
+                               start();
+                       }
+
+                       if (state.state < Altos.ao_flight_drogue)
+                               report_interval = 10000;
+                       else
+                               report_interval = 20000;
+                       if (old_state != null && old_state.state != state.state) {
+                               report_time = now();
+                               this.notify();
+                       } else if (spoken)
+                               set_report_time();
+               }
+
+               public IdleThread() {
+                       state = null;
+                       reported_landing = 0;
+                       report_interval = 10000;
+               }
+       }
+
+       boolean tell(AltosState state, AltosState old_state) {
+               boolean ret = false;
+               if (old_state == null || old_state.state != state.state) {
+                       voice.speak(state.data.state());
+                       if ((old_state == null || old_state.state <= Altos.ao_flight_boost) &&
+                           state.state > Altos.ao_flight_boost) {
+                               voice.speak("max speed: %d meters per second.",
+                                           (int) (state.max_speed + 0.5));
+                               ret = true;
+                       } else if ((old_state == null || old_state.state < Altos.ao_flight_drogue) &&
+                                  state.state >= Altos.ao_flight_drogue) {
+                               voice.speak("max height: %d meters.",
+                                           (int) (state.max_height + 0.5));
+                               ret = true;
+                       }
+               }
+               if (old_state == null || old_state.gps_ready != state.gps_ready) {
+                       if (state.gps_ready) {
+                               voice.speak("GPS ready");
+                               ret = true;
+                       }
+                       else if (old_state != null) {
+                               voice.speak("GPS lost");
+                               ret = true;
+                       }
+               }
+               old_state = state;
+               return ret;
+       }
+
+       public void run() {
+               boolean         interrupted = false;
+               String          line;
+               AltosState      state = null;
+               AltosState      old_state = null;
+               boolean         told;
+
+               idle_thread = new IdleThread();
+
+               display.reset();
+               try {
+                       for (;;) {
+                               try {
+                                       AltosRecord record = reader.read();
+                                       if (record == null)
+                                               break;
+                                       old_state = state;
+                                       state = new AltosState(record, state);
+                                       reader.update(state);
+                                       show(state, crc_errors);
+                                       told = tell(state, old_state);
+                                       idle_thread.notice(state, told);
+                               } catch (ParseException pp) {
+                                       System.out.printf("Parse error: %d \"%s\"\n", pp.getErrorOffset(), pp.getMessage());
+                               } catch (AltosCRCException ce) {
+                                       ++crc_errors;
+                                       show(state, crc_errors);
+                               }
+                       }
+               } catch (InterruptedException ee) {
+                       interrupted = true;
+               } catch (IOException ie) {
+                       JOptionPane.showMessageDialog(parent,
+                                                     String.format("Error reading from \"%s\"", name),
+                                                     "Telemetry Read Error",
+                                                     JOptionPane.ERROR_MESSAGE);
+               } finally {
+                       if (!interrupted)
+                               idle_thread.report(true);
+                       reader.close(interrupted);
+                       idle_thread.interrupt();
+                       try {
+                               idle_thread.join();
+                       } catch (InterruptedException ie) {}
+               }
+       }
+
+       public AltosDisplayThread(Frame in_parent, AltosVoice in_voice, AltosFlightDisplay in_display, AltosFlightReader in_reader) {
+               parent = in_parent;
+               voice = in_voice;
+               display = in_display;
+               reader = in_reader;
+       }
+}
diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java
new file mode 100644 (file)
index 0000000..02fc36f
--- /dev/null
@@ -0,0 +1,285 @@
+/*
+ * 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.*;
+
+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;
+
+       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  line = serial_line.get_reply(5000);
+
+                       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_pending.add(String.format("%s\n", line));
+
+                       /* signals the end of the version info */
+                       if (line.startsWith("software-version"))
+                               break;
+               }
+               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);
+
+                                       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;
+                                       }
+
+                                       if (cmd == Altos.AO_LOG_GPS_DATE) {
+                                               year = 2000 + (a & 0xff);
+                                               month = (a >> 8) & 0xff;
+                                               day = (b & 0xff);
+                                               want_file = 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.set_file(eeprom_name.getName());
+                                                       eeprom_file = new FileWriter(eeprom_name);
+                                                       if (eeprom_file != null) {
+                                                               FlushPending(eeprom_file, eeprom_pending);
+                                                               eeprom_pending = null;
+                                                       }
+                                               }
+                                       }
+
+                                       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);
+
+                                       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);
+                       }
+               }
+               if (eeprom_file != null) {
+                       eeprom_file.flush();
+                       eeprom_file.close();
+               }
+       }
+
+       public void run () {
+               if (remote) {
+                       serial_line.set_radio();
+                       serial_line.printf("p\nE 0\n");
+                       serial_line.flush_input();
+               }
+
+               monitor = new AltosEepromMonitor(frame, Altos.ao_flight_boost, Altos.ao_flight_landed);
+               monitor.addActionListener(new ActionListener() {
+                               public void actionPerformed(ActionEvent e) {
+                                       eeprom_thread.interrupt();
+                               }
+                       });
+               try {
+                       CaptureLog();
+               } catch (IOException ee) {
+                       JOptionPane.showMessageDialog(frame,
+                                                     device.toShortString(),
+                                                     ee.getLocalizedMessage(),
+                                                     JOptionPane.ERROR_MESSAGE);
+               } catch (InterruptedException ie) {
+               } catch (TimeoutException te) {
+                       JOptionPane.showMessageDialog(frame,
+                                                     String.format("Connection to \"%s\" failed",
+                                                                   device.toShortString()),
+                                                     "Connection Failed",
+                                                     JOptionPane.ERROR_MESSAGE);
+               }
+               if (remote)
+                       serial_line.printf("~");
+               monitor.done();
+               serial_line.flush_output();
+               serial_line.close();
+       }
+
+       public AltosEepromDownload(JFrame given_frame) {
+               frame = given_frame;
+               device = AltosDeviceDialog.show(frame, AltosDevice.product_any);
+
+               remote = false;
+
+               if (device != null) {
+                       try {
+                               serial_line = new AltosSerial(device);
+                               if (!device.matchProduct(AltosDevice.product_telemetrum))
+                                       remote = true;
+                               eeprom_thread = new Thread(this);
+                               eeprom_thread.start();
+                       } catch (FileNotFoundException ee) {
+                               JOptionPane.showMessageDialog(frame,
+                                                             String.format("Cannot open device \"%s\"",
+                                                                           device.toShortString()),
+                                                             "Cannot open target device",
+                                                             JOptionPane.ERROR_MESSAGE);
+                       } catch (AltosSerialInUseException si) {
+                               JOptionPane.showMessageDialog(frame,
+                                                             String.format("Device \"%s\" already in use",
+                                                                           device.toShortString()),
+                                                             "Device in use",
+                                                             JOptionPane.ERROR_MESSAGE);
+                       } catch (IOException ee) {
+                               JOptionPane.showMessageDialog(frame,
+                                                             device.toShortString(),
+                                                             ee.getLocalizedMessage(),
+                                                             JOptionPane.ERROR_MESSAGE);
+                       }
+               }
+       }
+}
diff --git a/altosui/AltosEepromIterable.java b/altosui/AltosEepromIterable.java
new file mode 100644 (file)
index 0000000..f8e6d7e
--- /dev/null
@@ -0,0 +1,423 @@
+/*
+ * 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;
+
+/*
+ * AltosRecords with an index field so they can be sorted by tick while preserving
+ * the original ordering for elements with matching ticks
+ */
+class AltosOrderedRecord extends AltosEepromRecord implements Comparable<AltosOrderedRecord> {
+
+       public int      index;
+
+       public AltosOrderedRecord(String line, int in_index, int prev_tick, boolean prev_tick_valid)
+               throws ParseException {
+               super(line);
+               if (prev_tick_valid) {
+                       tick |= (prev_tick & ~0xffff);
+                       if (tick < prev_tick) {
+                               if (prev_tick - tick > 0x8000)
+                                       tick += 0x10000;
+                       } else {
+                               if (tick - prev_tick > 0x8000)
+                                       tick -= 0x10000;
+                       }
+               }
+               index = in_index;
+       }
+
+       public AltosOrderedRecord(int in_cmd, int in_tick, int in_a, int in_b, int in_index) {
+               super(in_cmd, in_tick, in_a, in_b);
+               index = in_index;
+       }
+
+       public int compareTo(AltosOrderedRecord o) {
+               int     tick_diff = tick - o.tick;
+               if (tick_diff != 0)
+                       return tick_diff;
+               return index - o.index;
+       }
+}
+
+public class AltosEepromIterable extends AltosRecordIterable {
+
+       static final int        seen_flight = 1;
+       static final int        seen_sensor = 2;
+       static final int        seen_temp_volt = 4;
+       static final int        seen_deploy = 8;
+       static final int        seen_gps_time = 16;
+       static final int        seen_gps_lat = 32;
+       static final int        seen_gps_lon = 64;
+
+       static final int        seen_basic = seen_flight|seen_sensor|seen_temp_volt|seen_deploy;
+
+       AltosEepromRecord       flight_record;
+       AltosEepromRecord       gps_date_record;
+
+       TreeSet<AltosOrderedRecord>     records;
+
+       LinkedList<AltosRecord> list;
+
+       class EepromState {
+               int     seen;
+               int     n_pad_samples;
+               double  ground_pres;
+               int     gps_tick;
+               int     boost_tick;
+
+               EepromState() {
+                       seen = 0;
+                       n_pad_samples = 0;
+                       ground_pres = 0.0;
+                       gps_tick = 0;
+               }
+       }
+
+       void update_state(AltosRecord state, AltosEepromRecord record, EepromState eeprom) {
+               state.tick = record.tick;
+               switch (record.cmd) {
+               case Altos.AO_LOG_FLIGHT:
+                       eeprom.seen |= seen_flight;
+                       state.ground_accel = record.a;
+                       state.flight_accel = record.a;
+                       state.flight = record.b;
+                       eeprom.boost_tick = record.tick;
+                       break;
+               case Altos.AO_LOG_SENSOR:
+                       state.accel = record.a;
+                       state.pres = record.b;
+                       if (state.state < Altos.ao_flight_boost) {
+                               eeprom.n_pad_samples++;
+                               eeprom.ground_pres += state.pres;
+                               state.ground_pres = (int) (eeprom.ground_pres / eeprom.n_pad_samples);
+                               state.flight_pres = state.ground_pres;
+                       } else {
+                               state.flight_pres = (state.flight_pres * 15 + state.pres) / 16;
+                               state.flight_accel = (state.flight_accel * 15 + state.accel) / 16;
+                               state.flight_vel += (state.accel_plus_g - state.accel);
+                       }
+                       eeprom.seen |= seen_sensor;
+                       break;
+               case Altos.AO_LOG_TEMP_VOLT:
+                       state.temp = record.a;
+                       state.batt = record.b;
+                       eeprom.seen |= seen_temp_volt;
+                       break;
+               case Altos.AO_LOG_DEPLOY:
+                       state.drogue = record.a;
+                       state.main = record.b;
+                       eeprom.seen |= seen_deploy;
+                       break;
+               case Altos.AO_LOG_STATE:
+                       state.state = record.a;
+                       break;
+               case Altos.AO_LOG_GPS_TIME:
+                       eeprom.gps_tick = state.tick;
+                       AltosGPS old = state.gps;
+                       state.gps = new AltosGPS();
+
+                       /* GPS date doesn't get repeated through the file */
+                       if (old != null) {
+                               state.gps.year = old.year;
+                               state.gps.month = old.month;
+                               state.gps.day = old.day;
+                       }
+                       state.gps.hour = (record.a & 0xff);
+                       state.gps.minute = (record.a >> 8);
+                       state.gps.second = (record.b & 0xff);
+
+                       int flags = (record.b >> 8);
+                       state.gps.connected = (flags & Altos.AO_GPS_RUNNING) != 0;
+                       state.gps.locked = (flags & Altos.AO_GPS_VALID) != 0;
+                       state.gps.date_valid = (flags & Altos.AO_GPS_DATE_VALID) != 0;
+                       state.gps.nsat = (flags & Altos.AO_GPS_NUM_SAT_MASK) >>
+                               Altos.AO_GPS_NUM_SAT_SHIFT;
+                       break;
+               case Altos.AO_LOG_GPS_LAT:
+                       int lat32 = record.a | (record.b << 16);
+                       state.gps.lat = (double) lat32 / 1e7;
+                       break;
+               case Altos.AO_LOG_GPS_LON:
+                       int lon32 = record.a | (record.b << 16);
+                       state.gps.lon = (double) lon32 / 1e7;
+                       break;
+               case Altos.AO_LOG_GPS_ALT:
+                       state.gps.alt = record.a;
+                       break;
+               case Altos.AO_LOG_GPS_SAT:
+                       if (state.tick == eeprom.gps_tick) {
+                               int svid = record.a;
+                               int c_n0 = record.b >> 8;
+                               state.gps.add_sat(svid, c_n0);
+                       }
+                       break;
+               case Altos.AO_LOG_GPS_DATE:
+                       state.gps.year = (record.a & 0xff) + 2000;
+                       state.gps.month = record.a >> 8;
+                       state.gps.day = record.b & 0xff;
+                       break;
+
+               case Altos.AO_LOG_CONFIG_VERSION:
+                       break;
+               case Altos.AO_LOG_MAIN_DEPLOY:
+                       break;
+               case Altos.AO_LOG_APOGEE_DELAY:
+                       break;
+               case Altos.AO_LOG_RADIO_CHANNEL:
+                       break;
+               case Altos.AO_LOG_CALLSIGN:
+                       state.callsign = record.data;
+                       break;
+               case Altos.AO_LOG_ACCEL_CAL:
+                       state.accel_plus_g = record.a;
+                       state.accel_minus_g = record.b;
+                       break;
+               case Altos.AO_LOG_RADIO_CAL:
+                       break;
+               case Altos.AO_LOG_MANUFACTURER:
+                       break;
+               case Altos.AO_LOG_PRODUCT:
+                       break;
+               case Altos.AO_LOG_SERIAL_NUMBER:
+                       state.serial = record.a;
+                       break;
+               case Altos.AO_LOG_SOFTWARE_VERSION:
+                       break;
+               }
+       }
+
+       LinkedList<AltosRecord> make_list() {
+               LinkedList<AltosRecord>         list = new LinkedList<AltosRecord>();
+               Iterator<AltosOrderedRecord>    iterator = records.iterator();
+               AltosOrderedRecord              record = null;
+               AltosRecord                     state = new AltosRecord();
+               boolean                         last_reported = false;
+               EepromState                     eeprom = new EepromState();
+
+               state.state = Altos.ao_flight_pad;
+               state.accel_plus_g = 15758;
+               state.accel_minus_g = 16294;
+
+               /* Pull in static data from the flight and gps_date records */
+               if (flight_record != null)
+                       update_state(state, flight_record, eeprom);
+               if (gps_date_record != null)
+                       update_state(state, gps_date_record, eeprom);
+
+               while (iterator.hasNext()) {
+                       record = iterator.next();
+                       if ((eeprom.seen & seen_basic) == seen_basic && record.tick != state.tick) {
+                               AltosRecord r = new AltosRecord(state);
+                               r.time = (r.tick - eeprom.boost_tick) / 100.0;
+                               list.add(r);
+                       }
+                       update_state(state, record, eeprom);
+               }
+               AltosRecord r = new AltosRecord(state);
+               r.time = (r.tick - eeprom.boost_tick) / 100.0;
+               list.add(r);
+               return list;
+       }
+
+       public Iterator<AltosRecord> iterator() {
+               if (list == null)
+                       list = make_list();
+               return list.iterator();
+       }
+
+       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) {
+                       case Altos.AO_LOG_CONFIG_VERSION:
+                               out.printf("# Config version: %s\n", record.data);
+                               break;
+                       case Altos.AO_LOG_MAIN_DEPLOY:
+                               out.printf("# Main deploy: %s\n", record.a);
+                               break;
+                       case Altos.AO_LOG_APOGEE_DELAY:
+                               out.printf("# Apogee delay: %s\n", record.a);
+                               break;
+                       case Altos.AO_LOG_RADIO_CHANNEL:
+                               out.printf("# Radio channel: %s\n", record.a);
+                               break;
+                       case Altos.AO_LOG_CALLSIGN:
+                               out.printf("# Callsign: %s\n", record.data);
+                               break;
+                       case Altos.AO_LOG_ACCEL_CAL:
+                               out.printf ("# Accel cal: %d %d\n", record.a, record.b);
+                               break;
+                       case Altos.AO_LOG_RADIO_CAL:
+                               out.printf ("# Radio cal: %d\n", record.a);
+                               break;
+                       case Altos.AO_LOG_MANUFACTURER:
+                               out.printf ("# Manufacturer: %s\n", record.data);
+                               break;
+                       case Altos.AO_LOG_PRODUCT:
+                               out.printf ("# Product: %s\n", record.data);
+                               break;
+                       case Altos.AO_LOG_SERIAL_NUMBER:
+                               out.printf ("# Serial number: %d\n", record.a);
+                               break;
+                       case Altos.AO_LOG_SOFTWARE_VERSION:
+                               out.printf ("# Software version: %s\n", record.data);
+                               break;
+                       }
+               }
+       }
+
+       /*
+        * Given an AO_LOG_GPS_TIME record with correct time, and one
+        * missing time, rewrite the missing time values with the good
+        * ones, assuming that the difference between them is 'diff' seconds
+        */
+       void update_time(AltosOrderedRecord good, AltosOrderedRecord bad) {
+
+               int diff = (bad.tick - good.tick + 50) / 100;
+
+               int hour = (good.a & 0xff);
+               int minute = (good.a >> 8);
+               int second = (good.b & 0xff);
+               int flags = (good.b >> 8);
+               int seconds = hour * 3600 + minute * 60 + second;
+
+               /* Make sure this looks like a good GPS value */
+               if ((flags & Altos.AO_GPS_NUM_SAT_MASK) >> Altos.AO_GPS_NUM_SAT_SHIFT < 4)
+                       flags = (flags & ~Altos.AO_GPS_NUM_SAT_MASK) | (4 << Altos.AO_GPS_NUM_SAT_SHIFT);
+               flags |= Altos.AO_GPS_RUNNING;
+               flags |= Altos.AO_GPS_VALID;
+
+               int new_seconds = seconds + diff;
+               if (new_seconds < 0)
+                       new_seconds += 24 * 3600;
+               int new_second = (new_seconds % 60);
+               int new_minutes = (new_seconds / 60);
+               int new_minute = (new_minutes % 60);
+               int new_hours = (new_minutes / 60);
+               int new_hour = (new_hours % 24);
+
+               bad.a = new_hour + (new_minute << 8);
+               bad.b = new_second + (flags << 8);
+       }
+
+       /*
+        * Read the whole file, dumping records into a RB tree so
+        * we can enumerate them in time order -- the eeprom data
+        * are sometimes out of order with GPS data getting timestamps
+        * matching the first packet out of the GPS unit but not
+        * written until the final GPS packet has been received.
+        */
+       public AltosEepromIterable (FileInputStream input) {
+               records = new TreeSet<AltosOrderedRecord>();
+
+               AltosOrderedRecord last_gps_time = null;
+
+               int index = 0;
+               int prev_tick = 0;
+               boolean prev_tick_valid = false;
+               boolean missing_time = false;
+
+               try {
+                       for (;;) {
+                               String line = AltosRecord.gets(input);
+                               if (line == null)
+                                       break;
+                               AltosOrderedRecord record = new AltosOrderedRecord(line, index++, prev_tick, prev_tick_valid);
+                               if (record == null)
+                                       break;
+                               if (record.cmd == Altos.AO_LOG_INVALID)
+                                       continue;
+                               prev_tick = record.tick;
+                               if (record.cmd < Altos.AO_LOG_CONFIG_VERSION)
+                                       prev_tick_valid = true;
+                               if (record.cmd == Altos.AO_LOG_FLIGHT) {
+                                       flight_record = record;
+                                       continue;
+                               }
+
+                               /* Two firmware bugs caused the loss of some GPS data.
+                                * The flight date would never be recorded, and often
+                                * the flight time would get overwritten by another
+                                * record. Detect the loss of the GPS date and fix up the
+                                * missing time records
+                                */
+                               if (record.cmd == Altos.AO_LOG_GPS_DATE) {
+                                       gps_date_record = record;
+                                       continue;
+                               }
+
+                               /* go back and fix up any missing time values */
+                               if (record.cmd == Altos.AO_LOG_GPS_TIME) {
+                                       last_gps_time = record;
+                                       if (missing_time) {
+                                               Iterator<AltosOrderedRecord> iterator = records.iterator();
+                                               while (iterator.hasNext()) {
+                                                       AltosOrderedRecord old = iterator.next();
+                                                       if (old.cmd == Altos.AO_LOG_GPS_TIME &&
+                                                           old.a == -1 && old.b == -1)
+                                                       {
+                                                               update_time(record, old);
+                                                       }
+                                               }
+                                               missing_time = false;
+                                       }
+                               }
+
+                               if (record.cmd == Altos.AO_LOG_GPS_LAT) {
+                                       if (last_gps_time == null || last_gps_time.tick != record.tick) {
+                                               AltosOrderedRecord add_gps_time = new AltosOrderedRecord(Altos.AO_LOG_GPS_TIME,
+                                                                                                        record.tick,
+                                                                                                        -1, -1, index-1);
+                                               if (last_gps_time != null)
+                                                       update_time(last_gps_time, add_gps_time);
+                                               else
+                                                       missing_time = true;
+
+                                               records.add(add_gps_time);
+                                               record.index = index++;
+                                       }
+                               }
+                               records.add(record);
+
+                               /* Bail after reading the 'landed' record; we're all done */
+                               if (record.cmd == Altos.AO_LOG_STATE &&
+                                   record.a == Altos.ao_flight_landed)
+                                       break;
+                       }
+               } catch (IOException io) {
+               } catch (ParseException pe) {
+               }
+               try {
+                       input.close();
+               } catch (IOException ie) {
+               }
+       }
+}
diff --git a/altosui/AltosEepromMonitor.java b/altosui/AltosEepromMonitor.java
new file mode 100644 (file)
index 0000000..7ff00ea
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * 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;
+
+public class AltosEepromMonitor extends JDialog {
+
+       Container       pane;
+       Box             box;
+       JLabel          serial_label;
+       JLabel          flight_label;
+       JLabel          file_label;
+       JLabel          serial_value;
+       JLabel          flight_value;
+       JLabel          file_value;
+       JButton         cancel;
+       JProgressBar    pbar;
+       int             min_state, max_state;
+
+       public AltosEepromMonitor(JFrame owner, int in_min_state, int in_max_state) {
+               super (owner, "Download Flight Data", false);
+
+               GridBagConstraints c;
+               Insets il = new Insets(4,4,4,4);
+               Insets ir = new Insets(4,4,4,4);
+
+               pane = getContentPane();
+               pane.setLayout(new GridBagLayout());
+
+               c = new GridBagConstraints();
+               c.gridx = 0; c.gridy = 0;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = il;
+               serial_label = new JLabel("Serial:");
+               pane.add(serial_label, c);
+
+               c = new GridBagConstraints();
+               c.gridx = 1; c.gridy = 0;
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.weightx = 1;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = ir;
+               serial_value = new JLabel("");
+               pane.add(serial_value, c);
+
+               c = new GridBagConstraints();
+               c.fill = GridBagConstraints.NONE;
+               c.gridx = 0; c.gridy = 1;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = il;
+               flight_label = new JLabel("Flight:");
+               pane.add(flight_label, c);
+
+               c = new GridBagConstraints();
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.weightx = 1;
+               c.gridx = 1; c.gridy = 1;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = ir;
+               flight_value = new JLabel("");
+               pane.add(flight_value, c);
+
+               c = new GridBagConstraints();
+               c.fill = GridBagConstraints.NONE;
+               c.gridx = 0; c.gridy = 2;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = il;
+               file_label = new JLabel("File:");
+               pane.add(file_label, c);
+
+               c = new GridBagConstraints();
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.weightx = 1;
+               c.gridx = 1; c.gridy = 2;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = ir;
+               file_value = new JLabel("");
+               pane.add(file_value, c);
+
+               min_state = in_min_state;
+               max_state = in_max_state;
+               pbar = new JProgressBar();
+               pbar.setMinimum(0);
+               pbar.setMaximum((max_state - min_state) * 100);
+               pbar.setValue(0);
+               pbar.setString("startup");
+               pbar.setStringPainted(true);
+               pbar.setPreferredSize(new Dimension(600, 20));
+               c = new GridBagConstraints();
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.anchor = GridBagConstraints.CENTER;
+               c.gridx = 0; c.gridy = 3;
+               c.gridwidth = GridBagConstraints.REMAINDER;
+               Insets ib = new Insets(4,4,4,4);
+               c.insets = ib;
+               pane.add(pbar, c);
+
+
+               cancel = new JButton("Cancel");
+               c = new GridBagConstraints();
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.CENTER;
+               c.gridx = 0; c.gridy = 4;
+               c.gridwidth = GridBagConstraints.REMAINDER;
+               Insets ic = new Insets(4,4,4,4);
+               c.insets = ic;
+               pane.add(cancel, c);
+
+               pack();
+               setLocationRelativeTo(owner);
+               setVisible(true);
+       }
+
+       public void addActionListener (ActionListener l) {
+               cancel.addActionListener(l);
+       }
+
+       public void set_value(String state_name, int in_state, int in_block) {
+               int block = in_block;
+               int state = in_state;
+
+               if (block > 100)
+                       block = 100;
+               if (state < min_state) state = min_state;
+               if (state >= max_state) state = max_state - 1;
+               state -= min_state;
+
+               int pos = state * 100 + block;
+
+               pbar.setString(state_name);
+               pbar.setValue(pos);
+       }
+
+       public void set_serial(int serial) {
+               serial_value.setText(String.format("%d", serial));
+       }
+
+       public void set_flight(int flight) {
+               flight_value.setText(String.format("%d", flight));
+       }
+
+       public void set_file(String file) {
+               file_value.setText(String.format("%s", file));
+       }
+
+       public void done() {
+               setVisible(false);
+               dispose();
+       }
+}
diff --git a/altosui/AltosEepromRecord.java b/altosui/AltosEepromRecord.java
new file mode 100644 (file)
index 0000000..5a67381
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * 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;
+
+public class AltosEepromRecord {
+       public int      cmd;
+       public int      tick;
+       public int      a;
+       public int      b;
+       public String   data;
+       public boolean  tick_valid;
+
+       public AltosEepromRecord (String line) {
+               tick_valid = false;
+               tick = 0;
+               a = 0;
+               b = 0;
+               data = null;
+               if (line == null) {
+                       cmd = Altos.AO_LOG_INVALID;
+                       data = "";
+               } else {
+                       try {
+                               String[] tokens = line.split("\\s+");
+
+                               if (tokens[0].length() == 1) {
+                                       if (tokens.length != 4) {
+                                               cmd = Altos.AO_LOG_INVALID;
+                                               data = line;
+                                       } else {
+                                               cmd = tokens[0].codePointAt(0);
+                                               tick = Integer.parseInt(tokens[1],16);
+                                               tick_valid = true;
+                                               a = Integer.parseInt(tokens[2],16);
+                                               b = Integer.parseInt(tokens[3],16);
+                                       }
+                               } else if (tokens[0].equals("Config") && tokens[1].equals("version:")) {
+                                       cmd = Altos.AO_LOG_CONFIG_VERSION;
+                                       data = tokens[2];
+                               } else if (tokens[0].equals("Main") && tokens[1].equals("deploy:")) {
+                                       cmd = Altos.AO_LOG_MAIN_DEPLOY;
+                                       a = Integer.parseInt(tokens[2]);
+                               } else if (tokens[0].equals("Apogee") && tokens[1].equals("delay:")) {
+                                       cmd = Altos.AO_LOG_APOGEE_DELAY;
+                                       a = Integer.parseInt(tokens[2]);
+                               } else if (tokens[0].equals("Radio") && tokens[1].equals("channel:")) {
+                                       cmd = Altos.AO_LOG_RADIO_CHANNEL;
+                                       a = Integer.parseInt(tokens[2]);
+                               } else if (tokens[0].equals("Callsign:")) {
+                                       cmd = Altos.AO_LOG_CALLSIGN;
+                                       data = tokens[1].replaceAll("\"","");
+                               } else if (tokens[0].equals("Accel") && tokens[1].equals("cal")) {
+                                       cmd = Altos.AO_LOG_ACCEL_CAL;
+                                       a = Integer.parseInt(tokens[3]);
+                                       b = Integer.parseInt(tokens[5]);
+                               } else if (tokens[0].equals("Radio") && tokens[1].equals("cal:")) {
+                                       cmd = Altos.AO_LOG_RADIO_CAL;
+                                       a = Integer.parseInt(tokens[2]);
+                               } else if (tokens[0].equals("manufacturer")) {
+                                       cmd = Altos.AO_LOG_MANUFACTURER;
+                                       data = tokens[1];
+                               } else if (tokens[0].equals("product")) {
+                                       cmd = Altos.AO_LOG_PRODUCT;
+                                       data = tokens[1];
+                               } else if (tokens[0].equals("serial-number")) {
+                                       cmd = Altos.AO_LOG_SERIAL_NUMBER;
+                                       a = Integer.parseInt(tokens[1]);
+                               } else if (tokens[0].equals("software-version")) {
+                                       cmd = Altos.AO_LOG_SOFTWARE_VERSION;
+                                       data = tokens[1];
+                               } else {
+                                       cmd = Altos.AO_LOG_INVALID;
+                                       data = line;
+                               }
+                       } catch (NumberFormatException ne) {
+                               cmd = Altos.AO_LOG_INVALID;
+                               data = line;
+                       }
+               }
+       }
+
+       public AltosEepromRecord(int in_cmd, int in_tick, int in_a, int in_b) {
+               tick_valid = true;
+               cmd = in_cmd;
+               tick = in_tick;
+               a = in_a;
+               b = in_b;
+       }
+}
diff --git a/altosui/AltosFile.java b/altosui/AltosFile.java
new file mode 100644 (file)
index 0000000..0636057
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * 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.lang.*;
+import java.io.File;
+import java.util.*;
+
+class AltosFile extends File {
+
+       public AltosFile(int year, int month, int day, int serial, int flight, String extension) {
+               super (AltosPreferences.logdir(),
+                      String.format("%04d-%02d-%02d-serial-%03d-flight-%03d.%s",
+                                    year, month, day, serial, flight, extension));
+       }
+
+       public AltosFile(int serial, int flight, String extension) {
+               this(Calendar.getInstance().get(Calendar.YEAR),
+                    Calendar.getInstance().get(Calendar.MONTH) + 1,
+                    Calendar.getInstance().get(Calendar.DAY_OF_MONTH),
+                    serial,
+                    flight,
+                    extension);
+       }
+
+       public AltosFile(AltosTelemetry telem) {
+               this(telem.serial, telem.flight, "telem");
+       }
+}
diff --git a/altosui/AltosFlash.java b/altosui/AltosFlash.java
new file mode 100644 (file)
index 0000000..3af25c2
--- /dev/null
@@ -0,0 +1,344 @@
+/*
+ * 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;
+
+public class AltosFlash {
+       File            file;
+       FileInputStream input;
+       AltosHexfile    image;
+       JFrame          frame;
+       AltosDevice     debug_dongle;
+       AltosDebug      debug;
+       AltosRomconfig  rom_config;
+       ActionListener  listener;
+       boolean         aborted;
+
+       static final byte MOV_direct_data       = (byte) 0x75;
+       static final byte MOV_DPTR_data16       = (byte) 0x90;
+       static final byte MOV_A_data            = (byte) 0x74;
+       static final byte MOVX_atDPTR_A         = (byte) 0xf0;
+       static final byte MOVX_A_atDPTR         = (byte) 0xe0;
+       static final byte INC_DPTR              = (byte) 0xa3;
+       static final byte TRAP                  = (byte) 0xa5;
+
+       static final byte JB                    = (byte) 0x20;
+
+       static final byte MOV_A_direct          = (byte) 0xe5;
+       static final byte MOV_direct1_direct2   = (byte) 0x85;
+       static final byte MOV_direct_A          = (byte) 0xf5;
+       static final byte MOV_R0_data           = (byte) (0x78 | 0);
+       static final byte MOV_R1_data           = (byte) (0x78 | 1);
+       static final byte MOV_R2_data           = (byte) (0x78 | 2);
+       static final byte MOV_R3_data           = (byte) (0x78 | 3);
+       static final byte MOV_R4_data           = (byte) (0x78 | 4);
+       static final byte MOV_R5_data           = (byte) (0x78 | 5);
+       static final byte MOV_R6_data           = (byte) (0x78 | 6);
+       static final byte MOV_R7_data           = (byte) (0x78 | 7);
+       static final byte DJNZ_R0_rel           = (byte) (0xd8 | 0);
+       static final byte DJNZ_R1_rel           = (byte) (0xd8 | 1);
+       static final byte DJNZ_R2_rel           = (byte) (0xd8 | 2);
+       static final byte DJNZ_R3_rel           = (byte) (0xd8 | 3);
+       static final byte DJNZ_R4_rel           = (byte) (0xd8 | 4);
+       static final byte DJNZ_R5_rel           = (byte) (0xd8 | 5);
+       static final byte DJNZ_R6_rel           = (byte) (0xd8 | 6);
+       static final byte DJNZ_R7_rel           = (byte) (0xd8 | 7);
+
+       static final byte P1DIR                 = (byte) 0xFE;
+       static final byte P1                    = (byte) 0x90;
+
+       /* flash controller */
+       static final byte FWT                   = (byte) 0xAB;
+       static final byte FADDRL                = (byte) 0xAC;
+       static final byte FADDRH                = (byte) 0xAD;
+       static final byte FCTL                  = (byte) 0xAE;
+       static final byte FCTL_BUSY             = (byte) 0x80;
+       static final byte FCTL_BUSY_BIT         = (byte) 7;
+       static final byte FCTL_SWBSY            = (byte) 0x40;
+       static final byte FCTL_SWBSY_BIT        = (byte) 6;
+       static final byte FCTL_CONTRD           = (byte) 0x10;
+       static final byte FCTL_WRITE            = (byte) 0x02;
+       static final byte FCTL_ERASE            = (byte) 0x01;
+       static final byte FWDATA                = (byte) 0xAF;
+
+       static final byte ACC                   = (byte) 0xE0;
+
+       /* offsets within the flash_page program */
+       static final int FLASH_ADDR_HIGH        = 8;
+       static final int FLASH_ADDR_LOW         = 11;
+       static final int RAM_ADDR_HIGH          = 13;
+       static final int RAM_ADDR_LOW           = 14;
+       static final int FLASH_WORDS_HIGH       = 16;
+       static final int FLASH_WORDS_LOW        = 18;
+       static final int FLASH_TIMING           = 21;
+
+       /* sleep mode control */
+       static final int SLEEP                  = (byte) 0xbe;
+       static final int  SLEEP_USB_EN          = (byte) 0x80;
+       static final int  SLEEP_XOSC_STB        = (byte) 0x40;
+       static final int  SLEEP_HFRC_STB        = (byte) 0x20;
+       static final int  SLEEP_RST_MASK        = (byte) 0x18;
+       static final int   SLEEP_RST_POWERON    = (byte) 0x00;
+       static final int   SLEEP_RST_EXTERNAL   = (byte) 0x10;
+       static final int   SLEEP_RST_WATCHDOG   = (byte) 0x08;
+       static final int  SLEEP_OSC_PD          = (byte) 0x04;
+       static final int  SLEEP_MODE_MASK       = (byte) 0x03;
+       static final int   SLEEP_MODE_PM0       = (byte) 0x00;
+       static final int   SLEEP_MODE_PM1       = (byte) 0x01;
+       static final int   SLEEP_MODE_PM2       = (byte) 0x02;
+       static final int   SLEEP_MODE_PM3       = (byte) 0x03;
+
+       /* clock controller */
+       static final byte CLKCON                = (byte) 0xC6;
+       static final byte  CLKCON_OSC32K        = (byte) 0x80;
+       static final byte  CLKCON_OSC           = (byte) 0x40;
+       static final byte  CLKCON_TICKSPD       = (byte) 0x38;
+       static final byte  CLKCON_CLKSPD        = (byte) 0x07;
+
+       static final byte[] flash_page_proto = {
+
+               MOV_direct_data, P1DIR, (byte) 0x02,
+               MOV_direct_data, P1,    (byte) 0xFF,
+
+               MOV_direct_data, FADDRH, 0,     /* FLASH_ADDR_HIGH */
+
+               MOV_direct_data, FADDRL, 0,     /* FLASH_ADDR_LOW */
+
+               MOV_DPTR_data16, 0, 0,          /* RAM_ADDR_HIGH, RAM_ADDR_LOW */
+
+               MOV_R7_data, 0,                 /* FLASH_WORDS_HIGH */
+
+               MOV_R6_data, 0,                 /* FLASH_WORDS_LOW */
+
+
+               MOV_direct_data, FWT, 0x20,     /* FLASH_TIMING */
+
+               MOV_direct_data, FCTL, FCTL_ERASE,
+/* eraseWaitLoop: */
+               MOV_A_direct,           FCTL,
+               JB, ACC|FCTL_BUSY_BIT, (byte) 0xfb,
+
+               MOV_direct_data, P1, (byte) 0xfd,
+
+               MOV_direct_data, FCTL, FCTL_WRITE,
+/* writeLoop: */
+               MOV_R5_data, 2,
+/* writeWordLoop: */
+               MOVX_A_atDPTR,
+               INC_DPTR,
+               MOV_direct_A, FWDATA,
+               DJNZ_R5_rel, (byte) 0xfa,               /* writeWordLoop */
+/* writeWaitLoop: */
+               MOV_A_direct, FCTL,
+               JB, ACC|FCTL_SWBSY_BIT, (byte) 0xfb,    /* writeWaitLoop */
+               DJNZ_R6_rel, (byte) 0xf1,               /* writeLoop */
+               DJNZ_R7_rel, (byte) 0xef,                       /* writeLoop */
+
+               MOV_direct_data, P1DIR, (byte) 0x00,
+               MOV_direct_data, P1,    (byte) 0xFF,
+               TRAP,
+       };
+
+       public byte[] make_flash_page(int flash_addr, int ram_addr, int byte_count) {
+               int flash_word_addr = flash_addr >> 1;
+               int flash_word_count = ((byte_count + 1) >> 1);
+
+               byte[] flash_page = new byte[flash_page_proto.length];
+               for (int i = 0; i < flash_page.length; i++)
+                       flash_page[i] = flash_page_proto[i];
+
+               flash_page[FLASH_ADDR_HIGH]  = (byte) (flash_word_addr >> 8);
+               flash_page[FLASH_ADDR_LOW]   = (byte) (flash_word_addr);
+               flash_page[RAM_ADDR_HIGH]    = (byte) (ram_addr >> 8);
+               flash_page[RAM_ADDR_LOW]     = (byte) (ram_addr);
+
+               byte flash_words_low = (byte) (flash_word_count);
+               byte flash_words_high = (byte) (flash_word_count >> 8);
+               /* the flashing code has a minor 'bug' */
+               if (flash_words_low != 0)
+                       flash_words_high++;
+
+               flash_page[FLASH_WORDS_HIGH] = (byte) flash_words_high;
+               flash_page[FLASH_WORDS_LOW]  = (byte) flash_words_low;
+               return flash_page;
+       }
+
+       static byte[] set_clkcon_fast = {
+               MOV_direct_data, CLKCON, 0x00
+       };
+
+       static byte[] get_sleep = {
+               MOV_A_direct, SLEEP
+       };
+
+       public void clock_init() throws IOException, InterruptedException {
+               debug.debug_instr(set_clkcon_fast);
+
+               byte    status;
+               for (int times = 0; times < 20; times++) {
+                       Thread.sleep(1);
+                       status = debug.debug_instr(get_sleep);
+                       if ((status & SLEEP_XOSC_STB) != 0)
+                               return;
+               }
+               throw new IOException("Failed to initialize target clock");
+       }
+
+       void action(String s, int percent) {
+               if (listener != null && !aborted)
+                       listener.actionPerformed(new ActionEvent(this,
+                                                                percent,
+                                                                s));
+       }
+
+       void action(int part, int total) {
+               int percent = 100 * part / total;
+               action(String.format("%d/%d (%d%%)",
+                                    part, total, percent),
+                      percent);
+       }
+
+       void run(int pc) throws IOException, InterruptedException {
+               debug.set_pc(pc);
+               int set_pc = debug.get_pc();
+               if (pc != set_pc)
+                       throw new IOException("Failed to set target program counter");
+               debug.resume();
+
+               for (int times = 0; times < 20; times++) {
+                       byte status = debug.read_status();
+                       if ((status & AltosDebug.STATUS_CPU_HALTED) != 0)
+                               return;
+               }
+
+               throw new IOException("Failed to execute program on target");
+       }
+
+       public void flash() throws IOException, FileNotFoundException, InterruptedException {
+               if (!check_rom_config())
+                       throw new IOException("Invalid rom config settings");
+               if (image.address + image.data.length > 0x8000)
+                       throw new IOException(String.format("Flash image too long %d",
+                                                           image.address +
+                                                           image.data.length));
+               if ((image.address & 0x3ff) != 0)
+                       throw new IOException(String.format("Flash image must start on page boundary (is 0x%x)",
+                                                           image.address));
+               int ram_address = 0xf000;
+               int flash_prog = 0xf400;
+
+               /*
+                * Store desired config values into image
+                */
+               rom_config.write(image);
+               /*
+                * Bring up the clock
+                */
+               clock_init();
+
+               int remain = image.data.length;
+               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;
+                       if (this_time > 0x400)
+                               this_time = 0x400;
+
+                       /* write the data */
+                       debug.write_memory(ram_address, image.data,
+                                          image_start, this_time);
+
+                       /* write the flash program */
+                       byte[] flash_page = make_flash_page(flash_addr,
+                                                           ram_address,
+                                                           this_time);
+                       debug.write_memory(flash_prog, flash_page);
+
+                       run(flash_prog);
+
+                       byte[] check = debug.read_memory(flash_addr, this_time);
+                       for (int i = 0; i < this_time; i++)
+                               if (check[i] != image.data[image_start + i])
+                                       throw new IOException(String.format("Flash write failed at 0x%x (%02x != %02x)",
+                                                                           image.address + image_start + i,
+                                                                           check[i], image.data[image_start + i]));
+                       remain -= this_time;
+                       flash_addr += this_time;
+                       image_start += this_time;
+
+                       action(image.data.length - remain, image.data.length);
+               }
+               if (!aborted) {
+                       action("done", 100);
+                       debug.set_pc(image.address);
+                       debug.resume();
+               }
+               debug.close();
+       }
+
+       public void abort() {
+               aborted = true;
+               debug.close();
+       }
+
+       public void addActionListener(ActionListener l) {
+               listener = l;
+       }
+
+       public boolean check_rom_config() {
+               if (rom_config == null)
+                       rom_config = debug.romconfig();
+               return rom_config != null && rom_config.valid();
+       }
+
+       public void set_romconfig (AltosRomconfig romconfig) {
+               rom_config = romconfig;
+       }
+
+       public AltosRomconfig romconfig() {
+               if (!check_rom_config())
+                       return null;
+               return rom_config;
+       }
+
+       public AltosFlash(File in_file, AltosDevice in_debug_dongle)
+               throws IOException, FileNotFoundException, AltosSerialInUseException, InterruptedException {
+               file = in_file;
+               debug_dongle = in_debug_dongle;
+               debug = new AltosDebug(in_debug_dongle);
+               input = new FileInputStream(file);
+               image = new AltosHexfile(input);
+               if (!debug.check_connection()) {
+                       debug.close();
+                       throw new IOException("Debug port not connected");
+               }
+       }
+}
\ No newline at end of file
diff --git a/altosui/AltosFlashUI.java b/altosui/AltosFlashUI.java
new file mode 100644 (file)
index 0000000..f63097a
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * 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;
+
+public class AltosFlashUI
+       extends JDialog
+       implements Runnable, ActionListener
+{
+       Container       pane;
+       Box             box;
+       JLabel          serial_label;
+       JLabel          serial_value;
+       JLabel          file_label;
+       JLabel          file_value;
+       JProgressBar    pbar;
+       JButton         cancel;
+
+       File            file;
+       Thread          thread;
+       JFrame          frame;
+       AltosDevice     debug_dongle;
+       AltosFlash      flash;
+
+       public void actionPerformed(ActionEvent e) {
+               if (e.getSource() == cancel) {
+                       abort();
+                       dispose();
+               } else {
+                       String  cmd = e.getActionCommand();
+                       if (cmd.equals("done"))
+                               ;
+                       else if (cmd.equals("start")) {
+                               setVisible(true);
+                       } else {
+                               pbar.setValue(e.getID());
+                               pbar.setString(cmd);
+                       }
+               }
+       }
+
+       public void run() {
+               try {
+                       flash = new AltosFlash(file, debug_dongle);
+                       flash.addActionListener(this);
+                       AltosRomconfigUI romconfig_ui = new AltosRomconfigUI (frame);
+
+                       romconfig_ui.set(flash.romconfig());
+                       AltosRomconfig romconfig = romconfig_ui.showDialog();
+
+                       if (romconfig != null && romconfig.valid()) {
+                               flash.set_romconfig(romconfig);
+                               serial_value.setText(String.format("%d",
+                                                                  flash.romconfig().serial_number));
+                               file_value.setText(file.toString());
+                               setVisible(true);
+                               flash.flash();
+                               flash = null;
+                       }
+               } catch (FileNotFoundException ee) {
+                       JOptionPane.showMessageDialog(frame,
+                                                     "Cannot open image",
+                                                     file.toString(),
+                                                     JOptionPane.ERROR_MESSAGE);
+               } catch (AltosSerialInUseException si) {
+                       JOptionPane.showMessageDialog(frame,
+                                                     String.format("Device \"%s\" already in use",
+                                                                   debug_dongle.toShortString()),
+                                                     "Device in use",
+                                                     JOptionPane.ERROR_MESSAGE);
+               } catch (IOException e) {
+                       JOptionPane.showMessageDialog(frame,
+                                                     e.getMessage(),
+                                                     file.toString(),
+                                                     JOptionPane.ERROR_MESSAGE);
+               } catch (InterruptedException ie) {
+               } finally {
+                       abort();
+               }
+               dispose();
+       }
+
+       public void abort() {
+               if (flash != null)
+                       flash.abort();
+       }
+
+       public void build_dialog() {
+               GridBagConstraints c;
+               Insets il = new Insets(4,4,4,4);
+               Insets ir = new Insets(4,4,4,4);
+
+               pane = getContentPane();
+               pane.setLayout(new GridBagLayout());
+
+               c = new GridBagConstraints();
+               c.gridx = 0; c.gridy = 0;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = il;
+               serial_label = new JLabel("Serial:");
+               pane.add(serial_label, c);
+
+               c = new GridBagConstraints();
+               c.gridx = 1; c.gridy = 0;
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.weightx = 1;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = ir;
+               serial_value = new JLabel("");
+               pane.add(serial_value, c);
+
+               c = new GridBagConstraints();
+               c.fill = GridBagConstraints.NONE;
+               c.gridx = 0; c.gridy = 1;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = il;
+               file_label = new JLabel("File:");
+               pane.add(file_label, c);
+
+               c = new GridBagConstraints();
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.weightx = 1;
+               c.gridx = 1; c.gridy = 1;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = ir;
+               file_value = new JLabel("");
+               pane.add(file_value, c);
+
+               pbar = new JProgressBar();
+               pbar.setMinimum(0);
+               pbar.setMaximum(100);
+               pbar.setValue(0);
+               pbar.setString("");
+               pbar.setStringPainted(true);
+               pbar.setPreferredSize(new Dimension(600, 20));
+               c = new GridBagConstraints();
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.anchor = GridBagConstraints.CENTER;
+               c.gridx = 0; c.gridy = 2;
+               c.gridwidth = GridBagConstraints.REMAINDER;
+               Insets ib = new Insets(4,4,4,4);
+               c.insets = ib;
+               pane.add(pbar, c);
+
+               cancel = new JButton("Cancel");
+               c = new GridBagConstraints();
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.CENTER;
+               c.gridx = 0; c.gridy = 3;
+               c.gridwidth = GridBagConstraints.REMAINDER;
+               Insets ic = new Insets(4,4,4,4);
+               c.insets = ic;
+               pane.add(cancel, c);
+               cancel.addActionListener(this);
+               pack();
+               setLocationRelativeTo(frame);
+       }
+
+       public AltosFlashUI(JFrame in_frame) {
+               super(in_frame, "Program Altusmetrum Device", false);
+
+               frame = in_frame;
+
+               build_dialog();
+
+               debug_dongle = AltosDeviceDialog.show(frame, AltosDevice.product_any);
+
+               if (debug_dongle == null)
+                       return;
+
+               JFileChooser    hexfile_chooser = new JFileChooser();
+
+               File firmwaredir = AltosPreferences.firmwaredir();
+               if (firmwaredir != null)
+                       hexfile_chooser.setCurrentDirectory(firmwaredir);
+
+               hexfile_chooser.setDialogTitle("Select Flash Image");
+               hexfile_chooser.setFileFilter(new FileNameExtensionFilter("Flash Image", "ihx"));
+               int returnVal = hexfile_chooser.showOpenDialog(frame);
+
+               if (returnVal != JFileChooser.APPROVE_OPTION)
+                       return;
+
+               file = hexfile_chooser.getSelectedFile();
+
+               if (file != null)
+                       AltosPreferences.set_firmwaredir(file.getParentFile());
+
+               thread = new Thread(this);
+               thread.start();
+       }
+}
\ No newline at end of file
diff --git a/altosui/AltosFlightDisplay.java b/altosui/AltosFlightDisplay.java
new file mode 100644 (file)
index 0000000..d18d1d1
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * 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;
+
+public interface AltosFlightDisplay {
+       void reset();
+
+       void show(AltosState state, int crc_errors);
+}
diff --git a/altosui/AltosFlightInfoTableModel.java b/altosui/AltosFlightInfoTableModel.java
new file mode 100644 (file)
index 0000000..e23eff6
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * 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;
+
+public class AltosFlightInfoTableModel extends AbstractTableModel {
+       final static private String[] columnNames = {"Field", "Value"};
+
+       int     rows;
+       int     cols;
+       private String[][] data;
+
+       public int getColumnCount() { return cols; }
+       public int getRowCount() { return rows; }
+       public String getColumnName(int col) { return columnNames[col & 1]; }
+
+       public Object getValueAt(int row, int col) {
+               if (row >= rows || col >= cols)
+                       return "";
+               return data[row][col];
+       }
+
+       int[]   current_row;
+
+       public void reset() {
+               for (int i = 0; i < cols / 2; i++)
+                       current_row[i] = 0;
+       }
+
+       public void clear() {
+               reset();
+               for (int c = 0; c < cols; c++)
+                       for (int r = 0; r < rows; r++)
+                               data[r][c] = "";
+               fireTableDataChanged();
+       }
+
+       public void addRow(int col, String name, String value) {
+               if (current_row[col] < rows) {
+                       data[current_row[col]][col * 2] = name;
+                       data[current_row[col]][col * 2 + 1] = value;
+               }
+               current_row[col]++;
+       }
+
+       public void finish() {
+               for (int c = 0; c < cols / 2; c++)
+                       while (current_row[c] < rows)
+                               addRow(c, "", "");
+               fireTableDataChanged();
+       }
+
+       public AltosFlightInfoTableModel (int in_rows, int in_cols) {
+               rows = in_rows;
+               cols = in_cols * 2;
+               data = new String[rows][cols];
+               current_row = new int[in_cols];
+       }
+}
diff --git a/altosui/AltosFlightReader.java b/altosui/AltosFlightReader.java
new file mode 100644 (file)
index 0000000..3d59de9
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * 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.lang.*;
+import java.text.*;
+import java.io.*;
+
+public class AltosFlightReader {
+       String name;
+
+       int serial;
+
+       void init() { }
+
+       AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException { return null; }
+
+       void close(boolean interrupted) { }
+
+       void set_channel(int channel) { }
+
+       void update(AltosState state) throws InterruptedException { }
+}
diff --git a/altosui/AltosFlightStatus.java b/altosui/AltosFlightStatus.java
new file mode 100644 (file)
index 0000000..59c9e9d
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * 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;
+
+public class AltosFlightStatus extends JComponent implements AltosFlightDisplay {
+       GridBagLayout   layout;
+
+       public class FlightValue {
+               JLabel          label;
+               JTextField      value;
+
+               void show(AltosState state, int crc_errors) {}
+
+               void reset() {
+                       value.setText("");
+               }
+               public FlightValue (GridBagLayout layout, int x, String text) {
+                       GridBagConstraints      c = new GridBagConstraints();
+                       c.insets = new Insets(5, 5, 5, 5);
+                       c.anchor = GridBagConstraints.CENTER;
+                       c.fill = GridBagConstraints.BOTH;
+                       c.weightx = 1;
+                       c.weighty = 1;
+
+                       label = new JLabel(text);
+                       label.setFont(Altos.status_font);
+                       label.setHorizontalAlignment(SwingConstants.CENTER);
+                       c.gridx = x; c.gridy = 0;
+                       layout.setConstraints(label, c);
+                       add(label);
+
+                       value = new JTextField("");
+                       value.setFont(Altos.status_font);
+                       value.setHorizontalAlignment(SwingConstants.CENTER);
+                       c.gridx = x; c.gridy = 1;
+                       layout.setConstraints(value, c);
+                       add(value);
+               }
+       }
+
+       class Call extends FlightValue {
+               void show(AltosState state, int crc_errors) {
+                       value.setText(state.data.callsign);
+               }
+               public Call (GridBagLayout layout, int x) {
+                       super (layout, x, "Callsign");
+               }
+       }
+
+       Call call;
+
+       class Serial extends FlightValue {
+               void show(AltosState state, int crc_errors) {
+                       value.setText(String.format("%d", state.data.serial));
+               }
+               public Serial (GridBagLayout layout, int x) {
+                       super (layout, x, "Serial");
+               }
+       }
+
+       Serial serial;
+
+       class Flight extends FlightValue {
+               void show(AltosState state, int crc_errors) {
+                       value.setText(String.format("%d", state.data.flight));
+               }
+               public Flight (GridBagLayout layout, int x) {
+                       super (layout, x, "Flight");
+               }
+       }
+
+       Flight flight;
+
+       class FlightState extends FlightValue {
+               void show(AltosState state, int crc_errors) {
+                       value.setText(state.data.state());
+               }
+               public FlightState (GridBagLayout layout, int x) {
+                       super (layout, x, "State");
+               }
+       }
+
+       FlightState flight_state;
+
+       class RSSI extends FlightValue {
+               void show(AltosState state, int crc_errors) {
+                       value.setText(String.format("%d", state.data.rssi));
+               }
+               public RSSI (GridBagLayout layout, int x) {
+                       super (layout, x, "RSSI (dBm)");
+               }
+       }
+
+       RSSI rssi;
+
+       public void reset () {
+               call.reset();
+               serial.reset();
+               flight.reset();
+               flight_state.reset();
+               rssi.reset();
+       }
+
+       public void show (AltosState state, int crc_errors) {
+               call.show(state, crc_errors);
+               serial.show(state, crc_errors);
+               flight.show(state, crc_errors);
+               flight_state.show(state, crc_errors);
+               rssi.show(state, crc_errors);
+       }
+
+       public int height() {
+               Dimension d = layout.preferredLayoutSize(this);
+               return d.height;
+       }
+
+       public AltosFlightStatus() {
+               layout = new GridBagLayout();
+
+               setLayout(layout);
+
+               call = new Call(layout, 0);
+               serial = new Serial(layout, 1);
+               flight = new Flight(layout, 2);
+               flight_state = new FlightState(layout, 3);
+               rssi = new RSSI(layout, 4);
+       }
+}
diff --git a/altosui/AltosFlightStatusTableModel.java b/altosui/AltosFlightStatusTableModel.java
new file mode 100644 (file)
index 0000000..4c24b6a
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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;
+
+public class AltosFlightStatusTableModel extends AbstractTableModel {
+       private String[] columnNames = {"Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" };
+       private Object[] data = { 0, "idle", 0, 0 };
+
+       public int getColumnCount() { return columnNames.length; }
+       public int getRowCount() { return 2; }
+       public Object getValueAt(int row, int col) {
+               if (row == 0)
+                       return columnNames[col];
+               return data[col];
+       }
+
+       public void setValueAt(Object value, int col) {
+               data[col] = value;
+               fireTableCellUpdated(1, col);
+       }
+
+       public void setValueAt(Object value, int row, int col) {
+               setValueAt(value, col);
+       }
+
+       public void set(AltosState state) {
+               setValueAt(String.format("%1.0f", state.height), 0);
+               setValueAt(state.data.state(), 1);
+               setValueAt(state.data.rssi, 2);
+               double speed = state.baro_speed;
+               if (state.ascent)
+                       speed = state.speed;
+               setValueAt(String.format("%1.0f", speed), 3);
+       }
+}
diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java
new file mode 100644 (file)
index 0000000..24d25bd
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * 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;
+
+public class AltosFlightUI extends JFrame implements AltosFlightDisplay {
+       String[] statusNames = { "Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" };
+       Object[][] statusData = { { "0", "pad", "-50", "0" } };
+
+       AltosVoice              voice;
+       AltosFlightReader       reader;
+       AltosDisplayThread      thread;
+
+       JTabbedPane     pane;
+
+       AltosPad        pad;
+       AltosAscent     ascent;
+       AltosDescent    descent;
+       AltosLanded     landed;
+       AltosSiteMap    sitemap;
+
+       private AltosFlightStatus flightStatus;
+       private AltosInfoTable flightInfo;
+
+       static final int tab_pad = 1;
+       static final int tab_ascent = 2;
+       static final int tab_descent = 3;
+       static final int tab_landed = 4;
+
+       int cur_tab = 0;
+
+       boolean exit_on_close = false;
+
+       int which_tab(AltosState state) {
+               if (state.state < Altos.ao_flight_boost)
+                       return tab_pad;
+               if (state.state <= Altos.ao_flight_coast)
+                       return tab_ascent;
+               if (state.state <= Altos.ao_flight_main)
+                       return tab_descent;
+               return tab_landed;
+       }
+
+       void stop_display() {
+               if (thread != null && thread.isAlive()) {
+                       thread.interrupt();
+                       try {
+                               thread.join();
+                       } catch (InterruptedException ie) {}
+               }
+               thread = null;
+       }
+
+       void disconnect() {
+               stop_display();
+       }
+
+       public void reset() {
+               pad.reset();
+               ascent.reset();
+               descent.reset();
+               landed.reset();
+               flightInfo.clear();
+               sitemap.reset();
+       }
+
+       public void show(AltosState state, int crc_errors) {
+               int     tab = which_tab(state);
+               pad.show(state, crc_errors);
+               ascent.show(state, crc_errors);
+               descent.show(state, crc_errors);
+               landed.show(state, crc_errors);
+               if (tab != cur_tab) {
+                       switch (tab) {
+                       case tab_pad:
+                               pane.setSelectedComponent(pad);
+                               break;
+                       case tab_ascent:
+                               pane.setSelectedComponent(ascent);
+                               break;
+                       case tab_descent:
+                               pane.setSelectedComponent(descent);
+                               break;
+                       case tab_landed:
+                               pane.setSelectedComponent(landed);
+                       }
+                       cur_tab = tab;
+               }
+               flightStatus.show(state, crc_errors);
+               flightInfo.show(state, crc_errors);
+               sitemap.show(state, crc_errors);
+       }
+
+       public void set_exit_on_close() {
+               exit_on_close = true;
+       }
+
+       Container       bag;
+       JComboBox       channels;
+
+       public AltosFlightUI(AltosVoice in_voice, AltosFlightReader in_reader, final int serial) {
+               AltosPreferences.init(this);
+
+               voice = in_voice;
+               reader = in_reader;
+
+               bag = getContentPane();
+               bag.setLayout(new GridBagLayout());
+
+               GridBagConstraints c = new GridBagConstraints();
+
+               java.net.URL imgURL = AltosUI.class.getResource("/altus-metrum-16x16.jpg");
+               if (imgURL != null)
+                       setIconImage(new ImageIcon(imgURL).getImage());
+
+               setTitle(String.format("AltOS %s", reader.name));
+
+               /* Stick channel selector at top of table for telemetry monitoring */
+               if (serial >= 0) {
+                       // Channel menu
+                       channels = new AltosChannelMenu(AltosPreferences.channel(serial));
+                       channels.addActionListener(new ActionListener() {
+                               public void actionPerformed(ActionEvent e) {
+                                       int channel = channels.getSelectedIndex();
+                                       reader.set_channel(channel);
+                               }
+                       });
+                       c.gridx = 0;
+                       c.gridy = 0;
+                       c.anchor = GridBagConstraints.WEST;
+                       bag.add (channels, c);
+               }
+
+               /* Flight status is always visible */
+               flightStatus = new AltosFlightStatus();
+               c.gridx = 0;
+               c.gridy = 1;
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.weightx = 1;
+               bag.add(flightStatus, c);
+
+               /* The rest of the window uses a tabbed pane to
+                * show one of the alternate data views
+                */
+               pane = new JTabbedPane();
+
+               pad = new AltosPad();
+               pane.add("Launch Pad", pad);
+
+               ascent = new AltosAscent();
+               pane.add("Ascent", ascent);
+
+               descent = new AltosDescent();
+               pane.add("Descent", descent);
+
+               landed = new AltosLanded();
+               pane.add("Landed", landed);
+
+               flightInfo = new AltosInfoTable();
+               pane.add("Table", new JScrollPane(flightInfo));
+
+               sitemap = new AltosSiteMap();
+               pane.add("Site Map", sitemap);
+
+               /* Make the tabbed pane use the rest of the window space */
+               c.gridx = 0;
+               c.gridy = 2;
+               c.fill = GridBagConstraints.BOTH;
+               c.weightx = 1;
+               c.weighty = 1;
+               bag.add(pane, c);
+
+               setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
+               addWindowListener(new WindowAdapter() {
+                               @Override
+                               public void windowClosing(WindowEvent e) {
+                                       disconnect();
+                                       setVisible(false);
+                                       dispose();
+                                       if (exit_on_close)
+                                               System.exit(0);
+                               }
+                       });
+
+               pack();
+               setVisible(true);
+
+               thread = new AltosDisplayThread(this, voice, this, reader);
+
+               thread.start();
+       }
+
+       public AltosFlightUI (AltosVoice in_voice, AltosFlightReader in_reader) {
+               this(in_voice, in_reader, -1);
+       }
+}
diff --git a/altosui/AltosGPS.java b/altosui/AltosGPS.java
new file mode 100644 (file)
index 0000000..8382184
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * 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.lang.*;
+import java.text.*;
+
+public class AltosGPS {
+       public class AltosGPSSat {
+               int     svid;
+               int     c_n0;
+       }
+
+       int     nsat;
+       boolean locked;
+       boolean connected;
+       boolean date_valid;
+       double  lat;            /* degrees (+N -S) */
+       double  lon;            /* degrees (+E -W) */
+       int     alt;            /* m */
+       int     year;
+       int     month;
+       int     day;
+       int     hour;
+       int     minute;
+       int     second;
+
+       int     gps_extended;   /* has extra data */
+       double  ground_speed;   /* m/s */
+       int     course;         /* degrees */
+       double  climb_rate;     /* m/s */
+       double  hdop;           /* unitless? */
+       int     h_error;        /* m */
+       int     v_error;        /* m */
+
+       AltosGPSSat[] cc_gps_sat;       /* tracking data */
+
+       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);
+               hour = AltosParse.parse_int(hms[0]);
+               minute = AltosParse.parse_int(hms[1]);
+               second = AltosParse.parse_int(hms[2]);
+       }
+
+       void ClearGPSTime() {
+               year = month = day = 0;
+               hour = minute = second = 0;
+       }
+
+       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");
+
+               connected = false;
+               locked = false;
+               lat = lon = 0;
+               alt = 0;
+               ClearGPSTime();
+               if ((words[i]).equals("unlocked")) {
+                       connected = true;
+                       i++;
+               } else if ((words[i]).equals("not-connected")) {
+                       i++;
+               } else if (words.length >= 40) {
+                       locked = true;
+                       connected = true;
+
+                       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(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++;
+               }
+               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) {
+               lat = in_lat / 10.0e7;
+       }
+
+       public void set_longitude(int in_lon) {
+               lon = in_lon / 10.0e7;
+       }
+
+       public void set_time(int hour, int minute, int second) {
+               hour = hour;
+               minute = minute;
+               second = second;
+       }
+
+       public void set_date(int year, int month, int day) {
+               year = year;
+               month = month;
+               day = day;
+       }
+
+       public void set_flags(int flags) {
+               flags = flags;
+       }
+
+       public void set_altitude(int altitude) {
+               altitude = altitude;
+       }
+
+       public void add_sat(int svid, int c_n0) {
+               if (cc_gps_sat == null) {
+                       cc_gps_sat = new AltosGPS.AltosGPSSat[1];
+               } else {
+                       AltosGPSSat[] new_gps_sat = new AltosGPS.AltosGPSSat[cc_gps_sat.length + 1];
+                       for (int i = 0; i < cc_gps_sat.length; i++)
+                               new_gps_sat[i] = cc_gps_sat[i];
+                       cc_gps_sat = new_gps_sat;
+               }
+               AltosGPS.AltosGPSSat    sat = new AltosGPS.AltosGPSSat();
+               sat.svid = svid;
+               sat.c_n0 = c_n0;
+               cc_gps_sat[cc_gps_sat.length - 1] = sat;
+       }
+
+       public AltosGPS() {
+               ClearGPSTime();
+               cc_gps_sat = null;
+       }
+
+       public AltosGPS(AltosGPS old) {
+               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 */
+               year = old.year;
+               month = old.month;
+               day = old.day;
+               hour = old.hour;
+               minute = old.minute;
+               second = old.second;
+
+               gps_extended = old.gps_extended;        /* has extra data */
+               ground_speed = old.ground_speed;        /* m/s */
+               course = old.course;            /* degrees */
+               climb_rate = old.climb_rate;    /* m/s */
+               hdop = old.hdop;                /* unitless? */
+               h_error = old.h_error;  /* m */
+               v_error = old.v_error;  /* m */
+
+               if (old.cc_gps_sat != null) {
+                       cc_gps_sat = new AltosGPSSat[old.cc_gps_sat.length];
+                       for (int i = 0; i < old.cc_gps_sat.length; i++) {
+                               cc_gps_sat[i] = new AltosGPSSat();
+                               cc_gps_sat[i].svid = old.cc_gps_sat[i].svid;
+                               cc_gps_sat[i].c_n0 = old.cc_gps_sat[i].c_n0;
+                       }
+               }
+       }
+}
diff --git a/altosui/AltosGraph.java b/altosui/AltosGraph.java
new file mode 100644 (file)
index 0000000..58c2797
--- /dev/null
@@ -0,0 +1,25 @@
+
+// Copyright (c) 2010 Anthony Towns
+// GPL v2 or later
+
+package altosui;
+
+import java.io.*;
+
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.ChartUtilities;
+
+abstract class AltosGraph {
+    public String filename;
+    public abstract void addData(AltosDataPoint d);
+    public abstract JFreeChart createChart();
+    public void toPNG() throws java.io.IOException { toPNG(300, 500); }
+    public void toPNG(int width, int height)
+        throws java.io.IOException
+    {
+        File pngout = new File(filename);
+        JFreeChart chart = createChart();
+        ChartUtilities.saveChartAsPNG(pngout, chart, width, height);
+        System.out.println("Created " + filename);
+    }
+}
diff --git a/altosui/AltosGraphTime.java b/altosui/AltosGraphTime.java
new file mode 100644 (file)
index 0000000..a545128
--- /dev/null
@@ -0,0 +1,233 @@
+
+// Copyright (c) 2010 Anthony Towns
+// GPL v2 or later
+
+package altosui;
+
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import org.jfree.chart.ChartUtilities;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.axis.AxisLocation;
+import org.jfree.chart.axis.NumberAxis;
+import org.jfree.chart.labels.StandardXYToolTipGenerator;
+import org.jfree.chart.plot.PlotOrientation;
+import org.jfree.chart.plot.XYPlot;
+import org.jfree.chart.plot.ValueMarker;
+import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
+import org.jfree.chart.renderer.xy.XYItemRenderer;
+import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
+import org.jfree.data.xy.XYSeries;
+import org.jfree.data.xy.XYSeriesCollection;
+import org.jfree.ui.RectangleAnchor;
+import org.jfree.ui.TextAnchor;
+
+class AltosGraphTime extends AltosGraph {
+    static interface Element {
+        void attachGraph(AltosGraphTime g);
+        void gotTimeData(double time, AltosDataPoint d);
+        void addToPlot(AltosGraphTime g, XYPlot plot);
+    }
+
+    static class TimeAxis implements Element {
+        private int axis;
+        private Color color;
+        private String label;
+        private AxisLocation locn;
+        private double min_y = Double.NaN;
+
+        public TimeAxis(int axis, String label, Color color, AxisLocation locn)
+        {
+            this.axis = axis;
+            this.color = color;
+            this.label = label;
+            this.locn = locn;
+        }
+
+        public void setLowerBound(double min_y) {
+            this.min_y = min_y;
+        }
+
+        public void attachGraph(AltosGraphTime g) { return; }
+        public void gotTimeData(double time, AltosDataPoint d) { return; }
+
+        public void addToPlot(AltosGraphTime g, XYPlot plot) {
+            NumberAxis numAxis = new NumberAxis(label);
+            if (!Double.isNaN(min_y))
+                numAxis.setLowerBound(min_y);
+            plot.setRangeAxis(axis, numAxis);
+            plot.setRangeAxisLocation(axis, locn);
+            numAxis.setLabelPaint(color);
+            numAxis.setTickLabelPaint(color);
+            numAxis.setAutoRangeIncludesZero(false);
+        }
+    }
+
+    abstract static class TimeSeries implements Element {
+        protected XYSeries series;
+        private String axisName;
+        private Color color;
+
+        public TimeSeries(String axisName, String label, Color color) {
+            this.series = new XYSeries(label);
+            this.axisName = axisName;
+            this.color = color;
+        }
+
+        public void attachGraph(AltosGraphTime g) {
+            g.setAxis(this, axisName, color);
+        }
+        abstract public void gotTimeData(double time, AltosDataPoint d);
+
+        public void addToPlot(AltosGraphTime g, XYPlot plot) {
+            XYSeriesCollection dataset = new XYSeriesCollection();
+            dataset.addSeries(this.series);
+
+            XYItemRenderer renderer = new StandardXYItemRenderer();
+            renderer.setSeriesPaint(0, color);
+
+            int dataNum = g.getDataNum(this);
+            int axisNum = g.getAxisNum(this);
+
+            plot.setDataset(dataNum, dataset);
+            plot.mapDatasetToRangeAxis(dataNum, axisNum);
+            plot.setRenderer(dataNum, renderer);
+        }
+    }
+
+    static class StateMarker implements Element {
+        private double val = Double.NaN;
+        private String name;
+        private int state;
+
+        StateMarker(int state, String name) {
+            this.state = state;
+            this.name = name;
+        }
+
+        public void attachGraph(AltosGraphTime g) { return; }
+        public void gotTimeData(double time, AltosDataPoint d) {
+            if (Double.isNaN(val) || time < val) {
+                if (d.state() == state) {
+                    val = time;
+                }
+            }
+        }
+
+        public void addToPlot(AltosGraphTime g, XYPlot plot) {
+            if (Double.isNaN(val))
+                return;
+
+            ValueMarker m = new ValueMarker(val);
+            m.setLabel(name);
+            m.setLabelAnchor(RectangleAnchor.TOP_RIGHT);
+            m.setLabelTextAnchor(TextAnchor.TOP_LEFT);
+            plot.addDomainMarker(m);
+        }
+    }
+
+    private String callsign = null;
+    private Integer serial = null;
+    private Integer flight = null; 
+
+    private String title;
+    private ArrayList<Element> elements;
+    private HashMap<String,Integer> axes;
+    private HashMap<Element,Integer> datasets;
+    private ArrayList<Integer> datasetAxis;
+
+    public AltosGraphTime(String title) {
+        this.filename = title.toLowerCase().replaceAll("[^a-z0-9]","_")+".png";
+        this.title = title;
+        this.elements = new ArrayList<Element>();
+        this.axes = new HashMap<String,Integer>();
+        this.datasets = new HashMap<Element,Integer>();
+        this.datasetAxis = new ArrayList<Integer>();
+    }
+
+    public AltosGraphTime addElement(Element e) {
+        e.attachGraph(this);
+        elements.add(e);
+        return this;
+    }
+
+    public void setAxis(Element ds, String axisName, Color color) {
+        Integer axisNum = axes.get(axisName);
+        int dsNum = datasetAxis.size();
+        if (axisNum == null) {
+            axisNum = newAxis(axisName, color);
+        }
+        datasets.put(ds, dsNum);
+        datasetAxis.add(axisNum);
+    }
+
+    public int getAxisNum(Element ds) {
+        return datasetAxis.get( datasets.get(ds) ).intValue();
+    }
+    public int getDataNum(Element ds) {
+        return datasets.get(ds).intValue();
+    }
+
+    private Integer newAxis(String name, Color color) {
+        int cnt = axes.size();
+        AxisLocation locn = AxisLocation.BOTTOM_OR_LEFT;
+        if (cnt > 0) {
+            locn = AxisLocation.TOP_OR_RIGHT;
+        }
+        Integer res = new Integer(cnt);
+        axes.put(name, res);
+        this.addElement(new TimeAxis(cnt, name, color, locn));
+        return res;
+    }
+
+    public void addData(AltosDataPoint d) {
+        double time = d.time();
+        for (Element e : elements) {
+            e.gotTimeData(time, d);
+        }
+        if (callsign == null) callsign = d.callsign();
+        if (serial == null) serial = new Integer(d.serial());
+        if (flight == null) flight = new Integer(d.flight());
+    }
+
+    public JFreeChart createChart() {
+        NumberAxis xAxis = new NumberAxis("Time (s)");
+        xAxis.setAutoRangeIncludesZero(false);
+        XYItemRenderer renderer = new XYLineAndShapeRenderer(true, false);
+        XYPlot plot = new XYPlot();
+        plot.setDomainAxis(xAxis);
+        plot.setRenderer(renderer);
+        plot.setOrientation(PlotOrientation.VERTICAL);
+
+        if (serial != null && flight != null) {
+            title = serial + "/" + flight + ": " + title;
+        }
+        if (callsign != null) {
+            title = callsign + " - " + title;
+        }
+
+        renderer.setBaseToolTipGenerator(new StandardXYToolTipGenerator());
+        JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT,
+                                plot, true);
+        ChartUtilities.applyCurrentTheme(chart);
+
+        plot.setDomainPannable(true);
+        plot.setRangePannable(true);
+   
+        for (Element e : elements) {
+            e.addToPlot(this, plot);
+        }
+
+        return chart;
+    }
+
+    public void toPNG() throws java.io.IOException {
+        if (axes.size() > 1) {
+            toPNG(800, 500);
+        } else {
+            toPNG(300, 500);
+        }
+    }
+}
diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java
new file mode 100644 (file)
index 0000000..cd15865
--- /dev/null
@@ -0,0 +1,274 @@
+
+// Copyright (c) 2010 Anthony Towns
+// GPL v2 or later
+
+package altosui;
+
+import java.io.*;
+import java.util.ArrayList;
+
+import javax.swing.JFrame;
+import java.awt.Color;
+
+import org.jfree.chart.ChartPanel;
+import org.jfree.chart.ChartUtilities;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.axis.AxisLocation;
+import org.jfree.ui.ApplicationFrame;
+import org.jfree.ui.RefineryUtilities;
+
+public class AltosGraphUI extends JFrame 
+{
+    static final private Color red = new Color(194,31,31);
+    static final private Color green = new Color(31,194,31);
+    static final private Color blue = new Color(31,31,194);
+    static final private Color black = new Color(31,31,31);
+
+    static private class OverallGraphs {
+        AltosGraphTime.Element height = 
+            new AltosGraphTime.TimeSeries("Height (m)", "Height (AGL)", red) {
+                public void gotTimeData(double time, AltosDataPoint d) {
+                    series.add(time, d.height()); 
+                } 
+            };
+    
+        AltosGraphTime.Element speed =
+            new AltosGraphTime.TimeSeries("Speed (m/s)", "Vertical Speed", green) { 
+                public void gotTimeData(double time, AltosDataPoint d) {
+                    if (d.state() < Altos.ao_flight_drogue) {
+                        series.add(time, d.accel_speed());
+                    } else {
+                        series.add(time, d.baro_speed());
+                    }
+                }
+            };
+    
+        AltosGraphTime.Element acceleration =
+            new AltosGraphTime.TimeSeries("Acceleration (m/s\u00B2)", 
+                    "Axial Acceleration", blue) 
+            {
+                public void gotTimeData(double time, AltosDataPoint d) {
+                    series.add(time, d.acceleration());
+                }
+            };
+    
+        AltosGraphTime.Element temperature =
+            new AltosGraphTime.TimeSeries("Temperature (\u00B0C)", 
+                    "Board temperature", red) 
+            {
+                public void gotTimeData(double time, AltosDataPoint d) {
+                    series.add(time, d.temperature());
+                }
+            };
+    
+        AltosGraphTime.Element drogue_voltage =
+            new AltosGraphTime.TimeSeries("Voltage (V)", "Drogue Continuity", blue) 
+            {
+                public void gotTimeData(double time, AltosDataPoint d) {
+                    series.add(time, d.drogue_voltage());
+                }
+            };
+    
+        AltosGraphTime.Element main_voltage =
+            new AltosGraphTime.TimeSeries("Voltage (V)", "Main Continuity", green) 
+            {
+                public void gotTimeData(double time, AltosDataPoint d) {
+                    series.add(time, d.main_voltage());
+                }
+            };
+    
+        AltosGraphTime.Element e_pad    = new AltosGraphTime.StateMarker(Altos.ao_flight_pad, "Pad");
+        AltosGraphTime.Element e_boost  = new AltosGraphTime.StateMarker(Altos.ao_flight_boost, "Boost");
+        AltosGraphTime.Element e_fast   = new AltosGraphTime.StateMarker(Altos.ao_flight_fast, "Fast");
+        AltosGraphTime.Element e_coast  = new AltosGraphTime.StateMarker(Altos.ao_flight_coast, "Coast");
+       AltosGraphTime.Element e_drogue = new AltosGraphTime.StateMarker(Altos.ao_flight_drogue, "Drogue");
+       AltosGraphTime.Element e_main   = new AltosGraphTime.StateMarker(Altos.ao_flight_main, "Main");
+        AltosGraphTime.Element e_landed = new AltosGraphTime.StateMarker(Altos.ao_flight_landed, "Landed");
+    
+        protected AltosGraphTime myAltosGraphTime(String suffix) {
+            return (new AltosGraphTime("Overall " + suffix))
+                .addElement(e_boost)
+                .addElement(e_drogue)
+                .addElement(e_main)
+                .addElement(e_landed);
+        }
+    
+        public ArrayList<AltosGraph> graphs() {
+            ArrayList<AltosGraph> graphs = new ArrayList<AltosGraph>();
+    
+            graphs.add( myAltosGraphTime("Summary")
+                    .addElement(height)
+                    .addElement(speed)
+                    .addElement(acceleration) );
+    
+            graphs.add( myAltosGraphTime("Altitude")
+                    .addElement(height) );
+    
+            graphs.add( myAltosGraphTime("Speed")
+                    .addElement(speed) );
+    
+            graphs.add( myAltosGraphTime("Acceleration")
+                    .addElement(acceleration) );
+    
+            graphs.add( myAltosGraphTime("Temperature")
+                    .addElement(temperature) );
+    
+            graphs.add( myAltosGraphTime("Continuity")
+                    .addElement(drogue_voltage)
+                    .addElement(main_voltage) );
+    
+            return graphs;
+        }
+    }
+    
+    static private class AscentGraphs extends OverallGraphs {
+        protected AltosGraphTime myAltosGraphTime(String suffix) {
+            return (new AltosGraphTime("Ascent " + suffix) {
+                public void addData(AltosDataPoint d) {
+                    int state = d.state();
+                    if (Altos.ao_flight_boost <= state && state <= Altos.ao_flight_coast) {
+                        super.addData(d);
+                    }
+                }
+            }).addElement(e_boost)
+              .addElement(e_fast)
+              .addElement(e_coast);
+        }
+    }
+    
+    static private class DescentGraphs extends OverallGraphs {
+        protected AltosGraphTime myAltosGraphTime(String suffix) {
+            return (new AltosGraphTime("Descent " + suffix) {
+                public void addData(AltosDataPoint d) {
+                    int state = d.state();
+                    if (Altos.ao_flight_drogue <= state && state <= Altos.ao_flight_main) {
+                        super.addData(d);
+                    }
+                }
+            }).addElement(e_drogue)
+              .addElement(e_main);
+            // ((XYGraph)graph[8]).ymin = new Double(-50);
+        }
+    }
+
+       public AltosGraphUI(AltosRecordIterable records) {
+               super("Altos Graph");
+
+               Iterable<AltosDataPoint> reader = new AltosDataPointReader (records);
+               if (reader == null)
+                       return;
+        
+               init(reader, 0);
+       }
+
+    public AltosGraphUI(Iterable<AltosDataPoint> data, int which) 
+    {
+        super("Altos Graph");
+        init(data, which);
+    }
+
+    private void init(Iterable<AltosDataPoint> data, int which) {
+        AltosGraph graph = createGraph(data, which);
+
+        JFreeChart chart = graph.createChart();
+        ChartPanel chartPanel = new ChartPanel(chart);
+        chartPanel.setMouseWheelEnabled(true);
+        chartPanel.setPreferredSize(new java.awt.Dimension(800, 500));
+        setContentPane(chartPanel);
+
+        pack();
+
+        RefineryUtilities.centerFrameOnScreen(this);
+
+        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
+        setVisible(true);
+    }
+
+    private static AltosGraph createGraph(Iterable<AltosDataPoint> data,
+            int which)
+    {
+        return createGraphsWhich(data, which).get(0);
+    }
+
+    private static ArrayList<AltosGraph> createGraphs(
+            Iterable<AltosDataPoint> data)
+    {
+        return createGraphsWhich(data, -1);
+    }
+
+    private static ArrayList<AltosGraph> createGraphsWhich(
+            Iterable<AltosDataPoint> data, int which)
+    {
+        ArrayList<AltosGraph> graph = new ArrayList<AltosGraph>();
+        graph.addAll((new OverallGraphs()).graphs());
+        graph.addAll((new AscentGraphs()).graphs());
+        graph.addAll((new DescentGraphs()).graphs());
+
+        if (which > 0) {
+            if (which >= graph.size()) {
+                which = 0;
+            }
+            AltosGraph g = graph.get(which);
+            graph = new ArrayList<AltosGraph>();
+            graph.add(g);
+        }
+
+        for (AltosDataPoint dp : data) {
+            for (AltosGraph g : graph) {
+                g.addData(dp);
+            }
+        }
+
+        return graph;
+    }
+}
+
+/* gnuplot bits...
+ *
+300x400
+
+--------------------------------------------------------
+TOO HARD! :)
+
+"ascent-gps-accuracy.png" "Vertical error margin to apogee - GPS v Baro (m)"
+    5:($7 < 6 ? $24-$11 : 1/0)
+"descent-gps-accuracy.png" "Vertical error margin during descent - GPS v Baro (m)"
+    5:($7 < 6 ? 1/0 : $24-$11)
+
+set output "overall-gps-accuracy.png"
+set ylabel "distance above sea level (m)"
+plot "telemetry.csv" using 5:11 with lines ti "baro altitude" axis x1y1, \
+    "telemetry.csv" using 5:24 with lines ti "gps altitude" axis x1y1
+
+set term png tiny size 700,700 enhanced
+set xlabel "m"
+set ylabel "m"
+set polar
+set grid polar
+set rrange[*:*]
+set angles degrees
+
+set output "overall-gps-path.png"
+#:30 with yerrorlines
+plot "telemetry.csv" using (90-$33):($7 == 2 ? $31 : 1/0) with lines ti "pad", \
+    "telemetry.csv" using (90-$33):($7 == 3 ? $31 : 1/0) with lines ti "boost", \
+    "telemetry.csv" using (90-$33):($7 == 4 ? $31 : 1/0) with lines ti "fast", \
+    "telemetry.csv" using (90-$33):($7 == 5 ? $31 : 1/0) with lines ti "coast", \
+    "telemetry.csv" using (90-$33):($7 == 6 ? $31 : 1/0) with lines ti "drogue", \
+    "telemetry.csv" using (90-$33):($7 == 7 ? $31 : 1/0) with lines ti "main", \
+    "telemetry.csv" using (90-$33):($7 == 8 ? $31 : 1/0) with lines ti "landed"
+
+set output "ascent-gps-path.png"
+plot "telemetry.csv" using (90-$33):($7 == 2 ? $31 : 1/0):30 with lines ti "pad", \
+    "telemetry.csv" using (90-$33):($7 == 3 ? $31 : 1/0):20 with lines ti "boost", \
+    "telemetry.csv" using (90-$33):($7 == 4 ? $31 : 1/0):10 with lines ti "fast", \
+    "telemetry.csv" using (90-$33):($7 == 5 ? $31 : 1/0):5 with lines ti "coast"
+
+set output "descent-gps-path.png"
+plot "telemetry.csv" using (90-$33):($7 == 6 ? $31 : 1/0) with lines ti "drogue", \
+    "telemetry.csv" using (90-$33):($7 == 7 ? $31 : 1/0) with lines ti "main", \
+    "telemetry.csv" using (90-$33):($7 == 8 ? $31 : 1/0) with lines ti "landed"
+
+ */
+
+
diff --git a/altosui/AltosGreatCircle.java b/altosui/AltosGreatCircle.java
new file mode 100644 (file)
index 0000000..fb1b6ab
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * 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.lang.Math;
+
+public class AltosGreatCircle {
+       double  distance;
+       double  bearing;
+
+       double sqr(double a) { return a * a; }
+
+       static final double rad = Math.PI / 180;
+       static final double earth_radius = 6371.2 * 1000;       /* in meters */
+
+    static int BEARING_LONG = 0;
+    static int BEARING_SHORT = 1;
+    static int BEARING_VOICE = 2;
+    String bearing_words(int length) {
+        String [][] bearing_string = {
+          {
+            "North", "North North East", "North East", "East North East",
+            "East", "East South East", "South East", "South South East",
+            "South", "South South West", "South West", "West South West",
+            "West", "West North West", "North West", "North North West"
+          }, {
+            "N", "NNE", "NE", "ENE",
+            "E", "ESE", "SE", "SSE",
+            "S", "SSW", "SW", "WSW",
+            "W", "WNW", "NW", "NNW"
+          }, {
+            "north", "nor nor east", "north east", "east nor east",
+            "east", "east sow east", "south east", "sow sow east",
+            "south", "sow sow west", "south west", "west sow west",
+            "west", "west nor west", "north west", "nor nor west "
+          }
+        };
+        return bearing_string[length][(int)((bearing / 90 * 8 + 1) / 2)%16];
+    }
+
+       public AltosGreatCircle (double start_lat, double start_lon,
+                                double end_lat, double end_lon)
+       {
+               double lat1 = rad * start_lat;
+               double lon1 = rad * -start_lon;
+               double lat2 = rad * end_lat;
+               double lon2 = rad * -end_lon;
+
+               double d_lon = lon2 - lon1;
+
+               /* From http://en.wikipedia.org/wiki/Great-circle_distance */
+               double vdn = Math.sqrt(sqr(Math.cos(lat2) * Math.sin(d_lon)) +
+                                      sqr(Math.cos(lat1) * Math.sin(lat2) -
+                                          Math.sin(lat1) * Math.cos(lat2) * Math.cos(d_lon)));
+               double vdd = Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos(d_lon);
+               double d = Math.atan2(vdn,vdd);
+               double course;
+
+               if (Math.cos(lat1) < 1e-20) {
+                       if (lat1 > 0)
+                               course = Math.PI;
+                       else
+                               course = -Math.PI;
+               } else {
+                       if (d < 1e-10)
+                               course = 0;
+                       else
+                               course = Math.acos((Math.sin(lat2)-Math.sin(lat1)*Math.cos(d)) /
+                                                  (Math.sin(d)*Math.cos(lat1)));
+                       if (Math.sin(lon2-lon1) > 0)
+                               course = 2 * Math.PI-course;
+               }
+               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/altosui/AltosHexfile.java b/altosui/AltosHexfile.java
new file mode 100644 (file)
index 0000000..19e35ae
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * 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.lang.*;
+import java.io.*;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.LinkedList;
+import java.util.Iterator;
+import java.util.Arrays;
+
+class HexFileInputStream extends PushbackInputStream {
+       public int line;
+
+       public HexFileInputStream(FileInputStream o) {
+               super(new BufferedInputStream(o));
+               line = 1;
+       }
+
+       public int read() throws IOException {
+               int     c = super.read();
+               if (c == '\n')
+                       line++;
+               return c;
+       }
+
+       public void unread(int c) throws IOException {
+               if (c == '\n')
+                       line--;
+               if (c != -1)
+                       super.unread(c);
+       }
+}
+
+class HexRecord implements Comparable {
+       public int      address;
+       public int      type;
+       public byte     checksum;
+       public byte[]   data;
+
+       static final int NORMAL = 0;
+       static final int EOF = 1;
+       static final int EXTENDED_ADDRESS = 2;
+
+       enum read_state {
+               marker,
+               length,
+               address,
+               type,
+               data,
+               checksum,
+               newline,
+               white,
+               done,
+       }
+
+       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;
+       }
+
+       boolean isspace(int c) {
+               switch (c) {
+               case ' ':
+               case '\t':
+                       return true;
+               }
+               return false;
+       }
+
+       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;
+       }
+
+       public byte checksum() {
+               byte    got = 0;
+
+               got += data.length;
+               got += (address >> 8) & 0xff;
+               got += (address     ) & 0xff;
+               got += type;
+               for (int i = 0; i < data.length; i++)
+                       got += data[i];
+               return (byte) (-got);
+       }
+
+       public int compareTo(Object other) {
+               HexRecord       o = (HexRecord) other;
+               return address - o.address;
+       }
+
+       public String toString() {
+               return String.format("%04x: %02x (%d)", address, type, data.length);
+       }
+
+       public HexRecord(HexFileInputStream input) throws IOException {
+               read_state      state = read_state.marker;
+               int             nhexbytes = 0;
+               int             hex = 0;
+               int             ndata = 0;
+               byte            got_checksum;
+
+               while (state != read_state.done) {
+                       int c = input.read();
+                       if (c < 0 && state != read_state.white)
+                               throw new IOException(String.format("%d: Unexpected EOF", input.line));
+                       if (c == ' ')
+                               continue;
+                       switch (state) {
+                       case marker:
+                               if (c != ':')
+                                       throw new IOException("Missing ':'");
+                               state = read_state.length;
+                               nhexbytes = 2;
+                               hex = 0;
+                               break;
+                       case length:
+                       case address:
+                       case type:
+                       case data:
+                       case checksum:
+                               if(!ishex(c))
+                                       throw new IOException(String.format("Non-hex char '%c'", c));
+                               hex = hex << 4 | fromhex(c);
+                               --nhexbytes;
+                               if (nhexbytes != 0)
+                                       break;
+
+                               switch (state) {
+                               case length:
+                                       data = new byte[hex];
+                                       state = read_state.address;
+                                       nhexbytes = 4;
+                                       break;
+                               case address:
+                                       address = hex;
+                                       state = read_state.type;
+                                       nhexbytes = 2;
+                                       break;
+                               case type:
+                                       type = hex;
+                                       if (data.length > 0)
+                                               state = read_state.data;
+                                       else
+                                               state = read_state.checksum;
+                                       nhexbytes = 2;
+                                       ndata = 0;
+                                       break;
+                               case data:
+                                       data[ndata] = (byte) hex;
+                                       ndata++;
+                                       nhexbytes = 2;
+                                       if (ndata == data.length)
+                                               state = read_state.checksum;
+                                       break;
+                               case checksum:
+                                       checksum = (byte) hex;
+                                       state = read_state.newline;
+                                       break;
+                               default:
+                                       break;
+                               }
+                               hex = 0;
+                               break;
+                       case newline:
+                               if (c != '\n' && c != '\r')
+                                       throw new IOException("Missing newline");
+                               state = read_state.white;
+                               break;
+                       case white:
+                               if (!isspace(c)) {
+                                       input.unread(c);
+                                       state = read_state.done;
+                               }
+                               break;
+                       case done:
+                               break;
+                       }
+               }
+               got_checksum = checksum();
+               if (got_checksum != checksum)
+                       throw new IOException(String.format("Invalid checksum (read 0x%02x computed 0x%02x)\n",
+                                                           checksum, got_checksum));
+       }
+}
+
+public class AltosHexfile {
+       public int      address;
+       public byte[]   data;
+
+       public byte get_byte(int a) {
+               return data[a - address];
+       }
+
+       public AltosHexfile(FileInputStream file) throws IOException {
+               HexFileInputStream      input = new HexFileInputStream(file);
+               LinkedList<HexRecord>   record_list = new LinkedList<HexRecord>();
+               boolean                 done = false;
+
+               while (!done) {
+                       HexRecord       record = new HexRecord(input);
+
+                       if (record.type == HexRecord.EOF)
+                               done = true;
+                       else
+                               record_list.add(record);
+               }
+               HexRecord[] records  = record_list.toArray(new HexRecord[0]);
+               Arrays.sort(records);
+               if (records.length > 0) {
+                       int     base = records[0].address;
+                       int     bound = records[records.length-1].address +
+                               records[records.length-1].data.length;
+
+                       data = new byte[bound - base];
+                       address = base;
+                       Arrays.fill(data, (byte) 0xff);
+
+                       /* Paint the records into the new array */
+                       for (int i = 0; i < records.length; i++) {
+                               for (int j = 0; j < records[i].data.length; j++)
+                                       data[records[i].address - base + j] = records[i].data[j];
+                       }
+               }
+       }
+}
\ No newline at end of file
diff --git a/altosui/AltosIgnite.java b/altosui/AltosIgnite.java
new file mode 100644 (file)
index 0000000..3cbd8a7
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * 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.io.*;
+import java.util.concurrent.*;
+
+public class AltosIgnite {
+       AltosDevice     device;
+       AltosSerial     serial;
+       boolean         remote;
+       boolean         serial_started;
+       final static int        None = 0;
+       final static int        Apogee = 1;
+       final static int        Main = 2;
+
+       final static int        Unknown = 0;
+       final static int        Ready = 1;
+       final static int        Active = 2;
+       final static int        Open = 3;
+
+       private void start_serial() throws InterruptedException {
+               serial_started = true;
+               if (remote) {
+                       serial.set_radio();
+                       serial.printf("p\nE 0\n");
+                       serial.flush_input();
+               }
+       }
+
+       private void stop_serial() throws InterruptedException {
+               if (!serial_started)
+                       return;
+               serial_started = false;
+               if (serial == null)
+                       return;
+               if (remote) {
+                       serial.printf("~");
+                       serial.flush_output();
+               }
+       }
+
+       class string_ref {
+               String  value;
+
+               public String get() {
+                       return value;
+               }
+               public void set(String i) {
+                       value = i;
+               }
+               public string_ref() {
+                       value = null;
+               }
+       }
+
+       private boolean get_string(String line, String label, string_ref s) {
+               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);
+                       s.set(quoted);
+                       return true;
+               } else {
+                       return false;
+               }
+       }
+
+       private int status(String status_name) {
+               if (status_name.equals("unknown"))
+                       return Unknown;
+               if (status_name.equals("ready"))
+                       return Ready;
+               if (status_name.equals("active"))
+                       return Active;
+               if (status_name.equals("open"))
+                       return Open;
+               return Unknown;
+       }
+
+       public int status(int igniter) throws InterruptedException, TimeoutException {
+               int status = Unknown;
+               if (serial == null)
+                       return status;
+               string_ref status_name = new string_ref();
+               start_serial();
+               serial.printf("t\n");
+               for (;;) {
+                       String line = serial.get_reply(5000);
+                       if (line == null)
+                               throw new TimeoutException();
+                       if (get_string(line, "Igniter: drogue Status: ", status_name))
+                               if (igniter == Apogee)
+                                       status = status(status_name.get());
+                       if (get_string(line, "Igniter:   main Status: ", status_name)) {
+                               if (igniter == Main)
+                                       status = status(status_name.get());
+                               break;
+                       }
+               }
+               stop_serial();
+               return status;
+       }
+
+       public String status_string(int status) {
+               switch (status) {
+               case Unknown: return "Unknown";
+               case Ready: return "Ready";
+               case Active: return "Active";
+               case Open: return "Open";
+               default: return "Unknown";
+               }
+       }
+
+       public void fire(int igniter) {
+               if (serial == null)
+                       return;
+               try {
+                       start_serial();
+                       switch (igniter) {
+                       case Main:
+                               serial.printf("i DoIt main\n");
+                               break;
+                       case Apogee:
+                               serial.printf("i DoIt drogue\n");
+                               break;
+                       }
+               } catch (InterruptedException ie) {
+               } finally {
+                       try {
+                               stop_serial();
+                       } catch (InterruptedException ie) {
+                       }
+               }
+       }
+
+       public void close() {
+               try {
+                       stop_serial();
+               } catch (InterruptedException ie) {
+               }
+               serial.close();
+               serial = null;
+       }
+
+       public AltosIgnite(AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException {
+
+               device = in_device;
+               serial = new AltosSerial(device);
+               remote = false;
+
+               if (!device.matchProduct(AltosDevice.product_telemetrum))
+                       remote = true;
+       }
+}
\ No newline at end of file
diff --git a/altosui/AltosIgniteUI.java b/altosui/AltosIgniteUI.java
new file mode 100644 (file)
index 0000000..d542729
--- /dev/null
@@ -0,0 +1,317 @@
+/*
+ * 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 javax.swing.event.*;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.util.prefs.*;
+import java.util.concurrent.*;
+
+public class AltosIgniteUI
+       extends JDialog
+       implements ActionListener
+{
+       AltosDevice     device;
+       AltosIgnite     ignite;
+       JFrame          owner;
+       JLabel          label;
+       JRadioButton    apogee;
+       JLabel          apogee_status_label;
+       JRadioButton    main;
+       JLabel          main_status_label;
+       JToggleButton   arm;
+       JButton         fire;
+       javax.swing.Timer       timer;
+
+       int             apogee_status;
+       int             main_status;
+
+       final static int        timeout = 1 * 1000;
+
+       int             time_remaining;
+       boolean         timer_running;
+
+       void set_arm_text() {
+               if (arm.isSelected())
+                       arm.setText(String.format("%d", time_remaining));
+               else
+                       arm.setText("Arm");
+       }
+
+       void start_timer() {
+               time_remaining = 10;
+               set_arm_text();
+               timer_running = true;
+       }
+
+       void stop_timer() {
+               time_remaining = 0;
+               arm.setSelected(false);
+               arm.setEnabled(false);
+               fire.setEnabled(false);
+               timer_running = false;
+               set_arm_text();
+       }
+
+       void cancel () {
+               apogee.setSelected(false);
+               main.setSelected(false);
+               fire.setEnabled(false);
+               stop_timer();
+       }
+
+       void get_ignite_status() throws InterruptedException, TimeoutException {
+               apogee_status = ignite.status(AltosIgnite.Apogee);
+               main_status = ignite.status(AltosIgnite.Main);
+       }
+
+       void set_ignite_status() throws InterruptedException, TimeoutException {
+               get_ignite_status();
+               apogee_status_label.setText(String.format("\"%s\"", ignite.status_string(apogee_status)));
+               main_status_label.setText(String.format("\"%s\"", ignite.status_string(main_status)));
+       }
+
+       void close() {
+               timer.stop();
+               setVisible(false);
+               ignite.close();
+       }
+
+       void abort() {
+               close();
+               JOptionPane.showMessageDialog(owner,
+                                             String.format("Connection to \"%s\" failed",
+                                                           device.toShortString()),
+                                             "Connection Failed",
+                                             JOptionPane.ERROR_MESSAGE);
+       }
+
+       void tick_timer() {
+               if (timer_running) {
+                       --time_remaining;
+                       if (time_remaining <= 0)
+                               cancel();
+                       else
+                               set_arm_text();
+               }
+               try {
+                       set_ignite_status();
+               } catch (InterruptedException ie) {
+                       abort();
+               } catch (TimeoutException te) {
+                       abort();
+               }
+       }
+
+       void fire() {
+               if (arm.isEnabled() && arm.isSelected() && time_remaining > 0) {
+                       int     igniter = AltosIgnite.None;
+                       if (apogee.isSelected() && !main.isSelected())
+                               igniter = AltosIgnite.Apogee;
+                       else if (main.isSelected() && !apogee.isSelected())
+                               igniter = AltosIgnite.Main;
+                       ignite.fire(igniter);
+                       cancel();
+               }
+       }
+
+       public void actionPerformed(ActionEvent e) {
+               String cmd = e.getActionCommand();
+               if (cmd.equals("apogee") || cmd.equals("main")) {
+                       stop_timer();
+               }
+
+               if (cmd.equals("apogee") && apogee.isSelected()) {
+                       main.setSelected(false);
+                       arm.setEnabled(true);
+               }
+               if (cmd.equals("main") && main.isSelected()) {
+                       apogee.setSelected(false);
+                       arm.setEnabled(true);
+               }
+
+               if (cmd.equals("arm")) {
+                       if (arm.isSelected()) {
+                               fire.setEnabled(true);
+                               start_timer();
+                       } else
+                               cancel();
+               }
+               if (cmd.equals("fire"))
+                       fire();
+               if (cmd.equals("tick"))
+                       tick_timer();
+               if (cmd.equals("close")) {
+                       close();
+               }
+       }
+
+       /* A window listener to catch closing events and tell the config code */
+       class ConfigListener extends WindowAdapter {
+               AltosIgniteUI   ui;
+
+               public ConfigListener(AltosIgniteUI this_ui) {
+                       ui = this_ui;
+               }
+
+               public void windowClosing(WindowEvent e) {
+                       ui.actionPerformed(new ActionEvent(e.getSource(),
+                                                          ActionEvent.ACTION_PERFORMED,
+                                                          "close"));
+               }
+       }
+
+       private boolean open() {
+               device = AltosDeviceDialog.show(owner, AltosDevice.product_any);
+               if (device != null) {
+                       try {
+                               ignite = new AltosIgnite(device);
+                               return true;
+                       } catch (FileNotFoundException ee) {
+                               JOptionPane.showMessageDialog(owner,
+                                                             String.format("Cannot open device \"%s\"",
+                                                                           device.toShortString()),
+                                                             "Cannot open target device",
+                                                             JOptionPane.ERROR_MESSAGE);
+                       } catch (AltosSerialInUseException si) {
+                               JOptionPane.showMessageDialog(owner,
+                                                             String.format("Device \"%s\" already in use",
+                                                                           device.toShortString()),
+                                                             "Device in use",
+                                                             JOptionPane.ERROR_MESSAGE);
+                       } catch (IOException ee) {
+                               JOptionPane.showMessageDialog(owner,
+                                                             device.toShortString(),
+                                                             ee.getLocalizedMessage(),
+                                                             JOptionPane.ERROR_MESSAGE);
+                       }
+               }
+               return false;
+       }
+
+       public AltosIgniteUI(JFrame in_owner) {
+
+               owner = in_owner;
+               apogee_status = AltosIgnite.Unknown;
+               main_status = AltosIgnite.Unknown;
+
+               if (!open())
+                       return;
+
+               Container               pane = getContentPane();
+               GridBagConstraints      c = new GridBagConstraints();
+               Insets                  i = new Insets(4,4,4,4);
+
+               timer = new javax.swing.Timer(timeout, this);
+               timer.setActionCommand("tick");
+               timer_running = false;
+               timer.restart();
+
+               owner = in_owner;
+
+               pane.setLayout(new GridBagLayout());
+
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.CENTER;
+               c.insets = i;
+               c.weightx = 1;
+               c.weighty = 1;
+
+               c.gridx = 0;
+               c.gridy = 0;
+               c.gridwidth = 2;
+               c.anchor = GridBagConstraints.CENTER;
+               label = new JLabel ("Fire Igniter");
+               pane.add(label, c);
+
+               c.gridx = 0;
+               c.gridy = 1;
+               c.gridwidth = 1;
+               c.anchor = GridBagConstraints.WEST;
+               apogee = new JRadioButton ("Apogee");
+               pane.add(apogee, c);
+               apogee.addActionListener(this);
+               apogee.setActionCommand("apogee");
+
+               c.gridx = 1;
+               c.gridy = 1;
+               c.gridwidth = 1;
+               c.anchor = GridBagConstraints.WEST;
+               apogee_status_label = new JLabel();
+               pane.add(apogee_status_label, c);
+
+               c.gridx = 0;
+               c.gridy = 2;
+               c.gridwidth = 1;
+               c.anchor = GridBagConstraints.WEST;
+               main = new JRadioButton ("Main");
+               pane.add(main, c);
+               main.addActionListener(this);
+               main.setActionCommand("main");
+
+               c.gridx = 1;
+               c.gridy = 2;
+               c.gridwidth = 1;
+               c.anchor = GridBagConstraints.WEST;
+               main_status_label = new JLabel();
+               pane.add(main_status_label, c);
+
+               try {
+                       set_ignite_status();
+               } catch (InterruptedException ie) {
+                       abort();
+                       return;
+               } catch (TimeoutException te) {
+                       abort();
+                       return;
+               }
+
+               c.gridx = 0;
+               c.gridy = 3;
+               c.gridwidth = 1;
+               c.anchor = GridBagConstraints.CENTER;
+               arm = new JToggleButton ("Arm");
+               pane.add(arm, c);
+               arm.addActionListener(this);
+               arm.setActionCommand("arm");
+               arm.setEnabled(false);
+
+               c.gridx = 1;
+               c.gridy = 3;
+               c.gridwidth = 1;
+               c.anchor = GridBagConstraints.CENTER;
+               fire = new JButton ("Fire");
+               fire.setEnabled(false);
+               pane.add(fire, c);
+               fire.addActionListener(this);
+               fire.setActionCommand("fire");
+
+               pack();
+               setLocationRelativeTo(owner);
+               setVisible(true);
+
+               addWindowListener(new ConfigListener(this));
+       }
+}
\ No newline at end of file
diff --git a/altosui/AltosInfoTable.java b/altosui/AltosInfoTable.java
new file mode 100644 (file)
index 0000000..723f830
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * 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;
+
+public class AltosInfoTable extends JTable {
+       private AltosFlightInfoTableModel model;
+
+       private Font infoLabelFont = new Font("SansSerif", Font.PLAIN, 14);
+       private Font infoValueFont = new Font("Monospaced", Font.PLAIN, 14);
+
+       static final int info_columns = 3;
+       static final int info_rows = 17;
+
+       int desired_row_height() {
+               FontMetrics     infoValueMetrics = getFontMetrics(infoValueFont);
+               return (infoValueMetrics.getHeight() + infoValueMetrics.getLeading()) * 18 / 10;
+       }
+
+       public AltosInfoTable() {
+               super(new AltosFlightInfoTableModel(info_rows, info_columns));
+               model = (AltosFlightInfoTableModel) getModel();
+               setFont(infoValueFont);
+               setAutoResizeMode(AUTO_RESIZE_ALL_COLUMNS);
+               setShowGrid(true);
+               setRowHeight(desired_row_height());
+               doLayout();
+       }
+
+       public Dimension getPreferredScrollableViewportSize() {
+               return getPreferredSize();
+       }
+
+       void info_reset() {
+               model.reset();
+       }
+
+       void info_add_row(int col, String name, String value) {
+               model.addRow(col, name, value);
+       }
+
+       void info_add_row(int col, String name, String format, Object... parameters) {
+               info_add_row (col, name, String.format(format, parameters));
+       }
+
+       void info_add_deg(int col, String name, double v, int pos, int neg) {
+               int     c = pos;
+               if (v < 0) {
+                       c = neg;
+                       v = -v;
+               }
+               double  deg = Math.floor(v);
+               double  min = (v - deg) * 60;
+
+               info_add_row(col, name, String.format("%3.0f°%08.5f'", deg, min));
+       }
+
+       void info_finish() {
+               model.finish();
+       }
+
+       public void clear() {
+               model.clear();
+       }
+
+       public void show(AltosState state, int crc_errors) {
+               if (state == null)
+                       return;
+               info_reset();
+               info_add_row(0, "Rocket state", "%s", state.data.state());
+               info_add_row(0, "Callsign", "%s", state.data.callsign);
+               info_add_row(0, "Rocket serial", "%6d", state.data.serial);
+               info_add_row(0, "Rocket flight", "%6d", state.data.flight);
+
+               info_add_row(0, "RSSI", "%6d    dBm", state.data.rssi);
+               info_add_row(0, "CRC Errors", "%6d", crc_errors);
+               info_add_row(0, "Height", "%6.0f    m", state.height);
+               info_add_row(0, "Max height", "%6.0f    m", state.max_height);
+               info_add_row(0, "Acceleration", "%8.1f  m/s²", state.acceleration);
+               info_add_row(0, "Max acceleration", "%8.1f  m/s²", state.max_acceleration);
+               info_add_row(0, "Speed", "%8.1f  m/s", state.ascent ? state.speed : state.baro_speed);
+               info_add_row(0, "Max Speed", "%8.1f  m/s", state.max_speed);
+               info_add_row(0, "Temperature", "%9.2f °C", state.temperature);
+               info_add_row(0, "Battery", "%9.2f V", state.battery);
+               info_add_row(0, "Drogue", "%9.2f V", state.drogue_sense);
+               info_add_row(0, "Main", "%9.2f V", state.main_sense);
+               info_add_row(0, "Pad altitude", "%6.0f    m", state.ground_altitude);
+               if (state.gps == null) {
+                       info_add_row(1, "GPS", "not available");
+               } else {
+                       if (state.gps_ready)
+                               info_add_row(1, "GPS state", "%s", "ready");
+                       else
+                               info_add_row(1, "GPS state", "wait (%d)",
+                                            state.gps_waiting);
+                       if (state.data.gps.locked)
+                               info_add_row(1, "GPS", "   locked");
+                       else if (state.data.gps.connected)
+                               info_add_row(1, "GPS", " unlocked");
+                       else
+                               info_add_row(1, "GPS", "  missing");
+                       info_add_row(1, "Satellites", "%6d", state.data.gps.nsat);
+                       info_add_deg(1, "Latitude", state.gps.lat, 'N', 'S');
+                       info_add_deg(1, "Longitude", state.gps.lon, 'E', 'W');
+                       info_add_row(1, "GPS altitude", "%6d", state.gps.alt);
+                       info_add_row(1, "GPS height", "%6.0f", state.gps_height);
+
+                       /* The SkyTraq GPS doesn't report these values */
+                       if (false) {
+                               info_add_row(1, "GPS ground speed", "%8.1f m/s %3d°",
+                                            state.gps.ground_speed,
+                                            state.gps.course);
+                               info_add_row(1, "GPS climb rate", "%8.1f m/s",
+                                            state.gps.climb_rate);
+                               info_add_row(1, "GPS error", "%6d m(h)%3d m(v)",
+                                            state.gps.h_error, state.gps.v_error);
+                       }
+                       info_add_row(1, "GPS hdop", "%8.1f", state.gps.hdop);
+
+                       if (state.npad > 0) {
+                               if (state.from_pad != null) {
+                                       info_add_row(1, "Distance from pad", "%6d m",
+                                                    (int) (state.from_pad.distance + 0.5));
+                                       info_add_row(1, "Direction from pad", "%6d°",
+                                                    (int) (state.from_pad.bearing + 0.5));
+                                       info_add_row(1, "Elevation from pad", "%6d°",
+                                                    (int) (state.elevation + 0.5));
+                                       info_add_row(1, "Range from pad", "%6d m",
+                                                    (int) (state.range + 0.5));
+                               } else {
+                                       info_add_row(1, "Distance from pad", "unknown");
+                                       info_add_row(1, "Direction from pad", "unknown");
+                                       info_add_row(1, "Elevation from pad", "unknown");
+                                       info_add_row(1, "Range from pad", "unknown");
+                               }
+                               info_add_deg(1, "Pad latitude", state.pad_lat, 'N', 'S');
+                               info_add_deg(1, "Pad longitude", state.pad_lon, 'E', 'W');
+                               info_add_row(1, "Pad GPS alt", "%6.0f m", state.pad_alt);
+                       }
+                       info_add_row(1, "GPS date", "%04d-%02d-%02d",
+                                      state.gps.year,
+                                      state.gps.month,
+                                      state.gps.day);
+                       info_add_row(1, "GPS time", "  %02d:%02d:%02d",
+                                      state.gps.hour,
+                                      state.gps.minute,
+                                      state.gps.second);
+                       int     nsat_vis = 0;
+                       int     c;
+
+                       if (state.gps.cc_gps_sat == null)
+                               info_add_row(2, "Satellites Visible", "%4d", 0);
+                       else {
+                               info_add_row(2, "Satellites Visible", "%4d", state.gps.cc_gps_sat.length);
+                               for (c = 0; c < state.gps.cc_gps_sat.length; c++) {
+                                       info_add_row(2, "Satellite id,C/N0",
+                                                    "%4d, %4d",
+                                                    state.gps.cc_gps_sat[c].svid,
+                                                    state.gps.cc_gps_sat[c].c_n0);
+                               }
+                       }
+               }
+               info_finish();
+       }
+}
diff --git a/altosui/AltosKML.java b/altosui/AltosKML.java
new file mode 100644 (file)
index 0000000..d586033
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * 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.lang.*;
+import java.io.*;
+import java.text.*;
+import java.util.*;
+
+public class AltosKML implements AltosWriter {
+
+       File                    name;
+       PrintStream             out;
+       int                     state = -1;
+       AltosRecord             prev = null;
+
+       static final String[] kml_state_colors = {
+               "FF000000",
+               "FF000000",
+               "FF000000",
+               "FF0000FF",
+               "FF4080FF",
+               "FF00FFFF",
+               "FFFF0000",
+               "FF00FF00",
+               "FF000000",
+               "FFFFFFFF"
+       };
+
+       static final String kml_header_start =
+               "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+               "<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n" +
+               "<Document>\n" +
+               "  <name>AO Flight#%d S/N: %03d</name>\n" +
+               "  <description>\n";
+       static final String kml_header_end =
+               "  </description>\n" +
+               "  <open>0</open>\n";
+
+       static final String kml_style_start =
+               "  <Style id=\"ao-flightstate-%s\">\n" +
+               "    <LineStyle><color>%s</color><width>4</width></LineStyle>\n" +
+               "    <BalloonStyle>\n" +
+               "      <text>\n";
+
+       static final String kml_style_end =
+               "      </text>\n" +
+               "    </BalloonStyle>\n" +
+               "  </Style>\n";
+
+       static final String kml_placemark_start =
+               "  <Placemark>\n" +
+               "    <name>%s</name>\n" +
+               "    <styleUrl>#ao-flightstate-%s</styleUrl>\n" +
+               "    <LineString>\n" +
+               "      <tessellate>1</tessellate>\n" +
+               "      <altitudeMode>absolute</altitudeMode>\n" +
+               "      <coordinates>\n";
+
+       static final String kml_coord_fmt =
+       "        %12.7f, %12.7f, %12.7f <!-- alt %12.7f time %12.7f sats %d -->\n";
+
+       static final String kml_placemark_end =
+               "      </coordinates>\n" +
+               "    </LineString>\n" +
+               "  </Placemark>\n";
+
+       static final String kml_footer =
+               "</Document>\n" +
+               "</kml>\n";
+
+       void start (AltosRecord record) {
+               out.printf(kml_header_start, record.flight, record.serial);
+               out.printf("Date:   %04d-%02d-%02d\n",
+                          record.gps.year, record.gps.month, record.gps.day);
+               out.printf("Time:     %2d:%02d:%02d\n",
+                          record.gps.hour, record.gps.minute, record.gps.second);
+               out.printf("%s", kml_header_end);
+       }
+
+       boolean started = false;
+
+       void state_start(AltosRecord record) {
+               String  state_name = Altos.state_name(record.state);
+               out.printf(kml_style_start, state_name, kml_state_colors[record.state]);
+               out.printf("\tState: %s\n", state_name);
+               out.printf("%s", kml_style_end);
+               out.printf(kml_placemark_start, state_name, state_name);
+       }
+
+       void state_end(AltosRecord record) {
+               out.printf("%s", kml_placemark_end);
+       }
+
+       void coord(AltosRecord record) {
+               AltosGPS        gps = record.gps;
+               out.printf(kml_coord_fmt,
+                          gps.lon, gps.lat,
+                          record.filtered_altitude(), (double) gps.alt,
+                          record.time, gps.nsat);
+       }
+
+       void end() {
+               out.printf("%s", kml_footer);
+       }
+
+       public void close() {
+               if (prev != null) {
+                       state_end(prev);
+                       end();
+                       prev = null;
+               }
+       }
+
+       public void write(AltosRecord record) {
+               AltosGPS        gps = record.gps;
+
+               if (gps == null)
+                       return;
+               if (!started) {
+                       start(record);
+                       started = true;
+               }
+               if (prev != null &&
+                   prev.gps.second == record.gps.second &&
+                   prev.gps.minute == record.gps.minute &&
+                   prev.gps.hour == record.gps.hour)
+                       return;
+               if (record.state != state) {
+                       state = record.state;
+                       if (prev != null) {
+                               coord(record);
+                               state_end(prev);
+                       }
+                       state_start(record);
+               }
+               coord(record);
+               prev = record;
+       }
+
+       public void write(AltosRecordIterable iterable) {
+               for (AltosRecord record : iterable)
+                       write(record);
+       }
+
+       public AltosKML(File in_name) throws FileNotFoundException {
+               name = in_name;
+               out = new PrintStream(name);
+       }
+
+       public AltosKML(String in_string) throws FileNotFoundException {
+               this(new File(in_string));
+       }
+}
diff --git a/altosui/AltosLanded.java b/altosui/AltosLanded.java
new file mode 100644 (file)
index 0000000..d34efe6
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * 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;
+
+public class AltosLanded extends JComponent implements AltosFlightDisplay {
+       GridBagLayout   layout;
+       Font            label_font;
+       Font            value_font;
+
+       public class LandedValue {
+               JLabel          label;
+               JTextField      value;
+               void show(AltosState state, int crc_errors) {}
+
+               void reset() {
+                       value.setText("");
+               }
+
+               void show(String format, double v) {
+                       value.setText(String.format(format, v));
+               }
+
+               public LandedValue (GridBagLayout layout, int y, String text) {
+                       GridBagConstraints      c = new GridBagConstraints();
+                       c.weighty = 1;
+
+                       label = new JLabel(text);
+                       label.setFont(label_font);
+                       label.setHorizontalAlignment(SwingConstants.LEFT);
+                       c.gridx = 0; c.gridy = y;
+                       c.insets = new Insets(10, 10, 10, 10);
+                       c.anchor = GridBagConstraints.WEST;
+                       c.weightx = 0;
+                       c.fill = GridBagConstraints.VERTICAL;
+                       layout.setConstraints(label, c);
+                       add(label);
+
+                       value = new JTextField(Altos.text_width);
+                       value.setFont(value_font);
+                       value.setHorizontalAlignment(SwingConstants.RIGHT);
+                       c.gridx = 1; c.gridy = y;
+                       c.anchor = GridBagConstraints.WEST;
+                       c.weightx = 1;
+                       c.fill = GridBagConstraints.BOTH;
+                       layout.setConstraints(value, c);
+                       add(value);
+               }
+       }
+
+       String pos(double p, String pos, String neg) {
+               String  h = pos;
+               if (p < 0) {
+                       h = neg;
+                       p = -p;
+               }
+               int deg = (int) Math.floor(p);
+               double min = (p - Math.floor(p)) * 60.0;
+               return String.format("%s %4d° %9.6f", h, deg, min);
+       }
+
+       class Lat extends LandedValue {
+               void show (AltosState state, int crc_errors) {
+                       if (state.gps != null)
+                               value.setText(pos(state.gps.lat,"N", "S"));
+                       else
+                               value.setText("???");
+               }
+               public Lat (GridBagLayout layout, int y) {
+                       super (layout, y, "Latitude");
+               }
+       }
+
+       Lat lat;
+
+       class Lon extends LandedValue {
+               void show (AltosState state, int crc_errors) {
+                       if (state.gps != null)
+                               value.setText(pos(state.gps.lon,"E", "W"));
+                       else
+                               value.setText("???");
+               }
+               public Lon (GridBagLayout layout, int y) {
+                       super (layout, y, "Longitude");
+               }
+       }
+
+       Lon lon;
+
+       class Bearing extends LandedValue {
+               void show (AltosState state, int crc_errors) {
+                       if (state.from_pad != null)
+                               show("%3.0f°", state.from_pad.bearing);
+                       else
+                               value.setText("???");
+               }
+               public Bearing (GridBagLayout layout, int y) {
+                       super (layout, y, "Bearing");
+               }
+       }
+
+       Bearing bearing;
+
+       class Distance extends LandedValue {
+               void show (AltosState state, int crc_errors) {
+                       if (state.from_pad != null)
+                               show("%6.0f m", state.from_pad.distance);
+                       else
+                               value.setText("???");
+               }
+               public Distance (GridBagLayout layout, int y) {
+                       super (layout, y, "Distance");
+               }
+       }
+
+       Distance distance;
+
+       class Height extends LandedValue {
+               void show (AltosState state, int crc_errors) {
+                       show("%6.0f m", state.max_height);
+               }
+               public Height (GridBagLayout layout, int y) {
+                       super (layout, y, "Maximum Height");
+               }
+       }
+
+       Height  height;
+
+       class Speed extends LandedValue {
+               void show (AltosState state, int crc_errors) {
+                       show("%6.0f m/s", state.max_speed);
+               }
+               public Speed (GridBagLayout layout, int y) {
+                       super (layout, y, "Maximum Speed");
+               }
+       }
+
+       Speed   speed;
+
+       class Accel extends LandedValue {
+               void show (AltosState state, int crc_errors) {
+                       show("%6.0f m/s²", state.max_acceleration);
+               }
+               public Accel (GridBagLayout layout, int y) {
+                       super (layout, y, "Maximum Acceleration");
+               }
+       }
+
+       Accel   accel;
+
+       public void reset() {
+               lat.reset();
+               lon.reset();
+               bearing.reset();
+               distance.reset();
+               height.reset();
+               speed.reset();
+               accel.reset();
+       }
+
+       public void show(AltosState state, int crc_errors) {
+               bearing.show(state, crc_errors);
+               distance.show(state, crc_errors);
+               lat.show(state, crc_errors);
+               lon.show(state, crc_errors);
+               height.show(state, crc_errors);
+               speed.show(state, crc_errors);
+               accel.show(state, crc_errors);
+       }
+
+       public AltosLanded() {
+               layout = new GridBagLayout();
+
+               label_font = new Font("Dialog", Font.PLAIN, 22);
+               value_font = new Font("Monospaced", Font.PLAIN, 22);
+               setLayout(layout);
+
+               /* Elements in descent display */
+               bearing = new Bearing(layout, 0);
+               distance = new Distance(layout, 1);
+               lat = new Lat(layout, 2);
+               lon = new Lon(layout, 3);
+               height = new Height(layout, 4);
+               speed = new Speed(layout, 5);
+               accel = new Accel(layout, 6);
+       }
+}
diff --git a/altosui/AltosLed.java b/altosui/AltosLed.java
new file mode 100644 (file)
index 0000000..e08e996
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * 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;
+
+public class AltosLed extends JLabel {
+       ImageIcon       on, off;
+
+       ImageIcon create_icon(String path) {
+               java.net.URL imgURL = AltosUI.class.getResource(path);
+               if (imgURL != null)
+                       return new ImageIcon(imgURL);
+               System.err.printf("Cannot find icon \"%s\"\n", path);
+               return null;
+       }
+
+       public void set(boolean set) {
+               if (set)
+                       setIcon(on);
+               else
+                       setIcon(off);
+       }
+
+       public AltosLed(String on_path, String off_path) {
+               on = create_icon(on_path);
+               off = create_icon(off_path);
+               setIcon(off);
+       }
+}
diff --git a/altosui/AltosLights.java b/altosui/AltosLights.java
new file mode 100644 (file)
index 0000000..2fa3841
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * 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;
+
+public class AltosLights extends JComponent {
+
+       GridBagLayout   gridbag;
+
+       AltosLed        red, green;
+
+       ImageIcon create_icon(String path, String description) {
+               java.net.URL imgURL = AltosUI.class.getResource(path);
+               if (imgURL != null)
+                       return new ImageIcon(imgURL, description);
+               System.err.printf("Cannot find icon \"%s\"\n", path);
+               return null;
+       }
+
+       public void set (boolean on) {
+               if (on) {
+                       red.set(false);
+                       green.set(true);
+               } else {
+                       red.set(true);
+                       green.set(false);
+               }
+       }
+
+       public AltosLights() {
+               GridBagConstraints c;
+               gridbag = new GridBagLayout();
+               setLayout(gridbag);
+
+               c = new GridBagConstraints();
+               red = new AltosLed("/redled.png", "/grayled.png");
+               c.gridx = 0; c.gridy = 0;
+               c.insets = new Insets (0, 5, 0, 5);
+               gridbag.setConstraints(red, c);
+               add(red);
+               red.set(true);
+               green = new AltosLed("/greenled.png", "/grayled.png");
+               c.gridx = 1; c.gridy = 0;
+               gridbag.setConstraints(green, c);
+               add(green);
+               green.set(false);
+       }
+}
diff --git a/altosui/AltosLine.java b/altosui/AltosLine.java
new file mode 100644 (file)
index 0000000..86e9d4c
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * 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;
+
+public class AltosLine {
+       public String   line;
+
+       public AltosLine() {
+               line = null;
+       }
+
+       public AltosLine(String s) {
+               line = s;
+       }
+}
\ No newline at end of file
diff --git a/altosui/AltosLog.java b/altosui/AltosLog.java
new file mode 100644 (file)
index 0000000..dd147d2
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * 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.io.*;
+import java.lang.*;
+import java.util.*;
+import java.text.ParseException;
+import java.util.concurrent.LinkedBlockingQueue;
+
+/*
+ * This creates a thread to capture telemetry data and write it to
+ * a log file
+ */
+class AltosLog implements Runnable {
+
+       LinkedBlockingQueue<AltosLine>  input_queue;
+       LinkedBlockingQueue<String>     pending_queue;
+       int                             serial;
+       int                             flight;
+       FileWriter                      log_file;
+       Thread                          log_thread;
+
+       private void close_log_file() {
+               if (log_file != null) {
+                       try {
+                               log_file.close();
+                       } catch (IOException io) {
+                       }
+                       log_file = null;
+               }
+       }
+
+       void close() {
+               close_log_file();
+               if (log_thread != null) {
+                       log_thread.interrupt();
+                       log_thread = null;
+               }
+       }
+
+       boolean open (AltosTelemetry telem) throws IOException {
+               AltosFile       a = new AltosFile(telem);
+
+               log_file = new FileWriter(a, true);
+               if (log_file != null) {
+                       while (!pending_queue.isEmpty()) {
+                               try {
+                                       String s = pending_queue.take();
+                                       log_file.write(s);
+                                       log_file.write('\n');
+                               } catch (InterruptedException ie) {
+                               }
+                       }
+                       log_file.flush();
+               }
+               return log_file != null;
+       }
+
+       public void run () {
+               try {
+                       for (;;) {
+                               AltosLine       line = input_queue.take();
+                               if (line.line == null)
+                                       continue;
+                               try {
+                                       AltosTelemetry  telem = new AltosTelemetry(line.line);
+                                       if (telem.serial != serial || telem.flight != flight || log_file == null) {
+                                               close_log_file();
+                                               serial = telem.serial;
+                                               flight = telem.flight;
+                                               open(telem);
+                                       }
+                               } catch (ParseException pe) {
+                               } catch (AltosCRCException ce) {
+                               }
+                               if (log_file != null) {
+                                       log_file.write(line.line);
+                                       log_file.write('\n');
+                                       log_file.flush();
+                               } else
+                                       pending_queue.put(line.line);
+                       }
+               } catch (InterruptedException ie) {
+               } catch (IOException ie) {
+               }
+               close();
+       }
+
+       public AltosLog (AltosSerial s) {
+               pending_queue = new LinkedBlockingQueue<String> ();
+               input_queue = new LinkedBlockingQueue<AltosLine> ();
+               s.add_monitor(input_queue);
+               serial = -1;
+               flight = -1;
+               log_file = null;
+               log_thread = new Thread(this);
+               log_thread.start();
+       }
+}
diff --git a/altosui/AltosPad.java b/altosui/AltosPad.java
new file mode 100644 (file)
index 0000000..6695434
--- /dev/null
@@ -0,0 +1,269 @@
+/*
+ * 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;
+
+public class AltosPad extends JComponent implements AltosFlightDisplay {
+       GridBagLayout   layout;
+
+       public class LaunchStatus {
+               JLabel          label;
+               JTextField      value;
+               AltosLights     lights;
+
+               void show(AltosState state, int crc_errors) {}
+               void reset() {
+                       value.setText("");
+                       lights.set(false);
+               }
+
+               public LaunchStatus (GridBagLayout layout, int y, String text) {
+                       GridBagConstraints      c = new GridBagConstraints();
+                       c.weighty = 1;
+
+                       lights = new AltosLights();
+                       c.gridx = 0; c.gridy = y;
+                       c.anchor = GridBagConstraints.CENTER;
+                       c.fill = GridBagConstraints.VERTICAL;
+                       c.weightx = 0;
+                       layout.setConstraints(lights, c);
+                       add(lights);
+
+                       label = new JLabel(text);
+                       label.setFont(Altos.label_font);
+                       label.setHorizontalAlignment(SwingConstants.LEFT);
+                       c.gridx = 1; c.gridy = y;
+                       c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
+                       c.anchor = GridBagConstraints.WEST;
+                       c.fill = GridBagConstraints.VERTICAL;
+                       c.weightx = 0;
+                       layout.setConstraints(label, c);
+                       add(label);
+
+                       value = new JTextField(Altos.text_width);
+                       value.setFont(Altos.value_font);
+                       value.setHorizontalAlignment(SwingConstants.RIGHT);
+                       c.gridx = 2; c.gridy = y;
+                       c.anchor = GridBagConstraints.WEST;
+                       c.fill = GridBagConstraints.BOTH;
+                       c.weightx = 1;
+                       layout.setConstraints(value, c);
+                       add(value);
+
+               }
+       }
+
+       public class LaunchValue {
+               JLabel          label;
+               JTextField      value;
+               void show(AltosState state, int crc_errors) {}
+
+               void reset() {
+                       value.setText("");
+               }
+               public LaunchValue (GridBagLayout layout, int y, String text) {
+                       GridBagConstraints      c = new GridBagConstraints();
+                       c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
+                       c.weighty = 1;
+
+                       label = new JLabel(text);
+                       label.setFont(Altos.label_font);
+                       label.setHorizontalAlignment(SwingConstants.LEFT);
+                       c.gridx = 1; c.gridy = y;
+                       c.anchor = GridBagConstraints.WEST;
+                       c.fill = GridBagConstraints.VERTICAL;
+                       c.weightx = 0;
+                       layout.setConstraints(label, c);
+                       add(label);
+
+                       value = new JTextField(Altos.text_width);
+                       value.setFont(Altos.value_font);
+                       value.setHorizontalAlignment(SwingConstants.RIGHT);
+                       c.gridx = 2; c.gridy = y;
+                       c.anchor = GridBagConstraints.EAST;
+                       c.fill = GridBagConstraints.BOTH;
+                       c.weightx = 1;
+                       layout.setConstraints(value, c);
+                       add(value);
+               }
+       }
+
+       class Battery extends LaunchStatus {
+               void show (AltosState state, int crc_errors) {
+                       value.setText(String.format("%4.2f V", state.battery));
+                       lights.set(state.battery > 3.7);
+               }
+               public Battery (GridBagLayout layout, int y) {
+                       super(layout, y, "Battery Voltage");
+               }
+       }
+
+       Battery battery;
+
+       class Apogee extends LaunchStatus {
+               void show (AltosState state, int crc_errors) {
+                       value.setText(String.format("%4.2f V", state.drogue_sense));
+                       lights.set(state.drogue_sense > 3.2);
+               }
+               public Apogee (GridBagLayout layout, int y) {
+                       super(layout, y, "Apogee Igniter Voltage");
+               }
+       }
+
+       Apogee apogee;
+
+       class Main extends LaunchStatus {
+               void show (AltosState state, int crc_errors) {
+                       value.setText(String.format("%4.2f V", state.main_sense));
+                       lights.set(state.main_sense > 3.2);
+               }
+               public Main (GridBagLayout layout, int y) {
+                       super(layout, y, "Main Igniter Voltage");
+               }
+       }
+
+       Main main;
+
+       class GPSLocked extends LaunchStatus {
+               void show (AltosState state, int crc_errors) {
+                       value.setText(String.format("%4d sats", state.gps.nsat));
+                       lights.set(state.gps.locked);
+               }
+               public GPSLocked (GridBagLayout layout, int y) {
+                       super (layout, y, "GPS Locked");
+               }
+       }
+
+       GPSLocked gps_locked;
+
+       class GPSReady extends LaunchStatus {
+               void show (AltosState state, int crc_errors) {
+                       if (state.gps_ready)
+                               value.setText("Ready");
+                       else
+                               value.setText(String.format("Waiting %d", state.gps_waiting));
+                       lights.set(state.gps_ready);
+               }
+               public GPSReady (GridBagLayout layout, int y) {
+                       super (layout, y, "GPS Ready");
+               }
+       }
+
+       GPSReady gps_ready;
+
+       String pos(double p, String pos, String neg) {
+               String  h = pos;
+               if (p < 0) {
+                       h = neg;
+                       p = -p;
+               }
+               int deg = (int) Math.floor(p);
+               double min = (p - Math.floor(p)) * 60.0;
+               return String.format("%s %4d° %9.6f", h, deg, min);
+       }
+
+       class PadLat extends LaunchValue {
+               void show (AltosState state, int crc_errors) {
+                       value.setText(pos(state.pad_lat,"N", "S"));
+               }
+               public PadLat (GridBagLayout layout, int y) {
+                       super (layout, y, "Pad Latitude");
+               }
+       }
+
+       PadLat pad_lat;
+
+       class PadLon extends LaunchValue {
+               void show (AltosState state, int crc_errors) {
+                       value.setText(pos(state.pad_lon,"E", "W"));
+               }
+               public PadLon (GridBagLayout layout, int y) {
+                       super (layout, y, "Pad Longitude");
+               }
+       }
+
+       PadLon pad_lon;
+
+       class PadAlt extends LaunchValue {
+               void show (AltosState state, int crc_errors) {
+                       value.setText(String.format("%4.0f m", state.pad_alt));
+               }
+               public PadAlt (GridBagLayout layout, int y) {
+                       super (layout, y, "Pad Altitude");
+               }
+       }
+
+       PadAlt pad_alt;
+
+       public void reset() {
+               battery.reset();
+               apogee.reset();
+               main.reset();
+               gps_locked.reset();
+               gps_ready.reset();
+               pad_lat.reset();
+               pad_lon.reset();
+               pad_alt.reset();
+       }
+
+       public void show(AltosState state, int crc_errors) {
+               battery.show(state, crc_errors);
+               apogee.show(state, crc_errors);
+               main.show(state, crc_errors);
+               gps_locked.show(state, crc_errors);
+               gps_ready.show(state, crc_errors);
+               pad_lat.show(state, crc_errors);
+               pad_lon.show(state, crc_errors);
+               pad_alt.show(state, crc_errors);
+       }
+
+       public AltosPad() {
+               layout = new GridBagLayout();
+
+               setLayout(layout);
+
+               /* Elements in pad display:
+                *
+                * Battery voltage
+                * Igniter continuity
+                * GPS lock status
+                * GPS ready status
+                * GPS location
+                * Pad altitude
+                * RSSI
+                */
+               battery = new Battery(layout, 0);
+               apogee = new Apogee(layout, 1);
+               main = new Main(layout, 2);
+               gps_locked = new GPSLocked(layout, 3);
+               gps_ready = new GPSReady(layout, 4);
+               pad_lat = new PadLat(layout, 5);
+               pad_lon = new PadLon(layout, 6);
+               pad_alt = new PadAlt(layout, 7);
+       }
+}
diff --git a/altosui/AltosParse.java b/altosui/AltosParse.java
new file mode 100644 (file)
index 0000000..fbfcaae
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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.text.*;
+import java.lang.*;
+
+public class AltosParse {
+       static boolean isdigit(char c) {
+               return '0' <= c && c <= '9';
+       }
+
+       static int parse_int(String v) throws ParseException {
+               try {
+                       return Altos.fromdec(v);
+               } catch (NumberFormatException e) {
+                       throw new ParseException("error parsing int " + v, 0);
+               }
+       }
+
+       static int parse_hex(String v) throws ParseException {
+               try {
+                       return Altos.fromhex(v);
+               } catch (NumberFormatException e) {
+                       throw new ParseException("error parsing hex " + v, 0);
+               }
+       }
+
+       static double parse_double(String v) throws ParseException {
+               try {
+                       return Double.parseDouble(v);
+               } catch (NumberFormatException e) {
+                       throw new ParseException("error parsing double " + v, 0);
+               }
+       }
+
+       static double parse_coord(String coord) throws ParseException {
+               String[]        dsf = coord.split("\\D+");
+
+               if (dsf.length != 3) {
+                       throw new ParseException("error parsing coord " + coord, 0);
+               }
+               int deg = parse_int(dsf[0]);
+               int min = parse_int(dsf[1]);
+               int frac = parse_int(dsf[2]);
+
+               double r = deg + (min + frac / 10000.0) / 60.0;
+               if (coord.endsWith("S") || coord.endsWith("W"))
+                       r = -r;
+               return r;
+       }
+
+       static String strip_suffix(String v, String suffix) {
+               if (v.endsWith(suffix))
+                       return v.substring(0, v.length() - suffix.length());
+               return v;
+       }
+
+       static void word(String v, String m) throws ParseException {
+               if (!v.equals(m)) {
+                       throw new ParseException("error matching '" + v + "' '" + m + "'", 0);
+               }
+       }
+}
diff --git a/altosui/AltosPreferences.java b/altosui/AltosPreferences.java
new file mode 100644 (file)
index 0000000..e2a3df3
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * 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.io.*;
+import java.util.*;
+import java.text.*;
+import java.util.prefs.*;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.awt.Component;
+import javax.swing.*;
+import javax.swing.filechooser.FileSystemView;
+
+class AltosPreferences {
+       static Preferences preferences;
+
+       /* logdir preference name */
+       final static String logdirPreference = "LOGDIR";
+
+       /* channel preference name */
+       final static String channelPreferenceFormat = "CHANNEL-%d";
+
+       /* voice preference name */
+       final static String voicePreference = "VOICE";
+
+       /* callsign preference name */
+       final static String callsignPreference = "CALLSIGN";
+
+       /* firmware directory preference name */
+       final static String firmwaredirPreference = "FIRMWARE";
+
+       /* Default logdir is ~/TeleMetrum */
+       final static String logdirName = "TeleMetrum";
+
+       /* UI Component to pop dialogs up */
+       static Component component;
+
+       /* Log directory */
+       static File logdir;
+
+       /* Channel (map serial to channel) */
+       static Hashtable<Integer, Integer> channels;
+
+       /* Voice preference */
+       static boolean voice;
+
+       /* Callsign preference */
+       static String callsign;
+
+       /* Firmware directory */
+       static File firmwaredir;
+
+       public static void init(Component ui) {
+               preferences = Preferences.userRoot().node("/org/altusmetrum/altosui");
+
+               component = ui;
+
+               /* Initialize logdir from preferences */
+               String logdir_string = preferences.get(logdirPreference, null);
+               if (logdir_string != null)
+                       logdir = new File(logdir_string);
+               else {
+                       /* Use the file system view default directory */
+                       logdir = new File(FileSystemView.getFileSystemView().getDefaultDirectory(), logdirName);
+                       if (!logdir.exists())
+                               logdir.mkdirs();
+               }
+
+               channels = new Hashtable<Integer,Integer>();
+
+               voice = preferences.getBoolean(voicePreference, true);
+
+               callsign = preferences.get(callsignPreference,"N0CALL");
+
+               String firmwaredir_string = preferences.get(firmwaredirPreference, null);
+               if (firmwaredir_string != null)
+                       firmwaredir = new File(firmwaredir_string);
+               else
+                       firmwaredir = null;
+       }
+
+       static void flush_preferences() {
+               try {
+                       preferences.flush();
+               } catch (BackingStoreException ee) {
+                       JOptionPane.showMessageDialog(component,
+                                                     preferences.absolutePath(),
+                                                     "Cannot save prefernces",
+                                                     JOptionPane.ERROR_MESSAGE);
+               }
+       }
+
+       public static void set_logdir(File new_logdir) {
+               logdir = new_logdir;
+               synchronized (preferences) {
+                       preferences.put(logdirPreference, logdir.getPath());
+                       flush_preferences();
+               }
+       }
+
+       private static boolean check_dir(File dir) {
+               if (!dir.exists()) {
+                       if (!dir.mkdirs()) {
+                               JOptionPane.showMessageDialog(component,
+                                                             dir.getName(),
+                                                             "Cannot create directory",
+                                                             JOptionPane.ERROR_MESSAGE);
+                               return false;
+                       }
+               } else if (!dir.isDirectory()) {
+                       JOptionPane.showMessageDialog(component,
+                                                     dir.getName(),
+                                                     "Is not a directory",
+                                                     JOptionPane.ERROR_MESSAGE);
+                       return false;
+               }
+               return true;
+       }
+
+       /* Configure the log directory. This is where all telemetry and eeprom files
+        * will be written to, and where replay will look for telemetry files
+        */
+       public static void ConfigureLog() {
+               JFileChooser    logdir_chooser = new JFileChooser(logdir.getParentFile());
+
+               logdir_chooser.setDialogTitle("Configure Data Logging Directory");
+               logdir_chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+
+               if (logdir_chooser.showDialog(component, "Select Directory") == JFileChooser.APPROVE_OPTION) {
+                       File dir = logdir_chooser.getSelectedFile();
+                       if (check_dir(dir))
+                               set_logdir(dir);
+               }
+       }
+
+       public static File logdir() {
+               return logdir;
+       }
+
+       public static void set_channel(int serial, int new_channel) {
+               channels.put(serial, new_channel);
+               synchronized (preferences) {
+                       preferences.putInt(String.format(channelPreferenceFormat, serial), new_channel);
+                       flush_preferences();
+               }
+       }
+
+       public static int channel(int serial) {
+               if (channels.containsKey(serial))
+                       return channels.get(serial);
+               int channel = preferences.getInt(String.format(channelPreferenceFormat, serial), 0);
+               channels.put(serial, channel);
+               return channel;
+       }
+
+       public static void set_voice(boolean new_voice) {
+               voice = new_voice;
+               synchronized (preferences) {
+                       preferences.putBoolean(voicePreference, voice);
+                       flush_preferences();
+               }
+       }
+
+       public static boolean voice() {
+               return voice;
+       }
+
+       public static void set_callsign(String new_callsign) {
+               callsign = new_callsign;
+               synchronized(preferences) {
+                       preferences.put(callsignPreference, callsign);
+                       flush_preferences();
+               }
+       }
+
+       public static String callsign() {
+               return callsign;
+       }
+
+       public static void set_firmwaredir(File new_firmwaredir) {
+               firmwaredir = new_firmwaredir;
+               synchronized (preferences) {
+                       preferences.put(firmwaredirPreference, firmwaredir.getPath());
+                       flush_preferences();
+               }
+       }
+
+       public static File firmwaredir() {
+               return firmwaredir;
+       }
+}
diff --git a/altosui/AltosReader.java b/altosui/AltosReader.java
new file mode 100644 (file)
index 0000000..b9280a0
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 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.io.*;
+import java.util.*;
+import java.text.*;
+
+public class AltosReader {
+       public AltosRecord read() throws IOException, ParseException { return null; }
+       public void close() { }
+       public void write_comments(PrintStream out) { }
+}
diff --git a/altosui/AltosRecord.java b/altosui/AltosRecord.java
new file mode 100644 (file)
index 0000000..1160a27
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * 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.lang.*;
+import java.text.*;
+import java.util.HashMap;
+import java.io.*;
+
+public class AltosRecord {
+       int     version;
+       String  callsign;
+       int     serial;
+       int     flight;
+       int     rssi;
+       int     status;
+       int     state;
+       int     tick;
+       int     accel;
+       int     pres;
+       int     temp;
+       int     batt;
+       int     drogue;
+       int     main;
+       int     flight_accel;
+       int     ground_accel;
+       int     flight_vel;
+       int     flight_pres;
+       int     ground_pres;
+       int     accel_plus_g;
+       int     accel_minus_g;
+       AltosGPS        gps;
+
+       double  time;   /* seconds since boost */
+
+       /*
+        * Values for our MP3H6115A pressure sensor
+        *
+        * From the data sheet:
+        *
+        * Pressure range: 15-115 kPa
+        * Voltage at 115kPa: 2.82
+        * Output scale: 27mV/kPa
+        *
+        *
+        * 27 mV/kPa * 2047 / 3300 counts/mV = 16.75 counts/kPa
+        * 2.82V * 2047 / 3.3 counts/V = 1749 counts/115 kPa
+        */
+
+       static final double counts_per_kPa = 27 * 2047 / 3300;
+       static final double counts_at_101_3kPa = 1674.0;
+
+       static double
+       barometer_to_pressure(double count)
+       {
+               return ((count / 16.0) / 2047.0 + 0.095) / 0.009 * 1000.0;
+       }
+
+       public double raw_pressure() {
+               return barometer_to_pressure(pres);
+       }
+
+       public double filtered_pressure() {
+               return barometer_to_pressure(flight_pres);
+       }
+
+       public double ground_pressure() {
+               return barometer_to_pressure(ground_pres);
+       }
+
+       public double filtered_altitude() {
+               return AltosConvert.pressure_to_altitude(filtered_pressure());
+       }
+
+       public double raw_altitude() {
+               return AltosConvert.pressure_to_altitude(raw_pressure());
+       }
+
+       public double ground_altitude() {
+               return AltosConvert.pressure_to_altitude(ground_pressure());
+       }
+
+       public double filtered_height() {
+               return filtered_altitude() - ground_altitude();
+       }
+
+       public double raw_height() {
+               return raw_altitude() - ground_altitude();
+       }
+
+       public double battery_voltage() {
+               return AltosConvert.cc_battery_to_voltage(batt);
+       }
+
+       public double main_voltage() {
+               return AltosConvert.cc_ignitor_to_voltage(main);
+       }
+
+       public double drogue_voltage() {
+               return AltosConvert.cc_ignitor_to_voltage(drogue);
+       }
+
+       /* Value for the CC1111 built-in temperature sensor
+        * Output voltage at 0°C = 0.755V
+        * Coefficient = 0.00247V/°C
+        * Reference voltage = 1.25V
+        *
+        * temp = ((value / 32767) * 1.25 - 0.755) / 0.00247
+        *      = (value - 19791.268) / 32768 * 1.25 / 0.00247
+        */
+
+       static double
+       thermometer_to_temperature(double thermo)
+       {
+               return (thermo - 19791.268) / 32728.0 * 1.25 / 0.00247;
+       }
+
+       public double temperature() {
+               return thermometer_to_temperature(temp);
+       }
+
+       double accel_counts_per_mss() {
+               double  counts_per_g = Math.abs(accel_minus_g - accel_plus_g) / 2;
+
+               return counts_per_g / 9.80665;
+       }
+       public double acceleration() {
+               return (ground_accel - accel) / accel_counts_per_mss();
+       }
+
+       public double accel_speed() {
+               double speed = flight_vel / (accel_counts_per_mss() * 100.0);
+               return speed;
+       }
+
+       public String state() {
+               return Altos.state_name(state);
+       }
+
+       public static String gets(FileInputStream s) throws IOException {
+               int c;
+               String  line = "";
+
+               while ((c = s.read()) != -1) {
+                       if (c == '\r')
+                               continue;
+                       if (c == '\n') {
+                               return line;
+                       }
+                       line = line + (char) c;
+               }
+               return null;
+       }
+
+       public AltosRecord(AltosRecord old) {
+               version = old.version;
+               callsign = old.callsign;
+               serial = old.serial;
+               flight = old.flight;
+               rssi = old.rssi;
+               status = old.status;
+               state = old.state;
+               tick = old.tick;
+               accel = old.accel;
+               pres = old.pres;
+               temp = old.temp;
+               batt = old.batt;
+               drogue = old.drogue;
+               main = old.main;
+               flight_accel = old.flight_accel;
+               ground_accel = old.ground_accel;
+               flight_vel = old.flight_vel;
+               flight_pres = old.flight_pres;
+               ground_pres = old.ground_pres;
+               accel_plus_g = old.accel_plus_g;
+               accel_minus_g = old.accel_minus_g;
+               gps = new AltosGPS(old.gps);
+       }
+
+       public AltosRecord() {
+               version = 0;
+               callsign = "N0CALL";
+               serial = 0;
+               flight = 0;
+               rssi = 0;
+               status = 0;
+               state = Altos.ao_flight_startup;
+               tick = 0;
+               accel = 0;
+               pres = 0;
+               temp = 0;
+               batt = 0;
+               drogue = 0;
+               main = 0;
+               flight_accel = 0;
+               ground_accel = 0;
+               flight_vel = 0;
+               flight_pres = 0;
+               ground_pres = 0;
+               accel_plus_g = 0;
+               accel_minus_g = 0;
+               gps = new AltosGPS();
+       }
+}
diff --git a/altosui/AltosRecordIterable.java b/altosui/AltosRecordIterable.java
new file mode 100644 (file)
index 0000000..a7df92d
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+public abstract class AltosRecordIterable implements Iterable<AltosRecord> {
+       public abstract Iterator<AltosRecord> iterator();
+       public void write_comments(PrintStream out) { }
+}
diff --git a/altosui/AltosReplayReader.java b/altosui/AltosReplayReader.java
new file mode 100644 (file)
index 0000000..4e5e1d9
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * 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;
+
+/*
+ * Open an existing telemetry file and replay it in realtime
+ */
+
+public class AltosReplayReader extends AltosFlightReader {
+       Iterator<AltosRecord>   iterator;
+
+       public AltosRecord read() {
+               if (iterator.hasNext())
+                       return iterator.next();
+               return null;
+       }
+
+       public void close (boolean interrupted) {
+       }
+
+       void update(AltosState state) throws InterruptedException {
+               /* Make it run in realtime after the rocket leaves the pad */
+               if (state.state > Altos.ao_flight_pad)
+                       Thread.sleep((int) (Math.min(state.time_change,10) * 1000));
+       }
+
+       public AltosReplayReader(Iterator<AltosRecord> in_iterator, String in_name) {
+               iterator = in_iterator;
+               name = in_name;
+       }
+}
diff --git a/altosui/AltosRomconfig.java b/altosui/AltosRomconfig.java
new file mode 100644 (file)
index 0000000..55056b5
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * 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.io.*;
+
+public class AltosRomconfig {
+       public boolean  valid;
+       public int      version;
+       public int      check;
+       public int      serial_number;
+       public int      radio_calibration;
+
+       static int get_int(byte[] bytes, int start, int len) {
+               int     v = 0;
+               int     o = 0;
+               while (len > 0) {
+                       v = v | ((((int) bytes[start]) & 0xff) << o);
+                       start++;
+                       len--;
+                       o += 8;
+               }
+               return v;
+       }
+
+       static void put_int(int value, byte[] bytes, int start, int len) {
+               while (len > 0) {
+                       bytes[start] = (byte) (value & 0xff);
+                       start++;
+                       len--;
+                       value >>= 8;
+               }
+       }
+
+       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;
+
+               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;
+               }
+               if (offset >= bytes.length || bytes[offset] == 0)
+                       return;
+               int len = ((((int) bytes[offset]) & 0xff) - 2) / 2;
+               String fmt = String.format("%%0%dd", len);
+
+               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);
+               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);
+                               valid = true;
+                               break;
+                       }
+               }
+       }
+
+       public AltosRomconfig(AltosHexfile hexfile) {
+               this(hexfile.data, 0xa0 - hexfile.address);
+       }
+
+       public void write(byte[] bytes, int offset) throws IOException {
+               if (!valid)
+                       throw new IOException("rom configuration invalid");
+
+               if (offset < 0 || bytes.length < offset + 10)
+                       throw new IOException("image cannot contain rom config");
+
+               AltosRomconfig existing = new AltosRomconfig(bytes, offset);
+               if (!existing.valid)
+                       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);
+                       break;
+               }
+       }
+
+       public void write (AltosHexfile hexfile) throws IOException {
+               write(hexfile.data, 0xa0 - hexfile.address);
+               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) {
+               valid = true;
+               version = 1;
+               check = (~version & 0xffff);
+               serial_number = in_serial_number;
+               radio_calibration = in_radio_calibration;
+       }
+
+       public boolean valid() {
+               return valid && serial_number != 0;
+       }
+
+       public AltosRomconfig() {
+               valid = false;
+       }
+}
diff --git a/altosui/AltosRomconfigUI.java b/altosui/AltosRomconfigUI.java
new file mode 100644 (file)
index 0000000..e1dc974
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * 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 javax.swing.event.*;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.util.prefs.*;
+
+public class AltosRomconfigUI
+       extends JDialog
+       implements ActionListener
+{
+       Container       pane;
+       Box             box;
+       JLabel          serial_label;
+       JLabel          radio_calibration_label;
+
+       JFrame          owner;
+       JTextField      serial_value;
+       JTextField      radio_calibration_value;
+
+       JButton         ok;
+       JButton         cancel;
+
+       /* Build the UI using a grid bag */
+       public AltosRomconfigUI(JFrame in_owner) {
+               super (in_owner, "Configure TeleMetrum Rom Values", true);
+
+               owner = in_owner;
+               GridBagConstraints c;
+
+               Insets il = new Insets(4,4,4,4);
+               Insets ir = new Insets(4,4,4,4);
+
+               pane = getContentPane();
+               pane.setLayout(new GridBagLayout());
+
+               /* Serial */
+               c = new GridBagConstraints();
+               c.gridx = 0; c.gridy = 0;
+               c.gridwidth = 3;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = il;
+               serial_label = new JLabel("Serial:");
+               pane.add(serial_label, c);
+
+               c = new GridBagConstraints();
+               c.gridx = 3; c.gridy = 0;
+               c.gridwidth = 3;
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.weightx = 1;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = ir;
+               serial_value = new JTextField("0");
+               pane.add(serial_value, c);
+
+               /* Radio calibration value */
+               c = new GridBagConstraints();
+               c.gridx = 0; c.gridy = 1;
+               c.gridwidth = 3;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = il;
+               c.ipady = 5;
+               radio_calibration_label = new JLabel("Radio Calibration:");
+               pane.add(radio_calibration_label, c);
+
+               c = new GridBagConstraints();
+               c.gridx = 3; c.gridy = 1;
+               c.gridwidth = 3;
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.weightx = 1;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = ir;
+               c.ipady = 5;
+               radio_calibration_value = new JTextField("1186611");
+               pane.add(radio_calibration_value, c);
+
+               /* Buttons */
+               c = new GridBagConstraints();
+               c.gridx = 0; c.gridy = 2;
+               c.gridwidth = 3;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.CENTER;
+               c.insets = il;
+               ok = new JButton("OK");
+               pane.add(ok, c);
+               ok.addActionListener(this);
+               ok.setActionCommand("ok");
+
+               c = new GridBagConstraints();
+               c.gridx = 3; c.gridy = 2;
+               c.gridwidth = 3;
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.CENTER;
+               c.insets = il;
+               cancel = new JButton("Cancel");
+               pane.add(cancel, c);
+               cancel.addActionListener(this);
+               cancel.setActionCommand("cancel");
+
+               pack();
+               setLocationRelativeTo(owner);
+       }
+
+       boolean selected;
+
+       /* Listen for events from our buttons */
+       public void actionPerformed(ActionEvent e) {
+               String  cmd = e.getActionCommand();
+
+               if (cmd.equals("ok")) {
+                       AltosRomconfig  romconfig = romconfig();
+                       if (romconfig == null || !romconfig.valid()) {
+                               JOptionPane.showMessageDialog(this,
+                                                             "Invalid serial number or radio calibration value",
+                                                             "Invalid rom configuration",
+                                                             JOptionPane.ERROR_MESSAGE);
+                               return;
+                       }
+                       selected = true;
+               }
+               setVisible(false);
+       }
+
+       int serial() {
+               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);
+               }
+       }
+
+       AltosRomconfig romconfig() {
+               try {
+                       return new AltosRomconfig(serial(), radio_calibration());
+               } catch (NumberFormatException ne) {
+                       return null;
+               }
+       }
+
+       public AltosRomconfig showDialog() {
+               setVisible(true);
+               if (selected)
+                       return romconfig();
+               return null;
+       }
+}
diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java
new file mode 100644 (file)
index 0000000..b19143e
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ * 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.
+ */
+
+/*
+ * Deal with TeleDongle on a serial port
+ */
+
+package altosui;
+
+import java.lang.*;
+import java.io.*;
+import java.util.concurrent.*;
+import java.util.*;
+
+import libaltosJNI.*;
+
+/*
+ * This class reads from the serial port and places each received
+ * line in a queue. Dealing with that queue is left up to other
+ * threads.
+ */
+
+public class AltosSerial implements Runnable {
+
+       static List<String> devices_opened = Collections.synchronizedList(new LinkedList<String>());
+
+       AltosDevice device;
+       SWIGTYPE_p_altos_file altos;
+       LinkedList<LinkedBlockingQueue<AltosLine>> monitors;
+       LinkedBlockingQueue<AltosLine> reply_queue;
+       Thread input_thread;
+       String line;
+       byte[] line_bytes;
+       int line_count;
+       boolean monitor_mode;
+
+       public void run () {
+               int c;
+
+               try {
+                       for (;;) {
+                               c = libaltos.altos_getchar(altos, 0);
+                               if (Thread.interrupted())
+                                       break;
+                               if (c == libaltosConstants.LIBALTOS_ERROR) {
+                                       for (int e = 0; e < monitors.size(); e++) {
+                                               LinkedBlockingQueue<AltosLine> q = monitors.get(e);
+                                               q.put(new AltosLine());
+                                       }
+                                       reply_queue.put (new AltosLine());
+                                       break;
+                               }
+                               if (c == libaltosConstants.LIBALTOS_TIMEOUT)
+                                       continue;
+                               if (c == '\r')
+                                       continue;
+                               synchronized(this) {
+                                       if (c == '\n') {
+                                               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") || line.startsWith("CRC")) {
+                                                               for (int e = 0; e < monitors.size(); e++) {
+                                                                       LinkedBlockingQueue<AltosLine> q = monitors.get(e);
+                                                                       q.put(new AltosLine (line));
+                                                               }
+                                                       } else {
+//                                                             System.out.printf("GOT: %s\n", line);
+                                                               reply_queue.put(new AltosLine (line));
+                                                       }
+                                                       line_count = 0;
+                                                       line = "";
+                                               }
+                                       } else {
+                                               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++;
+                                       }
+                               }
+                       }
+               } catch (InterruptedException e) {
+               }
+       }
+
+       public void flush_output() {
+               if (altos != null)
+                       libaltos.altos_flush(altos);
+       }
+
+       public void flush_input() {
+               flush_output();
+               boolean got_some;
+               do {
+                       try {
+                               Thread.sleep(100);
+                       } catch (InterruptedException ie) {
+                       }
+                       got_some = !reply_queue.isEmpty();
+                       synchronized(this) {
+                               if (!"VERSION".startsWith(line) &&
+                                   !line.startsWith("VERSION"))
+                                       line = "";
+                               reply_queue.clear();
+                       }
+               } while (got_some);
+       }
+
+       public String get_reply() throws InterruptedException {
+               flush_output();
+               AltosLine line = reply_queue.take();
+               return line.line;
+       }
+
+       public String get_reply(int timeout) throws InterruptedException {
+               flush_output();
+               AltosLine line = reply_queue.poll(timeout, TimeUnit.MILLISECONDS);
+               if (line == null)
+                       return null;
+               return line.line;
+       }
+
+       public void add_monitor(LinkedBlockingQueue<AltosLine> q) {
+               set_monitor(true);
+               monitors.add(q);
+       }
+
+       public void remove_monitor(LinkedBlockingQueue<AltosLine> q) {
+               monitors.remove(q);
+               if (monitors.isEmpty())
+                       set_monitor(false);
+       }
+
+       public void close() {
+               if (altos != null) {
+                       libaltos.altos_close(altos);
+               }
+               if (input_thread != null) {
+                       try {
+                               input_thread.interrupt();
+                               input_thread.join();
+                       } catch (InterruptedException e) {
+                       }
+                       input_thread = null;
+               }
+               if (altos != null) {
+                       libaltos.altos_free(altos);
+                       altos = null;
+               }
+               synchronized (devices_opened) {
+                       devices_opened.remove(device.getPath());
+               }
+       }
+
+       public void putc(char c) {
+               if (altos != null)
+                       libaltos.altos_putchar(altos, c);
+       }
+
+       public void print(String data) {
+//             System.out.printf("\"%s\" ", data);
+               for (int i = 0; i < data.length(); i++)
+                       putc(data.charAt(i));
+       }
+
+       public void printf(String format, Object ... arguments) {
+               print(String.format(format, arguments));
+       }
+
+       private void open() throws FileNotFoundException, AltosSerialInUseException {
+               synchronized (devices_opened) {
+                       if (devices_opened.contains(device.getPath()))
+                               throw new AltosSerialInUseException(device);
+                       devices_opened.add(device.getPath());
+               }
+               altos = libaltos.altos_open(device);
+               if (altos == null) {
+                       close();
+                       throw new FileNotFoundException(device.toShortString());
+               }
+               input_thread = new Thread(this);
+               input_thread.start();
+               print("~\nE 0\n");
+               set_monitor(false);
+               flush_output();
+       }
+
+       public void set_radio() {
+               set_channel(AltosPreferences.channel(device.getSerial()));
+               set_callsign(AltosPreferences.callsign());
+       }
+
+       public void set_channel(int channel) {
+               if (altos != null) {
+                       if (monitor_mode)
+                               printf("m 0\nc r %d\nm 1\n", channel);
+                       else
+                               printf("c r %d\n", channel);
+                       flush_output();
+               }
+       }
+
+       void set_monitor(boolean monitor) {
+               monitor_mode = monitor;
+               if (altos != null) {
+                       if (monitor)
+                               printf("m 1\n");
+                       else
+                               printf("m 0\n");
+                       flush_output();
+               }
+       }
+
+       public void set_callsign(String callsign) {
+               if (altos != null) {
+                       printf ("c c %s\n", callsign);
+                       flush_output();
+               }
+       }
+
+       public AltosSerial(AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException {
+               device = in_device;
+               line = "";
+               monitor_mode = false;
+               monitors = new LinkedList<LinkedBlockingQueue<AltosLine>> ();
+               reply_queue = new LinkedBlockingQueue<AltosLine> ();
+               open();
+       }
+}
diff --git a/altosui/AltosSerialInUseException.java b/altosui/AltosSerialInUseException.java
new file mode 100644 (file)
index 0000000..4b108c7
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 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 libaltosJNI.*;
+
+public class AltosSerialInUseException extends Exception {
+       public altos_device     device;
+
+       public AltosSerialInUseException (altos_device in_device) {
+               device = in_device;
+       }
+}
diff --git a/altosui/AltosSerialMonitor.java b/altosui/AltosSerialMonitor.java
new file mode 100644 (file)
index 0000000..ad0e929
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * 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;
+
+public interface AltosSerialMonitor {
+       void data(String data);
+}
diff --git a/altosui/AltosSiteMap.java b/altosui/AltosSiteMap.java
new file mode 100644 (file)
index 0000000..8097060
--- /dev/null
@@ -0,0 +1,388 @@
+/*
+ * Copyright © 2010 Anthony Towns <aj@erisian.com.au>
+ *
+ * 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.image.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.MouseInputAdapter;
+import javax.imageio.ImageIO;
+import javax.swing.table.*;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.util.prefs.*;
+import java.lang.Math;
+import java.awt.geom.Point2D;
+import java.awt.geom.Line2D;
+
+public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay {
+       // preferred vertical step in a tile in naut. miles
+       // will actually choose a step size between x and 2x, where this
+       // is 1.5x
+       static final double tile_size_nmi = 0.75;
+
+       static final int px_size = 512;
+
+       static final int MAX_TILE_DELTA = 100;
+
+       private static Point2D.Double translatePoint(Point2D.Double p,
+                       Point2D.Double d)
+       {
+               return new Point2D.Double(p.x + d.x, p.y + d.y);
+       }
+
+       static class LatLng {
+               public double lat, lng;
+               public LatLng(double lat, double lng) {
+                       this.lat = lat;
+                       this.lng = lng;
+               }
+       }
+
+       // based on google js
+       //  http://maps.gstatic.com/intl/en_us/mapfiles/api-3/2/10/main.js
+       // search for fromLatLngToPoint and fromPointToLatLng
+       private static Point2D.Double pt(LatLng latlng, int zoom) {
+               double scale_x = 256/360.0 * Math.pow(2, zoom);
+               double scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom);
+               return pt(latlng, scale_x, scale_y);
+       }
+
+       private static Point2D.Double pt(LatLng latlng,
+                                        double scale_x, double scale_y)
+       {
+               Point2D.Double res = new Point2D.Double();
+               double e;
+
+               res.x = latlng.lng * scale_x;
+
+               e = Math.sin(Math.toRadians(latlng.lat));
+               e = Math.max(e,-(1-1.0E-15));
+               e = Math.min(e,  1-1.0E-15 );
+
+               res.y = 0.5*Math.log((1+e)/(1-e))*-scale_y;
+               return res;
+       }
+
+       static private LatLng latlng(Point2D.Double pt,
+                                    double scale_x, double scale_y)
+       {
+               double lat, lng;
+               double rads;
+
+               lng = pt.x/scale_x;
+               rads = 2 * Math.atan(Math.exp(-pt.y/scale_y));
+               lat = Math.toDegrees(rads - Math.PI/2);
+
+               return new LatLng(lat,lng);
+       }
+
+       int zoom;
+       double scale_x, scale_y;
+
+       private Point2D.Double pt(double lat, double lng) {
+               return pt(new LatLng(lat, lng), scale_x, scale_y);
+       }
+
+       private LatLng latlng(double x, double y) {
+               return latlng(new Point2D.Double(x,y), scale_x, scale_y);
+       }
+       private LatLng latlng(Point2D.Double pt) {
+               return latlng(pt, scale_x, scale_y);
+       }
+
+       HashMap<Point,AltosSiteMapTile> mapTiles = new HashMap<Point,AltosSiteMapTile>();
+       Point2D.Double centre;
+
+       private Point2D.Double tileCoordOffset(Point p) {
+               return new Point2D.Double(centre.x - p.x*px_size,
+                                         centre.y - p.y * px_size);
+       }
+
+       private Point tileOffset(Point2D.Double p) {
+               return new Point((int)Math.floor((centre.x+p.x)/px_size),
+                                (int)Math.floor((centre.y+p.y)/px_size));
+       }
+
+       private Point2D.Double getBaseLocation(double lat, double lng) {
+               Point2D.Double locn, north_step;
+
+               zoom = 2;
+               // stupid loop structure to please Java's control flow analysis
+               do {
+                       zoom++;
+                       scale_x = 256/360.0 * Math.pow(2, zoom);
+                       scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom);
+                       locn = pt(lat, lng);
+                       north_step = pt(lat+tile_size_nmi*4/3/60.0, lng);
+                       if (locn.y - north_step.y > px_size)
+                               break;
+               } while (zoom < 22);
+               locn.x = -px_size * Math.floor(locn.x/px_size);
+               locn.y = -px_size * Math.floor(locn.y/px_size);
+               return locn;
+       }
+
+       public void reset() {
+               // nothing
+       }
+
+       private void bgLoadMap(final AltosSiteMapTile tile,
+                              final File pngfile, final String pngurl)
+       {
+               //System.out.printf("Loading/fetching map %s\n", pngfile);
+               Thread thread = new Thread() {
+                       public void run() {
+                               ImageIcon res;
+                               res = AltosSiteMapCache.fetchAndLoadMap(pngfile, pngurl);
+                               if (res != null) {
+                                       tile.loadMap(res);
+                               } else {
+                                       System.out.printf("# Failed to fetch file %s\n", pngfile);
+                                       System.out.printf(" wget -O '%s' ''\n", pngfile, pngurl);
+                               }
+                       }
+               };
+               thread.start();
+       }
+
+       public static void prefetchMaps(double lat, double lng, int w, int h) {
+               AltosPreferences.init(null);
+
+               AltosSiteMap asm = new AltosSiteMap(true);
+               asm.centre = asm.getBaseLocation(lat, lng);
+
+               Point2D.Double p = new Point2D.Double();
+               Point2D.Double p2;
+               int dx = -w/2, dy = -h/2;
+               for (int y = dy; y < h+dy; y++) {
+                       for (int x = dx; x < w+dx; x++) {
+                               LatLng map_latlng = asm.latlng(
+                                                           -asm.centre.x + x*px_size + px_size/2,
+                                                           -asm.centre.y + y*px_size + px_size/2);
+                               File pngfile = asm.MapFile(map_latlng.lat, map_latlng.lng);
+                               String pngurl = asm.MapURL(map_latlng.lat, map_latlng.lng);
+                               if (pngfile.exists()) {
+                                       System.out.printf("Already have %s\n", pngfile);
+                               } else if (AltosSiteMapCache.fetchMap(pngfile, pngurl)) {
+                                       System.out.printf("Fetched map %s\n", pngfile);
+                               } else {
+                                       System.out.printf("# Failed to fetch file %s\n", pngfile);
+                                       System.out.printf(" wget -O '%s' ''\n", pngfile, pngurl);
+                               }
+                       }
+               }
+       }
+
+       private void initMap(AltosSiteMapTile tile, Point offset) {
+               Point2D.Double coord = tileCoordOffset(offset);
+
+               LatLng map_latlng = latlng(px_size/2-coord.x, px_size/2-coord.y);
+
+               File pngfile = MapFile(map_latlng.lat, map_latlng.lng);
+               String pngurl = MapURL(map_latlng.lat, map_latlng.lng);
+               bgLoadMap(tile, pngfile, pngurl);
+       }
+
+       private void initMaps(double lat, double lng) {
+               centre = getBaseLocation(lat, lng);
+
+               for (Point k : mapTiles.keySet()) {
+                       initMap(mapTiles.get(k), k);
+               }
+       }
+
+       private File MapFile(double lat, double lng) {
+               char chlat = lat < 0 ? 'S' : 'N';
+               char chlng = lng < 0 ? 'E' : 'W';
+               if (lat < 0) lat = -lat;
+               if (lng < 0) lng = -lng;
+               return new File(AltosPreferences.logdir(),
+                               String.format("map-%c%.6f,%c%.6f-%d.png",
+                                             chlat, lat, chlng, lng, zoom));
+       }
+
+       private String MapURL(double lat, double lng) {
+               return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=hybrid&format=png32", lat, lng, zoom, px_size, px_size);
+       }
+
+       boolean initialised = false;
+       Point2D.Double last_pt = null;
+       int last_state = -1;
+       public void show(final AltosState state, final int crc_errors) {
+               // if insufficient gps data, nothing to update
+               if (state.gps == null)
+                       return;
+               if (state.pad_lat == 0 && state.pad_lon == 0)
+                       return;
+               if (!state.gps.locked) {
+                       if (state.gps.nsat < 4)
+                               return;
+               }
+
+               if (!initialised) {
+                       initMaps(state.pad_lat, state.pad_lon);
+                       initialised = true;
+               }
+
+               final Point2D.Double pt = pt(state.gps.lat, state.gps.lon);
+               if (last_pt == pt && last_state == state.state)
+                       return;
+
+               if (last_pt == null) {
+                       last_pt = pt;
+               }
+               boolean in_any = false;
+               for (Point offset : mapTiles.keySet()) {
+                       AltosSiteMapTile tile = mapTiles.get(offset);
+                       Point2D.Double ref, lref;
+                       ref = translatePoint(pt, tileCoordOffset(offset));
+                       lref = translatePoint(last_pt, tileCoordOffset(offset));
+                       tile.show(state, crc_errors, lref, ref);
+                       if (0 <= ref.x && ref.x < px_size)
+                               if (0 <= ref.y && ref.y < px_size)
+                                       in_any = true;
+               }
+
+               Point offset = tileOffset(pt);
+               if (!in_any) {
+                       Point2D.Double ref, lref;
+                       ref = translatePoint(pt, tileCoordOffset(offset));
+                       lref = translatePoint(last_pt, tileCoordOffset(offset));
+
+                       AltosSiteMapTile tile = createTile(offset);
+                       tile.show(state, crc_errors, lref, ref);
+                       initMap(tile, offset);
+                       finishTileLater(tile, offset);
+               }
+
+               scrollRocketToVisible(pt);
+
+               if (offset != tileOffset(last_pt)) {
+                       ensureTilesAround(offset);
+               }
+
+               last_pt = pt;
+               last_state = state.state;
+       }
+
+       private AltosSiteMapTile createTile(Point offset) {
+               AltosSiteMapTile tile = new AltosSiteMapTile(px_size);
+               mapTiles.put(offset, tile);
+               return tile;
+       }
+       private void finishTileLater(final AltosSiteMapTile tile,
+                                    final Point offset)
+       {
+               SwingUtilities.invokeLater( new Runnable() {
+                       public void run() {
+                               addTileAt(tile, offset);
+                       }
+               } );
+       }
+
+       private void ensureTilesAround(Point base_offset) {
+               for (int x = -1; x <= 1; x++) {
+                       for (int y = -1; y <= 1; y++) {
+                               Point offset = new Point(base_offset.x + x, base_offset.y + y);
+                               if (mapTiles.containsKey(offset))
+                                       continue;
+                               AltosSiteMapTile tile = createTile(offset);
+                               initMap(tile, offset);
+                               finishTileLater(tile, offset);
+                       }
+               }
+       }
+
+       private Point topleft = new Point(0,0);
+       private void scrollRocketToVisible(Point2D.Double pt) {
+               Rectangle r = comp.getVisibleRect();
+               Point2D.Double copt = translatePoint(pt, tileCoordOffset(topleft));
+               int dx = (int)copt.x - r.width/2 - r.x;
+               int dy = (int)copt.y - r.height/2 - r.y;
+               if (Math.abs(dx) > r.width/4 || Math.abs(dy) > r.height/4) {
+                       r.x += dx;
+                       r.y += dy;
+                       comp.scrollRectToVisible(r);
+               }
+       }
+
+       private void addTileAt(AltosSiteMapTile tile, Point offset) {
+               if (Math.abs(offset.x) >= MAX_TILE_DELTA ||
+                               Math.abs(offset.y) >= MAX_TILE_DELTA)
+               {
+                       System.out.printf("Rocket too far away from pad (tile %d,%d)\n",
+                                         offset.x, offset.y);
+                       return;
+               }
+
+               boolean review = false;
+               Rectangle r = comp.getVisibleRect();
+               if (offset.x < topleft.x) {
+                       r.x += (topleft.x - offset.x) * px_size;
+                       topleft.x = offset.x;
+                       review = true;
+               }
+               if (offset.y < topleft.y) {
+                       r.y += (topleft.y - offset.y) * px_size;
+                       topleft.y = offset.y;
+                       review = true;
+               }
+               GridBagConstraints c = new GridBagConstraints();
+               c.anchor = GridBagConstraints.CENTER;
+               c.fill = GridBagConstraints.BOTH;
+               // put some space between the map tiles, debugging only
+               // c.insets = new Insets(5, 5, 5, 5);
+
+               c.gridx = offset.x + MAX_TILE_DELTA;
+               c.gridy = offset.y + MAX_TILE_DELTA;
+               layout.setConstraints(tile, c);
+
+               comp.add(tile);
+               if (review) {
+                       comp.scrollRectToVisible(r);
+               }
+       }
+
+       private AltosSiteMap(boolean knowWhatYouAreDoing) {
+               if (!knowWhatYouAreDoing) {
+                       throw new RuntimeException("Arggh.");
+               }
+       }
+
+       JComponent comp = new JComponent() { };
+       private GridBagLayout layout = new GridBagLayout();
+
+       public AltosSiteMap() {
+               GrabNDrag scroller = new GrabNDrag(comp);
+
+               comp.setLayout(layout);
+
+               for (int x = -1; x <= 1; x++) {
+                       for (int y = -1; y <= 1; y++) {
+                               Point offset = new Point(x, y);
+                               AltosSiteMapTile t = createTile(offset);
+                               addTileAt(t, offset);
+                       }
+               }
+               setViewportView(comp);
+               setPreferredSize(new Dimension(500,200));
+       }
+}
diff --git a/altosui/AltosSiteMapCache.java b/altosui/AltosSiteMapCache.java
new file mode 100644 (file)
index 0000000..2e62cc4
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright © 2010 Anthony Towns <aj@erisian.com.au>
+ *
+ * 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.image.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.imageio.ImageIO;
+import javax.swing.table.*;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.util.prefs.*;
+import java.net.URL;
+import java.net.URLConnection;
+
+public class AltosSiteMapCache extends JLabel {
+       public static boolean fetchMap(File file, String url) {
+               URL u;
+
+               try {
+                       u = new URL(url);
+               } catch (java.net.MalformedURLException e) {
+                       return false;
+               }
+
+               byte[] data;
+               try {
+                       URLConnection uc = u.openConnection();
+                       int contentLength = uc.getContentLength();
+                       InputStream in = new BufferedInputStream(uc.getInputStream());
+                       int bytesRead = 0;
+                       int offset = 0;
+                       data = new byte[contentLength];
+                       while (offset < contentLength) {
+                               bytesRead = in.read(data, offset, data.length - offset);
+                               if (bytesRead == -1)
+                                       break;
+                               offset += bytesRead;
+                       }
+                       in.close();
+
+                       if (offset != contentLength) {
+                               return false;
+                       }
+               } catch (IOException e) {
+                       return false;
+               }
+
+               try {
+                       FileOutputStream out = new FileOutputStream(file);
+                       out.write(data);
+                       out.flush();
+                       out.close();
+               } catch (FileNotFoundException e) {
+                       return false;
+               } catch (IOException e) {
+                       if (file.exists()) {
+                               file.delete();
+                       }
+                       return false;
+               }
+               return true;
+       }
+
+       public static ImageIcon fetchAndLoadMap(File pngfile, String url) {
+               if (!pngfile.exists()) {
+                       if (!fetchMap(pngfile, url)) {
+                               return null;
+                       }
+               }
+               return loadMap(pngfile, url);
+       }
+
+       public static ImageIcon loadMap(File pngfile, String url) {
+               if (!pngfile.exists()) {
+                       return null;
+               }
+
+               try {
+                       return new ImageIcon(ImageIO.read(pngfile));
+               } catch (IOException e) {
+                       System.out.printf("# IO error trying to load %s\n", pngfile);
+                       return null;
+               }
+       }
+}
diff --git a/altosui/AltosSiteMapTile.java b/altosui/AltosSiteMapTile.java
new file mode 100644 (file)
index 0000000..8301f42
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright © 2010 Anthony Towns <aj@erisian.com.au>
+ *
+ * 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.image.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.imageio.ImageIO;
+import javax.swing.table.*;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.util.prefs.*;
+import java.lang.Math;
+import java.awt.geom.Point2D;
+import java.awt.geom.Line2D;
+
+public class AltosSiteMapTile extends JLayeredPane {
+       JLabel mapLabel;
+       JLabel draw;
+       Graphics2D g2d;
+
+       public void loadMap(ImageIcon icn) {
+               mapLabel.setIcon(icn);
+       }
+
+       static Color stateColors[] = {
+               Color.WHITE,  // startup
+               Color.WHITE,  // idle
+               Color.WHITE,  // pad
+               Color.RED,    // boost
+               Color.PINK,   // fast
+               Color.YELLOW, // coast
+               Color.CYAN,   // drogue
+               Color.BLUE,   // main
+               Color.BLACK   // landed
+       };
+
+       private boolean drawn_landed_circle = false;
+       private boolean drawn_boost_circle = false;
+       public synchronized void show(AltosState state, int crc_errors,
+                                     Point2D.Double last_pt, Point2D.Double pt)
+       {
+               if (0 <= state.state && state.state < stateColors.length) {
+                       g2d.setColor(stateColors[state.state]);
+               }
+               g2d.draw(new Line2D.Double(last_pt, pt));
+
+               if (state.state == 3 && !drawn_boost_circle) {
+                       drawn_boost_circle = true;
+                       g2d.setColor(Color.RED);
+                       g2d.drawOval((int)last_pt.x-5, (int)last_pt.y-5, 10, 10);
+                       g2d.drawOval((int)last_pt.x-20, (int)last_pt.y-20, 40, 40);
+                       g2d.drawOval((int)last_pt.x-35, (int)last_pt.y-35, 70, 70);
+               }
+               if (state.state == 8 && !drawn_landed_circle) {
+                       drawn_landed_circle = true;
+                       g2d.setColor(Color.BLACK);
+                       g2d.drawOval((int)pt.x-5, (int)pt.y-5, 10, 10);
+                       g2d.drawOval((int)pt.x-20, (int)pt.y-20, 40, 40);
+                       g2d.drawOval((int)pt.x-35, (int)pt.y-35, 70, 70);
+               }
+
+               repaint();
+       }
+
+       public static Graphics2D fillLabel(JLabel l, Color c, int px_size) {
+               BufferedImage img = new BufferedImage(px_size, px_size,
+                                                     BufferedImage.TYPE_INT_ARGB);
+               Graphics2D g = img.createGraphics();
+               g.setColor(c);
+               g.fillRect(0, 0, px_size, px_size);
+               l.setIcon(new ImageIcon(img));
+               return g;
+       }
+
+       public AltosSiteMapTile(int px_size) {
+               setPreferredSize(new Dimension(px_size, px_size));
+
+               mapLabel = new JLabel();
+               fillLabel(mapLabel, Color.GRAY, px_size);
+               mapLabel.setOpaque(true);
+               mapLabel.setBounds(0, 0, px_size, px_size);
+               add(mapLabel, new Integer(0));
+
+               draw = new JLabel();
+               g2d = fillLabel(draw, new Color(127, 127, 127, 0), px_size);
+               g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+                                    RenderingHints.VALUE_ANTIALIAS_ON);
+               g2d.setStroke(new BasicStroke(6, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
+               draw.setBounds(0, 0, px_size, px_size);
+               draw.setOpaque(false);
+
+               add(draw, new Integer(1));
+       }
+}
diff --git a/altosui/AltosState.java b/altosui/AltosState.java
new file mode 100644 (file)
index 0000000..ec499d5
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * 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.
+ */
+
+/*
+ * Track flight state from telemetry or eeprom data stream
+ */
+
+package altosui;
+
+public class AltosState {
+       AltosRecord data;
+
+       /* derived data */
+
+       long    report_time;
+
+       double  time_change;
+       int     tick;
+
+       int     state;
+       boolean landed;
+       boolean ascent; /* going up? */
+
+       double  ground_altitude;
+       double  height;
+       double  speed;
+       double  acceleration;
+       double  battery;
+       double  temperature;
+       double  main_sense;
+       double  drogue_sense;
+       double  baro_speed;
+
+       double  max_height;
+       double  max_acceleration;
+       double  max_speed;
+
+       AltosGPS        gps;
+
+       double  pad_lat;
+       double  pad_lon;
+       double  pad_alt;
+
+       static final int MIN_PAD_SAMPLES = 10;
+
+       int     npad;
+       int     ngps;
+       int     gps_waiting;
+       boolean gps_ready;
+
+       AltosGreatCircle from_pad;
+       double  elevation;      /* from pad */
+       double  range;          /* total distance */
+
+       double  gps_height;
+
+       int     speak_tick;
+       double  speak_altitude;
+
+
+       void init (AltosRecord cur, AltosState prev_state) {
+               int             i;
+               AltosRecord prev;
+
+               data = cur;
+
+               ground_altitude = data.ground_altitude();
+               height = data.filtered_altitude() - ground_altitude;
+
+               report_time = System.currentTimeMillis();
+
+               acceleration = data.acceleration();
+               speed = data.accel_speed();
+               temperature = data.temperature();
+               drogue_sense = data.drogue_voltage();
+               main_sense = data.main_voltage();
+               battery = data.battery_voltage();
+               tick = data.tick;
+               state = data.state;
+
+               if (prev_state != null) {
+
+                       /* Preserve any existing gps data */
+                       npad = prev_state.npad;
+                       ngps = prev_state.ngps;
+                       gps = prev_state.gps;
+                       pad_lat = prev_state.pad_lat;
+                       pad_lon = prev_state.pad_lon;
+                       pad_alt = prev_state.pad_alt;
+                       max_height = prev_state.max_height;
+                       max_acceleration = prev_state.max_acceleration;
+                       max_speed = prev_state.max_speed;
+
+                       /* make sure the clock is monotonic */
+                       while (tick < prev_state.tick)
+                               tick += 65536;
+
+                       time_change = (tick - prev_state.tick) / 100.0;
+
+                       /* compute barometric speed */
+
+                       double height_change = height - prev_state.height;
+                       if (time_change > 0)
+                               baro_speed = (prev_state.baro_speed * 3 + (height_change / time_change)) / 4.0;
+                       else
+                               baro_speed = prev_state.baro_speed;
+               } else {
+                       npad = 0;
+                       ngps = 0;
+                       gps = null;
+                       baro_speed = 0;
+                       time_change = 0;
+               }
+
+               if (state == Altos.ao_flight_pad) {
+
+                       /* Track consecutive 'good' gps reports, waiting for 10 of them */
+                       if (data.gps != null && data.gps.locked && data.gps.nsat >= 4)
+                               npad++;
+                       else
+                               npad = 0;
+
+                       /* Average GPS data while on the pad */
+                       if (data.gps != null && data.gps.locked && data.gps.nsat >= 4) {
+                               if (ngps > 1) {
+                                       /* filter pad position */
+                                       pad_lat = (pad_lat * 31.0 + data.gps.lat) / 32.0;
+                                       pad_lon = (pad_lon * 31.0 + data.gps.lon) / 32.0;
+                                       pad_alt = (pad_alt * 31.0 + data.gps.alt) / 32.0;
+                               } else {
+                                       pad_lat = data.gps.lat;
+                                       pad_lon = data.gps.lon;
+                                       pad_alt = data.gps.alt;
+                               }
+                               ngps++;
+                       }
+               }
+
+               gps_waiting = MIN_PAD_SAMPLES - npad;
+               if (gps_waiting < 0)
+                       gps_waiting = 0;
+
+               gps_ready = gps_waiting == 0;
+
+               ascent = (Altos.ao_flight_boost <= state &&
+                         state <= Altos.ao_flight_coast);
+
+               /* Only look at accelerometer data on the way up */
+               if (ascent && acceleration > max_acceleration)
+                       max_acceleration = acceleration;
+               if (ascent && speed > max_speed)
+                       max_speed = speed;
+
+               if (height > max_height)
+                       max_height = height;
+               if (data.gps != null) {
+                       if (gps == null || !gps.locked || data.gps.locked)
+                               gps = data.gps;
+                       if (ngps > 0 && gps.locked) {
+                               from_pad = new AltosGreatCircle(pad_lat, pad_lon, gps.lat, gps.lon);
+                       }
+               }
+               elevation = 0;
+               range = -1;
+               if (ngps > 0) {
+                       gps_height = gps.alt - pad_alt;
+                       if (from_pad != null) {
+                               elevation = Math.atan2(height, from_pad.distance) * 180 / Math.PI;
+                               range = Math.sqrt(height * height + from_pad.distance * from_pad.distance);
+                       }
+               } else {
+                       gps_height = 0;
+               }
+       }
+
+       public AltosState(AltosRecord cur) {
+               init(cur, null);
+       }
+
+       public AltosState (AltosRecord cur, AltosState prev) {
+               init(cur, prev);
+       }
+}
diff --git a/altosui/AltosTelemetry.java b/altosui/AltosTelemetry.java
new file mode 100644 (file)
index 0000000..bdb6466
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * 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.lang.*;
+import java.text.*;
+import java.util.HashMap;
+
+/*
+ * Telemetry data contents
+ */
+
+
+/*
+ * The telemetry data stream is a bit of a mess at present, with no consistent
+ * formatting. In particular, the GPS data is formatted for viewing instead of parsing.
+ * However, the key feature is that every telemetry line contains all of the information
+ * necessary to describe the current rocket state, including the calibration values
+ * for accelerometer and barometer.
+ *
+ * GPS unlocked:
+ *
+ * VERSION 2 CALL KB0G SERIAL  51 FLIGHT     2 RSSI  -68 STATUS ff STATE     pad  1001 \
+ *    a: 16032 p: 21232 t: 20284 v: 25160 d:   204 m:   204 fa: 16038 ga: 16032 fv:       0 \
+ *    fp: 21232 gp: 21230 a+: 16049 a-: 16304 GPS  0 sat unlocked SAT 1   15  30
+ *
+ * GPS locked:
+ *
+ * VERSION 2 CALL KB0G SERIAL  51 FLIGHT     2 RSSI  -71 STATUS ff STATE     pad  2504 \
+ *     a: 16028 p: 21220 t: 20360 v: 25004 d:   208 m:   200 fa: 16031 ga: 16032 fv:     330 \
+ *     fp: 21231 gp: 21230 a+: 16049 a-: 16304 \
+ *     GPS  9 sat 2010-02-13 17:16:51 35°20.0803'N 106°45.2235'W  1790m  \
+ *     0.00m/s(H) 0°     0.00m/s(V) 1.0(hdop)     0(herr)     0(verr) \
+ *     SAT 10   29  30  24  28   5  25  21  20  15  33   1  23  30  24  18  26  10  29   2  26
+ */
+
+public class AltosTelemetry extends AltosRecord {
+       public AltosTelemetry(String line) throws ParseException, AltosCRCException {
+               String[] words = line.split("\\s+");
+               int     i = 0;
+
+               if (words[i].equals("CRC") && words[i+1].equals("INVALID")) {
+                       i += 2;
+                       AltosParse.word(words[i++], "RSSI");
+                       rssi = AltosParse.parse_int(words[i++]);
+                       throw new AltosCRCException(rssi);
+               }
+               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++];
+
+               AltosParse.word (words[i++], "SERIAL");
+               serial = 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++]);
+
+               AltosParse.word(words[i++], "STATE");
+               state = Altos.state(words[i++]);
+
+               tick = AltosParse.parse_int(words[i++]);
+
+               AltosParse.word(words[i++], "a:");
+               accel = AltosParse.parse_int(words[i++]);
+
+               AltosParse.word(words[i++], "p:");
+               pres = AltosParse.parse_int(words[i++]);
+
+               AltosParse.word(words[i++], "t:");
+               temp = AltosParse.parse_int(words[i++]);
+
+               AltosParse.word(words[i++], "v:");
+               batt = AltosParse.parse_int(words[i++]);
+
+               AltosParse.word(words[i++], "d:");
+               drogue = AltosParse.parse_int(words[i++]);
+
+               AltosParse.word(words[i++], "m:");
+               main = AltosParse.parse_int(words[i++]);
+
+               AltosParse.word(words[i++], "fa:");
+               flight_accel = AltosParse.parse_int(words[i++]);
+
+               AltosParse.word(words[i++], "ga:");
+               ground_accel = AltosParse.parse_int(words[i++]);
+
+               AltosParse.word(words[i++], "fv:");
+               flight_vel = AltosParse.parse_int(words[i++]);
+
+               AltosParse.word(words[i++], "fp:");
+               flight_pres = AltosParse.parse_int(words[i++]);
+
+               AltosParse.word(words[i++], "gp:");
+               ground_pres = 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++]);
+               } else {
+                       accel_plus_g = ground_accel;
+                       accel_minus_g = ground_accel + 530;
+               }
+
+               gps = new AltosGPS(words, i, version);
+       }
+}
diff --git a/altosui/AltosTelemetryIterable.java b/altosui/AltosTelemetryIterable.java
new file mode 100644 (file)
index 0000000..a71ab87
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * 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.io.*;
+import java.util.*;
+import java.text.*;
+
+public class AltosTelemetryIterable extends AltosRecordIterable {
+       LinkedList<AltosRecord> records;
+
+       public Iterator<AltosRecord> iterator () {
+               return records.iterator();
+       }
+
+       public AltosTelemetryIterable (FileInputStream input) {
+               boolean saw_boost = false;
+               int     current_tick = 0;
+               int     boost_tick = 0;
+
+               records = new LinkedList<AltosRecord> ();
+
+               try {
+                       for (;;) {
+                               String line = AltosRecord.gets(input);
+                               if (line == null) {
+                                       break;
+                               }
+                               try {
+                                       AltosTelemetry record = new AltosTelemetry(line);
+                                       if (record == null)
+                                               break;
+                                       if (records.isEmpty()) {
+                                               current_tick = record.tick;
+                                       } else {
+                                               int tick = record.tick | (current_tick & ~ 0xffff);
+                                               if (tick < current_tick - 0x1000)
+                                                       tick += 0x10000;
+                                               current_tick = tick;
+                                               record.tick = current_tick;
+                                       }
+                                       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 (AltosCRCException ce) {
+                                       System.out.printf("crc error\n");
+                               }
+                       }
+               } catch (IOException io) {
+                       System.out.printf("io exception\n");
+               }
+
+               /* adjust all tick counts to be relative to boost time */
+               for (AltosRecord r : this)
+                       r.time = (r.tick - boost_tick) / 100.0;
+
+               try {
+                       input.close();
+               } catch (IOException ie) {
+               }
+       }
+}
diff --git a/altosui/AltosTelemetryReader.java b/altosui/AltosTelemetryReader.java
new file mode 100644 (file)
index 0000000..6c5a939
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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.lang.*;
+import java.text.*;
+import java.io.*;
+import java.util.concurrent.*;
+
+class AltosTelemetryReader extends AltosFlightReader {
+       AltosDevice     device;
+       AltosSerial     serial;
+       AltosLog        log;
+
+       LinkedBlockingQueue<AltosLine> telem;
+
+       AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException {
+               AltosLine l = telem.take();
+               if (l.line == null)
+                       throw new IOException("IO error");
+               return new AltosTelemetry(l.line);
+       }
+
+       void close(boolean interrupted) {
+               serial.remove_monitor(telem);
+               log.close();
+               serial.close();
+       }
+
+       void set_channel(int channel) {
+               serial.set_channel(channel);
+               AltosPreferences.set_channel(device.getSerial(), channel);
+       }
+
+       public AltosTelemetryReader (AltosDevice in_device)
+               throws FileNotFoundException, AltosSerialInUseException, IOException {
+               device = in_device;
+               serial = new AltosSerial(device);
+               log = new AltosLog(serial);
+               name = device.toShortString();
+
+               telem = new LinkedBlockingQueue<AltosLine>();
+               serial.set_radio();
+               serial.add_monitor(telem);
+       }
+}
diff --git a/altosui/AltosUI.app/Contents/Info.plist b/altosui/AltosUI.app/Contents/Info.plist
new file mode 100644 (file)
index 0000000..97b1b59
--- /dev/null
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.9">
+<dict>
+       <key>CFBundleName</key>
+       <string>altosui</string>
+       <key>CFBundleVersion</key>
+       <string>100.0</string>
+       <key>CFBundleAllowMixedLocalizations</key>
+       <string>true</string>
+       <key>CFBundleExecutable</key>
+       <string>JavaApplicationStub</string>
+       <key>CFBundleDevelopmentRegion</key>
+       <string>English</string>
+       <key>CFBundlePackageType</key>
+       <string>APPL</string>
+       <key>CFBundleSignature</key>
+       <string>????</string>
+       <key>CFBundleGetInfoString</key>
+       <string>AltOS UI version 0.7</string>
+       <key>CFBundleInfoDictionaryVersion</key>
+       <string>6.0</string>
+       <key>CFBundleIconFile</key>
+       <string>AltosUIIcon.icns</string>
+       <key>Java</key>
+       <dict>
+               <key>MainClass</key>
+               <string>altosui.AltosUI</string>
+               <key>JVMVersion</key>
+               <string>1.5+</string>
+               <key>ClassPath</key>
+                       <array>
+                       <string>$JAVAROOT/altosui.jar</string>
+                       <string>$JAVAROOT/freetts.jar</string>
+                       </array>
+       </dict>
+</dict>
+</plist>
diff --git a/altosui/AltosUI.app/Contents/MacOS/JavaApplicationStub b/altosui/AltosUI.app/Contents/MacOS/JavaApplicationStub
new file mode 100755 (executable)
index 0000000..c661d3e
Binary files /dev/null and b/altosui/AltosUI.app/Contents/MacOS/JavaApplicationStub differ
diff --git a/altosui/AltosUI.app/Contents/PkgInfo b/altosui/AltosUI.app/Contents/PkgInfo
new file mode 100644 (file)
index 0000000..8a43480
--- /dev/null
@@ -0,0 +1 @@
+APPLAM.O
diff --git a/altosui/AltosUI.app/Contents/Resources/AltosUIIcon.icns b/altosui/AltosUI.app/Contents/Resources/AltosUIIcon.icns
new file mode 100644 (file)
index 0000000..fe49f36
Binary files /dev/null and b/altosui/AltosUI.app/Contents/Resources/AltosUIIcon.icns differ
diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java
new file mode 100644 (file)
index 0000000..94c4dd2
--- /dev/null
@@ -0,0 +1,405 @@
+/*
+ * 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 libaltosJNI.*;
+
+public class AltosUI extends JFrame {
+       public AltosVoice voice = new AltosVoice();
+
+       public static boolean load_library(Frame frame) {
+               if (!AltosDevice.load_library()) {
+                       JOptionPane.showMessageDialog(frame,
+                                                     String.format("No AltOS library in \"%s\"",
+                                                                   System.getProperty("java.library.path","<undefined>")),
+                                                     "Cannot load device access library",
+                                                     JOptionPane.ERROR_MESSAGE);
+                       return false;
+               }
+               return true;
+       }
+
+       void telemetry_window(AltosDevice device) {
+               try {
+                       AltosFlightReader reader = new AltosTelemetryReader(device);
+                       if (reader != null)
+                               new AltosFlightUI(voice, reader, device.getSerial());
+               } catch (FileNotFoundException ee) {
+                       JOptionPane.showMessageDialog(AltosUI.this,
+                                                     String.format("Cannot open device \"%s\"",
+                                                                   device.toShortString()),
+                                                     "Cannot open target device",
+                                                     JOptionPane.ERROR_MESSAGE);
+               } catch (AltosSerialInUseException si) {
+                       JOptionPane.showMessageDialog(AltosUI.this,
+                                                     String.format("Device \"%s\" already in use",
+                                                                   device.toShortString()),
+                                                     "Device in use",
+                                                     JOptionPane.ERROR_MESSAGE);
+               } catch (IOException ee) {
+                       JOptionPane.showMessageDialog(AltosUI.this,
+                                                     device.toShortString(),
+                                                     "Unkonwn I/O error",
+                                                     JOptionPane.ERROR_MESSAGE);
+               }
+       }
+
+       Container       pane;
+       GridBagLayout   gridbag;
+
+       JButton addButton(int x, int y, String label) {
+               GridBagConstraints      c;
+               JButton                 b;
+
+               c = new GridBagConstraints();
+               c.gridx = x; c.gridy = y;
+               c.fill = GridBagConstraints.BOTH;
+               c.weightx = 1;
+               c.weighty = 1;
+               b = new JButton(label);
+
+               Dimension ps = b.getPreferredSize();
+
+               gridbag.setConstraints(b, c);
+               add(b, c);
+               return b;
+       }
+
+       public AltosUI() {
+
+               load_library(null);
+
+               java.net.URL imgURL = AltosUI.class.getResource("/altus-metrum-16x16.jpg");
+               if (imgURL != null)
+                       setIconImage(new ImageIcon(imgURL).getImage());
+
+               AltosPreferences.init(this);
+
+               pane = getContentPane();
+               gridbag = new GridBagLayout();
+               pane.setLayout(gridbag);
+
+               JButton b;
+
+               b = addButton(0, 0, "Monitor Flight");
+               b.addActionListener(new ActionListener() {
+                                       public void actionPerformed(ActionEvent e) {
+                                               ConnectToDevice();
+                                       }
+                               });
+               b = addButton(1, 0, "Save Flight Data");
+               b.addActionListener(new ActionListener() {
+                                       public void actionPerformed(ActionEvent e) {
+                                               SaveFlightData();
+                                       }
+                               });
+               b = addButton(2, 0, "Replay Flight");
+               b.addActionListener(new ActionListener() {
+                                       public void actionPerformed(ActionEvent e) {
+                                               Replay();
+                                       }
+                               });
+               b = addButton(3, 0, "Graph Data");
+               b.addActionListener(new ActionListener() {
+                                       public void actionPerformed(ActionEvent e) {
+                                               GraphData();
+                                       }
+                               });
+               b = addButton(4, 0, "Export Data");
+               b.addActionListener(new ActionListener() {
+                                       public void actionPerformed(ActionEvent e) {
+                                               ExportData();
+                                       }
+                               });
+               b = addButton(0, 1, "Configure TeleMetrum");
+               b.addActionListener(new ActionListener() {
+                                       public void actionPerformed(ActionEvent e) {
+                                               ConfigureTeleMetrum();
+                                       }
+                               });
+
+               b = addButton(1, 1, "Configure AltosUI");
+               b.addActionListener(new ActionListener() {
+                               public void actionPerformed(ActionEvent e) {
+                                       ConfigureAltosUI();
+                               }
+                       });
+
+               b = addButton(2, 1, "Flash Image");
+               b.addActionListener(new ActionListener() {
+                               public void actionPerformed(ActionEvent e) {
+                                       FlashImage();
+                               }
+                       });
+
+               b = addButton(3, 1, "Fire Igniter");
+               b.addActionListener(new ActionListener() {
+                               public void actionPerformed(ActionEvent e) {
+                                       FireIgniter();
+                               }
+                       });
+
+               b = addButton(4, 1, "Quit");
+               b.addActionListener(new ActionListener() {
+                               public void actionPerformed(ActionEvent e) {
+                                       System.exit(0);
+                               }
+                       });
+
+               setTitle("AltOS");
+
+               pane.doLayout();
+               pane.validate();
+
+               doLayout();
+               validate();
+
+               setVisible(true);
+
+               Insets i = getInsets();
+               Dimension ps = rootPane.getPreferredSize();
+               ps.width += i.left + i.right;
+               ps.height += i.top + i.bottom;
+               setPreferredSize(ps);
+               setSize(ps);
+               setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
+               addWindowListener(new WindowAdapter() {
+                       @Override
+                       public void windowClosing(WindowEvent e) {
+                               System.exit(0);
+                       }
+               });
+       }
+
+       private void ConnectToDevice() {
+               AltosDevice     device = AltosDeviceDialog.show(AltosUI.this,
+                                                               AltosDevice.product_basestation);
+
+               if (device != null)
+                       telemetry_window(device);
+       }
+
+       void ConfigureCallsign() {
+               String  result;
+               result = JOptionPane.showInputDialog(AltosUI.this,
+                                                    "Configure Callsign",
+                                                    AltosPreferences.callsign());
+               if (result != null)
+                       AltosPreferences.set_callsign(result);
+       }
+
+       void ConfigureTeleMetrum() {
+               new AltosConfig(AltosUI.this);
+       }
+
+       void FlashImage() {
+               new AltosFlashUI(AltosUI.this);
+       }
+
+       void FireIgniter() {
+               new AltosIgniteUI(AltosUI.this);
+       }
+
+       /*
+        * Replay a flight from telemetry data
+        */
+       private void Replay() {
+               AltosDataChooser chooser = new AltosDataChooser(
+                       AltosUI.this);
+
+               AltosRecordIterable iterable = chooser.runDialog();
+               if (iterable != null) {
+                       AltosFlightReader reader = new AltosReplayReader(iterable.iterator(),
+                                                                        chooser.filename());
+                       new AltosFlightUI(voice, reader);
+               }
+       }
+
+       /* Connect to TeleMetrum, either directly or through
+        * a TeleDongle over the packet link
+        */
+       private void SaveFlightData() {
+               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() {
+               AltosDataChooser chooser;
+               chooser = new AltosDataChooser(this);
+               AltosRecordIterable record_reader = chooser.runDialog();
+               if (record_reader == null)
+                       return;
+               new AltosCSVUI(AltosUI.this, record_reader, chooser.file());
+       }
+
+       /* Load a flight log CSV file and display a pretty graph.
+        */
+
+       private void GraphData() {
+               AltosDataChooser chooser;
+               chooser = new AltosDataChooser(this);
+               AltosRecordIterable record_reader = chooser.runDialog();
+               if (record_reader == null)
+                       return;
+               new AltosGraphUI(record_reader);
+       }
+
+       private void ConfigureAltosUI() {
+               new AltosConfigureUI(AltosUI.this, voice);
+       }
+
+       static AltosRecordIterable open_logfile(String filename) {
+               File file = new File (filename);
+               try {
+                       FileInputStream in;
+
+                       in = new FileInputStream(file);
+                       if (filename.endsWith("eeprom"))
+                               return new AltosEepromIterable(in);
+                       else
+                               return new AltosTelemetryIterable(in);
+               } catch (FileNotFoundException fe) {
+                       System.out.printf("Cannot open '%s'\n", filename);
+                       return null;
+               }
+       }
+
+       static AltosWriter 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 AltosWriter open_kml(String filename) {
+               File file = new File (filename);
+               try {
+                       return new AltosKML(file);
+               } catch (FileNotFoundException fe) {
+                       System.out.printf("Cannot open '%s'\n", filename);
+                       return null;
+               }
+       }
+
+       static final int process_csv = 1;
+       static final int process_kml = 2;
+
+       static void process_file(String input, int process) {
+               AltosRecordIterable iterable = open_logfile(input);
+               if (iterable == null)
+                       return;
+               if (process == 0)
+                       process = process_csv;
+               if ((process & process_csv) != 0) {
+                       String output = Altos.replace_extension(input,".csv");
+                       System.out.printf("Processing \"%s\" to \"%s\"\n", input, output);
+                       if (input.equals(output)) {
+                               System.out.printf("Not processing '%s'\n", input);
+                       } else {
+                               AltosWriter writer = open_csv(output);
+                               if (writer != null) {
+                                       writer.write(iterable);
+                                       writer.close();
+                               }
+                       }
+               }
+               if ((process & process_kml) != 0) {
+                       String output = Altos.replace_extension(input,".kml");
+                       System.out.printf("Processing \"%s\" to \"%s\"\n", input, output);
+                       if (input.equals(output)) {
+                               System.out.printf("Not processing '%s'\n", input);
+                       } else {
+                               AltosWriter writer = open_kml(output);
+                               if (writer == null)
+                                       return;
+                               writer.write(iterable);
+                               writer.close();
+                       }
+               }
+       }
+
+       public static void main(final String[] args) {
+               int     process = 0;
+               /* Handle batch-mode */
+        if (args.length == 1 && args[0].equals("--help")) {
+               System.out.printf("Usage: altosui [OPTION]... [FILE]...\n");
+               System.out.printf("  Options:\n");
+               System.out.printf("    --fetchmaps <lat> <lon>\tpre-fetch maps for site map view\n");
+               System.out.printf("    --replay <filename>\t\trelive the glory of past flights \n");
+               System.out.printf("    --csv\tgenerate comma separated output for spreadsheets, etc\n");
+               System.out.printf("    --kml\tgenerate KML output for use with Google Earth\n");
+        } else if (args.length == 3 && args[0].equals("--fetchmaps")) {
+            double lat = Double.parseDouble(args[1]);
+            double lon = Double.parseDouble(args[2]);
+            AltosSiteMap.prefetchMaps(lat, lon, 5, 5);
+        } else if (args.length == 2 && args[0].equals("--replay")) {
+                       String filename = args[1];
+                       FileInputStream in;
+                       try {
+                               in = new FileInputStream(filename);
+                       } catch (Exception e) {
+                               System.out.printf("Failed to open file '%s'\n", filename);
+                               return;
+                       }
+                       AltosRecordIterable recs;
+                       AltosReplayReader reader;
+                       if (filename.endsWith("eeprom")) {
+                               recs = new AltosEepromIterable(in);
+                       } else {
+                               recs = new AltosTelemetryIterable(in);
+                       }
+                       reader = new AltosReplayReader(recs.iterator(), filename);
+                       AltosFlightUI flight_ui = new AltosFlightUI(new AltosVoice(), reader);
+                       flight_ui.set_exit_on_close();
+                       return;
+               } else if (args.length > 0) {
+                       for (int i = 0; i < args.length; i++) {
+                               if (args[i].equals("--kml"))
+                                       process |= process_kml;
+                               else if (args[i].equals("--csv"))
+                                       process |= process_csv;
+                               else
+                                       process_file(args[i], process);
+                       }
+               } else {
+                       AltosUI altosui = new AltosUI();
+                       altosui.setVisible(true);
+
+                       AltosDevice[] devices = AltosDevice.list(AltosDevice.product_basestation);
+                       for (int i = 0; i < devices.length; i++)
+                               altosui.telemetry_window(devices[i]);
+               }
+       }
+}
diff --git a/altosui/AltosVoice.java b/altosui/AltosVoice.java
new file mode 100644 (file)
index 0000000..ac13ee1
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * 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 com.sun.speech.freetts.Voice;
+import com.sun.speech.freetts.VoiceManager;
+import com.sun.speech.freetts.audio.JavaClipAudioPlayer;
+import java.util.concurrent.LinkedBlockingQueue;
+
+public class AltosVoice implements Runnable {
+       VoiceManager                    voice_manager;
+       Voice                           voice;
+       LinkedBlockingQueue<String>     phrases;
+       Thread                          thread;
+       boolean                         busy;
+
+       final static String voice_name = "kevin16";
+
+       public void run() {
+               try {
+                       for (;;) {
+                               String s = phrases.take();
+                               voice.speak(s);
+                               synchronized(this) {
+                                       if (phrases.isEmpty()) {
+                                               busy = false;
+                                               notifyAll();
+                                       }
+                               }
+                       }
+               } catch (InterruptedException e) {
+               }
+       }
+
+       public synchronized void drain() throws InterruptedException {
+               while (busy)
+                       wait();
+       }
+
+       public void speak_always(String s) {
+               try {
+                       if (voice != null) {
+                               synchronized(this) {
+                                       busy = true;
+                                       phrases.put(s);
+                               }
+                       }
+               } catch (InterruptedException e) {
+               }
+       }
+
+       public void speak(String s) {
+               if (AltosPreferences.voice())
+                       speak_always(s);
+       }
+
+       public void speak(String format, Object... parameters) {
+               speak(String.format(format, parameters));
+       }
+
+       public AltosVoice () {
+               busy = false;
+               voice_manager = VoiceManager.getInstance();
+               voice = voice_manager.getVoice(voice_name);
+               if (voice != null) {
+                       voice.allocate();
+                       phrases = new LinkedBlockingQueue<String> ();
+                       thread = new Thread(this);
+                       thread.start();
+               } else {
+                       System.out.printf("Voice manager failed to open %s\n", voice_name);
+                       Voice[] voices = voice_manager.getVoices();
+                       System.out.printf("Available voices:\n");
+                       for (int i = 0; i < voices.length; i++) {
+                               System.out.println("    " + voices[i].getName()
+                                                  + " (" + voices[i].getDomain() + " domain)");
+                       }
+               }
+       }
+}
diff --git a/altosui/AltosWriter.java b/altosui/AltosWriter.java
new file mode 100644 (file)
index 0000000..a172dff
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * 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.lang.*;
+import java.io.*;
+import java.text.*;
+import java.util.*;
+
+public interface AltosWriter {
+
+       public void write(AltosRecord record);
+
+       public void write(AltosRecordIterable iterable);
+
+       public void close();
+}
diff --git a/altosui/GrabNDrag.java b/altosui/GrabNDrag.java
new file mode 100644 (file)
index 0000000..e6b87b5
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright © 2010 Anthony Towns <aj@erisian.com.au>
+ *
+ * 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.image.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.MouseInputAdapter;
+import javax.imageio.ImageIO;
+import javax.swing.table.*;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
+class GrabNDrag extends MouseInputAdapter {
+       private JComponent scroll;
+       private Point startPt = new Point();
+
+       public GrabNDrag(JComponent scroll) {
+               this.scroll = scroll;
+               scroll.addMouseMotionListener(this);
+               scroll.addMouseListener(this);
+               scroll.setAutoscrolls(true);
+       }
+
+       public void mousePressed(MouseEvent e) {
+               startPt.setLocation(e.getPoint());
+       }
+       public void mouseDragged(MouseEvent e) {
+               int xd = e.getX() - startPt.x;
+               int yd = e.getY() - startPt.y;
+
+               Rectangle r = scroll.getVisibleRect();
+               r.x -= xd;
+               r.y -= yd;
+               scroll.scrollRectToVisible(r);
+       }
+}
diff --git a/altosui/Instdrv/NSIS/Contrib/InstDrv/Example.nsi b/altosui/Instdrv/NSIS/Contrib/InstDrv/Example.nsi
new file mode 100644 (file)
index 0000000..3ed821e
--- /dev/null
@@ -0,0 +1,84 @@
+#\r
+# InstDrv Example, (c) 2003 Jan Kiszka (Jan Kiszka@web.de)\r
+#\r
+\r
+Name "InstDrv.dll test"\r
+\r
+OutFile "InstDrv-Test.exe"\r
+\r
+ShowInstDetails show\r
+\r
+ComponentText "InstDrv Plugin Usage Example"\r
+\r
+Page components\r
+Page instfiles\r
+\r
+Section "Install a Driver" InstDriver\r
+    InstDrv::InitDriverSetup /NOUNLOAD "{4d36e978-e325-11ce-bfc1-08002be10318}" "IrCOMM2k"\r
+    Pop $0\r
+    DetailPrint "InitDriverSetup: $0"\r
+\r
+    InstDrv::DeleteOemInfFiles /NOUNLOAD\r
+    Pop $0\r
+    DetailPrint "DeleteOemInfFiles: $0"\r
+    StrCmp $0 "00000000" PrintInfNames ContInst1\r
+\r
+  PrintInfNames:\r
+    Pop $0\r
+    DetailPrint "Deleted $0"\r
+    Pop $0\r
+    DetailPrint "Deleted $0"\r
+\r
+  ContInst1:\r
+    InstDrv::CreateDevice /NOUNLOAD\r
+    Pop $0\r
+    DetailPrint "CreateDevice: $0"\r
+\r
+    SetOutPath $TEMP\r
+    File "ircomm2k.inf"\r
+    File "ircomm2k.sys"\r
+\r
+    InstDrv::InstallDriver /NOUNLOAD "$TEMP\ircomm2k.inf"\r
+    Pop $0\r
+    DetailPrint "InstallDriver: $0"\r
+    StrCmp $0 "00000000" PrintReboot ContInst2\r
+\r
+  PrintReboot:\r
+    Pop $0\r
+    DetailPrint "Reboot: $0"\r
+\r
+  ContInst2:\r
+    InstDrv::CountDevices\r
+    Pop $0\r
+    DetailPrint "CountDevices: $0"\r
+SectionEnd\r
+\r
+Section "Uninstall the driver again" UninstDriver\r
+    InstDrv::InitDriverSetup /NOUNLOAD "{4d36e978-e325-11ce-bfc1-08002be10318}" "IrCOMM2k"\r
+    Pop $0\r
+    DetailPrint "InitDriverSetup: $0"\r
+\r
+    InstDrv::DeleteOemInfFiles /NOUNLOAD\r
+    Pop $0\r
+    DetailPrint "DeleteOemInfFiles: $0"\r
+    StrCmp $0 "00000000" PrintInfNames ContUninst1\r
+\r
+  PrintInfNames:\r
+    Pop $0\r
+    DetailPrint "Deleted $0"\r
+    Pop $0\r
+    DetailPrint "Deleted $0"\r
+\r
+  ContUninst1:\r
+    InstDrv::RemoveAllDevices\r
+    Pop $0\r
+    DetailPrint "RemoveAllDevices: $0"\r
+    StrCmp $0 "00000000" PrintReboot ContUninst2\r
+\r
+  PrintReboot:\r
+    Pop $0\r
+    DetailPrint "Reboot: $0"\r
+\r
+  ContUninst2:\r
+    Delete "$SYSDIR\system32\ircomm2k.sys"\r
+SectionEnd
\ No newline at end of file
diff --git a/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv-Test.exe b/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv-Test.exe
new file mode 100644 (file)
index 0000000..615bae1
Binary files /dev/null and b/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv-Test.exe differ
diff --git a/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.c b/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.c
new file mode 100644 (file)
index 0000000..efe866e
--- /dev/null
@@ -0,0 +1,704 @@
+/*\r
+\r
+InstDrv.dll - Installs or Removes Device Drivers\r
+\r
+Copyright © 2003 Jan Kiszka (Jan.Kiszka@web.de)\r
+\r
+This software is provided 'as-is', without any express or implied\r
+warranty. In no event will the authors be held liable for any damages\r
+arising from the use of this software.\r
+\r
+Permission is granted to anyone to use this software for any purpose,\r
+including commercial applications, and to alter it and redistribute\r
+it freely, subject to the following restrictions:\r
+\r
+1. The origin of this software must not be misrepresented; \r
+   you must not claim that you wrote the original software.\r
+   If you use this software in a product, an acknowledgment in the\r
+   product documentation would be appreciated but is not required.\r
+2. Altered versions must be plainly marked as such,\r
+   and must not be misrepresented as being the original software.\r
+3. This notice may not be removed or altered from any distribution.\r
+\r
+*/\r
+\r
+\r
+#include <windows.h>\r
+#include <setupapi.h>\r
+#include <newdev.h>\r
+#include "../exdll/exdll.h"\r
+\r
+\r
+char    paramBuf[1024];\r
+GUID    devClass;\r
+char    hwIdBuf[1024];\r
+int     initialized = 0;\r
+\r
+\r
+\r
+void* memset(void* dst, int val, unsigned int len)\r
+{\r
+    while (len-- > 0)\r
+        *((char *)dst)++ = val;\r
+\r
+    return NULL;\r
+}\r
+\r
+\r
+\r
+void* memcpy(void* dst, const void* src, unsigned int len)\r
+{\r
+    while (len-- > 0)\r
+        *((char *)dst)++ = *((char *)src)++;\r
+\r
+    return NULL;\r
+}\r
+\r
+\r
+\r
+int HexCharToInt(char c)\r
+{\r
+    if ((c >= '0') && (c <= '9'))\r
+        return c - '0';\r
+    else if ((c >= 'a') && (c <= 'f'))\r
+        return c - 'a' + 10;\r
+    else if ((c >= 'A') && (c <= 'F'))\r
+        return c - 'A' + 10;\r
+    else\r
+        return -1;\r
+}\r
+\r
+\r
+\r
+BOOLEAN HexStringToUInt(char* str, int width, void* valBuf)\r
+{\r
+    int i, val;\r
+\r
+\r
+    for (i = width - 4; i >= 0; i -= 4)\r
+    {\r
+        val = HexCharToInt(*str++);\r
+        if (val < 0)\r
+            return FALSE;\r
+        *(unsigned int *)valBuf += val << i;\r
+    }\r
+\r
+    return TRUE;\r
+}\r
+\r
+\r
+\r
+BOOLEAN StringToGUID(char* guidStr, GUID* pGuid)\r
+{\r
+    int i;\r
+\r
+\r
+    memset(pGuid, 0, sizeof(GUID));\r
+\r
+    if (*guidStr++ != '{')\r
+        return FALSE;\r
+\r
+    if (!HexStringToUInt(guidStr, 32, &pGuid->Data1))\r
+        return FALSE;\r
+    guidStr += 8;\r
+\r
+    if (*guidStr++ != '-')\r
+        return FALSE;\r
+\r
+    if (!HexStringToUInt(guidStr, 16, &pGuid->Data2))\r
+        return FALSE;\r
+    guidStr += 4;\r
+\r
+    if (*guidStr++ != '-')\r
+        return FALSE;\r
+\r
+    if (!HexStringToUInt(guidStr, 16, &pGuid->Data3))\r
+        return FALSE;\r
+    guidStr += 4;\r
+\r
+    if (*guidStr++ != '-')\r
+        return FALSE;\r
+\r
+    for (i = 0; i < 2; i++)\r
+    {\r
+        if (!HexStringToUInt(guidStr, 8, &pGuid->Data4[i]))\r
+            return FALSE;\r
+        guidStr += 2;\r
+    }\r
+\r
+    if (*guidStr++ != '-')\r
+        return FALSE;\r
+\r
+    for (i = 2; i < 8; i++)\r
+    {\r
+        if (!HexStringToUInt(guidStr, 8, &pGuid->Data4[i]))\r
+            return FALSE;\r
+        guidStr += 2;\r
+    }\r
+\r
+    if (*guidStr++ != '}')\r
+        return FALSE;\r
+\r
+    return TRUE;\r
+}\r
+\r
+\r
+\r
+DWORD FindNextDevice(HDEVINFO devInfoSet, SP_DEVINFO_DATA* pDevInfoData, DWORD* pIndex)\r
+{\r
+    DWORD   buffersize = 0;\r
+    LPTSTR  buffer     = NULL;\r
+    DWORD   dataType;\r
+    DWORD   result;\r
+\r
+\r
+    while (1)\r
+    {\r
+        if (!SetupDiEnumDeviceInfo(devInfoSet, (*pIndex)++, pDevInfoData))\r
+        {\r
+            result = GetLastError();\r
+            break;\r
+        }\r
+\r
+      GetDeviceRegistryProperty:\r
+        if (!SetupDiGetDeviceRegistryProperty(devInfoSet, pDevInfoData, SPDRP_HARDWAREID,\r
+                                              &dataType, (PBYTE)buffer, buffersize,\r
+                                              &buffersize))\r
+        {\r
+            result = GetLastError();\r
+\r
+            if (result == ERROR_INSUFFICIENT_BUFFER)\r
+            {\r
+                if (buffer != NULL)\r
+                    LocalFree(buffer);\r
+\r
+                buffer = (LPTSTR)LocalAlloc(LPTR, buffersize);\r
+\r
+                if (buffer == NULL)\r
+                    break;\r
+\r
+                goto GetDeviceRegistryProperty;\r
+            }\r
+            else if (result == ERROR_INVALID_DATA)\r
+                continue;   // ignore invalid entries\r
+            else\r
+                break;      // break on other errors\r
+        }\r
+\r
+        if (lstrcmpi(buffer, hwIdBuf) == 0)\r
+        {\r
+            result  = 0;\r
+            break;\r
+        }\r
+    }\r
+\r
+    if (buffer != NULL)\r
+        LocalFree(buffer);\r
+\r
+    return result;\r
+}\r
+\r
+\r
+\r
+DWORD FindFirstDevice(HWND hwndParent, const GUID* pDevClass, const LPTSTR hwId,\r
+                      HDEVINFO* pDevInfoSet, SP_DEVINFO_DATA* pDevInfoData,\r
+                      DWORD *pIndex, DWORD flags)\r
+{\r
+    DWORD   result;\r
+\r
+\r
+    *pDevInfoSet = SetupDiGetClassDevs((GUID*)pDevClass, NULL, hwndParent, flags);\r
+    if (*pDevInfoSet == INVALID_HANDLE_VALUE)\r
+        return GetLastError();\r
+\r
+    pDevInfoData->cbSize = sizeof(SP_DEVINFO_DATA);\r
+    *pIndex = 0;\r
+\r
+    result = FindNextDevice(*pDevInfoSet, pDevInfoData, pIndex);\r
+\r
+    if (result != 0)\r
+        SetupDiDestroyDeviceInfoList(*pDevInfoSet);\r
+\r
+    return result;\r
+}\r
+\r
+\r
+\r
+/*\r
+ * InstDrv::InitDriverSetup devClass drvHWID\r
+ *\r
+ *  devClass    - GUID of the driver's device setup class\r
+ *  drvHWID     - Hardware ID of the supported device\r
+ *\r
+ * Return:\r
+ *  result      - error message, empty on success\r
+ */\r
+void __declspec(dllexport) InitDriverSetup(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)\r
+{\r
+    EXDLL_INIT();\r
+\r
+    /* convert class GUID */\r
+    popstring(paramBuf);\r
+\r
+    if (!StringToGUID(paramBuf, &devClass))\r
+    {\r
+        popstring(paramBuf);\r
+        pushstring("Invalid GUID!");\r
+        return;\r
+    }\r
+\r
+    /* get hardware ID */\r
+    memset(hwIdBuf, 0, sizeof(hwIdBuf));\r
+    popstring(hwIdBuf);\r
+\r
+    initialized = 1;\r
+    pushstring("");\r
+}\r
+\r
+\r
+\r
+/*\r
+ * InstDrv::CountDevices\r
+ *\r
+ * Return:\r
+ *  result      - Number of installed devices the driver supports\r
+ */\r
+void __declspec(dllexport) CountDevices(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)\r
+{\r
+    HDEVINFO            devInfoSet;\r
+    SP_DEVINFO_DATA     devInfoData;\r
+    int                 count = 0;\r
+    char                countBuf[16];\r
+    DWORD               index;\r
+    DWORD               result;\r
+\r
+\r
+    EXDLL_INIT();\r
+\r
+    if (!initialized)\r
+    {\r
+        pushstring("Fatal error!");\r
+        return;\r
+    }\r
+\r
+    result = FindFirstDevice(hwndParent, &devClass, hwIdBuf, &devInfoSet, &devInfoData,\r
+                             &index, DIGCF_PRESENT);\r
+    if (result != 0)\r
+    {\r
+        pushstring("0");\r
+        return;\r
+    }\r
+\r
+    do\r
+    {\r
+        count++;\r
+    } while (FindNextDevice(devInfoSet, &devInfoData, &index) == 0);\r
+\r
+    SetupDiDestroyDeviceInfoList(devInfoSet);\r
+\r
+    wsprintf(countBuf, "%d", count);\r
+    pushstring(countBuf);\r
+}\r
+\r
+\r
+\r
+/*\r
+ * InstDrv::CreateDevice\r
+ *\r
+ * Return:\r
+ *  result      - Windows error code\r
+ */\r
+void __declspec(dllexport) CreateDevice(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)\r
+{\r
+    HDEVINFO            devInfoSet;\r
+    SP_DEVINFO_DATA     devInfoData;\r
+    DWORD               result = 0;\r
+    char                resultBuf[16];\r
+\r
+\r
+    EXDLL_INIT();\r
+\r
+    if (!initialized)\r
+    {\r
+        pushstring("Fatal error!");\r
+        return;\r
+    }\r
+\r
+    devInfoSet = SetupDiCreateDeviceInfoList(&devClass, hwndParent);\r
+    if (devInfoSet == INVALID_HANDLE_VALUE)\r
+    {\r
+        wsprintf(resultBuf, "%08X", GetLastError());\r
+        pushstring(resultBuf);\r
+        return;\r
+    }\r
+\r
+    devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);\r
+    if (!SetupDiCreateDeviceInfo(devInfoSet, hwIdBuf, &devClass, NULL,\r
+                                 hwndParent, DICD_GENERATE_ID, &devInfoData))\r
+    {\r
+        result = GetLastError();\r
+        goto InstallCleanup;\r
+    }\r
+\r
+    if (!SetupDiSetDeviceRegistryProperty(devInfoSet, &devInfoData, SPDRP_HARDWAREID,\r
+                                          hwIdBuf, (lstrlen(hwIdBuf)+2)*sizeof(TCHAR))) \r
+    {\r
+        result = GetLastError();\r
+        goto InstallCleanup;\r
+    }\r
+\r
+    if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE, devInfoSet, &devInfoData))\r
+        result = GetLastError();\r
+\r
+  InstallCleanup:\r
+    SetupDiDestroyDeviceInfoList(devInfoSet);\r
+\r
+    wsprintf(resultBuf, "%08X", result);\r
+    pushstring(resultBuf);\r
+}\r
+\r
+\r
+\r
+/*\r
+ * InstDrv::InstallDriver infPath\r
+ *\r
+ * Return:\r
+ *  result      - Windows error code\r
+ *  reboot      - non-zero if reboot is required\r
+ */\r
+void __declspec(dllexport) InstallDriver(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)\r
+{\r
+    char    resultBuf[16];\r
+    BOOL    reboot;\r
+\r
+\r
+    EXDLL_INIT();\r
+    popstring(paramBuf);\r
+\r
+    if (!initialized)\r
+    {\r
+        pushstring("Fatal error!");\r
+        return;\r
+    }\r
+\r
+    if (!UpdateDriverForPlugAndPlayDevices(hwndParent, hwIdBuf, paramBuf,\r
+                                           INSTALLFLAG_FORCE, &reboot))\r
+    {\r
+        wsprintf(resultBuf, "%08X", GetLastError());\r
+        pushstring(resultBuf);\r
+    }\r
+    else\r
+    {\r
+        wsprintf(resultBuf, "%d", reboot);\r
+        pushstring(resultBuf);\r
+        pushstring("00000000");\r
+    }\r
+}\r
+\r
+\r
+\r
+/*\r
+ * InstDrv::DeleteOemInfFiles\r
+ *\r
+ * Return:\r
+ *  result      - Windows error code\r
+ *  oeminf      - Path of the deleted devices setup file (oemXX.inf)\r
+ *  oempnf      - Path of the deleted devices setup file (oemXX.pnf)\r
+ */\r
+void __declspec(dllexport) DeleteOemInfFiles(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)\r
+{\r
+    HDEVINFO                devInfo;\r
+    SP_DEVINFO_DATA         devInfoData;\r
+    SP_DRVINFO_DATA         drvInfoData;\r
+    SP_DRVINFO_DETAIL_DATA  drvInfoDetail;\r
+    DWORD                   index;\r
+    DWORD                   result;\r
+    char                    resultBuf[16];\r
+\r
+\r
+    if (!initialized)\r
+    {\r
+        pushstring("Fatal error!");\r
+        return;\r
+    }\r
+\r
+    result = FindFirstDevice(NULL, &devClass, hwIdBuf, &devInfo, &devInfoData, &index, 0);\r
+    if (result != 0)\r
+        goto Cleanup1;\r
+\r
+    if (!SetupDiBuildDriverInfoList(devInfo, &devInfoData, SPDIT_COMPATDRIVER))\r
+    {\r
+        result = GetLastError();\r
+        goto Cleanup2;\r
+    }\r
+\r
+    drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);\r
+    drvInfoDetail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);\r
+\r
+    if (!SetupDiEnumDriverInfo(devInfo, &devInfoData, SPDIT_COMPATDRIVER, 0, &drvInfoData))\r
+    {\r
+        result = GetLastError();\r
+        goto Cleanup3;\r
+    }\r
+\r
+    if (!SetupDiGetDriverInfoDetail(devInfo, &devInfoData, &drvInfoData,\r
+                                    &drvInfoDetail, sizeof(drvInfoDetail), NULL))\r
+    {\r
+        result = GetLastError();\r
+\r
+        if (result != ERROR_INSUFFICIENT_BUFFER)\r
+            goto Cleanup3;\r
+\r
+        result = 0;\r
+    }\r
+\r
+    pushstring(drvInfoDetail.InfFileName);\r
+    if (!DeleteFile(drvInfoDetail.InfFileName))\r
+        result = GetLastError();\r
+    else\r
+    {\r
+        index = lstrlen(drvInfoDetail.InfFileName);\r
+        if (index > 3)\r
+        {\r
+            lstrcpy(drvInfoDetail.InfFileName+index-3, "pnf");\r
+            pushstring(drvInfoDetail.InfFileName);\r
+            if (!DeleteFile(drvInfoDetail.InfFileName))\r
+                result = GetLastError();\r
+        }\r
+    }\r
+\r
+  Cleanup3:\r
+    SetupDiDestroyDriverInfoList(devInfo, &devInfoData, SPDIT_COMPATDRIVER);\r
+\r
+  Cleanup2:\r
+    SetupDiDestroyDeviceInfoList(devInfo);\r
+\r
+  Cleanup1:\r
+    wsprintf(resultBuf, "%08X", result);\r
+    pushstring(resultBuf);\r
+}\r
+\r
+\r
+\r
+/*\r
+ * InstDrv::RemoveAllDevices\r
+ *\r
+ * Return:\r
+ *  result      - Windows error code\r
+ *  reboot      - non-zero if reboot is required\r
+ */\r
+void __declspec(dllexport) RemoveAllDevices(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)\r
+{\r
+    HDEVINFO                devInfo;\r
+    SP_DEVINFO_DATA         devInfoData;\r
+    DWORD                   index;\r
+    DWORD                   result;\r
+    char                    resultBuf[16];\r
+    BOOL                    reboot = FALSE;\r
+    SP_DEVINSTALL_PARAMS    instParams;\r
+\r
+\r
+    EXDLL_INIT();\r
+\r
+    if (!initialized)\r
+    {\r
+        pushstring("Fatal error!");\r
+        return;\r
+    }\r
+\r
+    result = FindFirstDevice(NULL, &devClass, hwIdBuf, &devInfo, &devInfoData, &index, 0);\r
+    if (result != 0)\r
+        goto Cleanup1;\r
+\r
+    do\r
+    {\r
+        if (!SetupDiCallClassInstaller(DIF_REMOVE, devInfo, &devInfoData))\r
+        {\r
+            result = GetLastError();\r
+            break;\r
+        }\r
+\r
+        instParams.cbSize = sizeof(instParams);\r
+        if (!reboot &&\r
+            SetupDiGetDeviceInstallParams(devInfo, &devInfoData, &instParams) &&\r
+            ((instParams.Flags & (DI_NEEDRESTART|DI_NEEDREBOOT)) != 0))\r
+        {\r
+            reboot = TRUE;\r
+        }\r
+\r
+        result = FindNextDevice(devInfo, &devInfoData, &index);\r
+    } while (result == 0);\r
+\r
+    SetupDiDestroyDeviceInfoList(devInfo);\r
+\r
+  Cleanup1:\r
+    if ((result == 0) || (result == ERROR_NO_MORE_ITEMS))\r
+    {\r
+        wsprintf(resultBuf, "%d", reboot);\r
+        pushstring(resultBuf);\r
+        pushstring("00000000");\r
+    }\r
+    else\r
+    {\r
+        wsprintf(resultBuf, "%08X", result);\r
+        pushstring(resultBuf);\r
+    }\r
+}\r
+\r
+\r
+\r
+/*\r
+ * InstDrv::StartSystemService serviceName\r
+ *\r
+ * Return:\r
+ *  result      - Windows error code\r
+ */\r
+void __declspec(dllexport) StartSystemService(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)\r
+{\r
+    SC_HANDLE       managerHndl;\r
+    SC_HANDLE       svcHndl;\r
+    SERVICE_STATUS  svcStatus;\r
+    DWORD           oldCheckPoint;\r
+    DWORD           result;\r
+    char            resultBuf[16];\r
+\r
+\r
+    EXDLL_INIT();\r
+    popstring(paramBuf);\r
+\r
+    managerHndl = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);\r
+    if (managerHndl == NULL)\r
+    {\r
+        result = GetLastError();\r
+        goto Cleanup1;\r
+    }\r
+\r
+    svcHndl = OpenService(managerHndl, paramBuf, SERVICE_START | SERVICE_QUERY_STATUS);\r
+    if (svcHndl == NULL)\r
+    {\r
+        result = GetLastError();\r
+        goto Cleanup2;\r
+    }\r
+\r
+    if (!StartService(svcHndl, 0, NULL) || !QueryServiceStatus(svcHndl, &svcStatus))\r
+    {\r
+        result = GetLastError();\r
+        goto Cleanup3;\r
+    }\r
+\r
+    while (svcStatus.dwCurrentState == SERVICE_START_PENDING)\r
+    {\r
+        oldCheckPoint = svcStatus.dwCheckPoint;\r
+\r
+        Sleep(svcStatus.dwWaitHint);\r
+\r
+        if (!QueryServiceStatus(svcHndl, &svcStatus))\r
+        {\r
+            result = GetLastError();\r
+            break;\r
+        }\r
+\r
+        if (oldCheckPoint >= svcStatus.dwCheckPoint)\r
+        {\r
+            if ((svcStatus.dwCurrentState == SERVICE_STOPPED) &&\r
+                (svcStatus.dwWin32ExitCode != 0))\r
+                result = svcStatus.dwWin32ExitCode;\r
+            else\r
+                result = ERROR_SERVICE_REQUEST_TIMEOUT;\r
+        }\r
+    }\r
+\r
+    if (svcStatus.dwCurrentState == SERVICE_RUNNING)\r
+        result = 0;\r
+\r
+  Cleanup3:\r
+    CloseServiceHandle(svcHndl);\r
+\r
+  Cleanup2:\r
+    CloseServiceHandle(managerHndl);\r
+\r
+  Cleanup1:\r
+    wsprintf(resultBuf, "%08X", result);\r
+    pushstring(resultBuf);\r
+}\r
+\r
+\r
+\r
+/*\r
+ * InstDrv::StopSystemService serviceName\r
+ *\r
+ * Return:\r
+ *  result      - Windows error code\r
+ */\r
+void __declspec(dllexport) StopSystemService(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)\r
+{\r
+    SC_HANDLE       managerHndl;\r
+    SC_HANDLE       svcHndl;\r
+    SERVICE_STATUS  svcStatus;\r
+    DWORD           oldCheckPoint;\r
+    DWORD           result;\r
+    char            resultBuf[16];\r
+\r
+\r
+    EXDLL_INIT();\r
+    popstring(paramBuf);\r
+\r
+    managerHndl = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);\r
+    if (managerHndl == NULL)\r
+    {\r
+        result = GetLastError();\r
+        goto Cleanup1;\r
+    }\r
+\r
+    svcHndl = OpenService(managerHndl, paramBuf, SERVICE_STOP | SERVICE_QUERY_STATUS);\r
+    if (svcHndl == NULL)\r
+    {\r
+        result = GetLastError();\r
+        goto Cleanup2;\r
+    }\r
+\r
+    if (!ControlService(svcHndl, SERVICE_CONTROL_STOP, &svcStatus))\r
+    {\r
+        result = GetLastError();\r
+        goto Cleanup3;\r
+    }\r
+\r
+    while (svcStatus.dwCurrentState == SERVICE_STOP_PENDING)\r
+    {\r
+        oldCheckPoint = svcStatus.dwCheckPoint;\r
+\r
+        Sleep(svcStatus.dwWaitHint);\r
+\r
+        if (!QueryServiceStatus(svcHndl, &svcStatus))\r
+        {\r
+            result = GetLastError();\r
+            break;\r
+        }\r
+\r
+        if (oldCheckPoint >= svcStatus.dwCheckPoint)\r
+        {\r
+            result = ERROR_SERVICE_REQUEST_TIMEOUT;\r
+            break;\r
+        }\r
+    }\r
+\r
+    if (svcStatus.dwCurrentState == SERVICE_STOPPED)\r
+        result = 0;\r
+\r
+  Cleanup3:\r
+    CloseServiceHandle(svcHndl);\r
+\r
+  Cleanup2:\r
+    CloseServiceHandle(managerHndl);\r
+\r
+  Cleanup1:\r
+    wsprintf(resultBuf, "%08X", result);\r
+    pushstring(resultBuf);\r
+}\r
+\r
+\r
+\r
+BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)\r
+{\r
+    return TRUE;\r
+}\r
diff --git a/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsp b/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsp
new file mode 100644 (file)
index 0000000..874e66c
--- /dev/null
@@ -0,0 +1,110 @@
+# Microsoft Developer Studio Project File - Name="InstDrv" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** NICHT BEARBEITEN **\r
+\r
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102\r
+\r
+CFG=InstDrv - Win32 Debug\r
+!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE\r
+!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "InstDrv.mak".\r
+!MESSAGE \r
+!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben\r
+!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "InstDrv.mak" CFG="InstDrv - Win32 Debug"\r
+!MESSAGE \r
+!MESSAGE Für die Konfiguration stehen zur Auswahl:\r
+!MESSAGE \r
+!MESSAGE "InstDrv - Win32 Release" (basierend auf  "Win32 (x86) Dynamic-Link Library")\r
+!MESSAGE "InstDrv - Win32 Debug" (basierend auf  "Win32 (x86) Dynamic-Link Library")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+MTL=midl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "InstDrv - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release"\r
+# PROP Intermediate_Dir "Release"\r
+# PROP Ignore_Export_Lib 1\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INSTDRV_EXPORTS" /YX /FD /c\r
+# ADD CPP /nologo /MT /W3 /GX /O1 /I "C:\Programme\WINDDK\3790\inc\ddk\w2k" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INSTDRV_EXPORTS" /FD /c\r
+# SUBTRACT CPP /YX\r
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x407 /d "NDEBUG"\r
+# ADD RSC /l 0x407 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib shell32.lib setupapi.lib newdev.lib /nologo /entry:"_DllMainCRTStartup" /dll /machine:I386 /nodefaultlib /out:"../../Plugins/InstDrv.dll" /libpath:"C:\Programme\WINDDK\3790\lib\w2k\i386" /opt:nowin98\r
+# SUBTRACT LINK32 /pdb:none\r
+\r
+!ELSEIF  "$(CFG)" == "InstDrv - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Debug"\r
+# PROP Intermediate_Dir "Debug"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INSTDRV_EXPORTS" /YX /FD /GZ  /c\r
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INSTDRV_EXPORTS" /YX /FD /GZ  /c\r
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x407 /d "_DEBUG"\r
+# ADD RSC /l 0x407 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"_DllMainCRTStartup" /dll /debug /machine:I386 /pdbtype:sept\r
+# SUBTRACT LINK32 /nodefaultlib\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "InstDrv - Win32 Release"\r
+# Name "InstDrv - Win32 Debug"\r
+# Begin Group "Quellcodedateien"\r
+\r
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
+# Begin Source File\r
+\r
+SOURCE=.\InstDrv.c\r
+# End Source File\r
+# End Group\r
+# Begin Group "Header-Dateien"\r
+\r
+# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
+# End Group\r
+# Begin Group "Ressourcendateien"\r
+\r
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"\r
+# End Group\r
+# End Target\r
+# End Project\r
diff --git a/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsw b/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsw
new file mode 100644 (file)
index 0000000..b3d02f0
--- /dev/null
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00\r
+# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELÖSCHT WERDEN!\r
+\r
+###############################################################################\r
+\r
+Project: "InstDrv"=.\InstDrv.dsp - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Global:\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<3>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
diff --git a/altosui/Instdrv/NSIS/Contrib/InstDrv/Readme.txt b/altosui/Instdrv/NSIS/Contrib/InstDrv/Readme.txt
new file mode 100644 (file)
index 0000000..e5877aa
--- /dev/null
@@ -0,0 +1,141 @@
+InstDrv.dll version 0.2 - Installs or Removes Device Drivers\r
+------------------------------------------------------------\r
+\r
+\r
+The plugin helps you to create NSIS scripts for installing device drivers or\r
+removing them again. It can count installed device instances, create new ones\r
+or delete all supported device. InstDrv works on Windows 2000 or later.\r
+\r
+\r
+\r
+InstDrv::InitDriverSetup devClass drvHWID\r
+Return: result\r
+\r
+To start processing a driver, first call this function. devClass is the GUID\r
+of the device class the driver supports, drvHWID is the device hardware ID. If\r
+you don't know what these terms mean, you may want to take a look at the\r
+Windows DDK. This function returns an empty string on success, otherwise an\r
+error message.\r
+\r
+InitDriverSetup has to be called every time after the plugin dll has been\r
+(re-)loaded, or if you want to switch to a different driver.\r
+\r
+\r
+\r
+InstDrv::CountDevices\r
+Return: number\r
+\r
+This call returns the number of installed and supported devices of the driver.\r
+\r
+\r
+\r
+InstDrv::CreateDevice\r
+Return: result\r
+\r
+To create a new deviced node which the driver has to support, use this\r
+function. You may even call it multiple times for more than one instance. The\r
+return value is the Windows error code (in hex). Use CreateDevice before\r
+installing or updating the driver itself.\r
+\r
+\r
+\r
+InstDrv::InstallDriver infPath\r
+Return: result\r
+        reboot\r
+\r
+InstallDriver installs or updates a device driver as specified in the .inf\r
+setup script. It returns a Windows error code (in hex) and, on success, a flag\r
+signalling if a system reboot is required.\r
+\r
+\r
+\r
+InstDrv::DeleteOemInfFiles\r
+Return: result\r
+        oeminf\r
+        oempnf\r
+\r
+DeleteOemInfFiles tries to clean up the Windows inf directory by deleting the\r
+oemXX.inf and oemXX.pnf files associated with the drivers. It returns a\r
+Windows error code (in hex) and, on success, the names of the deleted files.\r
+This functions requires that at least one device instance is still present.\r
+So, call it before you remove the devices itself. You should also call it\r
+before updating a driver. This avoids that the inf directory gets slowly\r
+messed up with useless old setup scripts (which does NOT really accelerate\r
+Windows). The error code which comes up when no device is installed is\r
+"00000103".\r
+\r
+\r
+\r
+InstDrv::RemoveAllDevices\r
+Return: result\r
+        reboot\r
+\r
+This functions deletes all devices instances the driver supported. It returns\r
+a Windows error code (in hex) and, on success, a flag signalling if the system\r
+needs to be rebooted. You additionally have to remove the driver binaries from\r
+the system paths.\r
+\r
+\r
+\r
+InstDrv::StartSystemService serviceName\r
+Return: result\r
+\r
+Call this function to start the provided system service. The function blocks\r
+until the service is started or the system reported a timeout. The return value\r
+is the Windows error code (in hex).\r
+\r
+\r
+\r
+InstDrv::StopSystemService serviceName\r
+Return: result\r
+\r
+This function tries to stop the provided system service. It blocks until the\r
+service has been shut down or the system reported a timeout. The return value\r
+is the Windows error code (in hex).\r
+\r
+\r
+\r
+Example.nsi\r
+\r
+The example script installs or removes the virtual COM port driver of IrCOMM2k\r
+(2.0.0-alpha8, see www.ircomm2k.de/english). The driver and its setup script\r
+are only included for demonstration purposes, they do not work without the\r
+rest of IrCOMM2k (but they also do not cause any harm).\r
+\r
+\r
+\r
+Building the Source Code\r
+\r
+To build the plugin from the source code, some include files and libraries\r
+which come with the Windows DDK are required.\r
+\r
+\r
+\r
+History\r
+\r
+ 0.2    - fixed bug when calling InitDriverSetup the second time\r
+        - added StartSystemService and StopSystemService\r
+\r
+ 0.1    - first release\r
+\r
+\r
+\r
+License\r
+\r
+Copyright © 2003 Jan Kiszka (Jan.Kiszka@web.de)\r
+\r
+This software is provided 'as-is', without any express or implied\r
+warranty. In no event will the authors be held liable for any damages\r
+arising from the use of this software.\r
+\r
+Permission is granted to anyone to use this software for any purpose,\r
+including commercial applications, and to alter it and redistribute\r
+it freely, subject to the following restrictions:\r
+\r
+1. The origin of this software must not be misrepresented; \r
+   you must not claim that you wrote the original software.\r
+   If you use this software in a product, an acknowledgment in the\r
+   product documentation would be appreciated but is not required.\r
+2. Altered versions must be plainly marked as such,\r
+   and must not be misrepresented as being the original software.\r
+3. This notice may not be removed or altered from any distribution.\r
diff --git a/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.inf b/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.inf
new file mode 100644 (file)
index 0000000..ccda1d8
--- /dev/null
@@ -0,0 +1,137 @@
+; IrCOMM2k.inf\r
+;\r
+; Installation file for the Virtual Infrared-COM-Port\r
+;\r
+; (c) Copyright 2001, 2002 Jan Kiszka \r
+;\r
+\r
+[Version]\r
+Signature="$Windows NT$"\r
+Provider=%JK%\r
+Class=Ports\r
+ClassGUID={4d36e978-e325-11ce-bfc1-08002be10318}\r
+;DriverVer=03/26/2002,1.2.1.0\r
+\r
+[DestinationDirs]\r
+IrCOMM2k.Copy2Drivers  = 12\r
+IrCOMM2k.Copy2Winnt    = 10\r
+IrCOMM2k.Copy2System32 = 11\r
+IrCOMM2k.Copy2Help     = 18\r
+\r
+\r
+;\r
+; Driver information\r
+;\r
+\r
+[Manufacturer]\r
+%JK%   = JK.Mfg\r
+\r
+[JK.Mfg]\r
+%JK.DeviceDescIrCOMM% = IrCOMM2k_inst,IrCOMM2k\r
+\r
+\r
+;\r
+; General installation section\r
+;\r
+\r
+[IrCOMM2k_inst]\r
+CopyFiles = IrCOMM2k.Copy2Drivers ;,IrCOMM2k.Copy2System32,IrCOMM2k.Copy2Help,IrCOMM2k.Copy2Winnt\r
+;AddReg    = IrCOMM2k_inst_AddReg\r
+\r
+\r
+;\r
+; File sections\r
+;\r
+\r
+[IrCOMM2k.Copy2Drivers]\r
+ircomm2k.sys,,,2\r
+\r
+;[IrCOMM2k.Copy2System32]\r
+;ircomm2k.exe,,,2\r
+;ircomm2k.dll,,,2\r
+\r
+;[IrCOMM2k.Copy2Help]\r
+;ircomm2k.hlp,,,2\r
+\r
+;[IrCOMM2k.Copy2Winnt]\r
+;IrCOMM2k-Setup.exe,Setup.exe,,2\r
+\r
+\r
+;\r
+; Service Installation\r
+;\r
+\r
+[IrCOMM2k_inst.Services]\r
+AddService = IrCOMM2k,0x00000002,IrCOMM2k_DriverService_Inst,IrCOMM2k_DriverEventLog_Inst\r
+;AddService = IrCOMM2kSvc,,IrCOMM2k_Service_Inst\r
+\r
+[IrCOMM2k_DriverService_Inst]\r
+DisplayName    = %IrCOMM2k.DrvName%\r
+ServiceType    = 1                  ; SERVICE_KERNEL_DRIVER\r
+StartType      = 3                  ; SERVICE_DEMAND_START\r
+ErrorControl   = 0                  ; SERVICE_ERROR_IGNORE\r
+ServiceBinary  = %12%\ircomm2k.sys\r
+\r
+;[IrCOMM2k_Service_Inst]\r
+;DisplayName    = %IrCOMM2k.SvcName%\r
+;Description    = %IrCOMM2k.SvcDesc%\r
+;ServiceType    = 0x00000120         ; SERVICE_WIN32_SHARE_PROCESS, SERVICE_INTERACTIVE_PROCESS\r
+;StartType      = 2                  ; SERVICE_AUTO_START\r
+;ErrorControl   = 0                  ; SERVICE_ERROR_IGNORE\r
+;ServiceBinary  = %11%\ircomm2k.exe\r
+;Dependencies   = IrCOMM2k\r
+;AddReg         = IrCOMM2kSvcAddReg\r
+\r
+\r
+[IrCOMM2k_inst.nt.HW]\r
+AddReg=IrCOMM2kHwAddReg\r
+\r
+[IrCOMM2kHwAddReg]\r
+HKR,,PortSubClass,REG_BINARY,0x00000001\r
+;HKR,,TimeoutScaling,REG_DWORD,0x00000001\r
+;HKR,,StatusLines,REG_DWORD,0x00000000\r
+\r
+;[IrCOMM2k_inst_AddReg]\r
+;HKR,,EnumPropPages32,,"ircomm2k.dll,IrCOMM2kPropPageProvider"\r
+;HKLM,%UNINSTALL_KEY%,DisplayIcon,0x00020000,"%windir%\IrCOMM2k-Setup.exe"\r
+;HKLM,%UNINSTALL_KEY%,DisplayName,,"IrCOMM2k 1.2.1 "\r
+;HKLM,%UNINSTALL_KEY%,DisplayVersion,,"1.2.1"\r
+;HKLM,%UNINSTALL_KEY%,HelpLink,,"http://www.ircomm2k.de"\r
+;HKLM,%UNINSTALL_KEY%,Publisher,,%JK%\r
+;HKLM,%UNINSTALL_KEY%,UninstallString,0x00020000,"%windir%\IrCOMM2k-Setup.exe"\r
+\r
+;[IrCOMM2kSvcAddReg]\r
+;HKR,Parameters,ActiveConnectOnly,REG_DWORD,0x00000000\r
+\r
+\r
+[IrCOMM2k_DriverEventLog_Inst]\r
+AddReg = IrCOMM2k_DriverEventLog_AddReg\r
+\r
+[IrCOMM2k_DriverEventLog_AddReg]\r
+HKR,,EventMessageFile,REG_EXPAND_SZ,"%SystemRoot%\System32\IoLogMsg.dll;%SystemRoot%\System32\drivers\ircomm2k.sys"\r
+HKR,,TypesSupported,REG_DWORD,7\r
+\r
+\r
+[Strings]\r
+\r
+;\r
+; Non-Localizable Strings\r
+;\r
+\r
+REG_SZ         = 0x00000000\r
+REG_MULTI_SZ   = 0x00010000\r
+REG_EXPAND_SZ  = 0x00020000\r
+REG_BINARY     = 0x00000001\r
+REG_DWORD      = 0x00010001\r
+SERVICEROOT    = "System\CurrentControlSet\Services"\r
+UNINSTALL_KEY  = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\IrCOMM2k"\r
+\r
+;\r
+; Localizable Strings\r
+;\r
+\r
+JK                  = "Jan Kiszka"\r
+JK.DeviceDescIrCOMM = "Virtueller Infrarot-Kommunikationsanschluss"\r
+IrCOMM2k.DrvName    = "Virtueller Infrarot-Kommunikationsanschluss"\r
+;IrCOMM2k.SvcName    = "Virtueller Infrarot-Kommunikationsanschluß, Dienstprogramm"\r
+;IrCOMM2k.SvcDesc    = "Bildet über Infarot einen Kommunikationsanschluß nach."\r
diff --git a/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.sys b/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.sys
new file mode 100644 (file)
index 0000000..7882583
Binary files /dev/null and b/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.sys differ
diff --git a/altosui/Instdrv/NSIS/Plugins/InstDrv.dll b/altosui/Instdrv/NSIS/Plugins/InstDrv.dll
new file mode 100644 (file)
index 0000000..482e955
Binary files /dev/null and b/altosui/Instdrv/NSIS/Plugins/InstDrv.dll differ
diff --git a/altosui/Makefile-standalone b/altosui/Makefile-standalone
new file mode 100644 (file)
index 0000000..a95a5aa
--- /dev/null
@@ -0,0 +1,184 @@
+.SUFFIXES: .java .class
+
+CLASSPATH=classes:./*:/usr/share/java/*
+CLASSFILES=\
+       Altos.class \
+       AltosChannelMenu.class \
+       AltosConfig.class \
+       AltosConfigUI.class \
+       AltosConvert.class \
+       AltosCRCException.class \
+       AltosCSV.class \
+       AltosCSVUI.class \
+       AltosDebug.class \
+       AltosEepromDownload.class \
+       AltosEepromMonitor.class \
+       AltosEepromReader.class \
+       AltosEepromRecord.class \
+       AltosFile.class \
+       AltosFlash.class \
+       AltosFlashUI.class \
+       AltosFlightInfoTableModel.class \
+       AltosFlightStatusTableModel.class \
+       AltosGPS.class \
+       AltosGreatCircle.class \
+       AltosHexfile.class \
+       AltosLine.class \
+       AltosInfoTable.class \
+       AltosLog.class \
+       AltosLogfileChooser.class \
+       AltosParse.class \
+       AltosPreferences.class \
+       AltosReader.class \
+       AltosRecord.class \
+       AltosSerialMonitor.class \
+       AltosSerial.class \
+       AltosState.class \
+       AltosStatusTable.class \
+       AltosTelemetry.class \
+       AltosTelemetryReader.class \
+       AltosUI.class \
+       AltosDevice.class \
+       AltosDeviceDialog.class \
+       AltosRomconfig.class \
+       AltosRomconfigUI.class \
+       AltosVoice.class
+
+JAVA_ICON=../../icon/altus-metrum-16x16.jpg
+WINDOWS_ICON=../../icon/altus-metrum.ico
+
+# where altosui.jar gets installed
+ALTOSLIB=/usr/share/java
+
+# where freetts.jar is to be found
+FREETTSLIB=/usr/share/java
+
+# all of the freetts files
+FREETTSJAR= \
+       $(FREETTSLIB)/cmudict04.jar \
+       $(FREETTSLIB)/cmulex.jar \
+       $(FREETTSLIB)/cmu_time_awb.jar \
+       $(FREETTSLIB)/cmutimelex.jar \
+       $(FREETTSLIB)/cmu_us_kal.jar \
+       $(FREETTSLIB)/en_us.jar \
+       $(FREETTSLIB)/freetts.jar
+
+# The current hex files
+HEXLIB=../../src
+HEXFILES = \
+       $(HEXLIB)/telemetrum-v1.0.ihx \
+       $(HEXLIB)/teledongle-v0.2.ihx
+
+JAVAFLAGS=-Xlint:unchecked -Xlint:deprecation
+
+ALTOSUIJAR = altosui.jar
+FATJAR = fat/altosui.jar
+
+OS:=$(shell uname)
+
+LINUX_APP=altosui
+
+DARWIN_ZIP=Altos-Mac.zip
+
+WINDOWS_EXE=Altos-Windows.exe
+
+LINUX_TGZ=Altos-Linux.tgz
+
+all: altosui.jar $(LINUX_APP)
+fat: altosui.jar $(LINUX_APP) $(DARWIN_ZIP) $(WINDOWS_EXE) $(LINUX_TGZ)
+
+$(CLASSFILES):
+
+.java.class:
+       javac -encoding UTF8 -classpath "$(CLASSPATH)" $(JAVAFLAGS) $*.java
+
+altosui.jar: classes/images classes/altosui classes/libaltosJNI $(CLASSFILES) Manifest.txt
+       cd ./classes && jar cfm ../$@ altosui/Manifest.txt images/* altosui/*.class libaltosJNI/*.class
+
+Manifest.txt: Makefile $(CLASSFILES)
+       echo 'Main-Class: altosui.AltosUI' > $@
+       echo "Class-Path: $(FREETTSLIB)/freetts.jar" >> $@
+
+classes/altosui:
+       mkdir -p classes
+       ln -sf .. classes/altosui
+
+classes/libaltosJNI:
+       mkdir -p classes
+       ln -sf ../../libaltos/libaltosJNI classes/libaltosJNI
+
+classes/images:
+       mkdir -p classes/images
+       ln -sf ../../$(JAVA_ICON) classes/images
+
+altosui:
+       echo "#!/bin/sh" > $@
+       echo "exec java -Djava.library.path=/usr/lib/altos -jar /usr/share/java/altosui.jar" >> $@
+       chmod +x ./altosui
+
+fat/altosui:
+       echo "#!/bin/sh" > $@
+       echo 'ME=`which "$0"`' >> $@
+       echo 'DIR=`dirname "$ME"`' >> $@
+       echo 'exec java -Djava.library.path="$$DIR" -jar "$$DIR"/altosui.jar' >> $@
+       chmod +x $@
+
+fat/altosui.jar: $(CLASSFILES) $(JAVA_ICON) fat/classes/Manifest.txt
+       mkdir -p fat/classes
+       test -L fat/classes/altosui || ln -sf ../.. fat/classes/altosui
+       mkdir -p fat/classes/images
+       cp $(JAVA_ICON) fat/classes/images
+       test -L fat/classes/libaltosJNI || ln -sf ../../../libaltos/libaltosJNI fat/classes/libaltosJNI
+       cd ./fat/classes && jar cfm ../../$@ Manifest.txt images/* altosui/*.class libaltosJNI/*.class
+
+fat/classes/Manifest.txt: $(CLASSFILES) Makefile
+       mkdir -p fat/classes
+       echo 'Main-Class: altosui.AltosUI' > $@
+       echo "Class-Path: freetts.jar" >> $@
+
+install: altosui.jar altosui
+       install -m 0644 altosui.jar $(DESTDIR)/usr/share/java/altosui.jar
+       install -m 0644 altosui.1 $(DESTDIR)/usr/share/man/man1/altosui.1
+       install altosui $(DESTDIR)/usr/bin/altosui
+
+clean:
+       rm -f *.class altosui.jar
+       rm -f AltosUI.app/Contents/Resources/Java/*
+       rm -rf classes
+       rm -rf windows linux
+
+distclean:     clean
+       rm -f $(DARWIN_ZIP) $(WINDOWS_EXE) $(LINUX_TGZ)
+       rm -rf darwin fat
+
+FAT_FILES=$(FATJAR) $(FREETTSJAR) $(HEXFILES)
+
+LINUX_FILES=$(FAT_FILES) ../libaltos/libaltos.so fat/altosui
+$(LINUX_TGZ): $(LINUX_FILES)
+       rm -f $@
+       mkdir -p linux/AltOS
+       rm -f linux/AltOS/*
+       cp $(LINUX_FILES) linux/AltOS
+       cd linux && tar czf ../$@ AltOS
+
+DARWIN_RESOURCES=$(FATJAR) $(FREETTSJAR) ../libaltos/libaltos.dylib
+DARWIN_EXTRA=$(HEXFILES)
+DARWIN_FILES=$(DARWIN_RESOURCES) $(DARWIN_EXTRA)
+
+$(DARWIN_ZIP): $(DARWIN_FILES)
+       rm -f $@
+       cp -a AltosUI.app darwin/
+       mkdir -p darwin/AltosUI.app/Contents/Resources/Java
+       cp $(DARWIN_RESOURCES) darwin/AltosUI.app/Contents/Resources/Java
+       mkdir -p darwin/AltOS
+       cp $(DARWIN_EXTRA) darwin/AltOS
+       cd darwin && zip -r ../$@ AltosUI.app AltOS
+
+WINDOWS_FILES = $(FAT_FILES) ../libaltos/altos.dll ../../telemetrum.inf $(WINDOWS_ICON)
+
+$(WINDOWS_EXE): $(WINDOWS_FILES) altos-windows.nsi
+       rm -f $@
+       mkdir -p windows/AltOS
+       rm -f windows/AltOS/*
+       cp $(WINDOWS_FILES) windows/AltOS
+       makensis altos-windows.nsi
diff --git a/altosui/Makefile.am b/altosui/Makefile.am
new file mode 100644 (file)
index 0000000..e2ff55a
--- /dev/null
@@ -0,0 +1,272 @@
+SUBDIRS=libaltos
+JAVAROOT=classes
+AM_JAVACFLAGS=-encoding UTF-8
+
+man_MANS=altosui.1
+
+altoslibdir=$(libdir)/altos
+
+CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:libaltos:$(FREETTS)/*:/usr/share/java/*"
+
+bin_SCRIPTS=altosui
+
+altosui_JAVA = \
+       GrabNDrag.java \
+       AltosAscent.java \
+       AltosChannelMenu.java \
+       AltosConfig.java \
+       AltosConfigUI.java \
+       AltosConfigureUI.java \
+       AltosConvert.java \
+       AltosCRCException.java \
+       AltosCSV.java \
+       AltosCSVUI.java \
+       AltosDebug.java \
+       AltosDescent.java \
+       AltosDeviceDialog.java \
+       AltosDevice.java \
+       AltosDisplayThread.java \
+       AltosEepromDownload.java \
+       AltosEepromMonitor.java \
+       AltosEepromIterable.java \
+       AltosEepromRecord.java \
+       AltosFile.java \
+       AltosFlash.java \
+       AltosFlashUI.java \
+       AltosFlightDisplay.java \
+       AltosFlightInfoTableModel.java \
+       AltosFlightReader.java \
+       AltosFlightStatus.java \
+       AltosFlightUI.java \
+       AltosGPS.java \
+       AltosGreatCircle.java \
+       AltosHexfile.java \
+       Altos.java \
+       AltosIgnite.java \
+       AltosIgniteUI.java \
+       AltosInfoTable.java \
+       AltosKML.java \
+       AltosLanded.java \
+       AltosLed.java \
+       AltosLights.java \
+       AltosLine.java \
+       AltosLog.java \
+       AltosPad.java \
+       AltosParse.java \
+       AltosPreferences.java \
+       AltosReader.java \
+       AltosRecord.java \
+       AltosRecordIterable.java \
+       AltosTelemetryReader.java \
+       AltosReplayReader.java \
+       AltosRomconfig.java \
+       AltosRomconfigUI.java \
+       AltosSerial.java \
+       AltosSerialInUseException.java \
+       AltosSerialMonitor.java \
+       AltosSiteMap.java \
+       AltosSiteMapCache.java \
+       AltosSiteMapTile.java \
+       AltosState.java \
+       AltosTelemetry.java \
+       AltosTelemetryIterable.java \
+       AltosUI.java \
+       AltosWriter.java \
+       AltosDataPointReader.java \
+       AltosDataPoint.java \
+       AltosGraph.java \
+       AltosGraphTime.java \
+       AltosGraphUI.java \
+       AltosDataChooser.java \
+       AltosVoice.java
+
+JFREECHART_CLASS= \
+    jfreechart.jar
+
+JCOMMON_CLASS=\
+    jcommon.jar
+
+FREETTS_CLASS= \
+       cmudict04.jar \
+       cmulex.jar \
+       cmu_time_awb.jar \
+       cmutimelex.jar \
+       cmu_us_kal.jar \
+       en_us.jar \
+       freetts.jar
+
+LIBALTOS= \
+       libaltos.so \
+       libaltos.dylib \
+       altos.dll
+
+JAR=altosui.jar
+
+FATJAR=altosui-fat.jar
+
+# Icons
+ICONDIR=$(top_srcdir)/icon
+
+JAVA_ICON=$(ICONDIR)/altus-metrum-16x16.jpg
+
+ICONS= $(ICONDIR)/redled.png $(ICONDIR)/redoff.png \
+       $(ICONDIR)/greenled.png $(ICONDIR)/greenoff.png \
+       $(ICONDIR)/grayled.png $(ICONDIR)/grayoff.png
+
+# icon base names for jar
+ICONJAR= -C $(ICONDIR) altus-metrum-16x16.jpg \
+       -C $(ICONDIR) redled.png -C $(ICONDIR) redoff.png \
+       -C $(ICONDIR) greenled.png -C $(ICONDIR) greenoff.png \
+       -C $(ICONDIR) grayon.png -C $(ICONDIR) grayled.png
+
+WINDOWS_ICON=$(ICONDIR)/altus-metrum.ico
+
+# Firmware
+FIRMWARE_TD=$(top_srcdir)/src/teledongle-v0.2-$(VERSION).ihx
+FIRMWARE_TM=$(top_srcdir)/src/telemetrum-v1.0-$(VERSION).ihx
+FIRMWARE=$(FIRMWARE_TM) $(FIRMWARE_TD)
+
+# Distribution targets
+LINUX_DIST=Altos-Linux-$(VERSION).tar.bz2
+MACOSX_DIST=Altos-Mac-$(VERSION).zip
+WINDOWS_DIST=Altos-Windows-$(VERSION_DASH).exe
+
+FAT_FILES=$(FATJAR) $(FREETTS_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS)
+
+LINUX_FILES=$(FAT_FILES) libaltos.so $(FIRMWARE)
+LINUX_EXTRA=altosui-fat
+
+MACOSX_FILES=$(FAT_FILES) libaltos.dylib
+MACOSX_EXTRA=$(FIRMWARE)
+
+WINDOWS_FILES=$(FAT_FILES) altos.dll $(top_srcdir)/telemetrum.inf $(WINDOWS_ICON)
+
+all-local: classes/altosui $(JAR) altosui altosui-test altosui-jdb
+
+clean-local:
+       -rm -rf classes $(JAR) $(FATJAR) \
+               $(LINUX_DIST) $(MACOSX_DIST) windows $(WINDOWS_DIST) $(FREETTS_CLASS) \
+               $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) Manifest.txt Manifest-fat.txt altos-windows.log \
+               altosui altosui-test altosui-jdb macosx linux
+
+if FATINSTALL
+
+FATTARGET=$(FATDIR)/$(VERSION)
+
+LINUX_DIST_TARGET=$(FATTARGET)/$(LINUX_DIST)
+MACOSX_DIST_TARGET=$(FATTARGET)/$(MACOSX_DIST)
+WINDOWS_DIST_TARGET=$(FATTARGET)/$(WINDOWS_DIST)
+
+fat: $(LINUX_DIST_TARGET) $(MACOSX_DIST_TARGET) $(WINDOWS_DIST_TARGET)
+
+$(LINUX_DIST_TARGET): $(LINUX_DIST)
+       mkdir -p $(FATTARGET)
+       cp -p $< $@
+
+$(MACOSX_DIST_TARGET): $(MACOSX_DIST)
+       mkdir -p $(FATTARGET)
+       cp -p $< $@
+
+$(WINDOWS_DIST_TARGET): $(WINDOWS_DIST)
+       mkdir -p $(FATTARGET)
+       cp -p $< $@
+
+else
+fat: $(LINUX_DIST) $(MACOSX_DIST) $(WINDOWS_DIST)
+endif
+
+
+altosuidir=$(datadir)/java
+
+install-altosuiJAVA: altosui.jar
+       @$(NORMAL_INSTALL)
+       test -z "$(altosuidir)" || $(MKDIR_P) "$(DESTDIR)$(altosuidir)"
+       echo " $(INSTALL_DATA)" "$<" "'$(DESTDIR)$(altosuidir)/altosui.jar'"; \
+       $(INSTALL_DATA) "$<" "$(DESTDIR)$(altosuidir)"
+
+classes/altosui:
+       mkdir -p classes/altosui
+
+$(JAR): classaltosui.stamp Manifest.txt $(JAVA_ICON)
+       jar cfm $@ Manifest.txt \
+               $(ICONJAR) \
+               -C classes altosui \
+               -C libaltos libaltosJNI
+
+$(FATJAR): classaltosui.stamp Manifest-fat.txt $(FREETTS_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) $(JAVA_ICON)
+       jar cfm $@ Manifest-fat.txt \
+               $(ICONJAR) \
+               -C classes altosui \
+               -C libaltos libaltosJNI
+
+Manifest.txt: Makefile
+       echo 'Main-Class: altosui.AltosUI' > $@
+       echo "Class-Path: $(FREETTS)/freetts.jar $(JFREECHART)/jfreechart.jar $(JCOMMON)/jcommon.jar" >> $@
+
+Manifest-fat.txt:
+       echo 'Main-Class: altosui.AltosUI' > $@
+       echo "Class-Path: freetts.jar jfreechart.jar jcommon.jar" >> $@
+
+altosui: Makefile
+       echo "#!/bin/sh" > $@
+       echo 'exec java  -cp "$(FREETTS)/*:$(JFREECHART)/*:$(JCOMMON)/*" -Djava.library.path="$(altoslibdir)" -jar "$(altosuidir)/altosui.jar" "$$@"' >> $@
+       chmod +x $@
+
+altosui-test: Makefile
+       echo "#!/bin/sh" > $@
+       echo 'exec java -cp "$(FREETTS)/*:$(JFREECHART)/*:$(JCOMMON)/*" -Djava.library.path="libaltos/.libs" -jar altosui.jar "$$@"' >> $@
+       chmod +x $@
+
+altosui-jdb: Makefile
+       echo "#!/bin/sh" > $@
+       echo 'exec jdb -classpath "classes:libaltos:$(FREETTS)/*:$(JFREECHART)/*:$(JCOMMON)/*" -Djava.library.path="libaltos/.libs" altosui/AltosUI "$$@"' >> $@
+       chmod +x $@
+
+libaltos.so:
+       -rm -f "$@"
+       $(LN_S) libaltos/.libs/"$@" .
+
+libaltos.dylib:
+       -rm -f "$@"
+       $(LN_S) libaltos/"$@" .
+
+altos.dll:
+       -rm -f "$@"
+       $(LN_S) libaltos/"$@" .
+
+$(FREETTS_CLASS):
+       -rm -f "$@"
+       $(LN_S) "$(FREETTS)"/"$@" .
+
+$(JFREECHART_CLASS):
+       -rm -f "$@"
+       $(LN_S) "$(JFREECHART)"/"$@" .
+
+$(JCOMMON_CLASS):
+       -rm -f "$@"
+       $(LN_S) "$(JCOMMON)"/"$@" .
+
+$(LINUX_DIST): $(LINUX_FILES) $(LINUX_EXTRA)
+       -rm -f $@
+       -rm -rf linux
+       mkdir -p linux/AltOS
+       cp -p $(LINUX_FILES) linux/AltOS
+       cp -p altosui-fat linux/AltOS/altosui
+       chmod +x linux/AltOS/altosui
+       tar cjf $@ -C linux AltOS
+
+$(MACOSX_DIST): $(MACOSX_FILES) $(MACOSX_EXTRA)
+       -rm -f $@
+       -rm -rf macosx
+       mkdir macosx
+       cp -a AltosUI.app macosx/
+       mkdir -p macosx/AltOS macosx/AltosUI.app/Contents/Resources/Java
+       cp -p $(FATJAR) macosx/AltosUI.app/Contents/Resources/Java/altosui.jar
+       cp -p $(FREETTS_CLASS) libaltos.dylib macosx/AltosUI.app/Contents/Resources/Java
+       cp -p $(JFREECHART_CLASS) libaltos.dylib macosx/AltosUI.app/Contents/Resources/Java
+       cp -p $(MACOSX_EXTRA) macosx/AltOS
+       cd macosx && zip -r ../$@ AltosUI.app AltOS
+
+$(WINDOWS_DIST): $(WINDOWS_FILES) altos-windows.nsi
+       -rm -f $@
+       makensis -Oaltos-windows.log "-XOutFile $@" "-DVERSION=$(VERSION)" altos-windows.nsi
diff --git a/altosui/altos-windows.nsi b/altosui/altos-windows.nsi
new file mode 100644 (file)
index 0000000..37777fd
--- /dev/null
@@ -0,0 +1,113 @@
+!addplugindir Instdrv/NSIS/Plugins
+
+Name "Altus Metrum Installer"
+
+; Default install directory
+InstallDir "$PROGRAMFILES\AltusMetrum"
+
+; Tell the installer where to re-install a new version
+InstallDirRegKey HKLM "Software\AltusMetrum" "Install_Dir"
+
+LicenseText "GNU General Public License Version 2"
+LicenseData "../../COPYING"
+
+; Need admin privs for Vista or Win7
+RequestExecutionLevel admin
+
+ShowInstDetails Show
+
+ComponentText "Altus Metrum Software and Driver Installer"
+
+; Pages to present
+
+Page license
+Page components
+Page directory
+Page instfiles
+
+UninstPage uninstConfirm
+UninstPage instfiles
+
+; And the stuff to install
+
+Section "Install Driver" InstDriver
+       InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} "Altus Metrum"
+       Pop $0
+       DetailPrint "InitDriverSetup: $0"
+
+       InstDrv::DeleteOemInfFiles /NOUNLOAD
+       InstDrv::CreateDevice /NOUNLOAD
+       SetOutPath $TEMP
+       File "../../telemetrum.inf"
+       InstDrv::InstallDriver /NOUNLOAD "$TEMP\telemetrum.inf"
+
+       SetOutPath $INSTDIR
+       File "../../telemetrum.inf"
+SectionEnd
+
+Section "AltosUI Application"
+       SetOutPath $INSTDIR
+
+       File "altosui-fat.jar"
+       File "cmudict04.jar"
+       File "cmulex.jar"
+       File "cmu_time_awb.jar"
+       File "cmutimelex.jar"
+       File "cmu_us_kal.jar"
+       File "en_us.jar"
+       File "freetts.jar"
+
+       File "*.dll"
+
+       File "../../icon/*.ico"
+
+       CreateShortCut "$SMPROGRAMS\AltusMetrum.lnk" "$INSTDIR\altosui-fat.jar" "" "$INSTDIR\altus-metrum.ico"
+SectionEnd
+
+Section "AltosUI Desktop Shortcut"
+       CreateShortCut "$DESKTOP\AltusMetrum.lnk" "$INSTDIR\altosui-fat.jar"  "" "$INSTDIR\altus-metrum.ico"
+SectionEnd
+
+Section "TeleMetrum and TeleDongle Firmware"
+
+       SetOutPath $INSTDIR
+
+       File "../../src/telemetrum-v1.0/telemetrum-v1.0-${VERSION}.ihx"
+       File "../../src/teledongle-v0.2/teledongle-v0.2-${VERSION}.ihx"
+
+SectionEnd
+
+Section "Uninstaller"
+
+       ; Deal with the uninstaller
+       
+       SetOutPath $INSTDIR
+
+       ; Write the install path to the registry
+       WriteRegStr HKLM SOFTWARE\AltusMetrum "Install_Dir" "$INSTDIR"
+       
+       ; Write the uninstall keys for windows
+       WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "DisplayName" "Altus Metrum"
+       WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "UninstallString" '"$INSTDIR\uninstall.exe"'
+       WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "NoModify" "1"
+       WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "NoRepair" "1"
+
+       WriteUninstaller "uninstall.exe"
+SectionEnd
+
+Section "Uninstall"
+       DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum"
+       DeleteRegKey HKLM "Software\AltusMetrum"
+
+       Delete "$INSTDIR\*.*"
+       RMDir "$INSTDIR"
+
+       ; Remove devices
+       InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} "Altus Metrum"
+       InstDrv::DeleteOemInfFiles /NOUNLOAD
+       InstDrv::RemoveAllDevices
+
+       ; Remove shortcuts, if any
+       Delete "$SMPROGRAMS\AltusMetrum.lnk"
+       Delete "$DESKTOP\AltusMetrum.lnk"
+SectionEnd
diff --git a/altosui/altosui-fat b/altosui/altosui-fat
new file mode 100755 (executable)
index 0000000..95b1c05
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/sh
+me=`which "$0"`
+dir=`dirname "$me"`
+exec java -cp "$dir/*" -Djava.library.path="$dir" -jar "$dir"/altosui-fat.jar  "$@"
diff --git a/altosui/altosui.1 b/altosui/altosui.1
new file mode 100644 (file)
index 0000000..57fa448
--- /dev/null
@@ -0,0 +1,46 @@
+.\"
+.\" Copyright © 2010 Bdale Garbee <bdale@gag.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; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" 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.
+.\"
+.\"
+.TH ALTOSUI 1 "altosui" ""
+.SH NAME
+altosui \- Rocket flight monitor
+.SH SYNOPSIS
+.B "altosui"
+.SH DESCRIPTION
+.I altosui
+connects to a TeleDongle or TeleMetrum device through a USB serial device.
+It provides a menu-oriented
+user interface to monitor, record and review rocket flight data.
+.SH USAGE
+When connected to a TeleDongle device, altosui turns on the radio
+receiver and listens for telemetry packets. It displays the received
+telemetry data, and reports flight status via voice synthesis. All
+received telemetry information is recorded to a file.
+.P
+When connected to a TeleMetrum device, altosui can be used to configure the
+TeleMetrum, and to downloads the eeprom data and store it in a file.
+.P
+A number of other menu options exist, including the ability to export flight
+data in different formats.
+.SH FILES
+All data log files are recorded into a user-specified directory
+(default ~/TeleMetrum). Files are named using the current date, the serial
+number of the reporting device, the flight number recorded in the data
+and either '.telem' for telemetry data or '.eeprom' for eeprom data.
+.SH AUTHOR
+Keith Packard
diff --git a/altosui/altusmetrum.jpg b/altosui/altusmetrum.jpg
new file mode 100644 (file)
index 0000000..0402792
Binary files /dev/null and b/altosui/altusmetrum.jpg differ
diff --git a/altosui/libaltos/.gitignore b/altosui/libaltos/.gitignore
new file mode 100644 (file)
index 0000000..c490e6f
--- /dev/null
@@ -0,0 +1,12 @@
+*.so
+*.lo
+*.la
+*.java
+*.class
+.libs/
+classlibaltos.stamp
+libaltos_wrap.c
+libaltosJNI
+cjnitest
+libaltos.swig
+swig_bindings/
diff --git a/altosui/libaltos/Makefile-standalone b/altosui/libaltos/Makefile-standalone
new file mode 100644 (file)
index 0000000..4e43805
--- /dev/null
@@ -0,0 +1,126 @@
+OS:=$(shell uname)
+
+#
+# Linux
+#
+ifeq ($(OS),Linux)
+
+JAVA_CFLAGS=-I/usr/lib/jvm/java-6-openjdk/include
+
+OS_LIB_CFLAGS=-DLINUX -DPOSIX_TTY $(JAVA_CFLAGS)
+
+OS_APP_CFLAGS=$(OS_LIB_CFLAGS)
+
+OS_LDFLAGS=
+
+LIBNAME=libaltos.so
+EXEEXT=
+endif
+
+#
+# Darwin (Mac OS X)
+#
+ifeq ($(OS),Darwin)
+
+OS_LIB_CFLAGS=\
+       -DDARWIN -DPOSIX_TTY -arch i386 -arch x86_64 \
+       --sysroot=/Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.5 \
+       -iwithsysroot /System/Library/Frameworks/JavaVM.framework/Headers \
+       -iwithsysroot /System/Library/Frameworks/IOKit.framework/Headers \
+       -iwithsysroot /System/Library/Frameworks/CoreFoundation.framework/Headers
+OS_APP_CFLAGS=$(OS_LIB_CFLAGS)
+
+OS_LDFLAGS =\
+       -framework IOKit -framework CoreFoundation
+
+LIBNAME=libaltos.dylib
+EXEEXT=
+
+endif
+
+#
+# Windows
+#
+ifneq (,$(findstring MINGW,$(OS)))
+
+CC=gcc
+
+OS_LIB_CFLAGS = -DWINDOWS -mconsole -DBUILD_DLL
+OS_APP_CFLAGS = -DWINDOWS -mconsole
+
+OS_LDFLAGS = -lgdi32 -luser32 -lcfgmgr32 -lsetupapi -lole32 \
+       -ladvapi32 -lcomctl32 -mconsole -Wl,--add-stdcall-alias
+
+LIBNAME=altos.dll
+
+EXEEXT=.exe
+
+endif
+
+.SUFFIXES: .java .class
+
+CLASSPATH=".:jnitest/*:libaltosJNI:/usr/share/java/*"
+
+SWIG_DIR=swig_bindings/java
+SWIG_FILE=$(SWIG_DIR)/libaltos.swig
+SWIG_WRAP=$(SWIG_DIR)/libaltos_wrap.c
+
+JNI_DIR=libaltosJNI
+JNI_FILE=$(JNI_DIR)/libaltosJNI.java
+JNI_SRCS=$(JNI_FILE) \
+       $(JNI_DIR)/SWIGTYPE_p_altos_file.java \
+       $(JNI_DIR)/SWIGTYPE_p_altos_list.java \
+       $(JNI_DIR)/altos_device.java \
+       $(JNI_DIR)/libaltos.java
+
+JAVAFILES=\
+       $(JNI_SRCS)
+
+CLASSFILES = $(JAVAFILES:%.java=%.class)
+
+JAVAFLAGS=-Xlint:unchecked
+
+CJNITEST=cjnitest$(EXEEXT)
+
+all: $(LIBNAME) $(CJNITEST) $(CLASSFILES)
+
+.java.class:
+       javac -encoding UTF8 -classpath "$(CLASSPATH)" $(JAVAFLAGS) $*.java
+
+CFLAGS=$(OS_LIB_CFLAGS) -O -I.
+
+LDFLAGS=$(OS_LDFLAGS)
+
+HEADERS=libaltos.h
+SRCS = libaltos.c $(SWIG_WRAP)
+OBJS = $(SRCS:%.c=%.o)
+LIBS = $(DARWIN_LIBS)
+
+$(CJNITEST): cjnitest.c $(LIBNAME)
+       $(CC) -o $@ $(OS_APP_CFLAGS) cjnitest.c $(LIBNAME) $(LIBS) $(LDFLAGS)
+
+$(LIBNAME): $(OBJS)
+       $(CC) -shared $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(LDFLAGS)
+
+clean:
+       rm -f $(CLASSFILES) $(OBJS) $(LIBNAME) $(CJNITEST) cjnitest.o
+       rm -rf swig_bindings libaltosJNI
+
+distclean:     clean
+
+$(JNI_FILE): libaltos.i0 $(HEADERS)
+       mkdir -p $(SWIG_DIR)
+       mkdir -p libaltosJNI
+       sed 's;//%;%;' libaltos.i0 $(HEADERS) > $(SWIG_FILE)
+       swig -java -package libaltosJNI $(SWIG_FILE)
+       cp swig_bindings/java/*.java libaltosJNI
+
+$(SWIG_WRAP): $(JNI_FILE)
+
+ifeq ($(OS),Linux)
+install:       $(LIBNAME)
+       install -c $(LIBNAME) $(DESTDIR)/usr/lib/altos/$(LIBNAME)
+
+endif
+
+.NOTPARALLEL:
diff --git a/altosui/libaltos/Makefile.am b/altosui/libaltos/Makefile.am
new file mode 100644 (file)
index 0000000..388d210
--- /dev/null
@@ -0,0 +1,41 @@
+JAVAC=javac
+AM_CFLAGS=-DLINUX -DPOSIX_TTY -I$(JVM_INCLUDE)
+AM_JAVACFLAGS=-encoding UTF-8
+
+altoslibdir=$(libdir)/altos
+
+altoslib_LTLIBRARIES=libaltos.la
+
+libaltos_la_LDFLAGS = -version-info 1:0:1
+
+libaltos_la_SOURCES=\
+       libaltos.c \
+       libaltos_wrap.c
+
+noinst_PROGRAMS=cjnitest
+
+cjnitest_LDADD=libaltos.la
+
+LIBS=
+
+HFILES=libaltos.h
+
+SWIG_FILE=libaltos.swig
+
+CLASSDIR=libaltosJNI
+
+$(SWIG_FILE): libaltos.i0 $(HFILES)
+       sed 's;//%;%;' libaltos.i0 $(HFILES) > $(SWIG_FILE)
+
+all-local: classlibaltos.stamp
+
+libaltos_wrap.c: classlibaltos.stamp
+
+classlibaltos.stamp: $(SWIG_FILE)
+       swig -java -package libaltosJNI $(SWIG_FILE)
+       mkdir -p libaltosJNI
+       $(JAVAC) -d . $(AM_JAVACFLAGS) $(JAVACFLAGS) *.java && \
+       touch classlibaltos.stamp
+
+clean-local:
+       -rm -rf libaltosJNI *.class *.java classlibaltos.stamp $(SWIG_FILE) libaltos_wrap.c
diff --git a/altosui/libaltos/altos.dll b/altosui/libaltos/altos.dll
new file mode 100755 (executable)
index 0000000..28e9b4a
Binary files /dev/null and b/altosui/libaltos/altos.dll differ
diff --git a/altosui/libaltos/cjnitest.c b/altosui/libaltos/cjnitest.c
new file mode 100644 (file)
index 0000000..c6d6e06
--- /dev/null
@@ -0,0 +1,43 @@
+#include <stdio.h>
+#include "libaltos.h"
+
+static void
+altos_puts(struct altos_file *file, char *string)
+{
+       char    c;
+
+       while ((c = *string++))
+               altos_putchar(file, c);
+}
+
+main ()
+{
+       struct altos_device     device;
+       struct altos_list       *list;
+
+       altos_init();
+       list = altos_list_start();
+       while (altos_list_next(list, &device)) {
+               struct altos_file       *file;
+               int                     c;
+
+               printf ("%04x:%04x %-20s %4d %s\n", device.vendor, device.product,
+                       device.name, device.serial, device.path);
+
+               file = altos_open(&device);
+               if (!file) {
+                       printf("altos_open failed\n");
+                       continue;
+               }
+               altos_puts(file,"v\nc s\n");
+               altos_flush(file);
+               while ((c = altos_getchar(file, 100)) >= 0) {
+                       putchar (c);
+               }
+               if (c != LIBALTOS_TIMEOUT)
+                       printf ("getchar returns %d\n", c);
+               altos_close(file);
+       }
+       altos_list_finish(list);
+       altos_fini();
+}
diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c
new file mode 100644 (file)
index 0000000..465f0ac
--- /dev/null
@@ -0,0 +1,1028 @@
+/*
+ * 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.
+ */
+
+#include "libaltos.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define USE_POLL
+
+PUBLIC int
+altos_init(void)
+{
+       return LIBALTOS_SUCCESS;
+}
+
+PUBLIC void
+altos_fini(void)
+{
+}
+
+#ifdef DARWIN
+
+#undef USE_POLL
+
+/* Mac OS X don't have strndup even if _GNU_SOURCE is defined */
+static char *
+altos_strndup (const char *s, size_t n)
+{
+    size_t len = strlen (s);
+    char *ret;
+
+    if (len <= n)
+       return strdup (s);
+    ret = malloc(n + 1);
+    strncpy(ret, s, n);
+    ret[n] = '\0';
+    return ret;
+}
+
+#else
+#define altos_strndup strndup
+#endif
+
+/*
+ * Scan for Altus Metrum devices by looking through /sys
+ */
+
+#ifdef LINUX
+
+#define _GNU_SOURCE
+#include <ctype.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static char *
+cc_fullname (char *dir, char *file)
+{
+       char    *new;
+       int     dlen = strlen (dir);
+       int     flen = strlen (file);
+       int     slen = 0;
+
+       if (dir[dlen-1] != '/')
+               slen = 1;
+       new = malloc (dlen + slen + flen + 1);
+       if (!new)
+               return 0;
+       strcpy(new, dir);
+       if (slen)
+               strcat (new, "/");
+       strcat(new, file);
+       return new;
+}
+
+static char *
+cc_basename(char *file)
+{
+       char *b;
+
+       b = strrchr(file, '/');
+       if (!b)
+               return file;
+       return b + 1;
+}
+
+static char *
+load_string(char *dir, char *file)
+{
+       char    *full = cc_fullname(dir, file);
+       char    line[4096];
+       char    *r;
+       FILE    *f;
+       int     rlen;
+
+       f = fopen(full, "r");
+       free(full);
+       if (!f)
+               return NULL;
+       r = fgets(line, sizeof (line), f);
+       fclose(f);
+       if (!r)
+               return NULL;
+       rlen = strlen(r);
+       if (r[rlen-1] == '\n')
+               r[rlen-1] = '\0';
+       return strdup(r);
+}
+
+static int
+load_hex(char *dir, char *file)
+{
+       char    *line;
+       char    *end;
+       long    i;
+
+       line = load_string(dir, file);
+       if (!line)
+               return -1;
+       i = strtol(line, &end, 16);
+       free(line);
+       if (end == line)
+               return -1;
+       return i;
+}
+
+static int
+load_dec(char *dir, char *file)
+{
+       char    *line;
+       char    *end;
+       long    i;
+
+       line = load_string(dir, file);
+       if (!line)
+               return -1;
+       i = strtol(line, &end, 10);
+       free(line);
+       if (end == line)
+               return -1;
+       return i;
+}
+
+static int
+dir_filter_tty_colon(const struct dirent *d)
+{
+       return strncmp(d->d_name, "tty:", 4) == 0;
+}
+
+static int
+dir_filter_tty(const struct dirent *d)
+{
+       return strncmp(d->d_name, "tty", 3) == 0;
+}
+
+struct altos_usbdev {
+       char    *sys;
+       char    *tty;
+       char    *manufacturer;
+       char    *product_name;
+       int     serial; /* AltOS always uses simple integer serial numbers */
+       int     idProduct;
+       int     idVendor;
+};
+
+static char *
+usb_tty(char *sys)
+{
+       char *base;
+       int num_configs;
+       int config;
+       struct dirent **namelist;
+       int interface;
+       int num_interfaces;
+       char endpoint_base[20];
+       char *endpoint_full;
+       char *tty_dir;
+       int ntty;
+       char *tty;
+
+       base = cc_basename(sys);
+       num_configs = load_hex(sys, "bNumConfigurations");
+       num_interfaces = load_hex(sys, "bNumInterfaces");
+       for (config = 1; config <= num_configs; config++) {
+               for (interface = 0; interface < num_interfaces; interface++) {
+                       sprintf(endpoint_base, "%s:%d.%d",
+                               base, config, interface);
+                       endpoint_full = cc_fullname(sys, endpoint_base);
+
+                       /* Check for tty:ttyACMx style names
+                        */
+                       ntty = scandir(endpoint_full, &namelist,
+                                      dir_filter_tty_colon,
+                                      alphasort);
+                       if (ntty > 0) {
+                               free(endpoint_full);
+                               tty = cc_fullname("/dev", namelist[0]->d_name + 4);
+                               free(namelist);
+                               return tty;
+                       }
+
+                       /* Check for tty/ttyACMx style names
+                        */
+                       tty_dir = cc_fullname(endpoint_full, "tty");
+                       free(endpoint_full);
+                       ntty = scandir(tty_dir, &namelist,
+                                      dir_filter_tty,
+                                      alphasort);
+                       free (tty_dir);
+                       if (ntty > 0) {
+                               tty = cc_fullname("/dev", namelist[0]->d_name);
+                               free(namelist);
+                               return tty;
+                       }
+               }
+       }
+       return NULL;
+}
+
+static struct altos_usbdev *
+usb_scan_device(char *sys)
+{
+       struct altos_usbdev *usbdev;
+
+       usbdev = calloc(1, sizeof (struct altos_usbdev));
+       if (!usbdev)
+               return NULL;
+       usbdev->sys = strdup(sys);
+       usbdev->manufacturer = load_string(sys, "manufacturer");
+       usbdev->product_name = load_string(sys, "product");
+       usbdev->serial = load_dec(sys, "serial");
+       usbdev->idProduct = load_hex(sys, "idProduct");
+       usbdev->idVendor = load_hex(sys, "idVendor");
+       usbdev->tty = usb_tty(sys);
+       return usbdev;
+}
+
+static void
+usbdev_free(struct altos_usbdev *usbdev)
+{
+       free(usbdev->sys);
+       free(usbdev->manufacturer);
+       free(usbdev->product_name);
+       /* this can get used as a return value */
+       if (usbdev->tty)
+               free(usbdev->tty);
+       free(usbdev);
+}
+
+#define USB_DEVICES    "/sys/bus/usb/devices"
+
+static int
+dir_filter_dev(const struct dirent *d)
+{
+       const char      *n = d->d_name;
+       char    c;
+
+       while ((c = *n++)) {
+               if (isdigit(c))
+                       continue;
+               if (c == '-')
+                       continue;
+               if (c == '.' && n != d->d_name + 1)
+                       continue;
+               return 0;
+       }
+       return 1;
+}
+
+struct altos_list {
+       struct altos_usbdev     **dev;
+       int                     current;
+       int                     ndev;
+};
+
+struct altos_list *
+altos_list_start(void)
+{
+       int                     e;
+       struct dirent           **ents;
+       char                    *dir;
+       struct altos_usbdev     *dev;
+       struct altos_list       *devs;
+       int                     n;
+
+       devs = calloc(1, sizeof (struct altos_list));
+       if (!devs)
+               return NULL;
+
+       n = scandir (USB_DEVICES, &ents,
+                    dir_filter_dev,
+                    alphasort);
+       if (!n)
+               return 0;
+       for (e = 0; e < n; e++) {
+               dir = cc_fullname(USB_DEVICES, ents[e]->d_name);
+               dev = usb_scan_device(dir);
+               free(dir);
+               if (USB_IS_ALTUSMETRUM(dev->idVendor, dev->idProduct)) {
+                       if (devs->dev)
+                               devs->dev = realloc(devs->dev,
+                                                   devs->ndev + 1 * sizeof (struct usbdev *));
+                       else
+                               devs->dev = malloc (sizeof (struct usbdev *));
+                       devs->dev[devs->ndev++] = dev;
+               }
+       }
+       free(ents);
+       devs->current = 0;
+       return devs;
+}
+
+int
+altos_list_next(struct altos_list *list, struct altos_device *device)
+{
+       struct altos_usbdev *dev;
+       if (list->current >= list->ndev)
+               return 0;
+       dev = list->dev[list->current];
+       strcpy(device->name, dev->product_name);
+       device->vendor = dev->idVendor;
+       device->product = dev->idProduct;
+       strcpy(device->path, dev->tty);
+       device->serial = dev->serial;
+       list->current++;
+       return 1;
+}
+
+void
+altos_list_finish(struct altos_list *usbdevs)
+{
+       int     i;
+
+       if (!usbdevs)
+               return;
+       for (i = 0; i < usbdevs->ndev; i++)
+               usbdev_free(usbdevs->dev[i]);
+       free(usbdevs);
+}
+
+#endif
+
+#ifdef DARWIN
+
+#include <IOKitLib.h>
+#include <IOKit/usb/USBspec.h>
+#include <sys/param.h>
+#include <paths.h>
+#include <CFNumber.h>
+#include <IOBSD.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+struct altos_list {
+       io_iterator_t iterator;
+};
+
+static int
+get_string(io_object_t object, CFStringRef entry, char *result, int result_len)
+{
+       CFTypeRef entry_as_string;
+       Boolean got_string;
+
+       entry_as_string = IORegistryEntrySearchCFProperty (object,
+                                                          kIOServicePlane,
+                                                          entry,
+                                                          kCFAllocatorDefault,
+                                                          kIORegistryIterateRecursively);
+       if (entry_as_string) {
+               got_string = CFStringGetCString(entry_as_string,
+                                               result, result_len,
+                                               kCFStringEncodingASCII);
+    
+               CFRelease(entry_as_string);
+               if (got_string)
+                       return 1;
+       }
+       return 0;
+}
+
+static int
+get_number(io_object_t object, CFStringRef entry, int *result)
+{
+       CFTypeRef entry_as_number;
+       Boolean got_number;
+       
+       entry_as_number = IORegistryEntrySearchCFProperty (object,
+                                                          kIOServicePlane,
+                                                          entry,
+                                                          kCFAllocatorDefault,
+                                                          kIORegistryIterateRecursively);
+       if (entry_as_number) {
+               got_number = CFNumberGetValue(entry_as_number,
+                                             kCFNumberIntType,
+                                             result);
+               if (got_number)
+                       return 1;
+       }
+       return 0;
+}
+
+struct altos_list *
+altos_list_start(void)
+{
+       struct altos_list *list = calloc (sizeof (struct altos_list), 1);
+       CFMutableDictionaryRef matching_dictionary = IOServiceMatching("IOUSBDevice");
+       io_iterator_t tdIterator;
+       io_object_t tdObject;
+       kern_return_t ret;
+       int i;
+
+       ret = IOServiceGetMatchingServices(kIOMasterPortDefault, matching_dictionary, &list->iterator);
+       if (ret != kIOReturnSuccess)
+               return NULL;
+       return list;
+}
+
+int
+altos_list_next(struct altos_list *list, struct altos_device *device)
+{
+       io_object_t object;
+       char serial_string[128];
+
+       for (;;) {
+               object = IOIteratorNext(list->iterator);
+               if (!object)
+                       return 0;
+  
+               if (!get_number (object, CFSTR(kUSBVendorID), &device->vendor) ||
+                   !get_number (object, CFSTR(kUSBProductID), &device->product))
+                       continue;
+               if (device->vendor != 0xfffe)
+                       continue;
+               if (device->product < 0x000a || 0x0013 < device->product)
+                       continue;
+               if (get_string (object, CFSTR("IOCalloutDevice"), device->path, sizeof (device->path)) &&
+                   get_string (object, CFSTR("USB Product Name"), device->name, sizeof (device->name)) &&
+                   get_string (object, CFSTR("USB Serial Number"), serial_string, sizeof (serial_string))) {
+                       device->serial = atoi(serial_string);
+                       return 1;
+               }
+       }
+}
+
+void
+altos_list_finish(struct altos_list *list)
+{
+       IOObjectRelease (list->iterator);
+       free(list);
+}
+
+#endif
+
+#ifdef POSIX_TTY
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <errno.h>
+
+#define USB_BUF_SIZE   64
+
+struct altos_file {
+       int                             fd;
+#ifdef USE_POLL
+       int                             pipe[2];
+#else
+       int                             out_fd;
+#endif
+       unsigned char                   out_data[USB_BUF_SIZE];
+       int                             out_used;
+       unsigned char                   in_data[USB_BUF_SIZE];
+       int                             in_used;
+       int                             in_read;
+};
+
+PUBLIC struct altos_file *
+altos_open(struct altos_device *device)
+{
+       struct altos_file       *file = calloc (sizeof (struct altos_file), 1);
+       int                     ret;
+       struct termios          term;
+
+       if (!file)
+               return NULL;
+
+       file->fd = open(device->path, O_RDWR | O_NOCTTY);
+       if (file->fd < 0) {
+               perror(device->path);
+               free(file);
+               return NULL;
+       }
+#ifdef USE_POLL
+       pipe(file->pipe);
+#else
+       file->out_fd = open(device->path, O_RDWR | O_NOCTTY);
+       if (file->out_fd < 0) {
+               perror(device->path);
+               close(file->fd);
+               free(file);
+               return NULL;
+       }
+#endif
+       ret = tcgetattr(file->fd, &term);
+       if (ret < 0) {
+               perror("tcgetattr");
+               close(file->fd);
+#ifndef USE_POLL
+               close(file->out_fd);
+#endif
+               free(file);
+               return NULL;
+       }
+       cfmakeraw(&term);
+#ifdef USE_POLL
+       term.c_cc[VMIN] = 1;
+       term.c_cc[VTIME] = 0;
+#else
+       term.c_cc[VMIN] = 0;
+       term.c_cc[VTIME] = 1;
+#endif
+       ret = tcsetattr(file->fd, TCSAFLUSH, &term);
+       if (ret < 0) {
+               perror("tcsetattr");
+               close(file->fd);
+#ifndef USE_POLL
+               close(file->out_fd);
+#endif
+               free(file);
+               return NULL;
+       }
+       return file;
+}
+
+PUBLIC void
+altos_close(struct altos_file *file)
+{
+       if (file->fd != -1) {
+               int     fd = file->fd;
+               file->fd = -1;
+#ifdef USE_POLL
+               write(file->pipe[1], "\r", 1);
+#else
+               close(file->out_fd);
+               file->out_fd = -1;
+#endif
+               close(fd);
+       }
+}
+
+PUBLIC void
+altos_free(struct altos_file *file)
+{
+       altos_close(file);
+       free(file);
+}
+
+PUBLIC int
+altos_flush(struct altos_file *file)
+{
+       if (file->out_used && 0) {
+               printf ("flush \"");
+               fwrite(file->out_data, 1, file->out_used, stdout);
+               printf ("\"\n");
+       }
+       while (file->out_used) {
+               int     ret;
+
+               if (file->fd < 0)
+                       return -EBADF;
+#ifdef USE_POLL
+               ret = write (file->fd, file->out_data, file->out_used);
+#else
+               ret = write (file->out_fd, file->out_data, file->out_used);
+#endif
+               if (ret < 0)
+                       return -errno;
+               if (ret) {
+                       memmove(file->out_data, file->out_data + ret,
+                               file->out_used - ret);
+                       file->out_used -= ret;
+               }
+       }
+       return 0;
+}
+
+PUBLIC int
+altos_putchar(struct altos_file *file, char c)
+{
+       int     ret;
+
+       if (file->out_used == USB_BUF_SIZE) {
+               ret = altos_flush(file);
+               if (ret) {
+                       return ret;
+               }
+       }
+       file->out_data[file->out_used++] = c;
+       ret = 0;
+       if (file->out_used == USB_BUF_SIZE)
+               ret = altos_flush(file);
+       return 0;
+}
+
+#ifdef USE_POLL
+#include <poll.h>
+#endif
+
+static int
+altos_fill(struct altos_file *file, int timeout)
+{
+       int             ret;
+#ifdef USE_POLL
+       struct pollfd   fd[2];
+#endif
+
+       if (timeout == 0)
+               timeout = -1;
+       while (file->in_read == file->in_used) {
+               if (file->fd < 0)
+                       return LIBALTOS_ERROR;
+#ifdef USE_POLL
+               fd[0].fd = file->fd;
+               fd[0].events = POLLIN|POLLERR|POLLHUP|POLLNVAL;
+               fd[1].fd = file->pipe[0];
+               fd[1].events = POLLIN;
+               ret = poll(fd, 2, timeout);
+               if (ret < 0) {
+                       perror("altos_getchar");
+                       return LIBALTOS_ERROR;
+               }
+               if (ret == 0)
+                       return LIBALTOS_TIMEOUT;
+
+               if (fd[0].revents & (POLLHUP|POLLERR|POLLNVAL))
+                       return LIBALTOS_ERROR;
+               if (fd[0].revents & POLLIN)
+#endif
+               {
+                       ret = read(file->fd, file->in_data, USB_BUF_SIZE);
+                       if (ret < 0) {
+                               perror("altos_getchar");
+                               return LIBALTOS_ERROR;
+                       }
+                       file->in_read = 0;
+                       file->in_used = ret;
+#ifndef USE_POLL
+                       if (ret == 0 && timeout > 0)
+                               return LIBALTOS_TIMEOUT;
+#endif
+               }
+       }
+       if (file->in_used && 0) {
+               printf ("fill \"");
+               fwrite(file->in_data, 1, file->in_used, stdout);
+               printf ("\"\n");
+       }
+       return 0;
+}
+
+PUBLIC int
+altos_getchar(struct altos_file *file, int timeout)
+{
+       int     ret;
+       while (file->in_read == file->in_used) {
+               if (file->fd < 0)
+                       return LIBALTOS_ERROR;
+               ret = altos_fill(file, timeout);
+               if (ret)
+                       return ret;
+       }
+       return file->in_data[file->in_read++];
+}
+
+#endif /* POSIX_TTY */
+
+#ifdef WINDOWS
+
+#include <stdlib.h>
+#include <windows.h>
+#include <setupapi.h>
+
+struct altos_list {
+       HDEVINFO        dev_info;
+       int             index;
+};
+
+#define USB_BUF_SIZE   64
+
+struct altos_file {
+       HANDLE                          handle;
+       unsigned char                   out_data[USB_BUF_SIZE];
+       int                             out_used;
+       unsigned char                   in_data[USB_BUF_SIZE];
+       int                             in_used;
+       int                             in_read;
+       OVERLAPPED                      ov_read;
+       BOOL                            pend_read;
+       OVERLAPPED                      ov_write;
+};
+
+PUBLIC struct altos_list *
+altos_list_start(void)
+{
+       struct altos_list       *list = calloc(1, sizeof (struct altos_list));
+
+       if (!list)
+               return NULL;
+       list->dev_info = SetupDiGetClassDevs(NULL, "USB", NULL,
+                                            DIGCF_ALLCLASSES|DIGCF_PRESENT);
+       if (list->dev_info == INVALID_HANDLE_VALUE) {
+               printf("SetupDiGetClassDevs failed %d\n", GetLastError());
+               free(list);
+               return NULL;
+       }
+       list->index = 0;
+       return list;
+}
+
+PUBLIC int
+altos_list_next(struct altos_list *list, struct altos_device *device)
+{
+       SP_DEVINFO_DATA dev_info_data;
+       char            port[128];
+       DWORD           port_len;
+       char            friendlyname[256];
+       char            symbolic[256];
+       DWORD           symbolic_len;
+       HKEY            dev_key;
+       int             vid, pid;
+       int             serial;
+       HRESULT         result;
+       DWORD           friendlyname_type;
+       DWORD           friendlyname_len;
+
+       dev_info_data.cbSize = sizeof (SP_DEVINFO_DATA);
+       while(SetupDiEnumDeviceInfo(list->dev_info, list->index,
+                                   &dev_info_data))
+       {
+               list->index++;
+
+               dev_key = SetupDiOpenDevRegKey(list->dev_info, &dev_info_data,
+                                              DICS_FLAG_GLOBAL, 0, DIREG_DEV,
+                                              KEY_READ);
+               if (dev_key == INVALID_HANDLE_VALUE) {
+                       printf("cannot open device registry key\n");
+                       continue;
+               }
+
+               /* Fetch symbolic name for this device and parse out
+                * the vid/pid/serial info */
+               symbolic_len = sizeof(symbolic);
+               result = RegQueryValueEx(dev_key, "SymbolicName", NULL, NULL,
+                                        symbolic, &symbolic_len);
+               if (result != 0) {
+                       printf("cannot find SymbolicName value\n");
+                       RegCloseKey(dev_key);
+                       continue;
+               }
+               vid = pid = serial = 0;
+               sscanf(symbolic + sizeof("\\??\\USB#VID_") - 1,
+                      "%04X", &vid);
+               sscanf(symbolic + sizeof("\\??\\USB#VID_XXXX&PID_") - 1,
+                      "%04X", &pid);
+               sscanf(symbolic + sizeof("\\??\\USB#VID_XXXX&PID_XXXX#") - 1,
+                      "%d", &serial);
+               if (!USB_IS_ALTUSMETRUM(vid, pid)) {
+                       RegCloseKey(dev_key);
+                       continue;
+               }
+
+               /* Fetch the com port name */
+               port_len = sizeof (port);
+               result = RegQueryValueEx(dev_key, "PortName", NULL, NULL,
+                                        port, &port_len);
+               RegCloseKey(dev_key);
+               if (result != 0) {
+                       printf("failed to get PortName\n");
+                       continue;
+               }
+
+               /* Fetch the device description which is the device name,
+                * with firmware that has unique USB ids */
+               friendlyname_len = sizeof (friendlyname);
+               if(!SetupDiGetDeviceRegistryProperty(list->dev_info,
+                                                    &dev_info_data,
+                                                    SPDRP_FRIENDLYNAME,
+                                                    &friendlyname_type,
+                                                    (BYTE *)friendlyname,
+                                                    sizeof(friendlyname),
+                                                    &friendlyname_len))
+               {
+                       printf("Failed to get friendlyname\n");
+                       continue;
+               }
+               device->vendor = vid;
+               device->product = pid;
+               device->serial = serial;
+               strcpy(device->name, friendlyname);
+
+               strcpy(device->path, port);
+               return 1;
+       }
+       result = GetLastError();
+       if (result != ERROR_NO_MORE_ITEMS)
+               printf ("SetupDiEnumDeviceInfo failed error %d\n", result);
+       return 0;
+}
+
+PUBLIC void
+altos_list_finish(struct altos_list *list)
+{
+       SetupDiDestroyDeviceInfoList(list->dev_info);
+       free(list);
+}
+
+static int
+altos_queue_read(struct altos_file *file)
+{
+       DWORD   got;
+       if (file->pend_read)
+               return LIBALTOS_SUCCESS;
+
+       if (!ReadFile(file->handle, file->in_data, USB_BUF_SIZE, &got, &file->ov_read)) {
+               if (GetLastError() != ERROR_IO_PENDING)
+                       return LIBALTOS_ERROR;
+               file->pend_read = TRUE;
+       } else {
+               file->pend_read = FALSE;
+               file->in_read = 0;
+               file->in_used = got;
+       }
+       return LIBALTOS_SUCCESS;
+}
+
+static int
+altos_wait_read(struct altos_file *file, int timeout)
+{
+       DWORD   ret;
+       DWORD   got;
+
+       if (!file->pend_read)
+               return LIBALTOS_SUCCESS;
+
+       if (!timeout)
+               timeout = INFINITE;
+
+       ret = WaitForSingleObject(file->ov_read.hEvent, timeout);
+       switch (ret) {
+       case WAIT_OBJECT_0:
+               if (!GetOverlappedResult(file->handle, &file->ov_read, &got, FALSE))
+                       return LIBALTOS_ERROR;
+               file->pend_read = FALSE;
+               file->in_read = 0;
+               file->in_used = got;
+               break;
+       case WAIT_TIMEOUT:
+               return LIBALTOS_TIMEOUT;
+               break;
+       default:
+               return LIBALTOS_ERROR;
+       }
+       return LIBALTOS_SUCCESS;
+}
+
+static int
+altos_fill(struct altos_file *file, int timeout)
+{
+       int     ret;
+
+       if (file->in_read < file->in_used)
+               return LIBALTOS_SUCCESS;
+
+       file->in_read = file->in_used = 0;
+
+       ret = altos_queue_read(file);
+       if (ret)
+               return ret;
+       ret = altos_wait_read(file, timeout);
+       if (ret)
+               return ret;
+
+       return LIBALTOS_SUCCESS;
+}
+
+PUBLIC int
+altos_flush(struct altos_file *file)
+{
+       DWORD   put;
+       char    *data = file->out_data;
+       char    used = file->out_used;
+       DWORD   ret;
+
+       while (used) {
+               if (!WriteFile(file->handle, data, used, &put, &file->ov_write)) {
+                       if (GetLastError() != ERROR_IO_PENDING)
+                               return LIBALTOS_ERROR;
+                       ret = WaitForSingleObject(file->ov_write.hEvent, INFINITE);
+                       switch (ret) {
+                       case WAIT_OBJECT_0:
+                               if (!GetOverlappedResult(file->handle, &file->ov_write, &put, FALSE))
+                                       return LIBALTOS_ERROR;
+                               break;
+                       default:
+                               return LIBALTOS_ERROR;
+                       }
+               }
+               data += put;
+               used -= put;
+       }
+       file->out_used = 0;
+       return LIBALTOS_SUCCESS;
+}
+
+PUBLIC struct altos_file *
+altos_open(struct altos_device *device)
+{
+       struct altos_file       *file = calloc (1, sizeof (struct altos_file));
+       char    full_name[64];
+       DCB dcbSerialParams = {0};
+       COMMTIMEOUTS timeouts;
+
+       if (!file)
+               return NULL;
+
+       strcpy(full_name, "\\\\.\\");
+       strcat(full_name, device->path);
+       file->handle = CreateFile(full_name, GENERIC_READ|GENERIC_WRITE,
+                                 0, NULL, OPEN_EXISTING,
+                                 FILE_FLAG_OVERLAPPED, NULL);
+       if (file->handle == INVALID_HANDLE_VALUE) {
+               free(file);
+               return NULL;
+       }
+       file->ov_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+       file->ov_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+       timeouts.ReadIntervalTimeout = MAXDWORD;
+       timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
+       timeouts.ReadTotalTimeoutConstant = 1 << 30;    /* almost forever */
+       timeouts.WriteTotalTimeoutMultiplier = 0;
+       timeouts.WriteTotalTimeoutConstant = 0;
+       SetCommTimeouts(file->handle, &timeouts);
+
+       dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
+       if (!GetCommState(file->handle, &dcbSerialParams)) {
+               CloseHandle(file->handle);
+               free(file);
+               return NULL;
+       }
+       dcbSerialParams.BaudRate = CBR_9600;
+       dcbSerialParams.ByteSize = 8;
+       dcbSerialParams.StopBits = ONESTOPBIT;
+       dcbSerialParams.Parity = NOPARITY;
+       if (!SetCommState(file->handle, &dcbSerialParams)) {
+               CloseHandle(file->handle);
+               free(file);
+               return NULL;
+       }
+
+       return file;
+}
+
+PUBLIC void
+altos_close(struct altos_file *file)
+{
+       if (file->handle != INVALID_HANDLE_VALUE) {
+               CloseHandle(file->handle);
+               file->handle = INVALID_HANDLE_VALUE;
+       }
+}
+
+PUBLIC void
+altos_free(struct altos_file *file)
+{
+       altos_close(file);
+       free(file);
+}
+
+int
+altos_putchar(struct altos_file *file, char c)
+{
+       int     ret;
+
+       if (file->out_used == USB_BUF_SIZE) {
+               ret = altos_flush(file);
+               if (ret)
+                       return ret;
+       }
+       file->out_data[file->out_used++] = c;
+       if (file->out_used == USB_BUF_SIZE)
+               return altos_flush(file);
+       return LIBALTOS_SUCCESS;
+}
+
+int
+altos_getchar(struct altos_file *file, int timeout)
+{
+       int     ret;
+       while (file->in_read == file->in_used) {
+               if (file->handle == INVALID_HANDLE_VALUE)
+                       return LIBALTOS_ERROR;
+               ret = altos_fill(file, timeout);
+               if (ret)
+                       return ret;
+       }
+       return file->in_data[file->in_read++];
+}
+
+#endif
diff --git a/altosui/libaltos/libaltos.dylib b/altosui/libaltos/libaltos.dylib
new file mode 100755 (executable)
index 0000000..89aa12e
Binary files /dev/null and b/altosui/libaltos/libaltos.dylib differ
diff --git a/altosui/libaltos/libaltos.h b/altosui/libaltos/libaltos.h
new file mode 100644 (file)
index 0000000..6e94899
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+
+#ifndef _LIBALTOS_H_
+#define _LIBALTOS_H_
+
+#include <stdlib.h>
+
+#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+# ifndef BUILD_STATIC
+#  ifdef BUILD_DLL
+#   define PUBLIC __declspec(dllexport)
+#  else
+#   define PUBLIC __declspec(dllimport)
+#  endif
+# endif /* BUILD_STATIC */
+#endif
+
+#ifndef PUBLIC
+# define PUBLIC
+#endif
+
+#define USB_VENDOR_FSF                 0xfffe
+#define USB_VENDOR_ALTUSMETRUM         USB_VENDOR_FSF
+#define USB_PRODUCT_ALTUSMETRUM                0x000a
+#define USB_PRODUCT_TELEMETRUM         0x000b
+#define USB_PRODUCT_TELEDONGLE         0x000c
+#define USB_PRODUCT_TELETERRA          0x000d
+#define USB_PRODUCT_ALTUSMETRUM_MIN    0x000a
+#define USB_PRODUCT_ALTUSMETRUM_MAX    0x0013
+
+#define USB_IS_ALTUSMETRUM(v,p)        ((v) == USB_VENDOR_ALTUSMETRUM && \
+               (USB_PRODUCT_ALTUSMETRUM_MIN <= (p) && \
+                (p) <= USB_PRODUCT_ALTUSMETRUM_MAX))
+
+struct altos_device {
+       //%immutable;
+       int                             vendor;
+       int                             product;
+       int                             serial;
+       char                            name[256];
+       char                            path[256];
+       //%mutable;
+};
+
+#define LIBALTOS_SUCCESS       0
+#define LIBALTOS_ERROR         -1
+#define LIBALTOS_TIMEOUT       -2
+
+/* Returns 0 for success, < 0 on error */
+PUBLIC int
+altos_init(void);
+
+PUBLIC void
+altos_fini(void);
+
+PUBLIC struct altos_list *
+altos_list_start(void);
+
+/* Returns 1 for success, zero on end of list */
+PUBLIC int
+altos_list_next(struct altos_list *list, struct altos_device *device);
+
+PUBLIC void
+altos_list_finish(struct altos_list *list);
+
+PUBLIC struct altos_file *
+altos_open(struct altos_device *device);
+
+PUBLIC void
+altos_close(struct altos_file *file);
+
+PUBLIC void
+altos_free(struct altos_file *file);
+
+/* Returns < 0 for error */
+PUBLIC int
+altos_putchar(struct altos_file *file, char c);
+
+/* Returns < 0 for error */
+PUBLIC int
+altos_flush(struct altos_file *file);
+
+/* Returns < 0 for error or timeout. timeout of 0 == wait forever */
+PUBLIC int
+altos_getchar(struct altos_file *file, int timeout);
+
+#endif /* _LIBALTOS_H_ */
diff --git a/altosui/libaltos/libaltos.i0 b/altosui/libaltos/libaltos.i0
new file mode 100644 (file)
index 0000000..d06468f
--- /dev/null
@@ -0,0 +1,5 @@
+%module libaltos
+%{
+#include "libaltos.h"
+%}
+
index 54dc777af134dd8e80c4a3fbf1b5e04c6fe3779a..2850e909003cbe82e1171c8ff7be8f797a185306 100644 (file)
@@ -1 +1 @@
-SUBDIRS=lib ao-rawload ao-dbg ao-dumplog ao-bitbang ao-eeprom ao-list ao-load ao-postflight ao-view libaltos altosui
+SUBDIRS=lib ao-rawload ao-dbg ao-dumplog ao-bitbang ao-eeprom ao-list ao-load ao-postflight ao-view
diff --git a/ao-tools/altosui/.gitignore b/ao-tools/altosui/.gitignore
deleted file mode 100644 (file)
index 89be1d5..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-windows/
-linux/
-macosx/
-fat/
-Manifest.txt
-Manifest-fat.txt
-libaltosJNI
-classes
-altosui
-altosui-test
-classaltosui.stamp
-Altos-Linux-*.tar.bz2
-Altos-Mac-*.zip
-Altos-Windows-*.exe
-*.dll
-*.dylib
-*.so
-*.jar
-*.class
diff --git a/ao-tools/altosui/AltOS Package Configuration.pmdoc/01altosui-contents.xml b/ao-tools/altosui/AltOS Package Configuration.pmdoc/01altosui-contents.xml
deleted file mode 100644 (file)
index 18e00fe..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<pkg-contents spec="1.12"><f n="AltosUI.app" o="keithp" g="keithp" p="16877" pt="/Users/keithp/altos/ao-tools/altosui/AltosUI.app" m="false" t="file"><f n="Contents" o="keithp" g="keithp" p="16877"><f n="Info.plist" o="keithp" g="keithp" p="33188"/><f n="MacOS" o="keithp" g="keithp" p="16877"><f n="JavaApplicationStub" o="keithp" g="keithp" p="33133"/></f><f n="PkgInfo" o="keithp" g="keithp" p="33188"/><f n="Resources" o="keithp" g="keithp" p="16877"><f n="AltosUIIcon.icns" o="keithp" g="keithp" p="33188"/><f n="Java" o="keithp" g="keithp" p="16877"/></f></f></f></pkg-contents>
\ No newline at end of file
diff --git a/ao-tools/altosui/AltOS Package Configuration.pmdoc/01altosui.xml b/ao-tools/altosui/AltOS Package Configuration.pmdoc/01altosui.xml
deleted file mode 100644 (file)
index 6170931..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<pkgref spec="1.12" uuid="C5762664-2F26-4536-94C4-56F0FBC08D1A"><config><identifier>org.altusmetrum.altosUi.AltosUI.pkg</identifier><version>0.7</version><description></description><post-install type="none"/><installFrom relative="true" mod="true">AltosUI.app</installFrom><installTo mod="true" relocatable="true">/Applications/AltosUI.app</installTo><flags><followSymbolicLinks/></flags><packageStore type="internal"></packageStore><mod>installTo.path</mod><mod>installFrom.isRelativeType</mod><mod>version</mod><mod>parent</mod><mod>requireAuthorization</mod><mod>installTo</mod></config><contents><file-list>01altosui-contents.xml</file-list><filter>/CVS$</filter><filter>/\.svn$</filter><filter>/\.cvsignore$</filter><filter>/\.cvspass$</filter><filter>/\.DS_Store$</filter></contents></pkgref>
\ No newline at end of file
diff --git a/ao-tools/altosui/AltOS Package Configuration.pmdoc/index.xml b/ao-tools/altosui/AltOS Package Configuration.pmdoc/index.xml
deleted file mode 100644 (file)
index fabe54a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<pkmkdoc spec="1.12"><properties><title>AltOS UI</title><build>/Users/keithp/altos/ao-tools/altosui/AltosUI.pkg</build><organization>org.altusmetrum</organization><userSees ui="both"/><min-target os="3"/><domain system="true" user="true"/></properties><distribution><versions min-spec="1.000000"/><scripts></scripts></distribution><description>Install AltOS User Interface</description><contents><choice title="AltosUI" id="choice0" starts_selected="true" starts_enabled="true" starts_hidden="false"><pkgref id="org.altusmetrum.altosUi.AltosUI.pkg"/></choice></contents><resources bg-scale="tofit" bg-align="center"><locale lang="en"><resource relative="true" mod="true" type="background">altusmetrum.jpg</resource></locale></resources><flags/><item type="file">01altosui.xml</item><mod>properties.anywhereDomain</mod><mod>properties.title</mod><mod>properties.customizeOption</mod><mod>description</mod><mod>properties.userDomain</mod><mod>properties.systemDomain</mod></pkmkdoc>
\ No newline at end of file
diff --git a/ao-tools/altosui/Altos.java b/ao-tools/altosui/Altos.java
deleted file mode 100644 (file)
index 8ee94e0..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * 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.util.*;
-import java.text.*;
-
-public class Altos {
-       /* EEProm command letters */
-       static final int AO_LOG_FLIGHT = 'F';
-       static final int AO_LOG_SENSOR = 'A';
-       static final int AO_LOG_TEMP_VOLT = 'T';
-       static final int AO_LOG_DEPLOY = 'D';
-       static final int AO_LOG_STATE = 'S';
-       static final int AO_LOG_GPS_TIME = 'G';
-       static final int AO_LOG_GPS_LAT = 'N';
-       static final int AO_LOG_GPS_LON = 'W';
-       static final int AO_LOG_GPS_ALT = 'H';
-       static final int AO_LOG_GPS_SAT = 'V';
-       static final int AO_LOG_GPS_DATE = 'Y';
-
-       /* Added for header fields in eeprom files */
-       static final int AO_LOG_CONFIG_VERSION = 1000;
-       static final int AO_LOG_MAIN_DEPLOY = 1001;
-       static final int AO_LOG_APOGEE_DELAY = 1002;
-       static final int AO_LOG_RADIO_CHANNEL = 1003;
-       static final int AO_LOG_CALLSIGN = 1004;
-       static final int AO_LOG_ACCEL_CAL = 1005;
-       static final int AO_LOG_RADIO_CAL = 1006;
-       static final int AO_LOG_MANUFACTURER = 1007;
-       static final int AO_LOG_PRODUCT = 1008;
-       static final int AO_LOG_SERIAL_NUMBER = 1009;
-       static final int AO_LOG_SOFTWARE_VERSION = 1010;
-
-       /* Added to flag invalid records */
-       static final int AO_LOG_INVALID = -1;
-
-       /* Flight state numbers and names */
-       static final int ao_flight_startup = 0;
-       static final int ao_flight_idle = 1;
-       static final int ao_flight_pad = 2;
-       static final int ao_flight_boost = 3;
-       static final int ao_flight_fast = 4;
-       static final int ao_flight_coast = 5;
-       static final int ao_flight_drogue = 6;
-       static final int ao_flight_main = 7;
-       static final int ao_flight_landed = 8;
-       static final int ao_flight_invalid = 9;
-
-       static HashMap<String,Integer>  string_to_state = new HashMap<String,Integer>();
-
-       static boolean map_initialized = false;
-
-       static final int tab_elt_pad = 5;
-
-       static final Font label_font = new Font("Dialog", Font.PLAIN, 22);
-       static final Font value_font = new Font("Monospaced", Font.PLAIN, 22);
-       static final Font status_font = new Font("SansSerif", Font.BOLD, 24);
-
-       static final int text_width = 16;
-
-       static void initialize_map()
-       {
-               string_to_state.put("startup", ao_flight_startup);
-               string_to_state.put("idle", ao_flight_idle);
-               string_to_state.put("pad", ao_flight_pad);
-               string_to_state.put("boost", ao_flight_boost);
-               string_to_state.put("fast", ao_flight_fast);
-               string_to_state.put("coast", ao_flight_coast);
-               string_to_state.put("drogue", ao_flight_drogue);
-               string_to_state.put("main", ao_flight_main);
-               string_to_state.put("landed", ao_flight_landed);
-               string_to_state.put("invalid", ao_flight_invalid);
-               map_initialized = true;
-       }
-
-       static String[] state_to_string = {
-               "startup",
-               "idle",
-               "pad",
-               "boost",
-               "fast",
-               "coast",
-               "drogue",
-               "main",
-               "landed",
-               "invalid",
-       };
-
-       static public int state(String state) {
-               if (!map_initialized)
-                       initialize_map();
-               if (string_to_state.containsKey(state))
-                       return string_to_state.get(state);
-               return ao_flight_invalid;
-       }
-
-       static public String state_name(int state) {
-               if (state < 0 || state_to_string.length <= state)
-                       return "invalid";
-               return state_to_string[state];
-       }
-
-       static final int AO_GPS_VALID = (1 << 4);
-       static final int AO_GPS_RUNNING = (1 << 5);
-       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;
-       }
-
-       static String replace_extension(String input, String extension) {
-               int dot = input.lastIndexOf(".");
-               if (dot > 0)
-                       input = input.substring(0,dot);
-               return input.concat(extension);
-       }
-}
diff --git a/ao-tools/altosui/AltosAscent.java b/ao-tools/altosui/AltosAscent.java
deleted file mode 100644 (file)
index 64bdcf3..0000000
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * 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;
-
-public class AltosAscent extends JComponent implements AltosFlightDisplay {
-       GridBagLayout   layout;
-
-       public class AscentStatus {
-               JLabel          label;
-               JTextField      value;
-               AltosLights     lights;
-
-               void show(AltosState state, int crc_errors) {}
-               void reset() {
-                       value.setText("");
-                       lights.set(false);
-               }
-
-               public AscentStatus (GridBagLayout layout, int y, String text) {
-                       GridBagConstraints      c = new GridBagConstraints();
-                       c.weighty = 1;
-
-                       lights = new AltosLights();
-                       c.gridx = 0; c.gridy = y;
-                       c.anchor = GridBagConstraints.CENTER;
-                       c.fill = GridBagConstraints.VERTICAL;
-                       c.weightx = 0;
-                       layout.setConstraints(lights, c);
-                       add(lights);
-
-                       label = new JLabel(text);
-                       label.setFont(Altos.label_font);
-                       label.setHorizontalAlignment(SwingConstants.LEFT);
-                       c.gridx = 1; c.gridy = y;
-                       c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
-                       c.anchor = GridBagConstraints.WEST;
-                       c.fill = GridBagConstraints.VERTICAL;
-                       c.weightx = 0;
-                       layout.setConstraints(label, c);
-                       add(label);
-
-                       value = new JTextField(Altos.text_width);
-                       value.setFont(Altos.value_font);
-                       value.setHorizontalAlignment(SwingConstants.RIGHT);
-                       c.gridx = 2; c.gridy = y;
-                       c.gridwidth = 2;
-                       c.anchor = GridBagConstraints.WEST;
-                       c.fill = GridBagConstraints.BOTH;
-                       c.weightx = 1;
-                       layout.setConstraints(value, c);
-                       add(value);
-
-               }
-       }
-
-       public class AscentValue {
-               JLabel          label;
-               JTextField      value;
-               void show(AltosState state, int crc_errors) {}
-
-               void reset() {
-                       value.setText("");
-               }
-               public AscentValue (GridBagLayout layout, int y, String text) {
-                       GridBagConstraints      c = new GridBagConstraints();
-                       c.weighty = 1;
-
-                       label = new JLabel(text);
-                       label.setFont(Altos.label_font);
-                       label.setHorizontalAlignment(SwingConstants.LEFT);
-                       c.gridx = 1; c.gridy = y;
-                       c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
-                       c.anchor = GridBagConstraints.WEST;
-                       c.fill = GridBagConstraints.VERTICAL;
-                       c.weightx = 0;
-                       layout.setConstraints(label, c);
-                       add(label);
-
-                       value = new JTextField(Altos.text_width);
-                       value.setFont(Altos.value_font);
-                       value.setHorizontalAlignment(SwingConstants.RIGHT);
-                       c.gridx = 2; c.gridy = y;
-                       c.anchor = GridBagConstraints.WEST;
-                       c.fill = GridBagConstraints.BOTH;
-                       c.gridwidth = 2;
-                       c.weightx = 1;
-                       layout.setConstraints(value, c);
-                       add(value);
-               }
-       }
-
-       public class AscentValueHold {
-               JLabel          label;
-               JTextField      value;
-               JTextField      max_value;
-               double          max;
-
-               void show(AltosState state, int crc_errors) {}
-
-               void reset() {
-                       value.setText("");
-                       max_value.setText("");
-                       max = 0;
-               }
-
-               void show(String format, double v) {
-                       value.setText(String.format(format, v));
-                       if (v > max) {
-                               max_value.setText(String.format(format, v));
-                               max = v;
-                       }
-               }
-               public AscentValueHold (GridBagLayout layout, int y, String text) {
-                       GridBagConstraints      c = new GridBagConstraints();
-                       c.weighty = 1;
-
-                       label = new JLabel(text);
-                       label.setFont(Altos.label_font);
-                       label.setHorizontalAlignment(SwingConstants.LEFT);
-                       c.gridx = 1; c.gridy = y;
-                       c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
-                       c.anchor = GridBagConstraints.WEST;
-                       c.fill = GridBagConstraints.VERTICAL;
-                       c.weightx = 0;
-                       layout.setConstraints(label, c);
-                       add(label);
-
-                       value = new JTextField(Altos.text_width);
-                       value.setFont(Altos.value_font);
-                       value.setHorizontalAlignment(SwingConstants.RIGHT);
-                       c.gridx = 2; c.gridy = y;
-                       c.anchor = GridBagConstraints.EAST;
-                       c.fill = GridBagConstraints.BOTH;
-                       c.weightx = 1;
-                       layout.setConstraints(value, c);
-                       add(value);
-
-                       max_value = new JTextField(Altos.text_width);
-                       max_value.setFont(Altos.value_font);
-                       max_value.setHorizontalAlignment(SwingConstants.RIGHT);
-                       c.gridx = 3; c.gridy = y;
-                       c.anchor = GridBagConstraints.EAST;
-                       c.fill = GridBagConstraints.BOTH;
-                       c.weightx = 1;
-                       layout.setConstraints(max_value, c);
-                       add(max_value);
-               }
-       }
-
-
-       class Height extends AscentValueHold {
-               void show (AltosState state, int crc_errors) {
-                       show("%6.0f m", state.height);
-               }
-               public Height (GridBagLayout layout, int y) {
-                       super (layout, y, "Height");
-               }
-       }
-
-       Height  height;
-
-       class Speed extends AscentValueHold {
-               void show (AltosState state, int crc_errors) {
-                       double speed = state.speed;
-                       if (!state.ascent)
-                               speed = state.baro_speed;
-                       show("%6.0f m/s", speed);
-               }
-               public Speed (GridBagLayout layout, int y) {
-                       super (layout, y, "Speed");
-               }
-       }
-
-       Speed   speed;
-
-       class Accel extends AscentValueHold {
-               void show (AltosState state, int crc_errors) {
-                       show("%6.0f m/s²", state.acceleration);
-               }
-               public Accel (GridBagLayout layout, int y) {
-                       super (layout, y, "Acceleration");
-               }
-       }
-
-       Accel   accel;
-
-       String pos(double p, String pos, String neg) {
-               String  h = pos;
-               if (p < 0) {
-                       h = neg;
-                       p = -p;
-               }
-               int deg = (int) Math.floor(p);
-               double min = (p - Math.floor(p)) * 60.0;
-               return String.format("%s %4d° %9.6f", h, deg, min);
-       }
-
-       class Apogee extends AscentStatus {
-               void show (AltosState state, int crc_errors) {
-                       value.setText(String.format("%4.2f V", state.drogue_sense));
-                       lights.set(state.drogue_sense > 3.2);
-               }
-               public Apogee (GridBagLayout layout, int y) {
-                       super(layout, y, "Apogee Igniter Voltage");
-               }
-       }
-
-       Apogee apogee;
-
-       class Main extends AscentStatus {
-               void show (AltosState state, int crc_errors) {
-                       value.setText(String.format("%4.2f V", state.main_sense));
-                       lights.set(state.main_sense > 3.2);
-               }
-               public Main (GridBagLayout layout, int y) {
-                       super(layout, y, "Main Igniter Voltage");
-               }
-       }
-
-       Main main;
-
-       class Lat extends AscentValue {
-               void show (AltosState state, int crc_errors) {
-                       if (state.gps != null)
-                               value.setText(pos(state.gps.lat,"N", "S"));
-                       else
-                               value.setText("???");
-               }
-               public Lat (GridBagLayout layout, int y) {
-                       super (layout, y, "Latitude");
-               }
-       }
-
-       Lat lat;
-
-       class Lon extends AscentValue {
-               void show (AltosState state, int crc_errors) {
-                       if (state.gps != null)
-                               value.setText(pos(state.gps.lon,"E", "W"));
-                       else
-                               value.setText("???");
-               }
-               public Lon (GridBagLayout layout, int y) {
-                       super (layout, y, "Longitude");
-               }
-       }
-
-       Lon lon;
-
-       public void reset() {
-               lat.reset();
-               lon.reset();
-               main.reset();
-               apogee.reset();
-               height.reset();
-               speed.reset();
-               accel.reset();
-       }
-
-       public void show(AltosState state, int crc_errors) {
-               lat.show(state, crc_errors);
-               lon.show(state, crc_errors);
-               height.show(state, crc_errors);
-               main.show(state, crc_errors);
-               apogee.show(state, crc_errors);
-               speed.show(state, crc_errors);
-               accel.show(state, crc_errors);
-       }
-
-       public void labels(GridBagLayout layout, int y) {
-               GridBagConstraints      c;
-               JLabel                  cur, max;
-
-               cur = new JLabel("Current");
-               cur.setFont(Altos.label_font);
-               c = new GridBagConstraints();
-               c.gridx = 2; c.gridy = y;
-               c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
-               layout.setConstraints(cur, c);
-               add(cur);
-
-               max = new JLabel("Maximum");
-               max.setFont(Altos.label_font);
-               c.gridx = 3; c.gridy = y;
-               layout.setConstraints(max, c);
-               add(max);
-       }
-
-       public AltosAscent() {
-               layout = new GridBagLayout();
-
-               setLayout(layout);
-
-               /* Elements in ascent display:
-                *
-                * lat
-                * lon
-                * height
-                */
-               labels(layout, 0);
-               height = new Height(layout, 1);
-               speed = new Speed(layout, 2);
-               accel = new Accel(layout, 3);
-               lat = new Lat(layout, 4);
-               lon = new Lon(layout, 5);
-               apogee = new Apogee(layout, 6);
-               main = new Main(layout, 7);
-       }
-}
diff --git a/ao-tools/altosui/AltosCRCException.java b/ao-tools/altosui/AltosCRCException.java
deleted file mode 100644 (file)
index 4a529bc..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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;
-
-public class AltosCRCException extends Exception {
-       public int rssi;
-
-       public AltosCRCException (int in_rssi) {
-               rssi = in_rssi;
-       }
-}
diff --git a/ao-tools/altosui/AltosCSV.java b/ao-tools/altosui/AltosCSV.java
deleted file mode 100644 (file)
index df98b2b..0000000
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * 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.lang.*;
-import java.io.*;
-import java.text.*;
-import java.util.*;
-
-public class AltosCSV implements AltosWriter {
-       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 = 2;
-
-       /* Version 2 format:
-        *
-        * General info
-        *      version number
-        *      serial number
-        *      flight number
-        *      callsign
-        *      time (seconds since boost)
-        *      rssi
-        *      link quality
-        *
-        * Flight status
-        *      state
-        *      state name
-        *
-        * Basic sensors
-        *      acceleration (m/s²)
-        *      pressure (mBar)
-        *      altitude (m)
-        *      height (m)
-        *      accelerometer speed (m/s)
-        *      barometer speed (m/s)
-        *      temp (°C)
-        *      battery (V)
-        *      drogue (V)
-        *      main (V)
-        *
-        * GPS data
-        *      connected (1/0)
-        *      locked (1/0)
-        *      nsat (used for solution)
-        *      latitude (°)
-        *      longitude (°)
-        *      altitude (m)
-        *      year (e.g. 2010)
-        *      month (1-12)
-        *      day (1-31)
-        *      hour (0-23)
-        *      minute (0-59)
-        *      second (0-59)
-        *      from_pad_dist (m)
-        *      from_pad_azimuth (deg true)
-        *      from_pad_range (m)
-        *      from_pad_elevation (deg from horizon)
-        *      hdop
-        *
-        * GPS Sat data
-        *      C/N0 data for all 32 valid SDIDs
-        */
-
-       void write_general_header() {
-               out.printf("version,serial,flight,call,time,rssi,lqi");
-       }
-
-       void write_general(AltosRecord record) {
-               out.printf("%s, %d, %d, %s, %8.2f, %4d, %3d",
-                          ALTOS_CSV_VERSION, record.serial, record.flight, record.callsign,
-                          (double) record.time,
-                          record.rssi,
-                          record.status & 0x7f);
-       }
-
-       void write_flight_header() {
-               out.printf("state,state_name");
-       }
-
-       void write_flight(AltosRecord record) {
-               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.raw_pressure(),
-                          record.raw_altitude(),
-                          record.raw_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_range,pad_az,pad_el,hdop");
-       }
-
-       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,%9.0f,%4.0f,%4.0f,%6.1f",
-                          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,
-                          state.range,
-                          from_pad.bearing,
-                          state.elevation,
-                          gps.hdop);
-       }
-
-       void write_gps_sat_header() {
-               for(int i = 1; i <= 32; i++) {
-                       out.printf("sat%02d", i);
-                       if (i != 32)
-                               out.printf(",");
-               }
-       }
-
-       void write_gps_sat(AltosRecord record) {
-               AltosGPS        gps = record.gps;
-               for(int i = 1; i <= 32; i++) {
-                       int     c_n0 = 0;
-                       if (gps != null && gps.cc_gps_sat != null) {
-                               for(int j = 0; j < gps.cc_gps_sat.length; j++)
-                                       if (gps.cc_gps_sat[j].svid == i) {
-                                               c_n0 = gps.cc_gps_sat[j].c_n0;
-                                               break;
-                                       }
-                       }
-                       out.printf ("%3d", c_n0);
-                       if (i != 32)
-                               out.printf(",");
-               }
-       }
-
-       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(","); write_gps_sat_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(",");
-               write_gps_sat(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;
-               }
-               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(AltosRecordIterable iterable) {
-               iterable.write_comments(out());
-               for (AltosRecord r : iterable)
-                       write(r);
-       }
-
-       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
deleted file mode 100644 (file)
index e1b6002..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * 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;
-
-public class AltosCSVUI
-       extends JDialog
-       implements ActionListener
-{
-       JFileChooser            csv_chooser;
-       JPanel                  accessory;
-       JComboBox               combo_box;
-       AltosRecordIterable     iterable;
-       AltosWriter             writer;
-
-       static String[]         combo_box_items = { "Comma Separated Values (.CSV)", "Googleearth Data (.KML)" };
-
-       void set_default_file() {
-               File    current = csv_chooser.getSelectedFile();
-               String  current_name = current.getName();
-               String  new_name = null;
-               String  selected = (String) combo_box.getSelectedItem();
-
-               if (selected.contains("CSV"))
-                       new_name = Altos.replace_extension(current_name, ".csv");
-               else if (selected.contains("KML"))
-                       new_name = Altos.replace_extension(current_name, ".kml");
-               if (new_name != null)
-                       csv_chooser.setSelectedFile(new File(new_name));
-       }
-
-       public void actionPerformed(ActionEvent e) {
-               if (e.getActionCommand().equals("comboBoxChanged"))
-                       set_default_file();
-       }
-
-       public AltosCSVUI(JFrame frame, AltosRecordIterable in_iterable, File source_file) {
-               iterable = in_iterable;
-               csv_chooser = new JFileChooser(source_file);
-
-               accessory = new JPanel();
-               accessory.setLayout(new GridBagLayout());
-
-               GridBagConstraints      c = new GridBagConstraints();
-               c.fill = GridBagConstraints.NONE;
-               c.weightx = 1;
-               c.weighty = 0;
-               c.insets = new Insets (4, 4, 4, 4);
-
-               JLabel accessory_label = new JLabel("Export File Type");
-               c.gridx = 0;
-               c.gridy = 0;
-               accessory.add(accessory_label, c);
-
-               combo_box = new JComboBox(combo_box_items);
-               combo_box.addActionListener(this);
-               c.gridx = 0;
-               c.gridy = 1;
-               accessory.add(combo_box, c);
-
-               csv_chooser.setAccessory(accessory);
-               csv_chooser.setSelectedFile(source_file);
-               set_default_file();
-               int ret = csv_chooser.showSaveDialog(frame);
-               if (ret == JFileChooser.APPROVE_OPTION) {
-                       File file = csv_chooser.getSelectedFile();
-                       String type = (String) combo_box.getSelectedItem();
-                       try {
-                               if (type.contains("CSV"))
-                                       writer = new AltosCSV(file);
-                               else
-                                       writer = new AltosKML(file);
-                               writer.write(iterable);
-                               writer.close();
-                       } catch (FileNotFoundException ee) {
-                               JOptionPane.showMessageDialog(frame,
-                                                             file.getName(),
-                                                             "Cannot open file",
-                                                             JOptionPane.ERROR_MESSAGE);
-                       }
-               }
-       }
-}
diff --git a/ao-tools/altosui/AltosChannelMenu.java b/ao-tools/altosui/AltosChannelMenu.java
deleted file mode 100644 (file)
index abbb86f..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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;
-
-public class AltosChannelMenu extends JComboBox implements ActionListener {
-       int                             channel;
-
-       public AltosChannelMenu(int current_channel) {
-
-               channel = current_channel;
-
-               for (int c = 0; c <= 9; c++)
-                       addItem(String.format("Channel %1d (%7.3fMHz)", c, 434.550 + c * 0.1));
-               setSelectedIndex(channel);
-               setMaximumRowCount(10);
-       }
-
-}
diff --git a/ao-tools/altosui/AltosConfig.java b/ao-tools/altosui/AltosConfig.java
deleted file mode 100644 (file)
index 1c42870..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * 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.*;
-
-import libaltosJNI.*;
-
-public class AltosConfig implements Runnable, ActionListener {
-
-       class int_ref {
-               int     value;
-
-               public int get() {
-                       return value;
-               }
-               public void set(int i) {
-                       value = i;
-               }
-               public int_ref(int i) {
-                       value = i;
-               }
-       }
-
-       class string_ref {
-               String  value;
-
-               public String get() {
-                       return value;
-               }
-               public void set(String i) {
-                       value = i;
-               }
-               public string_ref(String i) {
-                       value = i;
-               }
-       }
-
-       JFrame          owner;
-       AltosDevice     device;
-       AltosSerial     serial_line;
-       boolean         remote;
-       Thread          config_thread;
-       int_ref         serial;
-       int_ref         main_deploy;
-       int_ref         apogee_delay;
-       int_ref         radio_channel;
-       int_ref         radio_calibration;
-       string_ref      version;
-       string_ref      product;
-       string_ref      callsign;
-       AltosConfigUI   config_ui;
-       boolean         serial_started;
-
-       boolean get_int(String line, String label, int_ref x) {
-               if (line.startsWith(label)) {
-                       try {
-                               String tail = line.substring(label.length()).trim();
-                               String[] tokens = tail.split("\\s+");
-                               if (tokens.length > 0) {
-                                       int     i = Integer.parseInt(tokens[0]);
-                                       x.set(i);
-                                       return true;
-                               }
-                       } catch (NumberFormatException ne) {
-                       }
-               }
-               return false;
-       }
-
-       boolean get_string(String line, String label, string_ref s) {
-               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);
-                       s.set(quoted);
-                       return true;
-               } else {
-                       return false;
-               }
-       }
-
-       void start_serial() throws InterruptedException {
-               serial_started = true;
-               if (remote) {
-                       serial_line.set_radio();
-                       serial_line.printf("p\nE 0\n");
-                       serial_line.flush_input();
-               }
-       }
-
-       void stop_serial() throws InterruptedException {
-               if (!serial_started)
-                       return;
-               serial_started = false;
-               if (remote) {
-                       serial_line.printf("~");
-                       serial_line.flush_output();
-               }
-       }
-
-       void get_data() throws InterruptedException, TimeoutException {
-               try {
-                       start_serial();
-                       serial_line.printf("c s\nv\n");
-                       for (;;) {
-                               String line = serial_line.get_reply(5000);
-                               if (line == null)
-                                       throw new TimeoutException();
-                               get_int(line, "serial-number", serial);
-                               get_int(line, "Main deploy:", main_deploy);
-                               get_int(line, "Apogee delay:", apogee_delay);
-                               get_int(line, "Radio channel:", radio_channel);
-                               get_int(line, "Radio cal:", radio_calibration);
-                               get_string(line, "Callsign:", callsign);
-                               get_string(line,"software-version", version);
-                               get_string(line,"product", product);
-
-                               /* signals the end of the version info */
-                               if (line.startsWith("software-version"))
-                                       break;
-                       }
-               } finally {
-                       stop_serial();
-               }
-       }
-
-       void init_ui () throws InterruptedException, TimeoutException {
-               config_ui = new AltosConfigUI(owner, remote);
-               config_ui.addActionListener(this);
-               set_ui();
-       }
-
-       void abort() {
-               JOptionPane.showMessageDialog(owner,
-                                             String.format("Connection to \"%s\" failed",
-                                                           device.toShortString()),
-                                             "Connection Failed",
-                                             JOptionPane.ERROR_MESSAGE);
-               try {
-                       stop_serial();
-               } catch (InterruptedException ie) {
-               }
-               serial_line.close();
-               serial_line = null;
-       }
-
-       void set_ui() throws InterruptedException, TimeoutException {
-               if (serial_line != null)
-                       get_data();
-               config_ui.set_serial(serial.get());
-               config_ui.set_product(product.get());
-               config_ui.set_version(version.get());
-               config_ui.set_main_deploy(main_deploy.get());
-               config_ui.set_apogee_delay(apogee_delay.get());
-               config_ui.set_radio_channel(radio_channel.get());
-               config_ui.set_radio_calibration(radio_calibration.get());
-               config_ui.set_callsign(callsign.get());
-               config_ui.set_clean();
-       }
-
-       void run_dialog() {
-       }
-
-       void save_data() {
-               main_deploy.set(config_ui.main_deploy());
-               apogee_delay.set(config_ui.apogee_delay());
-               radio_channel.set(config_ui.radio_channel());
-               radio_calibration.set(config_ui.radio_calibration());
-               callsign.set(config_ui.callsign());
-               try {
-                       start_serial();
-                       serial_line.printf("c m %d\n", main_deploy.get());
-                       serial_line.printf("c d %d\n", apogee_delay.get());
-                       if (!remote) {
-                               serial_line.printf("c r %d\n", radio_channel.get());
-                               serial_line.printf("c f %d\n", radio_calibration.get());
-                       }
-                       serial_line.printf("c c %s\n", callsign.get());
-                       serial_line.printf("c w\n");
-               } catch (InterruptedException ie) {
-               } finally {
-                       try {
-                               stop_serial();
-                       } catch (InterruptedException ie) {
-                       }
-               }
-       }
-
-       public void actionPerformed(ActionEvent e) {
-               String  cmd = e.getActionCommand();
-               try {
-                       if (cmd.equals("Save")) {
-                               save_data();
-                               set_ui();
-                       } else if (cmd.equals("Reset")) {
-                               set_ui();
-                       } else if (cmd.equals("Reboot")) {
-                               if (serial_line != null) {
-                                       start_serial();
-                                       serial_line.printf("r eboot\n");
-                                       serial_line.flush_output();
-                                       stop_serial();
-                                       serial_line.close();
-                               }
-                       } else if (cmd.equals("Close")) {
-                               if (serial_line != null)
-                                       serial_line.close();
-                       }
-               } catch (InterruptedException ie) {
-                       abort();
-               } catch (TimeoutException te) {
-                       abort();
-               }
-       }
-
-       public void run () {
-               try {
-                       init_ui();
-                       config_ui.make_visible();
-               } catch (InterruptedException ie) {
-                       abort();
-               } catch (TimeoutException te) {
-                       abort();
-               }
-       }
-
-       public AltosConfig(JFrame given_owner) {
-               owner = given_owner;
-
-               serial = new int_ref(0);
-               main_deploy = new int_ref(250);
-               apogee_delay = new int_ref(0);
-               radio_channel = new int_ref(0);
-               radio_calibration = new int_ref(1186611);
-               callsign = new string_ref("N0CALL");
-               version = new string_ref("unknown");
-               product = new string_ref("unknown");
-
-               device = AltosDeviceDialog.show(owner, AltosDevice.product_any);
-               if (device != null) {
-                       try {
-                               serial_line = new AltosSerial(device);
-                               if (!device.matchProduct(AltosDevice.product_telemetrum))
-                                       remote = true;
-                               config_thread = new Thread(this);
-                               config_thread.start();
-                       } catch (FileNotFoundException ee) {
-                               JOptionPane.showMessageDialog(owner,
-                                                             String.format("Cannot open device \"%s\"",
-                                                                           device.toShortString()),
-                                                             "Cannot open target device",
-                                                             JOptionPane.ERROR_MESSAGE);
-                       } catch (AltosSerialInUseException si) {
-                               JOptionPane.showMessageDialog(owner,
-                                                             String.format("Device \"%s\" already in use",
-                                                                           device.toShortString()),
-                                                             "Device in use",
-                                                             JOptionPane.ERROR_MESSAGE);
-                       } catch (IOException ee) {
-                               JOptionPane.showMessageDialog(owner,
-                                                             device.toShortString(),
-                                                             ee.getLocalizedMessage(),
-                                                             JOptionPane.ERROR_MESSAGE);
-                       }
-               }
-       }
-}
\ No newline at end of file
diff --git a/ao-tools/altosui/AltosConfigUI.java b/ao-tools/altosui/AltosConfigUI.java
deleted file mode 100644 (file)
index cfa5d7b..0000000
+++ /dev/null
@@ -1,466 +0,0 @@
-/*
- * 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 javax.swing.event.*;
-import java.io.*;
-import java.util.*;
-import java.text.*;
-import java.util.prefs.*;
-import java.util.concurrent.LinkedBlockingQueue;
-
-import libaltosJNI.*;
-
-public class AltosConfigUI
-       extends JDialog
-       implements ActionListener, ItemListener, DocumentListener
-{
-
-       Container       pane;
-       Box             box;
-       JLabel          product_label;
-       JLabel          version_label;
-       JLabel          serial_label;
-       JLabel          main_deploy_label;
-       JLabel          apogee_delay_label;
-       JLabel          radio_channel_label;
-       JLabel          radio_calibration_label;
-       JLabel          callsign_label;
-
-       public boolean          dirty;
-
-       JFrame          owner;
-       JLabel          product_value;
-       JLabel          version_value;
-       JLabel          serial_value;
-       JComboBox       main_deploy_value;
-       JComboBox       apogee_delay_value;
-       JComboBox       radio_channel_value;
-       JTextField      radio_calibration_value;
-       JTextField      callsign_value;
-
-       JButton         save;
-       JButton         reset;
-       JButton         reboot;
-       JButton         close;
-
-       ActionListener  listener;
-
-       static String[] main_deploy_values = {
-               "100", "150", "200", "250", "300", "350",
-               "400", "450", "500"
-       };
-
-       static String[] apogee_delay_values = {
-               "0", "1", "2", "3", "4", "5"
-       };
-
-       static String[] radio_channel_values = new String[10];
-               {
-                       for (int i = 0; i <= 9; i++)
-                               radio_channel_values[i] = String.format("Channel %1d (%7.3fMHz)",
-                                                                       i, 434.550 + i * 0.1);
-               }
-
-       /* A window listener to catch closing events and tell the config code */
-       class ConfigListener extends WindowAdapter {
-               AltosConfigUI   ui;
-
-               public ConfigListener(AltosConfigUI this_ui) {
-                       ui = this_ui;
-               }
-
-               public void windowClosing(WindowEvent e) {
-                       ui.actionPerformed(new ActionEvent(e.getSource(),
-                                                          ActionEvent.ACTION_PERFORMED,
-                                                          "Close"));
-               }
-       }
-
-       /* Build the UI using a grid bag */
-       public AltosConfigUI(JFrame in_owner, boolean remote) {
-               super (in_owner, "Configure TeleMetrum", false);
-
-               owner = in_owner;
-               GridBagConstraints c;
-
-               Insets il = new Insets(4,4,4,4);
-               Insets ir = new Insets(4,4,4,4);
-
-               pane = getContentPane();
-               pane.setLayout(new GridBagLayout());
-
-               /* Product */
-               c = new GridBagConstraints();
-               c.gridx = 0; c.gridy = 0;
-               c.gridwidth = 4;
-               c.fill = GridBagConstraints.NONE;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = il;
-               product_label = new JLabel("Product:");
-               pane.add(product_label, c);
-
-               c = new GridBagConstraints();
-               c.gridx = 4; c.gridy = 0;
-               c.gridwidth = 4;
-               c.fill = GridBagConstraints.HORIZONTAL;
-               c.weightx = 1;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = ir;
-               product_value = new JLabel("");
-               pane.add(product_value, c);
-
-               /* Version */
-               c = new GridBagConstraints();
-               c.gridx = 0; c.gridy = 1;
-               c.gridwidth = 4;
-               c.fill = GridBagConstraints.NONE;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = il;
-               c.ipady = 5;
-               version_label = new JLabel("Software version:");
-               pane.add(version_label, c);
-
-               c = new GridBagConstraints();
-               c.gridx = 4; c.gridy = 1;
-               c.gridwidth = 4;
-               c.fill = GridBagConstraints.HORIZONTAL;
-               c.weightx = 1;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = ir;
-               c.ipady = 5;
-               version_value = new JLabel("");
-               pane.add(version_value, c);
-
-               /* Serial */
-               c = new GridBagConstraints();
-               c.gridx = 0; c.gridy = 2;
-               c.gridwidth = 4;
-               c.fill = GridBagConstraints.NONE;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = il;
-               c.ipady = 5;
-               serial_label = new JLabel("Serial:");
-               pane.add(serial_label, c);
-
-               c = new GridBagConstraints();
-               c.gridx = 4; c.gridy = 2;
-               c.gridwidth = 4;
-               c.fill = GridBagConstraints.HORIZONTAL;
-               c.weightx = 1;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = ir;
-               c.ipady = 5;
-               serial_value = new JLabel("");
-               pane.add(serial_value, c);
-
-               /* Main deploy */
-               c = new GridBagConstraints();
-               c.gridx = 0; c.gridy = 3;
-               c.gridwidth = 4;
-               c.fill = GridBagConstraints.NONE;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = il;
-               c.ipady = 5;
-               main_deploy_label = new JLabel("Main Deploy Altitude(m):");
-               pane.add(main_deploy_label, c);
-
-               c = new GridBagConstraints();
-               c.gridx = 4; c.gridy = 3;
-               c.gridwidth = 4;
-               c.fill = GridBagConstraints.HORIZONTAL;
-               c.weightx = 1;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = ir;
-               c.ipady = 5;
-               main_deploy_value = new JComboBox(main_deploy_values);
-               main_deploy_value.setEditable(true);
-               main_deploy_value.addItemListener(this);
-               pane.add(main_deploy_value, c);
-
-               /* Apogee delay */
-               c = new GridBagConstraints();
-               c.gridx = 0; c.gridy = 4;
-               c.gridwidth = 4;
-               c.fill = GridBagConstraints.NONE;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = il;
-               c.ipady = 5;
-               apogee_delay_label = new JLabel("Apogee Delay(s):");
-               pane.add(apogee_delay_label, c);
-
-               c = new GridBagConstraints();
-               c.gridx = 4; c.gridy = 4;
-               c.gridwidth = 4;
-               c.fill = GridBagConstraints.HORIZONTAL;
-               c.weightx = 1;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = ir;
-               c.ipady = 5;
-               apogee_delay_value = new JComboBox(apogee_delay_values);
-               apogee_delay_value.setEditable(true);
-               apogee_delay_value.addItemListener(this);
-               pane.add(apogee_delay_value, c);
-
-               /* Radio channel */
-               c = new GridBagConstraints();
-               c.gridx = 0; c.gridy = 5;
-               c.gridwidth = 4;
-               c.fill = GridBagConstraints.NONE;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = il;
-               c.ipady = 5;
-               radio_channel_label = new JLabel("Radio Channel:");
-               pane.add(radio_channel_label, c);
-
-               c = new GridBagConstraints();
-               c.gridx = 4; c.gridy = 5;
-               c.gridwidth = 4;
-               c.fill = GridBagConstraints.HORIZONTAL;
-               c.weightx = 1;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = ir;
-               c.ipady = 5;
-               radio_channel_value = new JComboBox(radio_channel_values);
-               radio_channel_value.setEditable(false);
-               radio_channel_value.addItemListener(this);
-               if (remote)
-                       radio_channel_value.setEnabled(false);
-               pane.add(radio_channel_value, c);
-
-               /* Radio Calibration */
-               c = new GridBagConstraints();
-               c.gridx = 0; c.gridy = 6;
-               c.gridwidth = 4;
-               c.fill = GridBagConstraints.NONE;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = il;
-               c.ipady = 5;
-               radio_calibration_label = new JLabel("RF Calibration:");
-               pane.add(radio_calibration_label, c);
-
-               c = new GridBagConstraints();
-               c.gridx = 4; c.gridy = 6;
-               c.gridwidth = 4;
-               c.fill = GridBagConstraints.HORIZONTAL;
-               c.weightx = 1;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = ir;
-               c.ipady = 5;
-               radio_calibration_value = new JTextField(String.format("%d", 1186611));
-               radio_calibration_value.getDocument().addDocumentListener(this);
-               if (remote)
-                       radio_calibration_value.setEnabled(false);
-               pane.add(radio_calibration_value, c);
-
-               /* Callsign */
-               c = new GridBagConstraints();
-               c.gridx = 0; c.gridy = 7;
-               c.gridwidth = 4;
-               c.fill = GridBagConstraints.NONE;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = il;
-               c.ipady = 5;
-               callsign_label = new JLabel("Callsign:");
-               pane.add(callsign_label, c);
-
-               c = new GridBagConstraints();
-               c.gridx = 4; c.gridy = 7;
-               c.gridwidth = 4;
-               c.fill = GridBagConstraints.HORIZONTAL;
-               c.weightx = 1;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = ir;
-               c.ipady = 5;
-               callsign_value = new JTextField(AltosPreferences.callsign());
-               callsign_value.getDocument().addDocumentListener(this);
-               pane.add(callsign_value, c);
-
-               /* Buttons */
-               c = new GridBagConstraints();
-               c.gridx = 0; c.gridy = 8;
-               c.gridwidth = 2;
-               c.fill = GridBagConstraints.NONE;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = il;
-               save = new JButton("Save");
-               pane.add(save, c);
-               save.addActionListener(this);
-               save.setActionCommand("Save");
-
-               c = new GridBagConstraints();
-               c.gridx = 2; c.gridy = 8;
-               c.gridwidth = 2;
-               c.fill = GridBagConstraints.NONE;
-               c.anchor = GridBagConstraints.CENTER;
-               c.insets = il;
-               reset = new JButton("Reset");
-               pane.add(reset, c);
-               reset.addActionListener(this);
-               reset.setActionCommand("Reset");
-
-               c = new GridBagConstraints();
-               c.gridx = 4; c.gridy = 8;
-               c.gridwidth = 2;
-               c.fill = GridBagConstraints.NONE;
-               c.anchor = GridBagConstraints.CENTER;
-               c.insets = il;
-               reboot = new JButton("Reboot");
-               pane.add(reboot, c);
-               reboot.addActionListener(this);
-               reboot.setActionCommand("Reboot");
-
-               c = new GridBagConstraints();
-               c.gridx = 6; c.gridy = 8;
-               c.gridwidth = 2;
-               c.fill = GridBagConstraints.NONE;
-               c.anchor = GridBagConstraints.LINE_END;
-               c.insets = il;
-               close = new JButton("Close");
-               pane.add(close, c);
-               close.addActionListener(this);
-               close.setActionCommand("Close");
-
-               addWindowListener(new ConfigListener(this));
-       }
-
-       /* Once the initial values are set, the config code will show the dialog */
-       public void make_visible() {
-               pack();
-               setLocationRelativeTo(owner);
-               setVisible(true);
-       }
-
-       /* If any values have been changed, confirm before closing */
-       public boolean check_dirty(String operation) {
-               if (dirty) {
-                       Object[] options = { String.format("%s anyway", operation), "Keep editing" };
-                       int i;
-                       i = JOptionPane.showOptionDialog(this,
-                                                        String.format("Configuration modified. %s anyway?", operation),
-                                                        "Configuration Modified",
-                                                        JOptionPane.DEFAULT_OPTION,
-                                                        JOptionPane.WARNING_MESSAGE,
-                                                        null, options, options[1]);
-                       if (i != 0)
-                               return false;
-               }
-               return true;
-       }
-
-       /* Listen for events from our buttons */
-       public void actionPerformed(ActionEvent e) {
-               String  cmd = e.getActionCommand();
-
-               if (cmd.equals("Close") || cmd.equals("Reboot"))
-                       if (!check_dirty(cmd))
-                               return;
-               listener.actionPerformed(e);
-               if (cmd.equals("Close") || cmd.equals("Reboot")) {
-                       setVisible(false);
-                       dispose();
-               }
-               dirty = false;
-       }
-
-       /* ItemListener interface method */
-       public void itemStateChanged(ItemEvent e) {
-               dirty = true;
-       }
-
-       /* DocumentListener interface methods */
-       public void changedUpdate(DocumentEvent e) {
-               dirty = true;
-       }
-
-       public void insertUpdate(DocumentEvent e) {
-               dirty = true;
-       }
-
-       public void removeUpdate(DocumentEvent e) {
-               dirty = true;
-       }
-
-       /* Let the config code hook on a listener */
-       public void addActionListener(ActionListener l) {
-               listener = l;
-       }
-
-       /* set and get all of the dialog values */
-       public void set_product(String product) {
-               product_value.setText(product);
-       }
-
-       public void set_version(String version) {
-               version_value.setText(version);
-       }
-
-       public void set_serial(int serial) {
-               serial_value.setText(String.format("%d", serial));
-       }
-
-       public void set_main_deploy(int new_main_deploy) {
-               main_deploy_value.setSelectedItem(Integer.toString(new_main_deploy));
-       }
-
-       public int main_deploy() {
-               return Integer.parseInt(main_deploy_value.getSelectedItem().toString());
-       }
-
-       public void set_apogee_delay(int new_apogee_delay) {
-               apogee_delay_value.setSelectedItem(Integer.toString(new_apogee_delay));
-       }
-
-       public int apogee_delay() {
-               return Integer.parseInt(apogee_delay_value.getSelectedItem().toString());
-       }
-
-       public void set_radio_channel(int new_radio_channel) {
-               radio_channel_value.setSelectedIndex(new_radio_channel);
-       }
-
-       public int radio_channel() {
-               return radio_channel_value.getSelectedIndex();
-       }
-
-       public void set_radio_calibration(int new_radio_calibration) {
-               radio_calibration_value.setText(String.format("%d", new_radio_calibration));
-       }
-
-       public int radio_calibration() {
-               return Integer.parseInt(radio_calibration_value.getText());
-       }
-
-       public void set_callsign(String new_callsign) {
-               callsign_value.setText(new_callsign);
-       }
-
-       public String callsign() {
-               return callsign_value.getText();
-       }
-
-       public void set_clean() {
-               dirty = false;
-       }
-
- }
\ No newline at end of file
diff --git a/ao-tools/altosui/AltosConfigureUI.java b/ao-tools/altosui/AltosConfigureUI.java
deleted file mode 100644 (file)
index 153c59f..0000000
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * 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 javax.swing.event.*;
-import java.io.*;
-import java.util.*;
-import java.text.*;
-import java.util.prefs.*;
-import java.util.concurrent.LinkedBlockingQueue;
-
-public class AltosConfigureUI
-       extends JDialog
-       implements DocumentListener
-{
-       JFrame          owner;
-       AltosVoice      voice;
-       Container       pane;
-
-       JRadioButton    enable_voice;
-       JButton         test_voice;
-       JButton         close;
-
-       JButton         configure_log;
-       JTextField      log_directory;
-
-       JLabel          callsign_label;
-       JTextField      callsign_value;
-
-       /* DocumentListener interface methods */
-       public void changedUpdate(DocumentEvent e) {
-               AltosPreferences.set_callsign(callsign_value.getText());
-       }
-
-       public void insertUpdate(DocumentEvent e) {
-               changedUpdate(e);
-       }
-
-       public void removeUpdate(DocumentEvent e) {
-               changedUpdate(e);
-       }
-
-       public AltosConfigureUI(JFrame in_owner, AltosVoice in_voice) {
-               super(in_owner, "Configure AltosUI", false);
-
-               GridBagConstraints      c;
-
-               Insets insets = new Insets(4, 4, 4, 4);
-
-               owner = in_owner;
-               voice = in_voice;
-               pane = getContentPane();
-               pane.setLayout(new GridBagLayout());
-
-               c = new GridBagConstraints();
-               c.insets = insets;
-               c.fill = GridBagConstraints.NONE;
-               c.anchor = GridBagConstraints.WEST;
-
-               /* Nice label at the top */
-               c.gridx = 0;
-               c.gridy = 0;
-               c.gridwidth = 3;
-               c.fill = GridBagConstraints.NONE;
-               c.anchor = GridBagConstraints.CENTER;
-               pane.add(new JLabel ("Configure AltOS UI"), c);
-
-               /* Voice settings */
-               c.gridx = 0;
-               c.gridy = 1;
-               c.gridwidth = 1;
-               c.fill = GridBagConstraints.NONE;
-               c.anchor = GridBagConstraints.WEST;
-               pane.add(new JLabel("Voice"), c);
-
-               enable_voice = new JRadioButton("Enable", AltosPreferences.voice());
-               enable_voice.addActionListener(new ActionListener() {
-                               public void actionPerformed(ActionEvent e) {
-                                       JRadioButton item = (JRadioButton) e.getSource();
-                                       boolean enabled = item.isSelected();
-                                       AltosPreferences.set_voice(enabled);
-                                       if (enabled)
-                                               voice.speak_always("Enable voice.");
-                                       else
-                                               voice.speak_always("Disable voice.");
-                               }
-                       });
-               c.gridx = 1;
-               c.gridy = 1;
-               c.gridwidth = 1;
-               c.weightx = 1;
-               c.fill = GridBagConstraints.NONE;
-               c.anchor = GridBagConstraints.WEST;
-               pane.add(enable_voice, c);
-
-               c.gridx = 2;
-               c.gridy = 1;
-               c.gridwidth = 1;
-               c.weightx = 1;
-               c.fill = GridBagConstraints.NONE;
-               c.anchor = GridBagConstraints.EAST;
-               test_voice = new JButton("Test Voice");
-               test_voice.addActionListener(new ActionListener() {
-                               public void actionPerformed(ActionEvent e) {
-                                       voice.speak("That's one small step for man; one giant leap for mankind.");
-                               }
-                       });
-               pane.add(test_voice, c);
-
-               /* Log directory settings */
-               c.gridx = 0;
-               c.gridy = 2;
-               c.gridwidth = 1;
-               c.fill = GridBagConstraints.NONE;
-               c.anchor = GridBagConstraints.WEST;
-               pane.add(new JLabel("Log Directory"), c);
-
-               configure_log = new JButton(AltosPreferences.logdir().getPath());
-               configure_log.addActionListener(new ActionListener() {
-                               public void actionPerformed(ActionEvent e) {
-                                       AltosPreferences.ConfigureLog();
-                                       configure_log.setText(AltosPreferences.logdir().getPath());
-                               }
-                       });
-               c.gridx = 1;
-               c.gridy = 2;
-               c.gridwidth = 2;
-               c.fill = GridBagConstraints.BOTH;
-               c.anchor = GridBagConstraints.WEST;
-               pane.add(configure_log, c);
-
-               /* Callsign setting */
-               c.gridx = 0;
-               c.gridy = 3;
-               c.gridwidth = 1;
-               c.fill = GridBagConstraints.NONE;
-               c.anchor = GridBagConstraints.WEST;
-               pane.add(new JLabel("Callsign"), c);
-
-               callsign_value = new JTextField(AltosPreferences.callsign());
-               callsign_value.getDocument().addDocumentListener(this);
-               c.gridx = 1;
-               c.gridy = 3;
-               c.gridwidth = 2;
-               c.fill = GridBagConstraints.BOTH;
-               c.anchor = GridBagConstraints.WEST;
-               pane.add(callsign_value, c);
-
-               /* And a close button at the bottom */
-               close = new JButton("Close");
-               close.addActionListener(new ActionListener() {
-                               public void actionPerformed(ActionEvent e) {
-                                       setVisible(false);
-                               }
-                       });
-               c.gridx = 0;
-               c.gridy = 4;
-               c.gridwidth = 3;
-               c.fill = GridBagConstraints.NONE;
-               c.anchor = GridBagConstraints.CENTER;
-               pane.add(close, c);
-
-               pack();
-               setLocationRelativeTo(owner);
-               setVisible(true);
-       }
-}
diff --git a/ao-tools/altosui/AltosConvert.java b/ao-tools/altosui/AltosConvert.java
deleted file mode 100644 (file)
index 8cc1df2..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * 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.
- */
-
-/*
- * Sensor data conversion functions
- */
-package altosui;
-
-public class AltosConvert {
-       /*
-        * Pressure Sensor Model, version 1.1
-        *
-        * written by Holly Grimes
-        *
-        * Uses the International Standard Atmosphere as described in
-        *   "A Quick Derivation relating altitude to air pressure" (version 1.03)
-        *    from the Portland State Aerospace Society, except that the atmosphere
-        *    is divided into layers with each layer having a different lapse rate.
-        *
-        * Lapse rate data for each layer was obtained from Wikipedia on Sept. 1, 2007
-        *    at site <http://en.wikipedia.org/wiki/International_Standard_Atmosphere
-        *
-        * Height measurements use the local tangent plane.  The postive z-direction is up.
-        *
-        * All measurements are given in SI units (Kelvin, Pascal, meter, meters/second^2).
-        *   The lapse rate is given in Kelvin/meter, the gas constant for air is given
-        *   in Joules/(kilogram-Kelvin).
-        */
-
-       static final double GRAVITATIONAL_ACCELERATION = -9.80665;
-       static final double AIR_GAS_CONSTANT            = 287.053;
-       static final double NUMBER_OF_LAYERS            = 7;
-       static final double MAXIMUM_ALTITUDE            = 84852.0;
-       static final double MINIMUM_PRESSURE            = 0.3734;
-       static final double LAYER0_BASE_TEMPERATURE     = 288.15;
-       static final double LAYER0_BASE_PRESSURE        = 101325;
-
-       /* lapse rate and base altitude for each layer in the atmosphere */
-       static final double[] lapse_rate = {
-               -0.0065, 0.0, 0.001, 0.0028, 0.0, -0.0028, -0.002
-       };
-
-       static final int[] base_altitude = {
-               0, 11000, 20000, 32000, 47000, 51000, 71000
-       };
-
-       /* outputs atmospheric pressure associated with the given altitude.
-        * altitudes are measured with respect to the mean sea level
-        */
-       static double
-       altitude_to_pressure(double altitude)
-       {
-               double base_temperature = LAYER0_BASE_TEMPERATURE;
-               double base_pressure = LAYER0_BASE_PRESSURE;
-
-               double pressure;
-               double base; /* base for function to determine pressure */
-               double exponent; /* exponent for function to determine pressure */
-               int layer_number; /* identifies layer in the atmosphere */
-               double delta_z; /* difference between two altitudes */
-
-               if (altitude > MAXIMUM_ALTITUDE) /* FIX ME: use sensor data to improve model */
-                       return 0;
-
-               /* calculate the base temperature and pressure for the atmospheric layer
-                  associated with the inputted altitude */
-               for(layer_number = 0; layer_number < NUMBER_OF_LAYERS - 1 && altitude > base_altitude[layer_number + 1]; layer_number++) {
-                       delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number];
-                       if (lapse_rate[layer_number] == 0.0) {
-                               exponent = GRAVITATIONAL_ACCELERATION * delta_z
-                                       / AIR_GAS_CONSTANT / base_temperature;
-                               base_pressure *= Math.exp(exponent);
-                       }
-                       else {
-                               base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0;
-                               exponent = GRAVITATIONAL_ACCELERATION /
-                                       (AIR_GAS_CONSTANT * lapse_rate[layer_number]);
-                               base_pressure *= Math.pow(base, exponent);
-                       }
-                       base_temperature += delta_z * lapse_rate[layer_number];
-               }
-
-               /* calculate the pressure at the inputted altitude */
-               delta_z = altitude - base_altitude[layer_number];
-               if (lapse_rate[layer_number] == 0.0) {
-                       exponent = GRAVITATIONAL_ACCELERATION * delta_z
-                               / AIR_GAS_CONSTANT / base_temperature;
-                       pressure = base_pressure * Math.exp(exponent);
-               }
-               else {
-                       base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0;
-                       exponent = GRAVITATIONAL_ACCELERATION /
-                               (AIR_GAS_CONSTANT * lapse_rate[layer_number]);
-                       pressure = base_pressure * Math.pow(base, exponent);
-               }
-
-               return pressure;
-       }
-
-
-/* outputs the altitude associated with the given pressure. the altitude
-   returned is measured with respect to the mean sea level */
-       static double
-       pressure_to_altitude(double pressure)
-       {
-
-               double next_base_temperature = LAYER0_BASE_TEMPERATURE;
-               double next_base_pressure = LAYER0_BASE_PRESSURE;
-
-               double altitude;
-               double base_pressure;
-               double base_temperature;
-               double base; /* base for function to determine base pressure of next layer */
-               double exponent; /* exponent for function to determine base pressure
-                                   of next layer */
-               double coefficient;
-               int layer_number; /* identifies layer in the atmosphere */
-               int delta_z; /* difference between two altitudes */
-
-               if (pressure < 0)  /* illegal pressure */
-                       return -1;
-               if (pressure < MINIMUM_PRESSURE) /* FIX ME: use sensor data to improve model */
-                       return MAXIMUM_ALTITUDE;
-
-               /* calculate the base temperature and pressure for the atmospheric layer
-                  associated with the inputted pressure. */
-               layer_number = -1;
-               do {
-                       layer_number++;
-                       base_pressure = next_base_pressure;
-                       base_temperature = next_base_temperature;
-                       delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number];
-                       if (lapse_rate[layer_number] == 0.0) {
-                               exponent = GRAVITATIONAL_ACCELERATION * delta_z
-                                       / AIR_GAS_CONSTANT / base_temperature;
-                               next_base_pressure *= Math.exp(exponent);
-                       }
-                       else {
-                               base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0;
-                               exponent = GRAVITATIONAL_ACCELERATION /
-                                       (AIR_GAS_CONSTANT * lapse_rate[layer_number]);
-                               next_base_pressure *= Math.pow(base, exponent);
-                       }
-                       next_base_temperature += delta_z * lapse_rate[layer_number];
-               }
-               while(layer_number < NUMBER_OF_LAYERS - 1 && pressure < next_base_pressure);
-
-               /* calculate the altitude associated with the inputted pressure */
-               if (lapse_rate[layer_number] == 0.0) {
-                       coefficient = (AIR_GAS_CONSTANT / GRAVITATIONAL_ACCELERATION)
-                               * base_temperature;
-                       altitude = base_altitude[layer_number]
-                               + coefficient * Math.log(pressure / base_pressure);
-               }
-               else {
-                       base = pressure / base_pressure;
-                       exponent = AIR_GAS_CONSTANT * lapse_rate[layer_number]
-                               / GRAVITATIONAL_ACCELERATION;
-                       coefficient = base_temperature / lapse_rate[layer_number];
-                       altitude = base_altitude[layer_number]
-                               + coefficient * (Math.pow(base, exponent) - 1);
-               }
-
-               return altitude;
-       }
-
-       static double
-       cc_battery_to_voltage(double battery)
-       {
-               return battery / 32767.0 * 5.0;
-       }
-
-       static double
-       cc_ignitor_to_voltage(double ignite)
-       {
-               return ignite / 32767 * 15.0;
-       }
-}
diff --git a/ao-tools/altosui/AltosDataChooser.java b/ao-tools/altosui/AltosDataChooser.java
deleted file mode 100644 (file)
index 15de05c..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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.*;
-
-public class AltosDataChooser extends JFileChooser {
-       JFrame  frame;
-       String  filename;
-       File    file;
-
-       public String filename() {
-               return filename;
-       }
-
-       public File file() {
-               return file;
-       }
-
-       public AltosRecordIterable runDialog() {
-               int     ret;
-
-               ret = showOpenDialog(frame);
-               if (ret == APPROVE_OPTION) {
-                       file = getSelectedFile();
-                       if (file == null)
-                               return null;
-                       filename = file.getName();
-                       try {
-                               if (filename.endsWith("eeprom")) {
-                                       FileInputStream in = new FileInputStream(file);
-                                       return new AltosEepromIterable(in);
-                               } else if (filename.endsWith("telem")) {
-                                       FileInputStream in = new FileInputStream(file);
-                                       return new AltosTelemetryIterable(in);
-                               } else {
-                                       throw new FileNotFoundException();
-                               }
-                       } catch (FileNotFoundException fe) {
-                               JOptionPane.showMessageDialog(frame,
-                                                             filename,
-                                                             "Cannot open file",
-                                                             JOptionPane.ERROR_MESSAGE);
-                       }
-               }
-               return null;
-       }
-
-       public AltosDataChooser(JFrame in_frame) {
-               frame = in_frame;
-               setDialogTitle("Select Flight Record File");
-               setFileFilter(new FileNameExtensionFilter("Flight data file",
-                                                         "telem", "eeprom"));
-               setCurrentDirectory(AltosPreferences.logdir());
-       }
-}
diff --git a/ao-tools/altosui/AltosDataPoint.java b/ao-tools/altosui/AltosDataPoint.java
deleted file mode 100644 (file)
index 66313e0..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-
-// Copyright (c) 2010 Anthony Towns
-// GPL v2 or later
-
-package altosui;
-
-interface AltosDataPoint {
-    int version();
-    int serial();
-    int flight();
-    String callsign();
-    double time();
-    double rssi();
-
-    int state();
-    String state_name();
-
-    double acceleration();
-    double pressure();
-    double altitude();
-    double height();
-    double accel_speed();
-    double baro_speed();
-    double temperature();
-    double battery_voltage();
-    double drogue_voltage();
-    double main_voltage();
-}
-
diff --git a/ao-tools/altosui/AltosDataPointReader.java b/ao-tools/altosui/AltosDataPointReader.java
deleted file mode 100644 (file)
index 7704310..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-
-// Copyright (c) 2010 Anthony Towns
-// GPL v2 or later
-
-package altosui;
-
-import java.io.IOException;
-import java.text.ParseException;
-import java.lang.UnsupportedOperationException;
-import java.util.NoSuchElementException;
-import java.util.Iterator;
-
-class AltosDataPointReader implements Iterable<AltosDataPoint> {
-    Iterator<AltosRecord> iter;
-    AltosState state;
-    AltosRecord record;
-
-    public AltosDataPointReader(Iterable<AltosRecord> reader) {
-        this.iter = reader.iterator();
-        this.state = null;
-    }
-
-    private void read_next_record() 
-        throws NoSuchElementException
-    {
-        record = iter.next();
-        state = new AltosState(record, state);
-    }
-
-    private AltosDataPoint current_dp() {
-        assert this.record != null;
-        
-        return new AltosDataPoint() {
-            public int version() { return record.version; }
-            public int serial() { return record.serial; }
-            public int flight() { return record.flight; }
-            public String callsign() { return record.callsign; }
-            public double time() { return record.time; }
-            public double rssi() { return record.rssi; }
-
-            public int state() { return record.state; }
-            public String state_name() { return record.state(); }
-
-            public double acceleration() { return record.acceleration(); }
-            public double pressure() { return record.raw_pressure(); }
-            public double altitude() { return record.raw_altitude(); }
-            public double height() { return record.raw_height(); }
-            public double accel_speed() { return record.accel_speed(); }
-            public double baro_speed() { return state.baro_speed; }
-            public double temperature() { return record.temperature(); }
-            public double battery_voltage() { return record.battery_voltage(); }
-            public double drogue_voltage() { return record.drogue_voltage(); }
-            public double main_voltage() { return record.main_voltage(); }
-        };
-    }
-
-    public Iterator<AltosDataPoint> iterator() {
-        return new Iterator<AltosDataPoint>() {
-            public void remove() { 
-                throw new UnsupportedOperationException(); 
-            }
-            public boolean hasNext() {
-                return iter.hasNext();
-            }
-            public AltosDataPoint next() {
-                read_next_record();
-                return current_dp();
-            }
-        };
-    }
-}
-
diff --git a/ao-tools/altosui/AltosDebug.java b/ao-tools/altosui/AltosDebug.java
deleted file mode 100644 (file)
index 8d435b6..0000000
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * 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.lang.*;
-import java.io.*;
-import java.util.concurrent.*;
-import java.util.*;
-
-import libaltosJNI.*;
-
-public class AltosDebug extends AltosSerial {
-
-       public static final byte WR_CONFIG =            0x1d;
-       public static final byte RD_CONFIG =            0x24;
-       public static final byte CONFIG_TIMERS_OFF =            (1 << 3);
-       public static final byte CONFIG_DMA_PAUSE =             (1 << 2);
-       public static final byte CONFIG_TIMER_SUSPEND =         (1 << 1);
-       public static final byte SET_FLASH_INFO_PAGE =          (1 << 0);
-
-       public static final byte GET_PC =               0x28;
-       public static final byte READ_STATUS =          0x34;
-       public static final byte STATUS_CHIP_ERASE_DONE =       (byte) (1 << 7);
-       public static final byte STATUS_PCON_IDLE =             (1 << 6);
-       public static final byte STATUS_CPU_HALTED =            (1 << 5);
-       public static final byte STATUS_POWER_MODE_0 =          (1 << 4);
-       public static final byte STATUS_HALT_STATUS =           (1 << 3);
-       public static final byte STATUS_DEBUG_LOCKED =          (1 << 2);
-       public static final byte STATUS_OSCILLATOR_STABLE =     (1 << 1);
-       public static final byte STATUS_STACK_OVERFLOW =        (1 << 0);
-
-       public static final byte SET_HW_BRKPNT =        0x3b;
-       public static byte       HW_BRKPNT_N(byte n)    { return (byte) ((n) << 3); }
-       public static final byte HW_BRKPNT_N_MASK =             (0x3 << 3);
-       public static final byte HW_BRKPNT_ENABLE =             (1 << 2);
-
-       public static final byte HALT =                 0x44;
-       public static final byte RESUME =               0x4c;
-       public static       byte DEBUG_INSTR(byte n)    { return (byte) (0x54|(n)); }
-       public static final byte STEP_INSTR =           0x5c;
-       public static        byte STEP_REPLACE(byte n)  { return  (byte) (0x64|(n)); }
-       public static final byte GET_CHIP_ID =          0x68;
-
-
-       boolean debug_mode;
-
-       void ensure_debug_mode() {
-               if (!debug_mode) {
-                       printf("D\n");
-                       flush_input();
-                       debug_mode = true;
-               }
-       }
-
-       void dump_memory(String header, int address, byte[] bytes, int start, int len) {
-               System.out.printf("%s\n", header);
-               for (int j = 0; j < len; j++) {
-                       if ((j & 15) == 0) {
-                               if (j != 0)
-                                       System.out.printf("\n");
-                               System.out.printf ("%04x:", address + j);
-                       }
-                       System.out.printf(" %02x", bytes[start + j]);
-               }
-               System.out.printf("\n");
-       }
-
-       /*
-        * Write target memory
-        */
-       public void write_memory(int address, byte[] bytes, int start, int len) {
-               ensure_debug_mode();
-//             dump_memory("write_memory", address, bytes, start, len);
-               printf("O %x %x\n", len, address);
-               for (int i = 0; i < len; i++)
-                       printf("%02x", bytes[start + i]);
-       }
-
-       public void write_memory(int address, byte[] bytes) {
-               write_memory(address, bytes, 0, bytes.length);
-       }
-
-       /*
-        * Read target memory
-        */
-       public byte[] read_memory(int address, int length)
-               throws IOException, InterruptedException {
-               byte[]  data = new byte[length];
-
-               flush_input();
-               ensure_debug_mode();
-               printf("I %x %x\n", length, address);
-               int i = 0;
-               int start = 0;
-               while (i < length) {
-                       String  line = get_reply().trim();
-                       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) ((Altos.fromhex(line.charAt(j*2)) << 4) +
-                                                 Altos.fromhex(line.charAt(j*2+1)));
-                       start += this_time;
-                       i += this_time;
-               }
-//             dump_memory("read_memory", address, data, 0, length);
-
-               return data;
-       }
-
-       /*
-        * Write raw bytes to the debug link using the 'P' command
-        */
-       public void write_bytes(byte[] bytes) throws IOException {
-               int i = 0;
-               ensure_debug_mode();
-               while (i < bytes.length) {
-                       int this_time = bytes.length - i;
-                       if (this_time > 8)
-                               this_time = 0;
-                       printf("P");
-                       for (int j = 0; j < this_time; j++)
-                               printf(" %02x", bytes[i+j]);
-                       printf("\n");
-                       i += this_time;
-               }
-       }
-
-       public void write_byte(byte b) throws IOException {
-               byte[] bytes = { b };
-               write_bytes(bytes);
-       }
-
-       /*
-        * Read raw bytes from the debug link using the 'G' command
-        */
-       public byte[] read_bytes(int length)
-               throws IOException, InterruptedException {
-
-               flush_input();
-               ensure_debug_mode();
-               printf("G %x\n", length);
-               int i = 0;
-               byte[] data = new byte[length];
-               while (i < length) {
-                       String line = get_reply().trim();
-                       String tokens[] = line.split("\\s+");
-                       for (int j = 0; j < tokens.length; j++) {
-                               if (!Altos.ishex(tokens[j]) ||
-                                   tokens[j].length() != 2)
-                                       throw new IOException(
-                                               String.format
-                                               ("Invalid read_bytes reply \"%s\"", line));
-                               try {
-                                       data[i + j] = (byte) Integer.parseInt(tokens[j], 16);
-                               } catch (NumberFormatException ne) {
-                                       throw new IOException(
-                                               String.format
-                                               ("Invalid read_bytes reply \"%s\"", line));
-                               }
-                       }
-                       i += tokens.length;
-               }
-               return data;
-       }
-
-       public byte read_byte() throws IOException, InterruptedException {
-               return read_bytes(1)[0];
-       }
-
-       public byte debug_instr(byte[] instruction) throws IOException, InterruptedException {
-               byte[] command = new byte[1 + instruction.length];
-               command[0] = DEBUG_INSTR((byte) instruction.length);
-               for (int i = 0; i < instruction.length; i++)
-                       command[i+1] = instruction[i];
-               write_bytes(command);
-               return read_byte();
-       }
-
-       public byte resume() throws IOException, InterruptedException {
-               write_byte(RESUME);
-               return read_byte();
-       }
-
-       public int read_uint16() throws IOException, InterruptedException {
-               byte[] d = read_bytes(2);
-               return ((int) (d[0] & 0xff) << 8) | (d[1] & 0xff);
-       }
-
-       public int read_uint8()  throws IOException, InterruptedException {
-               byte[] d = read_bytes(1);
-               return (int) (d[0] & 0xff);
-       }
-
-       public int get_chip_id() throws IOException, InterruptedException {
-               write_byte(GET_CHIP_ID);
-               return read_uint16();
-       }
-
-       public int get_pc() throws IOException, InterruptedException {
-               write_byte(GET_PC);
-               return read_uint16();
-       }
-
-       public byte read_status() throws IOException, InterruptedException {
-               write_byte(READ_STATUS);
-               return read_byte();
-       }
-
-       static final byte LJMP                  = 0x02;
-
-       public void set_pc(int pc) throws IOException, InterruptedException {
-               byte high = (byte) (pc >> 8);
-               byte low = (byte) pc;
-               byte[] jump_mem = { LJMP, high, low };
-               debug_instr(jump_mem);
-       }
-
-       public boolean check_connection() throws IOException, InterruptedException {
-               byte reply = read_status();
-               if ((reply & STATUS_CHIP_ERASE_DONE) == 0)
-                       return false;
-               if ((reply & STATUS_PCON_IDLE) != 0)
-                       return false;
-               if ((reply & STATUS_POWER_MODE_0) == 0)
-                       return false;
-               return true;
-       }
-
-       public AltosRomconfig romconfig() {
-               try {
-                       byte[] bytes = read_memory(0xa0, 10);
-                       return new AltosRomconfig(bytes, 0);
-               } catch (IOException ie) {
-               } catch (InterruptedException ie) {
-               }
-               return new AltosRomconfig();
-       }
-
-       /*
-        * Reset target
-        */
-       public void reset() {
-               printf ("R\n");
-       }
-
-       public AltosDebug (AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException {
-               super(in_device);
-       }
-}
\ No newline at end of file
diff --git a/ao-tools/altosui/AltosDescent.java b/ao-tools/altosui/AltosDescent.java
deleted file mode 100644 (file)
index 16ccd45..0000000
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- * 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;
-
-public class AltosDescent extends JComponent implements AltosFlightDisplay {
-       GridBagLayout   layout;
-
-       public abstract class DescentStatus {
-               JLabel          label;
-               JTextField      value;
-               AltosLights     lights;
-
-               abstract void show(AltosState state, int crc_errors);
-               void reset() {
-                       value.setText("");
-                       lights.set(false);
-               }
-
-               public DescentStatus (GridBagLayout layout, int y, String text) {
-                       GridBagConstraints      c = new GridBagConstraints();
-                       c.weighty = 1;
-
-                       lights = new AltosLights();
-                       c.gridx = 0; c.gridy = y;
-                       c.anchor = GridBagConstraints.CENTER;
-                       c.fill = GridBagConstraints.VERTICAL;
-                       c.weightx = 0;
-                       layout.setConstraints(lights, c);
-                       add(lights);
-
-                       label = new JLabel(text);
-                       label.setFont(Altos.label_font);
-                       label.setHorizontalAlignment(SwingConstants.LEFT);
-                       c.gridx = 1; c.gridy = y;
-                       c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
-                       c.anchor = GridBagConstraints.WEST;
-                       c.fill = GridBagConstraints.VERTICAL;
-                       c.gridwidth = 3;
-                       c.weightx = 0;
-                       layout.setConstraints(label, c);
-                       add(label);
-
-                       value = new JTextField(Altos.text_width);
-                       value.setFont(Altos.value_font);
-                       value.setHorizontalAlignment(SwingConstants.RIGHT);
-                       c.gridx = 4; c.gridy = y;
-                       c.gridwidth = 1;
-                       c.anchor = GridBagConstraints.WEST;
-                       c.fill = GridBagConstraints.BOTH;
-                       c.weightx = 1;
-                       layout.setConstraints(value, c);
-                       add(value);
-
-               }
-       }
-
-       public abstract class DescentValue {
-               JLabel          label;
-               JTextField      value;
-
-               void reset() {
-                       value.setText("");
-               }
-
-               abstract void show(AltosState state, int crc_errors);
-
-               void show(String format, double v) {
-                       value.setText(String.format(format, v));
-               }
-
-               void show(String v) {
-                       value.setText(v);
-               }
-
-               public DescentValue (GridBagLayout layout, int x, int y, String text) {
-                       GridBagConstraints      c = new GridBagConstraints();
-                       c.weighty = 1;
-
-                       label = new JLabel(text);
-                       label.setFont(Altos.label_font);
-                       label.setHorizontalAlignment(SwingConstants.LEFT);
-                       c.gridx = x + 1; c.gridy = y;
-                       c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
-                       c.anchor = GridBagConstraints.WEST;
-                       c.fill = GridBagConstraints.VERTICAL;
-                       c.weightx = 0;
-                       add(label, c);
-
-                       value = new JTextField(Altos.text_width);
-                       value.setFont(Altos.value_font);
-                       value.setHorizontalAlignment(SwingConstants.RIGHT);
-                       c.gridx = x + 2; c.gridy = y;
-                       c.gridwidth = 1;
-                       c.anchor = GridBagConstraints.WEST;
-                       c.fill = GridBagConstraints.BOTH;
-                       c.weightx = 1;
-                       add(value, c);
-               }
-       }
-
-       public abstract class DescentDualValue {
-               JLabel          label;
-               JTextField      value1;
-               JTextField      value2;
-
-               void reset() {
-                       value1.setText("");
-                       value2.setText("");
-               }
-
-               abstract void show(AltosState state, int crc_errors);
-               void show(String v1, String v2) {
-                       value1.setText(v1);
-                       value2.setText(v2);
-               }
-               void show(String f1, double v1, String f2, double v2) {
-                       value1.setText(String.format(f1, v1));
-                       value2.setText(String.format(f2, v2));
-               }
-
-               public DescentDualValue (GridBagLayout layout, int x, int y, String text) {
-                       GridBagConstraints      c = new GridBagConstraints();
-                       c.weighty = 1;
-
-                       label = new JLabel(text);
-                       label.setFont(Altos.label_font);
-                       label.setHorizontalAlignment(SwingConstants.LEFT);
-                       c.gridx = x + 1; c.gridy = y;
-                       c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
-                       c.anchor = GridBagConstraints.WEST;
-                       c.fill = GridBagConstraints.VERTICAL;
-                       c.weightx = 0;
-                       layout.setConstraints(label, c);
-                       add(label);
-
-                       value1 = new JTextField(Altos.text_width);
-                       value1.setFont(Altos.value_font);
-                       value1.setHorizontalAlignment(SwingConstants.RIGHT);
-                       c.gridx = x + 2; c.gridy = y;
-                       c.anchor = GridBagConstraints.WEST;
-                       c.fill = GridBagConstraints.BOTH;
-                       c.weightx = 1;
-                       layout.setConstraints(value1, c);
-                       add(value1);
-
-                       value2 = new JTextField(Altos.text_width);
-                       value2.setFont(Altos.value_font);
-                       value2.setHorizontalAlignment(SwingConstants.RIGHT);
-                       c.gridx = x + 4; c.gridy = y;
-                       c.anchor = GridBagConstraints.WEST;
-                       c.fill = GridBagConstraints.BOTH;
-                       c.weightx = 1;
-                       c.gridwidth = 1;
-                       layout.setConstraints(value2, c);
-                       add(value2);
-               }
-       }
-
-       class Height extends DescentValue {
-               void show (AltosState state, int crc_errors) {
-                       show("%6.0f m", state.height);
-               }
-               public Height (GridBagLayout layout, int x, int y) {
-                       super (layout, x, y, "Height");
-               }
-       }
-
-       Height  height;
-
-       class Speed extends DescentValue {
-               void show (AltosState state, int crc_errors) {
-                       double speed = state.speed;
-                       if (!state.ascent)
-                               speed = state.baro_speed;
-                       show("%6.0f m/s", speed);
-               }
-               public Speed (GridBagLayout layout, int x, int y) {
-                       super (layout, x, y, "Speed");
-               }
-       }
-
-       Speed   speed;
-
-       String pos(double p, String pos, String neg) {
-               String  h = pos;
-               if (p < 0) {
-                       h = neg;
-                       p = -p;
-               }
-               int deg = (int) Math.floor(p);
-               double min = (p - Math.floor(p)) * 60.0;
-               return String.format("%s %d° %9.6f", h, deg, min);
-       }
-
-       class Lat extends DescentValue {
-               void show (AltosState state, int crc_errors) {
-                       if (state.gps != null)
-                               show(pos(state.gps.lat,"N", "S"));
-                       else
-                               show("???");
-               }
-               public Lat (GridBagLayout layout, int x, int y) {
-                       super (layout, x, y, "Latitude");
-               }
-       }
-
-       Lat lat;
-
-       class Lon extends DescentValue {
-               void show (AltosState state, int crc_errors) {
-                       if (state.gps != null)
-                               show(pos(state.gps.lon,"W", "E"));
-                       else
-                               show("???");
-               }
-               public Lon (GridBagLayout layout, int x, int y) {
-                       super (layout, x, y, "Longitude");
-               }
-       }
-
-       Lon lon;
-
-       class Apogee extends DescentStatus {
-               void show (AltosState state, int crc_errors) {
-                       value.setText(String.format("%4.2f V", state.drogue_sense));
-                       lights.set(state.drogue_sense > 3.2);
-               }
-               public Apogee (GridBagLayout layout, int y) {
-                       super(layout, y, "Apogee Igniter Voltage");
-               }
-       }
-
-       Apogee apogee;
-
-       class Main extends DescentStatus {
-               void show (AltosState state, int crc_errors) {
-                       value.setText(String.format("%4.2f V", state.main_sense));
-                       lights.set(state.main_sense > 3.2);
-               }
-               public Main (GridBagLayout layout, int y) {
-                       super(layout, y, "Main Igniter Voltage");
-               }
-       }
-
-       Main main;
-
-       class Bearing extends DescentDualValue {
-               void show (AltosState state, int crc_errors) {
-                       if (state.from_pad != null) {
-                               show( String.format("%3.0f°", state.from_pad.bearing),
-                                     state.from_pad.bearing_words(
-                                             AltosGreatCircle.BEARING_LONG));
-                       } else {
-                               show("???", "???");
-                       }
-               }
-               public Bearing (GridBagLayout layout, int x, int y) {
-                       super (layout, x, y, "Bearing");
-               }
-       }
-
-       Bearing bearing;
-
-       class Range extends DescentValue {
-               void show (AltosState state, int crc_errors) {
-                       show("%6.0f m", state.range);
-               }
-               public Range (GridBagLayout layout, int x, int y) {
-                       super (layout, x, y, "Range");
-               }
-       }
-
-       Range range;
-
-       class Elevation extends DescentValue {
-               void show (AltosState state, int crc_errors) {
-                       show("%3.0f°", state.elevation);
-               }
-               public Elevation (GridBagLayout layout, int x, int y) {
-                       super (layout, x, y, "Elevation");
-               }
-       }
-
-       Elevation elevation;
-
-       public void reset() {
-               lat.reset();
-               lon.reset();
-               height.reset();
-               speed.reset();
-               bearing.reset();
-               range.reset();
-               elevation.reset();
-               main.reset();
-               apogee.reset();
-       }
-
-       public void show(AltosState state, int crc_errors) {
-               height.show(state, crc_errors);
-               speed.show(state, crc_errors);
-               bearing.show(state, crc_errors);
-               range.show(state, crc_errors);
-               elevation.show(state, crc_errors);
-               lat.show(state, crc_errors);
-               lon.show(state, crc_errors);
-               main.show(state, crc_errors);
-               apogee.show(state, crc_errors);
-       }
-
-       public AltosDescent() {
-               layout = new GridBagLayout();
-
-               setLayout(layout);
-
-               /* Elements in descent display */
-               speed = new Speed(layout, 0, 0);
-               height = new Height(layout, 2, 0);
-               elevation = new Elevation(layout, 0, 1);
-               range = new Range(layout, 2, 1);
-               bearing = new Bearing(layout, 0, 2);
-               lat = new Lat(layout, 0, 3);
-               lon = new Lon(layout, 2, 3);
-
-               apogee = new Apogee(layout, 4);
-               main = new Main(layout, 5);
-       }
-}
diff --git a/ao-tools/altosui/AltosDevice.java b/ao-tools/altosui/AltosDevice.java
deleted file mode 100644 (file)
index f0fda57..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * 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.lang.*;
-import java.util.*;
-import libaltosJNI.*;
-
-public class AltosDevice extends altos_device {
-
-       static public boolean initialized = false;
-       static public boolean loaded_library = false;
-
-       public static boolean load_library() {
-               if (!initialized) {
-                       try {
-                               System.loadLibrary("altos");
-                               libaltos.altos_init();
-                               loaded_library = true;
-                       } catch (UnsatisfiedLinkError e) {
-                               loaded_library = false;
-                       }
-                       initialized = true;
-               }
-               return loaded_library;
-       }
-
-       static int usb_vendor_altusmetrum() {
-               if (load_library())
-                       return libaltosConstants.USB_VENDOR_ALTUSMETRUM;
-               return 0x000a;
-       }
-
-       static int usb_product_altusmetrum() {
-               if (load_library())
-                       return libaltosConstants.USB_PRODUCT_ALTUSMETRUM;
-               return 0x000a;
-       }
-
-       static int usb_product_altusmetrum_min() {
-               if (load_library())
-                       return libaltosConstants.USB_PRODUCT_ALTUSMETRUM_MIN;
-               return 0x000a;
-       }
-
-       static int usb_product_altusmetrum_max() {
-               if (load_library())
-                       return libaltosConstants.USB_PRODUCT_ALTUSMETRUM_MAX;
-               return 0x000d;
-       }
-
-       static int usb_product_telemetrum() {
-               if (load_library())
-                       return libaltosConstants.USB_PRODUCT_TELEMETRUM;
-               return 0x000b;
-       }
-
-       static int usb_product_teledongle() {
-               if (load_library())
-                       return libaltosConstants.USB_PRODUCT_TELEDONGLE;
-               return 0x000c;
-       }
-
-       static int usb_product_teleterra() {
-               if (load_library())
-                       return libaltosConstants.USB_PRODUCT_TELETERRA;
-               return 0x000d;
-       }
-
-       public final static int vendor_altusmetrum = usb_vendor_altusmetrum();
-       public final static int product_altusmetrum = usb_product_altusmetrum();
-       public final static int product_telemetrum = usb_product_telemetrum();
-       public final static int product_teledongle = usb_product_teledongle();
-       public final static int product_teleterra = usb_product_teleterra();
-       public final static int product_altusmetrum_min = usb_product_altusmetrum_min();
-       public final static int product_altusmetrum_max = usb_product_altusmetrum_max();
-
-
-       public final static int product_any = 0x10000;
-       public final static int product_basestation = 0x10000 + 1;
-
-       public String toString() {
-               String  name = getName();
-               if (name == null)
-                       name = "Altus Metrum";
-               return String.format("%-20.20s %4d %s",
-                                    getName(), getSerial(), getPath());
-       }
-
-       public String toShortString() {
-               String  name = getName();
-               if (name == null)
-                       name = "Altus Metrum";
-               return String.format("%s %d %s",
-                                    name, getSerial(), getPath());
-
-       }
-
-       public boolean isAltusMetrum() {
-               if (getVendor() != vendor_altusmetrum)
-                       return false;
-               if (getProduct() < product_altusmetrum_min)
-                       return false;
-               if (getProduct() > product_altusmetrum_max)
-                       return false;
-               return true;
-       }
-
-       public boolean matchProduct(int want_product) {
-
-               if (!isAltusMetrum())
-                       return false;
-
-               if (want_product == product_any)
-                       return true;
-
-               if (want_product == product_basestation)
-                       return matchProduct(product_teledongle) || matchProduct(product_teleterra);
-
-               int have_product = getProduct();
-
-               if (have_product == product_altusmetrum)        /* old devices match any request */
-                       return true;
-
-               if (want_product == have_product)
-                       return true;
-
-               return false;
-       }
-
-       static AltosDevice[] list(int product) {
-               if (!load_library())
-                       return null;
-
-               SWIGTYPE_p_altos_list list = libaltos.altos_list_start();
-
-               ArrayList<AltosDevice> device_list = new ArrayList<AltosDevice>();
-               if (list != null) {
-                       SWIGTYPE_p_altos_file file;
-
-                       for (;;) {
-                               AltosDevice device = new AltosDevice();
-                               if (libaltos.altos_list_next(list, device) == 0)
-                                       break;
-                               if (device.matchProduct(product))
-                                       device_list.add(device);
-                       }
-                       libaltos.altos_list_finish(list);
-               }
-
-               AltosDevice[] devices = new AltosDevice[device_list.size()];
-               for (int i = 0; i < device_list.size(); i++)
-                       devices[i] = device_list.get(i);
-               return devices;
-       }
-}
\ No newline at end of file
diff --git a/ao-tools/altosui/AltosDeviceDialog.java b/ao-tools/altosui/AltosDeviceDialog.java
deleted file mode 100644 (file)
index 2966ad1..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * 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.lang.*;
-import java.util.*;
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.*;
-import libaltosJNI.libaltos;
-import libaltosJNI.altos_device;
-import libaltosJNI.SWIGTYPE_p_altos_file;
-import libaltosJNI.SWIGTYPE_p_altos_list;
-
-public class AltosDeviceDialog extends JDialog implements ActionListener {
-
-       private static AltosDeviceDialog        dialog;
-       private static AltosDevice              value = null;
-       private JList                           list;
-
-       public static AltosDevice show (Component frameComp, int product) {
-
-               Frame frame = JOptionPane.getFrameForComponent(frameComp);
-               AltosDevice[]   devices;
-               devices = AltosDevice.list(product);
-
-               if (devices != null && devices.length > 0) {
-                       value = null;
-                       dialog = new AltosDeviceDialog(frame, frameComp,
-                                                      devices,
-                                                      devices[0]);
-
-                       dialog.setVisible(true);
-                       return value;
-               } else {
-                       /* check for missing altos JNI library, which
-                        * will put up its own error dialog
-                        */
-                       if (AltosUI.load_library(frame)) {
-                               JOptionPane.showMessageDialog(frame,
-                                                             "No AltOS devices available",
-                                                             "No AltOS devices",
-                                                             JOptionPane.ERROR_MESSAGE);
-                       }
-                       return null;
-               }
-       }
-
-       private AltosDeviceDialog (Frame frame, Component location,
-                                  AltosDevice[] devices,
-                                  AltosDevice initial) {
-               super(frame, "Device Selection", true);
-
-               value = null;
-
-               JButton cancelButton = new JButton("Cancel");
-               cancelButton.addActionListener(this);
-
-               final JButton selectButton = new JButton("Select");
-               selectButton.setActionCommand("select");
-               selectButton.addActionListener(this);
-               getRootPane().setDefaultButton(selectButton);
-
-               list = new JList(devices) {
-                               //Subclass JList to workaround bug 4832765, which can cause the
-                               //scroll pane to not let the user easily scroll up to the beginning
-                               //of the list.  An alternative would be to set the unitIncrement
-                               //of the JScrollBar to a fixed value. You wouldn't get the nice
-                               //aligned scrolling, but it should work.
-                               public int getScrollableUnitIncrement(Rectangle visibleRect,
-                                                                     int orientation,
-                                                                     int direction) {
-                                       int row;
-                                       if (orientation == SwingConstants.VERTICAL &&
-                                           direction < 0 && (row = getFirstVisibleIndex()) != -1) {
-                                               Rectangle r = getCellBounds(row, row);
-                                               if ((r.y == visibleRect.y) && (row != 0))  {
-                                                       Point loc = r.getLocation();
-                                                       loc.y--;
-                                                       int prevIndex = locationToIndex(loc);
-                                                       Rectangle prevR = getCellBounds(prevIndex, prevIndex);
-
-                                                       if (prevR == null || prevR.y >= r.y) {
-                                                               return 0;
-                                                       }
-                                                       return prevR.height;
-                                               }
-                                       }
-                                       return super.getScrollableUnitIncrement(
-                                               visibleRect, orientation, direction);
-                               }
-                       };
-
-               list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
-               list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
-               list.setVisibleRowCount(-1);
-               list.addMouseListener(new MouseAdapter() {
-                                public void mouseClicked(MouseEvent e) {
-                                        if (e.getClickCount() == 2) {
-                                                selectButton.doClick(); //emulate button click
-                                        }
-                                }
-                       });
-               JScrollPane listScroller = new JScrollPane(list);
-               listScroller.setPreferredSize(new Dimension(400, 80));
-               listScroller.setAlignmentX(LEFT_ALIGNMENT);
-
-               //Create a container so that we can add a title around
-               //the scroll pane.  Can't add a title directly to the
-               //scroll pane because its background would be white.
-               //Lay out the label and scroll pane from top to bottom.
-               JPanel listPane = new JPanel();
-               listPane.setLayout(new BoxLayout(listPane, BoxLayout.PAGE_AXIS));
-
-               JLabel label = new JLabel("Select Device");
-               label.setLabelFor(list);
-               listPane.add(label);
-               listPane.add(Box.createRigidArea(new Dimension(0,5)));
-               listPane.add(listScroller);
-               listPane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
-
-               //Lay out the buttons from left to right.
-               JPanel buttonPane = new JPanel();
-               buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS));
-               buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
-               buttonPane.add(Box.createHorizontalGlue());
-               buttonPane.add(cancelButton);
-               buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
-               buttonPane.add(selectButton);
-
-               //Put everything together, using the content pane's BorderLayout.
-               Container contentPane = getContentPane();
-               contentPane.add(listPane, BorderLayout.CENTER);
-               contentPane.add(buttonPane, BorderLayout.PAGE_END);
-
-               //Initialize values.
-               list.setSelectedValue(initial, true);
-               pack();
-               setLocationRelativeTo(location);
-       }
-
-       //Handle clicks on the Set and Cancel buttons.
-       public void actionPerformed(ActionEvent e) {
-               if ("select".equals(e.getActionCommand()))
-                       AltosDeviceDialog.value = (AltosDevice)(list.getSelectedValue());
-               AltosDeviceDialog.dialog.setVisible(false);
-       }
-
-}
diff --git a/ao-tools/altosui/AltosDisplayThread.java b/ao-tools/altosui/AltosDisplayThread.java
deleted file mode 100644 (file)
index 3e71913..0000000
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * 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;
-
-public class AltosDisplayThread extends Thread {
-
-       Frame                   parent;
-       IdleThread              idle_thread;
-       AltosVoice              voice;
-       String                  name;
-       AltosFlightReader       reader;
-       int                     crc_errors;
-       AltosFlightDisplay      display;
-
-       synchronized void show(AltosState state, int crc_errors) {
-               if (state != null)
-                       display.show(state, crc_errors);
-       }
-
-       class IdleThread extends Thread {
-
-               boolean started;
-               private AltosState state;
-               int     reported_landing;
-               int     report_interval;
-               long    report_time;
-
-               public synchronized void report(boolean last) {
-                       if (state == null)
-                               return;
-
-                       /* reset the landing count once we hear about a new flight */
-                       if (state.state < Altos.ao_flight_drogue)
-                               reported_landing = 0;
-
-                       /* Shut up once the rocket is on the ground */
-                       if (reported_landing > 2) {
-                               return;
-                       }
-
-                       /* If the rocket isn't on the pad, then report height */
-                       if (Altos.ao_flight_drogue <= state.state &&
-                           state.state < Altos.ao_flight_landed &&
-                           state.range >= 0)
-                       {
-                               voice.speak("Height %d, bearing %s %d, elevation %d, range %d.\n",
-                                           (int) (state.height + 0.5),
-                        state.from_pad.bearing_words(
-                            AltosGreatCircle.BEARING_VOICE),
-                                           (int) (state.from_pad.bearing + 0.5),
-                                           (int) (state.elevation + 0.5),
-                                           (int) (state.range + 0.5));
-                       } else if (state.state > Altos.ao_flight_pad) {
-                               voice.speak("%d meters", (int) (state.height + 0.5));
-                       } else {
-                               reported_landing = 0;
-                       }
-
-                       /* If the rocket is coming down, check to see if it has landed;
-                        * either we've got a landed report or we haven't heard from it in
-                        * a long time
-                        */
-                       if (state.state >= Altos.ao_flight_drogue &&
-                           (last ||
-                            System.currentTimeMillis() - state.report_time >= 15000 ||
-                            state.state == Altos.ao_flight_landed))
-                       {
-                               if (Math.abs(state.baro_speed) < 20 && state.height < 100)
-                                       voice.speak("rocket landed safely");
-                               else
-                                       voice.speak("rocket may have crashed");
-                               if (state.from_pad != null)
-                                       voice.speak("Bearing %d degrees, range %d meters.",
-                                                   (int) (state.from_pad.bearing + 0.5),
-                                                   (int) (state.from_pad.distance + 0.5));
-                               ++reported_landing;
-                               if (state.state != Altos.ao_flight_landed) {
-                                       state.state = Altos.ao_flight_landed;
-                                       show(state, 0);
-                               }
-                       }
-               }
-
-               long now () {
-                       return System.currentTimeMillis();
-               }
-
-               void set_report_time() {
-                       report_time = now() + report_interval;
-               }
-
-               public void run () {
-                       try {
-                               for (;;) {
-                                       set_report_time();
-                                       for (;;) {
-                                               voice.drain();
-                                               synchronized (this) {
-                                                       long    sleep_time = report_time - now();
-                                                       if (sleep_time <= 0)
-                                                               break;
-                                                       wait(sleep_time);
-                                               }
-                                       }
-                                       report(false);
-                               }
-                       } catch (InterruptedException ie) {
-                               try {
-                                       voice.drain();
-                               } catch (InterruptedException iie) { }
-                       }
-               }
-
-               public synchronized void notice(AltosState new_state, boolean spoken) {
-                       AltosState old_state = state;
-                       state = new_state;
-                       if (!started && state.state > Altos.ao_flight_pad) {
-                               started = true;
-                               start();
-                       }
-
-                       if (state.state < Altos.ao_flight_drogue)
-                               report_interval = 10000;
-                       else
-                               report_interval = 20000;
-                       if (old_state != null && old_state.state != state.state) {
-                               report_time = now();
-                               this.notify();
-                       } else if (spoken)
-                               set_report_time();
-               }
-
-               public IdleThread() {
-                       state = null;
-                       reported_landing = 0;
-                       report_interval = 10000;
-               }
-       }
-
-       boolean tell(AltosState state, AltosState old_state) {
-               boolean ret = false;
-               if (old_state == null || old_state.state != state.state) {
-                       voice.speak(state.data.state());
-                       if ((old_state == null || old_state.state <= Altos.ao_flight_boost) &&
-                           state.state > Altos.ao_flight_boost) {
-                               voice.speak("max speed: %d meters per second.",
-                                           (int) (state.max_speed + 0.5));
-                               ret = true;
-                       } else if ((old_state == null || old_state.state < Altos.ao_flight_drogue) &&
-                                  state.state >= Altos.ao_flight_drogue) {
-                               voice.speak("max height: %d meters.",
-                                           (int) (state.max_height + 0.5));
-                               ret = true;
-                       }
-               }
-               if (old_state == null || old_state.gps_ready != state.gps_ready) {
-                       if (state.gps_ready) {
-                               voice.speak("GPS ready");
-                               ret = true;
-                       }
-                       else if (old_state != null) {
-                               voice.speak("GPS lost");
-                               ret = true;
-                       }
-               }
-               old_state = state;
-               return ret;
-       }
-
-       public void run() {
-               boolean         interrupted = false;
-               String          line;
-               AltosState      state = null;
-               AltosState      old_state = null;
-               boolean         told;
-
-               idle_thread = new IdleThread();
-
-               display.reset();
-               try {
-                       for (;;) {
-                               try {
-                                       AltosRecord record = reader.read();
-                                       if (record == null)
-                                               break;
-                                       old_state = state;
-                                       state = new AltosState(record, state);
-                                       reader.update(state);
-                                       show(state, crc_errors);
-                                       told = tell(state, old_state);
-                                       idle_thread.notice(state, told);
-                               } catch (ParseException pp) {
-                                       System.out.printf("Parse error: %d \"%s\"\n", pp.getErrorOffset(), pp.getMessage());
-                               } catch (AltosCRCException ce) {
-                                       ++crc_errors;
-                                       show(state, crc_errors);
-                               }
-                       }
-               } catch (InterruptedException ee) {
-                       interrupted = true;
-               } catch (IOException ie) {
-                       JOptionPane.showMessageDialog(parent,
-                                                     String.format("Error reading from \"%s\"", name),
-                                                     "Telemetry Read Error",
-                                                     JOptionPane.ERROR_MESSAGE);
-               } finally {
-                       if (!interrupted)
-                               idle_thread.report(true);
-                       reader.close(interrupted);
-                       idle_thread.interrupt();
-                       try {
-                               idle_thread.join();
-                       } catch (InterruptedException ie) {}
-               }
-       }
-
-       public AltosDisplayThread(Frame in_parent, AltosVoice in_voice, AltosFlightDisplay in_display, AltosFlightReader in_reader) {
-               parent = in_parent;
-               voice = in_voice;
-               display = in_display;
-               reader = in_reader;
-       }
-}
diff --git a/ao-tools/altosui/AltosEepromDownload.java b/ao-tools/altosui/AltosEepromDownload.java
deleted file mode 100644 (file)
index 02fc36f..0000000
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * 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.*;
-
-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;
-
-       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  line = serial_line.get_reply(5000);
-
-                       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_pending.add(String.format("%s\n", line));
-
-                       /* signals the end of the version info */
-                       if (line.startsWith("software-version"))
-                               break;
-               }
-               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);
-
-                                       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;
-                                       }
-
-                                       if (cmd == Altos.AO_LOG_GPS_DATE) {
-                                               year = 2000 + (a & 0xff);
-                                               month = (a >> 8) & 0xff;
-                                               day = (b & 0xff);
-                                               want_file = 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.set_file(eeprom_name.getName());
-                                                       eeprom_file = new FileWriter(eeprom_name);
-                                                       if (eeprom_file != null) {
-                                                               FlushPending(eeprom_file, eeprom_pending);
-                                                               eeprom_pending = null;
-                                                       }
-                                               }
-                                       }
-
-                                       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);
-
-                                       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);
-                       }
-               }
-               if (eeprom_file != null) {
-                       eeprom_file.flush();
-                       eeprom_file.close();
-               }
-       }
-
-       public void run () {
-               if (remote) {
-                       serial_line.set_radio();
-                       serial_line.printf("p\nE 0\n");
-                       serial_line.flush_input();
-               }
-
-               monitor = new AltosEepromMonitor(frame, Altos.ao_flight_boost, Altos.ao_flight_landed);
-               monitor.addActionListener(new ActionListener() {
-                               public void actionPerformed(ActionEvent e) {
-                                       eeprom_thread.interrupt();
-                               }
-                       });
-               try {
-                       CaptureLog();
-               } catch (IOException ee) {
-                       JOptionPane.showMessageDialog(frame,
-                                                     device.toShortString(),
-                                                     ee.getLocalizedMessage(),
-                                                     JOptionPane.ERROR_MESSAGE);
-               } catch (InterruptedException ie) {
-               } catch (TimeoutException te) {
-                       JOptionPane.showMessageDialog(frame,
-                                                     String.format("Connection to \"%s\" failed",
-                                                                   device.toShortString()),
-                                                     "Connection Failed",
-                                                     JOptionPane.ERROR_MESSAGE);
-               }
-               if (remote)
-                       serial_line.printf("~");
-               monitor.done();
-               serial_line.flush_output();
-               serial_line.close();
-       }
-
-       public AltosEepromDownload(JFrame given_frame) {
-               frame = given_frame;
-               device = AltosDeviceDialog.show(frame, AltosDevice.product_any);
-
-               remote = false;
-
-               if (device != null) {
-                       try {
-                               serial_line = new AltosSerial(device);
-                               if (!device.matchProduct(AltosDevice.product_telemetrum))
-                                       remote = true;
-                               eeprom_thread = new Thread(this);
-                               eeprom_thread.start();
-                       } catch (FileNotFoundException ee) {
-                               JOptionPane.showMessageDialog(frame,
-                                                             String.format("Cannot open device \"%s\"",
-                                                                           device.toShortString()),
-                                                             "Cannot open target device",
-                                                             JOptionPane.ERROR_MESSAGE);
-                       } catch (AltosSerialInUseException si) {
-                               JOptionPane.showMessageDialog(frame,
-                                                             String.format("Device \"%s\" already in use",
-                                                                           device.toShortString()),
-                                                             "Device in use",
-                                                             JOptionPane.ERROR_MESSAGE);
-                       } catch (IOException ee) {
-                               JOptionPane.showMessageDialog(frame,
-                                                             device.toShortString(),
-                                                             ee.getLocalizedMessage(),
-                                                             JOptionPane.ERROR_MESSAGE);
-                       }
-               }
-       }
-}
diff --git a/ao-tools/altosui/AltosEepromIterable.java b/ao-tools/altosui/AltosEepromIterable.java
deleted file mode 100644 (file)
index f8e6d7e..0000000
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * 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;
-
-/*
- * AltosRecords with an index field so they can be sorted by tick while preserving
- * the original ordering for elements with matching ticks
- */
-class AltosOrderedRecord extends AltosEepromRecord implements Comparable<AltosOrderedRecord> {
-
-       public int      index;
-
-       public AltosOrderedRecord(String line, int in_index, int prev_tick, boolean prev_tick_valid)
-               throws ParseException {
-               super(line);
-               if (prev_tick_valid) {
-                       tick |= (prev_tick & ~0xffff);
-                       if (tick < prev_tick) {
-                               if (prev_tick - tick > 0x8000)
-                                       tick += 0x10000;
-                       } else {
-                               if (tick - prev_tick > 0x8000)
-                                       tick -= 0x10000;
-                       }
-               }
-               index = in_index;
-       }
-
-       public AltosOrderedRecord(int in_cmd, int in_tick, int in_a, int in_b, int in_index) {
-               super(in_cmd, in_tick, in_a, in_b);
-               index = in_index;
-       }
-
-       public int compareTo(AltosOrderedRecord o) {
-               int     tick_diff = tick - o.tick;
-               if (tick_diff != 0)
-                       return tick_diff;
-               return index - o.index;
-       }
-}
-
-public class AltosEepromIterable extends AltosRecordIterable {
-
-       static final int        seen_flight = 1;
-       static final int        seen_sensor = 2;
-       static final int        seen_temp_volt = 4;
-       static final int        seen_deploy = 8;
-       static final int        seen_gps_time = 16;
-       static final int        seen_gps_lat = 32;
-       static final int        seen_gps_lon = 64;
-
-       static final int        seen_basic = seen_flight|seen_sensor|seen_temp_volt|seen_deploy;
-
-       AltosEepromRecord       flight_record;
-       AltosEepromRecord       gps_date_record;
-
-       TreeSet<AltosOrderedRecord>     records;
-
-       LinkedList<AltosRecord> list;
-
-       class EepromState {
-               int     seen;
-               int     n_pad_samples;
-               double  ground_pres;
-               int     gps_tick;
-               int     boost_tick;
-
-               EepromState() {
-                       seen = 0;
-                       n_pad_samples = 0;
-                       ground_pres = 0.0;
-                       gps_tick = 0;
-               }
-       }
-
-       void update_state(AltosRecord state, AltosEepromRecord record, EepromState eeprom) {
-               state.tick = record.tick;
-               switch (record.cmd) {
-               case Altos.AO_LOG_FLIGHT:
-                       eeprom.seen |= seen_flight;
-                       state.ground_accel = record.a;
-                       state.flight_accel = record.a;
-                       state.flight = record.b;
-                       eeprom.boost_tick = record.tick;
-                       break;
-               case Altos.AO_LOG_SENSOR:
-                       state.accel = record.a;
-                       state.pres = record.b;
-                       if (state.state < Altos.ao_flight_boost) {
-                               eeprom.n_pad_samples++;
-                               eeprom.ground_pres += state.pres;
-                               state.ground_pres = (int) (eeprom.ground_pres / eeprom.n_pad_samples);
-                               state.flight_pres = state.ground_pres;
-                       } else {
-                               state.flight_pres = (state.flight_pres * 15 + state.pres) / 16;
-                               state.flight_accel = (state.flight_accel * 15 + state.accel) / 16;
-                               state.flight_vel += (state.accel_plus_g - state.accel);
-                       }
-                       eeprom.seen |= seen_sensor;
-                       break;
-               case Altos.AO_LOG_TEMP_VOLT:
-                       state.temp = record.a;
-                       state.batt = record.b;
-                       eeprom.seen |= seen_temp_volt;
-                       break;
-               case Altos.AO_LOG_DEPLOY:
-                       state.drogue = record.a;
-                       state.main = record.b;
-                       eeprom.seen |= seen_deploy;
-                       break;
-               case Altos.AO_LOG_STATE:
-                       state.state = record.a;
-                       break;
-               case Altos.AO_LOG_GPS_TIME:
-                       eeprom.gps_tick = state.tick;
-                       AltosGPS old = state.gps;
-                       state.gps = new AltosGPS();
-
-                       /* GPS date doesn't get repeated through the file */
-                       if (old != null) {
-                               state.gps.year = old.year;
-                               state.gps.month = old.month;
-                               state.gps.day = old.day;
-                       }
-                       state.gps.hour = (record.a & 0xff);
-                       state.gps.minute = (record.a >> 8);
-                       state.gps.second = (record.b & 0xff);
-
-                       int flags = (record.b >> 8);
-                       state.gps.connected = (flags & Altos.AO_GPS_RUNNING) != 0;
-                       state.gps.locked = (flags & Altos.AO_GPS_VALID) != 0;
-                       state.gps.date_valid = (flags & Altos.AO_GPS_DATE_VALID) != 0;
-                       state.gps.nsat = (flags & Altos.AO_GPS_NUM_SAT_MASK) >>
-                               Altos.AO_GPS_NUM_SAT_SHIFT;
-                       break;
-               case Altos.AO_LOG_GPS_LAT:
-                       int lat32 = record.a | (record.b << 16);
-                       state.gps.lat = (double) lat32 / 1e7;
-                       break;
-               case Altos.AO_LOG_GPS_LON:
-                       int lon32 = record.a | (record.b << 16);
-                       state.gps.lon = (double) lon32 / 1e7;
-                       break;
-               case Altos.AO_LOG_GPS_ALT:
-                       state.gps.alt = record.a;
-                       break;
-               case Altos.AO_LOG_GPS_SAT:
-                       if (state.tick == eeprom.gps_tick) {
-                               int svid = record.a;
-                               int c_n0 = record.b >> 8;
-                               state.gps.add_sat(svid, c_n0);
-                       }
-                       break;
-               case Altos.AO_LOG_GPS_DATE:
-                       state.gps.year = (record.a & 0xff) + 2000;
-                       state.gps.month = record.a >> 8;
-                       state.gps.day = record.b & 0xff;
-                       break;
-
-               case Altos.AO_LOG_CONFIG_VERSION:
-                       break;
-               case Altos.AO_LOG_MAIN_DEPLOY:
-                       break;
-               case Altos.AO_LOG_APOGEE_DELAY:
-                       break;
-               case Altos.AO_LOG_RADIO_CHANNEL:
-                       break;
-               case Altos.AO_LOG_CALLSIGN:
-                       state.callsign = record.data;
-                       break;
-               case Altos.AO_LOG_ACCEL_CAL:
-                       state.accel_plus_g = record.a;
-                       state.accel_minus_g = record.b;
-                       break;
-               case Altos.AO_LOG_RADIO_CAL:
-                       break;
-               case Altos.AO_LOG_MANUFACTURER:
-                       break;
-               case Altos.AO_LOG_PRODUCT:
-                       break;
-               case Altos.AO_LOG_SERIAL_NUMBER:
-                       state.serial = record.a;
-                       break;
-               case Altos.AO_LOG_SOFTWARE_VERSION:
-                       break;
-               }
-       }
-
-       LinkedList<AltosRecord> make_list() {
-               LinkedList<AltosRecord>         list = new LinkedList<AltosRecord>();
-               Iterator<AltosOrderedRecord>    iterator = records.iterator();
-               AltosOrderedRecord              record = null;
-               AltosRecord                     state = new AltosRecord();
-               boolean                         last_reported = false;
-               EepromState                     eeprom = new EepromState();
-
-               state.state = Altos.ao_flight_pad;
-               state.accel_plus_g = 15758;
-               state.accel_minus_g = 16294;
-
-               /* Pull in static data from the flight and gps_date records */
-               if (flight_record != null)
-                       update_state(state, flight_record, eeprom);
-               if (gps_date_record != null)
-                       update_state(state, gps_date_record, eeprom);
-
-               while (iterator.hasNext()) {
-                       record = iterator.next();
-                       if ((eeprom.seen & seen_basic) == seen_basic && record.tick != state.tick) {
-                               AltosRecord r = new AltosRecord(state);
-                               r.time = (r.tick - eeprom.boost_tick) / 100.0;
-                               list.add(r);
-                       }
-                       update_state(state, record, eeprom);
-               }
-               AltosRecord r = new AltosRecord(state);
-               r.time = (r.tick - eeprom.boost_tick) / 100.0;
-               list.add(r);
-               return list;
-       }
-
-       public Iterator<AltosRecord> iterator() {
-               if (list == null)
-                       list = make_list();
-               return list.iterator();
-       }
-
-       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) {
-                       case Altos.AO_LOG_CONFIG_VERSION:
-                               out.printf("# Config version: %s\n", record.data);
-                               break;
-                       case Altos.AO_LOG_MAIN_DEPLOY:
-                               out.printf("# Main deploy: %s\n", record.a);
-                               break;
-                       case Altos.AO_LOG_APOGEE_DELAY:
-                               out.printf("# Apogee delay: %s\n", record.a);
-                               break;
-                       case Altos.AO_LOG_RADIO_CHANNEL:
-                               out.printf("# Radio channel: %s\n", record.a);
-                               break;
-                       case Altos.AO_LOG_CALLSIGN:
-                               out.printf("# Callsign: %s\n", record.data);
-                               break;
-                       case Altos.AO_LOG_ACCEL_CAL:
-                               out.printf ("# Accel cal: %d %d\n", record.a, record.b);
-                               break;
-                       case Altos.AO_LOG_RADIO_CAL:
-                               out.printf ("# Radio cal: %d\n", record.a);
-                               break;
-                       case Altos.AO_LOG_MANUFACTURER:
-                               out.printf ("# Manufacturer: %s\n", record.data);
-                               break;
-                       case Altos.AO_LOG_PRODUCT:
-                               out.printf ("# Product: %s\n", record.data);
-                               break;
-                       case Altos.AO_LOG_SERIAL_NUMBER:
-                               out.printf ("# Serial number: %d\n", record.a);
-                               break;
-                       case Altos.AO_LOG_SOFTWARE_VERSION:
-                               out.printf ("# Software version: %s\n", record.data);
-                               break;
-                       }
-               }
-       }
-
-       /*
-        * Given an AO_LOG_GPS_TIME record with correct time, and one
-        * missing time, rewrite the missing time values with the good
-        * ones, assuming that the difference between them is 'diff' seconds
-        */
-       void update_time(AltosOrderedRecord good, AltosOrderedRecord bad) {
-
-               int diff = (bad.tick - good.tick + 50) / 100;
-
-               int hour = (good.a & 0xff);
-               int minute = (good.a >> 8);
-               int second = (good.b & 0xff);
-               int flags = (good.b >> 8);
-               int seconds = hour * 3600 + minute * 60 + second;
-
-               /* Make sure this looks like a good GPS value */
-               if ((flags & Altos.AO_GPS_NUM_SAT_MASK) >> Altos.AO_GPS_NUM_SAT_SHIFT < 4)
-                       flags = (flags & ~Altos.AO_GPS_NUM_SAT_MASK) | (4 << Altos.AO_GPS_NUM_SAT_SHIFT);
-               flags |= Altos.AO_GPS_RUNNING;
-               flags |= Altos.AO_GPS_VALID;
-
-               int new_seconds = seconds + diff;
-               if (new_seconds < 0)
-                       new_seconds += 24 * 3600;
-               int new_second = (new_seconds % 60);
-               int new_minutes = (new_seconds / 60);
-               int new_minute = (new_minutes % 60);
-               int new_hours = (new_minutes / 60);
-               int new_hour = (new_hours % 24);
-
-               bad.a = new_hour + (new_minute << 8);
-               bad.b = new_second + (flags << 8);
-       }
-
-       /*
-        * Read the whole file, dumping records into a RB tree so
-        * we can enumerate them in time order -- the eeprom data
-        * are sometimes out of order with GPS data getting timestamps
-        * matching the first packet out of the GPS unit but not
-        * written until the final GPS packet has been received.
-        */
-       public AltosEepromIterable (FileInputStream input) {
-               records = new TreeSet<AltosOrderedRecord>();
-
-               AltosOrderedRecord last_gps_time = null;
-
-               int index = 0;
-               int prev_tick = 0;
-               boolean prev_tick_valid = false;
-               boolean missing_time = false;
-
-               try {
-                       for (;;) {
-                               String line = AltosRecord.gets(input);
-                               if (line == null)
-                                       break;
-                               AltosOrderedRecord record = new AltosOrderedRecord(line, index++, prev_tick, prev_tick_valid);
-                               if (record == null)
-                                       break;
-                               if (record.cmd == Altos.AO_LOG_INVALID)
-                                       continue;
-                               prev_tick = record.tick;
-                               if (record.cmd < Altos.AO_LOG_CONFIG_VERSION)
-                                       prev_tick_valid = true;
-                               if (record.cmd == Altos.AO_LOG_FLIGHT) {
-                                       flight_record = record;
-                                       continue;
-                               }
-
-                               /* Two firmware bugs caused the loss of some GPS data.
-                                * The flight date would never be recorded, and often
-                                * the flight time would get overwritten by another
-                                * record. Detect the loss of the GPS date and fix up the
-                                * missing time records
-                                */
-                               if (record.cmd == Altos.AO_LOG_GPS_DATE) {
-                                       gps_date_record = record;
-                                       continue;
-                               }
-
-                               /* go back and fix up any missing time values */
-                               if (record.cmd == Altos.AO_LOG_GPS_TIME) {
-                                       last_gps_time = record;
-                                       if (missing_time) {
-                                               Iterator<AltosOrderedRecord> iterator = records.iterator();
-                                               while (iterator.hasNext()) {
-                                                       AltosOrderedRecord old = iterator.next();
-                                                       if (old.cmd == Altos.AO_LOG_GPS_TIME &&
-                                                           old.a == -1 && old.b == -1)
-                                                       {
-                                                               update_time(record, old);
-                                                       }
-                                               }
-                                               missing_time = false;
-                                       }
-                               }
-
-                               if (record.cmd == Altos.AO_LOG_GPS_LAT) {
-                                       if (last_gps_time == null || last_gps_time.tick != record.tick) {
-                                               AltosOrderedRecord add_gps_time = new AltosOrderedRecord(Altos.AO_LOG_GPS_TIME,
-                                                                                                        record.tick,
-                                                                                                        -1, -1, index-1);
-                                               if (last_gps_time != null)
-                                                       update_time(last_gps_time, add_gps_time);
-                                               else
-                                                       missing_time = true;
-
-                                               records.add(add_gps_time);
-                                               record.index = index++;
-                                       }
-                               }
-                               records.add(record);
-
-                               /* Bail after reading the 'landed' record; we're all done */
-                               if (record.cmd == Altos.AO_LOG_STATE &&
-                                   record.a == Altos.ao_flight_landed)
-                                       break;
-                       }
-               } catch (IOException io) {
-               } catch (ParseException pe) {
-               }
-               try {
-                       input.close();
-               } catch (IOException ie) {
-               }
-       }
-}
diff --git a/ao-tools/altosui/AltosEepromMonitor.java b/ao-tools/altosui/AltosEepromMonitor.java
deleted file mode 100644 (file)
index 7ff00ea..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * 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;
-
-public class AltosEepromMonitor extends JDialog {
-
-       Container       pane;
-       Box             box;
-       JLabel          serial_label;
-       JLabel          flight_label;
-       JLabel          file_label;
-       JLabel          serial_value;
-       JLabel          flight_value;
-       JLabel          file_value;
-       JButton         cancel;
-       JProgressBar    pbar;
-       int             min_state, max_state;
-
-       public AltosEepromMonitor(JFrame owner, int in_min_state, int in_max_state) {
-               super (owner, "Download Flight Data", false);
-
-               GridBagConstraints c;
-               Insets il = new Insets(4,4,4,4);
-               Insets ir = new Insets(4,4,4,4);
-
-               pane = getContentPane();
-               pane.setLayout(new GridBagLayout());
-
-               c = new GridBagConstraints();
-               c.gridx = 0; c.gridy = 0;
-               c.fill = GridBagConstraints.NONE;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = il;
-               serial_label = new JLabel("Serial:");
-               pane.add(serial_label, c);
-
-               c = new GridBagConstraints();
-               c.gridx = 1; c.gridy = 0;
-               c.fill = GridBagConstraints.HORIZONTAL;
-               c.weightx = 1;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = ir;
-               serial_value = new JLabel("");
-               pane.add(serial_value, c);
-
-               c = new GridBagConstraints();
-               c.fill = GridBagConstraints.NONE;
-               c.gridx = 0; c.gridy = 1;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = il;
-               flight_label = new JLabel("Flight:");
-               pane.add(flight_label, c);
-
-               c = new GridBagConstraints();
-               c.fill = GridBagConstraints.HORIZONTAL;
-               c.weightx = 1;
-               c.gridx = 1; c.gridy = 1;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = ir;
-               flight_value = new JLabel("");
-               pane.add(flight_value, c);
-
-               c = new GridBagConstraints();
-               c.fill = GridBagConstraints.NONE;
-               c.gridx = 0; c.gridy = 2;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = il;
-               file_label = new JLabel("File:");
-               pane.add(file_label, c);
-
-               c = new GridBagConstraints();
-               c.fill = GridBagConstraints.HORIZONTAL;
-               c.weightx = 1;
-               c.gridx = 1; c.gridy = 2;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = ir;
-               file_value = new JLabel("");
-               pane.add(file_value, c);
-
-               min_state = in_min_state;
-               max_state = in_max_state;
-               pbar = new JProgressBar();
-               pbar.setMinimum(0);
-               pbar.setMaximum((max_state - min_state) * 100);
-               pbar.setValue(0);
-               pbar.setString("startup");
-               pbar.setStringPainted(true);
-               pbar.setPreferredSize(new Dimension(600, 20));
-               c = new GridBagConstraints();
-               c.fill = GridBagConstraints.HORIZONTAL;
-               c.anchor = GridBagConstraints.CENTER;
-               c.gridx = 0; c.gridy = 3;
-               c.gridwidth = GridBagConstraints.REMAINDER;
-               Insets ib = new Insets(4,4,4,4);
-               c.insets = ib;
-               pane.add(pbar, c);
-
-
-               cancel = new JButton("Cancel");
-               c = new GridBagConstraints();
-               c.fill = GridBagConstraints.NONE;
-               c.anchor = GridBagConstraints.CENTER;
-               c.gridx = 0; c.gridy = 4;
-               c.gridwidth = GridBagConstraints.REMAINDER;
-               Insets ic = new Insets(4,4,4,4);
-               c.insets = ic;
-               pane.add(cancel, c);
-
-               pack();
-               setLocationRelativeTo(owner);
-               setVisible(true);
-       }
-
-       public void addActionListener (ActionListener l) {
-               cancel.addActionListener(l);
-       }
-
-       public void set_value(String state_name, int in_state, int in_block) {
-               int block = in_block;
-               int state = in_state;
-
-               if (block > 100)
-                       block = 100;
-               if (state < min_state) state = min_state;
-               if (state >= max_state) state = max_state - 1;
-               state -= min_state;
-
-               int pos = state * 100 + block;
-
-               pbar.setString(state_name);
-               pbar.setValue(pos);
-       }
-
-       public void set_serial(int serial) {
-               serial_value.setText(String.format("%d", serial));
-       }
-
-       public void set_flight(int flight) {
-               flight_value.setText(String.format("%d", flight));
-       }
-
-       public void set_file(String file) {
-               file_value.setText(String.format("%s", file));
-       }
-
-       public void done() {
-               setVisible(false);
-               dispose();
-       }
-}
diff --git a/ao-tools/altosui/AltosEepromRecord.java b/ao-tools/altosui/AltosEepromRecord.java
deleted file mode 100644 (file)
index 5a67381..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * 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;
-
-public class AltosEepromRecord {
-       public int      cmd;
-       public int      tick;
-       public int      a;
-       public int      b;
-       public String   data;
-       public boolean  tick_valid;
-
-       public AltosEepromRecord (String line) {
-               tick_valid = false;
-               tick = 0;
-               a = 0;
-               b = 0;
-               data = null;
-               if (line == null) {
-                       cmd = Altos.AO_LOG_INVALID;
-                       data = "";
-               } else {
-                       try {
-                               String[] tokens = line.split("\\s+");
-
-                               if (tokens[0].length() == 1) {
-                                       if (tokens.length != 4) {
-                                               cmd = Altos.AO_LOG_INVALID;
-                                               data = line;
-                                       } else {
-                                               cmd = tokens[0].codePointAt(0);
-                                               tick = Integer.parseInt(tokens[1],16);
-                                               tick_valid = true;
-                                               a = Integer.parseInt(tokens[2],16);
-                                               b = Integer.parseInt(tokens[3],16);
-                                       }
-                               } else if (tokens[0].equals("Config") && tokens[1].equals("version:")) {
-                                       cmd = Altos.AO_LOG_CONFIG_VERSION;
-                                       data = tokens[2];
-                               } else if (tokens[0].equals("Main") && tokens[1].equals("deploy:")) {
-                                       cmd = Altos.AO_LOG_MAIN_DEPLOY;
-                                       a = Integer.parseInt(tokens[2]);
-                               } else if (tokens[0].equals("Apogee") && tokens[1].equals("delay:")) {
-                                       cmd = Altos.AO_LOG_APOGEE_DELAY;
-                                       a = Integer.parseInt(tokens[2]);
-                               } else if (tokens[0].equals("Radio") && tokens[1].equals("channel:")) {
-                                       cmd = Altos.AO_LOG_RADIO_CHANNEL;
-                                       a = Integer.parseInt(tokens[2]);
-                               } else if (tokens[0].equals("Callsign:")) {
-                                       cmd = Altos.AO_LOG_CALLSIGN;
-                                       data = tokens[1].replaceAll("\"","");
-                               } else if (tokens[0].equals("Accel") && tokens[1].equals("cal")) {
-                                       cmd = Altos.AO_LOG_ACCEL_CAL;
-                                       a = Integer.parseInt(tokens[3]);
-                                       b = Integer.parseInt(tokens[5]);
-                               } else if (tokens[0].equals("Radio") && tokens[1].equals("cal:")) {
-                                       cmd = Altos.AO_LOG_RADIO_CAL;
-                                       a = Integer.parseInt(tokens[2]);
-                               } else if (tokens[0].equals("manufacturer")) {
-                                       cmd = Altos.AO_LOG_MANUFACTURER;
-                                       data = tokens[1];
-                               } else if (tokens[0].equals("product")) {
-                                       cmd = Altos.AO_LOG_PRODUCT;
-                                       data = tokens[1];
-                               } else if (tokens[0].equals("serial-number")) {
-                                       cmd = Altos.AO_LOG_SERIAL_NUMBER;
-                                       a = Integer.parseInt(tokens[1]);
-                               } else if (tokens[0].equals("software-version")) {
-                                       cmd = Altos.AO_LOG_SOFTWARE_VERSION;
-                                       data = tokens[1];
-                               } else {
-                                       cmd = Altos.AO_LOG_INVALID;
-                                       data = line;
-                               }
-                       } catch (NumberFormatException ne) {
-                               cmd = Altos.AO_LOG_INVALID;
-                               data = line;
-                       }
-               }
-       }
-
-       public AltosEepromRecord(int in_cmd, int in_tick, int in_a, int in_b) {
-               tick_valid = true;
-               cmd = in_cmd;
-               tick = in_tick;
-               a = in_a;
-               b = in_b;
-       }
-}
diff --git a/ao-tools/altosui/AltosFile.java b/ao-tools/altosui/AltosFile.java
deleted file mode 100644 (file)
index 0636057..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.lang.*;
-import java.io.File;
-import java.util.*;
-
-class AltosFile extends File {
-
-       public AltosFile(int year, int month, int day, int serial, int flight, String extension) {
-               super (AltosPreferences.logdir(),
-                      String.format("%04d-%02d-%02d-serial-%03d-flight-%03d.%s",
-                                    year, month, day, serial, flight, extension));
-       }
-
-       public AltosFile(int serial, int flight, String extension) {
-               this(Calendar.getInstance().get(Calendar.YEAR),
-                    Calendar.getInstance().get(Calendar.MONTH) + 1,
-                    Calendar.getInstance().get(Calendar.DAY_OF_MONTH),
-                    serial,
-                    flight,
-                    extension);
-       }
-
-       public AltosFile(AltosTelemetry telem) {
-               this(telem.serial, telem.flight, "telem");
-       }
-}
diff --git a/ao-tools/altosui/AltosFlash.java b/ao-tools/altosui/AltosFlash.java
deleted file mode 100644 (file)
index 3af25c2..0000000
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- * 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;
-
-public class AltosFlash {
-       File            file;
-       FileInputStream input;
-       AltosHexfile    image;
-       JFrame          frame;
-       AltosDevice     debug_dongle;
-       AltosDebug      debug;
-       AltosRomconfig  rom_config;
-       ActionListener  listener;
-       boolean         aborted;
-
-       static final byte MOV_direct_data       = (byte) 0x75;
-       static final byte MOV_DPTR_data16       = (byte) 0x90;
-       static final byte MOV_A_data            = (byte) 0x74;
-       static final byte MOVX_atDPTR_A         = (byte) 0xf0;
-       static final byte MOVX_A_atDPTR         = (byte) 0xe0;
-       static final byte INC_DPTR              = (byte) 0xa3;
-       static final byte TRAP                  = (byte) 0xa5;
-
-       static final byte JB                    = (byte) 0x20;
-
-       static final byte MOV_A_direct          = (byte) 0xe5;
-       static final byte MOV_direct1_direct2   = (byte) 0x85;
-       static final byte MOV_direct_A          = (byte) 0xf5;
-       static final byte MOV_R0_data           = (byte) (0x78 | 0);
-       static final byte MOV_R1_data           = (byte) (0x78 | 1);
-       static final byte MOV_R2_data           = (byte) (0x78 | 2);
-       static final byte MOV_R3_data           = (byte) (0x78 | 3);
-       static final byte MOV_R4_data           = (byte) (0x78 | 4);
-       static final byte MOV_R5_data           = (byte) (0x78 | 5);
-       static final byte MOV_R6_data           = (byte) (0x78 | 6);
-       static final byte MOV_R7_data           = (byte) (0x78 | 7);
-       static final byte DJNZ_R0_rel           = (byte) (0xd8 | 0);
-       static final byte DJNZ_R1_rel           = (byte) (0xd8 | 1);
-       static final byte DJNZ_R2_rel           = (byte) (0xd8 | 2);
-       static final byte DJNZ_R3_rel           = (byte) (0xd8 | 3);
-       static final byte DJNZ_R4_rel           = (byte) (0xd8 | 4);
-       static final byte DJNZ_R5_rel           = (byte) (0xd8 | 5);
-       static final byte DJNZ_R6_rel           = (byte) (0xd8 | 6);
-       static final byte DJNZ_R7_rel           = (byte) (0xd8 | 7);
-
-       static final byte P1DIR                 = (byte) 0xFE;
-       static final byte P1                    = (byte) 0x90;
-
-       /* flash controller */
-       static final byte FWT                   = (byte) 0xAB;
-       static final byte FADDRL                = (byte) 0xAC;
-       static final byte FADDRH                = (byte) 0xAD;
-       static final byte FCTL                  = (byte) 0xAE;
-       static final byte FCTL_BUSY             = (byte) 0x80;
-       static final byte FCTL_BUSY_BIT         = (byte) 7;
-       static final byte FCTL_SWBSY            = (byte) 0x40;
-       static final byte FCTL_SWBSY_BIT        = (byte) 6;
-       static final byte FCTL_CONTRD           = (byte) 0x10;
-       static final byte FCTL_WRITE            = (byte) 0x02;
-       static final byte FCTL_ERASE            = (byte) 0x01;
-       static final byte FWDATA                = (byte) 0xAF;
-
-       static final byte ACC                   = (byte) 0xE0;
-
-       /* offsets within the flash_page program */
-       static final int FLASH_ADDR_HIGH        = 8;
-       static final int FLASH_ADDR_LOW         = 11;
-       static final int RAM_ADDR_HIGH          = 13;
-       static final int RAM_ADDR_LOW           = 14;
-       static final int FLASH_WORDS_HIGH       = 16;
-       static final int FLASH_WORDS_LOW        = 18;
-       static final int FLASH_TIMING           = 21;
-
-       /* sleep mode control */
-       static final int SLEEP                  = (byte) 0xbe;
-       static final int  SLEEP_USB_EN          = (byte) 0x80;
-       static final int  SLEEP_XOSC_STB        = (byte) 0x40;
-       static final int  SLEEP_HFRC_STB        = (byte) 0x20;
-       static final int  SLEEP_RST_MASK        = (byte) 0x18;
-       static final int   SLEEP_RST_POWERON    = (byte) 0x00;
-       static final int   SLEEP_RST_EXTERNAL   = (byte) 0x10;
-       static final int   SLEEP_RST_WATCHDOG   = (byte) 0x08;
-       static final int  SLEEP_OSC_PD          = (byte) 0x04;
-       static final int  SLEEP_MODE_MASK       = (byte) 0x03;
-       static final int   SLEEP_MODE_PM0       = (byte) 0x00;
-       static final int   SLEEP_MODE_PM1       = (byte) 0x01;
-       static final int   SLEEP_MODE_PM2       = (byte) 0x02;
-       static final int   SLEEP_MODE_PM3       = (byte) 0x03;
-
-       /* clock controller */
-       static final byte CLKCON                = (byte) 0xC6;
-       static final byte  CLKCON_OSC32K        = (byte) 0x80;
-       static final byte  CLKCON_OSC           = (byte) 0x40;
-       static final byte  CLKCON_TICKSPD       = (byte) 0x38;
-       static final byte  CLKCON_CLKSPD        = (byte) 0x07;
-
-       static final byte[] flash_page_proto = {
-
-               MOV_direct_data, P1DIR, (byte) 0x02,
-               MOV_direct_data, P1,    (byte) 0xFF,
-
-               MOV_direct_data, FADDRH, 0,     /* FLASH_ADDR_HIGH */
-
-               MOV_direct_data, FADDRL, 0,     /* FLASH_ADDR_LOW */
-
-               MOV_DPTR_data16, 0, 0,          /* RAM_ADDR_HIGH, RAM_ADDR_LOW */
-
-               MOV_R7_data, 0,                 /* FLASH_WORDS_HIGH */
-
-               MOV_R6_data, 0,                 /* FLASH_WORDS_LOW */
-
-
-               MOV_direct_data, FWT, 0x20,     /* FLASH_TIMING */
-
-               MOV_direct_data, FCTL, FCTL_ERASE,
-/* eraseWaitLoop: */
-               MOV_A_direct,           FCTL,
-               JB, ACC|FCTL_BUSY_BIT, (byte) 0xfb,
-
-               MOV_direct_data, P1, (byte) 0xfd,
-
-               MOV_direct_data, FCTL, FCTL_WRITE,
-/* writeLoop: */
-               MOV_R5_data, 2,
-/* writeWordLoop: */
-               MOVX_A_atDPTR,
-               INC_DPTR,
-               MOV_direct_A, FWDATA,
-               DJNZ_R5_rel, (byte) 0xfa,               /* writeWordLoop */
-/* writeWaitLoop: */
-               MOV_A_direct, FCTL,
-               JB, ACC|FCTL_SWBSY_BIT, (byte) 0xfb,    /* writeWaitLoop */
-               DJNZ_R6_rel, (byte) 0xf1,               /* writeLoop */
-               DJNZ_R7_rel, (byte) 0xef,                       /* writeLoop */
-
-               MOV_direct_data, P1DIR, (byte) 0x00,
-               MOV_direct_data, P1,    (byte) 0xFF,
-               TRAP,
-       };
-
-       public byte[] make_flash_page(int flash_addr, int ram_addr, int byte_count) {
-               int flash_word_addr = flash_addr >> 1;
-               int flash_word_count = ((byte_count + 1) >> 1);
-
-               byte[] flash_page = new byte[flash_page_proto.length];
-               for (int i = 0; i < flash_page.length; i++)
-                       flash_page[i] = flash_page_proto[i];
-
-               flash_page[FLASH_ADDR_HIGH]  = (byte) (flash_word_addr >> 8);
-               flash_page[FLASH_ADDR_LOW]   = (byte) (flash_word_addr);
-               flash_page[RAM_ADDR_HIGH]    = (byte) (ram_addr >> 8);
-               flash_page[RAM_ADDR_LOW]     = (byte) (ram_addr);
-
-               byte flash_words_low = (byte) (flash_word_count);
-               byte flash_words_high = (byte) (flash_word_count >> 8);
-               /* the flashing code has a minor 'bug' */
-               if (flash_words_low != 0)
-                       flash_words_high++;
-
-               flash_page[FLASH_WORDS_HIGH] = (byte) flash_words_high;
-               flash_page[FLASH_WORDS_LOW]  = (byte) flash_words_low;
-               return flash_page;
-       }
-
-       static byte[] set_clkcon_fast = {
-               MOV_direct_data, CLKCON, 0x00
-       };
-
-       static byte[] get_sleep = {
-               MOV_A_direct, SLEEP
-       };
-
-       public void clock_init() throws IOException, InterruptedException {
-               debug.debug_instr(set_clkcon_fast);
-
-               byte    status;
-               for (int times = 0; times < 20; times++) {
-                       Thread.sleep(1);
-                       status = debug.debug_instr(get_sleep);
-                       if ((status & SLEEP_XOSC_STB) != 0)
-                               return;
-               }
-               throw new IOException("Failed to initialize target clock");
-       }
-
-       void action(String s, int percent) {
-               if (listener != null && !aborted)
-                       listener.actionPerformed(new ActionEvent(this,
-                                                                percent,
-                                                                s));
-       }
-
-       void action(int part, int total) {
-               int percent = 100 * part / total;
-               action(String.format("%d/%d (%d%%)",
-                                    part, total, percent),
-                      percent);
-       }
-
-       void run(int pc) throws IOException, InterruptedException {
-               debug.set_pc(pc);
-               int set_pc = debug.get_pc();
-               if (pc != set_pc)
-                       throw new IOException("Failed to set target program counter");
-               debug.resume();
-
-               for (int times = 0; times < 20; times++) {
-                       byte status = debug.read_status();
-                       if ((status & AltosDebug.STATUS_CPU_HALTED) != 0)
-                               return;
-               }
-
-               throw new IOException("Failed to execute program on target");
-       }
-
-       public void flash() throws IOException, FileNotFoundException, InterruptedException {
-               if (!check_rom_config())
-                       throw new IOException("Invalid rom config settings");
-               if (image.address + image.data.length > 0x8000)
-                       throw new IOException(String.format("Flash image too long %d",
-                                                           image.address +
-                                                           image.data.length));
-               if ((image.address & 0x3ff) != 0)
-                       throw new IOException(String.format("Flash image must start on page boundary (is 0x%x)",
-                                                           image.address));
-               int ram_address = 0xf000;
-               int flash_prog = 0xf400;
-
-               /*
-                * Store desired config values into image
-                */
-               rom_config.write(image);
-               /*
-                * Bring up the clock
-                */
-               clock_init();
-
-               int remain = image.data.length;
-               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;
-                       if (this_time > 0x400)
-                               this_time = 0x400;
-
-                       /* write the data */
-                       debug.write_memory(ram_address, image.data,
-                                          image_start, this_time);
-
-                       /* write the flash program */
-                       byte[] flash_page = make_flash_page(flash_addr,
-                                                           ram_address,
-                                                           this_time);
-                       debug.write_memory(flash_prog, flash_page);
-
-                       run(flash_prog);
-
-                       byte[] check = debug.read_memory(flash_addr, this_time);
-                       for (int i = 0; i < this_time; i++)
-                               if (check[i] != image.data[image_start + i])
-                                       throw new IOException(String.format("Flash write failed at 0x%x (%02x != %02x)",
-                                                                           image.address + image_start + i,
-                                                                           check[i], image.data[image_start + i]));
-                       remain -= this_time;
-                       flash_addr += this_time;
-                       image_start += this_time;
-
-                       action(image.data.length - remain, image.data.length);
-               }
-               if (!aborted) {
-                       action("done", 100);
-                       debug.set_pc(image.address);
-                       debug.resume();
-               }
-               debug.close();
-       }
-
-       public void abort() {
-               aborted = true;
-               debug.close();
-       }
-
-       public void addActionListener(ActionListener l) {
-               listener = l;
-       }
-
-       public boolean check_rom_config() {
-               if (rom_config == null)
-                       rom_config = debug.romconfig();
-               return rom_config != null && rom_config.valid();
-       }
-
-       public void set_romconfig (AltosRomconfig romconfig) {
-               rom_config = romconfig;
-       }
-
-       public AltosRomconfig romconfig() {
-               if (!check_rom_config())
-                       return null;
-               return rom_config;
-       }
-
-       public AltosFlash(File in_file, AltosDevice in_debug_dongle)
-               throws IOException, FileNotFoundException, AltosSerialInUseException, InterruptedException {
-               file = in_file;
-               debug_dongle = in_debug_dongle;
-               debug = new AltosDebug(in_debug_dongle);
-               input = new FileInputStream(file);
-               image = new AltosHexfile(input);
-               if (!debug.check_connection()) {
-                       debug.close();
-                       throw new IOException("Debug port not connected");
-               }
-       }
-}
\ No newline at end of file
diff --git a/ao-tools/altosui/AltosFlashUI.java b/ao-tools/altosui/AltosFlashUI.java
deleted file mode 100644 (file)
index f63097a..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * 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;
-
-public class AltosFlashUI
-       extends JDialog
-       implements Runnable, ActionListener
-{
-       Container       pane;
-       Box             box;
-       JLabel          serial_label;
-       JLabel          serial_value;
-       JLabel          file_label;
-       JLabel          file_value;
-       JProgressBar    pbar;
-       JButton         cancel;
-
-       File            file;
-       Thread          thread;
-       JFrame          frame;
-       AltosDevice     debug_dongle;
-       AltosFlash      flash;
-
-       public void actionPerformed(ActionEvent e) {
-               if (e.getSource() == cancel) {
-                       abort();
-                       dispose();
-               } else {
-                       String  cmd = e.getActionCommand();
-                       if (cmd.equals("done"))
-                               ;
-                       else if (cmd.equals("start")) {
-                               setVisible(true);
-                       } else {
-                               pbar.setValue(e.getID());
-                               pbar.setString(cmd);
-                       }
-               }
-       }
-
-       public void run() {
-               try {
-                       flash = new AltosFlash(file, debug_dongle);
-                       flash.addActionListener(this);
-                       AltosRomconfigUI romconfig_ui = new AltosRomconfigUI (frame);
-
-                       romconfig_ui.set(flash.romconfig());
-                       AltosRomconfig romconfig = romconfig_ui.showDialog();
-
-                       if (romconfig != null && romconfig.valid()) {
-                               flash.set_romconfig(romconfig);
-                               serial_value.setText(String.format("%d",
-                                                                  flash.romconfig().serial_number));
-                               file_value.setText(file.toString());
-                               setVisible(true);
-                               flash.flash();
-                               flash = null;
-                       }
-               } catch (FileNotFoundException ee) {
-                       JOptionPane.showMessageDialog(frame,
-                                                     "Cannot open image",
-                                                     file.toString(),
-                                                     JOptionPane.ERROR_MESSAGE);
-               } catch (AltosSerialInUseException si) {
-                       JOptionPane.showMessageDialog(frame,
-                                                     String.format("Device \"%s\" already in use",
-                                                                   debug_dongle.toShortString()),
-                                                     "Device in use",
-                                                     JOptionPane.ERROR_MESSAGE);
-               } catch (IOException e) {
-                       JOptionPane.showMessageDialog(frame,
-                                                     e.getMessage(),
-                                                     file.toString(),
-                                                     JOptionPane.ERROR_MESSAGE);
-               } catch (InterruptedException ie) {
-               } finally {
-                       abort();
-               }
-               dispose();
-       }
-
-       public void abort() {
-               if (flash != null)
-                       flash.abort();
-       }
-
-       public void build_dialog() {
-               GridBagConstraints c;
-               Insets il = new Insets(4,4,4,4);
-               Insets ir = new Insets(4,4,4,4);
-
-               pane = getContentPane();
-               pane.setLayout(new GridBagLayout());
-
-               c = new GridBagConstraints();
-               c.gridx = 0; c.gridy = 0;
-               c.fill = GridBagConstraints.NONE;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = il;
-               serial_label = new JLabel("Serial:");
-               pane.add(serial_label, c);
-
-               c = new GridBagConstraints();
-               c.gridx = 1; c.gridy = 0;
-               c.fill = GridBagConstraints.HORIZONTAL;
-               c.weightx = 1;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = ir;
-               serial_value = new JLabel("");
-               pane.add(serial_value, c);
-
-               c = new GridBagConstraints();
-               c.fill = GridBagConstraints.NONE;
-               c.gridx = 0; c.gridy = 1;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = il;
-               file_label = new JLabel("File:");
-               pane.add(file_label, c);
-
-               c = new GridBagConstraints();
-               c.fill = GridBagConstraints.HORIZONTAL;
-               c.weightx = 1;
-               c.gridx = 1; c.gridy = 1;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = ir;
-               file_value = new JLabel("");
-               pane.add(file_value, c);
-
-               pbar = new JProgressBar();
-               pbar.setMinimum(0);
-               pbar.setMaximum(100);
-               pbar.setValue(0);
-               pbar.setString("");
-               pbar.setStringPainted(true);
-               pbar.setPreferredSize(new Dimension(600, 20));
-               c = new GridBagConstraints();
-               c.fill = GridBagConstraints.HORIZONTAL;
-               c.anchor = GridBagConstraints.CENTER;
-               c.gridx = 0; c.gridy = 2;
-               c.gridwidth = GridBagConstraints.REMAINDER;
-               Insets ib = new Insets(4,4,4,4);
-               c.insets = ib;
-               pane.add(pbar, c);
-
-               cancel = new JButton("Cancel");
-               c = new GridBagConstraints();
-               c.fill = GridBagConstraints.NONE;
-               c.anchor = GridBagConstraints.CENTER;
-               c.gridx = 0; c.gridy = 3;
-               c.gridwidth = GridBagConstraints.REMAINDER;
-               Insets ic = new Insets(4,4,4,4);
-               c.insets = ic;
-               pane.add(cancel, c);
-               cancel.addActionListener(this);
-               pack();
-               setLocationRelativeTo(frame);
-       }
-
-       public AltosFlashUI(JFrame in_frame) {
-               super(in_frame, "Program Altusmetrum Device", false);
-
-               frame = in_frame;
-
-               build_dialog();
-
-               debug_dongle = AltosDeviceDialog.show(frame, AltosDevice.product_any);
-
-               if (debug_dongle == null)
-                       return;
-
-               JFileChooser    hexfile_chooser = new JFileChooser();
-
-               File firmwaredir = AltosPreferences.firmwaredir();
-               if (firmwaredir != null)
-                       hexfile_chooser.setCurrentDirectory(firmwaredir);
-
-               hexfile_chooser.setDialogTitle("Select Flash Image");
-               hexfile_chooser.setFileFilter(new FileNameExtensionFilter("Flash Image", "ihx"));
-               int returnVal = hexfile_chooser.showOpenDialog(frame);
-
-               if (returnVal != JFileChooser.APPROVE_OPTION)
-                       return;
-
-               file = hexfile_chooser.getSelectedFile();
-
-               if (file != null)
-                       AltosPreferences.set_firmwaredir(file.getParentFile());
-
-               thread = new Thread(this);
-               thread.start();
-       }
-}
\ No newline at end of file
diff --git a/ao-tools/altosui/AltosFlightDisplay.java b/ao-tools/altosui/AltosFlightDisplay.java
deleted file mode 100644 (file)
index d18d1d1..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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;
-
-public interface AltosFlightDisplay {
-       void reset();
-
-       void show(AltosState state, int crc_errors);
-}
diff --git a/ao-tools/altosui/AltosFlightInfoTableModel.java b/ao-tools/altosui/AltosFlightInfoTableModel.java
deleted file mode 100644 (file)
index e23eff6..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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;
-
-public class AltosFlightInfoTableModel extends AbstractTableModel {
-       final static private String[] columnNames = {"Field", "Value"};
-
-       int     rows;
-       int     cols;
-       private String[][] data;
-
-       public int getColumnCount() { return cols; }
-       public int getRowCount() { return rows; }
-       public String getColumnName(int col) { return columnNames[col & 1]; }
-
-       public Object getValueAt(int row, int col) {
-               if (row >= rows || col >= cols)
-                       return "";
-               return data[row][col];
-       }
-
-       int[]   current_row;
-
-       public void reset() {
-               for (int i = 0; i < cols / 2; i++)
-                       current_row[i] = 0;
-       }
-
-       public void clear() {
-               reset();
-               for (int c = 0; c < cols; c++)
-                       for (int r = 0; r < rows; r++)
-                               data[r][c] = "";
-               fireTableDataChanged();
-       }
-
-       public void addRow(int col, String name, String value) {
-               if (current_row[col] < rows) {
-                       data[current_row[col]][col * 2] = name;
-                       data[current_row[col]][col * 2 + 1] = value;
-               }
-               current_row[col]++;
-       }
-
-       public void finish() {
-               for (int c = 0; c < cols / 2; c++)
-                       while (current_row[c] < rows)
-                               addRow(c, "", "");
-               fireTableDataChanged();
-       }
-
-       public AltosFlightInfoTableModel (int in_rows, int in_cols) {
-               rows = in_rows;
-               cols = in_cols * 2;
-               data = new String[rows][cols];
-               current_row = new int[in_cols];
-       }
-}
diff --git a/ao-tools/altosui/AltosFlightReader.java b/ao-tools/altosui/AltosFlightReader.java
deleted file mode 100644 (file)
index 3d59de9..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.lang.*;
-import java.text.*;
-import java.io.*;
-
-public class AltosFlightReader {
-       String name;
-
-       int serial;
-
-       void init() { }
-
-       AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException { return null; }
-
-       void close(boolean interrupted) { }
-
-       void set_channel(int channel) { }
-
-       void update(AltosState state) throws InterruptedException { }
-}
diff --git a/ao-tools/altosui/AltosFlightStatus.java b/ao-tools/altosui/AltosFlightStatus.java
deleted file mode 100644 (file)
index 59c9e9d..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * 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;
-
-public class AltosFlightStatus extends JComponent implements AltosFlightDisplay {
-       GridBagLayout   layout;
-
-       public class FlightValue {
-               JLabel          label;
-               JTextField      value;
-
-               void show(AltosState state, int crc_errors) {}
-
-               void reset() {
-                       value.setText("");
-               }
-               public FlightValue (GridBagLayout layout, int x, String text) {
-                       GridBagConstraints      c = new GridBagConstraints();
-                       c.insets = new Insets(5, 5, 5, 5);
-                       c.anchor = GridBagConstraints.CENTER;
-                       c.fill = GridBagConstraints.BOTH;
-                       c.weightx = 1;
-                       c.weighty = 1;
-
-                       label = new JLabel(text);
-                       label.setFont(Altos.status_font);
-                       label.setHorizontalAlignment(SwingConstants.CENTER);
-                       c.gridx = x; c.gridy = 0;
-                       layout.setConstraints(label, c);
-                       add(label);
-
-                       value = new JTextField("");
-                       value.setFont(Altos.status_font);
-                       value.setHorizontalAlignment(SwingConstants.CENTER);
-                       c.gridx = x; c.gridy = 1;
-                       layout.setConstraints(value, c);
-                       add(value);
-               }
-       }
-
-       class Call extends FlightValue {
-               void show(AltosState state, int crc_errors) {
-                       value.setText(state.data.callsign);
-               }
-               public Call (GridBagLayout layout, int x) {
-                       super (layout, x, "Callsign");
-               }
-       }
-
-       Call call;
-
-       class Serial extends FlightValue {
-               void show(AltosState state, int crc_errors) {
-                       value.setText(String.format("%d", state.data.serial));
-               }
-               public Serial (GridBagLayout layout, int x) {
-                       super (layout, x, "Serial");
-               }
-       }
-
-       Serial serial;
-
-       class Flight extends FlightValue {
-               void show(AltosState state, int crc_errors) {
-                       value.setText(String.format("%d", state.data.flight));
-               }
-               public Flight (GridBagLayout layout, int x) {
-                       super (layout, x, "Flight");
-               }
-       }
-
-       Flight flight;
-
-       class FlightState extends FlightValue {
-               void show(AltosState state, int crc_errors) {
-                       value.setText(state.data.state());
-               }
-               public FlightState (GridBagLayout layout, int x) {
-                       super (layout, x, "State");
-               }
-       }
-
-       FlightState flight_state;
-
-       class RSSI extends FlightValue {
-               void show(AltosState state, int crc_errors) {
-                       value.setText(String.format("%d", state.data.rssi));
-               }
-               public RSSI (GridBagLayout layout, int x) {
-                       super (layout, x, "RSSI (dBm)");
-               }
-       }
-
-       RSSI rssi;
-
-       public void reset () {
-               call.reset();
-               serial.reset();
-               flight.reset();
-               flight_state.reset();
-               rssi.reset();
-       }
-
-       public void show (AltosState state, int crc_errors) {
-               call.show(state, crc_errors);
-               serial.show(state, crc_errors);
-               flight.show(state, crc_errors);
-               flight_state.show(state, crc_errors);
-               rssi.show(state, crc_errors);
-       }
-
-       public int height() {
-               Dimension d = layout.preferredLayoutSize(this);
-               return d.height;
-       }
-
-       public AltosFlightStatus() {
-               layout = new GridBagLayout();
-
-               setLayout(layout);
-
-               call = new Call(layout, 0);
-               serial = new Serial(layout, 1);
-               flight = new Flight(layout, 2);
-               flight_state = new FlightState(layout, 3);
-               rssi = new RSSI(layout, 4);
-       }
-}
diff --git a/ao-tools/altosui/AltosFlightStatusTableModel.java b/ao-tools/altosui/AltosFlightStatusTableModel.java
deleted file mode 100644 (file)
index 4c24b6a..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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;
-
-public class AltosFlightStatusTableModel extends AbstractTableModel {
-       private String[] columnNames = {"Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" };
-       private Object[] data = { 0, "idle", 0, 0 };
-
-       public int getColumnCount() { return columnNames.length; }
-       public int getRowCount() { return 2; }
-       public Object getValueAt(int row, int col) {
-               if (row == 0)
-                       return columnNames[col];
-               return data[col];
-       }
-
-       public void setValueAt(Object value, int col) {
-               data[col] = value;
-               fireTableCellUpdated(1, col);
-       }
-
-       public void setValueAt(Object value, int row, int col) {
-               setValueAt(value, col);
-       }
-
-       public void set(AltosState state) {
-               setValueAt(String.format("%1.0f", state.height), 0);
-               setValueAt(state.data.state(), 1);
-               setValueAt(state.data.rssi, 2);
-               double speed = state.baro_speed;
-               if (state.ascent)
-                       speed = state.speed;
-               setValueAt(String.format("%1.0f", speed), 3);
-       }
-}
diff --git a/ao-tools/altosui/AltosFlightUI.java b/ao-tools/altosui/AltosFlightUI.java
deleted file mode 100644 (file)
index 24d25bd..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * 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;
-
-public class AltosFlightUI extends JFrame implements AltosFlightDisplay {
-       String[] statusNames = { "Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" };
-       Object[][] statusData = { { "0", "pad", "-50", "0" } };
-
-       AltosVoice              voice;
-       AltosFlightReader       reader;
-       AltosDisplayThread      thread;
-
-       JTabbedPane     pane;
-
-       AltosPad        pad;
-       AltosAscent     ascent;
-       AltosDescent    descent;
-       AltosLanded     landed;
-       AltosSiteMap    sitemap;
-
-       private AltosFlightStatus flightStatus;
-       private AltosInfoTable flightInfo;
-
-       static final int tab_pad = 1;
-       static final int tab_ascent = 2;
-       static final int tab_descent = 3;
-       static final int tab_landed = 4;
-
-       int cur_tab = 0;
-
-       boolean exit_on_close = false;
-
-       int which_tab(AltosState state) {
-               if (state.state < Altos.ao_flight_boost)
-                       return tab_pad;
-               if (state.state <= Altos.ao_flight_coast)
-                       return tab_ascent;
-               if (state.state <= Altos.ao_flight_main)
-                       return tab_descent;
-               return tab_landed;
-       }
-
-       void stop_display() {
-               if (thread != null && thread.isAlive()) {
-                       thread.interrupt();
-                       try {
-                               thread.join();
-                       } catch (InterruptedException ie) {}
-               }
-               thread = null;
-       }
-
-       void disconnect() {
-               stop_display();
-       }
-
-       public void reset() {
-               pad.reset();
-               ascent.reset();
-               descent.reset();
-               landed.reset();
-               flightInfo.clear();
-               sitemap.reset();
-       }
-
-       public void show(AltosState state, int crc_errors) {
-               int     tab = which_tab(state);
-               pad.show(state, crc_errors);
-               ascent.show(state, crc_errors);
-               descent.show(state, crc_errors);
-               landed.show(state, crc_errors);
-               if (tab != cur_tab) {
-                       switch (tab) {
-                       case tab_pad:
-                               pane.setSelectedComponent(pad);
-                               break;
-                       case tab_ascent:
-                               pane.setSelectedComponent(ascent);
-                               break;
-                       case tab_descent:
-                               pane.setSelectedComponent(descent);
-                               break;
-                       case tab_landed:
-                               pane.setSelectedComponent(landed);
-                       }
-                       cur_tab = tab;
-               }
-               flightStatus.show(state, crc_errors);
-               flightInfo.show(state, crc_errors);
-               sitemap.show(state, crc_errors);
-       }
-
-       public void set_exit_on_close() {
-               exit_on_close = true;
-       }
-
-       Container       bag;
-       JComboBox       channels;
-
-       public AltosFlightUI(AltosVoice in_voice, AltosFlightReader in_reader, final int serial) {
-               AltosPreferences.init(this);
-
-               voice = in_voice;
-               reader = in_reader;
-
-               bag = getContentPane();
-               bag.setLayout(new GridBagLayout());
-
-               GridBagConstraints c = new GridBagConstraints();
-
-               java.net.URL imgURL = AltosUI.class.getResource("/altus-metrum-16x16.jpg");
-               if (imgURL != null)
-                       setIconImage(new ImageIcon(imgURL).getImage());
-
-               setTitle(String.format("AltOS %s", reader.name));
-
-               /* Stick channel selector at top of table for telemetry monitoring */
-               if (serial >= 0) {
-                       // Channel menu
-                       channels = new AltosChannelMenu(AltosPreferences.channel(serial));
-                       channels.addActionListener(new ActionListener() {
-                               public void actionPerformed(ActionEvent e) {
-                                       int channel = channels.getSelectedIndex();
-                                       reader.set_channel(channel);
-                               }
-                       });
-                       c.gridx = 0;
-                       c.gridy = 0;
-                       c.anchor = GridBagConstraints.WEST;
-                       bag.add (channels, c);
-               }
-
-               /* Flight status is always visible */
-               flightStatus = new AltosFlightStatus();
-               c.gridx = 0;
-               c.gridy = 1;
-               c.fill = GridBagConstraints.HORIZONTAL;
-               c.weightx = 1;
-               bag.add(flightStatus, c);
-
-               /* The rest of the window uses a tabbed pane to
-                * show one of the alternate data views
-                */
-               pane = new JTabbedPane();
-
-               pad = new AltosPad();
-               pane.add("Launch Pad", pad);
-
-               ascent = new AltosAscent();
-               pane.add("Ascent", ascent);
-
-               descent = new AltosDescent();
-               pane.add("Descent", descent);
-
-               landed = new AltosLanded();
-               pane.add("Landed", landed);
-
-               flightInfo = new AltosInfoTable();
-               pane.add("Table", new JScrollPane(flightInfo));
-
-               sitemap = new AltosSiteMap();
-               pane.add("Site Map", sitemap);
-
-               /* Make the tabbed pane use the rest of the window space */
-               c.gridx = 0;
-               c.gridy = 2;
-               c.fill = GridBagConstraints.BOTH;
-               c.weightx = 1;
-               c.weighty = 1;
-               bag.add(pane, c);
-
-               setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
-               addWindowListener(new WindowAdapter() {
-                               @Override
-                               public void windowClosing(WindowEvent e) {
-                                       disconnect();
-                                       setVisible(false);
-                                       dispose();
-                                       if (exit_on_close)
-                                               System.exit(0);
-                               }
-                       });
-
-               pack();
-               setVisible(true);
-
-               thread = new AltosDisplayThread(this, voice, this, reader);
-
-               thread.start();
-       }
-
-       public AltosFlightUI (AltosVoice in_voice, AltosFlightReader in_reader) {
-               this(in_voice, in_reader, -1);
-       }
-}
diff --git a/ao-tools/altosui/AltosGPS.java b/ao-tools/altosui/AltosGPS.java
deleted file mode 100644 (file)
index 8382184..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * 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.lang.*;
-import java.text.*;
-
-public class AltosGPS {
-       public class AltosGPSSat {
-               int     svid;
-               int     c_n0;
-       }
-
-       int     nsat;
-       boolean locked;
-       boolean connected;
-       boolean date_valid;
-       double  lat;            /* degrees (+N -S) */
-       double  lon;            /* degrees (+E -W) */
-       int     alt;            /* m */
-       int     year;
-       int     month;
-       int     day;
-       int     hour;
-       int     minute;
-       int     second;
-
-       int     gps_extended;   /* has extra data */
-       double  ground_speed;   /* m/s */
-       int     course;         /* degrees */
-       double  climb_rate;     /* m/s */
-       double  hdop;           /* unitless? */
-       int     h_error;        /* m */
-       int     v_error;        /* m */
-
-       AltosGPSSat[] cc_gps_sat;       /* tracking data */
-
-       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);
-               hour = AltosParse.parse_int(hms[0]);
-               minute = AltosParse.parse_int(hms[1]);
-               second = AltosParse.parse_int(hms[2]);
-       }
-
-       void ClearGPSTime() {
-               year = month = day = 0;
-               hour = minute = second = 0;
-       }
-
-       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");
-
-               connected = false;
-               locked = false;
-               lat = lon = 0;
-               alt = 0;
-               ClearGPSTime();
-               if ((words[i]).equals("unlocked")) {
-                       connected = true;
-                       i++;
-               } else if ((words[i]).equals("not-connected")) {
-                       i++;
-               } else if (words.length >= 40) {
-                       locked = true;
-                       connected = true;
-
-                       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(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++;
-               }
-               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) {
-               lat = in_lat / 10.0e7;
-       }
-
-       public void set_longitude(int in_lon) {
-               lon = in_lon / 10.0e7;
-       }
-
-       public void set_time(int hour, int minute, int second) {
-               hour = hour;
-               minute = minute;
-               second = second;
-       }
-
-       public void set_date(int year, int month, int day) {
-               year = year;
-               month = month;
-               day = day;
-       }
-
-       public void set_flags(int flags) {
-               flags = flags;
-       }
-
-       public void set_altitude(int altitude) {
-               altitude = altitude;
-       }
-
-       public void add_sat(int svid, int c_n0) {
-               if (cc_gps_sat == null) {
-                       cc_gps_sat = new AltosGPS.AltosGPSSat[1];
-               } else {
-                       AltosGPSSat[] new_gps_sat = new AltosGPS.AltosGPSSat[cc_gps_sat.length + 1];
-                       for (int i = 0; i < cc_gps_sat.length; i++)
-                               new_gps_sat[i] = cc_gps_sat[i];
-                       cc_gps_sat = new_gps_sat;
-               }
-               AltosGPS.AltosGPSSat    sat = new AltosGPS.AltosGPSSat();
-               sat.svid = svid;
-               sat.c_n0 = c_n0;
-               cc_gps_sat[cc_gps_sat.length - 1] = sat;
-       }
-
-       public AltosGPS() {
-               ClearGPSTime();
-               cc_gps_sat = null;
-       }
-
-       public AltosGPS(AltosGPS old) {
-               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 */
-               year = old.year;
-               month = old.month;
-               day = old.day;
-               hour = old.hour;
-               minute = old.minute;
-               second = old.second;
-
-               gps_extended = old.gps_extended;        /* has extra data */
-               ground_speed = old.ground_speed;        /* m/s */
-               course = old.course;            /* degrees */
-               climb_rate = old.climb_rate;    /* m/s */
-               hdop = old.hdop;                /* unitless? */
-               h_error = old.h_error;  /* m */
-               v_error = old.v_error;  /* m */
-
-               if (old.cc_gps_sat != null) {
-                       cc_gps_sat = new AltosGPSSat[old.cc_gps_sat.length];
-                       for (int i = 0; i < old.cc_gps_sat.length; i++) {
-                               cc_gps_sat[i] = new AltosGPSSat();
-                               cc_gps_sat[i].svid = old.cc_gps_sat[i].svid;
-                               cc_gps_sat[i].c_n0 = old.cc_gps_sat[i].c_n0;
-                       }
-               }
-       }
-}
diff --git a/ao-tools/altosui/AltosGraph.java b/ao-tools/altosui/AltosGraph.java
deleted file mode 100644 (file)
index 58c2797..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-
-// Copyright (c) 2010 Anthony Towns
-// GPL v2 or later
-
-package altosui;
-
-import java.io.*;
-
-import org.jfree.chart.JFreeChart;
-import org.jfree.chart.ChartUtilities;
-
-abstract class AltosGraph {
-    public String filename;
-    public abstract void addData(AltosDataPoint d);
-    public abstract JFreeChart createChart();
-    public void toPNG() throws java.io.IOException { toPNG(300, 500); }
-    public void toPNG(int width, int height)
-        throws java.io.IOException
-    {
-        File pngout = new File(filename);
-        JFreeChart chart = createChart();
-        ChartUtilities.saveChartAsPNG(pngout, chart, width, height);
-        System.out.println("Created " + filename);
-    }
-}
diff --git a/ao-tools/altosui/AltosGraphTime.java b/ao-tools/altosui/AltosGraphTime.java
deleted file mode 100644 (file)
index a545128..0000000
+++ /dev/null
@@ -1,233 +0,0 @@
-
-// Copyright (c) 2010 Anthony Towns
-// GPL v2 or later
-
-package altosui;
-
-import java.awt.Color;
-import java.util.ArrayList;
-import java.util.HashMap;
-
-import org.jfree.chart.ChartUtilities;
-import org.jfree.chart.JFreeChart;
-import org.jfree.chart.axis.AxisLocation;
-import org.jfree.chart.axis.NumberAxis;
-import org.jfree.chart.labels.StandardXYToolTipGenerator;
-import org.jfree.chart.plot.PlotOrientation;
-import org.jfree.chart.plot.XYPlot;
-import org.jfree.chart.plot.ValueMarker;
-import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
-import org.jfree.chart.renderer.xy.XYItemRenderer;
-import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
-import org.jfree.data.xy.XYSeries;
-import org.jfree.data.xy.XYSeriesCollection;
-import org.jfree.ui.RectangleAnchor;
-import org.jfree.ui.TextAnchor;
-
-class AltosGraphTime extends AltosGraph {
-    static interface Element {
-        void attachGraph(AltosGraphTime g);
-        void gotTimeData(double time, AltosDataPoint d);
-        void addToPlot(AltosGraphTime g, XYPlot plot);
-    }
-
-    static class TimeAxis implements Element {
-        private int axis;
-        private Color color;
-        private String label;
-        private AxisLocation locn;
-        private double min_y = Double.NaN;
-
-        public TimeAxis(int axis, String label, Color color, AxisLocation locn)
-        {
-            this.axis = axis;
-            this.color = color;
-            this.label = label;
-            this.locn = locn;
-        }
-
-        public void setLowerBound(double min_y) {
-            this.min_y = min_y;
-        }
-
-        public void attachGraph(AltosGraphTime g) { return; }
-        public void gotTimeData(double time, AltosDataPoint d) { return; }
-
-        public void addToPlot(AltosGraphTime g, XYPlot plot) {
-            NumberAxis numAxis = new NumberAxis(label);
-            if (!Double.isNaN(min_y))
-                numAxis.setLowerBound(min_y);
-            plot.setRangeAxis(axis, numAxis);
-            plot.setRangeAxisLocation(axis, locn);
-            numAxis.setLabelPaint(color);
-            numAxis.setTickLabelPaint(color);
-            numAxis.setAutoRangeIncludesZero(false);
-        }
-    }
-
-    abstract static class TimeSeries implements Element {
-        protected XYSeries series;
-        private String axisName;
-        private Color color;
-
-        public TimeSeries(String axisName, String label, Color color) {
-            this.series = new XYSeries(label);
-            this.axisName = axisName;
-            this.color = color;
-        }
-
-        public void attachGraph(AltosGraphTime g) {
-            g.setAxis(this, axisName, color);
-        }
-        abstract public void gotTimeData(double time, AltosDataPoint d);
-
-        public void addToPlot(AltosGraphTime g, XYPlot plot) {
-            XYSeriesCollection dataset = new XYSeriesCollection();
-            dataset.addSeries(this.series);
-
-            XYItemRenderer renderer = new StandardXYItemRenderer();
-            renderer.setSeriesPaint(0, color);
-
-            int dataNum = g.getDataNum(this);
-            int axisNum = g.getAxisNum(this);
-
-            plot.setDataset(dataNum, dataset);
-            plot.mapDatasetToRangeAxis(dataNum, axisNum);
-            plot.setRenderer(dataNum, renderer);
-        }
-    }
-
-    static class StateMarker implements Element {
-        private double val = Double.NaN;
-        private String name;
-        private int state;
-
-        StateMarker(int state, String name) {
-            this.state = state;
-            this.name = name;
-        }
-
-        public void attachGraph(AltosGraphTime g) { return; }
-        public void gotTimeData(double time, AltosDataPoint d) {
-            if (Double.isNaN(val) || time < val) {
-                if (d.state() == state) {
-                    val = time;
-                }
-            }
-        }
-
-        public void addToPlot(AltosGraphTime g, XYPlot plot) {
-            if (Double.isNaN(val))
-                return;
-
-            ValueMarker m = new ValueMarker(val);
-            m.setLabel(name);
-            m.setLabelAnchor(RectangleAnchor.TOP_RIGHT);
-            m.setLabelTextAnchor(TextAnchor.TOP_LEFT);
-            plot.addDomainMarker(m);
-        }
-    }
-
-    private String callsign = null;
-    private Integer serial = null;
-    private Integer flight = null; 
-
-    private String title;
-    private ArrayList<Element> elements;
-    private HashMap<String,Integer> axes;
-    private HashMap<Element,Integer> datasets;
-    private ArrayList<Integer> datasetAxis;
-
-    public AltosGraphTime(String title) {
-        this.filename = title.toLowerCase().replaceAll("[^a-z0-9]","_")+".png";
-        this.title = title;
-        this.elements = new ArrayList<Element>();
-        this.axes = new HashMap<String,Integer>();
-        this.datasets = new HashMap<Element,Integer>();
-        this.datasetAxis = new ArrayList<Integer>();
-    }
-
-    public AltosGraphTime addElement(Element e) {
-        e.attachGraph(this);
-        elements.add(e);
-        return this;
-    }
-
-    public void setAxis(Element ds, String axisName, Color color) {
-        Integer axisNum = axes.get(axisName);
-        int dsNum = datasetAxis.size();
-        if (axisNum == null) {
-            axisNum = newAxis(axisName, color);
-        }
-        datasets.put(ds, dsNum);
-        datasetAxis.add(axisNum);
-    }
-
-    public int getAxisNum(Element ds) {
-        return datasetAxis.get( datasets.get(ds) ).intValue();
-    }
-    public int getDataNum(Element ds) {
-        return datasets.get(ds).intValue();
-    }
-
-    private Integer newAxis(String name, Color color) {
-        int cnt = axes.size();
-        AxisLocation locn = AxisLocation.BOTTOM_OR_LEFT;
-        if (cnt > 0) {
-            locn = AxisLocation.TOP_OR_RIGHT;
-        }
-        Integer res = new Integer(cnt);
-        axes.put(name, res);
-        this.addElement(new TimeAxis(cnt, name, color, locn));
-        return res;
-    }
-
-    public void addData(AltosDataPoint d) {
-        double time = d.time();
-        for (Element e : elements) {
-            e.gotTimeData(time, d);
-        }
-        if (callsign == null) callsign = d.callsign();
-        if (serial == null) serial = new Integer(d.serial());
-        if (flight == null) flight = new Integer(d.flight());
-    }
-
-    public JFreeChart createChart() {
-        NumberAxis xAxis = new NumberAxis("Time (s)");
-        xAxis.setAutoRangeIncludesZero(false);
-        XYItemRenderer renderer = new XYLineAndShapeRenderer(true, false);
-        XYPlot plot = new XYPlot();
-        plot.setDomainAxis(xAxis);
-        plot.setRenderer(renderer);
-        plot.setOrientation(PlotOrientation.VERTICAL);
-
-        if (serial != null && flight != null) {
-            title = serial + "/" + flight + ": " + title;
-        }
-        if (callsign != null) {
-            title = callsign + " - " + title;
-        }
-
-        renderer.setBaseToolTipGenerator(new StandardXYToolTipGenerator());
-        JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT,
-                                plot, true);
-        ChartUtilities.applyCurrentTheme(chart);
-
-        plot.setDomainPannable(true);
-        plot.setRangePannable(true);
-   
-        for (Element e : elements) {
-            e.addToPlot(this, plot);
-        }
-
-        return chart;
-    }
-
-    public void toPNG() throws java.io.IOException {
-        if (axes.size() > 1) {
-            toPNG(800, 500);
-        } else {
-            toPNG(300, 500);
-        }
-    }
-}
diff --git a/ao-tools/altosui/AltosGraphUI.java b/ao-tools/altosui/AltosGraphUI.java
deleted file mode 100644 (file)
index cd15865..0000000
+++ /dev/null
@@ -1,274 +0,0 @@
-
-// Copyright (c) 2010 Anthony Towns
-// GPL v2 or later
-
-package altosui;
-
-import java.io.*;
-import java.util.ArrayList;
-
-import javax.swing.JFrame;
-import java.awt.Color;
-
-import org.jfree.chart.ChartPanel;
-import org.jfree.chart.ChartUtilities;
-import org.jfree.chart.JFreeChart;
-import org.jfree.chart.axis.AxisLocation;
-import org.jfree.ui.ApplicationFrame;
-import org.jfree.ui.RefineryUtilities;
-
-public class AltosGraphUI extends JFrame 
-{
-    static final private Color red = new Color(194,31,31);
-    static final private Color green = new Color(31,194,31);
-    static final private Color blue = new Color(31,31,194);
-    static final private Color black = new Color(31,31,31);
-
-    static private class OverallGraphs {
-        AltosGraphTime.Element height = 
-            new AltosGraphTime.TimeSeries("Height (m)", "Height (AGL)", red) {
-                public void gotTimeData(double time, AltosDataPoint d) {
-                    series.add(time, d.height()); 
-                } 
-            };
-    
-        AltosGraphTime.Element speed =
-            new AltosGraphTime.TimeSeries("Speed (m/s)", "Vertical Speed", green) { 
-                public void gotTimeData(double time, AltosDataPoint d) {
-                    if (d.state() < Altos.ao_flight_drogue) {
-                        series.add(time, d.accel_speed());
-                    } else {
-                        series.add(time, d.baro_speed());
-                    }
-                }
-            };
-    
-        AltosGraphTime.Element acceleration =
-            new AltosGraphTime.TimeSeries("Acceleration (m/s\u00B2)", 
-                    "Axial Acceleration", blue) 
-            {
-                public void gotTimeData(double time, AltosDataPoint d) {
-                    series.add(time, d.acceleration());
-                }
-            };
-    
-        AltosGraphTime.Element temperature =
-            new AltosGraphTime.TimeSeries("Temperature (\u00B0C)", 
-                    "Board temperature", red) 
-            {
-                public void gotTimeData(double time, AltosDataPoint d) {
-                    series.add(time, d.temperature());
-                }
-            };
-    
-        AltosGraphTime.Element drogue_voltage =
-            new AltosGraphTime.TimeSeries("Voltage (V)", "Drogue Continuity", blue) 
-            {
-                public void gotTimeData(double time, AltosDataPoint d) {
-                    series.add(time, d.drogue_voltage());
-                }
-            };
-    
-        AltosGraphTime.Element main_voltage =
-            new AltosGraphTime.TimeSeries("Voltage (V)", "Main Continuity", green) 
-            {
-                public void gotTimeData(double time, AltosDataPoint d) {
-                    series.add(time, d.main_voltage());
-                }
-            };
-    
-        AltosGraphTime.Element e_pad    = new AltosGraphTime.StateMarker(Altos.ao_flight_pad, "Pad");
-        AltosGraphTime.Element e_boost  = new AltosGraphTime.StateMarker(Altos.ao_flight_boost, "Boost");
-        AltosGraphTime.Element e_fast   = new AltosGraphTime.StateMarker(Altos.ao_flight_fast, "Fast");
-        AltosGraphTime.Element e_coast  = new AltosGraphTime.StateMarker(Altos.ao_flight_coast, "Coast");
-       AltosGraphTime.Element e_drogue = new AltosGraphTime.StateMarker(Altos.ao_flight_drogue, "Drogue");
-       AltosGraphTime.Element e_main   = new AltosGraphTime.StateMarker(Altos.ao_flight_main, "Main");
-        AltosGraphTime.Element e_landed = new AltosGraphTime.StateMarker(Altos.ao_flight_landed, "Landed");
-    
-        protected AltosGraphTime myAltosGraphTime(String suffix) {
-            return (new AltosGraphTime("Overall " + suffix))
-                .addElement(e_boost)
-                .addElement(e_drogue)
-                .addElement(e_main)
-                .addElement(e_landed);
-        }
-    
-        public ArrayList<AltosGraph> graphs() {
-            ArrayList<AltosGraph> graphs = new ArrayList<AltosGraph>();
-    
-            graphs.add( myAltosGraphTime("Summary")
-                    .addElement(height)
-                    .addElement(speed)
-                    .addElement(acceleration) );
-    
-            graphs.add( myAltosGraphTime("Altitude")
-                    .addElement(height) );
-    
-            graphs.add( myAltosGraphTime("Speed")
-                    .addElement(speed) );
-    
-            graphs.add( myAltosGraphTime("Acceleration")
-                    .addElement(acceleration) );
-    
-            graphs.add( myAltosGraphTime("Temperature")
-                    .addElement(temperature) );
-    
-            graphs.add( myAltosGraphTime("Continuity")
-                    .addElement(drogue_voltage)
-                    .addElement(main_voltage) );
-    
-            return graphs;
-        }
-    }
-    
-    static private class AscentGraphs extends OverallGraphs {
-        protected AltosGraphTime myAltosGraphTime(String suffix) {
-            return (new AltosGraphTime("Ascent " + suffix) {
-                public void addData(AltosDataPoint d) {
-                    int state = d.state();
-                    if (Altos.ao_flight_boost <= state && state <= Altos.ao_flight_coast) {
-                        super.addData(d);
-                    }
-                }
-            }).addElement(e_boost)
-              .addElement(e_fast)
-              .addElement(e_coast);
-        }
-    }
-    
-    static private class DescentGraphs extends OverallGraphs {
-        protected AltosGraphTime myAltosGraphTime(String suffix) {
-            return (new AltosGraphTime("Descent " + suffix) {
-                public void addData(AltosDataPoint d) {
-                    int state = d.state();
-                    if (Altos.ao_flight_drogue <= state && state <= Altos.ao_flight_main) {
-                        super.addData(d);
-                    }
-                }
-            }).addElement(e_drogue)
-              .addElement(e_main);
-            // ((XYGraph)graph[8]).ymin = new Double(-50);
-        }
-    }
-
-       public AltosGraphUI(AltosRecordIterable records) {
-               super("Altos Graph");
-
-               Iterable<AltosDataPoint> reader = new AltosDataPointReader (records);
-               if (reader == null)
-                       return;
-        
-               init(reader, 0);
-       }
-
-    public AltosGraphUI(Iterable<AltosDataPoint> data, int which) 
-    {
-        super("Altos Graph");
-        init(data, which);
-    }
-
-    private void init(Iterable<AltosDataPoint> data, int which) {
-        AltosGraph graph = createGraph(data, which);
-
-        JFreeChart chart = graph.createChart();
-        ChartPanel chartPanel = new ChartPanel(chart);
-        chartPanel.setMouseWheelEnabled(true);
-        chartPanel.setPreferredSize(new java.awt.Dimension(800, 500));
-        setContentPane(chartPanel);
-
-        pack();
-
-        RefineryUtilities.centerFrameOnScreen(this);
-
-        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
-        setVisible(true);
-    }
-
-    private static AltosGraph createGraph(Iterable<AltosDataPoint> data,
-            int which)
-    {
-        return createGraphsWhich(data, which).get(0);
-    }
-
-    private static ArrayList<AltosGraph> createGraphs(
-            Iterable<AltosDataPoint> data)
-    {
-        return createGraphsWhich(data, -1);
-    }
-
-    private static ArrayList<AltosGraph> createGraphsWhich(
-            Iterable<AltosDataPoint> data, int which)
-    {
-        ArrayList<AltosGraph> graph = new ArrayList<AltosGraph>();
-        graph.addAll((new OverallGraphs()).graphs());
-        graph.addAll((new AscentGraphs()).graphs());
-        graph.addAll((new DescentGraphs()).graphs());
-
-        if (which > 0) {
-            if (which >= graph.size()) {
-                which = 0;
-            }
-            AltosGraph g = graph.get(which);
-            graph = new ArrayList<AltosGraph>();
-            graph.add(g);
-        }
-
-        for (AltosDataPoint dp : data) {
-            for (AltosGraph g : graph) {
-                g.addData(dp);
-            }
-        }
-
-        return graph;
-    }
-}
-
-/* gnuplot bits...
- *
-300x400
-
---------------------------------------------------------
-TOO HARD! :)
-
-"ascent-gps-accuracy.png" "Vertical error margin to apogee - GPS v Baro (m)"
-    5:($7 < 6 ? $24-$11 : 1/0)
-"descent-gps-accuracy.png" "Vertical error margin during descent - GPS v Baro (m)"
-    5:($7 < 6 ? 1/0 : $24-$11)
-
-set output "overall-gps-accuracy.png"
-set ylabel "distance above sea level (m)"
-plot "telemetry.csv" using 5:11 with lines ti "baro altitude" axis x1y1, \
-    "telemetry.csv" using 5:24 with lines ti "gps altitude" axis x1y1
-
-set term png tiny size 700,700 enhanced
-set xlabel "m"
-set ylabel "m"
-set polar
-set grid polar
-set rrange[*:*]
-set angles degrees
-
-set output "overall-gps-path.png"
-#:30 with yerrorlines
-plot "telemetry.csv" using (90-$33):($7 == 2 ? $31 : 1/0) with lines ti "pad", \
-    "telemetry.csv" using (90-$33):($7 == 3 ? $31 : 1/0) with lines ti "boost", \
-    "telemetry.csv" using (90-$33):($7 == 4 ? $31 : 1/0) with lines ti "fast", \
-    "telemetry.csv" using (90-$33):($7 == 5 ? $31 : 1/0) with lines ti "coast", \
-    "telemetry.csv" using (90-$33):($7 == 6 ? $31 : 1/0) with lines ti "drogue", \
-    "telemetry.csv" using (90-$33):($7 == 7 ? $31 : 1/0) with lines ti "main", \
-    "telemetry.csv" using (90-$33):($7 == 8 ? $31 : 1/0) with lines ti "landed"
-
-set output "ascent-gps-path.png"
-plot "telemetry.csv" using (90-$33):($7 == 2 ? $31 : 1/0):30 with lines ti "pad", \
-    "telemetry.csv" using (90-$33):($7 == 3 ? $31 : 1/0):20 with lines ti "boost", \
-    "telemetry.csv" using (90-$33):($7 == 4 ? $31 : 1/0):10 with lines ti "fast", \
-    "telemetry.csv" using (90-$33):($7 == 5 ? $31 : 1/0):5 with lines ti "coast"
-
-set output "descent-gps-path.png"
-plot "telemetry.csv" using (90-$33):($7 == 6 ? $31 : 1/0) with lines ti "drogue", \
-    "telemetry.csv" using (90-$33):($7 == 7 ? $31 : 1/0) with lines ti "main", \
-    "telemetry.csv" using (90-$33):($7 == 8 ? $31 : 1/0) with lines ti "landed"
-
- */
-
-
diff --git a/ao-tools/altosui/AltosGreatCircle.java b/ao-tools/altosui/AltosGreatCircle.java
deleted file mode 100644 (file)
index fb1b6ab..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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.lang.Math;
-
-public class AltosGreatCircle {
-       double  distance;
-       double  bearing;
-
-       double sqr(double a) { return a * a; }
-
-       static final double rad = Math.PI / 180;
-       static final double earth_radius = 6371.2 * 1000;       /* in meters */
-
-    static int BEARING_LONG = 0;
-    static int BEARING_SHORT = 1;
-    static int BEARING_VOICE = 2;
-    String bearing_words(int length) {
-        String [][] bearing_string = {
-          {
-            "North", "North North East", "North East", "East North East",
-            "East", "East South East", "South East", "South South East",
-            "South", "South South West", "South West", "West South West",
-            "West", "West North West", "North West", "North North West"
-          }, {
-            "N", "NNE", "NE", "ENE",
-            "E", "ESE", "SE", "SSE",
-            "S", "SSW", "SW", "WSW",
-            "W", "WNW", "NW", "NNW"
-          }, {
-            "north", "nor nor east", "north east", "east nor east",
-            "east", "east sow east", "south east", "sow sow east",
-            "south", "sow sow west", "south west", "west sow west",
-            "west", "west nor west", "north west", "nor nor west "
-          }
-        };
-        return bearing_string[length][(int)((bearing / 90 * 8 + 1) / 2)%16];
-    }
-
-       public AltosGreatCircle (double start_lat, double start_lon,
-                                double end_lat, double end_lon)
-       {
-               double lat1 = rad * start_lat;
-               double lon1 = rad * -start_lon;
-               double lat2 = rad * end_lat;
-               double lon2 = rad * -end_lon;
-
-               double d_lon = lon2 - lon1;
-
-               /* From http://en.wikipedia.org/wiki/Great-circle_distance */
-               double vdn = Math.sqrt(sqr(Math.cos(lat2) * Math.sin(d_lon)) +
-                                      sqr(Math.cos(lat1) * Math.sin(lat2) -
-                                          Math.sin(lat1) * Math.cos(lat2) * Math.cos(d_lon)));
-               double vdd = Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos(d_lon);
-               double d = Math.atan2(vdn,vdd);
-               double course;
-
-               if (Math.cos(lat1) < 1e-20) {
-                       if (lat1 > 0)
-                               course = Math.PI;
-                       else
-                               course = -Math.PI;
-               } else {
-                       if (d < 1e-10)
-                               course = 0;
-                       else
-                               course = Math.acos((Math.sin(lat2)-Math.sin(lat1)*Math.cos(d)) /
-                                                  (Math.sin(d)*Math.cos(lat1)));
-                       if (Math.sin(lon2-lon1) > 0)
-                               course = 2 * Math.PI-course;
-               }
-               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/AltosHexfile.java b/ao-tools/altosui/AltosHexfile.java
deleted file mode 100644 (file)
index 19e35ae..0000000
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * 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.lang.*;
-import java.io.*;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.LinkedList;
-import java.util.Iterator;
-import java.util.Arrays;
-
-class HexFileInputStream extends PushbackInputStream {
-       public int line;
-
-       public HexFileInputStream(FileInputStream o) {
-               super(new BufferedInputStream(o));
-               line = 1;
-       }
-
-       public int read() throws IOException {
-               int     c = super.read();
-               if (c == '\n')
-                       line++;
-               return c;
-       }
-
-       public void unread(int c) throws IOException {
-               if (c == '\n')
-                       line--;
-               if (c != -1)
-                       super.unread(c);
-       }
-}
-
-class HexRecord implements Comparable {
-       public int      address;
-       public int      type;
-       public byte     checksum;
-       public byte[]   data;
-
-       static final int NORMAL = 0;
-       static final int EOF = 1;
-       static final int EXTENDED_ADDRESS = 2;
-
-       enum read_state {
-               marker,
-               length,
-               address,
-               type,
-               data,
-               checksum,
-               newline,
-               white,
-               done,
-       }
-
-       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;
-       }
-
-       boolean isspace(int c) {
-               switch (c) {
-               case ' ':
-               case '\t':
-                       return true;
-               }
-               return false;
-       }
-
-       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;
-       }
-
-       public byte checksum() {
-               byte    got = 0;
-
-               got += data.length;
-               got += (address >> 8) & 0xff;
-               got += (address     ) & 0xff;
-               got += type;
-               for (int i = 0; i < data.length; i++)
-                       got += data[i];
-               return (byte) (-got);
-       }
-
-       public int compareTo(Object other) {
-               HexRecord       o = (HexRecord) other;
-               return address - o.address;
-       }
-
-       public String toString() {
-               return String.format("%04x: %02x (%d)", address, type, data.length);
-       }
-
-       public HexRecord(HexFileInputStream input) throws IOException {
-               read_state      state = read_state.marker;
-               int             nhexbytes = 0;
-               int             hex = 0;
-               int             ndata = 0;
-               byte            got_checksum;
-
-               while (state != read_state.done) {
-                       int c = input.read();
-                       if (c < 0 && state != read_state.white)
-                               throw new IOException(String.format("%d: Unexpected EOF", input.line));
-                       if (c == ' ')
-                               continue;
-                       switch (state) {
-                       case marker:
-                               if (c != ':')
-                                       throw new IOException("Missing ':'");
-                               state = read_state.length;
-                               nhexbytes = 2;
-                               hex = 0;
-                               break;
-                       case length:
-                       case address:
-                       case type:
-                       case data:
-                       case checksum:
-                               if(!ishex(c))
-                                       throw new IOException(String.format("Non-hex char '%c'", c));
-                               hex = hex << 4 | fromhex(c);
-                               --nhexbytes;
-                               if (nhexbytes != 0)
-                                       break;
-
-                               switch (state) {
-                               case length:
-                                       data = new byte[hex];
-                                       state = read_state.address;
-                                       nhexbytes = 4;
-                                       break;
-                               case address:
-                                       address = hex;
-                                       state = read_state.type;
-                                       nhexbytes = 2;
-                                       break;
-                               case type:
-                                       type = hex;
-                                       if (data.length > 0)
-                                               state = read_state.data;
-                                       else
-                                               state = read_state.checksum;
-                                       nhexbytes = 2;
-                                       ndata = 0;
-                                       break;
-                               case data:
-                                       data[ndata] = (byte) hex;
-                                       ndata++;
-                                       nhexbytes = 2;
-                                       if (ndata == data.length)
-                                               state = read_state.checksum;
-                                       break;
-                               case checksum:
-                                       checksum = (byte) hex;
-                                       state = read_state.newline;
-                                       break;
-                               default:
-                                       break;
-                               }
-                               hex = 0;
-                               break;
-                       case newline:
-                               if (c != '\n' && c != '\r')
-                                       throw new IOException("Missing newline");
-                               state = read_state.white;
-                               break;
-                       case white:
-                               if (!isspace(c)) {
-                                       input.unread(c);
-                                       state = read_state.done;
-                               }
-                               break;
-                       case done:
-                               break;
-                       }
-               }
-               got_checksum = checksum();
-               if (got_checksum != checksum)
-                       throw new IOException(String.format("Invalid checksum (read 0x%02x computed 0x%02x)\n",
-                                                           checksum, got_checksum));
-       }
-}
-
-public class AltosHexfile {
-       public int      address;
-       public byte[]   data;
-
-       public byte get_byte(int a) {
-               return data[a - address];
-       }
-
-       public AltosHexfile(FileInputStream file) throws IOException {
-               HexFileInputStream      input = new HexFileInputStream(file);
-               LinkedList<HexRecord>   record_list = new LinkedList<HexRecord>();
-               boolean                 done = false;
-
-               while (!done) {
-                       HexRecord       record = new HexRecord(input);
-
-                       if (record.type == HexRecord.EOF)
-                               done = true;
-                       else
-                               record_list.add(record);
-               }
-               HexRecord[] records  = record_list.toArray(new HexRecord[0]);
-               Arrays.sort(records);
-               if (records.length > 0) {
-                       int     base = records[0].address;
-                       int     bound = records[records.length-1].address +
-                               records[records.length-1].data.length;
-
-                       data = new byte[bound - base];
-                       address = base;
-                       Arrays.fill(data, (byte) 0xff);
-
-                       /* Paint the records into the new array */
-                       for (int i = 0; i < records.length; i++) {
-                               for (int j = 0; j < records[i].data.length; j++)
-                                       data[records[i].address - base + j] = records[i].data[j];
-                       }
-               }
-       }
-}
\ No newline at end of file
diff --git a/ao-tools/altosui/AltosIgnite.java b/ao-tools/altosui/AltosIgnite.java
deleted file mode 100644 (file)
index 3cbd8a7..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * 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.io.*;
-import java.util.concurrent.*;
-
-public class AltosIgnite {
-       AltosDevice     device;
-       AltosSerial     serial;
-       boolean         remote;
-       boolean         serial_started;
-       final static int        None = 0;
-       final static int        Apogee = 1;
-       final static int        Main = 2;
-
-       final static int        Unknown = 0;
-       final static int        Ready = 1;
-       final static int        Active = 2;
-       final static int        Open = 3;
-
-       private void start_serial() throws InterruptedException {
-               serial_started = true;
-               if (remote) {
-                       serial.set_radio();
-                       serial.printf("p\nE 0\n");
-                       serial.flush_input();
-               }
-       }
-
-       private void stop_serial() throws InterruptedException {
-               if (!serial_started)
-                       return;
-               serial_started = false;
-               if (serial == null)
-                       return;
-               if (remote) {
-                       serial.printf("~");
-                       serial.flush_output();
-               }
-       }
-
-       class string_ref {
-               String  value;
-
-               public String get() {
-                       return value;
-               }
-               public void set(String i) {
-                       value = i;
-               }
-               public string_ref() {
-                       value = null;
-               }
-       }
-
-       private boolean get_string(String line, String label, string_ref s) {
-               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);
-                       s.set(quoted);
-                       return true;
-               } else {
-                       return false;
-               }
-       }
-
-       private int status(String status_name) {
-               if (status_name.equals("unknown"))
-                       return Unknown;
-               if (status_name.equals("ready"))
-                       return Ready;
-               if (status_name.equals("active"))
-                       return Active;
-               if (status_name.equals("open"))
-                       return Open;
-               return Unknown;
-       }
-
-       public int status(int igniter) throws InterruptedException, TimeoutException {
-               int status = Unknown;
-               if (serial == null)
-                       return status;
-               string_ref status_name = new string_ref();
-               start_serial();
-               serial.printf("t\n");
-               for (;;) {
-                       String line = serial.get_reply(5000);
-                       if (line == null)
-                               throw new TimeoutException();
-                       if (get_string(line, "Igniter: drogue Status: ", status_name))
-                               if (igniter == Apogee)
-                                       status = status(status_name.get());
-                       if (get_string(line, "Igniter:   main Status: ", status_name)) {
-                               if (igniter == Main)
-                                       status = status(status_name.get());
-                               break;
-                       }
-               }
-               stop_serial();
-               return status;
-       }
-
-       public String status_string(int status) {
-               switch (status) {
-               case Unknown: return "Unknown";
-               case Ready: return "Ready";
-               case Active: return "Active";
-               case Open: return "Open";
-               default: return "Unknown";
-               }
-       }
-
-       public void fire(int igniter) {
-               if (serial == null)
-                       return;
-               try {
-                       start_serial();
-                       switch (igniter) {
-                       case Main:
-                               serial.printf("i DoIt main\n");
-                               break;
-                       case Apogee:
-                               serial.printf("i DoIt drogue\n");
-                               break;
-                       }
-               } catch (InterruptedException ie) {
-               } finally {
-                       try {
-                               stop_serial();
-                       } catch (InterruptedException ie) {
-                       }
-               }
-       }
-
-       public void close() {
-               try {
-                       stop_serial();
-               } catch (InterruptedException ie) {
-               }
-               serial.close();
-               serial = null;
-       }
-
-       public AltosIgnite(AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException {
-
-               device = in_device;
-               serial = new AltosSerial(device);
-               remote = false;
-
-               if (!device.matchProduct(AltosDevice.product_telemetrum))
-                       remote = true;
-       }
-}
\ No newline at end of file
diff --git a/ao-tools/altosui/AltosIgniteUI.java b/ao-tools/altosui/AltosIgniteUI.java
deleted file mode 100644 (file)
index d542729..0000000
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * 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 javax.swing.event.*;
-import java.io.*;
-import java.util.*;
-import java.text.*;
-import java.util.prefs.*;
-import java.util.concurrent.*;
-
-public class AltosIgniteUI
-       extends JDialog
-       implements ActionListener
-{
-       AltosDevice     device;
-       AltosIgnite     ignite;
-       JFrame          owner;
-       JLabel          label;
-       JRadioButton    apogee;
-       JLabel          apogee_status_label;
-       JRadioButton    main;
-       JLabel          main_status_label;
-       JToggleButton   arm;
-       JButton         fire;
-       javax.swing.Timer       timer;
-
-       int             apogee_status;
-       int             main_status;
-
-       final static int        timeout = 1 * 1000;
-
-       int             time_remaining;
-       boolean         timer_running;
-
-       void set_arm_text() {
-               if (arm.isSelected())
-                       arm.setText(String.format("%d", time_remaining));
-               else
-                       arm.setText("Arm");
-       }
-
-       void start_timer() {
-               time_remaining = 10;
-               set_arm_text();
-               timer_running = true;
-       }
-
-       void stop_timer() {
-               time_remaining = 0;
-               arm.setSelected(false);
-               arm.setEnabled(false);
-               fire.setEnabled(false);
-               timer_running = false;
-               set_arm_text();
-       }
-
-       void cancel () {
-               apogee.setSelected(false);
-               main.setSelected(false);
-               fire.setEnabled(false);
-               stop_timer();
-       }
-
-       void get_ignite_status() throws InterruptedException, TimeoutException {
-               apogee_status = ignite.status(AltosIgnite.Apogee);
-               main_status = ignite.status(AltosIgnite.Main);
-       }
-
-       void set_ignite_status() throws InterruptedException, TimeoutException {
-               get_ignite_status();
-               apogee_status_label.setText(String.format("\"%s\"", ignite.status_string(apogee_status)));
-               main_status_label.setText(String.format("\"%s\"", ignite.status_string(main_status)));
-       }
-
-       void close() {
-               timer.stop();
-               setVisible(false);
-               ignite.close();
-       }
-
-       void abort() {
-               close();
-               JOptionPane.showMessageDialog(owner,
-                                             String.format("Connection to \"%s\" failed",
-                                                           device.toShortString()),
-                                             "Connection Failed",
-                                             JOptionPane.ERROR_MESSAGE);
-       }
-
-       void tick_timer() {
-               if (timer_running) {
-                       --time_remaining;
-                       if (time_remaining <= 0)
-                               cancel();
-                       else
-                               set_arm_text();
-               }
-               try {
-                       set_ignite_status();
-               } catch (InterruptedException ie) {
-                       abort();
-               } catch (TimeoutException te) {
-                       abort();
-               }
-       }
-
-       void fire() {
-               if (arm.isEnabled() && arm.isSelected() && time_remaining > 0) {
-                       int     igniter = AltosIgnite.None;
-                       if (apogee.isSelected() && !main.isSelected())
-                               igniter = AltosIgnite.Apogee;
-                       else if (main.isSelected() && !apogee.isSelected())
-                               igniter = AltosIgnite.Main;
-                       ignite.fire(igniter);
-                       cancel();
-               }
-       }
-
-       public void actionPerformed(ActionEvent e) {
-               String cmd = e.getActionCommand();
-               if (cmd.equals("apogee") || cmd.equals("main")) {
-                       stop_timer();
-               }
-
-               if (cmd.equals("apogee") && apogee.isSelected()) {
-                       main.setSelected(false);
-                       arm.setEnabled(true);
-               }
-               if (cmd.equals("main") && main.isSelected()) {
-                       apogee.setSelected(false);
-                       arm.setEnabled(true);
-               }
-
-               if (cmd.equals("arm")) {
-                       if (arm.isSelected()) {
-                               fire.setEnabled(true);
-                               start_timer();
-                       } else
-                               cancel();
-               }
-               if (cmd.equals("fire"))
-                       fire();
-               if (cmd.equals("tick"))
-                       tick_timer();
-               if (cmd.equals("close")) {
-                       close();
-               }
-       }
-
-       /* A window listener to catch closing events and tell the config code */
-       class ConfigListener extends WindowAdapter {
-               AltosIgniteUI   ui;
-
-               public ConfigListener(AltosIgniteUI this_ui) {
-                       ui = this_ui;
-               }
-
-               public void windowClosing(WindowEvent e) {
-                       ui.actionPerformed(new ActionEvent(e.getSource(),
-                                                          ActionEvent.ACTION_PERFORMED,
-                                                          "close"));
-               }
-       }
-
-       private boolean open() {
-               device = AltosDeviceDialog.show(owner, AltosDevice.product_any);
-               if (device != null) {
-                       try {
-                               ignite = new AltosIgnite(device);
-                               return true;
-                       } catch (FileNotFoundException ee) {
-                               JOptionPane.showMessageDialog(owner,
-                                                             String.format("Cannot open device \"%s\"",
-                                                                           device.toShortString()),
-                                                             "Cannot open target device",
-                                                             JOptionPane.ERROR_MESSAGE);
-                       } catch (AltosSerialInUseException si) {
-                               JOptionPane.showMessageDialog(owner,
-                                                             String.format("Device \"%s\" already in use",
-                                                                           device.toShortString()),
-                                                             "Device in use",
-                                                             JOptionPane.ERROR_MESSAGE);
-                       } catch (IOException ee) {
-                               JOptionPane.showMessageDialog(owner,
-                                                             device.toShortString(),
-                                                             ee.getLocalizedMessage(),
-                                                             JOptionPane.ERROR_MESSAGE);
-                       }
-               }
-               return false;
-       }
-
-       public AltosIgniteUI(JFrame in_owner) {
-
-               owner = in_owner;
-               apogee_status = AltosIgnite.Unknown;
-               main_status = AltosIgnite.Unknown;
-
-               if (!open())
-                       return;
-
-               Container               pane = getContentPane();
-               GridBagConstraints      c = new GridBagConstraints();
-               Insets                  i = new Insets(4,4,4,4);
-
-               timer = new javax.swing.Timer(timeout, this);
-               timer.setActionCommand("tick");
-               timer_running = false;
-               timer.restart();
-
-               owner = in_owner;
-
-               pane.setLayout(new GridBagLayout());
-
-               c.fill = GridBagConstraints.NONE;
-               c.anchor = GridBagConstraints.CENTER;
-               c.insets = i;
-               c.weightx = 1;
-               c.weighty = 1;
-
-               c.gridx = 0;
-               c.gridy = 0;
-               c.gridwidth = 2;
-               c.anchor = GridBagConstraints.CENTER;
-               label = new JLabel ("Fire Igniter");
-               pane.add(label, c);
-
-               c.gridx = 0;
-               c.gridy = 1;
-               c.gridwidth = 1;
-               c.anchor = GridBagConstraints.WEST;
-               apogee = new JRadioButton ("Apogee");
-               pane.add(apogee, c);
-               apogee.addActionListener(this);
-               apogee.setActionCommand("apogee");
-
-               c.gridx = 1;
-               c.gridy = 1;
-               c.gridwidth = 1;
-               c.anchor = GridBagConstraints.WEST;
-               apogee_status_label = new JLabel();
-               pane.add(apogee_status_label, c);
-
-               c.gridx = 0;
-               c.gridy = 2;
-               c.gridwidth = 1;
-               c.anchor = GridBagConstraints.WEST;
-               main = new JRadioButton ("Main");
-               pane.add(main, c);
-               main.addActionListener(this);
-               main.setActionCommand("main");
-
-               c.gridx = 1;
-               c.gridy = 2;
-               c.gridwidth = 1;
-               c.anchor = GridBagConstraints.WEST;
-               main_status_label = new JLabel();
-               pane.add(main_status_label, c);
-
-               try {
-                       set_ignite_status();
-               } catch (InterruptedException ie) {
-                       abort();
-                       return;
-               } catch (TimeoutException te) {
-                       abort();
-                       return;
-               }
-
-               c.gridx = 0;
-               c.gridy = 3;
-               c.gridwidth = 1;
-               c.anchor = GridBagConstraints.CENTER;
-               arm = new JToggleButton ("Arm");
-               pane.add(arm, c);
-               arm.addActionListener(this);
-               arm.setActionCommand("arm");
-               arm.setEnabled(false);
-
-               c.gridx = 1;
-               c.gridy = 3;
-               c.gridwidth = 1;
-               c.anchor = GridBagConstraints.CENTER;
-               fire = new JButton ("Fire");
-               fire.setEnabled(false);
-               pane.add(fire, c);
-               fire.addActionListener(this);
-               fire.setActionCommand("fire");
-
-               pack();
-               setLocationRelativeTo(owner);
-               setVisible(true);
-
-               addWindowListener(new ConfigListener(this));
-       }
-}
\ No newline at end of file
diff --git a/ao-tools/altosui/AltosInfoTable.java b/ao-tools/altosui/AltosInfoTable.java
deleted file mode 100644 (file)
index 723f830..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * 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;
-
-public class AltosInfoTable extends JTable {
-       private AltosFlightInfoTableModel model;
-
-       private Font infoLabelFont = new Font("SansSerif", Font.PLAIN, 14);
-       private Font infoValueFont = new Font("Monospaced", Font.PLAIN, 14);
-
-       static final int info_columns = 3;
-       static final int info_rows = 17;
-
-       int desired_row_height() {
-               FontMetrics     infoValueMetrics = getFontMetrics(infoValueFont);
-               return (infoValueMetrics.getHeight() + infoValueMetrics.getLeading()) * 18 / 10;
-       }
-
-       public AltosInfoTable() {
-               super(new AltosFlightInfoTableModel(info_rows, info_columns));
-               model = (AltosFlightInfoTableModel) getModel();
-               setFont(infoValueFont);
-               setAutoResizeMode(AUTO_RESIZE_ALL_COLUMNS);
-               setShowGrid(true);
-               setRowHeight(desired_row_height());
-               doLayout();
-       }
-
-       public Dimension getPreferredScrollableViewportSize() {
-               return getPreferredSize();
-       }
-
-       void info_reset() {
-               model.reset();
-       }
-
-       void info_add_row(int col, String name, String value) {
-               model.addRow(col, name, value);
-       }
-
-       void info_add_row(int col, String name, String format, Object... parameters) {
-               info_add_row (col, name, String.format(format, parameters));
-       }
-
-       void info_add_deg(int col, String name, double v, int pos, int neg) {
-               int     c = pos;
-               if (v < 0) {
-                       c = neg;
-                       v = -v;
-               }
-               double  deg = Math.floor(v);
-               double  min = (v - deg) * 60;
-
-               info_add_row(col, name, String.format("%3.0f°%08.5f'", deg, min));
-       }
-
-       void info_finish() {
-               model.finish();
-       }
-
-       public void clear() {
-               model.clear();
-       }
-
-       public void show(AltosState state, int crc_errors) {
-               if (state == null)
-                       return;
-               info_reset();
-               info_add_row(0, "Rocket state", "%s", state.data.state());
-               info_add_row(0, "Callsign", "%s", state.data.callsign);
-               info_add_row(0, "Rocket serial", "%6d", state.data.serial);
-               info_add_row(0, "Rocket flight", "%6d", state.data.flight);
-
-               info_add_row(0, "RSSI", "%6d    dBm", state.data.rssi);
-               info_add_row(0, "CRC Errors", "%6d", crc_errors);
-               info_add_row(0, "Height", "%6.0f    m", state.height);
-               info_add_row(0, "Max height", "%6.0f    m", state.max_height);
-               info_add_row(0, "Acceleration", "%8.1f  m/s²", state.acceleration);
-               info_add_row(0, "Max acceleration", "%8.1f  m/s²", state.max_acceleration);
-               info_add_row(0, "Speed", "%8.1f  m/s", state.ascent ? state.speed : state.baro_speed);
-               info_add_row(0, "Max Speed", "%8.1f  m/s", state.max_speed);
-               info_add_row(0, "Temperature", "%9.2f °C", state.temperature);
-               info_add_row(0, "Battery", "%9.2f V", state.battery);
-               info_add_row(0, "Drogue", "%9.2f V", state.drogue_sense);
-               info_add_row(0, "Main", "%9.2f V", state.main_sense);
-               info_add_row(0, "Pad altitude", "%6.0f    m", state.ground_altitude);
-               if (state.gps == null) {
-                       info_add_row(1, "GPS", "not available");
-               } else {
-                       if (state.gps_ready)
-                               info_add_row(1, "GPS state", "%s", "ready");
-                       else
-                               info_add_row(1, "GPS state", "wait (%d)",
-                                            state.gps_waiting);
-                       if (state.data.gps.locked)
-                               info_add_row(1, "GPS", "   locked");
-                       else if (state.data.gps.connected)
-                               info_add_row(1, "GPS", " unlocked");
-                       else
-                               info_add_row(1, "GPS", "  missing");
-                       info_add_row(1, "Satellites", "%6d", state.data.gps.nsat);
-                       info_add_deg(1, "Latitude", state.gps.lat, 'N', 'S');
-                       info_add_deg(1, "Longitude", state.gps.lon, 'E', 'W');
-                       info_add_row(1, "GPS altitude", "%6d", state.gps.alt);
-                       info_add_row(1, "GPS height", "%6.0f", state.gps_height);
-
-                       /* The SkyTraq GPS doesn't report these values */
-                       if (false) {
-                               info_add_row(1, "GPS ground speed", "%8.1f m/s %3d°",
-                                            state.gps.ground_speed,
-                                            state.gps.course);
-                               info_add_row(1, "GPS climb rate", "%8.1f m/s",
-                                            state.gps.climb_rate);
-                               info_add_row(1, "GPS error", "%6d m(h)%3d m(v)",
-                                            state.gps.h_error, state.gps.v_error);
-                       }
-                       info_add_row(1, "GPS hdop", "%8.1f", state.gps.hdop);
-
-                       if (state.npad > 0) {
-                               if (state.from_pad != null) {
-                                       info_add_row(1, "Distance from pad", "%6d m",
-                                                    (int) (state.from_pad.distance + 0.5));
-                                       info_add_row(1, "Direction from pad", "%6d°",
-                                                    (int) (state.from_pad.bearing + 0.5));
-                                       info_add_row(1, "Elevation from pad", "%6d°",
-                                                    (int) (state.elevation + 0.5));
-                                       info_add_row(1, "Range from pad", "%6d m",
-                                                    (int) (state.range + 0.5));
-                               } else {
-                                       info_add_row(1, "Distance from pad", "unknown");
-                                       info_add_row(1, "Direction from pad", "unknown");
-                                       info_add_row(1, "Elevation from pad", "unknown");
-                                       info_add_row(1, "Range from pad", "unknown");
-                               }
-                               info_add_deg(1, "Pad latitude", state.pad_lat, 'N', 'S');
-                               info_add_deg(1, "Pad longitude", state.pad_lon, 'E', 'W');
-                               info_add_row(1, "Pad GPS alt", "%6.0f m", state.pad_alt);
-                       }
-                       info_add_row(1, "GPS date", "%04d-%02d-%02d",
-                                      state.gps.year,
-                                      state.gps.month,
-                                      state.gps.day);
-                       info_add_row(1, "GPS time", "  %02d:%02d:%02d",
-                                      state.gps.hour,
-                                      state.gps.minute,
-                                      state.gps.second);
-                       int     nsat_vis = 0;
-                       int     c;
-
-                       if (state.gps.cc_gps_sat == null)
-                               info_add_row(2, "Satellites Visible", "%4d", 0);
-                       else {
-                               info_add_row(2, "Satellites Visible", "%4d", state.gps.cc_gps_sat.length);
-                               for (c = 0; c < state.gps.cc_gps_sat.length; c++) {
-                                       info_add_row(2, "Satellite id,C/N0",
-                                                    "%4d, %4d",
-                                                    state.gps.cc_gps_sat[c].svid,
-                                                    state.gps.cc_gps_sat[c].c_n0);
-                               }
-                       }
-               }
-               info_finish();
-       }
-}
diff --git a/ao-tools/altosui/AltosKML.java b/ao-tools/altosui/AltosKML.java
deleted file mode 100644 (file)
index d586033..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * 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.lang.*;
-import java.io.*;
-import java.text.*;
-import java.util.*;
-
-public class AltosKML implements AltosWriter {
-
-       File                    name;
-       PrintStream             out;
-       int                     state = -1;
-       AltosRecord             prev = null;
-
-       static final String[] kml_state_colors = {
-               "FF000000",
-               "FF000000",
-               "FF000000",
-               "FF0000FF",
-               "FF4080FF",
-               "FF00FFFF",
-               "FFFF0000",
-               "FF00FF00",
-               "FF000000",
-               "FFFFFFFF"
-       };
-
-       static final String kml_header_start =
-               "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
-               "<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n" +
-               "<Document>\n" +
-               "  <name>AO Flight#%d S/N: %03d</name>\n" +
-               "  <description>\n";
-       static final String kml_header_end =
-               "  </description>\n" +
-               "  <open>0</open>\n";
-
-       static final String kml_style_start =
-               "  <Style id=\"ao-flightstate-%s\">\n" +
-               "    <LineStyle><color>%s</color><width>4</width></LineStyle>\n" +
-               "    <BalloonStyle>\n" +
-               "      <text>\n";
-
-       static final String kml_style_end =
-               "      </text>\n" +
-               "    </BalloonStyle>\n" +
-               "  </Style>\n";
-
-       static final String kml_placemark_start =
-               "  <Placemark>\n" +
-               "    <name>%s</name>\n" +
-               "    <styleUrl>#ao-flightstate-%s</styleUrl>\n" +
-               "    <LineString>\n" +
-               "      <tessellate>1</tessellate>\n" +
-               "      <altitudeMode>absolute</altitudeMode>\n" +
-               "      <coordinates>\n";
-
-       static final String kml_coord_fmt =
-       "        %12.7f, %12.7f, %12.7f <!-- alt %12.7f time %12.7f sats %d -->\n";
-
-       static final String kml_placemark_end =
-               "      </coordinates>\n" +
-               "    </LineString>\n" +
-               "  </Placemark>\n";
-
-       static final String kml_footer =
-               "</Document>\n" +
-               "</kml>\n";
-
-       void start (AltosRecord record) {
-               out.printf(kml_header_start, record.flight, record.serial);
-               out.printf("Date:   %04d-%02d-%02d\n",
-                          record.gps.year, record.gps.month, record.gps.day);
-               out.printf("Time:     %2d:%02d:%02d\n",
-                          record.gps.hour, record.gps.minute, record.gps.second);
-               out.printf("%s", kml_header_end);
-       }
-
-       boolean started = false;
-
-       void state_start(AltosRecord record) {
-               String  state_name = Altos.state_name(record.state);
-               out.printf(kml_style_start, state_name, kml_state_colors[record.state]);
-               out.printf("\tState: %s\n", state_name);
-               out.printf("%s", kml_style_end);
-               out.printf(kml_placemark_start, state_name, state_name);
-       }
-
-       void state_end(AltosRecord record) {
-               out.printf("%s", kml_placemark_end);
-       }
-
-       void coord(AltosRecord record) {
-               AltosGPS        gps = record.gps;
-               out.printf(kml_coord_fmt,
-                          gps.lon, gps.lat,
-                          record.filtered_altitude(), (double) gps.alt,
-                          record.time, gps.nsat);
-       }
-
-       void end() {
-               out.printf("%s", kml_footer);
-       }
-
-       public void close() {
-               if (prev != null) {
-                       state_end(prev);
-                       end();
-                       prev = null;
-               }
-       }
-
-       public void write(AltosRecord record) {
-               AltosGPS        gps = record.gps;
-
-               if (gps == null)
-                       return;
-               if (!started) {
-                       start(record);
-                       started = true;
-               }
-               if (prev != null &&
-                   prev.gps.second == record.gps.second &&
-                   prev.gps.minute == record.gps.minute &&
-                   prev.gps.hour == record.gps.hour)
-                       return;
-               if (record.state != state) {
-                       state = record.state;
-                       if (prev != null) {
-                               coord(record);
-                               state_end(prev);
-                       }
-                       state_start(record);
-               }
-               coord(record);
-               prev = record;
-       }
-
-       public void write(AltosRecordIterable iterable) {
-               for (AltosRecord record : iterable)
-                       write(record);
-       }
-
-       public AltosKML(File in_name) throws FileNotFoundException {
-               name = in_name;
-               out = new PrintStream(name);
-       }
-
-       public AltosKML(String in_string) throws FileNotFoundException {
-               this(new File(in_string));
-       }
-}
diff --git a/ao-tools/altosui/AltosLanded.java b/ao-tools/altosui/AltosLanded.java
deleted file mode 100644 (file)
index d34efe6..0000000
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * 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;
-
-public class AltosLanded extends JComponent implements AltosFlightDisplay {
-       GridBagLayout   layout;
-       Font            label_font;
-       Font            value_font;
-
-       public class LandedValue {
-               JLabel          label;
-               JTextField      value;
-               void show(AltosState state, int crc_errors) {}
-
-               void reset() {
-                       value.setText("");
-               }
-
-               void show(String format, double v) {
-                       value.setText(String.format(format, v));
-               }
-
-               public LandedValue (GridBagLayout layout, int y, String text) {
-                       GridBagConstraints      c = new GridBagConstraints();
-                       c.weighty = 1;
-
-                       label = new JLabel(text);
-                       label.setFont(label_font);
-                       label.setHorizontalAlignment(SwingConstants.LEFT);
-                       c.gridx = 0; c.gridy = y;
-                       c.insets = new Insets(10, 10, 10, 10);
-                       c.anchor = GridBagConstraints.WEST;
-                       c.weightx = 0;
-                       c.fill = GridBagConstraints.VERTICAL;
-                       layout.setConstraints(label, c);
-                       add(label);
-
-                       value = new JTextField(Altos.text_width);
-                       value.setFont(value_font);
-                       value.setHorizontalAlignment(SwingConstants.RIGHT);
-                       c.gridx = 1; c.gridy = y;
-                       c.anchor = GridBagConstraints.WEST;
-                       c.weightx = 1;
-                       c.fill = GridBagConstraints.BOTH;
-                       layout.setConstraints(value, c);
-                       add(value);
-               }
-       }
-
-       String pos(double p, String pos, String neg) {
-               String  h = pos;
-               if (p < 0) {
-                       h = neg;
-                       p = -p;
-               }
-               int deg = (int) Math.floor(p);
-               double min = (p - Math.floor(p)) * 60.0;
-               return String.format("%s %4d° %9.6f", h, deg, min);
-       }
-
-       class Lat extends LandedValue {
-               void show (AltosState state, int crc_errors) {
-                       if (state.gps != null)
-                               value.setText(pos(state.gps.lat,"N", "S"));
-                       else
-                               value.setText("???");
-               }
-               public Lat (GridBagLayout layout, int y) {
-                       super (layout, y, "Latitude");
-               }
-       }
-
-       Lat lat;
-
-       class Lon extends LandedValue {
-               void show (AltosState state, int crc_errors) {
-                       if (state.gps != null)
-                               value.setText(pos(state.gps.lon,"E", "W"));
-                       else
-                               value.setText("???");
-               }
-               public Lon (GridBagLayout layout, int y) {
-                       super (layout, y, "Longitude");
-               }
-       }
-
-       Lon lon;
-
-       class Bearing extends LandedValue {
-               void show (AltosState state, int crc_errors) {
-                       if (state.from_pad != null)
-                               show("%3.0f°", state.from_pad.bearing);
-                       else
-                               value.setText("???");
-               }
-               public Bearing (GridBagLayout layout, int y) {
-                       super (layout, y, "Bearing");
-               }
-       }
-
-       Bearing bearing;
-
-       class Distance extends LandedValue {
-               void show (AltosState state, int crc_errors) {
-                       if (state.from_pad != null)
-                               show("%6.0f m", state.from_pad.distance);
-                       else
-                               value.setText("???");
-               }
-               public Distance (GridBagLayout layout, int y) {
-                       super (layout, y, "Distance");
-               }
-       }
-
-       Distance distance;
-
-       class Height extends LandedValue {
-               void show (AltosState state, int crc_errors) {
-                       show("%6.0f m", state.max_height);
-               }
-               public Height (GridBagLayout layout, int y) {
-                       super (layout, y, "Maximum Height");
-               }
-       }
-
-       Height  height;
-
-       class Speed extends LandedValue {
-               void show (AltosState state, int crc_errors) {
-                       show("%6.0f m/s", state.max_speed);
-               }
-               public Speed (GridBagLayout layout, int y) {
-                       super (layout, y, "Maximum Speed");
-               }
-       }
-
-       Speed   speed;
-
-       class Accel extends LandedValue {
-               void show (AltosState state, int crc_errors) {
-                       show("%6.0f m/s²", state.max_acceleration);
-               }
-               public Accel (GridBagLayout layout, int y) {
-                       super (layout, y, "Maximum Acceleration");
-               }
-       }
-
-       Accel   accel;
-
-       public void reset() {
-               lat.reset();
-               lon.reset();
-               bearing.reset();
-               distance.reset();
-               height.reset();
-               speed.reset();
-               accel.reset();
-       }
-
-       public void show(AltosState state, int crc_errors) {
-               bearing.show(state, crc_errors);
-               distance.show(state, crc_errors);
-               lat.show(state, crc_errors);
-               lon.show(state, crc_errors);
-               height.show(state, crc_errors);
-               speed.show(state, crc_errors);
-               accel.show(state, crc_errors);
-       }
-
-       public AltosLanded() {
-               layout = new GridBagLayout();
-
-               label_font = new Font("Dialog", Font.PLAIN, 22);
-               value_font = new Font("Monospaced", Font.PLAIN, 22);
-               setLayout(layout);
-
-               /* Elements in descent display */
-               bearing = new Bearing(layout, 0);
-               distance = new Distance(layout, 1);
-               lat = new Lat(layout, 2);
-               lon = new Lon(layout, 3);
-               height = new Height(layout, 4);
-               speed = new Speed(layout, 5);
-               accel = new Accel(layout, 6);
-       }
-}
diff --git a/ao-tools/altosui/AltosLed.java b/ao-tools/altosui/AltosLed.java
deleted file mode 100644 (file)
index e08e996..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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;
-
-public class AltosLed extends JLabel {
-       ImageIcon       on, off;
-
-       ImageIcon create_icon(String path) {
-               java.net.URL imgURL = AltosUI.class.getResource(path);
-               if (imgURL != null)
-                       return new ImageIcon(imgURL);
-               System.err.printf("Cannot find icon \"%s\"\n", path);
-               return null;
-       }
-
-       public void set(boolean set) {
-               if (set)
-                       setIcon(on);
-               else
-                       setIcon(off);
-       }
-
-       public AltosLed(String on_path, String off_path) {
-               on = create_icon(on_path);
-               off = create_icon(off_path);
-               setIcon(off);
-       }
-}
diff --git a/ao-tools/altosui/AltosLights.java b/ao-tools/altosui/AltosLights.java
deleted file mode 100644 (file)
index 2fa3841..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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;
-
-public class AltosLights extends JComponent {
-
-       GridBagLayout   gridbag;
-
-       AltosLed        red, green;
-
-       ImageIcon create_icon(String path, String description) {
-               java.net.URL imgURL = AltosUI.class.getResource(path);
-               if (imgURL != null)
-                       return new ImageIcon(imgURL, description);
-               System.err.printf("Cannot find icon \"%s\"\n", path);
-               return null;
-       }
-
-       public void set (boolean on) {
-               if (on) {
-                       red.set(false);
-                       green.set(true);
-               } else {
-                       red.set(true);
-                       green.set(false);
-               }
-       }
-
-       public AltosLights() {
-               GridBagConstraints c;
-               gridbag = new GridBagLayout();
-               setLayout(gridbag);
-
-               c = new GridBagConstraints();
-               red = new AltosLed("/redled.png", "/grayled.png");
-               c.gridx = 0; c.gridy = 0;
-               c.insets = new Insets (0, 5, 0, 5);
-               gridbag.setConstraints(red, c);
-               add(red);
-               red.set(true);
-               green = new AltosLed("/greenled.png", "/grayled.png");
-               c.gridx = 1; c.gridy = 0;
-               gridbag.setConstraints(green, c);
-               add(green);
-               green.set(false);
-       }
-}
diff --git a/ao-tools/altosui/AltosLine.java b/ao-tools/altosui/AltosLine.java
deleted file mode 100644 (file)
index 86e9d4c..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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;
-
-public class AltosLine {
-       public String   line;
-
-       public AltosLine() {
-               line = null;
-       }
-
-       public AltosLine(String s) {
-               line = s;
-       }
-}
\ No newline at end of file
diff --git a/ao-tools/altosui/AltosLog.java b/ao-tools/altosui/AltosLog.java
deleted file mode 100644 (file)
index dd147d2..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * 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.io.*;
-import java.lang.*;
-import java.util.*;
-import java.text.ParseException;
-import java.util.concurrent.LinkedBlockingQueue;
-
-/*
- * This creates a thread to capture telemetry data and write it to
- * a log file
- */
-class AltosLog implements Runnable {
-
-       LinkedBlockingQueue<AltosLine>  input_queue;
-       LinkedBlockingQueue<String>     pending_queue;
-       int                             serial;
-       int                             flight;
-       FileWriter                      log_file;
-       Thread                          log_thread;
-
-       private void close_log_file() {
-               if (log_file != null) {
-                       try {
-                               log_file.close();
-                       } catch (IOException io) {
-                       }
-                       log_file = null;
-               }
-       }
-
-       void close() {
-               close_log_file();
-               if (log_thread != null) {
-                       log_thread.interrupt();
-                       log_thread = null;
-               }
-       }
-
-       boolean open (AltosTelemetry telem) throws IOException {
-               AltosFile       a = new AltosFile(telem);
-
-               log_file = new FileWriter(a, true);
-               if (log_file != null) {
-                       while (!pending_queue.isEmpty()) {
-                               try {
-                                       String s = pending_queue.take();
-                                       log_file.write(s);
-                                       log_file.write('\n');
-                               } catch (InterruptedException ie) {
-                               }
-                       }
-                       log_file.flush();
-               }
-               return log_file != null;
-       }
-
-       public void run () {
-               try {
-                       for (;;) {
-                               AltosLine       line = input_queue.take();
-                               if (line.line == null)
-                                       continue;
-                               try {
-                                       AltosTelemetry  telem = new AltosTelemetry(line.line);
-                                       if (telem.serial != serial || telem.flight != flight || log_file == null) {
-                                               close_log_file();
-                                               serial = telem.serial;
-                                               flight = telem.flight;
-                                               open(telem);
-                                       }
-                               } catch (ParseException pe) {
-                               } catch (AltosCRCException ce) {
-                               }
-                               if (log_file != null) {
-                                       log_file.write(line.line);
-                                       log_file.write('\n');
-                                       log_file.flush();
-                               } else
-                                       pending_queue.put(line.line);
-                       }
-               } catch (InterruptedException ie) {
-               } catch (IOException ie) {
-               }
-               close();
-       }
-
-       public AltosLog (AltosSerial s) {
-               pending_queue = new LinkedBlockingQueue<String> ();
-               input_queue = new LinkedBlockingQueue<AltosLine> ();
-               s.add_monitor(input_queue);
-               serial = -1;
-               flight = -1;
-               log_file = null;
-               log_thread = new Thread(this);
-               log_thread.start();
-       }
-}
diff --git a/ao-tools/altosui/AltosPad.java b/ao-tools/altosui/AltosPad.java
deleted file mode 100644 (file)
index 6695434..0000000
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * 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;
-
-public class AltosPad extends JComponent implements AltosFlightDisplay {
-       GridBagLayout   layout;
-
-       public class LaunchStatus {
-               JLabel          label;
-               JTextField      value;
-               AltosLights     lights;
-
-               void show(AltosState state, int crc_errors) {}
-               void reset() {
-                       value.setText("");
-                       lights.set(false);
-               }
-
-               public LaunchStatus (GridBagLayout layout, int y, String text) {
-                       GridBagConstraints      c = new GridBagConstraints();
-                       c.weighty = 1;
-
-                       lights = new AltosLights();
-                       c.gridx = 0; c.gridy = y;
-                       c.anchor = GridBagConstraints.CENTER;
-                       c.fill = GridBagConstraints.VERTICAL;
-                       c.weightx = 0;
-                       layout.setConstraints(lights, c);
-                       add(lights);
-
-                       label = new JLabel(text);
-                       label.setFont(Altos.label_font);
-                       label.setHorizontalAlignment(SwingConstants.LEFT);
-                       c.gridx = 1; c.gridy = y;
-                       c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
-                       c.anchor = GridBagConstraints.WEST;
-                       c.fill = GridBagConstraints.VERTICAL;
-                       c.weightx = 0;
-                       layout.setConstraints(label, c);
-                       add(label);
-
-                       value = new JTextField(Altos.text_width);
-                       value.setFont(Altos.value_font);
-                       value.setHorizontalAlignment(SwingConstants.RIGHT);
-                       c.gridx = 2; c.gridy = y;
-                       c.anchor = GridBagConstraints.WEST;
-                       c.fill = GridBagConstraints.BOTH;
-                       c.weightx = 1;
-                       layout.setConstraints(value, c);
-                       add(value);
-
-               }
-       }
-
-       public class LaunchValue {
-               JLabel          label;
-               JTextField      value;
-               void show(AltosState state, int crc_errors) {}
-
-               void reset() {
-                       value.setText("");
-               }
-               public LaunchValue (GridBagLayout layout, int y, String text) {
-                       GridBagConstraints      c = new GridBagConstraints();
-                       c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad);
-                       c.weighty = 1;
-
-                       label = new JLabel(text);
-                       label.setFont(Altos.label_font);
-                       label.setHorizontalAlignment(SwingConstants.LEFT);
-                       c.gridx = 1; c.gridy = y;
-                       c.anchor = GridBagConstraints.WEST;
-                       c.fill = GridBagConstraints.VERTICAL;
-                       c.weightx = 0;
-                       layout.setConstraints(label, c);
-                       add(label);
-
-                       value = new JTextField(Altos.text_width);
-                       value.setFont(Altos.value_font);
-                       value.setHorizontalAlignment(SwingConstants.RIGHT);
-                       c.gridx = 2; c.gridy = y;
-                       c.anchor = GridBagConstraints.EAST;
-                       c.fill = GridBagConstraints.BOTH;
-                       c.weightx = 1;
-                       layout.setConstraints(value, c);
-                       add(value);
-               }
-       }
-
-       class Battery extends LaunchStatus {
-               void show (AltosState state, int crc_errors) {
-                       value.setText(String.format("%4.2f V", state.battery));
-                       lights.set(state.battery > 3.7);
-               }
-               public Battery (GridBagLayout layout, int y) {
-                       super(layout, y, "Battery Voltage");
-               }
-       }
-
-       Battery battery;
-
-       class Apogee extends LaunchStatus {
-               void show (AltosState state, int crc_errors) {
-                       value.setText(String.format("%4.2f V", state.drogue_sense));
-                       lights.set(state.drogue_sense > 3.2);
-               }
-               public Apogee (GridBagLayout layout, int y) {
-                       super(layout, y, "Apogee Igniter Voltage");
-               }
-       }
-
-       Apogee apogee;
-
-       class Main extends LaunchStatus {
-               void show (AltosState state, int crc_errors) {
-                       value.setText(String.format("%4.2f V", state.main_sense));
-                       lights.set(state.main_sense > 3.2);
-               }
-               public Main (GridBagLayout layout, int y) {
-                       super(layout, y, "Main Igniter Voltage");
-               }
-       }
-
-       Main main;
-
-       class GPSLocked extends LaunchStatus {
-               void show (AltosState state, int crc_errors) {
-                       value.setText(String.format("%4d sats", state.gps.nsat));
-                       lights.set(state.gps.locked);
-               }
-               public GPSLocked (GridBagLayout layout, int y) {
-                       super (layout, y, "GPS Locked");
-               }
-       }
-
-       GPSLocked gps_locked;
-
-       class GPSReady extends LaunchStatus {
-               void show (AltosState state, int crc_errors) {
-                       if (state.gps_ready)
-                               value.setText("Ready");
-                       else
-                               value.setText(String.format("Waiting %d", state.gps_waiting));
-                       lights.set(state.gps_ready);
-               }
-               public GPSReady (GridBagLayout layout, int y) {
-                       super (layout, y, "GPS Ready");
-               }
-       }
-
-       GPSReady gps_ready;
-
-       String pos(double p, String pos, String neg) {
-               String  h = pos;
-               if (p < 0) {
-                       h = neg;
-                       p = -p;
-               }
-               int deg = (int) Math.floor(p);
-               double min = (p - Math.floor(p)) * 60.0;
-               return String.format("%s %4d° %9.6f", h, deg, min);
-       }
-
-       class PadLat extends LaunchValue {
-               void show (AltosState state, int crc_errors) {
-                       value.setText(pos(state.pad_lat,"N", "S"));
-               }
-               public PadLat (GridBagLayout layout, int y) {
-                       super (layout, y, "Pad Latitude");
-               }
-       }
-
-       PadLat pad_lat;
-
-       class PadLon extends LaunchValue {
-               void show (AltosState state, int crc_errors) {
-                       value.setText(pos(state.pad_lon,"E", "W"));
-               }
-               public PadLon (GridBagLayout layout, int y) {
-                       super (layout, y, "Pad Longitude");
-               }
-       }
-
-       PadLon pad_lon;
-
-       class PadAlt extends LaunchValue {
-               void show (AltosState state, int crc_errors) {
-                       value.setText(String.format("%4.0f m", state.pad_alt));
-               }
-               public PadAlt (GridBagLayout layout, int y) {
-                       super (layout, y, "Pad Altitude");
-               }
-       }
-
-       PadAlt pad_alt;
-
-       public void reset() {
-               battery.reset();
-               apogee.reset();
-               main.reset();
-               gps_locked.reset();
-               gps_ready.reset();
-               pad_lat.reset();
-               pad_lon.reset();
-               pad_alt.reset();
-       }
-
-       public void show(AltosState state, int crc_errors) {
-               battery.show(state, crc_errors);
-               apogee.show(state, crc_errors);
-               main.show(state, crc_errors);
-               gps_locked.show(state, crc_errors);
-               gps_ready.show(state, crc_errors);
-               pad_lat.show(state, crc_errors);
-               pad_lon.show(state, crc_errors);
-               pad_alt.show(state, crc_errors);
-       }
-
-       public AltosPad() {
-               layout = new GridBagLayout();
-
-               setLayout(layout);
-
-               /* Elements in pad display:
-                *
-                * Battery voltage
-                * Igniter continuity
-                * GPS lock status
-                * GPS ready status
-                * GPS location
-                * Pad altitude
-                * RSSI
-                */
-               battery = new Battery(layout, 0);
-               apogee = new Apogee(layout, 1);
-               main = new Main(layout, 2);
-               gps_locked = new GPSLocked(layout, 3);
-               gps_ready = new GPSReady(layout, 4);
-               pad_lat = new PadLat(layout, 5);
-               pad_lon = new PadLon(layout, 6);
-               pad_alt = new PadAlt(layout, 7);
-       }
-}
diff --git a/ao-tools/altosui/AltosParse.java b/ao-tools/altosui/AltosParse.java
deleted file mode 100644 (file)
index fbfcaae..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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.text.*;
-import java.lang.*;
-
-public class AltosParse {
-       static boolean isdigit(char c) {
-               return '0' <= c && c <= '9';
-       }
-
-       static int parse_int(String v) throws ParseException {
-               try {
-                       return Altos.fromdec(v);
-               } catch (NumberFormatException e) {
-                       throw new ParseException("error parsing int " + v, 0);
-               }
-       }
-
-       static int parse_hex(String v) throws ParseException {
-               try {
-                       return Altos.fromhex(v);
-               } catch (NumberFormatException e) {
-                       throw new ParseException("error parsing hex " + v, 0);
-               }
-       }
-
-       static double parse_double(String v) throws ParseException {
-               try {
-                       return Double.parseDouble(v);
-               } catch (NumberFormatException e) {
-                       throw new ParseException("error parsing double " + v, 0);
-               }
-       }
-
-       static double parse_coord(String coord) throws ParseException {
-               String[]        dsf = coord.split("\\D+");
-
-               if (dsf.length != 3) {
-                       throw new ParseException("error parsing coord " + coord, 0);
-               }
-               int deg = parse_int(dsf[0]);
-               int min = parse_int(dsf[1]);
-               int frac = parse_int(dsf[2]);
-
-               double r = deg + (min + frac / 10000.0) / 60.0;
-               if (coord.endsWith("S") || coord.endsWith("W"))
-                       r = -r;
-               return r;
-       }
-
-       static String strip_suffix(String v, String suffix) {
-               if (v.endsWith(suffix))
-                       return v.substring(0, v.length() - suffix.length());
-               return v;
-       }
-
-       static void word(String v, String m) throws ParseException {
-               if (!v.equals(m)) {
-                       throw new ParseException("error matching '" + v + "' '" + m + "'", 0);
-               }
-       }
-}
diff --git a/ao-tools/altosui/AltosPreferences.java b/ao-tools/altosui/AltosPreferences.java
deleted file mode 100644 (file)
index e2a3df3..0000000
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * 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.io.*;
-import java.util.*;
-import java.text.*;
-import java.util.prefs.*;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.awt.Component;
-import javax.swing.*;
-import javax.swing.filechooser.FileSystemView;
-
-class AltosPreferences {
-       static Preferences preferences;
-
-       /* logdir preference name */
-       final static String logdirPreference = "LOGDIR";
-
-       /* channel preference name */
-       final static String channelPreferenceFormat = "CHANNEL-%d";
-
-       /* voice preference name */
-       final static String voicePreference = "VOICE";
-
-       /* callsign preference name */
-       final static String callsignPreference = "CALLSIGN";
-
-       /* firmware directory preference name */
-       final static String firmwaredirPreference = "FIRMWARE";
-
-       /* Default logdir is ~/TeleMetrum */
-       final static String logdirName = "TeleMetrum";
-
-       /* UI Component to pop dialogs up */
-       static Component component;
-
-       /* Log directory */
-       static File logdir;
-
-       /* Channel (map serial to channel) */
-       static Hashtable<Integer, Integer> channels;
-
-       /* Voice preference */
-       static boolean voice;
-
-       /* Callsign preference */
-       static String callsign;
-
-       /* Firmware directory */
-       static File firmwaredir;
-
-       public static void init(Component ui) {
-               preferences = Preferences.userRoot().node("/org/altusmetrum/altosui");
-
-               component = ui;
-
-               /* Initialize logdir from preferences */
-               String logdir_string = preferences.get(logdirPreference, null);
-               if (logdir_string != null)
-                       logdir = new File(logdir_string);
-               else {
-                       /* Use the file system view default directory */
-                       logdir = new File(FileSystemView.getFileSystemView().getDefaultDirectory(), logdirName);
-                       if (!logdir.exists())
-                               logdir.mkdirs();
-               }
-
-               channels = new Hashtable<Integer,Integer>();
-
-               voice = preferences.getBoolean(voicePreference, true);
-
-               callsign = preferences.get(callsignPreference,"N0CALL");
-
-               String firmwaredir_string = preferences.get(firmwaredirPreference, null);
-               if (firmwaredir_string != null)
-                       firmwaredir = new File(firmwaredir_string);
-               else
-                       firmwaredir = null;
-       }
-
-       static void flush_preferences() {
-               try {
-                       preferences.flush();
-               } catch (BackingStoreException ee) {
-                       JOptionPane.showMessageDialog(component,
-                                                     preferences.absolutePath(),
-                                                     "Cannot save prefernces",
-                                                     JOptionPane.ERROR_MESSAGE);
-               }
-       }
-
-       public static void set_logdir(File new_logdir) {
-               logdir = new_logdir;
-               synchronized (preferences) {
-                       preferences.put(logdirPreference, logdir.getPath());
-                       flush_preferences();
-               }
-       }
-
-       private static boolean check_dir(File dir) {
-               if (!dir.exists()) {
-                       if (!dir.mkdirs()) {
-                               JOptionPane.showMessageDialog(component,
-                                                             dir.getName(),
-                                                             "Cannot create directory",
-                                                             JOptionPane.ERROR_MESSAGE);
-                               return false;
-                       }
-               } else if (!dir.isDirectory()) {
-                       JOptionPane.showMessageDialog(component,
-                                                     dir.getName(),
-                                                     "Is not a directory",
-                                                     JOptionPane.ERROR_MESSAGE);
-                       return false;
-               }
-               return true;
-       }
-
-       /* Configure the log directory. This is where all telemetry and eeprom files
-        * will be written to, and where replay will look for telemetry files
-        */
-       public static void ConfigureLog() {
-               JFileChooser    logdir_chooser = new JFileChooser(logdir.getParentFile());
-
-               logdir_chooser.setDialogTitle("Configure Data Logging Directory");
-               logdir_chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
-
-               if (logdir_chooser.showDialog(component, "Select Directory") == JFileChooser.APPROVE_OPTION) {
-                       File dir = logdir_chooser.getSelectedFile();
-                       if (check_dir(dir))
-                               set_logdir(dir);
-               }
-       }
-
-       public static File logdir() {
-               return logdir;
-       }
-
-       public static void set_channel(int serial, int new_channel) {
-               channels.put(serial, new_channel);
-               synchronized (preferences) {
-                       preferences.putInt(String.format(channelPreferenceFormat, serial), new_channel);
-                       flush_preferences();
-               }
-       }
-
-       public static int channel(int serial) {
-               if (channels.containsKey(serial))
-                       return channels.get(serial);
-               int channel = preferences.getInt(String.format(channelPreferenceFormat, serial), 0);
-               channels.put(serial, channel);
-               return channel;
-       }
-
-       public static void set_voice(boolean new_voice) {
-               voice = new_voice;
-               synchronized (preferences) {
-                       preferences.putBoolean(voicePreference, voice);
-                       flush_preferences();
-               }
-       }
-
-       public static boolean voice() {
-               return voice;
-       }
-
-       public static void set_callsign(String new_callsign) {
-               callsign = new_callsign;
-               synchronized(preferences) {
-                       preferences.put(callsignPreference, callsign);
-                       flush_preferences();
-               }
-       }
-
-       public static String callsign() {
-               return callsign;
-       }
-
-       public static void set_firmwaredir(File new_firmwaredir) {
-               firmwaredir = new_firmwaredir;
-               synchronized (preferences) {
-                       preferences.put(firmwaredirPreference, firmwaredir.getPath());
-                       flush_preferences();
-               }
-       }
-
-       public static File firmwaredir() {
-               return firmwaredir;
-       }
-}
diff --git a/ao-tools/altosui/AltosReader.java b/ao-tools/altosui/AltosReader.java
deleted file mode 100644 (file)
index b9280a0..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.io.*;
-import java.util.*;
-import java.text.*;
-
-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/AltosRecord.java b/ao-tools/altosui/AltosRecord.java
deleted file mode 100644 (file)
index 1160a27..0000000
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * 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.lang.*;
-import java.text.*;
-import java.util.HashMap;
-import java.io.*;
-
-public class AltosRecord {
-       int     version;
-       String  callsign;
-       int     serial;
-       int     flight;
-       int     rssi;
-       int     status;
-       int     state;
-       int     tick;
-       int     accel;
-       int     pres;
-       int     temp;
-       int     batt;
-       int     drogue;
-       int     main;
-       int     flight_accel;
-       int     ground_accel;
-       int     flight_vel;
-       int     flight_pres;
-       int     ground_pres;
-       int     accel_plus_g;
-       int     accel_minus_g;
-       AltosGPS        gps;
-
-       double  time;   /* seconds since boost */
-
-       /*
-        * Values for our MP3H6115A pressure sensor
-        *
-        * From the data sheet:
-        *
-        * Pressure range: 15-115 kPa
-        * Voltage at 115kPa: 2.82
-        * Output scale: 27mV/kPa
-        *
-        *
-        * 27 mV/kPa * 2047 / 3300 counts/mV = 16.75 counts/kPa
-        * 2.82V * 2047 / 3.3 counts/V = 1749 counts/115 kPa
-        */
-
-       static final double counts_per_kPa = 27 * 2047 / 3300;
-       static final double counts_at_101_3kPa = 1674.0;
-
-       static double
-       barometer_to_pressure(double count)
-       {
-               return ((count / 16.0) / 2047.0 + 0.095) / 0.009 * 1000.0;
-       }
-
-       public double raw_pressure() {
-               return barometer_to_pressure(pres);
-       }
-
-       public double filtered_pressure() {
-               return barometer_to_pressure(flight_pres);
-       }
-
-       public double ground_pressure() {
-               return barometer_to_pressure(ground_pres);
-       }
-
-       public double filtered_altitude() {
-               return AltosConvert.pressure_to_altitude(filtered_pressure());
-       }
-
-       public double raw_altitude() {
-               return AltosConvert.pressure_to_altitude(raw_pressure());
-       }
-
-       public double ground_altitude() {
-               return AltosConvert.pressure_to_altitude(ground_pressure());
-       }
-
-       public double filtered_height() {
-               return filtered_altitude() - ground_altitude();
-       }
-
-       public double raw_height() {
-               return raw_altitude() - ground_altitude();
-       }
-
-       public double battery_voltage() {
-               return AltosConvert.cc_battery_to_voltage(batt);
-       }
-
-       public double main_voltage() {
-               return AltosConvert.cc_ignitor_to_voltage(main);
-       }
-
-       public double drogue_voltage() {
-               return AltosConvert.cc_ignitor_to_voltage(drogue);
-       }
-
-       /* Value for the CC1111 built-in temperature sensor
-        * Output voltage at 0°C = 0.755V
-        * Coefficient = 0.00247V/°C
-        * Reference voltage = 1.25V
-        *
-        * temp = ((value / 32767) * 1.25 - 0.755) / 0.00247
-        *      = (value - 19791.268) / 32768 * 1.25 / 0.00247
-        */
-
-       static double
-       thermometer_to_temperature(double thermo)
-       {
-               return (thermo - 19791.268) / 32728.0 * 1.25 / 0.00247;
-       }
-
-       public double temperature() {
-               return thermometer_to_temperature(temp);
-       }
-
-       double accel_counts_per_mss() {
-               double  counts_per_g = Math.abs(accel_minus_g - accel_plus_g) / 2;
-
-               return counts_per_g / 9.80665;
-       }
-       public double acceleration() {
-               return (ground_accel - accel) / accel_counts_per_mss();
-       }
-
-       public double accel_speed() {
-               double speed = flight_vel / (accel_counts_per_mss() * 100.0);
-               return speed;
-       }
-
-       public String state() {
-               return Altos.state_name(state);
-       }
-
-       public static String gets(FileInputStream s) throws IOException {
-               int c;
-               String  line = "";
-
-               while ((c = s.read()) != -1) {
-                       if (c == '\r')
-                               continue;
-                       if (c == '\n') {
-                               return line;
-                       }
-                       line = line + (char) c;
-               }
-               return null;
-       }
-
-       public AltosRecord(AltosRecord old) {
-               version = old.version;
-               callsign = old.callsign;
-               serial = old.serial;
-               flight = old.flight;
-               rssi = old.rssi;
-               status = old.status;
-               state = old.state;
-               tick = old.tick;
-               accel = old.accel;
-               pres = old.pres;
-               temp = old.temp;
-               batt = old.batt;
-               drogue = old.drogue;
-               main = old.main;
-               flight_accel = old.flight_accel;
-               ground_accel = old.ground_accel;
-               flight_vel = old.flight_vel;
-               flight_pres = old.flight_pres;
-               ground_pres = old.ground_pres;
-               accel_plus_g = old.accel_plus_g;
-               accel_minus_g = old.accel_minus_g;
-               gps = new AltosGPS(old.gps);
-       }
-
-       public AltosRecord() {
-               version = 0;
-               callsign = "N0CALL";
-               serial = 0;
-               flight = 0;
-               rssi = 0;
-               status = 0;
-               state = Altos.ao_flight_startup;
-               tick = 0;
-               accel = 0;
-               pres = 0;
-               temp = 0;
-               batt = 0;
-               drogue = 0;
-               main = 0;
-               flight_accel = 0;
-               ground_accel = 0;
-               flight_vel = 0;
-               flight_pres = 0;
-               ground_pres = 0;
-               accel_plus_g = 0;
-               accel_minus_g = 0;
-               gps = new AltosGPS();
-       }
-}
diff --git a/ao-tools/altosui/AltosRecordIterable.java b/ao-tools/altosui/AltosRecordIterable.java
deleted file mode 100644 (file)
index a7df92d..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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;
-
-public abstract class AltosRecordIterable implements Iterable<AltosRecord> {
-       public abstract Iterator<AltosRecord> iterator();
-       public void write_comments(PrintStream out) { }
-}
diff --git a/ao-tools/altosui/AltosReplayReader.java b/ao-tools/altosui/AltosReplayReader.java
deleted file mode 100644 (file)
index 4e5e1d9..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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;
-
-/*
- * Open an existing telemetry file and replay it in realtime
- */
-
-public class AltosReplayReader extends AltosFlightReader {
-       Iterator<AltosRecord>   iterator;
-
-       public AltosRecord read() {
-               if (iterator.hasNext())
-                       return iterator.next();
-               return null;
-       }
-
-       public void close (boolean interrupted) {
-       }
-
-       void update(AltosState state) throws InterruptedException {
-               /* Make it run in realtime after the rocket leaves the pad */
-               if (state.state > Altos.ao_flight_pad)
-                       Thread.sleep((int) (Math.min(state.time_change,10) * 1000));
-       }
-
-       public AltosReplayReader(Iterator<AltosRecord> in_iterator, String in_name) {
-               iterator = in_iterator;
-               name = in_name;
-       }
-}
diff --git a/ao-tools/altosui/AltosRomconfig.java b/ao-tools/altosui/AltosRomconfig.java
deleted file mode 100644 (file)
index 55056b5..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * 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.io.*;
-
-public class AltosRomconfig {
-       public boolean  valid;
-       public int      version;
-       public int      check;
-       public int      serial_number;
-       public int      radio_calibration;
-
-       static int get_int(byte[] bytes, int start, int len) {
-               int     v = 0;
-               int     o = 0;
-               while (len > 0) {
-                       v = v | ((((int) bytes[start]) & 0xff) << o);
-                       start++;
-                       len--;
-                       o += 8;
-               }
-               return v;
-       }
-
-       static void put_int(int value, byte[] bytes, int start, int len) {
-               while (len > 0) {
-                       bytes[start] = (byte) (value & 0xff);
-                       start++;
-                       len--;
-                       value >>= 8;
-               }
-       }
-
-       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;
-
-               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;
-               }
-               if (offset >= bytes.length || bytes[offset] == 0)
-                       return;
-               int len = ((((int) bytes[offset]) & 0xff) - 2) / 2;
-               String fmt = String.format("%%0%dd", len);
-
-               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);
-               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);
-                               valid = true;
-                               break;
-                       }
-               }
-       }
-
-       public AltosRomconfig(AltosHexfile hexfile) {
-               this(hexfile.data, 0xa0 - hexfile.address);
-       }
-
-       public void write(byte[] bytes, int offset) throws IOException {
-               if (!valid)
-                       throw new IOException("rom configuration invalid");
-
-               if (offset < 0 || bytes.length < offset + 10)
-                       throw new IOException("image cannot contain rom config");
-
-               AltosRomconfig existing = new AltosRomconfig(bytes, offset);
-               if (!existing.valid)
-                       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);
-                       break;
-               }
-       }
-
-       public void write (AltosHexfile hexfile) throws IOException {
-               write(hexfile.data, 0xa0 - hexfile.address);
-               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) {
-               valid = true;
-               version = 1;
-               check = (~version & 0xffff);
-               serial_number = in_serial_number;
-               radio_calibration = in_radio_calibration;
-       }
-
-       public boolean valid() {
-               return valid && serial_number != 0;
-       }
-
-       public AltosRomconfig() {
-               valid = false;
-       }
-}
diff --git a/ao-tools/altosui/AltosRomconfigUI.java b/ao-tools/altosui/AltosRomconfigUI.java
deleted file mode 100644 (file)
index e1dc974..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * 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 javax.swing.event.*;
-import java.io.*;
-import java.util.*;
-import java.text.*;
-import java.util.prefs.*;
-
-public class AltosRomconfigUI
-       extends JDialog
-       implements ActionListener
-{
-       Container       pane;
-       Box             box;
-       JLabel          serial_label;
-       JLabel          radio_calibration_label;
-
-       JFrame          owner;
-       JTextField      serial_value;
-       JTextField      radio_calibration_value;
-
-       JButton         ok;
-       JButton         cancel;
-
-       /* Build the UI using a grid bag */
-       public AltosRomconfigUI(JFrame in_owner) {
-               super (in_owner, "Configure TeleMetrum Rom Values", true);
-
-               owner = in_owner;
-               GridBagConstraints c;
-
-               Insets il = new Insets(4,4,4,4);
-               Insets ir = new Insets(4,4,4,4);
-
-               pane = getContentPane();
-               pane.setLayout(new GridBagLayout());
-
-               /* Serial */
-               c = new GridBagConstraints();
-               c.gridx = 0; c.gridy = 0;
-               c.gridwidth = 3;
-               c.fill = GridBagConstraints.NONE;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = il;
-               serial_label = new JLabel("Serial:");
-               pane.add(serial_label, c);
-
-               c = new GridBagConstraints();
-               c.gridx = 3; c.gridy = 0;
-               c.gridwidth = 3;
-               c.fill = GridBagConstraints.HORIZONTAL;
-               c.weightx = 1;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = ir;
-               serial_value = new JTextField("0");
-               pane.add(serial_value, c);
-
-               /* Radio calibration value */
-               c = new GridBagConstraints();
-               c.gridx = 0; c.gridy = 1;
-               c.gridwidth = 3;
-               c.fill = GridBagConstraints.NONE;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = il;
-               c.ipady = 5;
-               radio_calibration_label = new JLabel("Radio Calibration:");
-               pane.add(radio_calibration_label, c);
-
-               c = new GridBagConstraints();
-               c.gridx = 3; c.gridy = 1;
-               c.gridwidth = 3;
-               c.fill = GridBagConstraints.HORIZONTAL;
-               c.weightx = 1;
-               c.anchor = GridBagConstraints.LINE_START;
-               c.insets = ir;
-               c.ipady = 5;
-               radio_calibration_value = new JTextField("1186611");
-               pane.add(radio_calibration_value, c);
-
-               /* Buttons */
-               c = new GridBagConstraints();
-               c.gridx = 0; c.gridy = 2;
-               c.gridwidth = 3;
-               c.fill = GridBagConstraints.NONE;
-               c.anchor = GridBagConstraints.CENTER;
-               c.insets = il;
-               ok = new JButton("OK");
-               pane.add(ok, c);
-               ok.addActionListener(this);
-               ok.setActionCommand("ok");
-
-               c = new GridBagConstraints();
-               c.gridx = 3; c.gridy = 2;
-               c.gridwidth = 3;
-               c.fill = GridBagConstraints.NONE;
-               c.anchor = GridBagConstraints.CENTER;
-               c.insets = il;
-               cancel = new JButton("Cancel");
-               pane.add(cancel, c);
-               cancel.addActionListener(this);
-               cancel.setActionCommand("cancel");
-
-               pack();
-               setLocationRelativeTo(owner);
-       }
-
-       boolean selected;
-
-       /* Listen for events from our buttons */
-       public void actionPerformed(ActionEvent e) {
-               String  cmd = e.getActionCommand();
-
-               if (cmd.equals("ok")) {
-                       AltosRomconfig  romconfig = romconfig();
-                       if (romconfig == null || !romconfig.valid()) {
-                               JOptionPane.showMessageDialog(this,
-                                                             "Invalid serial number or radio calibration value",
-                                                             "Invalid rom configuration",
-                                                             JOptionPane.ERROR_MESSAGE);
-                               return;
-                       }
-                       selected = true;
-               }
-               setVisible(false);
-       }
-
-       int serial() {
-               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);
-               }
-       }
-
-       AltosRomconfig romconfig() {
-               try {
-                       return new AltosRomconfig(serial(), radio_calibration());
-               } catch (NumberFormatException ne) {
-                       return null;
-               }
-       }
-
-       public AltosRomconfig showDialog() {
-               setVisible(true);
-               if (selected)
-                       return romconfig();
-               return null;
-       }
-}
diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java
deleted file mode 100644 (file)
index b19143e..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * 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.
- */
-
-/*
- * Deal with TeleDongle on a serial port
- */
-
-package altosui;
-
-import java.lang.*;
-import java.io.*;
-import java.util.concurrent.*;
-import java.util.*;
-
-import libaltosJNI.*;
-
-/*
- * This class reads from the serial port and places each received
- * line in a queue. Dealing with that queue is left up to other
- * threads.
- */
-
-public class AltosSerial implements Runnable {
-
-       static List<String> devices_opened = Collections.synchronizedList(new LinkedList<String>());
-
-       AltosDevice device;
-       SWIGTYPE_p_altos_file altos;
-       LinkedList<LinkedBlockingQueue<AltosLine>> monitors;
-       LinkedBlockingQueue<AltosLine> reply_queue;
-       Thread input_thread;
-       String line;
-       byte[] line_bytes;
-       int line_count;
-       boolean monitor_mode;
-
-       public void run () {
-               int c;
-
-               try {
-                       for (;;) {
-                               c = libaltos.altos_getchar(altos, 0);
-                               if (Thread.interrupted())
-                                       break;
-                               if (c == libaltosConstants.LIBALTOS_ERROR) {
-                                       for (int e = 0; e < monitors.size(); e++) {
-                                               LinkedBlockingQueue<AltosLine> q = monitors.get(e);
-                                               q.put(new AltosLine());
-                                       }
-                                       reply_queue.put (new AltosLine());
-                                       break;
-                               }
-                               if (c == libaltosConstants.LIBALTOS_TIMEOUT)
-                                       continue;
-                               if (c == '\r')
-                                       continue;
-                               synchronized(this) {
-                                       if (c == '\n') {
-                                               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") || line.startsWith("CRC")) {
-                                                               for (int e = 0; e < monitors.size(); e++) {
-                                                                       LinkedBlockingQueue<AltosLine> q = monitors.get(e);
-                                                                       q.put(new AltosLine (line));
-                                                               }
-                                                       } else {
-//                                                             System.out.printf("GOT: %s\n", line);
-                                                               reply_queue.put(new AltosLine (line));
-                                                       }
-                                                       line_count = 0;
-                                                       line = "";
-                                               }
-                                       } else {
-                                               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++;
-                                       }
-                               }
-                       }
-               } catch (InterruptedException e) {
-               }
-       }
-
-       public void flush_output() {
-               if (altos != null)
-                       libaltos.altos_flush(altos);
-       }
-
-       public void flush_input() {
-               flush_output();
-               boolean got_some;
-               do {
-                       try {
-                               Thread.sleep(100);
-                       } catch (InterruptedException ie) {
-                       }
-                       got_some = !reply_queue.isEmpty();
-                       synchronized(this) {
-                               if (!"VERSION".startsWith(line) &&
-                                   !line.startsWith("VERSION"))
-                                       line = "";
-                               reply_queue.clear();
-                       }
-               } while (got_some);
-       }
-
-       public String get_reply() throws InterruptedException {
-               flush_output();
-               AltosLine line = reply_queue.take();
-               return line.line;
-       }
-
-       public String get_reply(int timeout) throws InterruptedException {
-               flush_output();
-               AltosLine line = reply_queue.poll(timeout, TimeUnit.MILLISECONDS);
-               if (line == null)
-                       return null;
-               return line.line;
-       }
-
-       public void add_monitor(LinkedBlockingQueue<AltosLine> q) {
-               set_monitor(true);
-               monitors.add(q);
-       }
-
-       public void remove_monitor(LinkedBlockingQueue<AltosLine> q) {
-               monitors.remove(q);
-               if (monitors.isEmpty())
-                       set_monitor(false);
-       }
-
-       public void close() {
-               if (altos != null) {
-                       libaltos.altos_close(altos);
-               }
-               if (input_thread != null) {
-                       try {
-                               input_thread.interrupt();
-                               input_thread.join();
-                       } catch (InterruptedException e) {
-                       }
-                       input_thread = null;
-               }
-               if (altos != null) {
-                       libaltos.altos_free(altos);
-                       altos = null;
-               }
-               synchronized (devices_opened) {
-                       devices_opened.remove(device.getPath());
-               }
-       }
-
-       public void putc(char c) {
-               if (altos != null)
-                       libaltos.altos_putchar(altos, c);
-       }
-
-       public void print(String data) {
-//             System.out.printf("\"%s\" ", data);
-               for (int i = 0; i < data.length(); i++)
-                       putc(data.charAt(i));
-       }
-
-       public void printf(String format, Object ... arguments) {
-               print(String.format(format, arguments));
-       }
-
-       private void open() throws FileNotFoundException, AltosSerialInUseException {
-               synchronized (devices_opened) {
-                       if (devices_opened.contains(device.getPath()))
-                               throw new AltosSerialInUseException(device);
-                       devices_opened.add(device.getPath());
-               }
-               altos = libaltos.altos_open(device);
-               if (altos == null) {
-                       close();
-                       throw new FileNotFoundException(device.toShortString());
-               }
-               input_thread = new Thread(this);
-               input_thread.start();
-               print("~\nE 0\n");
-               set_monitor(false);
-               flush_output();
-       }
-
-       public void set_radio() {
-               set_channel(AltosPreferences.channel(device.getSerial()));
-               set_callsign(AltosPreferences.callsign());
-       }
-
-       public void set_channel(int channel) {
-               if (altos != null) {
-                       if (monitor_mode)
-                               printf("m 0\nc r %d\nm 1\n", channel);
-                       else
-                               printf("c r %d\n", channel);
-                       flush_output();
-               }
-       }
-
-       void set_monitor(boolean monitor) {
-               monitor_mode = monitor;
-               if (altos != null) {
-                       if (monitor)
-                               printf("m 1\n");
-                       else
-                               printf("m 0\n");
-                       flush_output();
-               }
-       }
-
-       public void set_callsign(String callsign) {
-               if (altos != null) {
-                       printf ("c c %s\n", callsign);
-                       flush_output();
-               }
-       }
-
-       public AltosSerial(AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException {
-               device = in_device;
-               line = "";
-               monitor_mode = false;
-               monitors = new LinkedList<LinkedBlockingQueue<AltosLine>> ();
-               reply_queue = new LinkedBlockingQueue<AltosLine> ();
-               open();
-       }
-}
diff --git a/ao-tools/altosui/AltosSerialInUseException.java b/ao-tools/altosui/AltosSerialInUseException.java
deleted file mode 100644 (file)
index 4b108c7..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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 libaltosJNI.*;
-
-public class AltosSerialInUseException extends Exception {
-       public altos_device     device;
-
-       public AltosSerialInUseException (altos_device in_device) {
-               device = in_device;
-       }
-}
diff --git a/ao-tools/altosui/AltosSerialMonitor.java b/ao-tools/altosui/AltosSerialMonitor.java
deleted file mode 100644 (file)
index ad0e929..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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;
-
-public interface AltosSerialMonitor {
-       void data(String data);
-}
diff --git a/ao-tools/altosui/AltosSiteMap.java b/ao-tools/altosui/AltosSiteMap.java
deleted file mode 100644 (file)
index 8097060..0000000
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- * Copyright © 2010 Anthony Towns <aj@erisian.com.au>
- *
- * 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.image.*;
-import java.awt.event.*;
-import javax.swing.*;
-import javax.swing.event.MouseInputAdapter;
-import javax.imageio.ImageIO;
-import javax.swing.table.*;
-import java.io.*;
-import java.util.*;
-import java.text.*;
-import java.util.prefs.*;
-import java.lang.Math;
-import java.awt.geom.Point2D;
-import java.awt.geom.Line2D;
-
-public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay {
-       // preferred vertical step in a tile in naut. miles
-       // will actually choose a step size between x and 2x, where this
-       // is 1.5x
-       static final double tile_size_nmi = 0.75;
-
-       static final int px_size = 512;
-
-       static final int MAX_TILE_DELTA = 100;
-
-       private static Point2D.Double translatePoint(Point2D.Double p,
-                       Point2D.Double d)
-       {
-               return new Point2D.Double(p.x + d.x, p.y + d.y);
-       }
-
-       static class LatLng {
-               public double lat, lng;
-               public LatLng(double lat, double lng) {
-                       this.lat = lat;
-                       this.lng = lng;
-               }
-       }
-
-       // based on google js
-       //  http://maps.gstatic.com/intl/en_us/mapfiles/api-3/2/10/main.js
-       // search for fromLatLngToPoint and fromPointToLatLng
-       private static Point2D.Double pt(LatLng latlng, int zoom) {
-               double scale_x = 256/360.0 * Math.pow(2, zoom);
-               double scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom);
-               return pt(latlng, scale_x, scale_y);
-       }
-
-       private static Point2D.Double pt(LatLng latlng,
-                                        double scale_x, double scale_y)
-       {
-               Point2D.Double res = new Point2D.Double();
-               double e;
-
-               res.x = latlng.lng * scale_x;
-
-               e = Math.sin(Math.toRadians(latlng.lat));
-               e = Math.max(e,-(1-1.0E-15));
-               e = Math.min(e,  1-1.0E-15 );
-
-               res.y = 0.5*Math.log((1+e)/(1-e))*-scale_y;
-               return res;
-       }
-
-       static private LatLng latlng(Point2D.Double pt,
-                                    double scale_x, double scale_y)
-       {
-               double lat, lng;
-               double rads;
-
-               lng = pt.x/scale_x;
-               rads = 2 * Math.atan(Math.exp(-pt.y/scale_y));
-               lat = Math.toDegrees(rads - Math.PI/2);
-
-               return new LatLng(lat,lng);
-       }
-
-       int zoom;
-       double scale_x, scale_y;
-
-       private Point2D.Double pt(double lat, double lng) {
-               return pt(new LatLng(lat, lng), scale_x, scale_y);
-       }
-
-       private LatLng latlng(double x, double y) {
-               return latlng(new Point2D.Double(x,y), scale_x, scale_y);
-       }
-       private LatLng latlng(Point2D.Double pt) {
-               return latlng(pt, scale_x, scale_y);
-       }
-
-       HashMap<Point,AltosSiteMapTile> mapTiles = new HashMap<Point,AltosSiteMapTile>();
-       Point2D.Double centre;
-
-       private Point2D.Double tileCoordOffset(Point p) {
-               return new Point2D.Double(centre.x - p.x*px_size,
-                                         centre.y - p.y * px_size);
-       }
-
-       private Point tileOffset(Point2D.Double p) {
-               return new Point((int)Math.floor((centre.x+p.x)/px_size),
-                                (int)Math.floor((centre.y+p.y)/px_size));
-       }
-
-       private Point2D.Double getBaseLocation(double lat, double lng) {
-               Point2D.Double locn, north_step;
-
-               zoom = 2;
-               // stupid loop structure to please Java's control flow analysis
-               do {
-                       zoom++;
-                       scale_x = 256/360.0 * Math.pow(2, zoom);
-                       scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom);
-                       locn = pt(lat, lng);
-                       north_step = pt(lat+tile_size_nmi*4/3/60.0, lng);
-                       if (locn.y - north_step.y > px_size)
-                               break;
-               } while (zoom < 22);
-               locn.x = -px_size * Math.floor(locn.x/px_size);
-               locn.y = -px_size * Math.floor(locn.y/px_size);
-               return locn;
-       }
-
-       public void reset() {
-               // nothing
-       }
-
-       private void bgLoadMap(final AltosSiteMapTile tile,
-                              final File pngfile, final String pngurl)
-       {
-               //System.out.printf("Loading/fetching map %s\n", pngfile);
-               Thread thread = new Thread() {
-                       public void run() {
-                               ImageIcon res;
-                               res = AltosSiteMapCache.fetchAndLoadMap(pngfile, pngurl);
-                               if (res != null) {
-                                       tile.loadMap(res);
-                               } else {
-                                       System.out.printf("# Failed to fetch file %s\n", pngfile);
-                                       System.out.printf(" wget -O '%s' ''\n", pngfile, pngurl);
-                               }
-                       }
-               };
-               thread.start();
-       }
-
-       public static void prefetchMaps(double lat, double lng, int w, int h) {
-               AltosPreferences.init(null);
-
-               AltosSiteMap asm = new AltosSiteMap(true);
-               asm.centre = asm.getBaseLocation(lat, lng);
-
-               Point2D.Double p = new Point2D.Double();
-               Point2D.Double p2;
-               int dx = -w/2, dy = -h/2;
-               for (int y = dy; y < h+dy; y++) {
-                       for (int x = dx; x < w+dx; x++) {
-                               LatLng map_latlng = asm.latlng(
-                                                           -asm.centre.x + x*px_size + px_size/2,
-                                                           -asm.centre.y + y*px_size + px_size/2);
-                               File pngfile = asm.MapFile(map_latlng.lat, map_latlng.lng);
-                               String pngurl = asm.MapURL(map_latlng.lat, map_latlng.lng);
-                               if (pngfile.exists()) {
-                                       System.out.printf("Already have %s\n", pngfile);
-                               } else if (AltosSiteMapCache.fetchMap(pngfile, pngurl)) {
-                                       System.out.printf("Fetched map %s\n", pngfile);
-                               } else {
-                                       System.out.printf("# Failed to fetch file %s\n", pngfile);
-                                       System.out.printf(" wget -O '%s' ''\n", pngfile, pngurl);
-                               }
-                       }
-               }
-       }
-
-       private void initMap(AltosSiteMapTile tile, Point offset) {
-               Point2D.Double coord = tileCoordOffset(offset);
-
-               LatLng map_latlng = latlng(px_size/2-coord.x, px_size/2-coord.y);
-
-               File pngfile = MapFile(map_latlng.lat, map_latlng.lng);
-               String pngurl = MapURL(map_latlng.lat, map_latlng.lng);
-               bgLoadMap(tile, pngfile, pngurl);
-       }
-
-       private void initMaps(double lat, double lng) {
-               centre = getBaseLocation(lat, lng);
-
-               for (Point k : mapTiles.keySet()) {
-                       initMap(mapTiles.get(k), k);
-               }
-       }
-
-       private File MapFile(double lat, double lng) {
-               char chlat = lat < 0 ? 'S' : 'N';
-               char chlng = lng < 0 ? 'E' : 'W';
-               if (lat < 0) lat = -lat;
-               if (lng < 0) lng = -lng;
-               return new File(AltosPreferences.logdir(),
-                               String.format("map-%c%.6f,%c%.6f-%d.png",
-                                             chlat, lat, chlng, lng, zoom));
-       }
-
-       private String MapURL(double lat, double lng) {
-               return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=hybrid&format=png32", lat, lng, zoom, px_size, px_size);
-       }
-
-       boolean initialised = false;
-       Point2D.Double last_pt = null;
-       int last_state = -1;
-       public void show(final AltosState state, final int crc_errors) {
-               // if insufficient gps data, nothing to update
-               if (state.gps == null)
-                       return;
-               if (state.pad_lat == 0 && state.pad_lon == 0)
-                       return;
-               if (!state.gps.locked) {
-                       if (state.gps.nsat < 4)
-                               return;
-               }
-
-               if (!initialised) {
-                       initMaps(state.pad_lat, state.pad_lon);
-                       initialised = true;
-               }
-
-               final Point2D.Double pt = pt(state.gps.lat, state.gps.lon);
-               if (last_pt == pt && last_state == state.state)
-                       return;
-
-               if (last_pt == null) {
-                       last_pt = pt;
-               }
-               boolean in_any = false;
-               for (Point offset : mapTiles.keySet()) {
-                       AltosSiteMapTile tile = mapTiles.get(offset);
-                       Point2D.Double ref, lref;
-                       ref = translatePoint(pt, tileCoordOffset(offset));
-                       lref = translatePoint(last_pt, tileCoordOffset(offset));
-                       tile.show(state, crc_errors, lref, ref);
-                       if (0 <= ref.x && ref.x < px_size)
-                               if (0 <= ref.y && ref.y < px_size)
-                                       in_any = true;
-               }
-
-               Point offset = tileOffset(pt);
-               if (!in_any) {
-                       Point2D.Double ref, lref;
-                       ref = translatePoint(pt, tileCoordOffset(offset));
-                       lref = translatePoint(last_pt, tileCoordOffset(offset));
-
-                       AltosSiteMapTile tile = createTile(offset);
-                       tile.show(state, crc_errors, lref, ref);
-                       initMap(tile, offset);
-                       finishTileLater(tile, offset);
-               }
-
-               scrollRocketToVisible(pt);
-
-               if (offset != tileOffset(last_pt)) {
-                       ensureTilesAround(offset);
-               }
-
-               last_pt = pt;
-               last_state = state.state;
-       }
-
-       private AltosSiteMapTile createTile(Point offset) {
-               AltosSiteMapTile tile = new AltosSiteMapTile(px_size);
-               mapTiles.put(offset, tile);
-               return tile;
-       }
-       private void finishTileLater(final AltosSiteMapTile tile,
-                                    final Point offset)
-       {
-               SwingUtilities.invokeLater( new Runnable() {
-                       public void run() {
-                               addTileAt(tile, offset);
-                       }
-               } );
-       }
-
-       private void ensureTilesAround(Point base_offset) {
-               for (int x = -1; x <= 1; x++) {
-                       for (int y = -1; y <= 1; y++) {
-                               Point offset = new Point(base_offset.x + x, base_offset.y + y);
-                               if (mapTiles.containsKey(offset))
-                                       continue;
-                               AltosSiteMapTile tile = createTile(offset);
-                               initMap(tile, offset);
-                               finishTileLater(tile, offset);
-                       }
-               }
-       }
-
-       private Point topleft = new Point(0,0);
-       private void scrollRocketToVisible(Point2D.Double pt) {
-               Rectangle r = comp.getVisibleRect();
-               Point2D.Double copt = translatePoint(pt, tileCoordOffset(topleft));
-               int dx = (int)copt.x - r.width/2 - r.x;
-               int dy = (int)copt.y - r.height/2 - r.y;
-               if (Math.abs(dx) > r.width/4 || Math.abs(dy) > r.height/4) {
-                       r.x += dx;
-                       r.y += dy;
-                       comp.scrollRectToVisible(r);
-               }
-       }
-
-       private void addTileAt(AltosSiteMapTile tile, Point offset) {
-               if (Math.abs(offset.x) >= MAX_TILE_DELTA ||
-                               Math.abs(offset.y) >= MAX_TILE_DELTA)
-               {
-                       System.out.printf("Rocket too far away from pad (tile %d,%d)\n",
-                                         offset.x, offset.y);
-                       return;
-               }
-
-               boolean review = false;
-               Rectangle r = comp.getVisibleRect();
-               if (offset.x < topleft.x) {
-                       r.x += (topleft.x - offset.x) * px_size;
-                       topleft.x = offset.x;
-                       review = true;
-               }
-               if (offset.y < topleft.y) {
-                       r.y += (topleft.y - offset.y) * px_size;
-                       topleft.y = offset.y;
-                       review = true;
-               }
-               GridBagConstraints c = new GridBagConstraints();
-               c.anchor = GridBagConstraints.CENTER;
-               c.fill = GridBagConstraints.BOTH;
-               // put some space between the map tiles, debugging only
-               // c.insets = new Insets(5, 5, 5, 5);
-
-               c.gridx = offset.x + MAX_TILE_DELTA;
-               c.gridy = offset.y + MAX_TILE_DELTA;
-               layout.setConstraints(tile, c);
-
-               comp.add(tile);
-               if (review) {
-                       comp.scrollRectToVisible(r);
-               }
-       }
-
-       private AltosSiteMap(boolean knowWhatYouAreDoing) {
-               if (!knowWhatYouAreDoing) {
-                       throw new RuntimeException("Arggh.");
-               }
-       }
-
-       JComponent comp = new JComponent() { };
-       private GridBagLayout layout = new GridBagLayout();
-
-       public AltosSiteMap() {
-               GrabNDrag scroller = new GrabNDrag(comp);
-
-               comp.setLayout(layout);
-
-               for (int x = -1; x <= 1; x++) {
-                       for (int y = -1; y <= 1; y++) {
-                               Point offset = new Point(x, y);
-                               AltosSiteMapTile t = createTile(offset);
-                               addTileAt(t, offset);
-                       }
-               }
-               setViewportView(comp);
-               setPreferredSize(new Dimension(500,200));
-       }
-}
diff --git a/ao-tools/altosui/AltosSiteMapCache.java b/ao-tools/altosui/AltosSiteMapCache.java
deleted file mode 100644 (file)
index 2e62cc4..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright © 2010 Anthony Towns <aj@erisian.com.au>
- *
- * 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.image.*;
-import java.awt.event.*;
-import javax.swing.*;
-import javax.imageio.ImageIO;
-import javax.swing.table.*;
-import java.io.*;
-import java.util.*;
-import java.text.*;
-import java.util.prefs.*;
-import java.net.URL;
-import java.net.URLConnection;
-
-public class AltosSiteMapCache extends JLabel {
-       public static boolean fetchMap(File file, String url) {
-               URL u;
-
-               try {
-                       u = new URL(url);
-               } catch (java.net.MalformedURLException e) {
-                       return false;
-               }
-
-               byte[] data;
-               try {
-                       URLConnection uc = u.openConnection();
-                       int contentLength = uc.getContentLength();
-                       InputStream in = new BufferedInputStream(uc.getInputStream());
-                       int bytesRead = 0;
-                       int offset = 0;
-                       data = new byte[contentLength];
-                       while (offset < contentLength) {
-                               bytesRead = in.read(data, offset, data.length - offset);
-                               if (bytesRead == -1)
-                                       break;
-                               offset += bytesRead;
-                       }
-                       in.close();
-
-                       if (offset != contentLength) {
-                               return false;
-                       }
-               } catch (IOException e) {
-                       return false;
-               }
-
-               try {
-                       FileOutputStream out = new FileOutputStream(file);
-                       out.write(data);
-                       out.flush();
-                       out.close();
-               } catch (FileNotFoundException e) {
-                       return false;
-               } catch (IOException e) {
-                       if (file.exists()) {
-                               file.delete();
-                       }
-                       return false;
-               }
-               return true;
-       }
-
-       public static ImageIcon fetchAndLoadMap(File pngfile, String url) {
-               if (!pngfile.exists()) {
-                       if (!fetchMap(pngfile, url)) {
-                               return null;
-                       }
-               }
-               return loadMap(pngfile, url);
-       }
-
-       public static ImageIcon loadMap(File pngfile, String url) {
-               if (!pngfile.exists()) {
-                       return null;
-               }
-
-               try {
-                       return new ImageIcon(ImageIO.read(pngfile));
-               } catch (IOException e) {
-                       System.out.printf("# IO error trying to load %s\n", pngfile);
-                       return null;
-               }
-       }
-}
diff --git a/ao-tools/altosui/AltosSiteMapTile.java b/ao-tools/altosui/AltosSiteMapTile.java
deleted file mode 100644 (file)
index 8301f42..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright © 2010 Anthony Towns <aj@erisian.com.au>
- *
- * 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.image.*;
-import java.awt.event.*;
-import javax.swing.*;
-import javax.imageio.ImageIO;
-import javax.swing.table.*;
-import java.io.*;
-import java.util.*;
-import java.text.*;
-import java.util.prefs.*;
-import java.lang.Math;
-import java.awt.geom.Point2D;
-import java.awt.geom.Line2D;
-
-public class AltosSiteMapTile extends JLayeredPane {
-       JLabel mapLabel;
-       JLabel draw;
-       Graphics2D g2d;
-
-       public void loadMap(ImageIcon icn) {
-               mapLabel.setIcon(icn);
-       }
-
-       static Color stateColors[] = {
-               Color.WHITE,  // startup
-               Color.WHITE,  // idle
-               Color.WHITE,  // pad
-               Color.RED,    // boost
-               Color.PINK,   // fast
-               Color.YELLOW, // coast
-               Color.CYAN,   // drogue
-               Color.BLUE,   // main
-               Color.BLACK   // landed
-       };
-
-       private boolean drawn_landed_circle = false;
-       private boolean drawn_boost_circle = false;
-       public synchronized void show(AltosState state, int crc_errors,
-                                     Point2D.Double last_pt, Point2D.Double pt)
-       {
-               if (0 <= state.state && state.state < stateColors.length) {
-                       g2d.setColor(stateColors[state.state]);
-               }
-               g2d.draw(new Line2D.Double(last_pt, pt));
-
-               if (state.state == 3 && !drawn_boost_circle) {
-                       drawn_boost_circle = true;
-                       g2d.setColor(Color.RED);
-                       g2d.drawOval((int)last_pt.x-5, (int)last_pt.y-5, 10, 10);
-                       g2d.drawOval((int)last_pt.x-20, (int)last_pt.y-20, 40, 40);
-                       g2d.drawOval((int)last_pt.x-35, (int)last_pt.y-35, 70, 70);
-               }
-               if (state.state == 8 && !drawn_landed_circle) {
-                       drawn_landed_circle = true;
-                       g2d.setColor(Color.BLACK);
-                       g2d.drawOval((int)pt.x-5, (int)pt.y-5, 10, 10);
-                       g2d.drawOval((int)pt.x-20, (int)pt.y-20, 40, 40);
-                       g2d.drawOval((int)pt.x-35, (int)pt.y-35, 70, 70);
-               }
-
-               repaint();
-       }
-
-       public static Graphics2D fillLabel(JLabel l, Color c, int px_size) {
-               BufferedImage img = new BufferedImage(px_size, px_size,
-                                                     BufferedImage.TYPE_INT_ARGB);
-               Graphics2D g = img.createGraphics();
-               g.setColor(c);
-               g.fillRect(0, 0, px_size, px_size);
-               l.setIcon(new ImageIcon(img));
-               return g;
-       }
-
-       public AltosSiteMapTile(int px_size) {
-               setPreferredSize(new Dimension(px_size, px_size));
-
-               mapLabel = new JLabel();
-               fillLabel(mapLabel, Color.GRAY, px_size);
-               mapLabel.setOpaque(true);
-               mapLabel.setBounds(0, 0, px_size, px_size);
-               add(mapLabel, new Integer(0));
-
-               draw = new JLabel();
-               g2d = fillLabel(draw, new Color(127, 127, 127, 0), px_size);
-               g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
-                                    RenderingHints.VALUE_ANTIALIAS_ON);
-               g2d.setStroke(new BasicStroke(6, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
-               draw.setBounds(0, 0, px_size, px_size);
-               draw.setOpaque(false);
-
-               add(draw, new Integer(1));
-       }
-}
diff --git a/ao-tools/altosui/AltosState.java b/ao-tools/altosui/AltosState.java
deleted file mode 100644 (file)
index ec499d5..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * 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.
- */
-
-/*
- * Track flight state from telemetry or eeprom data stream
- */
-
-package altosui;
-
-public class AltosState {
-       AltosRecord data;
-
-       /* derived data */
-
-       long    report_time;
-
-       double  time_change;
-       int     tick;
-
-       int     state;
-       boolean landed;
-       boolean ascent; /* going up? */
-
-       double  ground_altitude;
-       double  height;
-       double  speed;
-       double  acceleration;
-       double  battery;
-       double  temperature;
-       double  main_sense;
-       double  drogue_sense;
-       double  baro_speed;
-
-       double  max_height;
-       double  max_acceleration;
-       double  max_speed;
-
-       AltosGPS        gps;
-
-       double  pad_lat;
-       double  pad_lon;
-       double  pad_alt;
-
-       static final int MIN_PAD_SAMPLES = 10;
-
-       int     npad;
-       int     ngps;
-       int     gps_waiting;
-       boolean gps_ready;
-
-       AltosGreatCircle from_pad;
-       double  elevation;      /* from pad */
-       double  range;          /* total distance */
-
-       double  gps_height;
-
-       int     speak_tick;
-       double  speak_altitude;
-
-
-       void init (AltosRecord cur, AltosState prev_state) {
-               int             i;
-               AltosRecord prev;
-
-               data = cur;
-
-               ground_altitude = data.ground_altitude();
-               height = data.filtered_altitude() - ground_altitude;
-
-               report_time = System.currentTimeMillis();
-
-               acceleration = data.acceleration();
-               speed = data.accel_speed();
-               temperature = data.temperature();
-               drogue_sense = data.drogue_voltage();
-               main_sense = data.main_voltage();
-               battery = data.battery_voltage();
-               tick = data.tick;
-               state = data.state;
-
-               if (prev_state != null) {
-
-                       /* Preserve any existing gps data */
-                       npad = prev_state.npad;
-                       ngps = prev_state.ngps;
-                       gps = prev_state.gps;
-                       pad_lat = prev_state.pad_lat;
-                       pad_lon = prev_state.pad_lon;
-                       pad_alt = prev_state.pad_alt;
-                       max_height = prev_state.max_height;
-                       max_acceleration = prev_state.max_acceleration;
-                       max_speed = prev_state.max_speed;
-
-                       /* make sure the clock is monotonic */
-                       while (tick < prev_state.tick)
-                               tick += 65536;
-
-                       time_change = (tick - prev_state.tick) / 100.0;
-
-                       /* compute barometric speed */
-
-                       double height_change = height - prev_state.height;
-                       if (time_change > 0)
-                               baro_speed = (prev_state.baro_speed * 3 + (height_change / time_change)) / 4.0;
-                       else
-                               baro_speed = prev_state.baro_speed;
-               } else {
-                       npad = 0;
-                       ngps = 0;
-                       gps = null;
-                       baro_speed = 0;
-                       time_change = 0;
-               }
-
-               if (state == Altos.ao_flight_pad) {
-
-                       /* Track consecutive 'good' gps reports, waiting for 10 of them */
-                       if (data.gps != null && data.gps.locked && data.gps.nsat >= 4)
-                               npad++;
-                       else
-                               npad = 0;
-
-                       /* Average GPS data while on the pad */
-                       if (data.gps != null && data.gps.locked && data.gps.nsat >= 4) {
-                               if (ngps > 1) {
-                                       /* filter pad position */
-                                       pad_lat = (pad_lat * 31.0 + data.gps.lat) / 32.0;
-                                       pad_lon = (pad_lon * 31.0 + data.gps.lon) / 32.0;
-                                       pad_alt = (pad_alt * 31.0 + data.gps.alt) / 32.0;
-                               } else {
-                                       pad_lat = data.gps.lat;
-                                       pad_lon = data.gps.lon;
-                                       pad_alt = data.gps.alt;
-                               }
-                               ngps++;
-                       }
-               }
-
-               gps_waiting = MIN_PAD_SAMPLES - npad;
-               if (gps_waiting < 0)
-                       gps_waiting = 0;
-
-               gps_ready = gps_waiting == 0;
-
-               ascent = (Altos.ao_flight_boost <= state &&
-                         state <= Altos.ao_flight_coast);
-
-               /* Only look at accelerometer data on the way up */
-               if (ascent && acceleration > max_acceleration)
-                       max_acceleration = acceleration;
-               if (ascent && speed > max_speed)
-                       max_speed = speed;
-
-               if (height > max_height)
-                       max_height = height;
-               if (data.gps != null) {
-                       if (gps == null || !gps.locked || data.gps.locked)
-                               gps = data.gps;
-                       if (ngps > 0 && gps.locked) {
-                               from_pad = new AltosGreatCircle(pad_lat, pad_lon, gps.lat, gps.lon);
-                       }
-               }
-               elevation = 0;
-               range = -1;
-               if (ngps > 0) {
-                       gps_height = gps.alt - pad_alt;
-                       if (from_pad != null) {
-                               elevation = Math.atan2(height, from_pad.distance) * 180 / Math.PI;
-                               range = Math.sqrt(height * height + from_pad.distance * from_pad.distance);
-                       }
-               } else {
-                       gps_height = 0;
-               }
-       }
-
-       public AltosState(AltosRecord cur) {
-               init(cur, null);
-       }
-
-       public AltosState (AltosRecord cur, AltosState prev) {
-               init(cur, prev);
-       }
-}
diff --git a/ao-tools/altosui/AltosTelemetry.java b/ao-tools/altosui/AltosTelemetry.java
deleted file mode 100644 (file)
index bdb6466..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * 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.lang.*;
-import java.text.*;
-import java.util.HashMap;
-
-/*
- * Telemetry data contents
- */
-
-
-/*
- * The telemetry data stream is a bit of a mess at present, with no consistent
- * formatting. In particular, the GPS data is formatted for viewing instead of parsing.
- * However, the key feature is that every telemetry line contains all of the information
- * necessary to describe the current rocket state, including the calibration values
- * for accelerometer and barometer.
- *
- * GPS unlocked:
- *
- * VERSION 2 CALL KB0G SERIAL  51 FLIGHT     2 RSSI  -68 STATUS ff STATE     pad  1001 \
- *    a: 16032 p: 21232 t: 20284 v: 25160 d:   204 m:   204 fa: 16038 ga: 16032 fv:       0 \
- *    fp: 21232 gp: 21230 a+: 16049 a-: 16304 GPS  0 sat unlocked SAT 1   15  30
- *
- * GPS locked:
- *
- * VERSION 2 CALL KB0G SERIAL  51 FLIGHT     2 RSSI  -71 STATUS ff STATE     pad  2504 \
- *     a: 16028 p: 21220 t: 20360 v: 25004 d:   208 m:   200 fa: 16031 ga: 16032 fv:     330 \
- *     fp: 21231 gp: 21230 a+: 16049 a-: 16304 \
- *     GPS  9 sat 2010-02-13 17:16:51 35°20.0803'N 106°45.2235'W  1790m  \
- *     0.00m/s(H) 0°     0.00m/s(V) 1.0(hdop)     0(herr)     0(verr) \
- *     SAT 10   29  30  24  28   5  25  21  20  15  33   1  23  30  24  18  26  10  29   2  26
- */
-
-public class AltosTelemetry extends AltosRecord {
-       public AltosTelemetry(String line) throws ParseException, AltosCRCException {
-               String[] words = line.split("\\s+");
-               int     i = 0;
-
-               if (words[i].equals("CRC") && words[i+1].equals("INVALID")) {
-                       i += 2;
-                       AltosParse.word(words[i++], "RSSI");
-                       rssi = AltosParse.parse_int(words[i++]);
-                       throw new AltosCRCException(rssi);
-               }
-               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++];
-
-               AltosParse.word (words[i++], "SERIAL");
-               serial = 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++]);
-
-               AltosParse.word(words[i++], "STATE");
-               state = Altos.state(words[i++]);
-
-               tick = AltosParse.parse_int(words[i++]);
-
-               AltosParse.word(words[i++], "a:");
-               accel = AltosParse.parse_int(words[i++]);
-
-               AltosParse.word(words[i++], "p:");
-               pres = AltosParse.parse_int(words[i++]);
-
-               AltosParse.word(words[i++], "t:");
-               temp = AltosParse.parse_int(words[i++]);
-
-               AltosParse.word(words[i++], "v:");
-               batt = AltosParse.parse_int(words[i++]);
-
-               AltosParse.word(words[i++], "d:");
-               drogue = AltosParse.parse_int(words[i++]);
-
-               AltosParse.word(words[i++], "m:");
-               main = AltosParse.parse_int(words[i++]);
-
-               AltosParse.word(words[i++], "fa:");
-               flight_accel = AltosParse.parse_int(words[i++]);
-
-               AltosParse.word(words[i++], "ga:");
-               ground_accel = AltosParse.parse_int(words[i++]);
-
-               AltosParse.word(words[i++], "fv:");
-               flight_vel = AltosParse.parse_int(words[i++]);
-
-               AltosParse.word(words[i++], "fp:");
-               flight_pres = AltosParse.parse_int(words[i++]);
-
-               AltosParse.word(words[i++], "gp:");
-               ground_pres = 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++]);
-               } else {
-                       accel_plus_g = ground_accel;
-                       accel_minus_g = ground_accel + 530;
-               }
-
-               gps = new AltosGPS(words, i, version);
-       }
-}
diff --git a/ao-tools/altosui/AltosTelemetryIterable.java b/ao-tools/altosui/AltosTelemetryIterable.java
deleted file mode 100644 (file)
index a71ab87..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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.io.*;
-import java.util.*;
-import java.text.*;
-
-public class AltosTelemetryIterable extends AltosRecordIterable {
-       LinkedList<AltosRecord> records;
-
-       public Iterator<AltosRecord> iterator () {
-               return records.iterator();
-       }
-
-       public AltosTelemetryIterable (FileInputStream input) {
-               boolean saw_boost = false;
-               int     current_tick = 0;
-               int     boost_tick = 0;
-
-               records = new LinkedList<AltosRecord> ();
-
-               try {
-                       for (;;) {
-                               String line = AltosRecord.gets(input);
-                               if (line == null) {
-                                       break;
-                               }
-                               try {
-                                       AltosTelemetry record = new AltosTelemetry(line);
-                                       if (record == null)
-                                               break;
-                                       if (records.isEmpty()) {
-                                               current_tick = record.tick;
-                                       } else {
-                                               int tick = record.tick | (current_tick & ~ 0xffff);
-                                               if (tick < current_tick - 0x1000)
-                                                       tick += 0x10000;
-                                               current_tick = tick;
-                                               record.tick = current_tick;
-                                       }
-                                       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 (AltosCRCException ce) {
-                                       System.out.printf("crc error\n");
-                               }
-                       }
-               } catch (IOException io) {
-                       System.out.printf("io exception\n");
-               }
-
-               /* adjust all tick counts to be relative to boost time */
-               for (AltosRecord r : this)
-                       r.time = (r.tick - boost_tick) / 100.0;
-
-               try {
-                       input.close();
-               } catch (IOException ie) {
-               }
-       }
-}
diff --git a/ao-tools/altosui/AltosTelemetryReader.java b/ao-tools/altosui/AltosTelemetryReader.java
deleted file mode 100644 (file)
index 6c5a939..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.lang.*;
-import java.text.*;
-import java.io.*;
-import java.util.concurrent.*;
-
-class AltosTelemetryReader extends AltosFlightReader {
-       AltosDevice     device;
-       AltosSerial     serial;
-       AltosLog        log;
-
-       LinkedBlockingQueue<AltosLine> telem;
-
-       AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException {
-               AltosLine l = telem.take();
-               if (l.line == null)
-                       throw new IOException("IO error");
-               return new AltosTelemetry(l.line);
-       }
-
-       void close(boolean interrupted) {
-               serial.remove_monitor(telem);
-               log.close();
-               serial.close();
-       }
-
-       void set_channel(int channel) {
-               serial.set_channel(channel);
-               AltosPreferences.set_channel(device.getSerial(), channel);
-       }
-
-       public AltosTelemetryReader (AltosDevice in_device)
-               throws FileNotFoundException, AltosSerialInUseException, IOException {
-               device = in_device;
-               serial = new AltosSerial(device);
-               log = new AltosLog(serial);
-               name = device.toShortString();
-
-               telem = new LinkedBlockingQueue<AltosLine>();
-               serial.set_radio();
-               serial.add_monitor(telem);
-       }
-}
diff --git a/ao-tools/altosui/AltosUI.app/Contents/Info.plist b/ao-tools/altosui/AltosUI.app/Contents/Info.plist
deleted file mode 100644 (file)
index 97b1b59..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
-       <key>CFBundleName</key>
-       <string>altosui</string>
-       <key>CFBundleVersion</key>
-       <string>100.0</string>
-       <key>CFBundleAllowMixedLocalizations</key>
-       <string>true</string>
-       <key>CFBundleExecutable</key>
-       <string>JavaApplicationStub</string>
-       <key>CFBundleDevelopmentRegion</key>
-       <string>English</string>
-       <key>CFBundlePackageType</key>
-       <string>APPL</string>
-       <key>CFBundleSignature</key>
-       <string>????</string>
-       <key>CFBundleGetInfoString</key>
-       <string>AltOS UI version 0.7</string>
-       <key>CFBundleInfoDictionaryVersion</key>
-       <string>6.0</string>
-       <key>CFBundleIconFile</key>
-       <string>AltosUIIcon.icns</string>
-       <key>Java</key>
-       <dict>
-               <key>MainClass</key>
-               <string>altosui.AltosUI</string>
-               <key>JVMVersion</key>
-               <string>1.5+</string>
-               <key>ClassPath</key>
-                       <array>
-                       <string>$JAVAROOT/altosui.jar</string>
-                       <string>$JAVAROOT/freetts.jar</string>
-                       </array>
-       </dict>
-</dict>
-</plist>
diff --git a/ao-tools/altosui/AltosUI.app/Contents/MacOS/JavaApplicationStub b/ao-tools/altosui/AltosUI.app/Contents/MacOS/JavaApplicationStub
deleted file mode 100755 (executable)
index c661d3e..0000000
Binary files a/ao-tools/altosui/AltosUI.app/Contents/MacOS/JavaApplicationStub and /dev/null differ
diff --git a/ao-tools/altosui/AltosUI.app/Contents/PkgInfo b/ao-tools/altosui/AltosUI.app/Contents/PkgInfo
deleted file mode 100644 (file)
index 8a43480..0000000
+++ /dev/null
@@ -1 +0,0 @@
-APPLAM.O
diff --git a/ao-tools/altosui/AltosUI.app/Contents/Resources/AltosUIIcon.icns b/ao-tools/altosui/AltosUI.app/Contents/Resources/AltosUIIcon.icns
deleted file mode 100644 (file)
index fe49f36..0000000
Binary files a/ao-tools/altosui/AltosUI.app/Contents/Resources/AltosUIIcon.icns and /dev/null differ
diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java
deleted file mode 100644 (file)
index 94c4dd2..0000000
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- * 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 libaltosJNI.*;
-
-public class AltosUI extends JFrame {
-       public AltosVoice voice = new AltosVoice();
-
-       public static boolean load_library(Frame frame) {
-               if (!AltosDevice.load_library()) {
-                       JOptionPane.showMessageDialog(frame,
-                                                     String.format("No AltOS library in \"%s\"",
-                                                                   System.getProperty("java.library.path","<undefined>")),
-                                                     "Cannot load device access library",
-                                                     JOptionPane.ERROR_MESSAGE);
-                       return false;
-               }
-               return true;
-       }
-
-       void telemetry_window(AltosDevice device) {
-               try {
-                       AltosFlightReader reader = new AltosTelemetryReader(device);
-                       if (reader != null)
-                               new AltosFlightUI(voice, reader, device.getSerial());
-               } catch (FileNotFoundException ee) {
-                       JOptionPane.showMessageDialog(AltosUI.this,
-                                                     String.format("Cannot open device \"%s\"",
-                                                                   device.toShortString()),
-                                                     "Cannot open target device",
-                                                     JOptionPane.ERROR_MESSAGE);
-               } catch (AltosSerialInUseException si) {
-                       JOptionPane.showMessageDialog(AltosUI.this,
-                                                     String.format("Device \"%s\" already in use",
-                                                                   device.toShortString()),
-                                                     "Device in use",
-                                                     JOptionPane.ERROR_MESSAGE);
-               } catch (IOException ee) {
-                       JOptionPane.showMessageDialog(AltosUI.this,
-                                                     device.toShortString(),
-                                                     "Unkonwn I/O error",
-                                                     JOptionPane.ERROR_MESSAGE);
-               }
-       }
-
-       Container       pane;
-       GridBagLayout   gridbag;
-
-       JButton addButton(int x, int y, String label) {
-               GridBagConstraints      c;
-               JButton                 b;
-
-               c = new GridBagConstraints();
-               c.gridx = x; c.gridy = y;
-               c.fill = GridBagConstraints.BOTH;
-               c.weightx = 1;
-               c.weighty = 1;
-               b = new JButton(label);
-
-               Dimension ps = b.getPreferredSize();
-
-               gridbag.setConstraints(b, c);
-               add(b, c);
-               return b;
-       }
-
-       public AltosUI() {
-
-               load_library(null);
-
-               java.net.URL imgURL = AltosUI.class.getResource("/altus-metrum-16x16.jpg");
-               if (imgURL != null)
-                       setIconImage(new ImageIcon(imgURL).getImage());
-
-               AltosPreferences.init(this);
-
-               pane = getContentPane();
-               gridbag = new GridBagLayout();
-               pane.setLayout(gridbag);
-
-               JButton b;
-
-               b = addButton(0, 0, "Monitor Flight");
-               b.addActionListener(new ActionListener() {
-                                       public void actionPerformed(ActionEvent e) {
-                                               ConnectToDevice();
-                                       }
-                               });
-               b = addButton(1, 0, "Save Flight Data");
-               b.addActionListener(new ActionListener() {
-                                       public void actionPerformed(ActionEvent e) {
-                                               SaveFlightData();
-                                       }
-                               });
-               b = addButton(2, 0, "Replay Flight");
-               b.addActionListener(new ActionListener() {
-                                       public void actionPerformed(ActionEvent e) {
-                                               Replay();
-                                       }
-                               });
-               b = addButton(3, 0, "Graph Data");
-               b.addActionListener(new ActionListener() {
-                                       public void actionPerformed(ActionEvent e) {
-                                               GraphData();
-                                       }
-                               });
-               b = addButton(4, 0, "Export Data");
-               b.addActionListener(new ActionListener() {
-                                       public void actionPerformed(ActionEvent e) {
-                                               ExportData();
-                                       }
-                               });
-               b = addButton(0, 1, "Configure TeleMetrum");
-               b.addActionListener(new ActionListener() {
-                                       public void actionPerformed(ActionEvent e) {
-                                               ConfigureTeleMetrum();
-                                       }
-                               });
-
-               b = addButton(1, 1, "Configure AltosUI");
-               b.addActionListener(new ActionListener() {
-                               public void actionPerformed(ActionEvent e) {
-                                       ConfigureAltosUI();
-                               }
-                       });
-
-               b = addButton(2, 1, "Flash Image");
-               b.addActionListener(new ActionListener() {
-                               public void actionPerformed(ActionEvent e) {
-                                       FlashImage();
-                               }
-                       });
-
-               b = addButton(3, 1, "Fire Igniter");
-               b.addActionListener(new ActionListener() {
-                               public void actionPerformed(ActionEvent e) {
-                                       FireIgniter();
-                               }
-                       });
-
-               b = addButton(4, 1, "Quit");
-               b.addActionListener(new ActionListener() {
-                               public void actionPerformed(ActionEvent e) {
-                                       System.exit(0);
-                               }
-                       });
-
-               setTitle("AltOS");
-
-               pane.doLayout();
-               pane.validate();
-
-               doLayout();
-               validate();
-
-               setVisible(true);
-
-               Insets i = getInsets();
-               Dimension ps = rootPane.getPreferredSize();
-               ps.width += i.left + i.right;
-               ps.height += i.top + i.bottom;
-               setPreferredSize(ps);
-               setSize(ps);
-               setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
-               addWindowListener(new WindowAdapter() {
-                       @Override
-                       public void windowClosing(WindowEvent e) {
-                               System.exit(0);
-                       }
-               });
-       }
-
-       private void ConnectToDevice() {
-               AltosDevice     device = AltosDeviceDialog.show(AltosUI.this,
-                                                               AltosDevice.product_basestation);
-
-               if (device != null)
-                       telemetry_window(device);
-       }
-
-       void ConfigureCallsign() {
-               String  result;
-               result = JOptionPane.showInputDialog(AltosUI.this,
-                                                    "Configure Callsign",
-                                                    AltosPreferences.callsign());
-               if (result != null)
-                       AltosPreferences.set_callsign(result);
-       }
-
-       void ConfigureTeleMetrum() {
-               new AltosConfig(AltosUI.this);
-       }
-
-       void FlashImage() {
-               new AltosFlashUI(AltosUI.this);
-       }
-
-       void FireIgniter() {
-               new AltosIgniteUI(AltosUI.this);
-       }
-
-       /*
-        * Replay a flight from telemetry data
-        */
-       private void Replay() {
-               AltosDataChooser chooser = new AltosDataChooser(
-                       AltosUI.this);
-
-               AltosRecordIterable iterable = chooser.runDialog();
-               if (iterable != null) {
-                       AltosFlightReader reader = new AltosReplayReader(iterable.iterator(),
-                                                                        chooser.filename());
-                       new AltosFlightUI(voice, reader);
-               }
-       }
-
-       /* Connect to TeleMetrum, either directly or through
-        * a TeleDongle over the packet link
-        */
-       private void SaveFlightData() {
-               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() {
-               AltosDataChooser chooser;
-               chooser = new AltosDataChooser(this);
-               AltosRecordIterable record_reader = chooser.runDialog();
-               if (record_reader == null)
-                       return;
-               new AltosCSVUI(AltosUI.this, record_reader, chooser.file());
-       }
-
-       /* Load a flight log CSV file and display a pretty graph.
-        */
-
-       private void GraphData() {
-               AltosDataChooser chooser;
-               chooser = new AltosDataChooser(this);
-               AltosRecordIterable record_reader = chooser.runDialog();
-               if (record_reader == null)
-                       return;
-               new AltosGraphUI(record_reader);
-       }
-
-       private void ConfigureAltosUI() {
-               new AltosConfigureUI(AltosUI.this, voice);
-       }
-
-       static AltosRecordIterable open_logfile(String filename) {
-               File file = new File (filename);
-               try {
-                       FileInputStream in;
-
-                       in = new FileInputStream(file);
-                       if (filename.endsWith("eeprom"))
-                               return new AltosEepromIterable(in);
-                       else
-                               return new AltosTelemetryIterable(in);
-               } catch (FileNotFoundException fe) {
-                       System.out.printf("Cannot open '%s'\n", filename);
-                       return null;
-               }
-       }
-
-       static AltosWriter 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 AltosWriter open_kml(String filename) {
-               File file = new File (filename);
-               try {
-                       return new AltosKML(file);
-               } catch (FileNotFoundException fe) {
-                       System.out.printf("Cannot open '%s'\n", filename);
-                       return null;
-               }
-       }
-
-       static final int process_csv = 1;
-       static final int process_kml = 2;
-
-       static void process_file(String input, int process) {
-               AltosRecordIterable iterable = open_logfile(input);
-               if (iterable == null)
-                       return;
-               if (process == 0)
-                       process = process_csv;
-               if ((process & process_csv) != 0) {
-                       String output = Altos.replace_extension(input,".csv");
-                       System.out.printf("Processing \"%s\" to \"%s\"\n", input, output);
-                       if (input.equals(output)) {
-                               System.out.printf("Not processing '%s'\n", input);
-                       } else {
-                               AltosWriter writer = open_csv(output);
-                               if (writer != null) {
-                                       writer.write(iterable);
-                                       writer.close();
-                               }
-                       }
-               }
-               if ((process & process_kml) != 0) {
-                       String output = Altos.replace_extension(input,".kml");
-                       System.out.printf("Processing \"%s\" to \"%s\"\n", input, output);
-                       if (input.equals(output)) {
-                               System.out.printf("Not processing '%s'\n", input);
-                       } else {
-                               AltosWriter writer = open_kml(output);
-                               if (writer == null)
-                                       return;
-                               writer.write(iterable);
-                               writer.close();
-                       }
-               }
-       }
-
-       public static void main(final String[] args) {
-               int     process = 0;
-               /* Handle batch-mode */
-        if (args.length == 1 && args[0].equals("--help")) {
-               System.out.printf("Usage: altosui [OPTION]... [FILE]...\n");
-               System.out.printf("  Options:\n");
-               System.out.printf("    --fetchmaps <lat> <lon>\tpre-fetch maps for site map view\n");
-               System.out.printf("    --replay <filename>\t\trelive the glory of past flights \n");
-               System.out.printf("    --csv\tgenerate comma separated output for spreadsheets, etc\n");
-               System.out.printf("    --kml\tgenerate KML output for use with Google Earth\n");
-        } else if (args.length == 3 && args[0].equals("--fetchmaps")) {
-            double lat = Double.parseDouble(args[1]);
-            double lon = Double.parseDouble(args[2]);
-            AltosSiteMap.prefetchMaps(lat, lon, 5, 5);
-        } else if (args.length == 2 && args[0].equals("--replay")) {
-                       String filename = args[1];
-                       FileInputStream in;
-                       try {
-                               in = new FileInputStream(filename);
-                       } catch (Exception e) {
-                               System.out.printf("Failed to open file '%s'\n", filename);
-                               return;
-                       }
-                       AltosRecordIterable recs;
-                       AltosReplayReader reader;
-                       if (filename.endsWith("eeprom")) {
-                               recs = new AltosEepromIterable(in);
-                       } else {
-                               recs = new AltosTelemetryIterable(in);
-                       }
-                       reader = new AltosReplayReader(recs.iterator(), filename);
-                       AltosFlightUI flight_ui = new AltosFlightUI(new AltosVoice(), reader);
-                       flight_ui.set_exit_on_close();
-                       return;
-               } else if (args.length > 0) {
-                       for (int i = 0; i < args.length; i++) {
-                               if (args[i].equals("--kml"))
-                                       process |= process_kml;
-                               else if (args[i].equals("--csv"))
-                                       process |= process_csv;
-                               else
-                                       process_file(args[i], process);
-                       }
-               } else {
-                       AltosUI altosui = new AltosUI();
-                       altosui.setVisible(true);
-
-                       AltosDevice[] devices = AltosDevice.list(AltosDevice.product_basestation);
-                       for (int i = 0; i < devices.length; i++)
-                               altosui.telemetry_window(devices[i]);
-               }
-       }
-}
diff --git a/ao-tools/altosui/AltosVoice.java b/ao-tools/altosui/AltosVoice.java
deleted file mode 100644 (file)
index ac13ee1..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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 com.sun.speech.freetts.Voice;
-import com.sun.speech.freetts.VoiceManager;
-import com.sun.speech.freetts.audio.JavaClipAudioPlayer;
-import java.util.concurrent.LinkedBlockingQueue;
-
-public class AltosVoice implements Runnable {
-       VoiceManager                    voice_manager;
-       Voice                           voice;
-       LinkedBlockingQueue<String>     phrases;
-       Thread                          thread;
-       boolean                         busy;
-
-       final static String voice_name = "kevin16";
-
-       public void run() {
-               try {
-                       for (;;) {
-                               String s = phrases.take();
-                               voice.speak(s);
-                               synchronized(this) {
-                                       if (phrases.isEmpty()) {
-                                               busy = false;
-                                               notifyAll();
-                                       }
-                               }
-                       }
-               } catch (InterruptedException e) {
-               }
-       }
-
-       public synchronized void drain() throws InterruptedException {
-               while (busy)
-                       wait();
-       }
-
-       public void speak_always(String s) {
-               try {
-                       if (voice != null) {
-                               synchronized(this) {
-                                       busy = true;
-                                       phrases.put(s);
-                               }
-                       }
-               } catch (InterruptedException e) {
-               }
-       }
-
-       public void speak(String s) {
-               if (AltosPreferences.voice())
-                       speak_always(s);
-       }
-
-       public void speak(String format, Object... parameters) {
-               speak(String.format(format, parameters));
-       }
-
-       public AltosVoice () {
-               busy = false;
-               voice_manager = VoiceManager.getInstance();
-               voice = voice_manager.getVoice(voice_name);
-               if (voice != null) {
-                       voice.allocate();
-                       phrases = new LinkedBlockingQueue<String> ();
-                       thread = new Thread(this);
-                       thread.start();
-               } else {
-                       System.out.printf("Voice manager failed to open %s\n", voice_name);
-                       Voice[] voices = voice_manager.getVoices();
-                       System.out.printf("Available voices:\n");
-                       for (int i = 0; i < voices.length; i++) {
-                               System.out.println("    " + voices[i].getName()
-                                                  + " (" + voices[i].getDomain() + " domain)");
-                       }
-               }
-       }
-}
diff --git a/ao-tools/altosui/AltosWriter.java b/ao-tools/altosui/AltosWriter.java
deleted file mode 100644 (file)
index a172dff..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.lang.*;
-import java.io.*;
-import java.text.*;
-import java.util.*;
-
-public interface AltosWriter {
-
-       public void write(AltosRecord record);
-
-       public void write(AltosRecordIterable iterable);
-
-       public void close();
-}
diff --git a/ao-tools/altosui/GrabNDrag.java b/ao-tools/altosui/GrabNDrag.java
deleted file mode 100644 (file)
index e6b87b5..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright © 2010 Anthony Towns <aj@erisian.com.au>
- *
- * 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.image.*;
-import java.awt.event.*;
-import javax.swing.*;
-import javax.swing.event.MouseInputAdapter;
-import javax.imageio.ImageIO;
-import javax.swing.table.*;
-import java.io.*;
-import java.util.*;
-import java.text.*;
-
-class GrabNDrag extends MouseInputAdapter {
-       private JComponent scroll;
-       private Point startPt = new Point();
-
-       public GrabNDrag(JComponent scroll) {
-               this.scroll = scroll;
-               scroll.addMouseMotionListener(this);
-               scroll.addMouseListener(this);
-               scroll.setAutoscrolls(true);
-       }
-
-       public void mousePressed(MouseEvent e) {
-               startPt.setLocation(e.getPoint());
-       }
-       public void mouseDragged(MouseEvent e) {
-               int xd = e.getX() - startPt.x;
-               int yd = e.getY() - startPt.y;
-
-               Rectangle r = scroll.getVisibleRect();
-               r.x -= xd;
-               r.y -= yd;
-               scroll.scrollRectToVisible(r);
-       }
-}
diff --git a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/Example.nsi b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/Example.nsi
deleted file mode 100644 (file)
index 3ed821e..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-#\r
-# InstDrv Example, (c) 2003 Jan Kiszka (Jan Kiszka@web.de)\r
-#\r
-\r
-Name "InstDrv.dll test"\r
-\r
-OutFile "InstDrv-Test.exe"\r
-\r
-ShowInstDetails show\r
-\r
-ComponentText "InstDrv Plugin Usage Example"\r
-\r
-Page components\r
-Page instfiles\r
-\r
-Section "Install a Driver" InstDriver\r
-    InstDrv::InitDriverSetup /NOUNLOAD "{4d36e978-e325-11ce-bfc1-08002be10318}" "IrCOMM2k"\r
-    Pop $0\r
-    DetailPrint "InitDriverSetup: $0"\r
-\r
-    InstDrv::DeleteOemInfFiles /NOUNLOAD\r
-    Pop $0\r
-    DetailPrint "DeleteOemInfFiles: $0"\r
-    StrCmp $0 "00000000" PrintInfNames ContInst1\r
-\r
-  PrintInfNames:\r
-    Pop $0\r
-    DetailPrint "Deleted $0"\r
-    Pop $0\r
-    DetailPrint "Deleted $0"\r
-\r
-  ContInst1:\r
-    InstDrv::CreateDevice /NOUNLOAD\r
-    Pop $0\r
-    DetailPrint "CreateDevice: $0"\r
-\r
-    SetOutPath $TEMP\r
-    File "ircomm2k.inf"\r
-    File "ircomm2k.sys"\r
-\r
-    InstDrv::InstallDriver /NOUNLOAD "$TEMP\ircomm2k.inf"\r
-    Pop $0\r
-    DetailPrint "InstallDriver: $0"\r
-    StrCmp $0 "00000000" PrintReboot ContInst2\r
-\r
-  PrintReboot:\r
-    Pop $0\r
-    DetailPrint "Reboot: $0"\r
-\r
-  ContInst2:\r
-    InstDrv::CountDevices\r
-    Pop $0\r
-    DetailPrint "CountDevices: $0"\r
-SectionEnd\r
-\r
-Section "Uninstall the driver again" UninstDriver\r
-    InstDrv::InitDriverSetup /NOUNLOAD "{4d36e978-e325-11ce-bfc1-08002be10318}" "IrCOMM2k"\r
-    Pop $0\r
-    DetailPrint "InitDriverSetup: $0"\r
-\r
-    InstDrv::DeleteOemInfFiles /NOUNLOAD\r
-    Pop $0\r
-    DetailPrint "DeleteOemInfFiles: $0"\r
-    StrCmp $0 "00000000" PrintInfNames ContUninst1\r
-\r
-  PrintInfNames:\r
-    Pop $0\r
-    DetailPrint "Deleted $0"\r
-    Pop $0\r
-    DetailPrint "Deleted $0"\r
-\r
-  ContUninst1:\r
-    InstDrv::RemoveAllDevices\r
-    Pop $0\r
-    DetailPrint "RemoveAllDevices: $0"\r
-    StrCmp $0 "00000000" PrintReboot ContUninst2\r
-\r
-  PrintReboot:\r
-    Pop $0\r
-    DetailPrint "Reboot: $0"\r
-\r
-  ContUninst2:\r
-    Delete "$SYSDIR\system32\ircomm2k.sys"\r
-SectionEnd
\ No newline at end of file
diff --git a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv-Test.exe b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv-Test.exe
deleted file mode 100644 (file)
index 615bae1..0000000
Binary files a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv-Test.exe and /dev/null differ
diff --git a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.c b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.c
deleted file mode 100644 (file)
index efe866e..0000000
+++ /dev/null
@@ -1,704 +0,0 @@
-/*\r
-\r
-InstDrv.dll - Installs or Removes Device Drivers\r
-\r
-Copyright © 2003 Jan Kiszka (Jan.Kiszka@web.de)\r
-\r
-This software is provided 'as-is', without any express or implied\r
-warranty. In no event will the authors be held liable for any damages\r
-arising from the use of this software.\r
-\r
-Permission is granted to anyone to use this software for any purpose,\r
-including commercial applications, and to alter it and redistribute\r
-it freely, subject to the following restrictions:\r
-\r
-1. The origin of this software must not be misrepresented; \r
-   you must not claim that you wrote the original software.\r
-   If you use this software in a product, an acknowledgment in the\r
-   product documentation would be appreciated but is not required.\r
-2. Altered versions must be plainly marked as such,\r
-   and must not be misrepresented as being the original software.\r
-3. This notice may not be removed or altered from any distribution.\r
-\r
-*/\r
-\r
-\r
-#include <windows.h>\r
-#include <setupapi.h>\r
-#include <newdev.h>\r
-#include "../exdll/exdll.h"\r
-\r
-\r
-char    paramBuf[1024];\r
-GUID    devClass;\r
-char    hwIdBuf[1024];\r
-int     initialized = 0;\r
-\r
-\r
-\r
-void* memset(void* dst, int val, unsigned int len)\r
-{\r
-    while (len-- > 0)\r
-        *((char *)dst)++ = val;\r
-\r
-    return NULL;\r
-}\r
-\r
-\r
-\r
-void* memcpy(void* dst, const void* src, unsigned int len)\r
-{\r
-    while (len-- > 0)\r
-        *((char *)dst)++ = *((char *)src)++;\r
-\r
-    return NULL;\r
-}\r
-\r
-\r
-\r
-int HexCharToInt(char c)\r
-{\r
-    if ((c >= '0') && (c <= '9'))\r
-        return c - '0';\r
-    else if ((c >= 'a') && (c <= 'f'))\r
-        return c - 'a' + 10;\r
-    else if ((c >= 'A') && (c <= 'F'))\r
-        return c - 'A' + 10;\r
-    else\r
-        return -1;\r
-}\r
-\r
-\r
-\r
-BOOLEAN HexStringToUInt(char* str, int width, void* valBuf)\r
-{\r
-    int i, val;\r
-\r
-\r
-    for (i = width - 4; i >= 0; i -= 4)\r
-    {\r
-        val = HexCharToInt(*str++);\r
-        if (val < 0)\r
-            return FALSE;\r
-        *(unsigned int *)valBuf += val << i;\r
-    }\r
-\r
-    return TRUE;\r
-}\r
-\r
-\r
-\r
-BOOLEAN StringToGUID(char* guidStr, GUID* pGuid)\r
-{\r
-    int i;\r
-\r
-\r
-    memset(pGuid, 0, sizeof(GUID));\r
-\r
-    if (*guidStr++ != '{')\r
-        return FALSE;\r
-\r
-    if (!HexStringToUInt(guidStr, 32, &pGuid->Data1))\r
-        return FALSE;\r
-    guidStr += 8;\r
-\r
-    if (*guidStr++ != '-')\r
-        return FALSE;\r
-\r
-    if (!HexStringToUInt(guidStr, 16, &pGuid->Data2))\r
-        return FALSE;\r
-    guidStr += 4;\r
-\r
-    if (*guidStr++ != '-')\r
-        return FALSE;\r
-\r
-    if (!HexStringToUInt(guidStr, 16, &pGuid->Data3))\r
-        return FALSE;\r
-    guidStr += 4;\r
-\r
-    if (*guidStr++ != '-')\r
-        return FALSE;\r
-\r
-    for (i = 0; i < 2; i++)\r
-    {\r
-        if (!HexStringToUInt(guidStr, 8, &pGuid->Data4[i]))\r
-            return FALSE;\r
-        guidStr += 2;\r
-    }\r
-\r
-    if (*guidStr++ != '-')\r
-        return FALSE;\r
-\r
-    for (i = 2; i < 8; i++)\r
-    {\r
-        if (!HexStringToUInt(guidStr, 8, &pGuid->Data4[i]))\r
-            return FALSE;\r
-        guidStr += 2;\r
-    }\r
-\r
-    if (*guidStr++ != '}')\r
-        return FALSE;\r
-\r
-    return TRUE;\r
-}\r
-\r
-\r
-\r
-DWORD FindNextDevice(HDEVINFO devInfoSet, SP_DEVINFO_DATA* pDevInfoData, DWORD* pIndex)\r
-{\r
-    DWORD   buffersize = 0;\r
-    LPTSTR  buffer     = NULL;\r
-    DWORD   dataType;\r
-    DWORD   result;\r
-\r
-\r
-    while (1)\r
-    {\r
-        if (!SetupDiEnumDeviceInfo(devInfoSet, (*pIndex)++, pDevInfoData))\r
-        {\r
-            result = GetLastError();\r
-            break;\r
-        }\r
-\r
-      GetDeviceRegistryProperty:\r
-        if (!SetupDiGetDeviceRegistryProperty(devInfoSet, pDevInfoData, SPDRP_HARDWAREID,\r
-                                              &dataType, (PBYTE)buffer, buffersize,\r
-                                              &buffersize))\r
-        {\r
-            result = GetLastError();\r
-\r
-            if (result == ERROR_INSUFFICIENT_BUFFER)\r
-            {\r
-                if (buffer != NULL)\r
-                    LocalFree(buffer);\r
-\r
-                buffer = (LPTSTR)LocalAlloc(LPTR, buffersize);\r
-\r
-                if (buffer == NULL)\r
-                    break;\r
-\r
-                goto GetDeviceRegistryProperty;\r
-            }\r
-            else if (result == ERROR_INVALID_DATA)\r
-                continue;   // ignore invalid entries\r
-            else\r
-                break;      // break on other errors\r
-        }\r
-\r
-        if (lstrcmpi(buffer, hwIdBuf) == 0)\r
-        {\r
-            result  = 0;\r
-            break;\r
-        }\r
-    }\r
-\r
-    if (buffer != NULL)\r
-        LocalFree(buffer);\r
-\r
-    return result;\r
-}\r
-\r
-\r
-\r
-DWORD FindFirstDevice(HWND hwndParent, const GUID* pDevClass, const LPTSTR hwId,\r
-                      HDEVINFO* pDevInfoSet, SP_DEVINFO_DATA* pDevInfoData,\r
-                      DWORD *pIndex, DWORD flags)\r
-{\r
-    DWORD   result;\r
-\r
-\r
-    *pDevInfoSet = SetupDiGetClassDevs((GUID*)pDevClass, NULL, hwndParent, flags);\r
-    if (*pDevInfoSet == INVALID_HANDLE_VALUE)\r
-        return GetLastError();\r
-\r
-    pDevInfoData->cbSize = sizeof(SP_DEVINFO_DATA);\r
-    *pIndex = 0;\r
-\r
-    result = FindNextDevice(*pDevInfoSet, pDevInfoData, pIndex);\r
-\r
-    if (result != 0)\r
-        SetupDiDestroyDeviceInfoList(*pDevInfoSet);\r
-\r
-    return result;\r
-}\r
-\r
-\r
-\r
-/*\r
- * InstDrv::InitDriverSetup devClass drvHWID\r
- *\r
- *  devClass    - GUID of the driver's device setup class\r
- *  drvHWID     - Hardware ID of the supported device\r
- *\r
- * Return:\r
- *  result      - error message, empty on success\r
- */\r
-void __declspec(dllexport) InitDriverSetup(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)\r
-{\r
-    EXDLL_INIT();\r
-\r
-    /* convert class GUID */\r
-    popstring(paramBuf);\r
-\r
-    if (!StringToGUID(paramBuf, &devClass))\r
-    {\r
-        popstring(paramBuf);\r
-        pushstring("Invalid GUID!");\r
-        return;\r
-    }\r
-\r
-    /* get hardware ID */\r
-    memset(hwIdBuf, 0, sizeof(hwIdBuf));\r
-    popstring(hwIdBuf);\r
-\r
-    initialized = 1;\r
-    pushstring("");\r
-}\r
-\r
-\r
-\r
-/*\r
- * InstDrv::CountDevices\r
- *\r
- * Return:\r
- *  result      - Number of installed devices the driver supports\r
- */\r
-void __declspec(dllexport) CountDevices(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)\r
-{\r
-    HDEVINFO            devInfoSet;\r
-    SP_DEVINFO_DATA     devInfoData;\r
-    int                 count = 0;\r
-    char                countBuf[16];\r
-    DWORD               index;\r
-    DWORD               result;\r
-\r
-\r
-    EXDLL_INIT();\r
-\r
-    if (!initialized)\r
-    {\r
-        pushstring("Fatal error!");\r
-        return;\r
-    }\r
-\r
-    result = FindFirstDevice(hwndParent, &devClass, hwIdBuf, &devInfoSet, &devInfoData,\r
-                             &index, DIGCF_PRESENT);\r
-    if (result != 0)\r
-    {\r
-        pushstring("0");\r
-        return;\r
-    }\r
-\r
-    do\r
-    {\r
-        count++;\r
-    } while (FindNextDevice(devInfoSet, &devInfoData, &index) == 0);\r
-\r
-    SetupDiDestroyDeviceInfoList(devInfoSet);\r
-\r
-    wsprintf(countBuf, "%d", count);\r
-    pushstring(countBuf);\r
-}\r
-\r
-\r
-\r
-/*\r
- * InstDrv::CreateDevice\r
- *\r
- * Return:\r
- *  result      - Windows error code\r
- */\r
-void __declspec(dllexport) CreateDevice(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)\r
-{\r
-    HDEVINFO            devInfoSet;\r
-    SP_DEVINFO_DATA     devInfoData;\r
-    DWORD               result = 0;\r
-    char                resultBuf[16];\r
-\r
-\r
-    EXDLL_INIT();\r
-\r
-    if (!initialized)\r
-    {\r
-        pushstring("Fatal error!");\r
-        return;\r
-    }\r
-\r
-    devInfoSet = SetupDiCreateDeviceInfoList(&devClass, hwndParent);\r
-    if (devInfoSet == INVALID_HANDLE_VALUE)\r
-    {\r
-        wsprintf(resultBuf, "%08X", GetLastError());\r
-        pushstring(resultBuf);\r
-        return;\r
-    }\r
-\r
-    devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);\r
-    if (!SetupDiCreateDeviceInfo(devInfoSet, hwIdBuf, &devClass, NULL,\r
-                                 hwndParent, DICD_GENERATE_ID, &devInfoData))\r
-    {\r
-        result = GetLastError();\r
-        goto InstallCleanup;\r
-    }\r
-\r
-    if (!SetupDiSetDeviceRegistryProperty(devInfoSet, &devInfoData, SPDRP_HARDWAREID,\r
-                                          hwIdBuf, (lstrlen(hwIdBuf)+2)*sizeof(TCHAR))) \r
-    {\r
-        result = GetLastError();\r
-        goto InstallCleanup;\r
-    }\r
-\r
-    if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE, devInfoSet, &devInfoData))\r
-        result = GetLastError();\r
-\r
-  InstallCleanup:\r
-    SetupDiDestroyDeviceInfoList(devInfoSet);\r
-\r
-    wsprintf(resultBuf, "%08X", result);\r
-    pushstring(resultBuf);\r
-}\r
-\r
-\r
-\r
-/*\r
- * InstDrv::InstallDriver infPath\r
- *\r
- * Return:\r
- *  result      - Windows error code\r
- *  reboot      - non-zero if reboot is required\r
- */\r
-void __declspec(dllexport) InstallDriver(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)\r
-{\r
-    char    resultBuf[16];\r
-    BOOL    reboot;\r
-\r
-\r
-    EXDLL_INIT();\r
-    popstring(paramBuf);\r
-\r
-    if (!initialized)\r
-    {\r
-        pushstring("Fatal error!");\r
-        return;\r
-    }\r
-\r
-    if (!UpdateDriverForPlugAndPlayDevices(hwndParent, hwIdBuf, paramBuf,\r
-                                           INSTALLFLAG_FORCE, &reboot))\r
-    {\r
-        wsprintf(resultBuf, "%08X", GetLastError());\r
-        pushstring(resultBuf);\r
-    }\r
-    else\r
-    {\r
-        wsprintf(resultBuf, "%d", reboot);\r
-        pushstring(resultBuf);\r
-        pushstring("00000000");\r
-    }\r
-}\r
-\r
-\r
-\r
-/*\r
- * InstDrv::DeleteOemInfFiles\r
- *\r
- * Return:\r
- *  result      - Windows error code\r
- *  oeminf      - Path of the deleted devices setup file (oemXX.inf)\r
- *  oempnf      - Path of the deleted devices setup file (oemXX.pnf)\r
- */\r
-void __declspec(dllexport) DeleteOemInfFiles(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)\r
-{\r
-    HDEVINFO                devInfo;\r
-    SP_DEVINFO_DATA         devInfoData;\r
-    SP_DRVINFO_DATA         drvInfoData;\r
-    SP_DRVINFO_DETAIL_DATA  drvInfoDetail;\r
-    DWORD                   index;\r
-    DWORD                   result;\r
-    char                    resultBuf[16];\r
-\r
-\r
-    if (!initialized)\r
-    {\r
-        pushstring("Fatal error!");\r
-        return;\r
-    }\r
-\r
-    result = FindFirstDevice(NULL, &devClass, hwIdBuf, &devInfo, &devInfoData, &index, 0);\r
-    if (result != 0)\r
-        goto Cleanup1;\r
-\r
-    if (!SetupDiBuildDriverInfoList(devInfo, &devInfoData, SPDIT_COMPATDRIVER))\r
-    {\r
-        result = GetLastError();\r
-        goto Cleanup2;\r
-    }\r
-\r
-    drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);\r
-    drvInfoDetail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);\r
-\r
-    if (!SetupDiEnumDriverInfo(devInfo, &devInfoData, SPDIT_COMPATDRIVER, 0, &drvInfoData))\r
-    {\r
-        result = GetLastError();\r
-        goto Cleanup3;\r
-    }\r
-\r
-    if (!SetupDiGetDriverInfoDetail(devInfo, &devInfoData, &drvInfoData,\r
-                                    &drvInfoDetail, sizeof(drvInfoDetail), NULL))\r
-    {\r
-        result = GetLastError();\r
-\r
-        if (result != ERROR_INSUFFICIENT_BUFFER)\r
-            goto Cleanup3;\r
-\r
-        result = 0;\r
-    }\r
-\r
-    pushstring(drvInfoDetail.InfFileName);\r
-    if (!DeleteFile(drvInfoDetail.InfFileName))\r
-        result = GetLastError();\r
-    else\r
-    {\r
-        index = lstrlen(drvInfoDetail.InfFileName);\r
-        if (index > 3)\r
-        {\r
-            lstrcpy(drvInfoDetail.InfFileName+index-3, "pnf");\r
-            pushstring(drvInfoDetail.InfFileName);\r
-            if (!DeleteFile(drvInfoDetail.InfFileName))\r
-                result = GetLastError();\r
-        }\r
-    }\r
-\r
-  Cleanup3:\r
-    SetupDiDestroyDriverInfoList(devInfo, &devInfoData, SPDIT_COMPATDRIVER);\r
-\r
-  Cleanup2:\r
-    SetupDiDestroyDeviceInfoList(devInfo);\r
-\r
-  Cleanup1:\r
-    wsprintf(resultBuf, "%08X", result);\r
-    pushstring(resultBuf);\r
-}\r
-\r
-\r
-\r
-/*\r
- * InstDrv::RemoveAllDevices\r
- *\r
- * Return:\r
- *  result      - Windows error code\r
- *  reboot      - non-zero if reboot is required\r
- */\r
-void __declspec(dllexport) RemoveAllDevices(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)\r
-{\r
-    HDEVINFO                devInfo;\r
-    SP_DEVINFO_DATA         devInfoData;\r
-    DWORD                   index;\r
-    DWORD                   result;\r
-    char                    resultBuf[16];\r
-    BOOL                    reboot = FALSE;\r
-    SP_DEVINSTALL_PARAMS    instParams;\r
-\r
-\r
-    EXDLL_INIT();\r
-\r
-    if (!initialized)\r
-    {\r
-        pushstring("Fatal error!");\r
-        return;\r
-    }\r
-\r
-    result = FindFirstDevice(NULL, &devClass, hwIdBuf, &devInfo, &devInfoData, &index, 0);\r
-    if (result != 0)\r
-        goto Cleanup1;\r
-\r
-    do\r
-    {\r
-        if (!SetupDiCallClassInstaller(DIF_REMOVE, devInfo, &devInfoData))\r
-        {\r
-            result = GetLastError();\r
-            break;\r
-        }\r
-\r
-        instParams.cbSize = sizeof(instParams);\r
-        if (!reboot &&\r
-            SetupDiGetDeviceInstallParams(devInfo, &devInfoData, &instParams) &&\r
-            ((instParams.Flags & (DI_NEEDRESTART|DI_NEEDREBOOT)) != 0))\r
-        {\r
-            reboot = TRUE;\r
-        }\r
-\r
-        result = FindNextDevice(devInfo, &devInfoData, &index);\r
-    } while (result == 0);\r
-\r
-    SetupDiDestroyDeviceInfoList(devInfo);\r
-\r
-  Cleanup1:\r
-    if ((result == 0) || (result == ERROR_NO_MORE_ITEMS))\r
-    {\r
-        wsprintf(resultBuf, "%d", reboot);\r
-        pushstring(resultBuf);\r
-        pushstring("00000000");\r
-    }\r
-    else\r
-    {\r
-        wsprintf(resultBuf, "%08X", result);\r
-        pushstring(resultBuf);\r
-    }\r
-}\r
-\r
-\r
-\r
-/*\r
- * InstDrv::StartSystemService serviceName\r
- *\r
- * Return:\r
- *  result      - Windows error code\r
- */\r
-void __declspec(dllexport) StartSystemService(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)\r
-{\r
-    SC_HANDLE       managerHndl;\r
-    SC_HANDLE       svcHndl;\r
-    SERVICE_STATUS  svcStatus;\r
-    DWORD           oldCheckPoint;\r
-    DWORD           result;\r
-    char            resultBuf[16];\r
-\r
-\r
-    EXDLL_INIT();\r
-    popstring(paramBuf);\r
-\r
-    managerHndl = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);\r
-    if (managerHndl == NULL)\r
-    {\r
-        result = GetLastError();\r
-        goto Cleanup1;\r
-    }\r
-\r
-    svcHndl = OpenService(managerHndl, paramBuf, SERVICE_START | SERVICE_QUERY_STATUS);\r
-    if (svcHndl == NULL)\r
-    {\r
-        result = GetLastError();\r
-        goto Cleanup2;\r
-    }\r
-\r
-    if (!StartService(svcHndl, 0, NULL) || !QueryServiceStatus(svcHndl, &svcStatus))\r
-    {\r
-        result = GetLastError();\r
-        goto Cleanup3;\r
-    }\r
-\r
-    while (svcStatus.dwCurrentState == SERVICE_START_PENDING)\r
-    {\r
-        oldCheckPoint = svcStatus.dwCheckPoint;\r
-\r
-        Sleep(svcStatus.dwWaitHint);\r
-\r
-        if (!QueryServiceStatus(svcHndl, &svcStatus))\r
-        {\r
-            result = GetLastError();\r
-            break;\r
-        }\r
-\r
-        if (oldCheckPoint >= svcStatus.dwCheckPoint)\r
-        {\r
-            if ((svcStatus.dwCurrentState == SERVICE_STOPPED) &&\r
-                (svcStatus.dwWin32ExitCode != 0))\r
-                result = svcStatus.dwWin32ExitCode;\r
-            else\r
-                result = ERROR_SERVICE_REQUEST_TIMEOUT;\r
-        }\r
-    }\r
-\r
-    if (svcStatus.dwCurrentState == SERVICE_RUNNING)\r
-        result = 0;\r
-\r
-  Cleanup3:\r
-    CloseServiceHandle(svcHndl);\r
-\r
-  Cleanup2:\r
-    CloseServiceHandle(managerHndl);\r
-\r
-  Cleanup1:\r
-    wsprintf(resultBuf, "%08X", result);\r
-    pushstring(resultBuf);\r
-}\r
-\r
-\r
-\r
-/*\r
- * InstDrv::StopSystemService serviceName\r
- *\r
- * Return:\r
- *  result      - Windows error code\r
- */\r
-void __declspec(dllexport) StopSystemService(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)\r
-{\r
-    SC_HANDLE       managerHndl;\r
-    SC_HANDLE       svcHndl;\r
-    SERVICE_STATUS  svcStatus;\r
-    DWORD           oldCheckPoint;\r
-    DWORD           result;\r
-    char            resultBuf[16];\r
-\r
-\r
-    EXDLL_INIT();\r
-    popstring(paramBuf);\r
-\r
-    managerHndl = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);\r
-    if (managerHndl == NULL)\r
-    {\r
-        result = GetLastError();\r
-        goto Cleanup1;\r
-    }\r
-\r
-    svcHndl = OpenService(managerHndl, paramBuf, SERVICE_STOP | SERVICE_QUERY_STATUS);\r
-    if (svcHndl == NULL)\r
-    {\r
-        result = GetLastError();\r
-        goto Cleanup2;\r
-    }\r
-\r
-    if (!ControlService(svcHndl, SERVICE_CONTROL_STOP, &svcStatus))\r
-    {\r
-        result = GetLastError();\r
-        goto Cleanup3;\r
-    }\r
-\r
-    while (svcStatus.dwCurrentState == SERVICE_STOP_PENDING)\r
-    {\r
-        oldCheckPoint = svcStatus.dwCheckPoint;\r
-\r
-        Sleep(svcStatus.dwWaitHint);\r
-\r
-        if (!QueryServiceStatus(svcHndl, &svcStatus))\r
-        {\r
-            result = GetLastError();\r
-            break;\r
-        }\r
-\r
-        if (oldCheckPoint >= svcStatus.dwCheckPoint)\r
-        {\r
-            result = ERROR_SERVICE_REQUEST_TIMEOUT;\r
-            break;\r
-        }\r
-    }\r
-\r
-    if (svcStatus.dwCurrentState == SERVICE_STOPPED)\r
-        result = 0;\r
-\r
-  Cleanup3:\r
-    CloseServiceHandle(svcHndl);\r
-\r
-  Cleanup2:\r
-    CloseServiceHandle(managerHndl);\r
-\r
-  Cleanup1:\r
-    wsprintf(resultBuf, "%08X", result);\r
-    pushstring(resultBuf);\r
-}\r
-\r
-\r
-\r
-BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)\r
-{\r
-    return TRUE;\r
-}\r
diff --git a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsp b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsp
deleted file mode 100644 (file)
index 874e66c..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-# Microsoft Developer Studio Project File - Name="InstDrv" - Package Owner=<4>\r
-# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
-# ** NICHT BEARBEITEN **\r
-\r
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102\r
-\r
-CFG=InstDrv - Win32 Debug\r
-!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE\r
-!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "InstDrv.mak".\r
-!MESSAGE \r
-!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben\r
-!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel:\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "InstDrv.mak" CFG="InstDrv - Win32 Debug"\r
-!MESSAGE \r
-!MESSAGE Für die Konfiguration stehen zur Auswahl:\r
-!MESSAGE \r
-!MESSAGE "InstDrv - Win32 Release" (basierend auf  "Win32 (x86) Dynamic-Link Library")\r
-!MESSAGE "InstDrv - Win32 Debug" (basierend auf  "Win32 (x86) Dynamic-Link Library")\r
-!MESSAGE \r
-\r
-# Begin Project\r
-# PROP AllowPerConfigDependencies 0\r
-# PROP Scc_ProjName ""\r
-# PROP Scc_LocalPath ""\r
-CPP=cl.exe\r
-MTL=midl.exe\r
-RSC=rc.exe\r
-\r
-!IF  "$(CFG)" == "InstDrv - Win32 Release"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 0\r
-# PROP BASE Output_Dir "Release"\r
-# PROP BASE Intermediate_Dir "Release"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 0\r
-# PROP Output_Dir "Release"\r
-# PROP Intermediate_Dir "Release"\r
-# PROP Ignore_Export_Lib 1\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INSTDRV_EXPORTS" /YX /FD /c\r
-# ADD CPP /nologo /MT /W3 /GX /O1 /I "C:\Programme\WINDDK\3790\inc\ddk\w2k" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INSTDRV_EXPORTS" /FD /c\r
-# SUBTRACT CPP /YX\r
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
-# ADD BASE RSC /l 0x407 /d "NDEBUG"\r
-# ADD RSC /l 0x407 /d "NDEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LINK32=link.exe\r
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386\r
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib shell32.lib setupapi.lib newdev.lib /nologo /entry:"_DllMainCRTStartup" /dll /machine:I386 /nodefaultlib /out:"../../Plugins/InstDrv.dll" /libpath:"C:\Programme\WINDDK\3790\lib\w2k\i386" /opt:nowin98\r
-# SUBTRACT LINK32 /pdb:none\r
-\r
-!ELSEIF  "$(CFG)" == "InstDrv - Win32 Debug"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 1\r
-# PROP BASE Output_Dir "Debug"\r
-# PROP BASE Intermediate_Dir "Debug"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 1\r
-# PROP Output_Dir "Debug"\r
-# PROP Intermediate_Dir "Debug"\r
-# PROP Ignore_Export_Lib 0\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INSTDRV_EXPORTS" /YX /FD /GZ  /c\r
-# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INSTDRV_EXPORTS" /YX /FD /GZ  /c\r
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
-# ADD BASE RSC /l 0x407 /d "_DEBUG"\r
-# ADD RSC /l 0x407 /d "_DEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LINK32=link.exe\r
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept\r
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"_DllMainCRTStartup" /dll /debug /machine:I386 /pdbtype:sept\r
-# SUBTRACT LINK32 /nodefaultlib\r
-\r
-!ENDIF \r
-\r
-# Begin Target\r
-\r
-# Name "InstDrv - Win32 Release"\r
-# Name "InstDrv - Win32 Debug"\r
-# Begin Group "Quellcodedateien"\r
-\r
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
-# Begin Source File\r
-\r
-SOURCE=.\InstDrv.c\r
-# End Source File\r
-# End Group\r
-# Begin Group "Header-Dateien"\r
-\r
-# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
-# End Group\r
-# Begin Group "Ressourcendateien"\r
-\r
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"\r
-# End Group\r
-# End Target\r
-# End Project\r
diff --git a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsw b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsw
deleted file mode 100644 (file)
index b3d02f0..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-Microsoft Developer Studio Workspace File, Format Version 6.00\r
-# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELÖSCHT WERDEN!\r
-\r
-###############################################################################\r
-\r
-Project: "InstDrv"=.\InstDrv.dsp - Package Owner=<4>\r
-\r
-Package=<5>\r
-{{{\r
-}}}\r
-\r
-Package=<4>\r
-{{{\r
-}}}\r
-\r
-###############################################################################\r
-\r
-Global:\r
-\r
-Package=<5>\r
-{{{\r
-}}}\r
-\r
-Package=<3>\r
-{{{\r
-}}}\r
-\r
-###############################################################################\r
-\r
diff --git a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/Readme.txt b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/Readme.txt
deleted file mode 100644 (file)
index e5877aa..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-InstDrv.dll version 0.2 - Installs or Removes Device Drivers\r
-------------------------------------------------------------\r
-\r
-\r
-The plugin helps you to create NSIS scripts for installing device drivers or\r
-removing them again. It can count installed device instances, create new ones\r
-or delete all supported device. InstDrv works on Windows 2000 or later.\r
-\r
-\r
-\r
-InstDrv::InitDriverSetup devClass drvHWID\r
-Return: result\r
-\r
-To start processing a driver, first call this function. devClass is the GUID\r
-of the device class the driver supports, drvHWID is the device hardware ID. If\r
-you don't know what these terms mean, you may want to take a look at the\r
-Windows DDK. This function returns an empty string on success, otherwise an\r
-error message.\r
-\r
-InitDriverSetup has to be called every time after the plugin dll has been\r
-(re-)loaded, or if you want to switch to a different driver.\r
-\r
-\r
-\r
-InstDrv::CountDevices\r
-Return: number\r
-\r
-This call returns the number of installed and supported devices of the driver.\r
-\r
-\r
-\r
-InstDrv::CreateDevice\r
-Return: result\r
-\r
-To create a new deviced node which the driver has to support, use this\r
-function. You may even call it multiple times for more than one instance. The\r
-return value is the Windows error code (in hex). Use CreateDevice before\r
-installing or updating the driver itself.\r
-\r
-\r
-\r
-InstDrv::InstallDriver infPath\r
-Return: result\r
-        reboot\r
-\r
-InstallDriver installs or updates a device driver as specified in the .inf\r
-setup script. It returns a Windows error code (in hex) and, on success, a flag\r
-signalling if a system reboot is required.\r
-\r
-\r
-\r
-InstDrv::DeleteOemInfFiles\r
-Return: result\r
-        oeminf\r
-        oempnf\r
-\r
-DeleteOemInfFiles tries to clean up the Windows inf directory by deleting the\r
-oemXX.inf and oemXX.pnf files associated with the drivers. It returns a\r
-Windows error code (in hex) and, on success, the names of the deleted files.\r
-This functions requires that at least one device instance is still present.\r
-So, call it before you remove the devices itself. You should also call it\r
-before updating a driver. This avoids that the inf directory gets slowly\r
-messed up with useless old setup scripts (which does NOT really accelerate\r
-Windows). The error code which comes up when no device is installed is\r
-"00000103".\r
-\r
-\r
-\r
-InstDrv::RemoveAllDevices\r
-Return: result\r
-        reboot\r
-\r
-This functions deletes all devices instances the driver supported. It returns\r
-a Windows error code (in hex) and, on success, a flag signalling if the system\r
-needs to be rebooted. You additionally have to remove the driver binaries from\r
-the system paths.\r
-\r
-\r
-\r
-InstDrv::StartSystemService serviceName\r
-Return: result\r
-\r
-Call this function to start the provided system service. The function blocks\r
-until the service is started or the system reported a timeout. The return value\r
-is the Windows error code (in hex).\r
-\r
-\r
-\r
-InstDrv::StopSystemService serviceName\r
-Return: result\r
-\r
-This function tries to stop the provided system service. It blocks until the\r
-service has been shut down or the system reported a timeout. The return value\r
-is the Windows error code (in hex).\r
-\r
-\r
-\r
-Example.nsi\r
-\r
-The example script installs or removes the virtual COM port driver of IrCOMM2k\r
-(2.0.0-alpha8, see www.ircomm2k.de/english). The driver and its setup script\r
-are only included for demonstration purposes, they do not work without the\r
-rest of IrCOMM2k (but they also do not cause any harm).\r
-\r
-\r
-\r
-Building the Source Code\r
-\r
-To build the plugin from the source code, some include files and libraries\r
-which come with the Windows DDK are required.\r
-\r
-\r
-\r
-History\r
-\r
- 0.2    - fixed bug when calling InitDriverSetup the second time\r
-        - added StartSystemService and StopSystemService\r
-\r
- 0.1    - first release\r
-\r
-\r
-\r
-License\r
-\r
-Copyright © 2003 Jan Kiszka (Jan.Kiszka@web.de)\r
-\r
-This software is provided 'as-is', without any express or implied\r
-warranty. In no event will the authors be held liable for any damages\r
-arising from the use of this software.\r
-\r
-Permission is granted to anyone to use this software for any purpose,\r
-including commercial applications, and to alter it and redistribute\r
-it freely, subject to the following restrictions:\r
-\r
-1. The origin of this software must not be misrepresented; \r
-   you must not claim that you wrote the original software.\r
-   If you use this software in a product, an acknowledgment in the\r
-   product documentation would be appreciated but is not required.\r
-2. Altered versions must be plainly marked as such,\r
-   and must not be misrepresented as being the original software.\r
-3. This notice may not be removed or altered from any distribution.\r
diff --git a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.inf b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.inf
deleted file mode 100644 (file)
index ccda1d8..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-; IrCOMM2k.inf\r
-;\r
-; Installation file for the Virtual Infrared-COM-Port\r
-;\r
-; (c) Copyright 2001, 2002 Jan Kiszka \r
-;\r
-\r
-[Version]\r
-Signature="$Windows NT$"\r
-Provider=%JK%\r
-Class=Ports\r
-ClassGUID={4d36e978-e325-11ce-bfc1-08002be10318}\r
-;DriverVer=03/26/2002,1.2.1.0\r
-\r
-[DestinationDirs]\r
-IrCOMM2k.Copy2Drivers  = 12\r
-IrCOMM2k.Copy2Winnt    = 10\r
-IrCOMM2k.Copy2System32 = 11\r
-IrCOMM2k.Copy2Help     = 18\r
-\r
-\r
-;\r
-; Driver information\r
-;\r
-\r
-[Manufacturer]\r
-%JK%   = JK.Mfg\r
-\r
-[JK.Mfg]\r
-%JK.DeviceDescIrCOMM% = IrCOMM2k_inst,IrCOMM2k\r
-\r
-\r
-;\r
-; General installation section\r
-;\r
-\r
-[IrCOMM2k_inst]\r
-CopyFiles = IrCOMM2k.Copy2Drivers ;,IrCOMM2k.Copy2System32,IrCOMM2k.Copy2Help,IrCOMM2k.Copy2Winnt\r
-;AddReg    = IrCOMM2k_inst_AddReg\r
-\r
-\r
-;\r
-; File sections\r
-;\r
-\r
-[IrCOMM2k.Copy2Drivers]\r
-ircomm2k.sys,,,2\r
-\r
-;[IrCOMM2k.Copy2System32]\r
-;ircomm2k.exe,,,2\r
-;ircomm2k.dll,,,2\r
-\r
-;[IrCOMM2k.Copy2Help]\r
-;ircomm2k.hlp,,,2\r
-\r
-;[IrCOMM2k.Copy2Winnt]\r
-;IrCOMM2k-Setup.exe,Setup.exe,,2\r
-\r
-\r
-;\r
-; Service Installation\r
-;\r
-\r
-[IrCOMM2k_inst.Services]\r
-AddService = IrCOMM2k,0x00000002,IrCOMM2k_DriverService_Inst,IrCOMM2k_DriverEventLog_Inst\r
-;AddService = IrCOMM2kSvc,,IrCOMM2k_Service_Inst\r
-\r
-[IrCOMM2k_DriverService_Inst]\r
-DisplayName    = %IrCOMM2k.DrvName%\r
-ServiceType    = 1                  ; SERVICE_KERNEL_DRIVER\r
-StartType      = 3                  ; SERVICE_DEMAND_START\r
-ErrorControl   = 0                  ; SERVICE_ERROR_IGNORE\r
-ServiceBinary  = %12%\ircomm2k.sys\r
-\r
-;[IrCOMM2k_Service_Inst]\r
-;DisplayName    = %IrCOMM2k.SvcName%\r
-;Description    = %IrCOMM2k.SvcDesc%\r
-;ServiceType    = 0x00000120         ; SERVICE_WIN32_SHARE_PROCESS, SERVICE_INTERACTIVE_PROCESS\r
-;StartType      = 2                  ; SERVICE_AUTO_START\r
-;ErrorControl   = 0                  ; SERVICE_ERROR_IGNORE\r
-;ServiceBinary  = %11%\ircomm2k.exe\r
-;Dependencies   = IrCOMM2k\r
-;AddReg         = IrCOMM2kSvcAddReg\r
-\r
-\r
-[IrCOMM2k_inst.nt.HW]\r
-AddReg=IrCOMM2kHwAddReg\r
-\r
-[IrCOMM2kHwAddReg]\r
-HKR,,PortSubClass,REG_BINARY,0x00000001\r
-;HKR,,TimeoutScaling,REG_DWORD,0x00000001\r
-;HKR,,StatusLines,REG_DWORD,0x00000000\r
-\r
-;[IrCOMM2k_inst_AddReg]\r
-;HKR,,EnumPropPages32,,"ircomm2k.dll,IrCOMM2kPropPageProvider"\r
-;HKLM,%UNINSTALL_KEY%,DisplayIcon,0x00020000,"%windir%\IrCOMM2k-Setup.exe"\r
-;HKLM,%UNINSTALL_KEY%,DisplayName,,"IrCOMM2k 1.2.1 "\r
-;HKLM,%UNINSTALL_KEY%,DisplayVersion,,"1.2.1"\r
-;HKLM,%UNINSTALL_KEY%,HelpLink,,"http://www.ircomm2k.de"\r
-;HKLM,%UNINSTALL_KEY%,Publisher,,%JK%\r
-;HKLM,%UNINSTALL_KEY%,UninstallString,0x00020000,"%windir%\IrCOMM2k-Setup.exe"\r
-\r
-;[IrCOMM2kSvcAddReg]\r
-;HKR,Parameters,ActiveConnectOnly,REG_DWORD,0x00000000\r
-\r
-\r
-[IrCOMM2k_DriverEventLog_Inst]\r
-AddReg = IrCOMM2k_DriverEventLog_AddReg\r
-\r
-[IrCOMM2k_DriverEventLog_AddReg]\r
-HKR,,EventMessageFile,REG_EXPAND_SZ,"%SystemRoot%\System32\IoLogMsg.dll;%SystemRoot%\System32\drivers\ircomm2k.sys"\r
-HKR,,TypesSupported,REG_DWORD,7\r
-\r
-\r
-[Strings]\r
-\r
-;\r
-; Non-Localizable Strings\r
-;\r
-\r
-REG_SZ         = 0x00000000\r
-REG_MULTI_SZ   = 0x00010000\r
-REG_EXPAND_SZ  = 0x00020000\r
-REG_BINARY     = 0x00000001\r
-REG_DWORD      = 0x00010001\r
-SERVICEROOT    = "System\CurrentControlSet\Services"\r
-UNINSTALL_KEY  = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\IrCOMM2k"\r
-\r
-;\r
-; Localizable Strings\r
-;\r
-\r
-JK                  = "Jan Kiszka"\r
-JK.DeviceDescIrCOMM = "Virtueller Infrarot-Kommunikationsanschluss"\r
-IrCOMM2k.DrvName    = "Virtueller Infrarot-Kommunikationsanschluss"\r
-;IrCOMM2k.SvcName    = "Virtueller Infrarot-Kommunikationsanschluß, Dienstprogramm"\r
-;IrCOMM2k.SvcDesc    = "Bildet über Infarot einen Kommunikationsanschluß nach."\r
diff --git a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.sys b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.sys
deleted file mode 100644 (file)
index 7882583..0000000
Binary files a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.sys and /dev/null differ
diff --git a/ao-tools/altosui/Instdrv/NSIS/Plugins/InstDrv.dll b/ao-tools/altosui/Instdrv/NSIS/Plugins/InstDrv.dll
deleted file mode 100644 (file)
index 482e955..0000000
Binary files a/ao-tools/altosui/Instdrv/NSIS/Plugins/InstDrv.dll and /dev/null differ
diff --git a/ao-tools/altosui/Makefile-standalone b/ao-tools/altosui/Makefile-standalone
deleted file mode 100644 (file)
index a95a5aa..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-.SUFFIXES: .java .class
-
-CLASSPATH=classes:./*:/usr/share/java/*
-CLASSFILES=\
-       Altos.class \
-       AltosChannelMenu.class \
-       AltosConfig.class \
-       AltosConfigUI.class \
-       AltosConvert.class \
-       AltosCRCException.class \
-       AltosCSV.class \
-       AltosCSVUI.class \
-       AltosDebug.class \
-       AltosEepromDownload.class \
-       AltosEepromMonitor.class \
-       AltosEepromReader.class \
-       AltosEepromRecord.class \
-       AltosFile.class \
-       AltosFlash.class \
-       AltosFlashUI.class \
-       AltosFlightInfoTableModel.class \
-       AltosFlightStatusTableModel.class \
-       AltosGPS.class \
-       AltosGreatCircle.class \
-       AltosHexfile.class \
-       AltosLine.class \
-       AltosInfoTable.class \
-       AltosLog.class \
-       AltosLogfileChooser.class \
-       AltosParse.class \
-       AltosPreferences.class \
-       AltosReader.class \
-       AltosRecord.class \
-       AltosSerialMonitor.class \
-       AltosSerial.class \
-       AltosState.class \
-       AltosStatusTable.class \
-       AltosTelemetry.class \
-       AltosTelemetryReader.class \
-       AltosUI.class \
-       AltosDevice.class \
-       AltosDeviceDialog.class \
-       AltosRomconfig.class \
-       AltosRomconfigUI.class \
-       AltosVoice.class
-
-JAVA_ICON=../../icon/altus-metrum-16x16.jpg
-WINDOWS_ICON=../../icon/altus-metrum.ico
-
-# where altosui.jar gets installed
-ALTOSLIB=/usr/share/java
-
-# where freetts.jar is to be found
-FREETTSLIB=/usr/share/java
-
-# all of the freetts files
-FREETTSJAR= \
-       $(FREETTSLIB)/cmudict04.jar \
-       $(FREETTSLIB)/cmulex.jar \
-       $(FREETTSLIB)/cmu_time_awb.jar \
-       $(FREETTSLIB)/cmutimelex.jar \
-       $(FREETTSLIB)/cmu_us_kal.jar \
-       $(FREETTSLIB)/en_us.jar \
-       $(FREETTSLIB)/freetts.jar
-
-# The current hex files
-HEXLIB=../../src
-HEXFILES = \
-       $(HEXLIB)/telemetrum-v1.0.ihx \
-       $(HEXLIB)/teledongle-v0.2.ihx
-
-JAVAFLAGS=-Xlint:unchecked -Xlint:deprecation
-
-ALTOSUIJAR = altosui.jar
-FATJAR = fat/altosui.jar
-
-OS:=$(shell uname)
-
-LINUX_APP=altosui
-
-DARWIN_ZIP=Altos-Mac.zip
-
-WINDOWS_EXE=Altos-Windows.exe
-
-LINUX_TGZ=Altos-Linux.tgz
-
-all: altosui.jar $(LINUX_APP)
-fat: altosui.jar $(LINUX_APP) $(DARWIN_ZIP) $(WINDOWS_EXE) $(LINUX_TGZ)
-
-$(CLASSFILES):
-
-.java.class:
-       javac -encoding UTF8 -classpath "$(CLASSPATH)" $(JAVAFLAGS) $*.java
-
-altosui.jar: classes/images classes/altosui classes/libaltosJNI $(CLASSFILES) Manifest.txt
-       cd ./classes && jar cfm ../$@ altosui/Manifest.txt images/* altosui/*.class libaltosJNI/*.class
-
-Manifest.txt: Makefile $(CLASSFILES)
-       echo 'Main-Class: altosui.AltosUI' > $@
-       echo "Class-Path: $(FREETTSLIB)/freetts.jar" >> $@
-
-classes/altosui:
-       mkdir -p classes
-       ln -sf .. classes/altosui
-
-classes/libaltosJNI:
-       mkdir -p classes
-       ln -sf ../../libaltos/libaltosJNI classes/libaltosJNI
-
-classes/images:
-       mkdir -p classes/images
-       ln -sf ../../$(JAVA_ICON) classes/images
-
-altosui:
-       echo "#!/bin/sh" > $@
-       echo "exec java -Djava.library.path=/usr/lib/altos -jar /usr/share/java/altosui.jar" >> $@
-       chmod +x ./altosui
-
-fat/altosui:
-       echo "#!/bin/sh" > $@
-       echo 'ME=`which "$0"`' >> $@
-       echo 'DIR=`dirname "$ME"`' >> $@
-       echo 'exec java -Djava.library.path="$$DIR" -jar "$$DIR"/altosui.jar' >> $@
-       chmod +x $@
-
-fat/altosui.jar: $(CLASSFILES) $(JAVA_ICON) fat/classes/Manifest.txt
-       mkdir -p fat/classes
-       test -L fat/classes/altosui || ln -sf ../.. fat/classes/altosui
-       mkdir -p fat/classes/images
-       cp $(JAVA_ICON) fat/classes/images
-       test -L fat/classes/libaltosJNI || ln -sf ../../../libaltos/libaltosJNI fat/classes/libaltosJNI
-       cd ./fat/classes && jar cfm ../../$@ Manifest.txt images/* altosui/*.class libaltosJNI/*.class
-
-fat/classes/Manifest.txt: $(CLASSFILES) Makefile
-       mkdir -p fat/classes
-       echo 'Main-Class: altosui.AltosUI' > $@
-       echo "Class-Path: freetts.jar" >> $@
-
-install: altosui.jar altosui
-       install -m 0644 altosui.jar $(DESTDIR)/usr/share/java/altosui.jar
-       install -m 0644 altosui.1 $(DESTDIR)/usr/share/man/man1/altosui.1
-       install altosui $(DESTDIR)/usr/bin/altosui
-
-clean:
-       rm -f *.class altosui.jar
-       rm -f AltosUI.app/Contents/Resources/Java/*
-       rm -rf classes
-       rm -rf windows linux
-
-distclean:     clean
-       rm -f $(DARWIN_ZIP) $(WINDOWS_EXE) $(LINUX_TGZ)
-       rm -rf darwin fat
-
-FAT_FILES=$(FATJAR) $(FREETTSJAR) $(HEXFILES)
-
-LINUX_FILES=$(FAT_FILES) ../libaltos/libaltos.so fat/altosui
-$(LINUX_TGZ): $(LINUX_FILES)
-       rm -f $@
-       mkdir -p linux/AltOS
-       rm -f linux/AltOS/*
-       cp $(LINUX_FILES) linux/AltOS
-       cd linux && tar czf ../$@ AltOS
-
-DARWIN_RESOURCES=$(FATJAR) $(FREETTSJAR) ../libaltos/libaltos.dylib
-DARWIN_EXTRA=$(HEXFILES)
-DARWIN_FILES=$(DARWIN_RESOURCES) $(DARWIN_EXTRA)
-
-$(DARWIN_ZIP): $(DARWIN_FILES)
-       rm -f $@
-       cp -a AltosUI.app darwin/
-       mkdir -p darwin/AltosUI.app/Contents/Resources/Java
-       cp $(DARWIN_RESOURCES) darwin/AltosUI.app/Contents/Resources/Java
-       mkdir -p darwin/AltOS
-       cp $(DARWIN_EXTRA) darwin/AltOS
-       cd darwin && zip -r ../$@ AltosUI.app AltOS
-
-WINDOWS_FILES = $(FAT_FILES) ../libaltos/altos.dll ../../telemetrum.inf $(WINDOWS_ICON)
-
-$(WINDOWS_EXE): $(WINDOWS_FILES) altos-windows.nsi
-       rm -f $@
-       mkdir -p windows/AltOS
-       rm -f windows/AltOS/*
-       cp $(WINDOWS_FILES) windows/AltOS
-       makensis altos-windows.nsi
diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am
deleted file mode 100644 (file)
index 93a43b1..0000000
+++ /dev/null
@@ -1,271 +0,0 @@
-JAVAROOT=classes
-AM_JAVACFLAGS=-encoding UTF-8
-
-man_MANS=altosui.1
-
-altoslibdir=$(libdir)/altos
-
-CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:../libaltos:$(FREETTS)/*:/usr/share/java/*"
-
-bin_SCRIPTS=altosui
-
-altosui_JAVA = \
-       GrabNDrag.java \
-       AltosAscent.java \
-       AltosChannelMenu.java \
-       AltosConfig.java \
-       AltosConfigUI.java \
-       AltosConfigureUI.java \
-       AltosConvert.java \
-       AltosCRCException.java \
-       AltosCSV.java \
-       AltosCSVUI.java \
-       AltosDebug.java \
-       AltosDescent.java \
-       AltosDeviceDialog.java \
-       AltosDevice.java \
-       AltosDisplayThread.java \
-       AltosEepromDownload.java \
-       AltosEepromMonitor.java \
-       AltosEepromIterable.java \
-       AltosEepromRecord.java \
-       AltosFile.java \
-       AltosFlash.java \
-       AltosFlashUI.java \
-       AltosFlightDisplay.java \
-       AltosFlightInfoTableModel.java \
-       AltosFlightReader.java \
-       AltosFlightStatus.java \
-       AltosFlightUI.java \
-       AltosGPS.java \
-       AltosGreatCircle.java \
-       AltosHexfile.java \
-       Altos.java \
-       AltosIgnite.java \
-       AltosIgniteUI.java \
-       AltosInfoTable.java \
-       AltosKML.java \
-       AltosLanded.java \
-       AltosLed.java \
-       AltosLights.java \
-       AltosLine.java \
-       AltosLog.java \
-       AltosPad.java \
-       AltosParse.java \
-       AltosPreferences.java \
-       AltosReader.java \
-       AltosRecord.java \
-       AltosRecordIterable.java \
-       AltosTelemetryReader.java \
-       AltosReplayReader.java \
-       AltosRomconfig.java \
-       AltosRomconfigUI.java \
-       AltosSerial.java \
-       AltosSerialInUseException.java \
-       AltosSerialMonitor.java \
-       AltosSiteMap.java \
-       AltosSiteMapCache.java \
-       AltosSiteMapTile.java \
-       AltosState.java \
-       AltosTelemetry.java \
-       AltosTelemetryIterable.java \
-       AltosUI.java \
-       AltosWriter.java \
-       AltosDataPointReader.java \
-       AltosDataPoint.java \
-       AltosGraph.java \
-       AltosGraphTime.java \
-       AltosGraphUI.java \
-       AltosDataChooser.java \
-       AltosVoice.java
-
-JFREECHART_CLASS= \
-    jfreechart.jar
-
-JCOMMON_CLASS=\
-    jcommon.jar
-
-FREETTS_CLASS= \
-       cmudict04.jar \
-       cmulex.jar \
-       cmu_time_awb.jar \
-       cmutimelex.jar \
-       cmu_us_kal.jar \
-       en_us.jar \
-       freetts.jar
-
-LIBALTOS= \
-       libaltos.so \
-       libaltos.dylib \
-       altos.dll
-
-JAR=altosui.jar
-
-FATJAR=altosui-fat.jar
-
-# Icons
-ICONDIR=$(top_srcdir)/icon
-
-JAVA_ICON=$(ICONDIR)/altus-metrum-16x16.jpg
-
-ICONS= $(ICONDIR)/redled.png $(ICONDIR)/redoff.png \
-       $(ICONDIR)/greenled.png $(ICONDIR)/greenoff.png \
-       $(ICONDIR)/grayled.png $(ICONDIR)/grayoff.png
-
-# icon base names for jar
-ICONJAR= -C $(ICONDIR) altus-metrum-16x16.jpg \
-       -C $(ICONDIR) redled.png -C $(ICONDIR) redoff.png \
-       -C $(ICONDIR) greenled.png -C $(ICONDIR) greenoff.png \
-       -C $(ICONDIR) grayon.png -C $(ICONDIR) grayled.png
-
-WINDOWS_ICON=$(ICONDIR)/altus-metrum.ico
-
-# Firmware
-FIRMWARE_TD=$(top_srcdir)/src/teledongle-v0.2-$(VERSION).ihx
-FIRMWARE_TM=$(top_srcdir)/src/telemetrum-v1.0-$(VERSION).ihx
-FIRMWARE=$(FIRMWARE_TM) $(FIRMWARE_TD)
-
-# Distribution targets
-LINUX_DIST=Altos-Linux-$(VERSION).tar.bz2
-MACOSX_DIST=Altos-Mac-$(VERSION).zip
-WINDOWS_DIST=Altos-Windows-$(VERSION_DASH).exe
-
-FAT_FILES=$(FATJAR) $(FREETTS_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS)
-
-LINUX_FILES=$(FAT_FILES) libaltos.so $(FIRMWARE)
-LINUX_EXTRA=altosui-fat
-
-MACOSX_FILES=$(FAT_FILES) libaltos.dylib
-MACOSX_EXTRA=$(FIRMWARE)
-
-WINDOWS_FILES=$(FAT_FILES) altos.dll $(top_srcdir)/telemetrum.inf $(WINDOWS_ICON)
-
-all-local: classes/altosui $(JAR) altosui altosui-test altosui-jdb
-
-clean-local:
-       -rm -rf classes $(JAR) $(FATJAR) \
-               $(LINUX_DIST) $(MACOSX_DIST) windows $(WINDOWS_DIST) $(FREETTS_CLASS) \
-               $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) Manifest.txt Manifest-fat.txt altos-windows.log \
-               altosui altosui-test altosui-jdb macosx linux
-
-if FATINSTALL
-
-FATTARGET=$(FATDIR)/$(VERSION)
-
-LINUX_DIST_TARGET=$(FATTARGET)/$(LINUX_DIST)
-MACOSX_DIST_TARGET=$(FATTARGET)/$(MACOSX_DIST)
-WINDOWS_DIST_TARGET=$(FATTARGET)/$(WINDOWS_DIST)
-
-fat: $(LINUX_DIST_TARGET) $(MACOSX_DIST_TARGET) $(WINDOWS_DIST_TARGET)
-
-$(LINUX_DIST_TARGET): $(LINUX_DIST)
-       mkdir -p $(FATTARGET)
-       cp -p $< $@
-
-$(MACOSX_DIST_TARGET): $(MACOSX_DIST)
-       mkdir -p $(FATTARGET)
-       cp -p $< $@
-
-$(WINDOWS_DIST_TARGET): $(WINDOWS_DIST)
-       mkdir -p $(FATTARGET)
-       cp -p $< $@
-
-else
-fat: $(LINUX_DIST) $(MACOSX_DIST) $(WINDOWS_DIST)
-endif
-
-
-altosuidir=$(datadir)/java
-
-install-altosuiJAVA: altosui.jar
-       @$(NORMAL_INSTALL)
-       test -z "$(altosuidir)" || $(MKDIR_P) "$(DESTDIR)$(altosuidir)"
-       echo " $(INSTALL_DATA)" "$<" "'$(DESTDIR)$(altosuidir)/altosui.jar'"; \
-       $(INSTALL_DATA) "$<" "$(DESTDIR)$(altosuidir)"
-
-classes/altosui:
-       mkdir -p classes/altosui
-
-$(JAR): classaltosui.stamp Manifest.txt $(JAVA_ICON)
-       jar cfm $@ Manifest.txt \
-               $(ICONJAR) \
-               -C classes altosui \
-               -C ../libaltos libaltosJNI
-
-$(FATJAR): classaltosui.stamp Manifest-fat.txt $(FREETTS_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) $(JAVA_ICON)
-       jar cfm $@ Manifest-fat.txt \
-               $(ICONJAR) \
-               -C classes altosui \
-               -C ../libaltos libaltosJNI
-
-Manifest.txt: Makefile
-       echo 'Main-Class: altosui.AltosUI' > $@
-       echo "Class-Path: $(FREETTS)/freetts.jar $(JFREECHART)/jfreechart.jar $(JCOMMON)/jcommon.jar" >> $@
-
-Manifest-fat.txt:
-       echo 'Main-Class: altosui.AltosUI' > $@
-       echo "Class-Path: freetts.jar jfreechart.jar jcommon.jar" >> $@
-
-altosui: Makefile
-       echo "#!/bin/sh" > $@
-       echo 'exec java  -cp "$(FREETTS)/*:$(JFREECHART)/*:$(JCOMMON)/*" -Djava.library.path="$(altoslibdir)" -jar "$(altosuidir)/altosui.jar" "$$@"' >> $@
-       chmod +x $@
-
-altosui-test: Makefile
-       echo "#!/bin/sh" > $@
-       echo 'exec java -cp "$(FREETTS)/*:$(JFREECHART)/*:$(JCOMMON)/*" -Djava.library.path="../libaltos/.libs" -jar altosui.jar "$$@"' >> $@
-       chmod +x $@
-
-altosui-jdb: Makefile
-       echo "#!/bin/sh" > $@
-       echo 'exec jdb -classpath "classes:../libaltos:$(FREETTS)/*:$(JFREECHART)/*:$(JCOMMON)/*" -Djava.library.path="../libaltos/.libs" altosui/AltosUI "$$@"' >> $@
-       chmod +x $@
-
-libaltos.so:
-       -rm -f "$@"
-       $(LN_S) ../libaltos/.libs/"$@" .
-
-libaltos.dylib:
-       -rm -f "$@"
-       $(LN_S) ../libaltos/"$@" .
-
-altos.dll:
-       -rm -f "$@"
-       $(LN_S) ../libaltos/"$@" .
-
-$(FREETTS_CLASS):
-       -rm -f "$@"
-       $(LN_S) "$(FREETTS)"/"$@" .
-
-$(JFREECHART_CLASS):
-       -rm -f "$@"
-       $(LN_S) "$(JFREECHART)"/"$@" .
-
-$(JCOMMON_CLASS):
-       -rm -f "$@"
-       $(LN_S) "$(JCOMMON)"/"$@" .
-
-$(LINUX_DIST): $(LINUX_FILES) $(LINUX_EXTRA)
-       -rm -f $@
-       -rm -rf linux
-       mkdir -p linux/AltOS
-       cp -p $(LINUX_FILES) linux/AltOS
-       cp -p altosui-fat linux/AltOS/altosui
-       chmod +x linux/AltOS/altosui
-       tar cjf $@ -C linux AltOS
-
-$(MACOSX_DIST): $(MACOSX_FILES) $(MACOSX_EXTRA)
-       -rm -f $@
-       -rm -rf macosx
-       mkdir macosx
-       cp -a AltosUI.app macosx/
-       mkdir -p macosx/AltOS macosx/AltosUI.app/Contents/Resources/Java
-       cp -p $(FATJAR) macosx/AltosUI.app/Contents/Resources/Java/altosui.jar
-       cp -p $(FREETTS_CLASS) libaltos.dylib macosx/AltosUI.app/Contents/Resources/Java
-       cp -p $(JFREECHART_CLASS) libaltos.dylib macosx/AltosUI.app/Contents/Resources/Java
-       cp -p $(MACOSX_EXTRA) macosx/AltOS
-       cd macosx && zip -r ../$@ AltosUI.app AltOS
-
-$(WINDOWS_DIST): $(WINDOWS_FILES) altos-windows.nsi
-       -rm -f $@
-       makensis -Oaltos-windows.log "-XOutFile $@" "-DVERSION=$(VERSION)" altos-windows.nsi
diff --git a/ao-tools/altosui/altos-windows.nsi b/ao-tools/altosui/altos-windows.nsi
deleted file mode 100644 (file)
index 37777fd..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-!addplugindir Instdrv/NSIS/Plugins
-
-Name "Altus Metrum Installer"
-
-; Default install directory
-InstallDir "$PROGRAMFILES\AltusMetrum"
-
-; Tell the installer where to re-install a new version
-InstallDirRegKey HKLM "Software\AltusMetrum" "Install_Dir"
-
-LicenseText "GNU General Public License Version 2"
-LicenseData "../../COPYING"
-
-; Need admin privs for Vista or Win7
-RequestExecutionLevel admin
-
-ShowInstDetails Show
-
-ComponentText "Altus Metrum Software and Driver Installer"
-
-; Pages to present
-
-Page license
-Page components
-Page directory
-Page instfiles
-
-UninstPage uninstConfirm
-UninstPage instfiles
-
-; And the stuff to install
-
-Section "Install Driver" InstDriver
-       InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} "Altus Metrum"
-       Pop $0
-       DetailPrint "InitDriverSetup: $0"
-
-       InstDrv::DeleteOemInfFiles /NOUNLOAD
-       InstDrv::CreateDevice /NOUNLOAD
-       SetOutPath $TEMP
-       File "../../telemetrum.inf"
-       InstDrv::InstallDriver /NOUNLOAD "$TEMP\telemetrum.inf"
-
-       SetOutPath $INSTDIR
-       File "../../telemetrum.inf"
-SectionEnd
-
-Section "AltosUI Application"
-       SetOutPath $INSTDIR
-
-       File "altosui-fat.jar"
-       File "cmudict04.jar"
-       File "cmulex.jar"
-       File "cmu_time_awb.jar"
-       File "cmutimelex.jar"
-       File "cmu_us_kal.jar"
-       File "en_us.jar"
-       File "freetts.jar"
-
-       File "*.dll"
-
-       File "../../icon/*.ico"
-
-       CreateShortCut "$SMPROGRAMS\AltusMetrum.lnk" "$INSTDIR\altosui-fat.jar" "" "$INSTDIR\altus-metrum.ico"
-SectionEnd
-
-Section "AltosUI Desktop Shortcut"
-       CreateShortCut "$DESKTOP\AltusMetrum.lnk" "$INSTDIR\altosui-fat.jar"  "" "$INSTDIR\altus-metrum.ico"
-SectionEnd
-
-Section "TeleMetrum and TeleDongle Firmware"
-
-       SetOutPath $INSTDIR
-
-       File "../../src/telemetrum-v1.0/telemetrum-v1.0-${VERSION}.ihx"
-       File "../../src/teledongle-v0.2/teledongle-v0.2-${VERSION}.ihx"
-
-SectionEnd
-
-Section "Uninstaller"
-
-       ; Deal with the uninstaller
-       
-       SetOutPath $INSTDIR
-
-       ; Write the install path to the registry
-       WriteRegStr HKLM SOFTWARE\AltusMetrum "Install_Dir" "$INSTDIR"
-       
-       ; Write the uninstall keys for windows
-       WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "DisplayName" "Altus Metrum"
-       WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "UninstallString" '"$INSTDIR\uninstall.exe"'
-       WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "NoModify" "1"
-       WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum" "NoRepair" "1"
-
-       WriteUninstaller "uninstall.exe"
-SectionEnd
-
-Section "Uninstall"
-       DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\AltusMetrum"
-       DeleteRegKey HKLM "Software\AltusMetrum"
-
-       Delete "$INSTDIR\*.*"
-       RMDir "$INSTDIR"
-
-       ; Remove devices
-       InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} "Altus Metrum"
-       InstDrv::DeleteOemInfFiles /NOUNLOAD
-       InstDrv::RemoveAllDevices
-
-       ; Remove shortcuts, if any
-       Delete "$SMPROGRAMS\AltusMetrum.lnk"
-       Delete "$DESKTOP\AltusMetrum.lnk"
-SectionEnd
diff --git a/ao-tools/altosui/altosui-fat b/ao-tools/altosui/altosui-fat
deleted file mode 100755 (executable)
index 95b1c05..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/sh
-me=`which "$0"`
-dir=`dirname "$me"`
-exec java -cp "$dir/*" -Djava.library.path="$dir" -jar "$dir"/altosui-fat.jar  "$@"
diff --git a/ao-tools/altosui/altosui.1 b/ao-tools/altosui/altosui.1
deleted file mode 100644 (file)
index 57fa448..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-.\"
-.\" Copyright © 2010 Bdale Garbee <bdale@gag.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; either version 2 of the License, or
-.\" (at your option) any later version.
-.\"
-.\" 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.
-.\"
-.\"
-.TH ALTOSUI 1 "altosui" ""
-.SH NAME
-altosui \- Rocket flight monitor
-.SH SYNOPSIS
-.B "altosui"
-.SH DESCRIPTION
-.I altosui
-connects to a TeleDongle or TeleMetrum device through a USB serial device.
-It provides a menu-oriented
-user interface to monitor, record and review rocket flight data.
-.SH USAGE
-When connected to a TeleDongle device, altosui turns on the radio
-receiver and listens for telemetry packets. It displays the received
-telemetry data, and reports flight status via voice synthesis. All
-received telemetry information is recorded to a file.
-.P
-When connected to a TeleMetrum device, altosui can be used to configure the
-TeleMetrum, and to downloads the eeprom data and store it in a file.
-.P
-A number of other menu options exist, including the ability to export flight
-data in different formats.
-.SH FILES
-All data log files are recorded into a user-specified directory
-(default ~/TeleMetrum). Files are named using the current date, the serial
-number of the reporting device, the flight number recorded in the data
-and either '.telem' for telemetry data or '.eeprom' for eeprom data.
-.SH AUTHOR
-Keith Packard
diff --git a/ao-tools/altosui/altusmetrum.jpg b/ao-tools/altosui/altusmetrum.jpg
deleted file mode 100644 (file)
index 0402792..0000000
Binary files a/ao-tools/altosui/altusmetrum.jpg and /dev/null differ
diff --git a/ao-tools/libaltos/.gitignore b/ao-tools/libaltos/.gitignore
deleted file mode 100644 (file)
index c490e6f..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-*.so
-*.lo
-*.la
-*.java
-*.class
-.libs/
-classlibaltos.stamp
-libaltos_wrap.c
-libaltosJNI
-cjnitest
-libaltos.swig
-swig_bindings/
diff --git a/ao-tools/libaltos/Makefile-standalone b/ao-tools/libaltos/Makefile-standalone
deleted file mode 100644 (file)
index 4e43805..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-OS:=$(shell uname)
-
-#
-# Linux
-#
-ifeq ($(OS),Linux)
-
-JAVA_CFLAGS=-I/usr/lib/jvm/java-6-openjdk/include
-
-OS_LIB_CFLAGS=-DLINUX -DPOSIX_TTY $(JAVA_CFLAGS)
-
-OS_APP_CFLAGS=$(OS_LIB_CFLAGS)
-
-OS_LDFLAGS=
-
-LIBNAME=libaltos.so
-EXEEXT=
-endif
-
-#
-# Darwin (Mac OS X)
-#
-ifeq ($(OS),Darwin)
-
-OS_LIB_CFLAGS=\
-       -DDARWIN -DPOSIX_TTY -arch i386 -arch x86_64 \
-       --sysroot=/Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.5 \
-       -iwithsysroot /System/Library/Frameworks/JavaVM.framework/Headers \
-       -iwithsysroot /System/Library/Frameworks/IOKit.framework/Headers \
-       -iwithsysroot /System/Library/Frameworks/CoreFoundation.framework/Headers
-OS_APP_CFLAGS=$(OS_LIB_CFLAGS)
-
-OS_LDFLAGS =\
-       -framework IOKit -framework CoreFoundation
-
-LIBNAME=libaltos.dylib
-EXEEXT=
-
-endif
-
-#
-# Windows
-#
-ifneq (,$(findstring MINGW,$(OS)))
-
-CC=gcc
-
-OS_LIB_CFLAGS = -DWINDOWS -mconsole -DBUILD_DLL
-OS_APP_CFLAGS = -DWINDOWS -mconsole
-
-OS_LDFLAGS = -lgdi32 -luser32 -lcfgmgr32 -lsetupapi -lole32 \
-       -ladvapi32 -lcomctl32 -mconsole -Wl,--add-stdcall-alias
-
-LIBNAME=altos.dll
-
-EXEEXT=.exe
-
-endif
-
-.SUFFIXES: .java .class
-
-CLASSPATH=".:jnitest/*:libaltosJNI:/usr/share/java/*"
-
-SWIG_DIR=swig_bindings/java
-SWIG_FILE=$(SWIG_DIR)/libaltos.swig
-SWIG_WRAP=$(SWIG_DIR)/libaltos_wrap.c
-
-JNI_DIR=libaltosJNI
-JNI_FILE=$(JNI_DIR)/libaltosJNI.java
-JNI_SRCS=$(JNI_FILE) \
-       $(JNI_DIR)/SWIGTYPE_p_altos_file.java \
-       $(JNI_DIR)/SWIGTYPE_p_altos_list.java \
-       $(JNI_DIR)/altos_device.java \
-       $(JNI_DIR)/libaltos.java
-
-JAVAFILES=\
-       $(JNI_SRCS)
-
-CLASSFILES = $(JAVAFILES:%.java=%.class)
-
-JAVAFLAGS=-Xlint:unchecked
-
-CJNITEST=cjnitest$(EXEEXT)
-
-all: $(LIBNAME) $(CJNITEST) $(CLASSFILES)
-
-.java.class:
-       javac -encoding UTF8 -classpath "$(CLASSPATH)" $(JAVAFLAGS) $*.java
-
-CFLAGS=$(OS_LIB_CFLAGS) -O -I.
-
-LDFLAGS=$(OS_LDFLAGS)
-
-HEADERS=libaltos.h
-SRCS = libaltos.c $(SWIG_WRAP)
-OBJS = $(SRCS:%.c=%.o)
-LIBS = $(DARWIN_LIBS)
-
-$(CJNITEST): cjnitest.c $(LIBNAME)
-       $(CC) -o $@ $(OS_APP_CFLAGS) cjnitest.c $(LIBNAME) $(LIBS) $(LDFLAGS)
-
-$(LIBNAME): $(OBJS)
-       $(CC) -shared $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(LDFLAGS)
-
-clean:
-       rm -f $(CLASSFILES) $(OBJS) $(LIBNAME) $(CJNITEST) cjnitest.o
-       rm -rf swig_bindings libaltosJNI
-
-distclean:     clean
-
-$(JNI_FILE): libaltos.i0 $(HEADERS)
-       mkdir -p $(SWIG_DIR)
-       mkdir -p libaltosJNI
-       sed 's;//%;%;' libaltos.i0 $(HEADERS) > $(SWIG_FILE)
-       swig -java -package libaltosJNI $(SWIG_FILE)
-       cp swig_bindings/java/*.java libaltosJNI
-
-$(SWIG_WRAP): $(JNI_FILE)
-
-ifeq ($(OS),Linux)
-install:       $(LIBNAME)
-       install -c $(LIBNAME) $(DESTDIR)/usr/lib/altos/$(LIBNAME)
-
-endif
-
-.NOTPARALLEL:
diff --git a/ao-tools/libaltos/Makefile.am b/ao-tools/libaltos/Makefile.am
deleted file mode 100644 (file)
index 388d210..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-JAVAC=javac
-AM_CFLAGS=-DLINUX -DPOSIX_TTY -I$(JVM_INCLUDE)
-AM_JAVACFLAGS=-encoding UTF-8
-
-altoslibdir=$(libdir)/altos
-
-altoslib_LTLIBRARIES=libaltos.la
-
-libaltos_la_LDFLAGS = -version-info 1:0:1
-
-libaltos_la_SOURCES=\
-       libaltos.c \
-       libaltos_wrap.c
-
-noinst_PROGRAMS=cjnitest
-
-cjnitest_LDADD=libaltos.la
-
-LIBS=
-
-HFILES=libaltos.h
-
-SWIG_FILE=libaltos.swig
-
-CLASSDIR=libaltosJNI
-
-$(SWIG_FILE): libaltos.i0 $(HFILES)
-       sed 's;//%;%;' libaltos.i0 $(HFILES) > $(SWIG_FILE)
-
-all-local: classlibaltos.stamp
-
-libaltos_wrap.c: classlibaltos.stamp
-
-classlibaltos.stamp: $(SWIG_FILE)
-       swig -java -package libaltosJNI $(SWIG_FILE)
-       mkdir -p libaltosJNI
-       $(JAVAC) -d . $(AM_JAVACFLAGS) $(JAVACFLAGS) *.java && \
-       touch classlibaltos.stamp
-
-clean-local:
-       -rm -rf libaltosJNI *.class *.java classlibaltos.stamp $(SWIG_FILE) libaltos_wrap.c
diff --git a/ao-tools/libaltos/altos.dll b/ao-tools/libaltos/altos.dll
deleted file mode 100755 (executable)
index 28e9b4a..0000000
Binary files a/ao-tools/libaltos/altos.dll and /dev/null differ
diff --git a/ao-tools/libaltos/cjnitest.c b/ao-tools/libaltos/cjnitest.c
deleted file mode 100644 (file)
index c6d6e06..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-#include <stdio.h>
-#include "libaltos.h"
-
-static void
-altos_puts(struct altos_file *file, char *string)
-{
-       char    c;
-
-       while ((c = *string++))
-               altos_putchar(file, c);
-}
-
-main ()
-{
-       struct altos_device     device;
-       struct altos_list       *list;
-
-       altos_init();
-       list = altos_list_start();
-       while (altos_list_next(list, &device)) {
-               struct altos_file       *file;
-               int                     c;
-
-               printf ("%04x:%04x %-20s %4d %s\n", device.vendor, device.product,
-                       device.name, device.serial, device.path);
-
-               file = altos_open(&device);
-               if (!file) {
-                       printf("altos_open failed\n");
-                       continue;
-               }
-               altos_puts(file,"v\nc s\n");
-               altos_flush(file);
-               while ((c = altos_getchar(file, 100)) >= 0) {
-                       putchar (c);
-               }
-               if (c != LIBALTOS_TIMEOUT)
-                       printf ("getchar returns %d\n", c);
-               altos_close(file);
-       }
-       altos_list_finish(list);
-       altos_fini();
-}
diff --git a/ao-tools/libaltos/libaltos.c b/ao-tools/libaltos/libaltos.c
deleted file mode 100644 (file)
index 465f0ac..0000000
+++ /dev/null
@@ -1,1028 +0,0 @@
-/*
- * 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.
- */
-
-#include "libaltos.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define USE_POLL
-
-PUBLIC int
-altos_init(void)
-{
-       return LIBALTOS_SUCCESS;
-}
-
-PUBLIC void
-altos_fini(void)
-{
-}
-
-#ifdef DARWIN
-
-#undef USE_POLL
-
-/* Mac OS X don't have strndup even if _GNU_SOURCE is defined */
-static char *
-altos_strndup (const char *s, size_t n)
-{
-    size_t len = strlen (s);
-    char *ret;
-
-    if (len <= n)
-       return strdup (s);
-    ret = malloc(n + 1);
-    strncpy(ret, s, n);
-    ret[n] = '\0';
-    return ret;
-}
-
-#else
-#define altos_strndup strndup
-#endif
-
-/*
- * Scan for Altus Metrum devices by looking through /sys
- */
-
-#ifdef LINUX
-
-#define _GNU_SOURCE
-#include <ctype.h>
-#include <dirent.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-static char *
-cc_fullname (char *dir, char *file)
-{
-       char    *new;
-       int     dlen = strlen (dir);
-       int     flen = strlen (file);
-       int     slen = 0;
-
-       if (dir[dlen-1] != '/')
-               slen = 1;
-       new = malloc (dlen + slen + flen + 1);
-       if (!new)
-               return 0;
-       strcpy(new, dir);
-       if (slen)
-               strcat (new, "/");
-       strcat(new, file);
-       return new;
-}
-
-static char *
-cc_basename(char *file)
-{
-       char *b;
-
-       b = strrchr(file, '/');
-       if (!b)
-               return file;
-       return b + 1;
-}
-
-static char *
-load_string(char *dir, char *file)
-{
-       char    *full = cc_fullname(dir, file);
-       char    line[4096];
-       char    *r;
-       FILE    *f;
-       int     rlen;
-
-       f = fopen(full, "r");
-       free(full);
-       if (!f)
-               return NULL;
-       r = fgets(line, sizeof (line), f);
-       fclose(f);
-       if (!r)
-               return NULL;
-       rlen = strlen(r);
-       if (r[rlen-1] == '\n')
-               r[rlen-1] = '\0';
-       return strdup(r);
-}
-
-static int
-load_hex(char *dir, char *file)
-{
-       char    *line;
-       char    *end;
-       long    i;
-
-       line = load_string(dir, file);
-       if (!line)
-               return -1;
-       i = strtol(line, &end, 16);
-       free(line);
-       if (end == line)
-               return -1;
-       return i;
-}
-
-static int
-load_dec(char *dir, char *file)
-{
-       char    *line;
-       char    *end;
-       long    i;
-
-       line = load_string(dir, file);
-       if (!line)
-               return -1;
-       i = strtol(line, &end, 10);
-       free(line);
-       if (end == line)
-               return -1;
-       return i;
-}
-
-static int
-dir_filter_tty_colon(const struct dirent *d)
-{
-       return strncmp(d->d_name, "tty:", 4) == 0;
-}
-
-static int
-dir_filter_tty(const struct dirent *d)
-{
-       return strncmp(d->d_name, "tty", 3) == 0;
-}
-
-struct altos_usbdev {
-       char    *sys;
-       char    *tty;
-       char    *manufacturer;
-       char    *product_name;
-       int     serial; /* AltOS always uses simple integer serial numbers */
-       int     idProduct;
-       int     idVendor;
-};
-
-static char *
-usb_tty(char *sys)
-{
-       char *base;
-       int num_configs;
-       int config;
-       struct dirent **namelist;
-       int interface;
-       int num_interfaces;
-       char endpoint_base[20];
-       char *endpoint_full;
-       char *tty_dir;
-       int ntty;
-       char *tty;
-
-       base = cc_basename(sys);
-       num_configs = load_hex(sys, "bNumConfigurations");
-       num_interfaces = load_hex(sys, "bNumInterfaces");
-       for (config = 1; config <= num_configs; config++) {
-               for (interface = 0; interface < num_interfaces; interface++) {
-                       sprintf(endpoint_base, "%s:%d.%d",
-                               base, config, interface);
-                       endpoint_full = cc_fullname(sys, endpoint_base);
-
-                       /* Check for tty:ttyACMx style names
-                        */
-                       ntty = scandir(endpoint_full, &namelist,
-                                      dir_filter_tty_colon,
-                                      alphasort);
-                       if (ntty > 0) {
-                               free(endpoint_full);
-                               tty = cc_fullname("/dev", namelist[0]->d_name + 4);
-                               free(namelist);
-                               return tty;
-                       }
-
-                       /* Check for tty/ttyACMx style names
-                        */
-                       tty_dir = cc_fullname(endpoint_full, "tty");
-                       free(endpoint_full);
-                       ntty = scandir(tty_dir, &namelist,
-                                      dir_filter_tty,
-                                      alphasort);
-                       free (tty_dir);
-                       if (ntty > 0) {
-                               tty = cc_fullname("/dev", namelist[0]->d_name);
-                               free(namelist);
-                               return tty;
-                       }
-               }
-       }
-       return NULL;
-}
-
-static struct altos_usbdev *
-usb_scan_device(char *sys)
-{
-       struct altos_usbdev *usbdev;
-
-       usbdev = calloc(1, sizeof (struct altos_usbdev));
-       if (!usbdev)
-               return NULL;
-       usbdev->sys = strdup(sys);
-       usbdev->manufacturer = load_string(sys, "manufacturer");
-       usbdev->product_name = load_string(sys, "product");
-       usbdev->serial = load_dec(sys, "serial");
-       usbdev->idProduct = load_hex(sys, "idProduct");
-       usbdev->idVendor = load_hex(sys, "idVendor");
-       usbdev->tty = usb_tty(sys);
-       return usbdev;
-}
-
-static void
-usbdev_free(struct altos_usbdev *usbdev)
-{
-       free(usbdev->sys);
-       free(usbdev->manufacturer);
-       free(usbdev->product_name);
-       /* this can get used as a return value */
-       if (usbdev->tty)
-               free(usbdev->tty);
-       free(usbdev);
-}
-
-#define USB_DEVICES    "/sys/bus/usb/devices"
-
-static int
-dir_filter_dev(const struct dirent *d)
-{
-       const char      *n = d->d_name;
-       char    c;
-
-       while ((c = *n++)) {
-               if (isdigit(c))
-                       continue;
-               if (c == '-')
-                       continue;
-               if (c == '.' && n != d->d_name + 1)
-                       continue;
-               return 0;
-       }
-       return 1;
-}
-
-struct altos_list {
-       struct altos_usbdev     **dev;
-       int                     current;
-       int                     ndev;
-};
-
-struct altos_list *
-altos_list_start(void)
-{
-       int                     e;
-       struct dirent           **ents;
-       char                    *dir;
-       struct altos_usbdev     *dev;
-       struct altos_list       *devs;
-       int                     n;
-
-       devs = calloc(1, sizeof (struct altos_list));
-       if (!devs)
-               return NULL;
-
-       n = scandir (USB_DEVICES, &ents,
-                    dir_filter_dev,
-                    alphasort);
-       if (!n)
-               return 0;
-       for (e = 0; e < n; e++) {
-               dir = cc_fullname(USB_DEVICES, ents[e]->d_name);
-               dev = usb_scan_device(dir);
-               free(dir);
-               if (USB_IS_ALTUSMETRUM(dev->idVendor, dev->idProduct)) {
-                       if (devs->dev)
-                               devs->dev = realloc(devs->dev,
-                                                   devs->ndev + 1 * sizeof (struct usbdev *));
-                       else
-                               devs->dev = malloc (sizeof (struct usbdev *));
-                       devs->dev[devs->ndev++] = dev;
-               }
-       }
-       free(ents);
-       devs->current = 0;
-       return devs;
-}
-
-int
-altos_list_next(struct altos_list *list, struct altos_device *device)
-{
-       struct altos_usbdev *dev;
-       if (list->current >= list->ndev)
-               return 0;
-       dev = list->dev[list->current];
-       strcpy(device->name, dev->product_name);
-       device->vendor = dev->idVendor;
-       device->product = dev->idProduct;
-       strcpy(device->path, dev->tty);
-       device->serial = dev->serial;
-       list->current++;
-       return 1;
-}
-
-void
-altos_list_finish(struct altos_list *usbdevs)
-{
-       int     i;
-
-       if (!usbdevs)
-               return;
-       for (i = 0; i < usbdevs->ndev; i++)
-               usbdev_free(usbdevs->dev[i]);
-       free(usbdevs);
-}
-
-#endif
-
-#ifdef DARWIN
-
-#include <IOKitLib.h>
-#include <IOKit/usb/USBspec.h>
-#include <sys/param.h>
-#include <paths.h>
-#include <CFNumber.h>
-#include <IOBSD.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-struct altos_list {
-       io_iterator_t iterator;
-};
-
-static int
-get_string(io_object_t object, CFStringRef entry, char *result, int result_len)
-{
-       CFTypeRef entry_as_string;
-       Boolean got_string;
-
-       entry_as_string = IORegistryEntrySearchCFProperty (object,
-                                                          kIOServicePlane,
-                                                          entry,
-                                                          kCFAllocatorDefault,
-                                                          kIORegistryIterateRecursively);
-       if (entry_as_string) {
-               got_string = CFStringGetCString(entry_as_string,
-                                               result, result_len,
-                                               kCFStringEncodingASCII);
-    
-               CFRelease(entry_as_string);
-               if (got_string)
-                       return 1;
-       }
-       return 0;
-}
-
-static int
-get_number(io_object_t object, CFStringRef entry, int *result)
-{
-       CFTypeRef entry_as_number;
-       Boolean got_number;
-       
-       entry_as_number = IORegistryEntrySearchCFProperty (object,
-                                                          kIOServicePlane,
-                                                          entry,
-                                                          kCFAllocatorDefault,
-                                                          kIORegistryIterateRecursively);
-       if (entry_as_number) {
-               got_number = CFNumberGetValue(entry_as_number,
-                                             kCFNumberIntType,
-                                             result);
-               if (got_number)
-                       return 1;
-       }
-       return 0;
-}
-
-struct altos_list *
-altos_list_start(void)
-{
-       struct altos_list *list = calloc (sizeof (struct altos_list), 1);
-       CFMutableDictionaryRef matching_dictionary = IOServiceMatching("IOUSBDevice");
-       io_iterator_t tdIterator;
-       io_object_t tdObject;
-       kern_return_t ret;
-       int i;
-
-       ret = IOServiceGetMatchingServices(kIOMasterPortDefault, matching_dictionary, &list->iterator);
-       if (ret != kIOReturnSuccess)
-               return NULL;
-       return list;
-}
-
-int
-altos_list_next(struct altos_list *list, struct altos_device *device)
-{
-       io_object_t object;
-       char serial_string[128];
-
-       for (;;) {
-               object = IOIteratorNext(list->iterator);
-               if (!object)
-                       return 0;
-  
-               if (!get_number (object, CFSTR(kUSBVendorID), &device->vendor) ||
-                   !get_number (object, CFSTR(kUSBProductID), &device->product))
-                       continue;
-               if (device->vendor != 0xfffe)
-                       continue;
-               if (device->product < 0x000a || 0x0013 < device->product)
-                       continue;
-               if (get_string (object, CFSTR("IOCalloutDevice"), device->path, sizeof (device->path)) &&
-                   get_string (object, CFSTR("USB Product Name"), device->name, sizeof (device->name)) &&
-                   get_string (object, CFSTR("USB Serial Number"), serial_string, sizeof (serial_string))) {
-                       device->serial = atoi(serial_string);
-                       return 1;
-               }
-       }
-}
-
-void
-altos_list_finish(struct altos_list *list)
-{
-       IOObjectRelease (list->iterator);
-       free(list);
-}
-
-#endif
-
-#ifdef POSIX_TTY
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <termios.h>
-#include <errno.h>
-
-#define USB_BUF_SIZE   64
-
-struct altos_file {
-       int                             fd;
-#ifdef USE_POLL
-       int                             pipe[2];
-#else
-       int                             out_fd;
-#endif
-       unsigned char                   out_data[USB_BUF_SIZE];
-       int                             out_used;
-       unsigned char                   in_data[USB_BUF_SIZE];
-       int                             in_used;
-       int                             in_read;
-};
-
-PUBLIC struct altos_file *
-altos_open(struct altos_device *device)
-{
-       struct altos_file       *file = calloc (sizeof (struct altos_file), 1);
-       int                     ret;
-       struct termios          term;
-
-       if (!file)
-               return NULL;
-
-       file->fd = open(device->path, O_RDWR | O_NOCTTY);
-       if (file->fd < 0) {
-               perror(device->path);
-               free(file);
-               return NULL;
-       }
-#ifdef USE_POLL
-       pipe(file->pipe);
-#else
-       file->out_fd = open(device->path, O_RDWR | O_NOCTTY);
-       if (file->out_fd < 0) {
-               perror(device->path);
-               close(file->fd);
-               free(file);
-               return NULL;
-       }
-#endif
-       ret = tcgetattr(file->fd, &term);
-       if (ret < 0) {
-               perror("tcgetattr");
-               close(file->fd);
-#ifndef USE_POLL
-               close(file->out_fd);
-#endif
-               free(file);
-               return NULL;
-       }
-       cfmakeraw(&term);
-#ifdef USE_POLL
-       term.c_cc[VMIN] = 1;
-       term.c_cc[VTIME] = 0;
-#else
-       term.c_cc[VMIN] = 0;
-       term.c_cc[VTIME] = 1;
-#endif
-       ret = tcsetattr(file->fd, TCSAFLUSH, &term);
-       if (ret < 0) {
-               perror("tcsetattr");
-               close(file->fd);
-#ifndef USE_POLL
-               close(file->out_fd);
-#endif
-               free(file);
-               return NULL;
-       }
-       return file;
-}
-
-PUBLIC void
-altos_close(struct altos_file *file)
-{
-       if (file->fd != -1) {
-               int     fd = file->fd;
-               file->fd = -1;
-#ifdef USE_POLL
-               write(file->pipe[1], "\r", 1);
-#else
-               close(file->out_fd);
-               file->out_fd = -1;
-#endif
-               close(fd);
-       }
-}
-
-PUBLIC void
-altos_free(struct altos_file *file)
-{
-       altos_close(file);
-       free(file);
-}
-
-PUBLIC int
-altos_flush(struct altos_file *file)
-{
-       if (file->out_used && 0) {
-               printf ("flush \"");
-               fwrite(file->out_data, 1, file->out_used, stdout);
-               printf ("\"\n");
-       }
-       while (file->out_used) {
-               int     ret;
-
-               if (file->fd < 0)
-                       return -EBADF;
-#ifdef USE_POLL
-               ret = write (file->fd, file->out_data, file->out_used);
-#else
-               ret = write (file->out_fd, file->out_data, file->out_used);
-#endif
-               if (ret < 0)
-                       return -errno;
-               if (ret) {
-                       memmove(file->out_data, file->out_data + ret,
-                               file->out_used - ret);
-                       file->out_used -= ret;
-               }
-       }
-       return 0;
-}
-
-PUBLIC int
-altos_putchar(struct altos_file *file, char c)
-{
-       int     ret;
-
-       if (file->out_used == USB_BUF_SIZE) {
-               ret = altos_flush(file);
-               if (ret) {
-                       return ret;
-               }
-       }
-       file->out_data[file->out_used++] = c;
-       ret = 0;
-       if (file->out_used == USB_BUF_SIZE)
-               ret = altos_flush(file);
-       return 0;
-}
-
-#ifdef USE_POLL
-#include <poll.h>
-#endif
-
-static int
-altos_fill(struct altos_file *file, int timeout)
-{
-       int             ret;
-#ifdef USE_POLL
-       struct pollfd   fd[2];
-#endif
-
-       if (timeout == 0)
-               timeout = -1;
-       while (file->in_read == file->in_used) {
-               if (file->fd < 0)
-                       return LIBALTOS_ERROR;
-#ifdef USE_POLL
-               fd[0].fd = file->fd;
-               fd[0].events = POLLIN|POLLERR|POLLHUP|POLLNVAL;
-               fd[1].fd = file->pipe[0];
-               fd[1].events = POLLIN;
-               ret = poll(fd, 2, timeout);
-               if (ret < 0) {
-                       perror("altos_getchar");
-                       return LIBALTOS_ERROR;
-               }
-               if (ret == 0)
-                       return LIBALTOS_TIMEOUT;
-
-               if (fd[0].revents & (POLLHUP|POLLERR|POLLNVAL))
-                       return LIBALTOS_ERROR;
-               if (fd[0].revents & POLLIN)
-#endif
-               {
-                       ret = read(file->fd, file->in_data, USB_BUF_SIZE);
-                       if (ret < 0) {
-                               perror("altos_getchar");
-                               return LIBALTOS_ERROR;
-                       }
-                       file->in_read = 0;
-                       file->in_used = ret;
-#ifndef USE_POLL
-                       if (ret == 0 && timeout > 0)
-                               return LIBALTOS_TIMEOUT;
-#endif
-               }
-       }
-       if (file->in_used && 0) {
-               printf ("fill \"");
-               fwrite(file->in_data, 1, file->in_used, stdout);
-               printf ("\"\n");
-       }
-       return 0;
-}
-
-PUBLIC int
-altos_getchar(struct altos_file *file, int timeout)
-{
-       int     ret;
-       while (file->in_read == file->in_used) {
-               if (file->fd < 0)
-                       return LIBALTOS_ERROR;
-               ret = altos_fill(file, timeout);
-               if (ret)
-                       return ret;
-       }
-       return file->in_data[file->in_read++];
-}
-
-#endif /* POSIX_TTY */
-
-#ifdef WINDOWS
-
-#include <stdlib.h>
-#include <windows.h>
-#include <setupapi.h>
-
-struct altos_list {
-       HDEVINFO        dev_info;
-       int             index;
-};
-
-#define USB_BUF_SIZE   64
-
-struct altos_file {
-       HANDLE                          handle;
-       unsigned char                   out_data[USB_BUF_SIZE];
-       int                             out_used;
-       unsigned char                   in_data[USB_BUF_SIZE];
-       int                             in_used;
-       int                             in_read;
-       OVERLAPPED                      ov_read;
-       BOOL                            pend_read;
-       OVERLAPPED                      ov_write;
-};
-
-PUBLIC struct altos_list *
-altos_list_start(void)
-{
-       struct altos_list       *list = calloc(1, sizeof (struct altos_list));
-
-       if (!list)
-               return NULL;
-       list->dev_info = SetupDiGetClassDevs(NULL, "USB", NULL,
-                                            DIGCF_ALLCLASSES|DIGCF_PRESENT);
-       if (list->dev_info == INVALID_HANDLE_VALUE) {
-               printf("SetupDiGetClassDevs failed %d\n", GetLastError());
-               free(list);
-               return NULL;
-       }
-       list->index = 0;
-       return list;
-}
-
-PUBLIC int
-altos_list_next(struct altos_list *list, struct altos_device *device)
-{
-       SP_DEVINFO_DATA dev_info_data;
-       char            port[128];
-       DWORD           port_len;
-       char            friendlyname[256];
-       char            symbolic[256];
-       DWORD           symbolic_len;
-       HKEY            dev_key;
-       int             vid, pid;
-       int             serial;
-       HRESULT         result;
-       DWORD           friendlyname_type;
-       DWORD           friendlyname_len;
-
-       dev_info_data.cbSize = sizeof (SP_DEVINFO_DATA);
-       while(SetupDiEnumDeviceInfo(list->dev_info, list->index,
-                                   &dev_info_data))
-       {
-               list->index++;
-
-               dev_key = SetupDiOpenDevRegKey(list->dev_info, &dev_info_data,
-                                              DICS_FLAG_GLOBAL, 0, DIREG_DEV,
-                                              KEY_READ);
-               if (dev_key == INVALID_HANDLE_VALUE) {
-                       printf("cannot open device registry key\n");
-                       continue;
-               }
-
-               /* Fetch symbolic name for this device and parse out
-                * the vid/pid/serial info */
-               symbolic_len = sizeof(symbolic);
-               result = RegQueryValueEx(dev_key, "SymbolicName", NULL, NULL,
-                                        symbolic, &symbolic_len);
-               if (result != 0) {
-                       printf("cannot find SymbolicName value\n");
-                       RegCloseKey(dev_key);
-                       continue;
-               }
-               vid = pid = serial = 0;
-               sscanf(symbolic + sizeof("\\??\\USB#VID_") - 1,
-                      "%04X", &vid);
-               sscanf(symbolic + sizeof("\\??\\USB#VID_XXXX&PID_") - 1,
-                      "%04X", &pid);
-               sscanf(symbolic + sizeof("\\??\\USB#VID_XXXX&PID_XXXX#") - 1,
-                      "%d", &serial);
-               if (!USB_IS_ALTUSMETRUM(vid, pid)) {
-                       RegCloseKey(dev_key);
-                       continue;
-               }
-
-               /* Fetch the com port name */
-               port_len = sizeof (port);
-               result = RegQueryValueEx(dev_key, "PortName", NULL, NULL,
-                                        port, &port_len);
-               RegCloseKey(dev_key);
-               if (result != 0) {
-                       printf("failed to get PortName\n");
-                       continue;
-               }
-
-               /* Fetch the device description which is the device name,
-                * with firmware that has unique USB ids */
-               friendlyname_len = sizeof (friendlyname);
-               if(!SetupDiGetDeviceRegistryProperty(list->dev_info,
-                                                    &dev_info_data,
-                                                    SPDRP_FRIENDLYNAME,
-                                                    &friendlyname_type,
-                                                    (BYTE *)friendlyname,
-                                                    sizeof(friendlyname),
-                                                    &friendlyname_len))
-               {
-                       printf("Failed to get friendlyname\n");
-                       continue;
-               }
-               device->vendor = vid;
-               device->product = pid;
-               device->serial = serial;
-               strcpy(device->name, friendlyname);
-
-               strcpy(device->path, port);
-               return 1;
-       }
-       result = GetLastError();
-       if (result != ERROR_NO_MORE_ITEMS)
-               printf ("SetupDiEnumDeviceInfo failed error %d\n", result);
-       return 0;
-}
-
-PUBLIC void
-altos_list_finish(struct altos_list *list)
-{
-       SetupDiDestroyDeviceInfoList(list->dev_info);
-       free(list);
-}
-
-static int
-altos_queue_read(struct altos_file *file)
-{
-       DWORD   got;
-       if (file->pend_read)
-               return LIBALTOS_SUCCESS;
-
-       if (!ReadFile(file->handle, file->in_data, USB_BUF_SIZE, &got, &file->ov_read)) {
-               if (GetLastError() != ERROR_IO_PENDING)
-                       return LIBALTOS_ERROR;
-               file->pend_read = TRUE;
-       } else {
-               file->pend_read = FALSE;
-               file->in_read = 0;
-               file->in_used = got;
-       }
-       return LIBALTOS_SUCCESS;
-}
-
-static int
-altos_wait_read(struct altos_file *file, int timeout)
-{
-       DWORD   ret;
-       DWORD   got;
-
-       if (!file->pend_read)
-               return LIBALTOS_SUCCESS;
-
-       if (!timeout)
-               timeout = INFINITE;
-
-       ret = WaitForSingleObject(file->ov_read.hEvent, timeout);
-       switch (ret) {
-       case WAIT_OBJECT_0:
-               if (!GetOverlappedResult(file->handle, &file->ov_read, &got, FALSE))
-                       return LIBALTOS_ERROR;
-               file->pend_read = FALSE;
-               file->in_read = 0;
-               file->in_used = got;
-               break;
-       case WAIT_TIMEOUT:
-               return LIBALTOS_TIMEOUT;
-               break;
-       default:
-               return LIBALTOS_ERROR;
-       }
-       return LIBALTOS_SUCCESS;
-}
-
-static int
-altos_fill(struct altos_file *file, int timeout)
-{
-       int     ret;
-
-       if (file->in_read < file->in_used)
-               return LIBALTOS_SUCCESS;
-
-       file->in_read = file->in_used = 0;
-
-       ret = altos_queue_read(file);
-       if (ret)
-               return ret;
-       ret = altos_wait_read(file, timeout);
-       if (ret)
-               return ret;
-
-       return LIBALTOS_SUCCESS;
-}
-
-PUBLIC int
-altos_flush(struct altos_file *file)
-{
-       DWORD   put;
-       char    *data = file->out_data;
-       char    used = file->out_used;
-       DWORD   ret;
-
-       while (used) {
-               if (!WriteFile(file->handle, data, used, &put, &file->ov_write)) {
-                       if (GetLastError() != ERROR_IO_PENDING)
-                               return LIBALTOS_ERROR;
-                       ret = WaitForSingleObject(file->ov_write.hEvent, INFINITE);
-                       switch (ret) {
-                       case WAIT_OBJECT_0:
-                               if (!GetOverlappedResult(file->handle, &file->ov_write, &put, FALSE))
-                                       return LIBALTOS_ERROR;
-                               break;
-                       default:
-                               return LIBALTOS_ERROR;
-                       }
-               }
-               data += put;
-               used -= put;
-       }
-       file->out_used = 0;
-       return LIBALTOS_SUCCESS;
-}
-
-PUBLIC struct altos_file *
-altos_open(struct altos_device *device)
-{
-       struct altos_file       *file = calloc (1, sizeof (struct altos_file));
-       char    full_name[64];
-       DCB dcbSerialParams = {0};
-       COMMTIMEOUTS timeouts;
-
-       if (!file)
-               return NULL;
-
-       strcpy(full_name, "\\\\.\\");
-       strcat(full_name, device->path);
-       file->handle = CreateFile(full_name, GENERIC_READ|GENERIC_WRITE,
-                                 0, NULL, OPEN_EXISTING,
-                                 FILE_FLAG_OVERLAPPED, NULL);
-       if (file->handle == INVALID_HANDLE_VALUE) {
-               free(file);
-               return NULL;
-       }
-       file->ov_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
-       file->ov_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
-
-       timeouts.ReadIntervalTimeout = MAXDWORD;
-       timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
-       timeouts.ReadTotalTimeoutConstant = 1 << 30;    /* almost forever */
-       timeouts.WriteTotalTimeoutMultiplier = 0;
-       timeouts.WriteTotalTimeoutConstant = 0;
-       SetCommTimeouts(file->handle, &timeouts);
-
-       dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
-       if (!GetCommState(file->handle, &dcbSerialParams)) {
-               CloseHandle(file->handle);
-               free(file);
-               return NULL;
-       }
-       dcbSerialParams.BaudRate = CBR_9600;
-       dcbSerialParams.ByteSize = 8;
-       dcbSerialParams.StopBits = ONESTOPBIT;
-       dcbSerialParams.Parity = NOPARITY;
-       if (!SetCommState(file->handle, &dcbSerialParams)) {
-               CloseHandle(file->handle);
-               free(file);
-               return NULL;
-       }
-
-       return file;
-}
-
-PUBLIC void
-altos_close(struct altos_file *file)
-{
-       if (file->handle != INVALID_HANDLE_VALUE) {
-               CloseHandle(file->handle);
-               file->handle = INVALID_HANDLE_VALUE;
-       }
-}
-
-PUBLIC void
-altos_free(struct altos_file *file)
-{
-       altos_close(file);
-       free(file);
-}
-
-int
-altos_putchar(struct altos_file *file, char c)
-{
-       int     ret;
-
-       if (file->out_used == USB_BUF_SIZE) {
-               ret = altos_flush(file);
-               if (ret)
-                       return ret;
-       }
-       file->out_data[file->out_used++] = c;
-       if (file->out_used == USB_BUF_SIZE)
-               return altos_flush(file);
-       return LIBALTOS_SUCCESS;
-}
-
-int
-altos_getchar(struct altos_file *file, int timeout)
-{
-       int     ret;
-       while (file->in_read == file->in_used) {
-               if (file->handle == INVALID_HANDLE_VALUE)
-                       return LIBALTOS_ERROR;
-               ret = altos_fill(file, timeout);
-               if (ret)
-                       return ret;
-       }
-       return file->in_data[file->in_read++];
-}
-
-#endif
diff --git a/ao-tools/libaltos/libaltos.dylib b/ao-tools/libaltos/libaltos.dylib
deleted file mode 100755 (executable)
index 89aa12e..0000000
Binary files a/ao-tools/libaltos/libaltos.dylib and /dev/null differ
diff --git a/ao-tools/libaltos/libaltos.h b/ao-tools/libaltos/libaltos.h
deleted file mode 100644 (file)
index 6e94899..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef _LIBALTOS_H_
-#define _LIBALTOS_H_
-
-#include <stdlib.h>
-
-#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
-# ifndef BUILD_STATIC
-#  ifdef BUILD_DLL
-#   define PUBLIC __declspec(dllexport)
-#  else
-#   define PUBLIC __declspec(dllimport)
-#  endif
-# endif /* BUILD_STATIC */
-#endif
-
-#ifndef PUBLIC
-# define PUBLIC
-#endif
-
-#define USB_VENDOR_FSF                 0xfffe
-#define USB_VENDOR_ALTUSMETRUM         USB_VENDOR_FSF
-#define USB_PRODUCT_ALTUSMETRUM                0x000a
-#define USB_PRODUCT_TELEMETRUM         0x000b
-#define USB_PRODUCT_TELEDONGLE         0x000c
-#define USB_PRODUCT_TELETERRA          0x000d
-#define USB_PRODUCT_ALTUSMETRUM_MIN    0x000a
-#define USB_PRODUCT_ALTUSMETRUM_MAX    0x0013
-
-#define USB_IS_ALTUSMETRUM(v,p)        ((v) == USB_VENDOR_ALTUSMETRUM && \
-               (USB_PRODUCT_ALTUSMETRUM_MIN <= (p) && \
-                (p) <= USB_PRODUCT_ALTUSMETRUM_MAX))
-
-struct altos_device {
-       //%immutable;
-       int                             vendor;
-       int                             product;
-       int                             serial;
-       char                            name[256];
-       char                            path[256];
-       //%mutable;
-};
-
-#define LIBALTOS_SUCCESS       0
-#define LIBALTOS_ERROR         -1
-#define LIBALTOS_TIMEOUT       -2
-
-/* Returns 0 for success, < 0 on error */
-PUBLIC int
-altos_init(void);
-
-PUBLIC void
-altos_fini(void);
-
-PUBLIC struct altos_list *
-altos_list_start(void);
-
-/* Returns 1 for success, zero on end of list */
-PUBLIC int
-altos_list_next(struct altos_list *list, struct altos_device *device);
-
-PUBLIC void
-altos_list_finish(struct altos_list *list);
-
-PUBLIC struct altos_file *
-altos_open(struct altos_device *device);
-
-PUBLIC void
-altos_close(struct altos_file *file);
-
-PUBLIC void
-altos_free(struct altos_file *file);
-
-/* Returns < 0 for error */
-PUBLIC int
-altos_putchar(struct altos_file *file, char c);
-
-/* Returns < 0 for error */
-PUBLIC int
-altos_flush(struct altos_file *file);
-
-/* Returns < 0 for error or timeout. timeout of 0 == wait forever */
-PUBLIC int
-altos_getchar(struct altos_file *file, int timeout);
-
-#endif /* _LIBALTOS_H_ */
diff --git a/ao-tools/libaltos/libaltos.i0 b/ao-tools/libaltos/libaltos.i0
deleted file mode 100644 (file)
index d06468f..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-%module libaltos
-%{
-#include "libaltos.h"
-%}
-
index 903c576554d6530428cfee6ca47acb1519a91994..22af00ab825375be547ac85b93199839f7d76243 100644 (file)
@@ -133,6 +133,8 @@ PKG_CHECK_MODULES([SNDFILE], [sndfile])
 
 AC_OUTPUT([
 Makefile
 
 AC_OUTPUT([
 Makefile
+altosui/Makefile
+altosui/libaltos/Makefile
 ao-tools/Makefile
 ao-tools/lib/Makefile
 ao-tools/ao-rawload/Makefile
 ao-tools/Makefile
 ao-tools/lib/Makefile
 ao-tools/ao-rawload/Makefile
@@ -144,8 +146,6 @@ ao-tools/ao-list/Makefile
 ao-tools/ao-load/Makefile
 ao-tools/ao-postflight/Makefile
 ao-tools/ao-view/Makefile
 ao-tools/ao-load/Makefile
 ao-tools/ao-postflight/Makefile
 ao-tools/ao-view/Makefile
-ao-tools/libaltos/Makefile
-ao-tools/altosui/Makefile
 ao-utils/Makefile
 src/Version
 ])
 ao-utils/Makefile
 src/Version
 ])