Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos
authorBdale Garbee <bdale@gag.com>
Tue, 23 Oct 2012 15:38:36 +0000 (09:38 -0600)
committerBdale Garbee <bdale@gag.com>
Tue, 23 Oct 2012 15:38:36 +0000 (09:38 -0600)
60 files changed:
altosdroid/.externalToolBuilders/Generate BuildInfo.java.launch [new file with mode: 0644]
altosdroid/.gitignore
altosdroid/.project
altosdroid/Makefile.am
altosdroid/buildinfo.sh [new file with mode: 0755]
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java
altosdroid/src/org/altusmetrum/AltosDroid/BuildInfo.java.in [new file with mode: 0644]
altoslib/AltosConfigData.java
altoslib/AltosEepromMega.java
altoslib/AltosEepromMegaIterable.java
altoslib/AltosIdleMonitor.java
altoslib/AltosLib.java
altoslib/AltosOrderedMegaRecord.java
altoslib/AltosPyro.java [new file with mode: 0644]
altoslib/AltosRecord.java
altoslib/AltosRecordMM.java
altoslib/AltosRecordNone.java [new file with mode: 0644]
altoslib/AltosRecordTM.java
altoslib/AltosState.java
altoslib/AltosTelemetryRecordLegacy.java
altoslib/AltosTelemetryRecordMegaData.java
altoslib/AltosTelemetryRecordRaw.java
altoslib/AltosTelemetryRecordSensor.java
altoslib/Makefile.am
altosui/AltosAscent.java
altosui/AltosCSV.java
altosui/AltosConfig.java
altosui/AltosConfigPyroUI.java [new file with mode: 0644]
altosui/AltosConfigUI.java
altosui/AltosDataChooser.java
altosui/AltosDataPoint.java
altosui/AltosDataPointReader.java
altosui/AltosDescent.java
altosui/AltosDialog.java
altosui/AltosDisplayThread.java
altosui/AltosEepromDownload.java
altosui/AltosFlightStats.java
altosui/AltosGraphUI.java
altosui/AltosInfoTable.java
altosui/AltosKML.java
altosui/AltosLanded.java
altosui/Makefile.am
src/Makefile
src/avr/ao_adc_avr.c
src/avr/ao_arch.h
src/avr/ao_pins.h
src/avr/ao_pwmin.c [new file with mode: 0644]
src/avr/ao_pwmin.h [new file with mode: 0644]
src/core/ao_log.h
src/core/ao_pyro.c
src/core/ao_pyro.h
src/product/ao_telescience.c
src/stm/ao_timer.c
src/telepyro-v0.1/Makefile
src/telescience-pwm/.gitignore [new file with mode: 0644]
src/telescience-pwm/Makefile [new file with mode: 0644]
src/test/ao_flight_test.c
src/test/run-mm [new file with mode: 0755]
src/util/check-avr-mem [changed mode: 0644->0755]

diff --git a/altosdroid/.externalToolBuilders/Generate BuildInfo.java.launch b/altosdroid/.externalToolBuilders/Generate BuildInfo.java.launch
new file mode 100644 (file)
index 0000000..3b8eff4
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
+<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${working_set:&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;resources&gt;&#10;&lt;item path=&quot;/AltosDroid/src/org/altusmetrum/AltosDroid/BuildInfo.java&quot; type=&quot;1&quot;/&gt;&#10;&lt;/resources&gt;}"/>
+<booleanAttribute key="org.eclipse.debug.core.capture_output" value="false"/>
+<booleanAttribute key="org.eclipse.debug.ui.ATTR_CONSOLE_OUTPUT_ON" value="false"/>
+<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/AltosDroid/buildinfo.sh}"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,auto,"/>
+<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/AltosDroid}"/>
+</launchConfiguration>
index c0bb8dd49fe499ffa29593dba371369e85d71f0d..e3acba4051795715f5a0514552778b6e09ae4371 100644 (file)
@@ -1,3 +1,4 @@
 local.properties
 bin
 gen
+src/org/altusmetrum/AltosDroid/BuildInfo.java
index 7b56596a3cbdd63eab336d51e0c5956b98d77961..ebe4a4bbc8aaf782401952810078cb74bd8627e9 100644 (file)
@@ -5,6 +5,16 @@
        <projects>
        </projects>
        <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
+                       <triggers>auto,full,incremental,</triggers>
+                       <arguments>
+                               <dictionary>
+                                       <key>LaunchConfigHandle</key>
+                                       <value>&lt;project&gt;/.externalToolBuilders/Generate BuildInfo.java.launch</value>
+                               </dictionary>
+                       </arguments>
+               </buildCommand>
                <buildCommand>
                        <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
                        <arguments>
index 96831b722ba7955a87242bf562e5823df8965f37..3860e110b1804357e8f070e792280852aa39f175 100644 (file)
@@ -30,6 +30,7 @@ SRC=\
        $(SRC_DIR)/TelemetryLogger.java \
        $(SRC_DIR)/AltosBluetooth.java \
        $(SRC_DIR)/DeviceListActivity.java \
+       $(SRC_DIR)/BuildInfo.java \
        $(SRC_DIR)/Dumper.java
 
 all: $(all_target)
@@ -38,6 +39,9 @@ $(ALTOSLIB): $(ALTOSLIB_SRCDIR)/$(ALTOSLIB_JAR)
        mkdir -p $(EXT_LIBDIR)
        cd $(EXT_LIBDIR) && ln -s $(shell echo $(EXT_LIBDIR) | sed 's|[^/]\+|..|g')/$(ALTOSLIB_SRCDIR)/$(ALTOSLIB_JAR) .
 
+$(SRC_DIR)/BuildInfo.java:
+       ./buildinfo.sh
+
 if ANDROID
 install-release: bin/AltosDroid-release.apk
        $(ADB) install -r bin/AltosDroid-release.apk
@@ -55,3 +59,4 @@ endif
 clean:
        $(clean_command)
 
+.PHONY: $(SRC_DIR)/BuildInfo.java
diff --git a/altosdroid/buildinfo.sh b/altosdroid/buildinfo.sh
new file mode 100755 (executable)
index 0000000..f620c4a
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/sh
+#
+
+describe=$(git describe --always 2>/dev/null || echo '')
+if [ -n "$describe" ]; then
+   version=$(echo $describe | cut -d- -f1)
+   commitnum=$(echo $describe | cut -d- -f2)
+   commithash=$(echo $describe | cut -d- -f3)
+else
+   . ../src/Version
+   version=$VERSION
+   commitnum=''
+   commithash=''
+fi
+
+builddate=$(date "+%Y-%m-%d")
+buildtime=$(date "+%H:%M")
+
+
+infile=src/org/altusmetrum/AltosDroid/BuildInfo.java.in
+outfile=src/org/altusmetrum/AltosDroid/BuildInfo.java
+
+echo "Version $describe, built on $builddate, $buildtime"
+
+sed -e "s/@DESCRIBE@/$describe/" \
+    -e "s/@VERSION@/$version/" \
+    -e "s/@COMMITNUM@/$commitnum/" \
+    -e "s/@COMMITHASH@/$commithash/" \
+    -e "s/@BUILDDATE@/$builddate/" \
+    -e "s/@BUILDTIME@/$buildtime/" \
+ $infile > $outfile
index 3396f77e40f9df866d94bd5ef87e355cfa1a3299..b1fc8d30fd091d124c52619f2c930e763235e843 100644 (file)
@@ -189,10 +189,7 @@ public class AltosDroid extends Activity {
                mSerialView.setText(String.format("%d", state.data.serial));
                mFlightView.setText(String.format("%d", state.data.flight));
                mStateView.setText(state.data.state());
-               double speed = state.speed;
-               if (!state.ascent)
-                       speed = state.baro_speed;
-               mSpeedView.setText(String.format("%6.0f m/s", speed));
+               mSpeedView.setText(String.format("%6.0f m/s", state.speed()));
                mAccelView.setText(String.format("%6.0f m/s²", state.acceleration));
                mRangeView.setText(String.format("%6.0f m", state.range));
                mHeightView.setText(String.format("%6.0f m", state.height));
index 3382d5516e76605a4f49e6d11a9a1d4763726245..264e35c6be17466929fa8c274b1037c32c1bbf8b 100644 (file)
@@ -67,7 +67,7 @@ public class AltosVoice {
                        speak(state.data.state());\r
                        if ((old_state == null || old_state.state <= AltosLib.ao_flight_boost) &&\r
                            state.state > AltosLib.ao_flight_boost) {\r
-                               speak(String.format("max speed: %d meters per second.", (int) (state.max_speed + 0.5)));\r
+                               speak(String.format("max speed: %d meters per second.", (int) (state.max_speed() + 0.5)));\r
                                spoke = true;\r
                        } else if ((old_state == null || old_state.state < AltosLib.ao_flight_drogue) &&\r
                                   state.state >= AltosLib.ao_flight_drogue) {\r
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/BuildInfo.java.in b/altosdroid/src/org/altusmetrum/AltosDroid/BuildInfo.java.in
new file mode 100644 (file)
index 0000000..763f814
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright © 2012 Mike Beattie <mike@ethernal.org>
+ *
+ * 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 org.altusmetrum.AltosDroid;
+
+public class BuildInfo {
+       public static final String git_describe = "@DESCRIBE@";
+       public static final String version      = "@VERSION@";
+       public static final String commitnum    = "@COMMITNUM@";
+       public static final String commithash   = "@COMMITHASH@";
+       public static final String builddate    = "@BUILDDATE@";
+       public static final String buildtime    = "@BUILDTIME@";
+}
+
index a962b1058ed5da60b9b4682a337839ba37ba2aeb..45a88783ad3a4a5e33fa023188804a66da6d077f 100644 (file)
@@ -50,6 +50,8 @@ public class AltosConfigData implements Iterable<String> {
        public int      storage_size;
        public int      storage_erase_unit;
 
+       public AltosPyro[]      pyros;
+
        public static String get_string(String line, String label) throws  ParseException {
                if (line.startsWith(label)) {
                        String  quoted = line.substring(label.length()).trim();
@@ -135,6 +137,10 @@ public class AltosConfigData implements Iterable<String> {
                radio_frequency = 0;
                stored_flight = 0;
                serial = -1;
+               pyros = null;
+
+               int npyro = 0;
+               int pyro = 0;
                for (;;) {
                        String line = link.get_reply();
                        if (line == null)
@@ -142,6 +148,16 @@ public class AltosConfigData implements Iterable<String> {
                        if (line.contains("Syntax error"))
                                continue;
                        lines.add(line);
+                       if (pyro < npyro - 1) {
+                               if (pyros == null)
+                                       pyros = new AltosPyro[npyro];
+                               try {
+                                       pyros[pyro] = new AltosPyro(pyro, line);
+                               } catch (ParseException e) {
+                               }
+                               ++pyro;
+                               continue;
+                       }
                        try { serial = get_int(line, "serial-number"); } catch (Exception e) {}
                        try { log_format = get_int(line, "log-format"); } catch (Exception e) {}
                        try { main_deploy = get_int(line, "Main deploy:"); } catch (Exception e) {}
@@ -173,6 +189,7 @@ public class AltosConfigData implements Iterable<String> {
                        try { get_int(line, "flight"); stored_flight++; }  catch (Exception e) {}
                        try { storage_size = get_int(line, "Storage size:"); } catch (Exception e) {}
                        try { storage_erase_unit = get_int(line, "Storage erase unit"); } catch (Exception e) {}
+                       try { npyro = get_int(line, "Pyro-count:"); pyro = 0; } catch (Exception e) {}
 
                        /* signals the end of the version info */
                        if (line.startsWith("software-version"))
index 26bacf8d854e33474457c4c8ef1a485e47232918..af4f8aca5b1de78b9e49a52e575161c1facefcf3 100644 (file)
@@ -24,7 +24,7 @@ public class AltosEepromMega {
        public int      tick;
        public boolean  valid;
        public String   data;
-       public int      a, b;
+       public int      config_a, config_b;
 
        public int      data8[];
 
@@ -66,12 +66,7 @@ public class AltosEepromMega {
        public int mag_x() { return data16(20); }
        public int mag_y() { return data16(22); }
        public int mag_z() { return data16(24); }
-       public int accel() {
-               int a = data16(26);
-               if (a != 0xffff)
-                       return a;
-               return accel_y();
-       }
+       public int accel() { return data16(26); }
 
        /* AO_LOG_VOLT elements */
        public int v_batt() { return data16(0); }
@@ -79,6 +74,22 @@ public class AltosEepromMega {
        public int nsense() { return data16(4); }
        public int sense(int i) { return data16(6 + i * 2); }
 
+       /* AO_LOG_GPS_TIME elements */
+       public int latitude() { return data32(0); }
+       public int longitude() { return data32(4); }
+       public int altitude() { return data16(8); }
+       public int hour() { return data8(10); }
+       public int minute() { return data8(11); }
+       public int second() { return data8(12); }
+       public int flags() { return data8(13); }
+       public int year() { return data8(14); }
+       public int month() { return data8(15); }
+       public int day() { return data8(16); }
+       
+       /* AO_LOG_GPS_SAT elements */
+       public int nsat() { return data16(0); }
+       public int svid(int n) { return data8(2 + n * 2); }
+       public int c_n(int n) { return data8(2 + n * 2 + 1); }
        public AltosEepromMega (AltosEepromChunk chunk, int start) throws ParseException {
                cmd = chunk.data(start);
 
@@ -126,26 +137,26 @@ public class AltosEepromMega {
                                        data = tokens[2];
                                } else if (tokens[0].equals("Main") && tokens[1].equals("deploy:")) {
                                        cmd = AltosLib.AO_LOG_MAIN_DEPLOY;
-                                       a = Integer.parseInt(tokens[2]);
+                                       config_a = Integer.parseInt(tokens[2]);
                                } else if (tokens[0].equals("Apogee") && tokens[1].equals("delay:")) {
                                        cmd = AltosLib.AO_LOG_APOGEE_DELAY;
-                                       a = Integer.parseInt(tokens[2]);
+                                       config_a = Integer.parseInt(tokens[2]);
                                } else if (tokens[0].equals("Radio") && tokens[1].equals("channel:")) {
                                        cmd = AltosLib.AO_LOG_RADIO_CHANNEL;
-                                       a = Integer.parseInt(tokens[2]);
+                                       config_a = Integer.parseInt(tokens[2]);
                                } else if (tokens[0].equals("Callsign:")) {
                                        cmd = AltosLib.AO_LOG_CALLSIGN;
                                        data = tokens[1].replaceAll("\"","");
                                } else if (tokens[0].equals("Accel") && tokens[1].equals("cal")) {
                                        cmd = AltosLib.AO_LOG_ACCEL_CAL;
-                                       a = Integer.parseInt(tokens[3]);
-                                       b = Integer.parseInt(tokens[5]);
+                                       config_a = Integer.parseInt(tokens[3]);
+                                       config_b = Integer.parseInt(tokens[5]);
                                } else if (tokens[0].equals("Radio") && tokens[1].equals("cal:")) {
                                        cmd = AltosLib.AO_LOG_RADIO_CAL;
-                                       a = Integer.parseInt(tokens[2]);
+                                       config_a = Integer.parseInt(tokens[2]);
                                } else if (tokens[0].equals("Max") && tokens[1].equals("flight") && tokens[2].equals("log:")) {
                                        cmd = AltosLib.AO_LOG_MAX_FLIGHT_LOG;
-                                       a = Integer.parseInt(tokens[3]);
+                                       config_a = Integer.parseInt(tokens[3]);
                                } else if (tokens[0].equals("manufacturer")) {
                                        cmd = AltosLib.AO_LOG_MANUFACTURER;
                                        data = tokens[1];
@@ -154,38 +165,38 @@ public class AltosEepromMega {
                                        data = tokens[1];
                                } else if (tokens[0].equals("serial-number")) {
                                        cmd = AltosLib.AO_LOG_SERIAL_NUMBER;
-                                       a = Integer.parseInt(tokens[1]);
+                                       config_a = Integer.parseInt(tokens[1]);
                                } else if (tokens[0].equals("log-format")) {
                                        cmd = AltosLib.AO_LOG_LOG_FORMAT;
-                                       a = Integer.parseInt(tokens[1]);
+                                       config_a = Integer.parseInt(tokens[1]);
                                } else if (tokens[0].equals("software-version")) {
                                        cmd = AltosLib.AO_LOG_SOFTWARE_VERSION;
                                        data = tokens[1];
                                } else if (tokens[0].equals("ms5607")) {
                                        if (tokens[1].equals("reserved:")) {
                                                cmd = AltosLib.AO_LOG_BARO_RESERVED;
-                                               a = Integer.parseInt(tokens[2]);
+                                               config_a = Integer.parseInt(tokens[2]);
                                        } else if (tokens[1].equals("sens:")) {
                                                cmd = AltosLib.AO_LOG_BARO_SENS;
-                                               a = Integer.parseInt(tokens[2]);
+                                               config_a = Integer.parseInt(tokens[2]);
                                        } else if (tokens[1].equals("off:")) {
                                                cmd = AltosLib.AO_LOG_BARO_OFF;
-                                               a = Integer.parseInt(tokens[2]);
+                                               config_a = Integer.parseInt(tokens[2]);
                                        } else if (tokens[1].equals("tcs:")) {
                                                cmd = AltosLib.AO_LOG_BARO_TCS;
-                                               a = Integer.parseInt(tokens[2]);
+                                               config_a = Integer.parseInt(tokens[2]);
                                        } else if (tokens[1].equals("tco:")) {
                                                cmd = AltosLib.AO_LOG_BARO_TCO;
-                                               a = Integer.parseInt(tokens[2]);
+                                               config_a = Integer.parseInt(tokens[2]);
                                        } else if (tokens[1].equals("tref:")) {
                                                cmd = AltosLib.AO_LOG_BARO_TREF;
-                                               a = Integer.parseInt(tokens[2]);
+                                               config_a = Integer.parseInt(tokens[2]);
                                        } else if (tokens[1].equals("tempsens:")) {
                                                cmd = AltosLib.AO_LOG_BARO_TEMPSENS;
-                                               a = Integer.parseInt(tokens[2]);
+                                               config_a = Integer.parseInt(tokens[2]);
                                        } else if (tokens[1].equals("crc:")) {
                                                cmd = AltosLib.AO_LOG_BARO_CRC;
-                                               a = Integer.parseInt(tokens[2]);
+                                               config_a = Integer.parseInt(tokens[2]);
                                        } else {
                                                cmd = AltosLib.AO_LOG_INVALID;
                                                data = line;
index 1ab2fcc8b473aee35e45a4306c5f32d481e19d89..16809089a3483eebe3ec282cb1ebf2c1b8c5f125 100644 (file)
@@ -106,80 +106,47 @@ public class AltosEepromMegaIterable extends AltosRecordIterable {
                        eeprom.sensor_tick = record.tick;
                        has_accel = true;
                        break;
-               case AltosLib.AO_LOG_PRESSURE:
-                       state.pres = record.b;
-                       state.flight_pres = state.pres;
-                       if (eeprom.n_pad_samples == 0) {
-                               eeprom.n_pad_samples++;
-                               state.ground_pres = state.pres;
-                       }
-                       eeprom.seen |= seen_sensor;
-                       break;
                case AltosLib.AO_LOG_TEMP_VOLT:
                        state.v_batt = record.v_batt();
                        state.v_pyro = record.v_pbatt();
-                       for (int i = 0; i < AltosRecordMM.num_sense; i++)
+                       for (int i = 0; i < record.nsense(); i++)
                                state.sense[i] = record.sense(i);
                        eeprom.seen |= seen_temp_volt;
                        break;
-//
-//             case AltosLib.AO_LOG_DEPLOY:
-//                     state.drogue = record.a;
-//                     state.main = record.b;
-//                     eeprom.seen |= seen_deploy;
-//                     has_ignite = true;
-//                     break;
-
                case AltosLib.AO_LOG_STATE:
                        state.state = record.state();
                        break;
                case AltosLib.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);
+                       state.gps.lat = record.latitude() / 1e7;
+                       state.gps.lon = record.longitude() / 1e7;
+                       state.gps.alt = record.altitude();
+                       state.gps.year = record.year() + 2000;
+                       state.gps.month = record.month();
+                       state.gps.day = record.day();
+
+                       state.gps.hour = record.hour();
+                       state.gps.minute = record.minute();
+                       state.gps.second = record.second();
 
-                       int flags = (record.b >> 8);
+                       int flags = record.flags();
                        state.gps.connected = (flags & AltosLib.AO_GPS_RUNNING) != 0;
                        state.gps.locked = (flags & AltosLib.AO_GPS_VALID) != 0;
                        state.gps.nsat = (flags & AltosLib.AO_GPS_NUM_SAT_MASK) >>
                                AltosLib.AO_GPS_NUM_SAT_SHIFT;
                        state.new_gps = true;
                        has_gps = true;
-                       break;
-               case AltosLib.AO_LOG_GPS_LAT:
-                       int lat32 = record.a | (record.b << 16);
-                       state.gps.lat = (double) lat32 / 1e7;
-                       break;
-               case AltosLib.AO_LOG_GPS_LON:
-                       int lon32 = record.a | (record.b << 16);
-                       state.gps.lon = (double) lon32 / 1e7;
-                       break;
-               case AltosLib.AO_LOG_GPS_ALT:
-                       state.gps.alt = record.a;
+                       eeprom.seen |= seen_gps_time | seen_gps_lat | seen_gps_lon;
                        break;
                case AltosLib.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);
+                               int nsat = record.nsat();
+                               for (int i = 0; i < nsat; i++)
+                                       state.gps.add_sat(record.svid(i), record.c_n(i));
                        }
                        break;
-               case AltosLib.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 AltosLib.AO_LOG_CONFIG_VERSION:
                        break;
                case AltosLib.AO_LOG_MAIN_DEPLOY:
@@ -192,8 +159,8 @@ public class AltosEepromMegaIterable extends AltosRecordIterable {
                        state.callsign = record.data;
                        break;
                case AltosLib.AO_LOG_ACCEL_CAL:
-                       state.accel_plus_g = record.a;
-                       state.accel_minus_g = record.b;
+                       state.accel_plus_g = record.config_a;
+                       state.accel_minus_g = record.config_b;
                        break;
                case AltosLib.AO_LOG_RADIO_CAL:
                        break;
@@ -202,33 +169,33 @@ public class AltosEepromMegaIterable extends AltosRecordIterable {
                case AltosLib.AO_LOG_PRODUCT:
                        break;
                case AltosLib.AO_LOG_SERIAL_NUMBER:
-                       state.serial = record.a;
+                       state.serial = record.config_a;
                        break;
                case AltosLib.AO_LOG_SOFTWARE_VERSION:
                        break;
                case AltosLib.AO_LOG_BARO_RESERVED:
-                       baro.reserved = record.a;
+                       baro.reserved = record.config_a;
                        break;
                case AltosLib.AO_LOG_BARO_SENS:
-                       baro.sens =record.a;
+                       baro.sens =record.config_a;
                        break;
                case AltosLib.AO_LOG_BARO_OFF:
-                       baro.off =record.a;
+                       baro.off =record.config_a;
                        break;
                case AltosLib.AO_LOG_BARO_TCS:
-                       baro.tcs =record.a;
+                       baro.tcs =record.config_a;
                        break;
                case AltosLib.AO_LOG_BARO_TCO:
-                       baro.tco =record.a;
+                       baro.tco =record.config_a;
                        break;
                case AltosLib.AO_LOG_BARO_TREF:
-                       baro.tref =record.a;
+                       baro.tref =record.config_a;
                        break;
                case AltosLib.AO_LOG_BARO_TEMPSENS:
-                       baro.tempsens =record.a;
+                       baro.tempsens =record.config_a;
                        break;
                case AltosLib.AO_LOG_BARO_CRC:
-                       baro.crc =record.a;
+                       baro.crc =record.config_a;
                        break;
                }
                state.seen |= eeprom.seen;
@@ -287,25 +254,25 @@ public class AltosEepromMegaIterable extends AltosRecordIterable {
                                out.printf("# Config version: %s\n", record.data);
                                break;
                        case AltosLib.AO_LOG_MAIN_DEPLOY:
-                               out.printf("# Main deploy: %s\n", record.a);
+                               out.printf("# Main deploy: %s\n", record.config_a);
                                break;
                        case AltosLib.AO_LOG_APOGEE_DELAY:
-                               out.printf("# Apogee delay: %s\n", record.a);
+                               out.printf("# Apogee delay: %s\n", record.config_a);
                                break;
                        case AltosLib.AO_LOG_RADIO_CHANNEL:
-                               out.printf("# Radio channel: %s\n", record.a);
+                               out.printf("# Radio channel: %s\n", record.config_a);
                                break;
                        case AltosLib.AO_LOG_CALLSIGN:
                                out.printf("# Callsign: %s\n", record.data);
                                break;
                        case AltosLib.AO_LOG_ACCEL_CAL:
-                               out.printf ("# Accel cal: %d %d\n", record.a, record.b);
+                               out.printf ("# Accel cal: %d %d\n", record.config_a, record.config_b);
                                break;
                        case AltosLib.AO_LOG_RADIO_CAL:
-                               out.printf ("# Radio cal: %d\n", record.a);
+                               out.printf ("# Radio cal: %d\n", record.config_a);
                                break;
                        case AltosLib.AO_LOG_MAX_FLIGHT_LOG:
-                               out.printf ("# Max flight log: %d\n", record.a);
+                               out.printf ("# Max flight log: %d\n", record.config_a);
                                break;
                        case AltosLib.AO_LOG_MANUFACTURER:
                                out.printf ("# Manufacturer: %s\n", record.data);
@@ -314,73 +281,39 @@ public class AltosEepromMegaIterable extends AltosRecordIterable {
                                out.printf ("# Product: %s\n", record.data);
                                break;
                        case AltosLib.AO_LOG_SERIAL_NUMBER:
-                               out.printf ("# Serial number: %d\n", record.a);
+                               out.printf ("# Serial number: %d\n", record.config_a);
                                break;
                        case AltosLib.AO_LOG_SOFTWARE_VERSION:
                                out.printf ("# Software version: %s\n", record.data);
                                break;
                        case AltosLib.AO_LOG_BARO_RESERVED:
-                               out.printf ("# Baro reserved: %d\n", record.a);
+                               out.printf ("# Baro reserved: %d\n", record.config_a);
                                break;
                        case AltosLib.AO_LOG_BARO_SENS:
-                               out.printf ("# Baro sens: %d\n", record.a);
+                               out.printf ("# Baro sens: %d\n", record.config_a);
                                break;
                        case AltosLib.AO_LOG_BARO_OFF:
-                               out.printf ("# Baro off: %d\n", record.a);
+                               out.printf ("# Baro off: %d\n", record.config_a);
                                break;
                        case AltosLib.AO_LOG_BARO_TCS:
-                               out.printf ("# Baro tcs: %d\n", record.a);
+                               out.printf ("# Baro tcs: %d\n", record.config_a);
                                break;
                        case AltosLib.AO_LOG_BARO_TCO:
-                               out.printf ("# Baro tco: %d\n", record.a);
+                               out.printf ("# Baro tco: %d\n", record.config_a);
                                break;
                        case AltosLib.AO_LOG_BARO_TREF:
-                               out.printf ("# Baro tref: %d\n", record.a);
+                               out.printf ("# Baro tref: %d\n", record.config_a);
                                break;
                        case AltosLib.AO_LOG_BARO_TEMPSENS:
-                               out.printf ("# Baro tempsens: %d\n", record.a);
+                               out.printf ("# Baro tempsens: %d\n", record.config_a);
                                break;
                        case AltosLib.AO_LOG_BARO_CRC:
-                               out.printf ("# Baro crc: %d\n", record.a);
+                               out.printf ("# Baro crc: %d\n", record.config_a);
                                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(AltosOrderedMegaRecord good, AltosOrderedMegaRecord 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 & AltosLib.AO_GPS_NUM_SAT_MASK) >> AltosLib.AO_GPS_NUM_SAT_SHIFT < 4)
-                       flags = (flags & ~AltosLib.AO_GPS_NUM_SAT_MASK) | (4 << AltosLib.AO_GPS_NUM_SAT_SHIFT);
-               flags |= AltosLib.AO_GPS_RUNNING;
-               flags |= AltosLib.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
@@ -416,53 +349,11 @@ public class AltosEepromMegaIterable extends AltosRecordIterable {
                                        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 == AltosLib.AO_LOG_GPS_DATE) {
-                                       gps_date_record = record;
-                                       continue;
-                               }
-
-                               /* go back and fix up any missing time values */
-                               if (record.cmd == AltosLib.AO_LOG_GPS_TIME) {
-                                       last_gps_time = record;
-                                       if (missing_time) {
-                                               Iterator<AltosOrderedMegaRecord> iterator = records.iterator();
-                                               while (iterator.hasNext()) {
-                                                       AltosOrderedMegaRecord old = iterator.next();
-                                                       if (old.cmd == AltosLib.AO_LOG_GPS_TIME &&
-                                                           old.a == -1 && old.b == -1)
-                                                       {
-                                                               update_time(record, old);
-                                                       }
-                                               }
-                                               missing_time = false;
-                                       }
-                               }
-
-                               if (record.cmd == AltosLib.AO_LOG_GPS_LAT) {
-                                       if (last_gps_time == null || last_gps_time.tick != record.tick) {
-                                               AltosOrderedMegaRecord add_gps_time = new AltosOrderedMegaRecord(AltosLib.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 == AltosLib.AO_LOG_STATE &&
-                                   record.a == AltosLib.ao_flight_landed)
+                                   record.state() == AltosLib.ao_flight_landed)
                                        break;
                        }
                } catch (IOException io) {
index 2c4965ff42047dc027f0073993b21ae4ce0375b8..07d8930d36e45a23229886957d8c577a61434556 100644 (file)
@@ -97,7 +97,7 @@ public class AltosIdleMonitor extends Thread {
                        else if (has_sensor_mm(config_data))
                                record = sensor_mm(config_data);
                        else
-                               record = new AltosRecord();
+                               record = new AltosRecordNone();
 
                        if (has_gps(config_data))
                                gps = new AltosGPSQuery(link, config_data);
index 192c445e0c42dabe2b9e3c42a209fe8843e9269c..07516aebd389fe3af4fcac245ffb42fa25ef8b1c 100644 (file)
@@ -199,7 +199,7 @@ public class AltosLib {
 
        public static String state_name_capital(int state) {
                if (state < 0 || state_to_string.length <= state)
-                       return "invalid";
+                       return "Invalid";
                return state_to_string_capital[state];
        }
 
index 05423dd94f1ad240bfd1ba0d25f35588b726e415..3aaf7b5b56066c173ce687ae112b7ee2a6f6da2e 100644 (file)
@@ -43,18 +43,6 @@ class AltosOrderedMegaRecord extends AltosEepromMega implements Comparable<Altos
                index = in_index;
        }
 
-       public AltosOrderedMegaRecord(int in_cmd, int in_tick, int in_a, int in_b, int in_index) {
-               super(in_cmd, in_tick);
-               a = in_a;
-               b = in_b;
-               index = in_index;
-       }
-
-       public String toString() {
-               return String.format("%d.%d %04x %04x %04x",
-                                    cmd, index, tick, a, b);
-       }
-
        public int compareTo(AltosOrderedMegaRecord o) {
                int     tick_diff = tick - o.tick;
                if (tick_diff != 0)
diff --git a/altoslib/AltosPyro.java b/altoslib/AltosPyro.java
new file mode 100644 (file)
index 0000000..1405116
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ * Copyright © 2012 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 org.altusmetrum.AltosLib;
+
+import java.util.*;
+import java.text.*;
+import java.util.concurrent.*;
+
+public class AltosPyro {
+       public static final int pyro_none                       = 0x00000000;
+
+       public static final int pyro_accel_less                 = 0x00000001;
+       public static final int pyro_accel_greater              = 0x00000002;
+       public static final String pyro_accel_less_string       = "a<";
+       public static final String pyro_accel_greater_string    = "a>";
+       public static final String pyro_accel_less_name         = "Acceleration less than (m/s²)";
+       public static final String pyro_accel_greater_name      = "Acceleration greater than (m/s²)";
+       public static final double pyro_accel_scale             = 16.0;
+
+       public static final int pyro_speed_less                 = 0x00000004;
+       public static final int pyro_speed_greater              = 0x00000008;
+       public static final String pyro_speed_less_string       = "s<";
+       public static final String pyro_speed_greater_string    = "s>";
+       public static final String pyro_speed_less_name         = "Speed less than (m/s)";
+       public static final String pyro_speed_greater_name      = "Speed greater than (m/s)";
+       public static final double pyro_speed_scale             = 16.0;
+
+       public static final int pyro_height_less                = 0x00000010;
+       public static final int pyro_height_greater             = 0x00000020;
+       public static final String pyro_height_less_string      = "h<";
+       public static final String pyro_height_greater_string   = "h>";
+       public static final String pyro_height_less_name        = "Height less than (m)";
+       public static final String pyro_height_greater_name     = "Height greater than (m)";
+       public static final double pyro_height_scale            = 1.0;
+
+       public static final int pyro_orient_less                = 0x00000040;
+       public static final int pyro_orient_greater             = 0x00000080;
+       public static final String pyro_orient_less_string      = "o<";
+       public static final String pyro_orient_greater_string   = "o>";
+       public static final String pyro_orient_less_name        = "Angle from vertical less than (degrees)";
+       public static final String pyro_orient_greater_name     = "Angle from vertical greater than (degrees)";
+       public static final double pyro_orient_scale            = 1.0;
+
+       public static final int pyro_time_less                  = 0x00000100;
+       public static final int pyro_time_greater               = 0x00000200;
+       public static final String pyro_time_less_string        = "t<";
+       public static final String pyro_time_greater_string     = "t>";
+       public static final String pyro_time_less_name          = "Time since boost less than (s)";
+       public static final String pyro_time_greater_name       = "Time since boost greater than (s)";
+       public static final double pyro_time_scale              = 100.0;
+
+       public static final int pyro_ascending                  = 0x00000400;
+       public static final int pyro_descending                 = 0x00000800;
+       public static final String pyro_ascending_string        = "A";
+       public static final String pyro_descending_string       = "D";
+       public static final String pyro_ascending_name          = "Ascending";
+       public static final String pyro_descending_name         = "Descending";
+
+       public static final int pyro_after_motor                = 0x00001000;
+       public static final String pyro_after_motor_string      = "m";
+       public static final String pyro_after_motor_name        = "After motor number";
+       public static final double pyro_after_motor_scale       = 1.0;
+
+       public static final int pyro_delay                      = 0x00002000;
+       public static final String pyro_delay_string            = "d";
+       public static final String pyro_delay_name              = "Delay after other conditions (s)";
+       public static final double pyro_delay_scale             = 100.0;
+
+       public static final int pyro_state_less                 = 0x00004000;
+       public static final int pyro_state_greater_or_equal     = 0x00008000;
+       public static final String pyro_state_less_string       = "f<";
+       public static final String pyro_state_greater_or_equal_string   = "f>=";
+       public static final String pyro_state_less_name         = "Flight state before";
+       public static final String pyro_state_greater_or_equal_name     = "Flight state after";
+       public static final double pyro_state_scale             = 1.0;
+
+       public static final int pyro_all                        = 0x0000ffff;
+
+       public static final int pyro_no_value                   = (pyro_ascending |
+                                                                  pyro_descending);
+
+       public static final int pyro_state_value                = pyro_state_less | pyro_state_greater_or_equal;
+
+       private static HashMap<String,Integer> string_to_pyro = new HashMap<String,Integer>();
+
+       private static HashMap<Integer,String> pyro_to_string = new HashMap<Integer,String>();
+
+       private static HashMap<Integer,String> pyro_to_name = new HashMap<Integer,String>();
+
+       private static HashMap<Integer,Double> pyro_to_scale = new HashMap<Integer,Double>();
+       
+       private static void insert_map(int flag, String string, String name, double scale) {
+               string_to_pyro.put(string, flag);
+               pyro_to_string.put(flag, string);
+               pyro_to_name.put(flag, name);
+               pyro_to_scale.put(flag, scale);
+       }
+       
+       public static int string_to_pyro(String name) {
+               if (string_to_pyro.containsKey(name))
+                       return string_to_pyro.get(name);
+               return pyro_none;
+       }
+
+       public static String pyro_to_string(int flag) {
+               if (pyro_to_string.containsKey(flag))
+                       return pyro_to_string.get(flag);
+               return null;
+       }
+
+       public static String pyro_to_name(int flag) {
+               if (pyro_to_name.containsKey(flag))
+                       return pyro_to_name.get(flag);
+               return null;
+       }
+
+       public static double pyro_to_scale(int flag) {
+               if (pyro_to_scale.containsKey(flag))
+                       return pyro_to_scale.get(flag);
+               return 1.0;
+       }
+
+       private static void initialize_maps() {
+               insert_map(pyro_accel_less, pyro_accel_less_string, pyro_accel_less_name, pyro_accel_scale);
+               insert_map(pyro_accel_greater, pyro_accel_greater_string, pyro_accel_greater_name, pyro_accel_scale);
+
+               insert_map(pyro_speed_less, pyro_speed_less_string, pyro_speed_less_name, pyro_speed_scale);
+               insert_map(pyro_speed_greater, pyro_speed_greater_string, pyro_speed_greater_name, pyro_speed_scale);
+
+               insert_map(pyro_height_less, pyro_height_less_string, pyro_height_less_name, pyro_height_scale);
+               insert_map(pyro_height_greater, pyro_height_greater_string, pyro_height_greater_name, pyro_height_scale);
+
+               insert_map(pyro_orient_less, pyro_orient_less_string, pyro_orient_less_name, pyro_orient_scale);
+               insert_map(pyro_orient_greater, pyro_orient_greater_string, pyro_orient_greater_name, pyro_orient_scale);
+
+               insert_map(pyro_time_less, pyro_time_less_string, pyro_time_less_name, pyro_time_scale);
+               insert_map(pyro_time_greater, pyro_time_greater_string, pyro_time_greater_name, pyro_time_scale);
+
+               insert_map(pyro_ascending, pyro_ascending_string, pyro_ascending_name, 1.0);
+               insert_map(pyro_descending, pyro_descending_string, pyro_descending_name, 1.0);
+
+               insert_map(pyro_after_motor, pyro_after_motor_string, pyro_after_motor_name, 1.0);
+               insert_map(pyro_delay, pyro_delay_string, pyro_delay_name, pyro_delay_scale);
+               
+               insert_map(pyro_state_less, pyro_state_less_string, pyro_state_less_name, 1.0);
+               insert_map(pyro_state_greater_or_equal, pyro_state_greater_or_equal_string, pyro_state_greater_or_equal_name, 1.0);
+       }
+
+       {
+               initialize_maps();
+       }
+
+       public int      channel;
+       public int      flags;
+       public int      accel_less, accel_greater;
+       public int      speed_less, speed_greater;
+       public int      height_less, height_greater;
+       public int      orient_less, orient_greater;
+       public int      time_less, time_greater;
+       public int      delay;
+       public int      state_less, state_greater_or_equal;
+       public int      motor;
+
+       public AltosPyro(int in_channel) {
+               channel = in_channel;
+               flags = 0;
+       }
+
+       private boolean set_ivalue(int flag, int value) {
+               switch (flag) {
+               case pyro_accel_less:                   accel_less = value; break;
+               case pyro_accel_greater:                accel_greater = value; break;
+               case pyro_speed_less:                   speed_less = value; break;
+               case pyro_speed_greater:                speed_greater = value; break;
+               case pyro_height_less:                  height_less = value; break;
+               case pyro_height_greater:               height_greater = value; break;
+               case pyro_orient_less:                  orient_less = value; break;
+               case pyro_orient_greater:               orient_greater = value; break;
+               case pyro_time_less:                    time_less = value; break;
+               case pyro_time_greater:                 time_greater = value; break;
+               case pyro_after_motor:                  motor = value; break;
+               case pyro_delay:                        delay = value; break;
+               case pyro_state_less:                   state_less = value; break;
+               case pyro_state_greater_or_equal:       state_greater_or_equal = value; break;
+               default:
+                       return false;
+               }
+               return true;
+       }
+
+       public boolean set_value(int flag, double dvalue) {
+               return set_ivalue(flag, (int) (dvalue * pyro_to_scale(flag)));
+       }
+
+       private int get_ivalue (int flag) {
+               int     value;
+
+               switch (flag) {
+               case pyro_accel_less:                   value = accel_less; break;
+               case pyro_accel_greater:                value = accel_greater; break;
+               case pyro_speed_less:                   value = speed_less; break;
+               case pyro_speed_greater:                value = speed_greater; break;
+               case pyro_height_less:                  value = height_less; break;
+               case pyro_height_greater:               value = height_greater; break;
+               case pyro_orient_less:                  value = orient_less; break;
+               case pyro_orient_greater:               value = orient_greater; break;
+               case pyro_time_less:                    value = time_less; break;
+               case pyro_time_greater:                 value = time_greater; break;
+               case pyro_after_motor:                  value = motor; break;
+               case pyro_delay:                        value = delay; break;
+               case pyro_state_less:                   value = state_less; break;
+               case pyro_state_greater_or_equal:       value = state_greater_or_equal; break;
+               default:                                value = 0; break;
+               }
+               return value;
+       }
+
+       public double get_value(int flag) {
+               return get_ivalue(flag) / pyro_to_scale(flag);
+       }
+
+       public AltosPyro(int in_channel, String line) throws ParseException {
+               String[] tokens = line.split("\\s+");
+
+               channel = in_channel;
+               flags = 0;
+
+               int i = 0;
+               if (tokens[i].equals("Pyro"))
+                       i += 2;
+
+               for (; i < tokens.length; i++) {
+
+                       if (tokens[i].equals("<disabled>"))
+                               break;
+
+                       int     flag = string_to_pyro(tokens[i]);
+                       if (flag == pyro_none)
+                               throw new ParseException(String.format("Invalid pyro token \"%s\"",
+                                                                      tokens[i]), i);
+                       flags |= flag;
+
+                       if ((flag & pyro_no_value) == 0) {
+                               int     value = 0;
+                               ++i;
+                               try {
+                                       value = AltosLib.fromdec(tokens[i]);
+                               } catch (NumberFormatException n) {
+                                       throw new ParseException(String.format("Invalid pyro value \"%s\"",
+                                                                              tokens[i]), i);
+                               }
+                               if (!set_ivalue(flag, value))
+                                       throw new ParseException(String.format("Internal parser error \"%s\" \"%s\"",
+                                                                              tokens[i-1], tokens[i]), i-1);
+                       }
+               }
+       }
+
+       public String toString() {
+               String  ret = String.format("%d", channel);
+
+               for (int flag = 1; flag <= flags; flag <<= 1) {
+                       if ((flags & flag) != 0) {
+                               String  add;
+                               if ((flag & pyro_no_value) == 0) {
+                                       add = String.format(" %s %d",
+                                                           pyro_to_string.get(flag),
+                                                           get_ivalue(flag));
+                               } else {
+                                       add = String.format(" %s",
+                                                           pyro_to_string.get(flag));
+                               }
+                               ret = ret.concat(add);
+                       }
+               }
+               return ret;
+       }
+}
index 8bab1d0cad2ad0c7b2700f809fc8ac09d14a6eff..091695154fea3cc01a2a5fecf7b2afebed47e218 100644 (file)
@@ -17,7 +17,7 @@
 
 package org.altusmetrum.AltosLib;
 
-public class AltosRecord implements Comparable <AltosRecord>, Cloneable {
+public abstract class AltosRecord implements Comparable <AltosRecord>, Cloneable {
 
        public static final int seen_flight = 1;
        public static final int seen_sensor = 2;
@@ -43,11 +43,6 @@ public class AltosRecord implements Comparable <AltosRecord>, Cloneable {
        public int      state;
        public int      tick;
 
-       /* Current flight dynamic state */
-       public double   acceleration;   /* m/s² */
-       public double   speed;          /* m/s */
-       public double   height;         /* m */
-
        public AltosGPS gps;
        public boolean  new_gps;
 
@@ -63,6 +58,11 @@ public class AltosRecord implements Comparable <AltosRecord>, Cloneable {
 
        public AltosRecordCompanion companion;
 
+       /* Telemetry sources have these values recorded from the flight computer */
+       public double   kalman_height;
+       public double   kalman_speed;
+       public double   kalman_acceleration;
+
        /*
         * Abstract methods that convert record data
         * to standard units:
@@ -75,76 +75,48 @@ public class AltosRecord implements Comparable <AltosRecord>, Cloneable {
         *      temperature:    °C
         */
 
-       public double raw_pressure() { return MISSING; }
-
-       public double filtered_pressure() { return MISSING; }
-
-       public double ground_pressure() { return MISSING; }
-
-       public double battery_voltage() { return MISSING; }
+       abstract public double pressure();
+       abstract public double ground_pressure();
+       abstract public double acceleration();
 
-       public double main_voltage() { return MISSING; }
+       public double altitude() {
+               double  p = pressure();
 
-       public double drogue_voltage() { return MISSING; }
-
-       public double temperature() { return MISSING; }
-       
-       public double acceleration() { return MISSING; }
-
-       public double accel_speed() { return MISSING; }
-
-       public AltosIMU imu() { return null; }
-
-       public AltosMag mag() { return null; }
-
-       /*
-        * Convert various pressure values to altitude
-        */
-
-       public double raw_altitude() {
-               double p = raw_pressure();
                if (p == MISSING)
                        return MISSING;
                return AltosConvert.pressure_to_altitude(p);
        }
 
        public double ground_altitude() {
-               double p = ground_pressure();
+               double  p = ground_pressure();
+
                if (p == MISSING)
                        return MISSING;
                return AltosConvert.pressure_to_altitude(p);
        }
 
-       public double filtered_altitude() {
-               double  ga = ground_altitude();
-               if (height != MISSING && ga != MISSING)
-                       return height + ga;
+       public double height() {
+               double  g = ground_altitude();
+               double  a = altitude();
 
-               double  p = filtered_pressure();
-               if (p == MISSING)
-                       return raw_altitude();
-               return AltosConvert.pressure_to_altitude(p);
+               if (g == MISSING)
+                       return MISSING;
+               if (a == MISSING)
+                       return MISSING;
+               return a - g;
        }
 
-       public double filtered_height() {
-               if (height != MISSING)
-                       return height;
+       public double battery_voltage() { return MISSING; }
 
-               double f = filtered_altitude();
-               double g = ground_altitude();
-               if (f == MISSING || g == MISSING)
-                       return MISSING;
-               return f - g;
-       }
+       public double main_voltage() { return MISSING; }
 
-       public double raw_height() {
-               double r = raw_altitude();
-               double g = ground_altitude();
+       public double drogue_voltage() { return MISSING; }
 
-               if (r == MISSING || g == MISSING)
-                       return height;
-               return r - g;
-       }
+       public double temperature() { return MISSING; }
+       
+       public AltosIMU imu() { return null; }
+
+       public AltosMag mag() { return null; }
 
        public String state() {
                return AltosLib.state_name(state);
@@ -164,12 +136,12 @@ public class AltosRecord implements Comparable <AltosRecord>, Cloneable {
                status = old.status;
                state = old.state;
                tick = old.tick;
-               acceleration = old.acceleration;
-               speed = old.speed;
-               height = old.height;
                gps = new AltosGPS(old.gps);
                new_gps = old.new_gps;
                companion = old.companion;
+               kalman_acceleration = old.kalman_acceleration;
+               kalman_speed = old.kalman_speed;
+               kalman_height = old.kalman_height;
        }
 
        public AltosRecord clone() {
@@ -192,11 +164,12 @@ public class AltosRecord implements Comparable <AltosRecord>, Cloneable {
                status = 0;
                state = AltosLib.ao_flight_startup;
                tick = 0;
-               acceleration = MISSING;
-               speed = MISSING;
-               height = MISSING;
                gps = new AltosGPS();
                new_gps = false;
                companion = null;
+
+               kalman_acceleration = MISSING;
+               kalman_speed = MISSING;
+               kalman_height = MISSING;
        }
 }
index 5f952f7a96a1b8aa02543076de90638f3e8cb860..9f5292346a61e773aee88f2aa22e290fda86590f 100644 (file)
@@ -19,6 +19,7 @@ package org.altusmetrum.AltosLib;
 
 public class AltosRecordMM extends AltosRecord {
 
+       /* Sensor values */
        public int      accel;
        public int      pres;
        public int      temp;
@@ -45,16 +46,12 @@ public class AltosRecordMM extends AltosRecord {
                return raw / 4095.0;
        }
 
-       public double raw_pressure() {
+       public double pressure() {
                if (pres != MISSING)
                        return pres;
                return MISSING;
        }
 
-       public double filtered_pressure() {
-               return raw_pressure();
-       }
-
        public double ground_pressure() {
                if (ground_pres != MISSING)
                        return ground_pres;
@@ -98,9 +95,6 @@ public class AltosRecordMM extends AltosRecord {
        }
 
        public double acceleration() {
-               if (acceleration != MISSING)
-                       return acceleration;
-
                if (ground_accel == MISSING || accel == MISSING)
                        return MISSING;
 
@@ -110,10 +104,6 @@ public class AltosRecordMM extends AltosRecord {
                return (ground_accel - accel) / accel_counts_per_mss();
        }
 
-       public double accel_speed() {
-               return speed;
-       }
-
        public void copy (AltosRecordMM old) {
                super.copy(old);
 
diff --git a/altoslib/AltosRecordNone.java b/altoslib/AltosRecordNone.java
new file mode 100644 (file)
index 0000000..ca0a5fe
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2012 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 org.altusmetrum.AltosLib;
+
+public class AltosRecordNone extends AltosRecord {
+
+       public double pressure() { return MISSING; }
+       public double ground_pressure() { return MISSING; }
+       public double temperature() { return MISSING; }
+       public double acceleration() { return MISSING; }
+
+       public AltosRecordNone(AltosRecord old) {
+               super.copy(old);
+       }
+
+       public AltosRecordNone() {
+               super();
+       }
+}
index 37accef60289cd8d2518d4217c5d9b22403cae26..9530be31fc4f26579cfb672654a6551b1b08d2bf 100644 (file)
@@ -18,6 +18,8 @@
 package org.altusmetrum.AltosLib;
 
 public class AltosRecordTM extends AltosRecord {
+
+       /* Sensor values */
        public int      accel;
        public int      pres;
        public int      temp;
@@ -57,18 +59,12 @@ public class AltosRecordTM extends AltosRecord {
                return ((count / 16.0) / 2047.0 + 0.095) / 0.009 * 1000.0;
        }
 
-       public double raw_pressure() {
+       public double pressure() {
                if (pres == MISSING)
                        return MISSING;
                return barometer_to_pressure(pres);
        }
 
-       public double filtered_pressure() {
-               if (flight_pres == MISSING)
-                       return MISSING;
-               return barometer_to_pressure(flight_pres);
-       }
-
        public double ground_pressure() {
                if (ground_pres == MISSING)
                        return MISSING;
@@ -121,22 +117,11 @@ public class AltosRecordTM extends AltosRecord {
        }
 
        public double acceleration() {
-               if (acceleration != MISSING)
-                       return acceleration;
-
                if (ground_accel == MISSING || accel == MISSING)
                        return MISSING;
                return (ground_accel - accel) / accel_counts_per_mss();
        }
 
-       public double accel_speed() {
-               if (speed != MISSING)
-                       return speed;
-               if (flight_vel == MISSING)
-                       return MISSING;
-               return flight_vel / (accel_counts_per_mss() * 100.0);
-       }
-
        public void copy(AltosRecordTM old) {
                super.copy(old);
 
index 2e4d8870e12684d5f6aa3ef6764f1338492f9281..f28dd1c6609f24070b7ba0fa4ce4e5f8f60205ed 100644 (file)
@@ -40,17 +40,17 @@ public class AltosState {
        public double   ground_altitude;
        public double   altitude;
        public double   height;
-       public double   speed;
        public double   acceleration;
        public double   battery;
        public double   temperature;
        public double   main_sense;
        public double   drogue_sense;
+       public double   accel_speed;
        public double   baro_speed;
 
        public double   max_height;
        public double   max_acceleration;
-       public double   max_speed;
+       public double   max_accel_speed;
        public double   max_baro_speed;
 
        public AltosGPS gps;
@@ -76,20 +76,39 @@ public class AltosState {
        public int      speak_tick;
        public double   speak_altitude;
 
-       public void init (AltosRecord cur, AltosState prev_state) {
-               //int           i;
-               //AltosRecord prev;
+       public double speed() {
+               if (ascent)
+                       return accel_speed;
+               else
+                       return baro_speed;
+       }
+
+       public double max_speed() {
+               if (max_accel_speed != 0)
+                       return max_accel_speed;
+               return max_baro_speed;
+       }
 
+       public void init (AltosRecord cur, AltosState prev_state) {
                data = cur;
 
                ground_altitude = data.ground_altitude();
-               altitude = data.raw_altitude();
-               height = data.filtered_height();
+
+               altitude = data.altitude();
+
+               if (data.kalman_height != AltosRecord.MISSING)
+                       height = data.kalman_height;
+               else {
+                       if (prev_state != null)
+                               height = (prev_state.height * 15 + altitude - ground_altitude) / 16.0;
+               }
 
                report_time = System.currentTimeMillis();
 
-               acceleration = data.acceleration();
-               speed = data.accel_speed();
+               if (data.kalman_acceleration != AltosRecord.MISSING)
+                       acceleration = data.kalman_acceleration;
+               else
+                       acceleration = data.acceleration();
                temperature = data.temperature();
                drogue_sense = data.drogue_voltage();
                main_sense = data.main_voltage();
@@ -108,7 +127,7 @@ public class AltosState {
                        pad_alt = prev_state.pad_alt;
                        max_height = prev_state.max_height;
                        max_acceleration = prev_state.max_acceleration;
-                       max_speed = prev_state.max_speed;
+                       max_accel_speed = prev_state.max_accel_speed;
                        max_baro_speed = prev_state.max_baro_speed;
                        imu = prev_state.imu;
                        mag = prev_state.mag;
@@ -119,23 +138,39 @@ public class AltosState {
 
                        time_change = (tick - prev_state.tick) / 100.0;
 
-                       /* compute barometric speed */
+                       if (data.kalman_speed != AltosRecord.MISSING) {
+                               baro_speed = accel_speed = data.kalman_speed;
+                       } else {
+                               /* compute barometric speed */
 
-                       double height_change = height - prev_state.height;
-                       if (data.speed != AltosRecord.MISSING)
-                               baro_speed = data.speed;
-                       else {
+                               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;
+
+                               if (acceleration == AltosRecord.MISSING) {
+                                       /* Fill in mising acceleration value */
+                                       accel_speed = baro_speed;
+                                       if (time_change > 0)
+                                               acceleration = (accel_speed - prev_state.accel_speed) / time_change;
+                                       else
+                                               acceleration = prev_state.acceleration;
+                               } else {
+                                       /* compute accelerometer speed */
+                                       accel_speed = prev_state.accel_speed + acceleration * time_change;
+                               }
                        }
+
                } else {
                        npad = 0;
                        ngps = 0;
                        gps = null;
                        baro_speed = 0;
+                       accel_speed = 0;
                        time_change = 0;
+                       if (acceleration == AltosRecord.MISSING)
+                               acceleration = 0;
                }
 
                time = tick / 100.0;
@@ -180,8 +215,8 @@ public class AltosState {
                /* Only look at accelerometer data under boost */
                if (boost && acceleration > max_acceleration && acceleration != AltosRecord.MISSING)
                        max_acceleration = acceleration;
-               if (boost && speed > max_speed && speed != AltosRecord.MISSING)
-                       max_speed = speed;
+               if (boost && accel_speed > max_accel_speed && accel_speed != AltosRecord.MISSING)
+                       max_accel_speed = accel_speed;
                if (boost && baro_speed > max_baro_speed && baro_speed != AltosRecord.MISSING)
                        max_baro_speed = baro_speed;
 
index 211760691e23668b3b52a0eda839861e10cbb61d..431897945549abdb521fcddca3f29497e64fc9dd 100644 (file)
@@ -257,9 +257,9 @@ public class AltosTelemetryRecordLegacy extends AltosTelemetryRecord {
                record.accel_minus_g = map.get_int(AO_TELEM_CAL_ACCEL_MINUS, AltosRecord.MISSING);
 
                /* flight computer values */
-               record.acceleration = map.get_double(AO_TELEM_KALMAN_ACCEL, AltosRecord.MISSING, 1/16.0);
-               record.speed = map.get_double(AO_TELEM_KALMAN_SPEED, AltosRecord.MISSING, 1/16.0);
-               record.height = map.get_int(AO_TELEM_KALMAN_HEIGHT, AltosRecord.MISSING);
+               record.kalman_acceleration = map.get_double(AO_TELEM_KALMAN_ACCEL, AltosRecord.MISSING, 1/16.0);
+               record.kalman_speed = map.get_double(AO_TELEM_KALMAN_SPEED, AltosRecord.MISSING, 1/16.0);
+               record.kalman_height = map.get_int(AO_TELEM_KALMAN_HEIGHT, AltosRecord.MISSING);
 
                record.flight_accel = map.get_int(AO_TELEM_ADHOC_ACCEL, AltosRecord.MISSING);
                record.flight_vel = map.get_int(AO_TELEM_ADHOC_SPEED, AltosRecord.MISSING);
@@ -334,9 +334,9 @@ public class AltosTelemetryRecordLegacy extends AltosTelemetryRecord {
 
                /* Old TeleDongle code with kalman-reporting TeleMetrum code */
                if ((record.flight_vel & 0xffff0000) == 0x80000000) {
-                       record.speed = ((short) record.flight_vel) / 16.0;
-                       record.acceleration = record.flight_accel / 16.0;
-                       record.height = record.flight_pres;
+                       record.kalman_speed = ((short) record.flight_vel) / 16.0;
+                       record.kalman_acceleration = record.flight_accel / 16.0;
+                       record.kalman_height = record.flight_pres;
                        record.flight_vel = AltosRecord.MISSING;
                        record.flight_pres = AltosRecord.MISSING;
                        record.flight_accel = AltosRecord.MISSING;
@@ -455,9 +455,9 @@ public class AltosTelemetryRecordLegacy extends AltosTelemetryRecord {
                record.accel_minus_g = int16(19);
 
                if (uint16(11) == 0x8000) {
-                       record.acceleration = int16(5);
-                       record.speed = int16(9);
-                       record.height = int16(13);
+                       record.kalman_acceleration = int16(5);
+                       record.kalman_speed = int16(9);
+                       record.kalman_height = int16(13);
                        record.flight_accel = AltosRecord.MISSING;
                        record.flight_vel = AltosRecord.MISSING;
                        record.flight_pres = AltosRecord.MISSING;
@@ -465,9 +465,9 @@ public class AltosTelemetryRecordLegacy extends AltosTelemetryRecord {
                        record.flight_accel = int16(5);
                        record.flight_vel = uint32(9);
                        record.flight_pres = int16(13);
-                       record.acceleration = AltosRecord.MISSING;
-                       record.speed = AltosRecord.MISSING;
-                       record.height = AltosRecord.MISSING;
+                       record.kalman_acceleration = AltosRecord.MISSING;
+                       record.kalman_speed = AltosRecord.MISSING;
+                       record.kalman_height = AltosRecord.MISSING;
                }
 
                record.gps = null;
index 8f55d238a3bae3689b96c7b816b8fac4efc731e3..16a7b80cc0f037a12e1cfc62c3f18c2a8982820a 100644 (file)
@@ -83,9 +83,9 @@ public class AltosTelemetryRecordMegaData extends AltosTelemetryRecordRaw {
                next.accel_plus_g = accel_plus_g;
                next.accel_minus_g = accel_minus_g;
 
-               next.acceleration = acceleration / 16.0;
-               next.speed = speed / 16.0;
-               next.height = height;
+               next.kalman_acceleration = acceleration / 16.0;
+               next.kalman_speed = speed / 16.0;
+               next.kalman_height = height;
 
                next.seen |= AltosRecord.seen_flight | AltosRecord.seen_temp_volt;
 
index fbb373d54dcdfb9beaba3e3610150b255cd47ac2..c21da6fc1cbe26f87eb480f0ecf6fce9477cc6f0 100644 (file)
@@ -65,7 +65,7 @@ public class AltosTelemetryRecordRaw extends AltosTelemetryRecord {
                if (previous != null)
                        next = previous.clone();
                else
-                       next = new AltosRecord();
+                       next = new AltosRecordNone();
                next.serial = serial;
                next.tick = tick;
                return next;
index 319a91b39d78df1195a9f64860973170bb3d79ee..f1fc156c484717e37f24bbf31ec7c336336c1cb3 100644 (file)
@@ -86,9 +86,9 @@ public class AltosTelemetryRecordSensor extends AltosTelemetryRecordRaw {
                        next.main = AltosRecord.MISSING;
                }
 
-               next.acceleration = acceleration / 16.0;
-               next.speed = speed / 16.0;
-               next.height = height;
+               next.kalman_acceleration = acceleration / 16.0;
+               next.kalman_speed = speed / 16.0;
+               next.kalman_height = height;
 
                next.ground_pres = ground_pres;
                if (type == packet_type_TM_sensor) {
index b56d8af1e312a6af46a73683ad9ba746c8e1e2a6..2579a65030a625a89784ab6876fbd97908e02886 100644 (file)
@@ -46,6 +46,7 @@ AltosLib_JAVA = \
        $(SRC)/AltosRecordCompanion.java \
        $(SRC)/AltosRecordIterable.java \
        $(SRC)/AltosRecord.java \
+       $(SRC)/AltosRecordNone.java \
        $(SRC)/AltosRecordTM.java \
        $(SRC)/AltosRecordMM.java \
        $(SRC)/AltosReplayReader.java \
@@ -74,7 +75,8 @@ AltosLib_JAVA = \
        $(SRC)/AltosDistance.java \
        $(SRC)/AltosHeight.java \
        $(SRC)/AltosSpeed.java \
-       $(SRC)/AltosAccel.java
+       $(SRC)/AltosAccel.java \
+       $(SRC)/AltosPyro.java
 
 JAR=AltosLib.jar
 
index 007c74ec639694ea46aeda47d960e1886b3d06be..a05c44041ba2a91a4b681c9ceb3b7ad3080265b7 100644 (file)
@@ -251,7 +251,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay {
 
        class Speed extends AscentValueHold {
                void show (AltosState state, int crc_errors) {
-                       double speed = state.speed;
+                       double speed = state.accel_speed;
                        if (!state.ascent)
                                speed = state.baro_speed;
                        show(AltosConvert.speed, speed);
index f8cc1ed6b1d12240a34ee74a7b28bfbc1018564c..1c929a7cd9d6a80946de1bc6792eb8528328c890 100644 (file)
@@ -128,10 +128,10 @@ public class AltosCSV implements AltosWriter {
        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(),
+                          record.pressure(),
+                          record.altitude(),
+                          record.height(),
+                          state.accel_speed,
                           state.baro_speed,
                           record.temperature(),
                           record.battery_voltage(),
index 44e5a3faf4c5265414476cbc0bc31464543c5a4a..44c6239af278821f0d229bd29e5d4eb2cdddb17b 100644 (file)
@@ -22,6 +22,7 @@ import javax.swing.*;
 import java.io.*;
 import java.util.concurrent.*;
 import org.altusmetrum.AltosLib.*;
+import java.text.*;
 
 public class AltosConfig implements ActionListener {
 
@@ -78,6 +79,8 @@ public class AltosConfig implements ActionListener {
        string_ref      version;
        string_ref      product;
        string_ref      callsign;
+       int_ref         npyro;
+       AltosPyro[]     pyros;
        AltosConfigUI   config_ui;
        boolean         serial_started;
        boolean         made_visible;
@@ -162,6 +165,8 @@ public class AltosConfig implements ActionListener {
                config_ui.set_ignite_mode(ignite_mode.get());
                config_ui.set_pad_orientation(pad_orientation.get());
                config_ui.set_callsign(callsign.get());
+               config_ui.set_pyros(pyros);
+               config_ui.set_has_pyro(npyro.get() > 0);
                config_ui.set_clean();
                if (!made_visible) {
                        made_visible = true;
@@ -169,6 +174,8 @@ public class AltosConfig implements ActionListener {
                }
        }
 
+       int     pyro;
+
        void process_line(String line) {
                if (line == null) {
                        abort();
@@ -179,6 +186,18 @@ public class AltosConfig implements ActionListener {
                                update_ui();
                        return;
                }
+               if (pyro < npyro.get()) {
+                       if (pyros == null)
+                               pyros = new AltosPyro[npyro.get()];
+
+                       try {
+                               pyros[pyro] = new AltosPyro(pyro, line);
+                       } catch (ParseException e) {
+                               System.out.printf ("pyro parse failed %s\n", line);
+                       }
+                       ++pyro;
+                       return;
+               }
                get_int(line, "serial-number", serial);
                get_int(line, "log-format", log_format);
                get_int(line, "Main deploy:", main_deploy);
@@ -200,6 +219,7 @@ public class AltosConfig implements ActionListener {
                get_string(line, "Callsign:", callsign);
                get_string(line,"software-version", version);
                get_string(line,"product", product);
+               get_int(line, "Pyro-count:", npyro);
        }
 
        final static int        serial_mode_read = 0;
@@ -243,6 +263,8 @@ public class AltosConfig implements ActionListener {
                        callsign.set("N0CALL");
                        version.set("unknown");
                        product.set("unknown");
+                       pyro = 0;
+                       npyro.set(0);
                }
 
                void get_data() {
@@ -304,6 +326,12 @@ public class AltosConfig implements ActionListener {
                                        serial_line.printf("c i %d\n", ignite_mode.get());
                                if (pad_orientation.get() >= 0)
                                        serial_line.printf("c o %d\n", pad_orientation.get());
+                               if (pyros.length > 0) {
+                                       for (int p = 0; p < pyros.length; p++) {
+                                               serial_line.printf("c P %s\n",
+                                                                  pyros[p].toString());
+                                       }
+                               }
                                serial_line.printf("c w\n");
                        } catch (InterruptedException ie) {
                        } catch (TimeoutException te) {
@@ -431,6 +459,9 @@ public class AltosConfig implements ActionListener {
                if (pad_orientation.get() >= 0)
                        pad_orientation.set(config_ui.pad_orientation());
                callsign.set(config_ui.callsign());
+               if (npyro.get() > 0) {
+                       pyros = config_ui.pyros();
+               }
                run_serial_thread(serial_mode_save);
        }
 
@@ -477,13 +508,14 @@ public class AltosConfig implements ActionListener {
                callsign = new string_ref("N0CALL");
                version = new string_ref("unknown");
                product = new string_ref("unknown");
+               npyro = new int_ref(0);
 
                device = AltosDeviceDialog.show(owner, Altos.product_any);
                if (device != null) {
                        try {
                                serial_line = new AltosSerial(device);
                                try {
-                                       if (!device.matchProduct(Altos.product_altimeter))
+                                       if (device.matchProduct(Altos.product_basestation))
                                                remote = true;
                                        init_ui();
                                } catch (InterruptedException ie) {
diff --git a/altosui/AltosConfigPyroUI.java b/altosui/AltosConfigPyroUI.java
new file mode 100644 (file)
index 0000000..17adb15
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ * Copyright © 2012 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.event.*;
+import org.altusmetrum.AltosLib.*;
+
+public class AltosConfigPyroUI
+       extends AltosDialog
+       implements ItemListener, DocumentListener
+{
+       AltosConfigUI   owner;
+       Container       pane;
+
+       static Insets il = new Insets(4,4,4,4);
+       static Insets ir = new Insets(4,4,4,4);
+
+       static String[] state_names;
+
+       static void make_state_names() {
+               if (state_names == null) {
+
+                       state_names = new String[AltosLib.ao_flight_landed - AltosLib.ao_flight_boost + 1];
+                       for (int state = AltosLib.ao_flight_boost; state <= AltosLib.ao_flight_landed; state++)
+                               state_names[state - AltosLib.ao_flight_boost] = AltosLib.state_name_capital(state);
+               }
+       }
+
+       class PyroItem implements ItemListener, DocumentListener
+       {
+               public int              flag;
+               public JRadioButton     enable;
+               public JTextField       value;
+               public JComboBox        combo;
+               AltosConfigPyroUI       ui;
+
+               public void set_enable(boolean enable) {
+                       if (value != null)
+                               value.setEnabled(enable);
+                       if (combo != null)
+                               combo.setEnabled(enable);
+               }
+
+               public void itemStateChanged(ItemEvent e) {
+                       set_enable(enable.isSelected());
+                       ui.set_dirty();
+               }
+
+               public void changedUpdate(DocumentEvent e) {
+                       ui.set_dirty();
+               }
+
+               public void insertUpdate(DocumentEvent e) {
+                       ui.set_dirty();
+               }
+
+               public void removeUpdate(DocumentEvent e) {
+                       ui.set_dirty();
+               }
+
+               public void set(boolean new_enable, double new_value) {
+                       enable.setSelected(new_enable);
+                       set_enable(new_enable);
+                       if (value != null) {
+                               double  scale = AltosPyro.pyro_to_scale(flag);
+                               String  format = "%6.0f";
+                               if (scale >= 10)
+                                       format = "%6.1f";
+                               else if (scale >= 100)
+                                       format = "%6.2f";
+                               value.setText(String.format(format, new_value));
+                       }
+                       if (combo != null)
+                               if (new_value >= AltosLib.ao_flight_boost && new_value <= AltosLib.ao_flight_landed)
+                                       combo.setSelectedIndex((int) new_value - AltosLib.ao_flight_boost);
+               }
+
+               public boolean enabled() {
+                       return enable.isSelected();
+               }
+
+               public double value() {
+                       if (value != null)
+                               return Double.parseDouble(value.getText());
+                       if (combo != null)
+                               return combo.getSelectedIndex() + AltosLib.ao_flight_boost;
+                       return 0;
+               }
+
+               public PyroItem(AltosConfigPyroUI in_ui, int in_flag, int x, int y) {
+
+                       ui = in_ui;
+                       flag = in_flag;
+
+                       GridBagConstraints      c;
+                       c = new GridBagConstraints();
+                       c.gridx = x; c.gridy = y;
+                       c.gridwidth = 1;
+                       c.fill = GridBagConstraints.NONE;
+                       c.anchor = GridBagConstraints.LINE_START;
+                       c.insets = il;
+                       enable = new JRadioButton();
+                       enable.addItemListener(this);
+                       pane.add(enable, c);
+                       
+                       if ((flag & AltosPyro.pyro_no_value) == 0) {
+                               c = new GridBagConstraints();
+                               c.gridx = x+1; c.gridy = y;
+                               c.gridwidth = 1;
+                               c.fill = GridBagConstraints.NONE;
+                               c.anchor = GridBagConstraints.LINE_START;
+                               c.insets = il;
+                               if ((flag & AltosPyro.pyro_state_value) != 0) {
+                                       make_state_names();
+                                       combo = new JComboBox(state_names);
+                                       combo.addItemListener(this);
+                                       pane.add(combo, c);
+                               } else {
+                                       value = new JTextField(10);
+                                       value.getDocument().addDocumentListener(this);
+                                       pane.add(value, c);
+                               }
+                       }
+               }
+       }
+
+       class PyroColumn {
+               public PyroItem[]       items;
+               public JLabel           label;
+               int                     channel;
+
+               public void set(AltosPyro pyro) {
+                       int row = 0;
+                       for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1) {
+                               if ((AltosPyro.pyro_all & flag) != 0) {
+                                       items[row].set((pyro.flags & flag) != 0,
+                                                      pyro.get_value(flag));
+                                       row++;
+                               }
+                       }
+               }
+
+               public AltosPyro get() {
+                       AltosPyro       p = new AltosPyro(channel);
+
+                       int row = 0;
+                       for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1) {
+                               if ((AltosPyro.pyro_all & flag) != 0) {
+                                       if (items[row].enabled()) {
+                                               System.out.printf ("Flag %x enabled\n", flag);
+                                               p.flags |= flag;
+                                               p.set_value(flag, items[row].value());
+                                       }
+                                       row++;
+                               }
+                       }
+                       System.out.printf ("Pyro %x %s\n", p.flags, p.toString());
+                       return p;
+               }
+
+               public PyroColumn(AltosConfigPyroUI ui, int x, int y, int in_channel) {
+
+                       channel = in_channel;
+
+                       int     nrow = 0;
+                       for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1)
+                               if ((flag & AltosPyro.pyro_all) != 0)
+                                       nrow++;
+
+                       items = new PyroItem[nrow];
+                       int row = 0;
+                       
+                       GridBagConstraints      c;
+                       c = new GridBagConstraints();
+                       c.gridx = x; c.gridy = y;
+                       c.gridwidth = 2;
+                       c.fill = GridBagConstraints.NONE;
+                       c.anchor = GridBagConstraints.CENTER;
+                       c.insets = il;
+                       label = new JLabel(String.format("Pyro Channel %d", channel));
+                       pane.add(label, c);
+                       y++;
+
+                       for (int flag = 1; flag < AltosPyro.pyro_all; flag <<= 1)
+                               if ((flag & AltosPyro.pyro_all) != 0) {
+                                       items[row] = new PyroItem(ui, flag, x, y + row);
+                                       row++;
+                               }
+               }
+       }
+
+       PyroColumn[]    columns;
+
+       public void set_pyros(AltosPyro[] pyros) {
+               for (int i = 0; i < pyros.length; i++) {
+                       if (pyros[i].channel < columns.length)
+                               columns[pyros[i].channel].set(pyros[i]);
+               }
+       }
+
+       public AltosPyro[] get_pyros() {
+               AltosPyro[]     pyros = new AltosPyro[columns.length];
+               for (int c = 0; c < columns.length; c++)
+                       pyros[c] = columns[c].get();
+               return pyros;
+       }
+
+       public void set_dirty() {
+               owner.set_dirty();
+       }
+
+       public void itemStateChanged(ItemEvent e) {
+               owner.set_dirty();
+       }
+
+       public void changedUpdate(DocumentEvent e) {
+               owner.set_dirty();
+       }
+
+       public void insertUpdate(DocumentEvent e) {
+               owner.set_dirty();
+       }
+
+       public void removeUpdate(DocumentEvent e) {
+               owner.set_dirty();
+       }
+
+       public AltosConfigPyroUI(AltosConfigUI in_owner, AltosPyro[] pyros) {
+
+               super(in_owner, "Configure Pyro Channels", false);
+
+               owner = in_owner;
+
+               GridBagConstraints      c;
+
+               pane = getContentPane();
+               pane.setLayout(new GridBagLayout());
+
+               int     row = 1;
+
+               for (int flag = 1; flag <= AltosPyro.pyro_all; flag <<= 1) {
+                       String  n;
+
+                       n = AltosPyro.pyro_to_name(flag);
+                       if (n != null) {
+                               c = new GridBagConstraints();
+                               c.gridx = 0; c.gridy = row;
+                               c.gridwidth = 1;
+                               c.fill = GridBagConstraints.NONE;
+                               c.anchor = GridBagConstraints.LINE_START;
+                               c.insets = il;
+                               JLabel label = new JLabel(n);
+                               pane.add(label, c);
+                               row++;
+                       }
+               }
+
+               columns = new PyroColumn[pyros.length];
+
+               for (int i = 0; i < pyros.length; i++) {
+                       columns[i] = new PyroColumn(this, i*2 + 1, 0, i);
+                       columns[i].set(pyros[i]);
+               }
+       }
+
+       public void make_visible() {
+               pack();
+               setVisible(true);
+       }
+}
index dd34a9cf348c84dbbb4a219652527f2e0db0c5a8..feac053be9ad0fc1ec358de8926c1ae5d1425231 100644 (file)
@@ -29,7 +29,6 @@ public class AltosConfigUI
 {
 
        Container       pane;
-       Box             box;
        JLabel          product_label;
        JLabel          version_label;
        JLabel          serial_label;
@@ -62,11 +61,15 @@ public class AltosConfigUI
        JComboBox       pad_orientation_value;
        JTextField      callsign_value;
 
+       JButton         pyro;
+
        JButton         save;
        JButton         reset;
        JButton         reboot;
        JButton         close;
 
+       AltosPyro[]     pyros;
+
        ActionListener  listener;
 
        static String[] main_deploy_values = {
@@ -510,6 +513,20 @@ public class AltosConfigUI
                set_pad_orientation_tool_tip();
                row++;
 
+               /* Pyro channels */
+               c = new GridBagConstraints();
+               c.gridx = 4; c.gridy = row;
+               c.gridwidth = 4;
+               c.fill = GridBagConstraints.HORIZONTAL;
+               c.anchor = GridBagConstraints.LINE_START;
+               c.insets = il;
+               c.ipady = 5;
+               pyro = new JButton("Configure Pyro Channels");
+               pane.add(pyro, c);
+               pyro.addActionListener(this);
+               pyro.setActionCommand("Pyro");
+               row++;
+
                /* Buttons */
                c = new GridBagConstraints();
                c.gridx = 0; c.gridy = row;
@@ -582,10 +599,30 @@ public class AltosConfigUI
                return true;
        }
 
+       void set_dirty() {
+               dirty = true;
+               save.setEnabled(true);
+       }
+
+       public void set_clean() {
+               dirty = false;
+               save.setEnabled(false);
+       }
+
+       AltosConfigPyroUI       pyro_ui;
+
        /* Listen for events from our buttons */
        public void actionPerformed(ActionEvent e) {
                String  cmd = e.getActionCommand();
 
+               if (cmd.equals("Pyro")) {
+                       if (pyro_ui == null && pyros != null) {
+                               pyro_ui = new AltosConfigPyroUI(this, pyros);
+                               pyro_ui.make_visible();
+                       }
+                       return;
+               }
+
                if (cmd.equals("Close") || cmd.equals("Reboot"))
                        if (!check_dirty(cmd))
                                return;
@@ -594,25 +631,25 @@ public class AltosConfigUI
                        setVisible(false);
                        dispose();
                }
-               dirty = false;
+               set_clean();
        }
 
        /* ItemListener interface method */
        public void itemStateChanged(ItemEvent e) {
-               dirty = true;
+               set_dirty();
        }
 
        /* DocumentListener interface methods */
        public void changedUpdate(DocumentEvent e) {
-               dirty = true;
+               set_dirty();
        }
 
        public void insertUpdate(DocumentEvent e) {
-               dirty = true;
+               set_dirty();
        }
 
        public void removeUpdate(DocumentEvent e) {
-               dirty = true;
+               set_dirty();
        }
 
        /* Let the config code hook on a listener */
@@ -725,8 +762,7 @@ public class AltosConfigUI
        }
 
        public void set_flight_log_max(int new_flight_log_max) {
-               if (new_flight_log_max == 0)
-                       flight_log_max_value.setEnabled(false);
+               flight_log_max_value.setEnabled(new_flight_log_max > 0);
                flight_log_max_value.setSelectedItem(Integer.toString(new_flight_log_max));
                set_flight_log_max_tool_tip();
        }
@@ -793,7 +829,19 @@ public class AltosConfigUI
                        return -1;
        }
 
-       public void set_clean() {
-               dirty = false;
+       public void set_has_pyro(boolean has_pyro) {
+               pyro.setEnabled(has_pyro);
+       }
+
+       public void set_pyros(AltosPyro[] new_pyros) {
+               pyros = new_pyros;
+               if (pyro_ui != null)
+                       pyro_ui.set_pyros(pyros);
+       }
+
+       public AltosPyro[] pyros() {
+               if (pyro_ui != null)
+                       pyros = pyro_ui.get_pyros();
+               return pyros;
        }
 }
index 4d2f321ec454c6ec08c8541fa682cc44b76360ad..a8a2ca4928e564428b95a2753aaebc71ba623f25 100644 (file)
@@ -70,6 +70,12 @@ public class AltosDataChooser extends JFileChooser {
        public AltosDataChooser(JFrame in_frame) {
                frame = in_frame;
                setDialogTitle("Select Flight Record File");
+               setFileFilter(new FileNameExtensionFilter("TeleMetrum eeprom file",
+                                                         "eeprom"));
+               setFileFilter(new FileNameExtensionFilter("Telemetry file",
+                                                         "telem"));
+               setFileFilter(new FileNameExtensionFilter("MegaMetrum eeprom file",
+                                                         "mega"));
                setFileFilter(new FileNameExtensionFilter("Flight data file",
                                                          "telem", "eeprom", "mega"));
                setCurrentDirectory(AltosUIPreferences.logdir());
index 5e07732026aeb2562b33eabeecfe7884b172c65c..4956e9f3c61eec2662056f746289c52db4abeb8a 100644 (file)
@@ -16,11 +16,8 @@ interface AltosDataPoint {
     String state_name();
 
     double acceleration();
-    double pressure();
-    double altitude();
     double height();
-    double accel_speed();
-    double baro_speed();
+    double speed();
     double temperature();
     double battery_voltage();
     double drogue_voltage();
index 2316cf97e1e36bcf447869b4dae248c4a9ab0999..88df081faeee4584d12113220eeaebbf443c1cd1 100644 (file)
@@ -12,7 +12,6 @@ import org.altusmetrum.AltosLib.*;
 class AltosDataPointReader implements Iterable<AltosDataPoint> {
     Iterator<AltosRecord> iter;
     AltosState state;
-    AltosRecord record;
     boolean has_gps;
     boolean has_accel;
     boolean has_ignite;
@@ -22,7 +21,7 @@ class AltosDataPointReader implements Iterable<AltosDataPoint> {
     public AltosDataPointReader(AltosRecordIterable reader) {
         this.iter = reader.iterator();
         this.state = null;
-       has_accel = reader.has_accel();
+       has_accel = true;
        has_gps = reader.has_gps();
        has_ignite = reader.has_ignite();
     }
@@ -30,35 +29,31 @@ class AltosDataPointReader implements Iterable<AltosDataPoint> {
     private void read_next_record() 
         throws NoSuchElementException
     {
-        record = iter.next();
-        state = new AltosState(record, state);
+        state = new AltosState(iter.next(), state);
     }
 
     private AltosDataPoint current_dp() {
-        assert this.record != null;
+        assert this.state != 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 version() { return state.data.version; }
+            public int serial() { return state.data.serial; }
+            public int flight() { return state.data.flight; }
+            public String callsign() { return state.data.callsign; }
+            public double time() { return state.data.time; }
+            public double rssi() { return state.data.rssi; }
 
-            public int state() { return record.state; }
-            public String state_name() { return record.state(); }
+            public int state() { return state.state; }
+            public String state_name() { return state.data.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 boolean has_accel() { return has_accel; }
+            public double acceleration() { return state.acceleration; }
+           public double height() { return state.height; }
+           public double speed() { return state.speed(); }
+            public double temperature() { return state.temperature; }
+            public double battery_voltage() { return state.battery; }
+            public double drogue_voltage() { return state.drogue_sense; }
+            public double main_voltage() { return state.main_sense; }
+           public boolean has_accel() { return true; } // return state.acceleration != AltosRecord.MISSING; }
         };
     }
 
@@ -68,14 +63,14 @@ class AltosDataPointReader implements Iterable<AltosDataPoint> {
                 throw new UnsupportedOperationException(); 
             }
             public boolean hasNext() {
-               if (record != null && record.state == Altos.ao_flight_landed)
+               if (state != null && state.state == Altos.ao_flight_landed)
                    return false;
                 return iter.hasNext();
             }
             public AltosDataPoint next() {
                do {
                    read_next_record();
-               } while (record.time < -1.0 && hasNext());
+               } while (state.data.time < -1.0 && hasNext());
                 return current_dp();
             }
         };
index a71cdc10c0fc97f2305951365294cc165f1d3580..2ea7cbfa7058a219e0d8e8a5b4e7d999bc051e78 100644 (file)
@@ -256,7 +256,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay {
 
        class Speed extends DescentValue {
                void show (AltosState state, int crc_errors) {
-                       double speed = state.speed;
+                       double speed = state.accel_speed;
                        if (!state.ascent)
                                speed = state.baro_speed;
                        show(AltosConvert.speed, speed);
index eac371aa2fde152f65382da3f15f8901c05ea2ce..c2a9d6e6e1a6af68e11c83dff70b8ef5b27ef365 100644 (file)
@@ -45,6 +45,12 @@ public class AltosDialog extends JDialog implements AltosUIListener {
                addWindowListener(new AltosDialogListener());
        }
 
+       public AltosDialog(Dialog dialog, String label, boolean modal) {
+               super(dialog, label, modal);
+               AltosUIPreferences.register_ui_listener(this);
+               addWindowListener(new AltosDialogListener());
+       }
+
        public AltosDialog(Frame frame, boolean modal) {
                super(frame, modal);
                AltosUIPreferences.register_ui_listener(this);
index f7a1d03eb2ad7b1bfa0f9e8f6d6bc667eef23ddc..1ba70c7efb6cebc245692caf3883297c470cf2d3 100644 (file)
@@ -197,7 +197,7 @@ public class AltosDisplayThread extends Thread {
                        if ((old_state == null || old_state.state <= Altos.ao_flight_boost) &&
                            state.state > Altos.ao_flight_boost) {
                                voice.speak("max speed: %s.",
-                                           AltosConvert.speed.say_units(state.max_speed + 0.5));
+                                           AltosConvert.speed.say_units(state.max_accel_speed + 0.5));
                                ret = true;
                        } else if ((old_state == null || old_state.state < Altos.ao_flight_drogue) &&
                                   state.state >= Altos.ao_flight_drogue) {
index a5e99749d9c12cb25cd035af04398df4b30e1442..21b467401dce8dd6ddf7463488fc34f8a265d414 100644 (file)
@@ -283,7 +283,7 @@ public class AltosEepromDownload implements Runnable {
                                if (r.cmd == Altos.AO_LOG_GPS_TIME) {
                                        year = 2000 + r.data8(14);
                                        month = r.data8(15);
-                                       day = r.data8(14);
+                                       day = r.data8(16);
                                        want_file = true;
                                }
 
index e48cb608189fa9d90f2fa2e4efbd60f21d0875fa..1653ca5708fef79092d0df7e6a1a1ddd8109f908 100644 (file)
@@ -24,7 +24,7 @@ public class AltosFlightStats {
        double          max_height;
        double          max_speed;
        double          max_acceleration;
-       double[]        state_speed = new double[Altos.ao_flight_invalid + 1];
+       double[]        state_accel_speed = new double[Altos.ao_flight_invalid + 1];
        double[]        state_baro_speed = new double[Altos.ao_flight_invalid + 1];
        double[]        state_accel = new double[Altos.ao_flight_invalid + 1];
        int[]           state_count = new int[Altos.ao_flight_invalid + 1];
@@ -123,7 +123,7 @@ public class AltosFlightStats {
                                        }
                                }
                                state_accel[state.state] += state.acceleration;
-                               state_speed[state.state] += state.speed;
+                               state_accel_speed[state.state] += state.accel_speed;
                                state_baro_speed[state.state] += state.baro_speed;
                                state_count[state.state]++;
                                if (state_start[state.state] == 0.0)
@@ -131,8 +131,8 @@ public class AltosFlightStats {
                                if (state_end[state.state] < state.time)
                                        state_end[state.state] = state.time;
                                max_height = state.max_height;
-                               if (state.max_speed != 0)
-                                       max_speed = state.max_speed;
+                               if (state.max_accel_speed != 0)
+                                       max_speed = state.max_accel_speed;
                                else
                                        max_speed = state.max_baro_speed;
                                max_acceleration = state.max_acceleration;
@@ -140,7 +140,7 @@ public class AltosFlightStats {
                }
                for (int s = Altos.ao_flight_startup; s <= Altos.ao_flight_landed; s++) {
                        if (state_count[s] > 0) {
-                               state_speed[s] /= state_count[s];
+                               state_accel_speed[s] /= state_count[s];
                                state_baro_speed[s] /= state_count[s];
                                state_accel[s] /= state_count[s];
                        }
index cb8e3d2072595d0ef0dcd6f8659fc7e7abb058e3..f59f70bab47781daf0783e747875e2ec45542152 100644 (file)
@@ -40,12 +40,7 @@ public class AltosGraphUI extends AltosFrame
         AltosGraphTime.Element speed =
                new AltosGraphTime.TimeSeries(String.format("Speed (%s)", AltosConvert.speed.show_units()), "Vertical Speed", green) { 
                 public void gotTimeData(double time, AltosDataPoint d) {
-                   double      speed;
-                   if (d.state() < Altos.ao_flight_drogue && d.has_accel()) {
-                       speed = d.accel_speed();
-                    } else {
-                       speed = d.baro_speed();
-                    }
+                   double      speed = d.speed();
                    if (speed != AltosRecord.MISSING)
                            series.add(time, AltosConvert.speed.value(speed));
                 }
index 86e02ab1ddcbe07733f6063fefc44086f6d4fdc1..11d1b0c1942bd61911482a46a7141485df8975e1 100644 (file)
@@ -114,8 +114,8 @@ public class AltosInfoTable extends JTable {
                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, "Speed", "%8.1f  m/s", state.speed());
+               info_add_row(0, "Max Speed", "%8.1f  m/s", state.max_accel_speed);
                info_add_row(0, "Temperature", "%9.2f °C", state.temperature);
                info_add_row(0, "Battery", "%9.2f V", state.battery);
                if (state.drogue_sense != AltosRecord.MISSING)
index 57339b1962fd8dd87368817eee9680e361f64721..281638bf3e92c0b14b200e58a854677e9a173b33 100644 (file)
@@ -109,7 +109,7 @@ public class AltosKML implements AltosWriter {
                AltosGPS        gps = record.gps;
                out.printf(kml_coord_fmt,
                           gps.lon, gps.lat,
-                          record.filtered_altitude(), (double) gps.alt,
+                          record.altitude(), (double) gps.alt,
                           record.time, gps.nsat);
        }
 
index 57c2d476989e9b5b50d1ff2701ea85d59a2d9ca1..5e073f7dce7184ff31ce9a7255c569f75c32e35e 100644 (file)
@@ -173,7 +173,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio
 
        class Speed extends LandedValue {
                void show (AltosState state, int crc_errors) {
-                       show(AltosConvert.speed, state.max_speed);
+                       show(AltosConvert.speed, state.max_speed());
                }
                public Speed (GridBagLayout layout, int y) {
                        super (layout, y, "Maximum Speed");
@@ -250,6 +250,9 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio
                                        } else if (filename.endsWith("telem")) {
                                                FileInputStream in = new FileInputStream(file);
                                                records = new AltosTelemetryIterable(in);
+                                       } else if (filename.endsWith("mega")) {
+                                               FileInputStream in = new FileInputStream(file);
+                                               records = new AltosEepromMegaIterable(in);
                                        } else {
                                                throw new FileNotFoundException(filename);
                                        }
index de7a86c09536d6fbd0bbe2a0ff18bb3722f62167..306a396e6fe5e21ded11331bcfc7ae6fc9ac2266 100644 (file)
@@ -24,6 +24,7 @@ altosui_JAVA = \
        AltosConfig.java \
        AltosConfigFreqUI.java \
        AltosConfigUI.java \
+       AltosConfigPyroUI.java \
        AltosConfigureUI.java \
        AltosConfigTD.java \
        AltosConfigTDUI.java \
index b8828d461d65e27e9c393b6163e035c48fbd39b7..1949e554f33abeb7ebcd8848a8d9bc4d149b4949 100644 (file)
@@ -27,7 +27,7 @@ ifneq ($(shell which sdcc),)
 endif
 
 ifneq ($(shell which avr-gcc),)
-       SUBDIRS += telescience-v0.1 telepyro-v0.1
+       SUBDIRS += telescience-v0.1 telescience-pwm telepyro-v0.1
 endif
 
 ifneq ($(shell which arm-none-eabi-gcc),)
index 3a262977512b606552211cee8b6122fcdea3a8e7..231512b2136e4993e54d9daa5a5c8f0109bfd250 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include "ao.h"
+#include "ao_pwmin.h"
 
 volatile __xdata struct ao_data        ao_data_ring[AO_DATA_RING];
 volatile __data uint8_t                ao_data_head;
@@ -93,9 +94,13 @@ ISR(ADC_vect)
        value = ADCL;
        value |= (ADCH << 8);
        ao_data_ring[ao_data_head].adc.adc[ao_adc_channel] = value;
-       if (++ao_adc_channel < NUM_ADC)
+       if (++ao_adc_channel < NUM_ADC - HAS_ICP3_COUNT)
                ao_adc_start();
        else {
+#if HAS_ICP3_COUNT
+               /* steal last adc channel for pwm input */
+               ao_data_ring[ao_data_head].adc.adc[ao_adc_channel] = ao_icp3_count;
+#endif
                ADCSRA = ADCSRA_INIT;
                ao_data_ring[ao_data_head].tick = ao_time();
                ao_data_head = ao_data_ring_next(ao_data_head);
index a14d0adecc6d7fc3d0cb3d5e0965768c15eb4818..96659aaf9c530c92fd16837b0975724da34a0918 100644 (file)
@@ -37,7 +37,9 @@
  * AVR definitions and code fragments for AltOS
  */
 
+#ifndef AO_STACK_SIZE
 #define AO_STACK_SIZE  116
+#endif
 
 /* Various definitions to make GCC look more like SDCC */
 
index bc423ff7b61404011e17f4baf1eb9f3bcca3a778..a08e87fa021660ed21c04050c1690e37e4ad1ea1 100644 (file)
@@ -32,7 +32,7 @@
        #define HAS_BEEP                0
 #endif
 
-#ifdef TELESCIENCE
+#if defined(TELESCIENCE) || defined(TELESCIENCE_PWM)
        #define LEDS_AVAILABLE          0
        #define HAS_USB                 1
        #define HAS_LOG                 1
        #define AVR_VCC_5V              0
        #define AVR_VCC_3V3             1
        #define AVR_CLOCK               8000000UL
+#ifdef TELESCIENCE_PWM
+       #define HAS_ICP3_COUNT          1
+#else
+       #define HAS_ICP3_COUNT          0
+#endif
 
        #define SPI_CS_PORT             PORTE
        #define SPI_CS_DIR              DDRE
@@ -64,6 +69,7 @@
 #endif
 
 #ifdef TELEPYRO
+       #define AO_STACK_SIZE           104
        #define LEDS_AVAILABLE          0
        #define HAS_USB                 1
        #define HAS_LOG                 0
@@ -81,6 +87,7 @@
        #define IS_COMPANION            1
        #define HAS_ORIENT              0
        #define ao_storage_pos_t        uint16_t
+       #define HAS_ICP3_COUNT          0
 
        #define AVR_VCC_5V              0
        #define AVR_VCC_3V3             1
diff --git a/src/avr/ao_pwmin.c b/src/avr/ao_pwmin.c
new file mode 100644 (file)
index 0000000..8439735
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright © 2012 Robert D. Garbee <robert@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; 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 "ao.h"
+#include "ao_pwmin.h"
+
+/* 
+ * This code implements a PWM input using ICP3.  
+ *
+ * The initial use is to measure wind speed in the ULA/Ball summer intern 
+ * project payload developed at Challenger Middle School.  
+ */
+
+volatile __data uint16_t ao_icp3_count = 0;
+volatile __data uint16_t ao_icp3_last = 0;
+
+uint16_t ao_icp3(void)
+{
+       uint16_t        v;
+       ao_arch_critical(
+               v = ao_icp3_count;
+               );
+       return v;
+}
+
+static void
+ao_pwmin_display(void) __reentrant
+{
+       /* display the most recent value */
+       printf("icp 3: %5u\n", ao_icp3());
+
+}
+
+
+ISR(TIMER3_CAPT_vect)
+{
+       
+       uint8_t lo = ICR3L; 
+       uint8_t hi = ICR3H;
+       uint16_t ao_icp3_this = (hi <<8) | lo;
+       
+       /* handling counter rollovers */
+       if (ao_icp3_this >= ao_icp3_last)
+               ao_icp3_count = ao_icp3_this - ao_icp3_last;
+       else 
+               ao_icp3_count = ao_icp3_this + (65536 - ao_icp3_last);
+       ao_icp3_last = ao_icp3_this;
+}
+
+__code struct ao_cmds ao_pwmin_cmds[] = {
+       { ao_pwmin_display,     "p\0PWM input" },
+       { 0, NULL },
+};
+
+void
+ao_pwmin_init(void)
+{
+       /* do hardware setup here */
+       TCCR3A = ((0 << WGM31) |        /* normal mode, OCR3A */
+                  (0 << WGM30));        /* normal mode, OCR3A */
+        TCCR3B = ((1 << ICNC3) |        /* input capture noise canceler on */
+                  (0 << ICES3) |        /* input capture on falling edge (don't care) */
+                  (0 << WGM33) |        /* normal mode, OCR3A */
+                  (0 << WGM32) |        /* normal mode, OCR3A */
+                  (3 << CS30));         /* clk/64 from prescaler */
+
+       
+
+        TIMSK3 = (1 << ICIE3);         /* Interrupt on input compare */
+
+               /* set the spike filter bit in the TCCR3B register */
+
+       ao_cmd_register(&ao_pwmin_cmds[0]);
+}
+
+
diff --git a/src/avr/ao_pwmin.h b/src/avr/ao_pwmin.h
new file mode 100644 (file)
index 0000000..8097d39
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright © 2012 Robert D. Garbee <robert@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; 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.
+ */
+
+void ao_pwmin_init(void);
+
+extern volatile __data uint16_t ao_icp3_count;
index eaaca444e1b504f220a89729c982f54b60804613..4eaed4207a16a56a94260bf6519162db8b3841c1 100644 (file)
@@ -197,15 +197,18 @@ struct ao_log_mega {
        uint8_t                 csum;                   /* 1 */
        uint16_t                tick;                   /* 2 */
        union {                                         /* 4 */
+               /* AO_LOG_FLIGHT */
                struct {
                        uint16_t        flight;         /* 4 */
                        int16_t         ground_accel;   /* 6 */
                        uint32_t        ground_pres;    /* 8 */
                } flight;                               /* 12 */
+               /* AO_LOG_STATE */
                struct {
                        uint16_t        state;
                        uint16_t        reason;
                } state;
+               /* AO_LOG_SENSOR */
                struct {
                        uint32_t        pres;           /* 4 */
                        uint32_t        temp;           /* 8 */
@@ -220,12 +223,14 @@ struct ao_log_mega {
                        int16_t         mag_z;          /* 28 */
                        int16_t         accel;          /* 30 */
                } sensor;       /* 32 */
+               /* AO_LOG_TEMP_VOLT */
                struct {
                        int16_t         v_batt;         /* 4 */
                        int16_t         v_pbatt;        /* 6 */
                        int16_t         n_sense;        /* 8 */
                        int16_t         sense[10];      /* 10 */
                } volt;                                 /* 30 */
+               /* AO_LOG_GPS_TIME */
                struct {
                        int32_t         latitude;       /* 4 */
                        int32_t         longitude;      /* 8 */
@@ -239,6 +244,7 @@ struct ao_log_mega {
                        uint8_t         day;            /* 20 */
                        uint8_t         pad;            /* 21 */
                } gps;  /* 22 */
+               /* AO_LOG_GPS_SAT */
                struct {
                        uint16_t        channels;       /* 4 */
                        struct {
index 4f37e9793e6cbe0c37dc424119e93445adc8a89f..aac8fda51c7219d6895fce2655ec922b01bf4b9f 100644 (file)
@@ -113,6 +113,15 @@ ao_pyro_ready(struct ao_pyro *pyro)
                        /* handled separately */
                        continue;
 
+               case ao_pyro_state_less:
+                       if (ao_flight_state < pyro->state_less)
+                               continue;
+                       break;
+               case ao_pyro_state_greater_or_equal:
+                       if (ao_flight_state >= pyro->state_greater_or_equal)
+                               continue;
+                       break;
+
                default:
                        continue;
                }
@@ -166,7 +175,7 @@ uint8_t     ao_pyro_wakeup;
 static void
 ao_pyro(void)
 {
-       uint8_t         p;
+       uint8_t         p, any_waiting;
        struct ao_pyro  *pyro;
 
        ao_config_get();
@@ -177,6 +186,7 @@ ao_pyro(void)
                ao_alarm(AO_MS_TO_TICKS(100));
                ao_sleep(&ao_pyro_wakeup);
                ao_clear_alarm();
+               any_waiting = 0;
                for (p = 0; p < AO_PYRO_NUM; p++) {
                        pyro = &ao_config.pyro[p];
 
@@ -190,6 +200,7 @@ ao_pyro(void)
                        if (!pyro->flags)
                                continue;
 
+                       any_waiting = 1;
                        /* Check pyro state to see if it shoule fire
                         */
                        if (!pyro->delay_done) {
@@ -213,7 +224,10 @@ ao_pyro(void)
 
                        ao_pyro_fire(p);
                }
+               if (!any_waiting)
+                       break;
        }
+       ao_exit();
 }
 
 __xdata struct ao_task ao_pyro_task;
@@ -257,6 +271,9 @@ const struct {
        { "t<", ao_pyro_time_less,      offsetof(struct ao_pyro, time_less), HELP("time less (s * 100)") },
        { "t>", ao_pyro_time_greater,   offsetof(struct ao_pyro, time_greater), HELP("time greater (s * 100)")  },
 
+       { "f<", ao_pyro_state_less,     offsetof(struct ao_pyro, state_less), HELP("state less") },
+       { "f>=",ao_pyro_state_greater_or_equal, offsetof(struct ao_pyro, state_greater_or_equal), HELP("state greater or equal")  },
+
        { "A", ao_pyro_ascending,       NO_VALUE, HELP("ascending") },
        { "D", ao_pyro_descending,      NO_VALUE, HELP("descending") },
 
index 5deb69d0bf3eccafef80479f28d176c43be7f51b..cde850add58eab6a2d8d2903820e6f2d44b11f9a 100644 (file)
@@ -42,6 +42,9 @@ enum ao_pyro_flag {
        ao_pyro_after_motor             = 0x00001000,
 
        ao_pyro_delay                   = 0x00002000,
+
+       ao_pyro_state_less              = 0x00004000,
+       ao_pyro_state_greater_or_equal  = 0x00008000,
 };
 
 struct ao_pyro {
@@ -52,6 +55,7 @@ struct ao_pyro {
        int16_t                 orient_less, orient_greater;
        int16_t                 time_less, time_greater;
        int16_t                 delay;
+       uint8_t                 state_less, state_greater_or_equal;
        int16_t                 motor;
        uint16_t                delay_done;
        uint8_t                 fired;
index 45b6d40e0c406ca1af29c1fadd69c5e65453bf33..d448d31854d888212378febdfa1c43d359552666 100644 (file)
@@ -16,6 +16,9 @@
  */
 
 #include "ao.h"
+#if HAS_ICP3_COUNT
+#include "ao_pwmin.h"
+#endif
 
 int
 main(void)
@@ -34,6 +37,9 @@ main(void)
        ao_usb_init();
        ao_adc_init();
        ao_log_single_init();
+#if HAS_ICP3_COUNT
+       ao_pwmin_init();
+#endif
        ao_start_scheduler();
        return 0;
 }
index 1132f7484fb7262cfd03175d3e001a4ba6d0cd27..f3011d3f0e159097c71ce8c3e3f49443c98d070b 100644 (file)
@@ -266,6 +266,7 @@ ao_clock_init(void)
        stm_rcc.csr |= (1 << STM_RCC_CSR_RMVF);
 
 
+#if DEBUG_THE_CLOCK
        /* Output SYSCLK on PA8 for measurments */
 
        stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN);
@@ -276,4 +277,5 @@ ao_clock_init(void)
 
        stm_rcc.cfgr |= (STM_RCC_CFGR_MCOPRE_DIV_1 << STM_RCC_CFGR_MCOPRE);
        stm_rcc.cfgr |= (STM_RCC_CFGR_MCOSEL_HSE << STM_RCC_CFGR_MCOSEL);
+#endif
 }
index 2ccd565f2008cf5fb9440d5a50112d9c90eef76d..6743ba66db37c9a30f2c690580dfa35611bd0d16 100644 (file)
@@ -96,7 +96,7 @@ ao_product.o: ao_product.c ao_product.h
 distclean:     clean
 
 clean:
-       rm -f $(OBJ)
+       rm -f $(OBJ) $(PROG) $(PROG).hex
        rm -f ao_product.h
 
 install:
diff --git a/src/telescience-pwm/.gitignore b/src/telescience-pwm/.gitignore
new file mode 100644 (file)
index 0000000..dfccadf
--- /dev/null
@@ -0,0 +1,2 @@
+telescience-v0.1*
+ao_product.h
diff --git a/src/telescience-pwm/Makefile b/src/telescience-pwm/Makefile
new file mode 100644 (file)
index 0000000..43d77e2
--- /dev/null
@@ -0,0 +1,116 @@
+#
+# AltOS build
+#
+#
+vpath % ..:../core:../product:../drivers:../avr
+vpath ao-make-product.5c ../util
+
+MCU=atmega32u4
+DUDECPUTYPE=m32u4
+#PROGRAMMER=stk500v2 -P usb
+PROGRAMMER=usbtiny
+LOADCMD=avrdude
+LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w:
+CC=avr-gcc
+OBJCOPY=avr-objcopy
+
+ifndef VERSION
+include ../Version
+endif
+
+INC = \
+       ao.h \
+       ao_arch.h \
+       ao_usb.h \
+       ao_pins.h \
+       ao_product.h
+
+#
+# Common AltOS sources
+#
+TELESCIENCE_STORAGE= \
+       ao_m25.c \
+       ao_spi_usart.c \
+       ao_storage.c
+
+TELESCIENCE_LOG= \
+       ao_log_single.c \
+       ao_log_telescience.c
+
+ALTOS_SRC = \
+       ao_clock.c \
+       ao_cmd.c \
+       ao_mutex.c \
+       ao_panic.c \
+       ao_product.c \
+       ao_stdio.c \
+       ao_task.c \
+       ao_timer.c \
+       ao_led.c \
+       ao_avr_stdio.c \
+       ao_romconfig.c \
+       ao_usb_avr.c \
+       ao_adc_avr.c \
+       ao_science_slave.c \
+       ao_spi_slave.c \
+       ao_pwmin.c \
+       $(TELESCIENCE_STORAGE)\
+       $(TELESCIENCE_LOG)
+
+PRODUCT=TeleScience-PWM
+MCU=atmega32u4
+PRODUCT_DEF=-DTELESCIENCE -DTELESCIENCE_PWM
+IDPRODUCT=0x0011
+CFLAGS = $(PRODUCT_DEF) -I. -I../avr -I../core -I..
+CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O3 -mcall-prologues -DAVR
+
+NICKLE=nickle
+
+PROG=telescience-pwm
+
+SRC=$(ALTOS_SRC) ao_telescience.c
+OBJ=$(SRC:.c=.o)
+
+V=0
+# The user has explicitly enabled quiet compilation.
+ifeq ($(V),0)
+quiet = @printf "  $1 $2 $@\n"; $($1)
+endif
+# Otherwise, print the full command line.
+quiet ?= $($1)
+
+all: $(PROG)
+
+CHECK=sh ../util/check-avr-mem
+
+$(PROG): Makefile $(OBJ)
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ)
+       $(call quiet,CHECK) $(PROG) || ($(RM) -f $(PROG); exit 1)
+
+$(PROG).hex: $(PROG)
+       avr-size $(PROG)
+       $(OBJCOPY) -R .eeprom -O ihex $(PROG) $@
+
+
+load: $(PROG).hex
+       $(LOADCMD) $(LOADARG)$(PROG).hex
+
+ao_product.h: ao-make-product.5c ../Version
+       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+ao_product.o: ao_product.c ao_product.h
+
+%.o : %.c $(INC)
+       $(call quiet,CC) -c $(CFLAGS) $<
+
+distclean:     clean
+
+clean:
+       rm -f *.o $(PROG) $(PROG).hex
+       rm -f ao_product.h
+
+install:
+
+uninstall:
+
+$(OBJ): ao_product.h $(INC)
index 0df9a5d79c0b9df7ca0a73be546f3029d59c1a82..7180f02d2cd4b5dba6ea2df607049e7a71fd404d 100644 (file)
@@ -39,7 +39,7 @@
 #define AO_ADC_NUM_SENSE       6
 #define HAS_MS5607             1
 #define HAS_MPU6000            1
-#define HAS_MMA655X            0
+#define HAS_MMA655X            1
 
 struct ao_adc {
        int16_t                 sense[AO_ADC_NUM_SENSE];
@@ -622,6 +622,9 @@ ao_sleep(void *wchan)
                                        ao_data_static.mpu6000.gyro_x = int16(bytes, 14);
                                        ao_data_static.mpu6000.gyro_y = -int16(bytes, 16);
                                        ao_data_static.mpu6000.gyro_z = int16(bytes, 18);
+#if HAS_MMA655X
+                                       ao_data_static.mma655x = int16(bytes, 26);
+#endif
                                        if (ao_records_read == 0)
                                                ao_ground_mpu6000 = ao_data_static.mpu6000;
                                        else if (ao_records_read < 10) {
diff --git a/src/test/run-mm b/src/test/run-mm
new file mode 100755 (executable)
index 0000000..6f3d97a
--- /dev/null
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+DIR=~/misc/rockets/flights
+
+for i in "$@"; do
+case "$i" in
+    */*)
+    file="$i"
+    ;;
+    *)
+    file="$DIR/$i"
+    ;;
+esac
+./ao_flight_test_mm "$file" > run-out.mm
+
+#./ao_flight_test_accel "$file" > run-out.accel
+#"run-out.accel" using 1:9 with lines lt 4 axes x1y1 title "accel height",\
+#"run-out.accel" using 1:11 with lines lt 4 axes x1y2 title "accel speed",\
+#"run-out.accel" using 1:13 with lines lt 4 axes x1y2 title "accel accel",\
+#"run-out.accel" using 1:15 with lines lt 4 axes x1y1 title "accel drogue",\
+#"run-out.accel" using 1:17 with lines lt 4 axes x1y1 title "accel main",\
+#
+
+gnuplot << EOF
+set ylabel "altitude (m)"
+set y2label "velocity (m/s), acceleration(m/s²)"
+set xlabel "time (s)"
+set xtics border out nomirror
+set ytics border out nomirror
+set y2tics border out nomirror
+set title "$i"
+plot "run-out.mm" using 1:3 with lines lw 2 lt 1 axes x1y1 title "raw height",\
+"run-out.mm" using 1:5 with lines lw 2 lt 1 axes x1y2 title "raw accel",\
+"run-out.mm" using 1:21 with lines lt 2 axes x1y1 title "mm height",\
+"run-out.mm" using 1:23 with lines lt 2 axes x1y2 title "mm speed",\
+"run-out.mm" using 1:25 with lines lt 2 axes x1y2 title "mm accel",\
+"run-out.mm" using 1:29 with lines lt 2 axes x1y1 title "mm drogue",\
+"run-out.mm" using 1:31 with lines lt 2 axes x1y1 title "mm main"
+pause mouse close
+EOF
+done
\ No newline at end of file
old mode 100644 (file)
new mode 100755 (executable)