summaryrefslogtreecommitdiff
path: root/altoslib
diff options
context:
space:
mode:
Diffstat (limited to 'altoslib')
-rw-r--r--altoslib/AltosAccel.java22
-rw-r--r--altoslib/AltosCRCException.java2
-rw-r--r--altoslib/AltosCompanion.java (renamed from altoslib/AltosRecordCompanion.java)6
-rw-r--r--altoslib/AltosConfigData.java6
-rw-r--r--altoslib/AltosConfigValues.java2
-rw-r--r--altoslib/AltosConvert.java58
-rw-r--r--altoslib/AltosDebug.java28
-rw-r--r--altoslib/AltosDistance.java28
-rw-r--r--altoslib/AltosEeprom.java127
-rw-r--r--altoslib/AltosEepromChunk.java30
-rw-r--r--altoslib/AltosEepromDownload.java261
-rw-r--r--altoslib/AltosEepromFile.java123
-rw-r--r--altoslib/AltosEepromHeader.java278
-rw-r--r--altoslib/AltosEepromIterable.java462
-rw-r--r--altoslib/AltosEepromList.java117
-rw-r--r--altoslib/AltosEepromLog.java6
-rw-r--r--altoslib/AltosEepromMega.java267
-rw-r--r--altoslib/AltosEepromMegaIterable.java367
-rw-r--r--altoslib/AltosEepromMetrum2.java177
-rw-r--r--altoslib/AltosEepromMini.java102
-rw-r--r--altoslib/AltosEepromMonitor.java45
-rw-r--r--altoslib/AltosEepromRecord.java135
-rw-r--r--altoslib/AltosEepromTM.java205
-rw-r--r--altoslib/AltosEepromTeleScience.java55
-rw-r--r--altoslib/AltosEepromTm.java159
-rw-r--r--altoslib/AltosFile.java40
-rw-r--r--altoslib/AltosFlash.java8
-rw-r--r--altoslib/AltosFlashListener.java2
-rw-r--r--altoslib/AltosFlightReader.java8
-rw-r--r--altoslib/AltosFrequency.java2
-rw-r--r--altoslib/AltosGPS.java181
-rw-r--r--altoslib/AltosGPSQuery.java97
-rw-r--r--altoslib/AltosGPSSat.java2
-rw-r--r--altoslib/AltosGreatCircle.java14
-rw-r--r--altoslib/AltosHeight.java22
-rw-r--r--altoslib/AltosHexfile.java90
-rw-r--r--altoslib/AltosHexsym.java (renamed from altoslib/AltosRecordNone.java)28
-rw-r--r--altoslib/AltosIMU.java70
-rw-r--r--altoslib/AltosIMUQuery.java46
-rw-r--r--altoslib/AltosIdle.java39
-rw-r--r--altoslib/AltosIdleFetch.java151
-rw-r--r--altoslib/AltosIdleMonitor.java126
-rw-r--r--altoslib/AltosIdleMonitorListener.java2
-rw-r--r--altoslib/AltosIgnite.java17
-rw-r--r--altoslib/AltosLib.java73
-rw-r--r--altoslib/AltosLine.java2
-rw-r--r--altoslib/AltosLink.java130
-rw-r--r--altoslib/AltosListenerState.java4
-rw-r--r--altoslib/AltosLog.java42
-rw-r--r--altoslib/AltosMag.java63
-rw-r--r--altoslib/AltosMma655x.java68
-rw-r--r--altoslib/AltosMs5607.java48
-rw-r--r--altoslib/AltosNoSymbol.java24
-rw-r--r--altoslib/AltosOrderedMegaRecord.java52
-rw-r--r--altoslib/AltosOrderedRecord.java63
-rw-r--r--altoslib/AltosParse.java2
-rw-r--r--altoslib/AltosPreferences.java2
-rw-r--r--altoslib/AltosPreferencesBackend.java2
-rw-r--r--altoslib/AltosProgrammer.java33
-rw-r--r--altoslib/AltosPyro.java70
-rw-r--r--altoslib/AltosRecord.java171
-rw-r--r--altoslib/AltosRecordMM.java178
-rw-r--r--altoslib/AltosRecordTM.java186
-rw-r--r--altoslib/AltosReplayReader.java9
-rw-r--r--altoslib/AltosRomconfig.java181
-rw-r--r--altoslib/AltosSelfFlash.java189
-rw-r--r--altoslib/AltosSensorEMini.java69
-rw-r--r--altoslib/AltosSensorMM.java2
-rw-r--r--altoslib/AltosSensorMega.java108
-rw-r--r--altoslib/AltosSensorMetrum.java65
-rw-r--r--altoslib/AltosSensorTM.java35
-rw-r--r--altoslib/AltosSensorTMini.java69
-rw-r--r--altoslib/AltosSpeed.java22
-rw-r--r--altoslib/AltosState.java1155
-rw-r--r--altoslib/AltosStateIterable.java (renamed from altoslib/AltosRecordIterable.java)16
-rw-r--r--altoslib/AltosStateUpdate.java22
-rw-r--r--altoslib/AltosTelemetry.java319
-rw-r--r--altoslib/AltosTelemetryConfiguration.java (renamed from altoslib/AltosTelemetryRecordConfiguration.java)31
-rw-r--r--altoslib/AltosTelemetryFile.java96
-rw-r--r--altoslib/AltosTelemetryIterable.java124
-rw-r--r--altoslib/AltosTelemetryLegacy.java (renamed from altoslib/AltosTelemetryRecordLegacy.java)301
-rw-r--r--altoslib/AltosTelemetryLocation.java (renamed from altoslib/AltosTelemetryRecordLocation.java)57
-rw-r--r--altoslib/AltosTelemetryMap.java2
-rw-r--r--altoslib/AltosTelemetryMegaData.java (renamed from altoslib/AltosTelemetryRecordMegaData.java)51
-rw-r--r--altoslib/AltosTelemetryMegaSensor.java (renamed from altoslib/AltosTelemetryRecordMegaSensor.java)50
-rw-r--r--altoslib/AltosTelemetryMetrumData.java (renamed from altoslib/AltosTelemetryRecordGeneral.java)35
-rw-r--r--altoslib/AltosTelemetryMetrumSensor.java69
-rw-r--r--altoslib/AltosTelemetryMini.java72
-rw-r--r--altoslib/AltosTelemetryRaw.java (renamed from altoslib/AltosMs5607Query.java)24
-rw-r--r--altoslib/AltosTelemetryReader.java38
-rw-r--r--altoslib/AltosTelemetryRecord.java135
-rw-r--r--altoslib/AltosTelemetryRecordCompanion.java52
-rw-r--r--altoslib/AltosTelemetryRecordRaw.java81
-rw-r--r--altoslib/AltosTelemetrySatellite.java (renamed from altoslib/AltosTelemetryRecordSatellite.java)22
-rw-r--r--altoslib/AltosTelemetrySensor.java (renamed from altoslib/AltosTelemetryRecordSensor.java)62
-rw-r--r--altoslib/AltosTelemetryStandard.java109
-rw-r--r--altoslib/AltosTemperature.java22
-rw-r--r--altoslib/AltosUnits.java79
-rw-r--r--altoslib/AltosUnitsListener.java2
-rw-r--r--altoslib/Makefile.am79
100 files changed, 5683 insertions, 3397 deletions
diff --git a/altoslib/AltosAccel.java b/altoslib/AltosAccel.java
index d02b3238..b838d30b 100644
--- a/altoslib/AltosAccel.java
+++ b/altoslib/AltosAccel.java
@@ -15,29 +15,35 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
public class AltosAccel extends AltosUnits {
- public double value(double v) {
- if (AltosConvert.imperial_units)
+ public double value(double v, boolean imperial_units) {
+ if (imperial_units)
return AltosConvert.meters_to_feet(v);
return v;
}
- public String show_units() {
- if (AltosConvert.imperial_units)
+ public double inverse(double v, boolean imperial_units) {
+ if (imperial_units)
+ return AltosConvert.feet_to_meters(v);
+ return v;
+ }
+
+ public String show_units(boolean imperial_units) {
+ if (imperial_units)
return "ft/s²";
return "m/s²";
}
- public String say_units() {
- if (AltosConvert.imperial_units)
+ public String say_units(boolean imperial_units) {
+ if (imperial_units)
return "feet per second squared";
return "meters per second squared";
}
- public int show_fraction(int width) {
+ public int show_fraction(int width, boolean imperial_units) {
return width / 9;
}
} \ No newline at end of file
diff --git a/altoslib/AltosCRCException.java b/altoslib/AltosCRCException.java
index 76e79add..be2ec4fe 100644
--- a/altoslib/AltosCRCException.java
+++ b/altoslib/AltosCRCException.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
public class AltosCRCException extends Exception {
public int rssi;
diff --git a/altoslib/AltosRecordCompanion.java b/altoslib/AltosCompanion.java
index b153fb5b..57bb21af 100644
--- a/altoslib/AltosRecordCompanion.java
+++ b/altoslib/AltosCompanion.java
@@ -15,9 +15,9 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
-public class AltosRecordCompanion {
+public class AltosCompanion {
public final static int board_id_telescience = 0x0a;
public final static int MAX_CHANNELS = 12;
@@ -27,7 +27,7 @@ public class AltosRecordCompanion {
public int channels;
public int[] companion_data;
- public AltosRecordCompanion(int in_channels) {
+ public AltosCompanion(int in_channels) {
channels = in_channels;
if (channels < 0)
channels = 0;
diff --git a/altoslib/AltosConfigData.java b/altoslib/AltosConfigData.java
index 2ca5a7a5..1c3085bd 100644
--- a/altoslib/AltosConfigData.java
+++ b/altoslib/AltosConfigData.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
import java.util.*;
import java.text.*;
@@ -336,6 +336,10 @@ public class AltosConfigData implements Iterable<String> {
public double frequency() {
int channel = radio_channel;
int setting = radio_setting;
+
+ if (radio_frequency < 0 && channel < 0 && setting < 0)
+ return -1;
+
if (channel < 0)
channel = 0;
if (setting < 0)
diff --git a/altoslib/AltosConfigValues.java b/altoslib/AltosConfigValues.java
index 027d10f4..fd5584c2 100644
--- a/altoslib/AltosConfigValues.java
+++ b/altoslib/AltosConfigValues.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
public interface AltosConfigValues {
/* set and get all of the dialog values */
diff --git a/altoslib/AltosConvert.java b/altoslib/AltosConvert.java
index a42b36c4..8d0b74dd 100644
--- a/altoslib/AltosConvert.java
+++ b/altoslib/AltosConvert.java
@@ -18,7 +18,7 @@
/*
* Sensor data conversion functions
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
public class AltosConvert {
/*
@@ -190,6 +190,46 @@ public class AltosConvert {
return ignite / 32767 * 15.0;
}
+ public static double
+ barometer_to_pressure(double count)
+ {
+ return ((count / 16.0) / 2047.0 + 0.095) / 0.009 * 1000.0;
+ }
+
+ static double
+ thermometer_to_temperature(double thermo)
+ {
+ return (thermo - 19791.268) / 32728.0 * 1.25 / 0.00247;
+ }
+
+ static double mega_adc(int raw) {
+ return raw / 4095.0;
+ }
+
+ static public double mega_battery_voltage(int v_batt) {
+ if (v_batt != AltosLib.MISSING)
+ return 3.3 * mega_adc(v_batt) * (15.0 + 27.0) / 27.0;
+ return AltosLib.MISSING;
+ }
+
+ static double mega_pyro_voltage(int raw) {
+ if (raw != AltosLib.MISSING)
+ return 3.3 * mega_adc(raw) * (100.0 + 27.0) / 27.0;
+ return AltosLib.MISSING;
+ }
+
+ static double tele_mini_voltage(int sensor) {
+ double supply = 3.3;
+
+ return sensor / 32767.0 * supply * 127/27;
+ }
+
+ static double easy_mini_voltage(int sensor) {
+ double supply = 3.0;
+
+ return sensor / 32767.0 * supply * 127/27;
+ }
+
public static double radio_to_frequency(int freq, int setting, int cal, int channel) {
double f;
@@ -242,14 +282,26 @@ public class AltosConvert {
return meters * (100 / (2.54 * 12));
}
+ public static double feet_to_meters(double feet) {
+ return feet * 12 * 2.54 / 100.0;
+ }
+
public static double meters_to_miles(double meters) {
return meters_to_feet(meters) / 5280;
}
+ public static double miles_to_meters(double miles) {
+ return feet_to_meters(miles * 5280);
+ }
+
public static double meters_to_mph(double mps) {
return meters_to_miles(mps) * 3600;
}
+ public static double mph_to_meters(double mps) {
+ return miles_to_meters(mps) / 3600;
+ }
+
public static double meters_to_mach(double meters) {
return meters / 343; /* something close to mach at usual rocket sites */
}
@@ -262,6 +314,10 @@ public class AltosConvert {
return c * 9/5 + 32;
}
+ public static double f_to_c(double c) {
+ return (c - 32) * 5/9;
+ }
+
public static boolean imperial_units = false;
public static AltosDistance distance = new AltosDistance();
diff --git a/altoslib/AltosDebug.java b/altoslib/AltosDebug.java
index 4d8e3ae7..fb11d39a 100644
--- a/altoslib/AltosDebug.java
+++ b/altoslib/AltosDebug.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
import java.io.*;
@@ -56,13 +56,10 @@ public class AltosDebug {
boolean debug_mode;
- void ensure_debug_mode() {
+ void ensure_debug_mode() throws InterruptedException {
if (!debug_mode) {
link.printf("D\n");
- try {
- link.flush_input();
- } catch (InterruptedException ie) {
- }
+ link.flush_input();
debug_mode = true;
}
}
@@ -81,13 +78,16 @@ public class AltosDebug {
}
public void close() {
- link.close();
+ try {
+ link.close();
+ } catch (InterruptedException ie) {
+ }
}
/*
* Write target memory
*/
- public void write_memory(int address, byte[] bytes, int start, int len) {
+ public void write_memory(int address, byte[] bytes, int start, int len) throws InterruptedException {
ensure_debug_mode();
// dump_memory("write_memory", address, bytes, start, len);
link.printf("O %x %x\n", len, address);
@@ -95,7 +95,7 @@ public class AltosDebug {
link.printf("%02x", bytes[start + i]);
}
- public void write_memory(int address, byte[] bytes) {
+ public void write_memory(int address, byte[] bytes) throws InterruptedException {
write_memory(address, bytes, 0, bytes.length);
}
@@ -132,7 +132,7 @@ public class AltosDebug {
/*
* Write raw bytes to the debug link using the 'P' command
*/
- public void write_bytes(byte[] bytes) throws IOException {
+ public void write_bytes(byte[] bytes) throws IOException, InterruptedException {
int i = 0;
ensure_debug_mode();
while (i < bytes.length) {
@@ -147,7 +147,7 @@ public class AltosDebug {
}
}
- public void write_byte(byte b) throws IOException {
+ public void write_byte(byte b) throws IOException, InterruptedException {
byte[] bytes = { b };
write_bytes(bytes);
}
@@ -257,12 +257,12 @@ public class AltosDebug {
return true;
}
- public AltosRomconfig romconfig() {
+ public AltosRomconfig romconfig() throws InterruptedException {
try {
byte[] bytes = read_memory(0xa0, 10);
- return new AltosRomconfig(bytes, 0);
+ AltosHexfile hexfile = new AltosHexfile (bytes, 0xa0);
+ return new AltosRomconfig(hexfile);
} catch (IOException ie) {
- } catch (InterruptedException ie) {
}
return new AltosRomconfig();
}
diff --git a/altoslib/AltosDistance.java b/altoslib/AltosDistance.java
index 25028ac7..8d359feb 100644
--- a/altoslib/AltosDistance.java
+++ b/altoslib/AltosDistance.java
@@ -15,36 +15,42 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
public class AltosDistance extends AltosUnits {
- public double value(double v) {
- if (AltosConvert.imperial_units)
+ public double value(double v, boolean imperial_units) {
+ if (imperial_units)
return AltosConvert.meters_to_miles(v);
return v;
}
- public String show_units() {
- if (AltosConvert.imperial_units)
+ public double inverse(double v, boolean imperial_units) {
+ if (imperial_units)
+ return AltosConvert.miles_to_meters(v);
+ return v;
+ }
+
+ public String show_units(boolean imperial_units) {
+ if (imperial_units)
return "miles";
return "m";
}
- public String say_units() {
- if (AltosConvert.imperial_units)
+ public String say_units(boolean imperial_units) {
+ if (imperial_units)
return "miles";
return "meters";
}
- public int show_fraction(int width) {
- if (AltosConvert.imperial_units)
+ public int show_fraction(int width, boolean imperial_units) {
+ if (imperial_units)
return width / 3;
return width / 9;
}
- public int say_fraction() {
- if (AltosConvert.imperial_units)
+ public int say_fraction(boolean imperial_units) {
+ if (imperial_units)
return 1;
return 0;
}
diff --git a/altoslib/AltosEeprom.java b/altoslib/AltosEeprom.java
new file mode 100644
index 00000000..dd5993c7
--- /dev/null
+++ b/altoslib/AltosEeprom.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright © 2013 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_2;
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
+public abstract class AltosEeprom implements AltosStateUpdate {
+ public int cmd;
+ public int tick;
+ public int data8[];
+ public boolean valid;
+
+ public int data8(int i) {
+ return data8[i];
+ }
+
+ public int data16(int i) {
+ return ((data8[i] | (data8[i+1] << 8)) << 16) >> 16;
+ }
+
+ public int data24(int i) {
+ return data8[i] | (data8[i+1] << 8) | (data8[i+2] << 16);
+ }
+
+ public int data32(int i) {
+ return data8[i] | (data8[i+1] << 8) | (data8[i+2] << 16) | (data8[i+3] << 24);
+ }
+
+ public final static int header_length = 4;
+
+ public abstract int record_length();
+
+ public void update_state(AltosState state) {
+ if (cmd == AltosLib.AO_LOG_FLIGHT)
+ state.set_boost_tick(tick);
+ else
+ state.set_tick(tick);
+ }
+
+ public void write(PrintStream out) {
+ out.printf("%c %04x", cmd, tick);
+ if (data8 != null) {
+ for (int i = 0; i < data8.length; i++)
+ out.printf (" %02x", data8[i]);
+ }
+ out.printf ("\n");
+ }
+
+ public String string() {
+ String s;
+
+ s = String.format("%c %04x", cmd, tick);
+ if (data8 != null) {
+ for (int i = 0; i < data8.length; i++) {
+ String d = String.format(" %02x", data8[i]);
+ s = s.concat(d);
+ }
+ }
+ s = s.concat("\n");
+ return s;
+ }
+
+ void parse_chunk(AltosEepromChunk chunk, int start) throws ParseException {
+ cmd = chunk.data(start);
+
+ int data_length = record_length() - header_length;
+
+ valid = !chunk.erased(start, record_length());
+ if (valid) {
+ if (AltosConvert.checksum(chunk.data, start, record_length()) != 0)
+ throw new ParseException(String.format("invalid checksum at 0x%x",
+ chunk.address + start), 0);
+ } else {
+ cmd = AltosLib.AO_LOG_INVALID;
+ }
+
+ tick = chunk.data16(start+2);
+
+ data8 = new int[data_length];
+ for (int i = 0; i < data_length; i++)
+ data8[i] = chunk.data(start + header_length + i);
+ }
+
+ void parse_string(String line) {
+ valid = false;
+ tick = 0;
+ cmd = AltosLib.AO_LOG_INVALID;
+
+ int data_length = record_length() - header_length;
+
+ if (line == null)
+ return;
+ try {
+ String[] tokens = line.split("\\s+");
+
+ if (tokens[0].length() == 1) {
+ if (tokens.length == 2 + data_length) {
+ cmd = tokens[0].codePointAt(0);
+ tick = Integer.parseInt(tokens[1],16);
+ valid = true;
+ data8 = new int[data_length];
+
+ for (int i = 0; i < data_length; i++)
+ data8[i] = Integer.parseInt(tokens[2 + i],16);
+ }
+ }
+ } catch (NumberFormatException ne) {
+ }
+ }
+}
diff --git a/altoslib/AltosEepromChunk.java b/altoslib/AltosEepromChunk.java
index b1bba3bb..c03fa931 100644
--- a/altoslib/AltosEepromChunk.java
+++ b/altoslib/AltosEepromChunk.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
import java.text.*;
import java.util.concurrent.*;
@@ -62,6 +62,34 @@ public class AltosEepromChunk {
return true;
}
+ public AltosEeprom eeprom(int offset, int log_format, AltosState state) throws ParseException {
+ AltosEeprom eeprom = null;
+ switch (log_format) {
+ case AltosLib.AO_LOG_FORMAT_FULL:
+ eeprom = new AltosEepromTM(this, offset);
+ break;
+ case AltosLib.AO_LOG_FORMAT_TINY:
+ eeprom = new AltosEepromTm(this, offset, state);
+ break;
+ case AltosLib.AO_LOG_FORMAT_TELEMETRY:
+ case AltosLib.AO_LOG_FORMAT_TELESCIENCE:
+ break;
+ case AltosLib.AO_LOG_FORMAT_TELEMEGA:
+ eeprom = new AltosEepromMega(this, offset);
+ break;
+ case AltosLib.AO_LOG_FORMAT_TELEMETRUM:
+ eeprom = new AltosEepromMetrum2(this, offset);
+ break;
+ case AltosLib.AO_LOG_FORMAT_TELEMINI:
+ case AltosLib.AO_LOG_FORMAT_EASYMINI:
+ eeprom = new AltosEepromMini(this, offset);
+ break;
+ default:
+ throw new ParseException("unknown eeprom format " + log_format, 0);
+ }
+ return eeprom;
+ }
+
public AltosEepromChunk(AltosLink link, int block, boolean flush)
throws TimeoutException, InterruptedException {
diff --git a/altoslib/AltosEepromDownload.java b/altoslib/AltosEepromDownload.java
new file mode 100644
index 00000000..1b043167
--- /dev/null
+++ b/altoslib/AltosEepromDownload.java
@@ -0,0 +1,261 @@
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altoslib_2;
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.util.concurrent.*;
+
+public class AltosEepromDownload implements Runnable {
+
+ AltosLink link;
+ boolean remote;
+ Thread eeprom_thread;
+ AltosEepromMonitor monitor;
+
+ boolean want_file;
+ FileWriter eeprom_file;
+ LinkedList<String> eeprom_pending;
+
+ AltosEepromList flights;
+ boolean success;
+ ParseException parse_exception;
+ AltosState state;
+
+ private void FlushPending() throws IOException {
+ for (String s : flights.config_data) {
+ eeprom_file.write(s);
+ eeprom_file.write('\n');
+ }
+
+ for (String s : eeprom_pending)
+ eeprom_file.write(s);
+ }
+
+ private void CheckFile(boolean force) throws IOException {
+ if (eeprom_file != null)
+ return;
+ if (force || (state.flight != 0 && want_file)) {
+ AltosFile eeprom_name;
+ AltosGPS gps = state.gps;
+
+ if (gps != null &&
+ gps.year != AltosLib.MISSING &&
+ gps.month != AltosLib.MISSING &&
+ gps.day != AltosLib.MISSING)
+ {
+ eeprom_name = new AltosFile(gps.year, gps.month, gps.day,
+ state.serial, state.flight, "eeprom");
+ } else
+ eeprom_name = new AltosFile(state.serial, state.flight, "eeprom");
+
+ eeprom_file = new FileWriter(eeprom_name);
+ if (eeprom_file != null) {
+ monitor.set_filename(eeprom_name.getName());
+ FlushPending();
+ eeprom_pending = null;
+ }
+ }
+ }
+
+ boolean done;
+ boolean start;
+
+ void LogEeprom(AltosEeprom r) throws IOException {
+ if (r.cmd != AltosLib.AO_LOG_INVALID) {
+ String line = r.string();
+ if (eeprom_file != null)
+ eeprom_file.write(line);
+ else
+ eeprom_pending.add(line);
+ }
+ }
+
+ void CaptureEeprom(AltosEepromChunk eechunk, int log_format) throws IOException, ParseException {
+ boolean any_valid = false;
+ boolean got_flight = false;
+
+ int record_length = 8;
+
+ state.set_serial(flights.config_data.serial);
+ monitor.set_serial(flights.config_data.serial);
+
+ for (int i = 0; i < AltosEepromChunk.chunk_size && !done; i += record_length) {
+ AltosEeprom r = eechunk.eeprom(i, log_format, state);
+
+ if (r == null)
+ continue;
+
+ record_length = r.record_length();
+
+ r.update_state(state);
+
+ if (!got_flight && state.flight != AltosLib.MISSING)
+ monitor.set_flight(state.flight);
+
+ /* Monitor state transitions to update display */
+ if (state.state != AltosLib.ao_flight_invalid &&
+ state.state <= AltosLib.ao_flight_landed)
+ {
+ if (state.state > AltosLib.ao_flight_pad)
+ want_file = true;
+ if (state.state == AltosLib.ao_flight_landed)
+ done = true;
+ }
+
+ if (state.gps != null)
+ want_file = true;
+
+ if (r.valid) {
+ any_valid = true;
+ LogEeprom(r);
+ }
+ }
+ if (!any_valid)
+ done = true;
+
+ CheckFile(false);
+ }
+
+ void CaptureLog(AltosEepromLog log) throws IOException, InterruptedException, TimeoutException, ParseException {
+ int block, state_block = 0;
+ int log_format = flights.config_data.log_format;
+
+ state = new AltosState();
+
+ done = false;
+ start = true;
+
+ if (flights.config_data.serial < 0)
+ throw new IOException("no serial number found");
+
+ /* Reset per-capture variables */
+ want_file = false;
+ eeprom_file = null;
+ eeprom_pending = new LinkedList<String>();
+
+ /* Set serial number in the monitor dialog window */
+ /* Now scan the eeprom, reading blocks of data and converting to .eeprom file form */
+
+ state_block = log.start_block;
+ for (block = log.start_block; !done && block < log.end_block; block++) {
+ monitor.set_value(state.state_name(),
+ state.state,
+ block - state_block,
+ block - log.start_block);
+
+ AltosEepromChunk eechunk = new AltosEepromChunk(link, block, block == log.start_block);
+
+ /*
+ * Guess what kind of data is there if the device
+ * didn't tell us
+ */
+
+ if (log_format == AltosLib.AO_LOG_FORMAT_UNKNOWN) {
+ if (block == log.start_block) {
+ if (eechunk.data(0) == AltosLib.AO_LOG_FLIGHT)
+ log_format = AltosLib.AO_LOG_FORMAT_FULL;
+ else
+ log_format = AltosLib.AO_LOG_FORMAT_TINY;
+ }
+ }
+
+ CaptureEeprom (eechunk, log_format);
+ }
+ CheckFile(true);
+ if (eeprom_file != null) {
+ eeprom_file.flush();
+ eeprom_file.close();
+ }
+ }
+
+ public void run () {
+ try {
+ boolean failed = false;
+ if (remote)
+ link.start_remote();
+
+ for (AltosEepromLog log : flights) {
+ parse_exception = null;
+ if (log.selected) {
+ monitor.reset();
+ try {
+ CaptureLog(log);
+ } catch (ParseException e) {
+ parse_exception = e;
+ }
+ }
+ if (parse_exception != null) {
+ failed = true;
+ monitor.show_message(String.format("Flight %d download error\n%s\nValid log data saved",
+ log.flight,
+ parse_exception.getMessage()),
+ link.name,
+ AltosEepromMonitor.WARNING_MESSAGE);
+ }
+ }
+ success = !failed;
+ } catch (IOException ee) {
+ monitor.show_message(ee.getLocalizedMessage(),
+ link.name,
+ AltosEepromMonitor.ERROR_MESSAGE);
+ } catch (InterruptedException ie) {
+ monitor.show_message(String.format("Connection to \"%s\" interrupted",
+ link.name),
+ "Connection Interrupted",
+ AltosEepromMonitor.ERROR_MESSAGE);
+ } catch (TimeoutException te) {
+ monitor.show_message(String.format("Connection to \"%s\" failed",
+ link.name),
+ "Connection Failed",
+ AltosEepromMonitor.ERROR_MESSAGE);
+ } finally {
+ if (remote) {
+ try {
+ link.stop_remote();
+ } catch (InterruptedException ie) {
+ }
+ }
+ link.flush_output();
+ }
+ monitor.done(success);
+ }
+
+ public void start() {
+ eeprom_thread = new Thread(this);
+ monitor.set_thread(eeprom_thread);
+ eeprom_thread.start();
+ }
+
+ public AltosEepromDownload(AltosEepromMonitor given_monitor,
+ AltosLink given_link,
+ boolean given_remote,
+ AltosEepromList given_flights) {
+
+ monitor = given_monitor;
+ link = given_link;
+ remote = given_remote;
+ flights = given_flights;
+ success = false;
+
+ monitor.set_states(AltosLib.ao_flight_boost, AltosLib.ao_flight_landed);
+
+ monitor.start();
+ }
+}
diff --git a/altoslib/AltosEepromFile.java b/altoslib/AltosEepromFile.java
new file mode 100644
index 00000000..60ab2573
--- /dev/null
+++ b/altoslib/AltosEepromFile.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright © 2013 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_2;
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
+class AltosEepromIterator implements Iterator<AltosState> {
+ AltosState state;
+ Iterator<AltosEeprom> body;
+ AltosEeprom next;
+ boolean seen;
+
+ public boolean hasNext() {
+ return !seen || body.hasNext();
+ }
+
+ public AltosState next() {
+ if (seen) {
+ AltosState n = state.clone();
+ AltosEeprom e = body.next();
+
+ e.update_state(n);
+ state = n;
+ }
+ seen = true;
+ return state;
+ }
+
+ public void remove () {
+ }
+
+ public AltosEepromIterator(AltosState start, Iterator<AltosEeprom> body) {
+ this.state = start;
+ this.body = body;
+ this.seen = false;
+ }
+}
+
+public class AltosEepromFile extends AltosStateIterable {
+
+ AltosEepromIterable headers;
+ AltosEepromIterable body;
+ AltosState start;
+
+ public void write_comments(PrintStream out) {
+ headers.write(out);
+ }
+
+ public void write(PrintStream out) {
+ headers.write(out);
+ body.write(out);
+ }
+
+ public AltosEepromFile(FileInputStream input) {
+ headers = new AltosEepromIterable(AltosEepromHeader.read(input));
+
+ start = headers.state();
+ start.set_state(AltosLib.ao_flight_pad);
+
+ switch (start.log_format) {
+ case AltosLib.AO_LOG_FORMAT_FULL:
+ body = new AltosEepromIterable(AltosEepromTM.read(input));
+ break;
+ case AltosLib.AO_LOG_FORMAT_TINY:
+ body = new AltosEepromIterable(AltosEepromTm.read(input));
+ break;
+ case AltosLib.AO_LOG_FORMAT_TELEMETRY:
+ case AltosLib.AO_LOG_FORMAT_TELESCIENCE:
+ case AltosLib.AO_LOG_FORMAT_TELEMEGA:
+ body = new AltosEepromIterable(AltosEepromMega.read(input));
+ break;
+ case AltosLib.AO_LOG_FORMAT_TELEMETRUM:
+ body = new AltosEepromIterable(AltosEepromMetrum2.read(input));
+ break;
+ case AltosLib.AO_LOG_FORMAT_TELEMINI:
+ case AltosLib.AO_LOG_FORMAT_EASYMINI:
+ body = new AltosEepromIterable(AltosEepromMini.read(input));
+ break;
+ default:
+ body = new AltosEepromIterable(new LinkedList<AltosEeprom>());
+ break;
+ }
+
+ /* Find boost tick */
+ AltosState state = start.clone();
+ for (AltosEeprom eeprom : body) {
+ eeprom.update_state(state);
+ state.finish_update();
+ if (state.state >= AltosLib.ao_flight_boost) {
+ start.set_boost_tick(state.tick);
+ break;
+ }
+ }
+ }
+
+ public Iterator<AltosState> iterator() {
+ AltosState state = start.clone();
+ Iterator<AltosEeprom> i = body.iterator();
+
+ while (i.hasNext() && !state.valid()) {
+ i.next().update_state(state);
+ state.finish_update();
+ }
+ return new AltosEepromIterator(state, i);
+ }
+} \ No newline at end of file
diff --git a/altoslib/AltosEepromHeader.java b/altoslib/AltosEepromHeader.java
new file mode 100644
index 00000000..0aeb78dd
--- /dev/null
+++ b/altoslib/AltosEepromHeader.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright © 2013 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_2;
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
+public class AltosEepromHeader extends AltosEeprom {
+
+ public int cmd;
+ public String data;
+ public int config_a, config_b;
+ public boolean last;
+ public boolean valid;
+
+ public int record_length () { return 0; }
+
+ /* XXX pull rest of config data to state */
+ public void update_state(AltosState state) {
+ switch (cmd) {
+ case AltosLib.AO_LOG_CONFIG_VERSION:
+ break;
+ case AltosLib.AO_LOG_MAIN_DEPLOY:
+ break;
+ case AltosLib.AO_LOG_APOGEE_DELAY:
+ break;
+ case AltosLib.AO_LOG_RADIO_CHANNEL:
+ break;
+ case AltosLib.AO_LOG_CALLSIGN:
+ state.set_callsign(data);
+ break;
+ case AltosLib.AO_LOG_ACCEL_CAL:
+ state.set_accel_g(config_a, config_b);
+ break;
+ case AltosLib.AO_LOG_RADIO_CAL:
+ break;
+ case AltosLib.AO_LOG_MANUFACTURER:
+ break;
+ case AltosLib.AO_LOG_PRODUCT:
+ break;
+ case AltosLib.AO_LOG_LOG_FORMAT:
+ state.log_format = config_a;
+ break;
+ case AltosLib.AO_LOG_SERIAL_NUMBER:
+ state.set_serial(config_a);
+ break;
+ case AltosLib.AO_LOG_BARO_RESERVED:
+ state.make_baro();
+ state.baro.reserved = config_a;
+ break;
+ case AltosLib.AO_LOG_BARO_SENS:
+ state.make_baro();
+ state.baro.sens = config_a;
+ break;
+ case AltosLib.AO_LOG_BARO_OFF:
+ state.make_baro();
+ state.baro.off = config_a;
+ break;
+ case AltosLib.AO_LOG_BARO_TCS:
+ state.make_baro();
+ state.baro.tcs = config_a;
+ break;
+ case AltosLib.AO_LOG_BARO_TCO:
+ state.make_baro();
+ state.baro.tco = config_a;
+ break;
+ case AltosLib.AO_LOG_BARO_TREF:
+ state.make_baro();
+ state.baro.tref = config_a;
+ break;
+ case AltosLib.AO_LOG_BARO_TEMPSENS:
+ state.make_baro();
+ state.baro.tempsens = config_a;
+ break;
+ case AltosLib.AO_LOG_BARO_CRC:
+ state.make_baro();
+ state.baro.crc = config_a;
+ break;
+ case AltosLib.AO_LOG_SOFTWARE_VERSION:
+ state.set_firmware_version(data);
+ break;
+ }
+ }
+
+ public void write(PrintStream out) {
+ switch (cmd) {
+ case AltosLib.AO_LOG_CONFIG_VERSION:
+ out.printf("# Config version: %s\n", data);
+ break;
+ case AltosLib.AO_LOG_MAIN_DEPLOY:
+ out.printf("# Main deploy: %s\n", config_a);
+ break;
+ case AltosLib.AO_LOG_APOGEE_DELAY:
+ out.printf("# Apogee delay: %s\n", config_a);
+ break;
+ case AltosLib.AO_LOG_RADIO_CHANNEL:
+ out.printf("# Radio channel: %s\n", config_a);
+ break;
+ case AltosLib.AO_LOG_CALLSIGN:
+ out.printf("# Callsign: %s\n", data);
+ break;
+ case AltosLib.AO_LOG_ACCEL_CAL:
+ out.printf ("# Accel cal: %d %d\n", config_a, config_b);
+ break;
+ case AltosLib.AO_LOG_RADIO_CAL:
+ out.printf ("# Radio cal: %d\n", config_a);
+ break;
+ case AltosLib.AO_LOG_MAX_FLIGHT_LOG:
+ out.printf ("# Max flight log: %d\n", config_a);
+ break;
+ case AltosLib.AO_LOG_MANUFACTURER:
+ out.printf ("# Manufacturer: %s\n", data);
+ break;
+ case AltosLib.AO_LOG_PRODUCT:
+ out.printf ("# Product: %s\n", data);
+ break;
+ case AltosLib.AO_LOG_SERIAL_NUMBER:
+ out.printf ("# Serial number: %d\n", config_a);
+ break;
+ case AltosLib.AO_LOG_SOFTWARE_VERSION:
+ out.printf ("# Software version: %s\n", data);
+ break;
+ case AltosLib.AO_LOG_BARO_RESERVED:
+ out.printf ("# Baro reserved: %d\n", config_a);
+ break;
+ case AltosLib.AO_LOG_BARO_SENS:
+ out.printf ("# Baro sens: %d\n", config_a);
+ break;
+ case AltosLib.AO_LOG_BARO_OFF:
+ out.printf ("# Baro off: %d\n", config_a);
+ break;
+ case AltosLib.AO_LOG_BARO_TCS:
+ out.printf ("# Baro tcs: %d\n", config_a);
+ break;
+ case AltosLib.AO_LOG_BARO_TCO:
+ out.printf ("# Baro tco: %d\n", config_a);
+ break;
+ case AltosLib.AO_LOG_BARO_TREF:
+ out.printf ("# Baro tref: %d\n", config_a);
+ break;
+ case AltosLib.AO_LOG_BARO_TEMPSENS:
+ out.printf ("# Baro tempsens: %d\n", config_a);
+ break;
+ case AltosLib.AO_LOG_BARO_CRC:
+ out.printf ("# Baro crc: %d\n", config_a);
+ break;
+ }
+ }
+
+ public AltosEepromHeader (String[] tokens) {
+ last = false;
+ valid = true;
+ try {
+ if (tokens[0].equals("Config") && tokens[1].equals("version:")) {
+ cmd = AltosLib.AO_LOG_CONFIG_VERSION;
+ data = tokens[2];
+ } else if (tokens[0].equals("Main") && tokens[1].equals("deploy:")) {
+ cmd = AltosLib.AO_LOG_MAIN_DEPLOY;
+ config_a = Integer.parseInt(tokens[2]);
+ } else if (tokens[0].equals("Apogee") && tokens[1].equals("delay:")) {
+ cmd = AltosLib.AO_LOG_APOGEE_DELAY;
+ config_a = Integer.parseInt(tokens[2]);
+ } else if (tokens[0].equals("Radio") && tokens[1].equals("channel:")) {
+ cmd = AltosLib.AO_LOG_RADIO_CHANNEL;
+ 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;
+ 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;
+ 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;
+ config_a = Integer.parseInt(tokens[3]);
+ } else if (tokens[0].equals("manufacturer")) {
+ cmd = AltosLib.AO_LOG_MANUFACTURER;
+ data = tokens[1];
+ } else if (tokens[0].equals("product")) {
+ cmd = AltosLib.AO_LOG_PRODUCT;
+ data = tokens[1];
+ } else if (tokens[0].equals("serial-number")) {
+ cmd = AltosLib.AO_LOG_SERIAL_NUMBER;
+ config_a = Integer.parseInt(tokens[1]);
+ } else if (tokens[0].equals("log-format")) {
+ cmd = AltosLib.AO_LOG_LOG_FORMAT;
+ config_a = Integer.parseInt(tokens[1]);
+ } else if (tokens[0].equals("software-version")) {
+ cmd = AltosLib.AO_LOG_SOFTWARE_VERSION;
+ data = tokens[1];
+ last = true;
+ } else if (tokens[0].equals("ms5607")) {
+ if (tokens[1].equals("reserved:")) {
+ cmd = AltosLib.AO_LOG_BARO_RESERVED;
+ config_a = Integer.parseInt(tokens[2]);
+ } else if (tokens[1].equals("sens:")) {
+ cmd = AltosLib.AO_LOG_BARO_SENS;
+ config_a = Integer.parseInt(tokens[2]);
+ } else if (tokens[1].equals("off:")) {
+ cmd = AltosLib.AO_LOG_BARO_OFF;
+ config_a = Integer.parseInt(tokens[2]);
+ } else if (tokens[1].equals("tcs:")) {
+ cmd = AltosLib.AO_LOG_BARO_TCS;
+ config_a = Integer.parseInt(tokens[2]);
+ } else if (tokens[1].equals("tco:")) {
+ cmd = AltosLib.AO_LOG_BARO_TCO;
+ config_a = Integer.parseInt(tokens[2]);
+ } else if (tokens[1].equals("tref:")) {
+ cmd = AltosLib.AO_LOG_BARO_TREF;
+ config_a = Integer.parseInt(tokens[2]);
+ } else if (tokens[1].equals("tempsens:")) {
+ cmd = AltosLib.AO_LOG_BARO_TEMPSENS;
+ config_a = Integer.parseInt(tokens[2]);
+ } else if (tokens[1].equals("crc:")) {
+ cmd = AltosLib.AO_LOG_BARO_CRC;
+ config_a = Integer.parseInt(tokens[2]);
+ } else {
+ cmd = AltosLib.AO_LOG_INVALID;
+ data = tokens[2];
+ }
+ } else
+ valid = false;
+ } catch (Exception e) {
+ valid = false;
+ }
+ }
+
+ static public LinkedList<AltosEeprom> read(FileInputStream input) {
+ LinkedList<AltosEeprom> headers = new LinkedList<AltosEeprom>();
+
+ for (;;) {
+ try {
+ String line = AltosLib.gets(input);
+ if (line == null)
+ break;
+ AltosEepromHeader header = new AltosEepromHeader(line);
+ headers.add(header);
+ if (header.last)
+ break;
+ } catch (IOException ie) {
+ break;
+ }
+ }
+
+ return headers;
+ }
+
+ static public void write (PrintStream out, LinkedList<AltosEepromHeader> headers) {
+ out.printf("# Comments\n");
+ for (AltosEepromHeader header : headers) {
+ header.write(out);
+ }
+
+ }
+
+ public AltosEepromHeader (String line) {
+ this(line.split("\\s+"));
+ }
+}
diff --git a/altoslib/AltosEepromIterable.java b/altoslib/AltosEepromIterable.java
index b84574ef..fc793579 100644
--- a/altoslib/AltosEepromIterable.java
+++ b/altoslib/AltosEepromIterable.java
@@ -1,5 +1,5 @@
/*
- * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ * Copyright © 2013 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
@@ -15,421 +15,105 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
import java.io.*;
import java.util.*;
import java.text.*;
-public class AltosEepromIterable extends AltosRecordIterable {
+class AltosEepromOrdered implements Comparable<AltosEepromOrdered> {
+ AltosEeprom eeprom;
+ int index;
+ int tick;
- static final int seen_basic = AltosRecord.seen_flight|AltosRecord.seen_sensor;
-
- boolean has_accel;
- boolean has_gps;
- boolean has_ignite;
-
- AltosEepromRecord flight_record;
- AltosEepromRecord gps_date_record;
-
- TreeSet<AltosOrderedRecord> records;
-
- LinkedList<AltosRecord> list;
-
- class EepromState {
- int seen;
- int n_pad_samples;
- double ground_pres;
- int gps_tick;
- int boost_tick;
- int sensor_tick;
-
- EepromState() {
- seen = 0;
- n_pad_samples = 0;
- ground_pres = 0.0;
- gps_tick = 0;
- }
+ int cmdi() {
+ if (eeprom.cmd == AltosLib.AO_LOG_FLIGHT)
+ return 0;
+ return 1;
}
- void update_state(AltosRecordTM state, AltosEepromRecord record, EepromState eeprom) {
- state.tick = record.tick;
- switch (record.cmd) {
- case AltosLib.AO_LOG_FLIGHT:
- eeprom.seen |= AltosRecord.seen_flight;
- state.ground_accel = record.a;
- state.flight_accel = record.a;
- state.flight = record.b;
- eeprom.boost_tick = record.tick;
- break;
- case AltosLib.AO_LOG_SENSOR:
- state.accel = record.a;
- state.pres = record.b;
- if (state.state < AltosLib.ao_flight_boost) {
- eeprom.n_pad_samples++;
- eeprom.ground_pres += state.pres;
- state.ground_pres = (int) (eeprom.ground_pres / eeprom.n_pad_samples);
- state.flight_pres = state.ground_pres;
- } else {
- state.flight_pres = (state.flight_pres * 15 + state.pres) / 16;
- }
- state.flight_accel = (state.flight_accel * 15 + state.accel) / 16;
- if ((eeprom.seen & AltosRecord.seen_sensor) == 0)
- eeprom.sensor_tick = record.tick - 1;
- state.flight_vel += (state.accel_plus_g - state.accel) * (record.tick - eeprom.sensor_tick);
- eeprom.seen |= AltosRecord.seen_sensor;
- 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 |= AltosRecord.seen_sensor;
- break;
- case AltosLib.AO_LOG_TEMP_VOLT:
- state.temp = record.a;
- state.batt = record.b;
- eeprom.seen |= AltosRecord.seen_temp_volt;
- break;
- case AltosLib.AO_LOG_DEPLOY:
- state.drogue = record.a;
- state.main = record.b;
- eeprom.seen |= AltosRecord.seen_deploy;
- has_ignite = true;
- break;
- case AltosLib.AO_LOG_STATE:
- state.state = record.a;
- break;
- case AltosLib.AO_LOG_GPS_TIME:
- eeprom.gps_tick = state.tick;
- eeprom.seen |= AltosRecord.seen_gps_time;
- AltosGPS old = state.gps;
- state.gps = new AltosGPS();
+ public int compareTo(AltosEepromOrdered o) {
+ int cmd_diff = cmdi() - o.cmdi();
- /* 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);
+ if (cmd_diff != 0)
+ return cmd_diff;
- int flags = (record.b >> 8);
- 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.gps_sequence++;
- has_gps = true;
- break;
- case AltosLib.AO_LOG_GPS_LAT:
- eeprom.seen |= AltosRecord.seen_gps_lat;
- int lat32 = record.a | (record.b << 16);
- if (state.gps == null)
- state.gps = new AltosGPS();
- state.gps.lat = (double) lat32 / 1e7;
- break;
- case AltosLib.AO_LOG_GPS_LON:
- eeprom.seen |= AltosRecord.seen_gps_lon;
- int lon32 = record.a | (record.b << 16);
- if (state.gps == null)
- state.gps = new AltosGPS();
- state.gps.lon = (double) lon32 / 1e7;
- break;
- case AltosLib.AO_LOG_GPS_ALT:
- if (state.gps == null)
- state.gps = new AltosGPS();
- state.gps.alt = record.a;
- break;
- case AltosLib.AO_LOG_GPS_SAT:
- if (state.tick == eeprom.gps_tick) {
- int svid = record.a;
- int c_n0 = record.b >> 8;
- if (state.gps == null)
- state.gps = new AltosGPS();
- state.gps.add_sat(svid, c_n0);
- }
- break;
- case AltosLib.AO_LOG_GPS_DATE:
- if (state.gps == null)
- state.gps = new AltosGPS();
- state.gps.year = (record.a & 0xff) + 2000;
- state.gps.month = record.a >> 8;
- state.gps.day = record.b & 0xff;
- break;
+ int tick_diff = tick - o.tick;
- case AltosLib.AO_LOG_CONFIG_VERSION:
- break;
- case AltosLib.AO_LOG_MAIN_DEPLOY:
- break;
- case AltosLib.AO_LOG_APOGEE_DELAY:
- break;
- case AltosLib.AO_LOG_RADIO_CHANNEL:
- break;
- case AltosLib.AO_LOG_CALLSIGN:
- state.callsign = record.data;
- break;
- case AltosLib.AO_LOG_ACCEL_CAL:
- state.accel_plus_g = record.a;
- state.accel_minus_g = record.b;
- break;
- case AltosLib.AO_LOG_RADIO_CAL:
- break;
- case AltosLib.AO_LOG_MANUFACTURER:
- break;
- case AltosLib.AO_LOG_PRODUCT:
- break;
- case AltosLib.AO_LOG_SERIAL_NUMBER:
- state.serial = record.a;
- break;
- case AltosLib.AO_LOG_SOFTWARE_VERSION:
- break;
- }
- state.seen |= eeprom.seen;
+ if (tick_diff != 0)
+ return tick_diff;
+ return index - o.index;
}
- LinkedList<AltosRecord> make_list() {
- LinkedList<AltosRecord> list = new LinkedList<AltosRecord>();
- Iterator<AltosOrderedRecord> iterator = records.iterator();
- AltosOrderedRecord record = null;
- AltosRecordTM state = new AltosRecordTM();
- //boolean last_reported = false;
- EepromState eeprom = new EepromState();
-
- state.state = AltosLib.ao_flight_pad;
- state.accel_plus_g = 15758;
- state.accel_minus_g = 16294;
- state.flight_vel = 0;
-
- /* Pull in static data from the flight and gps_date records */
- if (flight_record != null)
- update_state(state, flight_record, eeprom);
- if (gps_date_record != null)
- update_state(state, gps_date_record, eeprom);
+ AltosEepromOrdered (AltosEeprom eeprom, int index, int tick) {
+ this.eeprom = eeprom;
+ this.index = index;
+ this.tick = tick;
+ }
+}
- while (iterator.hasNext()) {
- record = iterator.next();
- if ((eeprom.seen & seen_basic) == seen_basic && record.tick != state.tick) {
- AltosRecordTM r = state.clone();
- r.time = (r.tick - eeprom.boost_tick) / 100.0;
- list.add(r);
+class AltosEepromOrderedIterator implements Iterator<AltosEeprom> {
+ TreeSet<AltosEepromOrdered> olist;
+ Iterator<AltosEepromOrdered> oiterator;
+
+ public AltosEepromOrderedIterator(Iterable<AltosEeprom> eeproms) {
+ olist = new TreeSet<AltosEepromOrdered>();
+
+ int tick = 0;
+ int index = 0;
+ boolean first = true;
+
+ for (AltosEeprom e : eeproms) {
+ int t = e.tick;
+ if (first)
+ tick = t;
+ else {
+ while (t < tick - 32767)
+ t += 65536;
+ tick = t;
}
- update_state(state, record, eeprom);
+ olist.add(new AltosEepromOrdered(e, index++, tick));
+ first = false;
}
- AltosRecordTM r = state.clone();
- r.time = (r.tick - eeprom.boost_tick) / 100.0;
- list.add(r);
- return list;
- }
- public Iterator<AltosRecord> iterator() {
- if (list == null)
- list = make_list();
- return list.iterator();
+ oiterator = olist.iterator();
}
- public boolean has_gps() { return has_gps; }
- public boolean has_accel() { return has_accel; }
- public boolean has_ignite() { return has_ignite; }
-
- public void write_comments(PrintStream out) {
- Iterator<AltosOrderedRecord> iterator = records.iterator();
- out.printf("# Comments\n");
- while (iterator.hasNext()) {
- AltosOrderedRecord record = iterator.next();
- switch (record.cmd) {
- case AltosLib.AO_LOG_CONFIG_VERSION:
- out.printf("# Config version: %s\n", record.data);
- break;
- case AltosLib.AO_LOG_MAIN_DEPLOY:
- out.printf("# Main deploy: %s\n", record.a);
- break;
- case AltosLib.AO_LOG_APOGEE_DELAY:
- out.printf("# Apogee delay: %s\n", record.a);
- break;
- case AltosLib.AO_LOG_RADIO_CHANNEL:
- out.printf("# Radio channel: %s\n", record.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);
- break;
- case AltosLib.AO_LOG_RADIO_CAL:
- out.printf ("# Radio cal: %d\n", record.a);
- break;
- case AltosLib.AO_LOG_MAX_FLIGHT_LOG:
- out.printf ("# Max flight log: %d\n", record.a);
- break;
- case AltosLib.AO_LOG_MANUFACTURER:
- out.printf ("# Manufacturer: %s\n", record.data);
- break;
- case AltosLib.AO_LOG_PRODUCT:
- out.printf ("# Product: %s\n", record.data);
- break;
- case AltosLib.AO_LOG_SERIAL_NUMBER:
- out.printf ("# Serial number: %d\n", record.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);
- break;
- case AltosLib.AO_LOG_BARO_SENS:
- out.printf ("# Baro sens: %d\n", record.a);
- break;
- case AltosLib.AO_LOG_BARO_OFF:
- out.printf ("# Baro off: %d\n", record.a);
- break;
- case AltosLib.AO_LOG_BARO_TCS:
- out.printf ("# Baro tcs: %d\n", record.a);
- break;
- case AltosLib.AO_LOG_BARO_TCO:
- out.printf ("# Baro tco: %d\n", record.a);
- break;
- case AltosLib.AO_LOG_BARO_TREF:
- out.printf ("# Baro tref: %d\n", record.a);
- break;
- case AltosLib.AO_LOG_BARO_TEMPSENS:
- out.printf ("# Baro tempsens: %d\n", record.a);
- break;
- case AltosLib.AO_LOG_BARO_CRC:
- out.printf ("# Baro crc: %d\n", record.a);
- break;
- }
- }
+ public boolean hasNext() {
+ return oiterator.hasNext();
}
- /*
- * Given an AO_LOG_GPS_TIME record with correct time, and one
- * missing time, rewrite the missing time values with the good
- * ones, assuming that the difference between them is 'diff' seconds
- */
- void update_time(AltosOrderedRecord good, AltosOrderedRecord bad) {
-
- int diff = (bad.tick - good.tick + 50) / 100;
-
- int hour = (good.a & 0xff);
- int minute = (good.a >> 8);
- int second = (good.b & 0xff);
- int flags = (good.b >> 8);
- int seconds = hour * 3600 + minute * 60 + second;
-
- /* Make sure this looks like a good GPS value */
- if ((flags & 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);
+ public AltosEeprom next() {
+ return oiterator.next().eeprom;
}
- /*
- * Read the whole file, dumping records into a RB tree so
- * we can enumerate them in time order -- the eeprom data
- * are sometimes out of order with GPS data getting timestamps
- * matching the first packet out of the GPS unit but not
- * written until the final GPS packet has been received.
- */
- public AltosEepromIterable (FileInputStream input) {
- records = new TreeSet<AltosOrderedRecord>();
-
- AltosOrderedRecord last_gps_time = null;
-
- int index = 0;
- int prev_tick = 0;
- boolean prev_tick_valid = false;
- boolean missing_time = false;
+ public void remove () {
+ }
+}
- try {
- for (;;) {
- String line = AltosLib.gets(input);
- if (line == null)
- break;
- AltosOrderedRecord record = new AltosOrderedRecord(line, index++, prev_tick, prev_tick_valid);
- if (record.cmd == AltosLib.AO_LOG_INVALID)
- continue;
- prev_tick = record.tick;
- if (record.cmd < AltosLib.AO_LOG_CONFIG_VERSION)
- prev_tick_valid = true;
- if (record.cmd == AltosLib.AO_LOG_FLIGHT) {
- flight_record = record;
- continue;
- }
+public class AltosEepromIterable implements Iterable<AltosEeprom> {
+ public LinkedList<AltosEeprom> eeproms;
- /* 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;
- }
+ public void write(PrintStream out) {
+ for (AltosEeprom eeprom : eeproms)
+ eeprom.write(out);
+ }
- /* 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<AltosOrderedRecord> iterator = records.iterator();
- while (iterator.hasNext()) {
- AltosOrderedRecord old = iterator.next();
- if (old.cmd == AltosLib.AO_LOG_GPS_TIME &&
- old.a == -1 && old.b == -1)
- {
- update_time(record, old);
- }
- }
- missing_time = false;
- }
- }
+ public AltosState state() {
+ AltosState state = new AltosState();
- if (record.cmd == AltosLib.AO_LOG_GPS_LAT) {
- if (last_gps_time == null || last_gps_time.tick != record.tick) {
- AltosOrderedRecord add_gps_time = new AltosOrderedRecord(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;
+ for (AltosEeprom header : eeproms)
+ header.update_state(state);
+ return state;
+ }
- records.add(add_gps_time);
- record.index = index++;
- }
- }
- records.add(record);
+ public AltosEepromIterable(LinkedList<AltosEeprom> eeproms) {
+ this.eeproms = eeproms;
+ }
- /* Bail after reading the 'landed' record; we're all done */
- if (record.cmd == AltosLib.AO_LOG_STATE &&
- record.a == AltosLib.ao_flight_landed)
- break;
- }
- } catch (IOException io) {
- } catch (ParseException pe) {
- }
- try {
- input.close();
- } catch (IOException ie) {
- }
+ public Iterator<AltosEeprom> iterator() {
+ if (eeproms == null)
+ eeproms = new LinkedList<AltosEeprom>();
+ return new AltosEepromOrderedIterator(eeproms);
}
-}
+} \ No newline at end of file
diff --git a/altoslib/AltosEepromList.java b/altoslib/AltosEepromList.java
new file mode 100644
index 00000000..763bd1e2
--- /dev/null
+++ b/altoslib/AltosEepromList.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altoslib_2;
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.util.concurrent.*;
+
+/*
+ * Temporary structure to hold the list of stored flights;
+ * each of these will be queried in turn to generate more
+ * complete information
+ */
+
+class AltosEepromFlight {
+ int flight;
+ int start;
+ int end;
+
+ public AltosEepromFlight(int in_flight, int in_start, int in_end) {
+ flight = in_flight;
+ start = in_start;
+ end = in_end;
+ }
+}
+
+/*
+ * Construct a list of flights available in a connected device
+ */
+
+public class AltosEepromList extends ArrayList<AltosEepromLog> {
+ public AltosConfigData config_data;
+
+ public AltosEepromList (AltosLink link, boolean remote)
+ throws IOException, InterruptedException, TimeoutException
+ {
+ try {
+ if (remote)
+ link.start_remote();
+ config_data = new AltosConfigData (link);
+// if (config_data.serial == 0)
+// throw new IOException("no serial number found");
+
+ ArrayList<AltosEepromFlight> flights = new ArrayList<AltosEepromFlight>();
+
+ if (config_data.flight_log_max != 0 || config_data.log_format != 0) {
+
+ /* Devices with newer firmware will support the 'l'
+ * command which will list the region of storage
+ * occupied by each available flight
+ */
+ link.printf("l\n");
+ for (;;) {
+ String line = link.get_reply(5000);
+ if (line == null)
+ throw new TimeoutException();
+ if (line.contains("done"))
+ break;
+ if (line.contains("Syntax"))
+ continue;
+ String[] tokens = line.split("\\s+");
+ if (tokens.length < 6)
+ break;
+
+ int flight = -1, start = -1, end = -1;
+ try {
+ if (tokens[0].equals("flight"))
+ flight = AltosParse.parse_int(tokens[1]);
+ if (tokens[2].equals("start"))
+ start = AltosParse.parse_hex(tokens[3]);
+ if (tokens[4].equals("end"))
+ end = AltosParse.parse_hex(tokens[5]);
+ if (flight > 0 && start >= 0 && end > 0)
+ flights.add(new AltosEepromFlight(flight, start, end));
+ } catch (ParseException pe) { System.out.printf("Parse error %s\n", pe.toString()); }
+ }
+ } else {
+
+ /* Older devices will hold only a single
+ * flight. This also assumes that any older
+ * device will have a 1MB flash device
+ */
+ flights.add(new AltosEepromFlight(0, 0, 0xfff));
+ }
+
+ /* With the list of flights collected, collect more complete
+ * information on them by reading the first block or two of
+ * data. This will add GPS coordinates and a date. For older
+ * firmware, this will also extract the flight number.
+ */
+ for (AltosEepromFlight flight : flights) {
+ add(new AltosEepromLog(config_data, link,
+ flight.flight, flight.start, flight.end));
+ }
+ } finally {
+ if (remote)
+ link.stop_remote();
+ link.flush_output();
+ }
+ }
+} \ No newline at end of file
diff --git a/altoslib/AltosEepromLog.java b/altoslib/AltosEepromLog.java
index 20026c6d..95c0c3f6 100644
--- a/altoslib/AltosEepromLog.java
+++ b/altoslib/AltosEepromLog.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
import java.text.*;
import java.util.concurrent.*;
@@ -72,9 +72,9 @@ public class AltosEepromLog {
for (block = in_start_block; block < in_end_block; block++) {
AltosEepromChunk eechunk = new AltosEepromChunk(link, block, block == in_start_block);
- for (int i = 0; i < AltosEepromChunk.chunk_size; i += AltosEepromRecord.record_length) {
+ for (int i = 0; i < AltosEepromChunk.chunk_size; i += AltosEepromTM.record_length) {
try {
- AltosEepromRecord r = new AltosEepromRecord(eechunk, i);
+ AltosEepromTM r = new AltosEepromTM(eechunk, i);
if (r.cmd == AltosLib.AO_LOG_FLIGHT) {
flight = r.b;
diff --git a/altoslib/AltosEepromMega.java b/altoslib/AltosEepromMega.java
index b077e26c..7a4ee52d 100644
--- a/altoslib/AltosEepromMega.java
+++ b/altoslib/AltosEepromMega.java
@@ -15,34 +15,16 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
+import java.io.*;
+import java.util.*;
import java.text.*;
-public class AltosEepromMega {
- public int cmd;
- public int tick;
- public boolean valid;
- public String data;
- public int config_a, config_b;
-
- public int data8[];
-
+public class AltosEepromMega extends AltosEeprom {
public static final int record_length = 32;
- static final int header_length = 4;
- static final int data_length = record_length - header_length;
-
- public int data8(int i) {
- return data8[i];
- }
- public int data16(int i) {
- return ((data8[i] | (data8[i+1] << 8)) << 16) >> 16;
- }
-
- public int data32(int i) {
- return data8[i] | (data8[i+1] << 8) | (data8[i+2] << 16) | (data8[i+3] << 24);
- }
+ public int record_length() { return record_length; }
/* AO_LOG_FLIGHT elements */
public int flight() { return data16(0); }
@@ -68,11 +50,12 @@ public class AltosEepromMega {
public int mag_z() { return data16(24); }
public int accel() { return data16(26); }
- /* AO_LOG_VOLT elements */
+ /* AO_LOG_TEMP_VOLT elements */
public int v_batt() { return data16(0); }
public int v_pbatt() { return data16(2); }
public int nsense() { return data16(4); }
public int sense(int i) { return data16(6 + i * 2); }
+ public int pyro() { return data16(26); }
/* AO_LOG_GPS_TIME elements */
public int latitude() { return data32(0); }
@@ -90,131 +73,139 @@ public class AltosEepromMega {
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);
-
- valid = !chunk.erased(start, record_length);
- if (valid) {
- if (AltosConvert.checksum(chunk.data, start, record_length) != 0)
- throw new ParseException(String.format("invalid checksum at 0x%x",
- chunk.address + start), 0);
- } else {
- cmd = AltosLib.AO_LOG_INVALID;
- }
+ parse_chunk(chunk, start);
+ }
- tick = chunk.data16(start+2);
+ public void update_state(AltosState state) {
+ super.update_state(state);
+
+ AltosGPS gps;
+
+ /* Flush any pending GPS changes */
+ if (state.gps_pending) {
+ switch (cmd) {
+ case AltosLib.AO_LOG_GPS_LAT:
+ case AltosLib.AO_LOG_GPS_LON:
+ case AltosLib.AO_LOG_GPS_ALT:
+ case AltosLib.AO_LOG_GPS_SAT:
+ case AltosLib.AO_LOG_GPS_DATE:
+ break;
+ default:
+ state.set_temp_gps();
+ break;
+ }
+ }
- data8 = new int[data_length];
- for (int i = 0; i < data_length; i++)
- data8[i] = chunk.data(start + header_length + i);
+ switch (cmd) {
+ case AltosLib.AO_LOG_FLIGHT:
+ state.set_boost_tick(tick);
+ state.set_flight(flight());
+ state.set_ground_accel(ground_accel());
+ state.set_ground_pressure(ground_pres());
+ state.set_temperature(ground_temp() / 100.0);
+ break;
+ case AltosLib.AO_LOG_STATE:
+ state.set_tick(tick);
+ state.set_state(state());
+ break;
+ case AltosLib.AO_LOG_SENSOR:
+ state.set_tick(tick);
+ state.set_ms5607(pres(), temp());
+
+ AltosIMU imu = new AltosIMU();
+ imu.accel_x = accel_x();
+ imu.accel_y = accel_y();
+ imu.accel_z = accel_z();
+
+ imu.gyro_x = gyro_x();
+ imu.gyro_y = gyro_y();
+ imu.gyro_z = gyro_z();
+ state.imu = imu;
+
+ AltosMag mag = new AltosMag();
+ mag.x = mag_x();
+ mag.y = mag_y();
+ mag.z = mag_z();
+
+ state.mag = mag;
+
+ state.set_accel(accel());
+
+ break;
+ case AltosLib.AO_LOG_TEMP_VOLT:
+ state.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt()));
+ state.set_pyro_voltage(AltosConvert.mega_pyro_voltage(v_pbatt()));
+
+ int nsense = nsense();
+
+ state.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense(nsense-2)));
+ state.set_main_voltage(AltosConvert.mega_pyro_voltage(sense(nsense-1)));
+
+ double voltages[] = new double[nsense-2];
+ for (int i = 0; i < nsense-2; i++)
+ voltages[i] = AltosConvert.mega_pyro_voltage(sense(i));
+
+ state.set_ignitor_voltage(voltages);
+ break;
+ case AltosLib.AO_LOG_GPS_TIME:
+ state.set_tick(tick);
+ gps = state.make_temp_gps(false);
+ gps.lat = latitude() / 1e7;
+ gps.lon = longitude() / 1e7;
+ gps.alt = altitude();
+
+ gps.hour = hour();
+ gps.minute = minute();
+ gps.second = second();
+
+ int flags = flags();
+
+ gps.connected = (flags & AltosLib.AO_GPS_RUNNING) != 0;
+ gps.locked = (flags & AltosLib.AO_GPS_VALID) != 0;
+ gps.nsat = (flags & AltosLib.AO_GPS_NUM_SAT_MASK) >>
+ AltosLib.AO_GPS_NUM_SAT_SHIFT;
+
+ gps.year = 2000 + year();
+ gps.month = month();
+ gps.day = day();
+ break;
+ case AltosLib.AO_LOG_GPS_SAT:
+ state.set_tick(tick);
+ gps = state.make_temp_gps(true);
+
+ int n = nsat();
+ for (int i = 0; i < n; i++)
+ gps.add_sat(svid(i), c_n(i));
+ break;
+ }
}
public AltosEepromMega (String line) {
- valid = false;
- tick = 0;
+ parse_string(line);
+ }
- if (line == null) {
- cmd = AltosLib.AO_LOG_INVALID;
- line = "";
- } else {
+ static public LinkedList<AltosEeprom> read(FileInputStream input) {
+ LinkedList<AltosEeprom> megas = new LinkedList<AltosEeprom>();
+
+ for (;;) {
try {
- String[] tokens = line.split("\\s+");
-
- if (tokens[0].length() == 1) {
- if (tokens.length != 2 + data_length) {
- cmd = AltosLib.AO_LOG_INVALID;
- data = line;
- } else {
- cmd = tokens[0].codePointAt(0);
- tick = Integer.parseInt(tokens[1],16);
- valid = true;
- data8 = new int[data_length];
- for (int i = 0; i < data_length; i++)
- data8[i] = Integer.parseInt(tokens[2 + i],16);
- }
- } else if (tokens[0].equals("Config") && tokens[1].equals("version:")) {
- cmd = AltosLib.AO_LOG_CONFIG_VERSION;
- data = tokens[2];
- } else if (tokens[0].equals("Main") && tokens[1].equals("deploy:")) {
- cmd = AltosLib.AO_LOG_MAIN_DEPLOY;
- config_a = Integer.parseInt(tokens[2]);
- } else if (tokens[0].equals("Apogee") && tokens[1].equals("delay:")) {
- cmd = AltosLib.AO_LOG_APOGEE_DELAY;
- config_a = Integer.parseInt(tokens[2]);
- } else if (tokens[0].equals("Radio") && tokens[1].equals("channel:")) {
- cmd = AltosLib.AO_LOG_RADIO_CHANNEL;
- 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;
- 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;
- 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;
- config_a = Integer.parseInt(tokens[3]);
- } else if (tokens[0].equals("manufacturer")) {
- cmd = AltosLib.AO_LOG_MANUFACTURER;
- data = tokens[1];
- } else if (tokens[0].equals("product")) {
- cmd = AltosLib.AO_LOG_PRODUCT;
- data = tokens[1];
- } else if (tokens[0].equals("serial-number")) {
- cmd = AltosLib.AO_LOG_SERIAL_NUMBER;
- config_a = Integer.parseInt(tokens[1]);
- } else if (tokens[0].equals("log-format")) {
- cmd = AltosLib.AO_LOG_LOG_FORMAT;
- 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;
- config_a = Integer.parseInt(tokens[2]);
- } else if (tokens[1].equals("sens:")) {
- cmd = AltosLib.AO_LOG_BARO_SENS;
- config_a = Integer.parseInt(tokens[2]);
- } else if (tokens[1].equals("off:")) {
- cmd = AltosLib.AO_LOG_BARO_OFF;
- config_a = Integer.parseInt(tokens[2]);
- } else if (tokens[1].equals("tcs:")) {
- cmd = AltosLib.AO_LOG_BARO_TCS;
- config_a = Integer.parseInt(tokens[2]);
- } else if (tokens[1].equals("tco:")) {
- cmd = AltosLib.AO_LOG_BARO_TCO;
- config_a = Integer.parseInt(tokens[2]);
- } else if (tokens[1].equals("tref:")) {
- cmd = AltosLib.AO_LOG_BARO_TREF;
- config_a = Integer.parseInt(tokens[2]);
- } else if (tokens[1].equals("tempsens:")) {
- cmd = AltosLib.AO_LOG_BARO_TEMPSENS;
- config_a = Integer.parseInt(tokens[2]);
- } else if (tokens[1].equals("crc:")) {
- cmd = AltosLib.AO_LOG_BARO_CRC;
- config_a = Integer.parseInt(tokens[2]);
- } else {
- cmd = AltosLib.AO_LOG_INVALID;
- data = line;
- }
- } else {
- cmd = AltosLib.AO_LOG_INVALID;
- data = line;
+ String line = AltosLib.gets(input);
+ if (line == null)
+ break;
+ try {
+ AltosEepromMega mega = new AltosEepromMega(line);
+ if (mega.cmd != AltosLib.AO_LOG_INVALID)
+ megas.add(mega);
+ } catch (Exception e) {
+ System.out.printf ("exception\n");
}
- } catch (NumberFormatException ne) {
- cmd = AltosLib.AO_LOG_INVALID;
- data = line;
+ } catch (IOException ie) {
+ break;
}
}
- }
- public AltosEepromMega(int in_cmd, int in_tick) {
- cmd = in_cmd;
- tick = in_tick;
- valid = true;
+ return megas;
}
}
diff --git a/altoslib/AltosEepromMegaIterable.java b/altoslib/AltosEepromMegaIterable.java
deleted file mode 100644
index 5736f937..00000000
--- a/altoslib/AltosEepromMegaIterable.java
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * Copyright © 2010 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.altoslib_1;
-
-import java.io.*;
-import java.util.*;
-import java.text.*;
-
-public class AltosEepromMegaIterable extends AltosRecordIterable {
-
- static final int seen_flight = 1;
- static final int seen_sensor = 2;
- static final int seen_temp_volt = 4;
- static final int seen_deploy = 8;
- static final int seen_gps_time = 16;
- static final int seen_gps_lat = 32;
- static final int seen_gps_lon = 64;
-
- static final int seen_basic = seen_flight|seen_sensor;
-
- boolean has_accel;
- boolean has_gps;
- boolean has_ignite;
-
- AltosEepromMega flight_record;
- AltosEepromMega gps_date_record;
-
- TreeSet<AltosOrderedMegaRecord> records;
-
- AltosMs5607 baro;
-
- LinkedList<AltosRecord> list;
-
- class EepromState {
- int seen;
- int n_pad_samples;
- double ground_pres;
- int gps_tick;
- int boost_tick;
- int sensor_tick;
-
- EepromState() {
- seen = 0;
- n_pad_samples = 0;
- ground_pres = 0.0;
- gps_tick = 0;
- }
- }
-
- void update_state(AltosRecordMM state, AltosEepromMega record, EepromState eeprom) {
- state.tick = record.tick;
- switch (record.cmd) {
- case AltosLib.AO_LOG_FLIGHT:
- eeprom.seen |= seen_flight;
- state.ground_accel = record.ground_accel();
- state.flight_accel = record.ground_accel();
- state.ground_pres = baro.set(record.ground_pres(), record.ground_temp());
- state.flight_pres = state.ground_pres;
- state.flight = record.data16(0);
- eeprom.boost_tick = record.tick;
- break;
- case AltosLib.AO_LOG_SENSOR:
- state.accel = record.accel();
- baro.set(record.pres(), record.temp());
- state.pres = baro.pa;
- state.temp = baro.cc;
- state.imu = new AltosIMU();
- state.imu.accel_x = record.accel_x();
- state.imu.accel_y = record.accel_y();
- state.imu.accel_z = record.accel_z();
- state.imu.gyro_x = record.gyro_x();
- state.imu.gyro_y = record.gyro_y();
- state.imu.gyro_z = record.gyro_z();
- state.mag = new AltosMag();
- state.mag.x = record.mag_x();
- state.mag.y = record.mag_y();
- state.mag.z = record.mag_z();
- if (state.state < AltosLib.ao_flight_boost) {
- eeprom.n_pad_samples++;
- eeprom.ground_pres += state.pres;
- state.ground_pres = (int) (eeprom.ground_pres / eeprom.n_pad_samples);
- state.flight_pres = state.ground_pres;
- } else {
- state.flight_pres = (state.flight_pres * 15 + state.pres) / 16;
- }
- state.flight_accel = (state.flight_accel * 15 + state.accel) / 16;
- if ((eeprom.seen & seen_sensor) == 0)
- eeprom.sensor_tick = record.tick - 1;
- state.flight_vel += (state.accel_plus_g - state.accel) * (record.tick - eeprom.sensor_tick);
- eeprom.seen |= seen_sensor;
- eeprom.sensor_tick = record.tick;
- has_accel = true;
- break;
- case AltosLib.AO_LOG_TEMP_VOLT:
- state.v_batt = record.v_batt();
- state.v_pyro = record.v_pbatt();
- for (int i = 0; i < record.nsense(); i++)
- state.sense[i] = record.sense(i);
- eeprom.seen |= seen_temp_volt;
- break;
- case AltosLib.AO_LOG_STATE:
- state.state = record.state();
- break;
- case AltosLib.AO_LOG_GPS_TIME:
- eeprom.gps_tick = state.tick;
- state.gps = new AltosGPS();
-
- 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.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.gps_sequence++;
- has_gps = true;
- 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 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_CONFIG_VERSION:
- break;
- case AltosLib.AO_LOG_MAIN_DEPLOY:
- break;
- case AltosLib.AO_LOG_APOGEE_DELAY:
- break;
- case AltosLib.AO_LOG_RADIO_CHANNEL:
- break;
- case AltosLib.AO_LOG_CALLSIGN:
- state.callsign = record.data;
- break;
- case AltosLib.AO_LOG_ACCEL_CAL:
- state.accel_plus_g = record.config_a;
- state.accel_minus_g = record.config_b;
- break;
- case AltosLib.AO_LOG_RADIO_CAL:
- break;
- case AltosLib.AO_LOG_MANUFACTURER:
- break;
- case AltosLib.AO_LOG_PRODUCT:
- break;
- case AltosLib.AO_LOG_SERIAL_NUMBER:
- state.serial = record.config_a;
- break;
- case AltosLib.AO_LOG_SOFTWARE_VERSION:
- break;
- case AltosLib.AO_LOG_BARO_RESERVED:
- baro.reserved = record.config_a;
- break;
- case AltosLib.AO_LOG_BARO_SENS:
- baro.sens =record.config_a;
- break;
- case AltosLib.AO_LOG_BARO_OFF:
- baro.off =record.config_a;
- break;
- case AltosLib.AO_LOG_BARO_TCS:
- baro.tcs =record.config_a;
- break;
- case AltosLib.AO_LOG_BARO_TCO:
- baro.tco =record.config_a;
- break;
- case AltosLib.AO_LOG_BARO_TREF:
- baro.tref =record.config_a;
- break;
- case AltosLib.AO_LOG_BARO_TEMPSENS:
- baro.tempsens =record.config_a;
- break;
- case AltosLib.AO_LOG_BARO_CRC:
- baro.crc =record.config_a;
- break;
- }
- state.seen |= eeprom.seen;
- }
-
- LinkedList<AltosRecord> make_list() {
- LinkedList<AltosRecord> list = new LinkedList<AltosRecord>();
- Iterator<AltosOrderedMegaRecord> iterator = records.iterator();
- AltosOrderedMegaRecord record = null;
- AltosRecordMM state = new AltosRecordMM();
- //boolean last_reported = false;
- EepromState eeprom = new EepromState();
-
- state.state = AltosLib.ao_flight_pad;
- state.accel_plus_g = 15758;
- state.accel_minus_g = 16294;
-
- /* Pull in static data from the flight and gps_date records */
- if (flight_record != null)
- update_state(state, flight_record, eeprom);
- if (gps_date_record != null)
- update_state(state, gps_date_record, eeprom);
-
- while (iterator.hasNext()) {
- record = iterator.next();
- if ((eeprom.seen & seen_basic) == seen_basic && record.tick != state.tick) {
- AltosRecordMM r = state.clone();
- r.time = (r.tick - eeprom.boost_tick) / 100.0;
- list.add(r);
- }
- update_state(state, record, eeprom);
- }
- AltosRecordMM r = state.clone();
- r.time = (r.tick - eeprom.boost_tick) / 100.0;
- list.add(r);
- return list;
- }
-
- public Iterator<AltosRecord> iterator() {
- if (list == null)
- list = make_list();
- return list.iterator();
- }
-
- public boolean has_gps() { return has_gps; }
- public boolean has_accel() { return has_accel; }
- public boolean has_ignite() { return has_ignite; }
-
- public void write_comments(PrintStream out) {
- Iterator<AltosOrderedMegaRecord> iterator = records.iterator();
- out.printf("# Comments\n");
- while (iterator.hasNext()) {
- AltosOrderedMegaRecord record = iterator.next();
- switch (record.cmd) {
- case AltosLib.AO_LOG_CONFIG_VERSION:
- out.printf("# Config version: %s\n", record.data);
- break;
- case AltosLib.AO_LOG_MAIN_DEPLOY:
- out.printf("# Main deploy: %s\n", record.config_a);
- break;
- case AltosLib.AO_LOG_APOGEE_DELAY:
- out.printf("# Apogee delay: %s\n", record.config_a);
- break;
- case AltosLib.AO_LOG_RADIO_CHANNEL:
- 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.config_a, record.config_b);
- break;
- case AltosLib.AO_LOG_RADIO_CAL:
- 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.config_a);
- break;
- case AltosLib.AO_LOG_MANUFACTURER:
- out.printf ("# Manufacturer: %s\n", record.data);
- break;
- case AltosLib.AO_LOG_PRODUCT:
- out.printf ("# Product: %s\n", record.data);
- break;
- case AltosLib.AO_LOG_SERIAL_NUMBER:
- 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.config_a);
- break;
- case AltosLib.AO_LOG_BARO_SENS:
- out.printf ("# Baro sens: %d\n", record.config_a);
- break;
- case AltosLib.AO_LOG_BARO_OFF:
- out.printf ("# Baro off: %d\n", record.config_a);
- break;
- case AltosLib.AO_LOG_BARO_TCS:
- out.printf ("# Baro tcs: %d\n", record.config_a);
- break;
- case AltosLib.AO_LOG_BARO_TCO:
- out.printf ("# Baro tco: %d\n", record.config_a);
- break;
- case AltosLib.AO_LOG_BARO_TREF:
- out.printf ("# Baro tref: %d\n", record.config_a);
- break;
- case AltosLib.AO_LOG_BARO_TEMPSENS:
- out.printf ("# Baro tempsens: %d\n", record.config_a);
- break;
- case AltosLib.AO_LOG_BARO_CRC:
- out.printf ("# Baro crc: %d\n", record.config_a);
- break;
- }
- }
- }
-
- /*
- * Read the whole file, dumping records into a RB tree so
- * we can enumerate them in time order -- the eeprom data
- * are sometimes out of order with GPS data getting timestamps
- * matching the first packet out of the GPS unit but not
- * written until the final GPS packet has been received.
- */
- public AltosEepromMegaIterable (FileInputStream input) {
- records = new TreeSet<AltosOrderedMegaRecord>();
-
- AltosOrderedMegaRecord last_gps_time = null;
-
- baro = new AltosMs5607();
-
- int index = 0;
- int prev_tick = 0;
- boolean prev_tick_valid = false;
- boolean missing_time = false;
-
- try {
- for (;;) {
- String line = AltosLib.gets(input);
- if (line == null)
- break;
- AltosOrderedMegaRecord record = new AltosOrderedMegaRecord(line, index++, prev_tick, prev_tick_valid);
- if (record.cmd == AltosLib.AO_LOG_INVALID)
- continue;
- prev_tick = record.tick;
- if (record.cmd < AltosLib.AO_LOG_CONFIG_VERSION)
- prev_tick_valid = true;
- if (record.cmd == AltosLib.AO_LOG_FLIGHT) {
- flight_record = record;
- continue;
- }
-
- records.add(record);
-
- /* Bail after reading the 'landed' record; we're all done */
- if (record.cmd == AltosLib.AO_LOG_STATE &&
- record.state() == AltosLib.ao_flight_landed)
- break;
- }
- } catch (IOException io) {
- } catch (ParseException pe) {
- }
- try {
- input.close();
- } catch (IOException ie) {
- }
- }
-}
diff --git a/altoslib/AltosEepromMetrum2.java b/altoslib/AltosEepromMetrum2.java
new file mode 100644
index 00000000..c1d62c0c
--- /dev/null
+++ b/altoslib/AltosEepromMetrum2.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altoslib_2;
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
+public class AltosEepromMetrum2 extends AltosEeprom {
+ public static final int record_length = 16;
+
+ public int record_length() { return record_length; }
+
+ /* AO_LOG_FLIGHT elements */
+ public int flight() { return data16(0); }
+ public int ground_accel() { return data16(2); }
+ public int ground_pres() { return data32(4); }
+ public int ground_temp() { return data32(8); }
+
+ /* AO_LOG_STATE elements */
+ public int state() { return data16(0); }
+ public int reason() { return data16(2); }
+
+ /* AO_LOG_SENSOR elements */
+ public int pres() { return data32(0); }
+ public int temp() { return data32(4); }
+ public int accel() { return data16(8); }
+
+ /* AO_LOG_TEMP_VOLT elements */
+ public int v_batt() { return data16(0); }
+ public int sense_a() { return data16(2); }
+ public int sense_m() { return data16(4); }
+
+ /* AO_LOG_GPS_POS elements */
+ public int latitude() { return data32(0); }
+ public int longitude() { return data32(4); }
+ public int altitude() { return data16(8); }
+
+ /* AO_LOG_GPS_TIME elements */
+ public int hour() { return data8(0); }
+ public int minute() { return data8(1); }
+ public int second() { return data8(2); }
+ public int flags() { return data8(3); }
+ public int year() { return data8(4); }
+ public int month() { return data8(5); }
+ public int day() { return data8(6); }
+
+ /* AO_LOG_GPS_SAT elements */
+ public int nsat() { return data8(0); }
+ public int more() { return data8(1); }
+ public int svid(int n) { return data8(2 + n * 2); }
+ public int c_n(int n) { return data8(2 + n * 2 + 1); }
+
+ public AltosEepromMetrum2 (AltosEepromChunk chunk, int start) throws ParseException {
+ parse_chunk(chunk, start);
+ }
+
+ public void update_state(AltosState state) {
+ super.update_state(state);
+
+ AltosGPS gps;
+
+ /* Flush any pending GPS changes */
+ if (state.gps_pending) {
+ switch (cmd) {
+ case AltosLib.AO_LOG_GPS_POS:
+ case AltosLib.AO_LOG_GPS_LAT:
+ case AltosLib.AO_LOG_GPS_LON:
+ case AltosLib.AO_LOG_GPS_ALT:
+ case AltosLib.AO_LOG_GPS_SAT:
+ case AltosLib.AO_LOG_GPS_DATE:
+ break;
+ default:
+ state.set_temp_gps();
+ break;
+ }
+ }
+
+ switch (cmd) {
+ case AltosLib.AO_LOG_FLIGHT:
+ state.set_flight(flight());
+ state.set_ground_accel(ground_accel());
+ state.set_ground_pressure(ground_pres());
+// state.set_temperature(ground_temp() / 100.0);
+ break;
+ case AltosLib.AO_LOG_STATE:
+ state.set_state(state());
+ break;
+ case AltosLib.AO_LOG_SENSOR:
+ state.set_ms5607(pres(), temp());
+ state.set_accel(accel());
+
+ break;
+ case AltosLib.AO_LOG_TEMP_VOLT:
+ state.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt()));
+
+ state.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense_a()));
+ state.set_main_voltage(AltosConvert.mega_pyro_voltage(sense_m()));
+
+ break;
+ case AltosLib.AO_LOG_GPS_POS:
+ gps = state.make_temp_gps(false);
+ gps.lat = latitude() / 1e7;
+ gps.lon = longitude() / 1e7;
+ gps.alt = altitude();
+ break;
+ case AltosLib.AO_LOG_GPS_TIME:
+ gps = state.make_temp_gps(false);
+
+ gps.hour = hour();
+ gps.minute = minute();
+ gps.second = second();
+
+ int flags = flags();
+
+ gps.connected = (flags & AltosLib.AO_GPS_RUNNING) != 0;
+ gps.locked = (flags & AltosLib.AO_GPS_VALID) != 0;
+ gps.nsat = (flags & AltosLib.AO_GPS_NUM_SAT_MASK) >>
+ AltosLib.AO_GPS_NUM_SAT_SHIFT;
+
+ gps.year = 2000 + year();
+ gps.month = month();
+ gps.day = day();
+ break;
+ case AltosLib.AO_LOG_GPS_SAT:
+ gps = state.make_temp_gps(true);
+
+ int n = nsat();
+ for (int i = 0; i < n; i++)
+ gps.add_sat(svid(i), c_n(i));
+ break;
+ }
+ }
+
+ public AltosEepromMetrum2 (String line) {
+ parse_string(line);
+ }
+
+ static public LinkedList<AltosEeprom> read(FileInputStream input) {
+ LinkedList<AltosEeprom> metrums = new LinkedList<AltosEeprom>();
+
+ for (;;) {
+ try {
+ String line = AltosLib.gets(input);
+ if (line == null)
+ break;
+ try {
+ AltosEepromMetrum2 metrum = new AltosEepromMetrum2(line);
+
+ if (metrum.cmd != AltosLib.AO_LOG_INVALID)
+ metrums.add(metrum);
+ } catch (Exception e) {
+ System.out.printf ("exception\n");
+ }
+ } catch (IOException ie) {
+ break;
+ }
+ }
+
+ return metrums;
+ }
+}
diff --git a/altoslib/AltosEepromMini.java b/altoslib/AltosEepromMini.java
new file mode 100644
index 00000000..a09a62ce
--- /dev/null
+++ b/altoslib/AltosEepromMini.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altoslib_2;
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
+public class AltosEepromMini extends AltosEeprom {
+ public static final int record_length = 16;
+
+ public int record_length() { return record_length; }
+
+ /* AO_LOG_FLIGHT elements */
+ public int flight() { return data16(0); }
+ public int ground_pres() { return data32(4); }
+
+ /* AO_LOG_STATE elements */
+ public int state() { return data16(0); }
+ public int reason() { return data16(2); }
+
+ /* AO_LOG_SENSOR elements */
+ public int pres() { return data24(0); }
+ public int temp() { return data24(3); }
+ public int sense_a() { return data16(6); }
+ public int sense_m() { return data16(8); }
+ public int v_batt() { return data16(10); }
+
+ double voltage(AltosState state, int sensor) {
+ if (state.log_format == AltosLib.AO_LOG_FORMAT_EASYMINI)
+ return AltosConvert.easy_mini_voltage(sensor);
+ else
+ return AltosConvert.tele_mini_voltage(sensor);
+ }
+
+ public void update_state(AltosState state) {
+ super.update_state(state);
+
+ switch (cmd) {
+ case AltosLib.AO_LOG_FLIGHT:
+ state.set_flight(flight());
+ state.set_ground_pressure(ground_pres());
+ break;
+ case AltosLib.AO_LOG_STATE:
+ state.set_state(state());
+ break;
+ case AltosLib.AO_LOG_SENSOR:
+ state.set_ms5607(pres(), temp());
+ state.set_apogee_voltage(voltage(state, sense_a()));
+ state.set_main_voltage(voltage(state, sense_m()));
+ state.set_battery_voltage(voltage(state, v_batt()));
+ break;
+ }
+ }
+
+ public AltosEepromMini (AltosEepromChunk chunk, int start) throws ParseException {
+ parse_chunk(chunk, start);
+ }
+
+ public AltosEepromMini (String line) {
+ parse_string(line);
+ }
+
+ public AltosEepromMini(int in_cmd, int in_tick) {
+ cmd = in_cmd;
+ tick = in_tick;
+ valid = true;
+ }
+
+ static public LinkedList<AltosEeprom> read(FileInputStream input) {
+ LinkedList<AltosEeprom> minis = new LinkedList<AltosEeprom>();
+
+ for (;;) {
+ try {
+ String line = AltosLib.gets(input);
+ if (line == null)
+ break;
+ AltosEepromMini mini = new AltosEepromMini(line);
+ minis.add(mini);
+ } catch (IOException ie) {
+ break;
+ }
+ }
+
+ return minis;
+ }
+}
diff --git a/altoslib/AltosEepromMonitor.java b/altoslib/AltosEepromMonitor.java
new file mode 100644
index 00000000..eeef0678
--- /dev/null
+++ b/altoslib/AltosEepromMonitor.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright © 2013 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_2;
+
+public interface AltosEepromMonitor {
+
+ public void set_states(int min_state, int max_state);
+
+ public void set_value(String in_state_name, int in_state, int in_state_block, int in_block);
+
+ public void set_serial(int in_serial);
+
+ public void set_flight(int in_flight);
+
+ public void set_filename(String in_file);
+
+ public void set_thread(Thread eeprom_thread);
+
+ final static int INFO_MESSAGE = 0;
+ final static int WARNING_MESSAGE = 1;
+ final static int ERROR_MESSAGE = 2;
+
+ public void show_message(String message, String title, int message_type);
+
+ public void start();
+
+ public void done(boolean success);
+
+ public void reset();
+}
diff --git a/altoslib/AltosEepromRecord.java b/altoslib/AltosEepromRecord.java
deleted file mode 100644
index 70ac1113..00000000
--- a/altoslib/AltosEepromRecord.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright © 2010 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.altoslib_1;
-
-import java.text.*;
-
-public class AltosEepromRecord {
- public int cmd;
- public int tick;
- public int a;
- public int b;
- public String data;
- public boolean tick_valid;
-
- public static final int record_length = 8;
-
- public AltosEepromRecord (AltosEepromChunk chunk, int start) throws ParseException {
-
- cmd = chunk.data(start);
- tick_valid = true;
-
- tick_valid = !chunk.erased(start, record_length);
- if (tick_valid) {
- if (AltosConvert.checksum(chunk.data, start, record_length) != 0)
- throw new ParseException(String.format("invalid checksum at 0x%x",
- chunk.address + start), 0);
- } else {
- cmd = AltosLib.AO_LOG_INVALID;
- }
-
- tick = chunk.data16(start + 2);
- a = chunk.data16(start + 4);
- b = chunk.data16(start + 6);
-
- data = null;
- }
-
- public AltosEepromRecord (String line) {
- tick_valid = false;
- tick = 0;
- a = 0;
- b = 0;
- data = null;
- if (line == null) {
- cmd = AltosLib.AO_LOG_INVALID;
- data = "";
- } else {
- try {
- String[] tokens = line.split("\\s+");
-
- if (tokens[0].length() == 1) {
- if (tokens.length != 4) {
- cmd = AltosLib.AO_LOG_INVALID;
- data = line;
- } else {
- cmd = tokens[0].codePointAt(0);
- tick = Integer.parseInt(tokens[1],16);
- tick_valid = true;
- a = Integer.parseInt(tokens[2],16);
- b = Integer.parseInt(tokens[3],16);
- }
- } else if (tokens[0].equals("Config") && tokens[1].equals("version:")) {
- cmd = AltosLib.AO_LOG_CONFIG_VERSION;
- data = tokens[2];
- } else if (tokens[0].equals("Main") && tokens[1].equals("deploy:")) {
- cmd = AltosLib.AO_LOG_MAIN_DEPLOY;
- 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]);
- } else if (tokens[0].equals("Radio") && tokens[1].equals("channel:")) {
- cmd = AltosLib.AO_LOG_RADIO_CHANNEL;
- 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]);
- } else if (tokens[0].equals("Radio") && tokens[1].equals("cal:")) {
- cmd = AltosLib.AO_LOG_RADIO_CAL;
- 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]);
- } else if (tokens[0].equals("manufacturer")) {
- cmd = AltosLib.AO_LOG_MANUFACTURER;
- data = tokens[1];
- } else if (tokens[0].equals("product")) {
- cmd = AltosLib.AO_LOG_PRODUCT;
- data = tokens[1];
- } else if (tokens[0].equals("serial-number")) {
- cmd = AltosLib.AO_LOG_SERIAL_NUMBER;
- a = Integer.parseInt(tokens[1]);
- } else if (tokens[0].equals("log-format")) {
- cmd = AltosLib.AO_LOG_LOG_FORMAT;
- a = Integer.parseInt(tokens[1]);
- } else if (tokens[0].equals("software-version")) {
- cmd = AltosLib.AO_LOG_SOFTWARE_VERSION;
- data = tokens[1];
- } else {
- cmd = AltosLib.AO_LOG_INVALID;
- data = line;
- }
- } catch (NumberFormatException ne) {
- cmd = AltosLib.AO_LOG_INVALID;
- data = line;
- }
- }
- }
-
- public AltosEepromRecord(int in_cmd, int in_tick, int in_a, int in_b) {
- tick_valid = true;
- cmd = in_cmd;
- tick = in_tick;
- a = in_a;
- b = in_b;
- }
-}
diff --git a/altoslib/AltosEepromTM.java b/altoslib/AltosEepromTM.java
new file mode 100644
index 00000000..36803912
--- /dev/null
+++ b/altoslib/AltosEepromTM.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altoslib_2;
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
+public class AltosEepromTM extends AltosEeprom {
+ public int a;
+ public int b;
+
+ public static final int record_length = 8;
+
+ public void write(PrintStream out) {
+ out.printf("%c %4x %4x %4x\n", cmd, tick, a, b);
+ }
+
+ public int record_length() { return record_length; }
+
+ public String string() {
+ return String.format("%c %4x %4x %4x\n", cmd, tick, a, b);
+ }
+
+ public void update_state(AltosState state) {
+ super.update_state(state);
+
+ AltosGPS gps;
+
+ /* Flush any pending GPS changes */
+ if (state.gps_pending) {
+ switch (cmd) {
+ case AltosLib.AO_LOG_GPS_LAT:
+ case AltosLib.AO_LOG_GPS_LON:
+ case AltosLib.AO_LOG_GPS_ALT:
+ case AltosLib.AO_LOG_GPS_SAT:
+ case AltosLib.AO_LOG_GPS_DATE:
+ break;
+ default:
+ state.set_temp_gps();
+ break;
+ }
+ }
+
+ switch (cmd) {
+ case AltosLib.AO_LOG_FLIGHT:
+ state.set_state(AltosLib.ao_flight_pad);
+ state.set_ground_accel(a);
+ state.set_flight(b);
+ state.set_boost_tick(tick);
+ break;
+ case AltosLib.AO_LOG_SENSOR:
+ state.set_accel(a);
+ state.set_pressure(AltosConvert.barometer_to_pressure(b));
+ break;
+ case AltosLib.AO_LOG_PRESSURE:
+ state.set_pressure(AltosConvert.barometer_to_pressure(b));
+ break;
+ case AltosLib.AO_LOG_TEMP_VOLT:
+ state.set_temperature(AltosConvert.thermometer_to_temperature(a));
+ state.set_battery_voltage(AltosConvert.cc_battery_to_voltage(b));
+ break;
+ case AltosLib.AO_LOG_DEPLOY:
+ state.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(a));
+ state.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(b));
+ break;
+ case AltosLib.AO_LOG_STATE:
+ state.set_state(a);
+ break;
+ case AltosLib.AO_LOG_GPS_TIME:
+ gps = state.make_temp_gps(false);
+
+ gps.hour = (a & 0xff);
+ gps.minute = (a >> 8);
+ gps.second = (b & 0xff);
+
+ int flags = (b >> 8);
+
+ gps.connected = (flags & AltosLib.AO_GPS_RUNNING) != 0;
+ gps.locked = (flags & AltosLib.AO_GPS_VALID) != 0;
+ gps.nsat = (flags & AltosLib.AO_GPS_NUM_SAT_MASK) >>
+ AltosLib.AO_GPS_NUM_SAT_SHIFT;
+ break;
+ case AltosLib.AO_LOG_GPS_LAT:
+ gps = state.make_temp_gps(false);
+
+ int lat32 = a | (b << 16);
+ gps.lat = (double) lat32 / 1e7;
+ break;
+ case AltosLib.AO_LOG_GPS_LON:
+ gps = state.make_temp_gps(false);
+
+ int lon32 = a | (b << 16);
+ gps.lon = (double) lon32 / 1e7;
+ break;
+ case AltosLib.AO_LOG_GPS_ALT:
+ gps = state.make_temp_gps(false);
+ gps.alt = a;
+ break;
+ case AltosLib.AO_LOG_GPS_SAT:
+ gps = state.make_temp_gps(true);
+ int svid = a;
+ int c_n0 = b >> 8;
+ gps.add_sat(svid, c_n0);
+ break;
+ case AltosLib.AO_LOG_GPS_DATE:
+ gps = state.make_temp_gps(false);
+ gps.year = (a & 0xff) + 2000;
+ gps.month = a >> 8;
+ gps.day = b & 0xff;
+ break;
+ }
+ }
+
+ public AltosEepromTM (AltosEepromChunk chunk, int start) throws ParseException {
+
+ cmd = chunk.data(start);
+ valid = true;
+
+ valid = !chunk.erased(start, record_length);
+ if (valid) {
+ if (AltosConvert.checksum(chunk.data, start, record_length) != 0)
+ throw new ParseException(String.format("invalid checksum at 0x%x",
+ chunk.address + start), 0);
+ } else {
+ cmd = AltosLib.AO_LOG_INVALID;
+ }
+
+ tick = chunk.data16(start + 2);
+ a = chunk.data16(start + 4);
+ b = chunk.data16(start + 6);
+ }
+
+ public AltosEepromTM (String line) {
+ valid = false;
+ tick = 0;
+ a = 0;
+ b = 0;
+ if (line == null) {
+ cmd = AltosLib.AO_LOG_INVALID;
+ } else {
+ try {
+ String[] tokens = line.split("\\s+");
+
+ if (tokens[0].length() == 1) {
+ if (tokens.length != 4) {
+ cmd = AltosLib.AO_LOG_INVALID;
+ } else {
+ cmd = tokens[0].codePointAt(0);
+ tick = Integer.parseInt(tokens[1],16);
+ valid = true;
+ a = Integer.parseInt(tokens[2],16);
+ b = Integer.parseInt(tokens[3],16);
+ }
+ } else {
+ cmd = AltosLib.AO_LOG_INVALID;
+ }
+ } catch (NumberFormatException ne) {
+ cmd = AltosLib.AO_LOG_INVALID;
+ }
+ }
+ }
+
+ public AltosEepromTM(int in_cmd, int in_tick, int in_a, int in_b) {
+ valid = true;
+ cmd = in_cmd;
+ tick = in_tick;
+ a = in_a;
+ b = in_b;
+ }
+
+ static public LinkedList<AltosEeprom> read(FileInputStream input) {
+ LinkedList<AltosEeprom> tms = new LinkedList<AltosEeprom>();
+
+ for (;;) {
+ try {
+ String line = AltosLib.gets(input);
+ if (line == null)
+ break;
+ AltosEepromTM tm = new AltosEepromTM(line);
+ tms.add(tm);
+ } catch (IOException ie) {
+ break;
+ }
+ }
+
+ return tms;
+ }
+
+}
diff --git a/altoslib/AltosEepromTeleScience.java b/altoslib/AltosEepromTeleScience.java
deleted file mode 100644
index 2a828cf3..00000000
--- a/altoslib/AltosEepromTeleScience.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.altoslib_1;
-
-import java.text.*;
-
-public class AltosEepromTeleScience {
- public int type;
- public int tick;
- public int tm_state;
- public int tm_tick;
- public int[] data;
- public boolean valid;
-
- public static final int AO_LOG_TELESCIENCE_START = 's';
- public static final int AO_LOG_TELESCIENCE_DATA = 'd';
-
- static final int max_data = 12;
- public static final int record_length = 32;
-
- public AltosEepromTeleScience (AltosEepromChunk chunk, int start) throws ParseException {
- type = chunk.data(start);
-
- valid = !chunk.erased(start, record_length);
- if (valid) {
- if (AltosConvert.checksum(chunk.data, start, record_length) != 0)
- throw new ParseException(String.format("invalid checksum at 0x%x",
- chunk.address + start), 0);
- } else {
- type = AltosLib.AO_LOG_INVALID;
- }
-
- tick = chunk.data16(start+2);
- tm_tick = chunk.data16(start+4);
- tm_state = chunk.data(start+6);
- data = new int[max_data];
- for (int i = 0; i < max_data; i++)
- data[i] = chunk.data16(start + 8 + i * 2);
- }
-}
diff --git a/altoslib/AltosEepromTm.java b/altoslib/AltosEepromTm.java
new file mode 100644
index 00000000..b8914131
--- /dev/null
+++ b/altoslib/AltosEepromTm.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altoslib_2;
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
+public class AltosEepromTm extends AltosEeprom {
+ public int i;
+ public int a;
+ public int b;
+
+ public static final int record_length = 2;
+
+ public void write(PrintStream out) {
+ out.printf("%c %4x %4x %4x\n", cmd, tick, a, b);
+ }
+
+ public int record_length() { return record_length; }
+
+ public String string() {
+ return String.format("%c %4x %4x %4x\n", cmd, tick, a, b);
+ }
+
+ public void update_state(AltosState state) {
+ super.update_state(state);
+
+ switch (cmd) {
+ case AltosLib.AO_LOG_FLIGHT:
+ state.set_state(AltosLib.ao_flight_boost);
+ state.set_flight(b);
+ break;
+ case AltosLib.AO_LOG_PRESSURE:
+ if (tick == 0)
+ state.set_ground_pressure(AltosConvert.barometer_to_pressure(b));
+ else
+ state.set_pressure(AltosConvert.barometer_to_pressure(b));
+ break;
+ case AltosLib.AO_LOG_STATE:
+ state.set_state(a);
+ break;
+ }
+ }
+
+ public AltosEepromTm (AltosEepromChunk chunk, int start, AltosState state) throws ParseException {
+ int value = chunk.data16(start);
+
+ int i = (chunk.address + start) / record_length;
+
+ cmd = chunk.data(start);
+ valid = true;
+
+ valid = !chunk.erased(start, record_length);
+
+ switch (i) {
+ case 0:
+ cmd = AltosLib.AO_LOG_FLIGHT;
+ tick = 0;
+ a = 0;
+ b = value;
+ break;
+ case 1:
+ cmd = AltosLib.AO_LOG_PRESSURE;
+ tick = 0;
+ a = 0;
+ b = value;
+ break;
+ default:
+ if ((value & 0x8000) != 0) {
+ cmd = AltosLib.AO_LOG_STATE;
+ tick = state.tick;
+ a = value & 0x7fff;
+ b = 0;
+ } else {
+ if (state.ascent)
+ tick = state.tick + 10;
+ else
+ tick = state.tick + 100;
+ cmd = AltosLib.AO_LOG_PRESSURE;
+ a = 0;
+ b = value;
+ }
+ break;
+ }
+ }
+
+ public AltosEepromTm (String line) {
+ valid = false;
+ tick = 0;
+ a = 0;
+ b = 0;
+ if (line == null) {
+ cmd = AltosLib.AO_LOG_INVALID;
+ } else {
+ try {
+ String[] tokens = line.split("\\s+");
+
+ if (tokens[0].length() == 1) {
+ if (tokens.length != 4) {
+ cmd = AltosLib.AO_LOG_INVALID;
+ } else {
+ cmd = tokens[0].codePointAt(0);
+ tick = Integer.parseInt(tokens[1],16);
+ valid = true;
+ a = Integer.parseInt(tokens[2],16);
+ b = Integer.parseInt(tokens[3],16);
+ }
+ } else {
+ cmd = AltosLib.AO_LOG_INVALID;
+ }
+ } catch (NumberFormatException ne) {
+ cmd = AltosLib.AO_LOG_INVALID;
+ }
+ }
+ }
+
+ public AltosEepromTm(int in_cmd, int in_tick, int in_a, int in_b) {
+ valid = true;
+ cmd = in_cmd;
+ tick = in_tick;
+ a = in_a;
+ b = in_b;
+ }
+
+ static public LinkedList<AltosEeprom> read(FileInputStream input) {
+ LinkedList<AltosEeprom> tms = new LinkedList<AltosEeprom>();
+
+ for (;;) {
+ try {
+ String line = AltosLib.gets(input);
+ if (line == null)
+ break;
+ AltosEepromTm tm = new AltosEepromTm(line);
+ tms.add(tm);
+ } catch (IOException ie) {
+ break;
+ }
+ }
+
+ return tms;
+ }
+
+}
diff --git a/altoslib/AltosFile.java b/altoslib/AltosFile.java
index 90dbc6db..f39c3962 100644
--- a/altoslib/AltosFile.java
+++ b/altoslib/AltosFile.java
@@ -15,17 +15,44 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
import java.io.File;
import java.util.*;
public class AltosFile extends File {
- public AltosFile(int year, int month, int day, int serial, int flight, String extension) {
+ static String number(int n) {
+ if (n == AltosLib.MISSING)
+ return "unkn";
+ else
+ return String.format("%04d", n);
+ }
+
+ static String receiver(int receiver) {
+ if (receiver == AltosLib.MISSING)
+ return "";
+ return String.format("-via-%04d", receiver);
+ }
+
+ public AltosFile(int year, int month, int day, int serial, int flight, int receiver, String extension) {
super (AltosPreferences.logdir(),
- String.format("%04d-%02d-%02d-serial-%03d-flight-%03d.%s",
- year, month, day, serial, flight, extension));
+ String.format("%04d-%02d-%02d-serial-%s-flight-%s%s.%s",
+ year, month, day, number(serial), number(flight), receiver(receiver), extension));
+ }
+
+ public AltosFile(int year, int month, int day, int serial, int flight, String extension) {
+ this(year, month, day, serial, flight, AltosLib.MISSING, extension);
+ }
+
+ public AltosFile(int serial, int flight, int receiver, String extension) {
+ this(Calendar.getInstance().get(Calendar.YEAR),
+ Calendar.getInstance().get(Calendar.MONTH) + 1,
+ Calendar.getInstance().get(Calendar.DAY_OF_MONTH),
+ serial,
+ flight,
+ receiver,
+ extension);
}
public AltosFile(int serial, int flight, String extension) {
@@ -34,10 +61,11 @@ public class AltosFile extends File {
Calendar.getInstance().get(Calendar.DAY_OF_MONTH),
serial,
flight,
+ AltosLib.MISSING,
extension);
}
- public AltosFile(AltosRecord telem) {
- this(telem.serial, telem.flight, "telem");
+ public AltosFile(AltosState state) {
+ this(state.serial, state.flight, state.receiver_serial, "telem");
}
}
diff --git a/altoslib/AltosFlash.java b/altoslib/AltosFlash.java
index 010274b9..0977070e 100644
--- a/altoslib/AltosFlash.java
+++ b/altoslib/AltosFlash.java
@@ -15,11 +15,11 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
import java.io.*;
-public class AltosFlash {
+public class AltosFlash extends AltosProgrammer {
File file;
FileInputStream input;
AltosHexfile image;
@@ -318,7 +318,7 @@ public class AltosFlash {
close();
}
- public boolean check_rom_config() {
+ public boolean check_rom_config() throws InterruptedException {
if (debug == null)
return true;
if (rom_config == null)
@@ -330,7 +330,7 @@ public class AltosFlash {
rom_config = romconfig;
}
- public AltosRomconfig romconfig() {
+ public AltosRomconfig romconfig() throws InterruptedException {
if (!check_rom_config())
return null;
return rom_config;
diff --git a/altoslib/AltosFlashListener.java b/altoslib/AltosFlashListener.java
index ab50b74a..777ae635 100644
--- a/altoslib/AltosFlashListener.java
+++ b/altoslib/AltosFlashListener.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
public interface AltosFlashListener {
public void position(String label, int percent);
diff --git a/altoslib/AltosFlightReader.java b/altoslib/AltosFlightReader.java
index 34526658..b251e7cc 100644
--- a/altoslib/AltosFlightReader.java
+++ b/altoslib/AltosFlightReader.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
import java.text.*;
import java.io.*;
@@ -28,7 +28,7 @@ public class AltosFlightReader {
public void init() { }
- public AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException { return null; }
+ public AltosState read() throws InterruptedException, ParseException, AltosCRCException, IOException { return null; }
public void close(boolean interrupted) { }
@@ -46,7 +46,7 @@ public class AltosFlightReader {
public File backing_file() { return null; }
- public boolean has_monitor_battery() { return false; }
+ public boolean has_monitor_battery() throws InterruptedException { return false; }
- public double monitor_battery() { return AltosRecord.MISSING; }
+ public double monitor_battery() throws InterruptedException { return AltosLib.MISSING; }
}
diff --git a/altoslib/AltosFrequency.java b/altoslib/AltosFrequency.java
index 484a2fd9..ece7525a 100644
--- a/altoslib/AltosFrequency.java
+++ b/altoslib/AltosFrequency.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
public class AltosFrequency {
public double frequency;
diff --git a/altoslib/AltosGPS.java b/altoslib/AltosGPS.java
index f23842f3..f5162225 100644
--- a/altoslib/AltosGPS.java
+++ b/altoslib/AltosGPS.java
@@ -15,20 +15,21 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
import java.text.*;
+import java.util.concurrent.*;
-public class AltosGPS {
+public class AltosGPS implements Cloneable {
- public final static int MISSING = AltosRecord.MISSING;
+ public final static int MISSING = AltosLib.MISSING;
public int nsat;
public boolean locked;
public boolean connected;
public double lat; /* degrees (+N -S) */
public double lon; /* degrees (+E -W) */
- public int alt; /* m */
+ public double alt; /* m */
public int year;
public int month;
public int day;
@@ -65,40 +66,40 @@ public class AltosGPS {
}
public void ClearGPSTime() {
- year = month = day = 0;
- hour = minute = second = 0;
+ year = month = day = AltosLib.MISSING;
+ hour = minute = second = AltosLib.MISSING;
}
public AltosGPS(AltosTelemetryMap map) throws ParseException {
- String state = map.get_string(AltosTelemetry.AO_TELEM_GPS_STATE,
- AltosTelemetry.AO_TELEM_GPS_STATE_ERROR);
+ String state = map.get_string(AltosTelemetryLegacy.AO_TELEM_GPS_STATE,
+ AltosTelemetryLegacy.AO_TELEM_GPS_STATE_ERROR);
- nsat = map.get_int(AltosTelemetry.AO_TELEM_GPS_NUM_SAT, 0);
- if (state.equals(AltosTelemetry.AO_TELEM_GPS_STATE_LOCKED)) {
+ nsat = map.get_int(AltosTelemetryLegacy.AO_TELEM_GPS_NUM_SAT, 0);
+ if (state.equals(AltosTelemetryLegacy.AO_TELEM_GPS_STATE_LOCKED)) {
connected = true;
locked = true;
- lat = map.get_double(AltosTelemetry.AO_TELEM_GPS_LATITUDE, MISSING, 1.0e-7);
- lon = map.get_double(AltosTelemetry.AO_TELEM_GPS_LONGITUDE, MISSING, 1.0e-7);
- alt = map.get_int(AltosTelemetry.AO_TELEM_GPS_ALTITUDE, MISSING);
- year = map.get_int(AltosTelemetry.AO_TELEM_GPS_YEAR, MISSING);
+ lat = map.get_double(AltosTelemetryLegacy.AO_TELEM_GPS_LATITUDE, MISSING, 1.0e-7);
+ lon = map.get_double(AltosTelemetryLegacy.AO_TELEM_GPS_LONGITUDE, MISSING, 1.0e-7);
+ alt = map.get_int(AltosTelemetryLegacy.AO_TELEM_GPS_ALTITUDE, MISSING);
+ year = map.get_int(AltosTelemetryLegacy.AO_TELEM_GPS_YEAR, MISSING);
if (year != MISSING)
year += 2000;
- month = map.get_int(AltosTelemetry.AO_TELEM_GPS_MONTH, MISSING);
- day = map.get_int(AltosTelemetry.AO_TELEM_GPS_DAY, MISSING);
-
- hour = map.get_int(AltosTelemetry.AO_TELEM_GPS_HOUR, 0);
- minute = map.get_int(AltosTelemetry.AO_TELEM_GPS_MINUTE, 0);
- second = map.get_int(AltosTelemetry.AO_TELEM_GPS_SECOND, 0);
-
- ground_speed = map.get_double(AltosTelemetry.AO_TELEM_GPS_HORIZONTAL_SPEED,
- AltosRecord.MISSING, 1/100.0);
- course = map.get_int(AltosTelemetry.AO_TELEM_GPS_COURSE,
- AltosRecord.MISSING);
- hdop = map.get_double(AltosTelemetry.AO_TELEM_GPS_HDOP, MISSING, 1.0);
- vdop = map.get_double(AltosTelemetry.AO_TELEM_GPS_VDOP, MISSING, 1.0);
- h_error = map.get_int(AltosTelemetry.AO_TELEM_GPS_HERROR, MISSING);
- v_error = map.get_int(AltosTelemetry.AO_TELEM_GPS_VERROR, MISSING);
- } else if (state.equals(AltosTelemetry.AO_TELEM_GPS_STATE_UNLOCKED)) {
+ month = map.get_int(AltosTelemetryLegacy.AO_TELEM_GPS_MONTH, MISSING);
+ day = map.get_int(AltosTelemetryLegacy.AO_TELEM_GPS_DAY, MISSING);
+
+ hour = map.get_int(AltosTelemetryLegacy.AO_TELEM_GPS_HOUR, 0);
+ minute = map.get_int(AltosTelemetryLegacy.AO_TELEM_GPS_MINUTE, 0);
+ second = map.get_int(AltosTelemetryLegacy.AO_TELEM_GPS_SECOND, 0);
+
+ ground_speed = map.get_double(AltosTelemetryLegacy.AO_TELEM_GPS_HORIZONTAL_SPEED,
+ AltosLib.MISSING, 1/100.0);
+ course = map.get_int(AltosTelemetryLegacy.AO_TELEM_GPS_COURSE,
+ AltosLib.MISSING);
+ hdop = map.get_double(AltosTelemetryLegacy.AO_TELEM_GPS_HDOP, MISSING, 1.0);
+ vdop = map.get_double(AltosTelemetryLegacy.AO_TELEM_GPS_VDOP, MISSING, 1.0);
+ h_error = map.get_int(AltosTelemetryLegacy.AO_TELEM_GPS_HERROR, MISSING);
+ v_error = map.get_int(AltosTelemetryLegacy.AO_TELEM_GPS_VERROR, MISSING);
+ } else if (state.equals(AltosTelemetryLegacy.AO_TELEM_GPS_STATE_UNLOCKED)) {
connected = true;
locked = false;
} else {
@@ -107,6 +108,62 @@ public class AltosGPS {
}
}
+ public boolean parse_string (String line, boolean says_done) {
+ String[] bits = line.split("\\s+");
+ if (bits.length == 0)
+ return false;
+ if (line.startsWith("Date:")) {
+ if (bits.length < 2)
+ return false;
+ String[] d = bits[1].split("/");
+ if (d.length < 3)
+ return false;
+ year = Integer.parseInt(d[0]) + 2000;
+ month = Integer.parseInt(d[1]);
+ day = Integer.parseInt(d[2]);
+ } else if (line.startsWith("Time:")) {
+ if (bits.length < 2)
+ return false;
+ String[] d = bits[1].split(":");
+ if (d.length < 3)
+ return false;
+ hour = Integer.parseInt(d[0]);
+ minute = Integer.parseInt(d[1]);
+ second = Integer.parseInt(d[2]);
+ } else if (line.startsWith("Lat/Lon:")) {
+ if (bits.length < 3)
+ return false;
+ lat = Integer.parseInt(bits[1]) * 1.0e-7;
+ lon = Integer.parseInt(bits[2]) * 1.0e-7;
+ } else if (line.startsWith("Alt:")) {
+ if (bits.length < 2)
+ return false;
+ alt = Integer.parseInt(bits[1]);
+ } else if (line.startsWith("Flags:")) {
+ if (bits.length < 2)
+ return false;
+ int status = Integer.decode(bits[1]);
+ connected = (status & AltosLib.AO_GPS_RUNNING) != 0;
+ locked = (status & AltosLib.AO_GPS_VALID) != 0;
+ if (!says_done)
+ return false;
+ } else if (line.startsWith("Sats:")) {
+ if (bits.length < 2)
+ return false;
+ nsat = Integer.parseInt(bits[1]);
+ cc_gps_sat = new AltosGPSSat[nsat];
+ for (int i = 0; i < nsat; i++) {
+ int svid = Integer.parseInt(bits[2+i*2]);
+ int cc_n0 = Integer.parseInt(bits[3+i*2]);
+ cc_gps_sat[i] = new AltosGPSSat(svid, cc_n0);
+ }
+ } else if (line.startsWith("done")) {
+ return false;
+ } else
+ return false;
+ return true;
+ }
+
public AltosGPS(String[] words, int i, int version) throws ParseException {
AltosParse.word(words[i++], "GPS");
nsat = AltosParse.parse_int(words[i++]);
@@ -212,10 +269,46 @@ public class AltosGPS {
}
public AltosGPS() {
+ lat = AltosLib.MISSING;
+ lon = AltosLib.MISSING;
+ alt = AltosLib.MISSING;
ClearGPSTime();
cc_gps_sat = null;
}
+ public AltosGPS clone() {
+ AltosGPS g = new AltosGPS();
+
+ g.nsat = nsat;
+ g.locked = locked;
+ g.connected = connected;
+ g.lat = lat; /* degrees (+N -S) */
+ g.lon = lon; /* degrees (+E -W) */
+ g.alt = alt; /* m */
+ g.year = year;
+ g.month = month;
+ g.day = day;
+ g.hour = hour;
+ g.minute = minute;
+ g.second = second;
+
+ g.ground_speed = ground_speed; /* m/s */
+ g.course = course; /* degrees */
+ g.climb_rate = climb_rate; /* m/s */
+ g.hdop = hdop; /* unitless? */
+ g.h_error = h_error; /* m */
+ g.v_error = v_error; /* m */
+
+ if (cc_gps_sat != null) {
+ g.cc_gps_sat = new AltosGPSSat[cc_gps_sat.length];
+ for (int i = 0; i < cc_gps_sat.length; i++) {
+ g.cc_gps_sat[i] = new AltosGPSSat(cc_gps_sat[i].svid,
+ cc_gps_sat[i].c_n0);
+ }
+ }
+ return g;
+ }
+
public AltosGPS(AltosGPS old) {
if (old != null) {
nsat = old.nsat;
@@ -247,8 +340,36 @@ public class AltosGPS {
}
}
} else {
+ lat = AltosLib.MISSING;
+ lon = AltosLib.MISSING;
+ alt = AltosLib.MISSING;
ClearGPSTime();
cc_gps_sat = null;
}
}
+
+ static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException {
+ try {
+ AltosGPS gps = new AltosGPS(link, config_data);
+
+ if (gps != null) {
+ state.set_gps(gps, state.gps_sequence++);
+ return;
+ }
+ } catch (TimeoutException te) {
+ }
+ state.set_gps(null, 0);
+ }
+
+ public AltosGPS (AltosLink link, AltosConfigData config_data) throws TimeoutException, InterruptedException {
+ boolean says_done = config_data.compare_version("1.0") >= 0;
+ link.printf("g\n");
+ for (;;) {
+ String line = link.get_reply_no_dialog(5000);
+ if (line == null)
+ throw new TimeoutException();
+ if (!parse_string(line, says_done))
+ break;
+ }
+ }
}
diff --git a/altoslib/AltosGPSQuery.java b/altoslib/AltosGPSQuery.java
deleted file mode 100644
index deb9d201..00000000
--- a/altoslib/AltosGPSQuery.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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_1;
-
-import java.util.concurrent.*;
-
-class AltosGPSQuery extends AltosGPS {
- public AltosGPSQuery (AltosLink link, AltosConfigData config_data)
- throws TimeoutException, InterruptedException {
- boolean says_done = config_data.compare_version("1.0") >= 0;
- link.printf("g\n");
- for (;;) {
- String line = link.get_reply_no_dialog(5000);
- if (line == null)
- throw new TimeoutException();
- String[] bits = line.split("\\s+");
- if (bits.length == 0)
- continue;
- if (line.startsWith("Date:")) {
- if (bits.length < 2)
- continue;
- String[] d = bits[1].split(":");
- if (d.length < 3)
- continue;
- year = Integer.parseInt(d[0]) + 2000;
- month = Integer.parseInt(d[1]);
- day = Integer.parseInt(d[2]);
- continue;
- }
- if (line.startsWith("Time:")) {
- if (bits.length < 2)
- continue;
- String[] d = bits[1].split("/");
- if (d.length < 3)
- continue;
- hour = Integer.parseInt(d[0]);
- minute = Integer.parseInt(d[1]);
- second = Integer.parseInt(d[2]);
- continue;
- }
- if (line.startsWith("Lat/Lon:")) {
- if (bits.length < 3)
- continue;
- lat = Integer.parseInt(bits[1]) * 1.0e-7;
- lon = Integer.parseInt(bits[2]) * 1.0e-7;
- continue;
- }
- if (line.startsWith("Alt:")) {
- if (bits.length < 2)
- continue;
- alt = Integer.parseInt(bits[1]);
- continue;
- }
- if (line.startsWith("Flags:")) {
- if (bits.length < 2)
- continue;
- int status = Integer.decode(bits[1]);
- connected = (status & AltosLib.AO_GPS_RUNNING) != 0;
- locked = (status & AltosLib.AO_GPS_VALID) != 0;
- if (!says_done)
- break;
- continue;
- }
- if (line.startsWith("Sats:")) {
- if (bits.length < 2)
- continue;
- nsat = Integer.parseInt(bits[1]);
- cc_gps_sat = new AltosGPSSat[nsat];
- for (int i = 0; i < nsat; i++) {
- int svid = Integer.parseInt(bits[2+i*2]);
- int cc_n0 = Integer.parseInt(bits[3+i*2]);
- cc_gps_sat[i] = new AltosGPSSat(svid, cc_n0);
- }
- }
- if (line.startsWith("done"))
- break;
- if (line.startsWith("Syntax error"))
- break;
- }
- }
-}
-
diff --git a/altoslib/AltosGPSSat.java b/altoslib/AltosGPSSat.java
index 8714dd8a..0e17d7f2 100644
--- a/altoslib/AltosGPSSat.java
+++ b/altoslib/AltosGPSSat.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
public class AltosGPSSat {
public int svid;
diff --git a/altoslib/AltosGreatCircle.java b/altoslib/AltosGreatCircle.java
index f1cf0ae9..2c84bf4a 100644
--- a/altoslib/AltosGreatCircle.java
+++ b/altoslib/AltosGreatCircle.java
@@ -15,11 +15,11 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
import java.lang.Math;
-public class AltosGreatCircle {
+public class AltosGreatCircle implements Cloneable {
public double distance;
public double bearing;
public double range;
@@ -95,6 +95,16 @@ public class AltosGreatCircle {
elevation = Math.atan2(height_diff, distance) * 180 / Math.PI;
}
+ public AltosGreatCircle clone() {
+ AltosGreatCircle n = new AltosGreatCircle();
+
+ n.distance = distance;
+ n.bearing = bearing;
+ n.range = range;
+ n.elevation = elevation;
+ return n;
+ }
+
public AltosGreatCircle (double start_lat, double start_lon,
double end_lat, double end_lon) {
this(start_lat, start_lon, 0, end_lat, end_lon, 0);
diff --git a/altoslib/AltosHeight.java b/altoslib/AltosHeight.java
index ed590812..84bd42d9 100644
--- a/altoslib/AltosHeight.java
+++ b/altoslib/AltosHeight.java
@@ -15,29 +15,35 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
public class AltosHeight extends AltosUnits {
- public double value(double v) {
- if (AltosConvert.imperial_units)
+ public double value(double v, boolean imperial_units) {
+ if (imperial_units)
return AltosConvert.meters_to_feet(v);
return v;
}
- public String show_units() {
- if (AltosConvert.imperial_units)
+ public double inverse(double v, boolean imperial_units) {
+ if (imperial_units)
+ return AltosConvert.feet_to_meters(v);
+ return v;
+ }
+
+ public String show_units(boolean imperial_units) {
+ if (imperial_units)
return "ft";
return "m";
}
- public String say_units() {
- if (AltosConvert.imperial_units)
+ public String say_units(boolean imperial_units) {
+ if (imperial_units)
return "feet";
return "meters";
}
- public int show_fraction(int width) {
+ public int show_fraction(int width, boolean imperial_units) {
return width / 9;
}
} \ No newline at end of file
diff --git a/altoslib/AltosHexfile.java b/altoslib/AltosHexfile.java
index 2140228a..717c1c5d 100644
--- a/altoslib/AltosHexfile.java
+++ b/altoslib/AltosHexfile.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
import java.io.*;
import java.util.LinkedList;
@@ -116,7 +116,7 @@ class HexRecord implements Comparable<Object> {
return String.format("%04x: %02x (%d)", address, type, data.length);
}
- public HexRecord(HexFileInputStream input) throws IOException {
+ public HexRecord(HexFileInputStream input) throws IOException, EOFException {
read_state state = read_state.marker;
int nhexbytes = 0;
int hex = 0;
@@ -125,14 +125,16 @@ class HexRecord implements Comparable<Object> {
while (state != read_state.done) {
int c = input.read();
- if (c < 0 && state != read_state.white)
+ if (c < 0 && state != read_state.white && state != read_state.marker)
throw new IOException(String.format("%d: Unexpected EOF", input.line));
if (c == ' ')
continue;
switch (state) {
case marker:
+ if (c == EOF || c == -1)
+ throw new EOFException();
if (c != ':')
- throw new IOException("Missing ':'");
+ throw new IOException(String.format ("Missing ':' (got %x)", c));
state = read_state.length;
nhexbytes = 2;
hex = 0;
@@ -208,25 +210,82 @@ class HexRecord implements Comparable<Object> {
}
public class AltosHexfile {
- public int address;
- public byte[] data;
+ public int address;
+ public byte[] data;
+ LinkedList<AltosHexsym> symlist = new LinkedList<AltosHexsym>();
public byte get_byte(int a) {
return data[a - address];
}
+ /* CC1111-based products have the romconfig stuff located
+ * at a fixed address; when the file we load has no symbols,
+ * assume it is one of those and set the symbols appropriately
+ */
+ final static int ao_romconfig_version_addr = 0xa0;
+ final static int ao_romconfig_check_addr = 0xa2;
+ final static int ao_serial_number_addr = 0xa4;
+ final static int ao_radio_cal_addr = 0xa6;
+ final static int ao_usb_descriptors_addr = 0xaa;
+
+ static AltosHexsym[] cc_symbols = {
+ new AltosHexsym("ao_romconfig_version", ao_romconfig_version_addr),
+ new AltosHexsym("ao_romconfig_check", ao_romconfig_check_addr),
+ new AltosHexsym("ao_serial_number", ao_serial_number_addr),
+ new AltosHexsym("ao_radio_cal", ao_radio_cal_addr),
+ new AltosHexsym("ao_usb_descriptors", ao_usb_descriptors_addr)
+ };
+
+ private void add_cc_symbols() {
+ for (int i = 0; i < cc_symbols.length; i++)
+ symlist.add(cc_symbols[i]);
+ }
+
+ public void add_symbol(AltosHexsym symbol) {
+ symlist.add(symbol);
+ }
+
+ /* Take symbols from another hexfile and duplicate them here */
+ public void add_symbols(AltosHexfile other) {
+ for (AltosHexsym symbol : other.symlist)
+ symlist.add(symbol);
+ }
+
+ public AltosHexsym lookup_symbol(String name) {
+ if (symlist.isEmpty())
+ add_cc_symbols();
+
+ for (AltosHexsym symbol : symlist)
+ if (name.equals(symbol.name))
+ return symbol;
+ return null;
+ }
+
+ private String make_string(byte[] data, int start, int length) {
+ String s = "";
+ for (int i = 0; i < length; i++)
+ s += (char) data[start + i];
+ return s;
+ }
+
+ public AltosHexfile(byte[] bytes, int offset) {
+ data = bytes;
+ address = offset;
+ }
+
public AltosHexfile(FileInputStream file) throws IOException {
HexFileInputStream input = new HexFileInputStream(file);
LinkedList<HexRecord> record_list = new LinkedList<HexRecord>();
boolean done = false;
while (!done) {
- HexRecord record = new HexRecord(input);
+ try {
+ HexRecord record = new HexRecord(input);
- if (record.type == HexRecord.EOF)
- done = true;
- else
record_list.add(record);
+ } catch (EOFException eof) {
+ done = true;
+ }
}
long extended_addr = 0;
@@ -234,9 +293,10 @@ public class AltosHexfile {
long bound = 0;
boolean set = false;
for (HexRecord record : record_list) {
+ long addr;
switch (record.type) {
case 0:
- long addr = extended_addr + record.address;
+ addr = extended_addr + record.address;
long r_bound = addr + record.data.length;
if (!set || addr < base)
base = addr;
@@ -256,6 +316,12 @@ public class AltosHexfile {
throw new IOException("invalid extended segment address record");
extended_addr = ((record.data[0] << 8) + (record.data[1])) << 16;
break;
+ case 0xfe:
+ String name = make_string(record.data, 0, record.data.length);
+ addr = extended_addr + record.address;
+ AltosHexsym s = new AltosHexsym(name, addr);
+ symlist.add(s);
+ break;
default:
throw new IOException ("invalid hex record type");
}
@@ -292,6 +358,8 @@ public class AltosHexfile {
throw new IOException("invalid extended segment address record");
extended_addr = ((record.data[0] << 8) + (record.data[1])) << 16;
break;
+ case 0xfe:
+ break;
default:
throw new IOException ("invalid hex record type");
}
diff --git a/altoslib/AltosRecordNone.java b/altoslib/AltosHexsym.java
index a95b6a9c..810a4803 100644
--- a/altoslib/AltosRecordNone.java
+++ b/altoslib/AltosHexsym.java
@@ -1,5 +1,5 @@
/*
- * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ * Copyright © 2013 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
@@ -15,24 +15,16 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
-public class AltosRecordNone extends AltosRecord {
+public class AltosHexsym {
+ String name;
+ long address;
- public double pressure() { return MISSING; }
- public double ground_pressure() { return MISSING; }
- public double temperature() { return MISSING; }
- public double acceleration() { return MISSING; }
+ final static long invalid_addr = 0xffffffff;
- public AltosRecordNone(AltosRecord old) {
- super.copy(old);
+ public AltosHexsym(String name, long address) {
+ this.name = name;
+ this.address = address;
}
-
- public AltosRecordNone clone() {
- return new AltosRecordNone(this);
- }
-
- public AltosRecordNone() {
- super();
- }
-}
+} \ No newline at end of file
diff --git a/altoslib/AltosIMU.java b/altoslib/AltosIMU.java
index 8f6731fa..6d88ccae 100644
--- a/altoslib/AltosIMU.java
+++ b/altoslib/AltosIMU.java
@@ -15,9 +15,11 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
-public class AltosIMU {
+import java.util.concurrent.*;
+
+public class AltosIMU implements Cloneable {
public int accel_x;
public int accel_y;
public int accel_z;
@@ -25,5 +27,67 @@ public class AltosIMU {
public int gyro_x;
public int gyro_y;
public int gyro_z;
+
+ public boolean parse_string(String line) {
+ if (!line.startsWith("Accel:"))
+ return false;
+
+ String[] items = line.split("\\s+");
+
+ if (items.length >= 8) {
+ accel_x = Integer.parseInt(items[1]);
+ accel_y = Integer.parseInt(items[2]);
+ accel_z = Integer.parseInt(items[3]);
+ gyro_x = Integer.parseInt(items[5]);
+ gyro_y = Integer.parseInt(items[6]);
+ gyro_z = Integer.parseInt(items[7]);
+ }
+ return true;
+ }
+
+ public AltosIMU clone() {
+ AltosIMU n = new AltosIMU();
+
+ n.accel_x = accel_x;
+ n.accel_y = accel_y;
+ n.accel_z = accel_z;
+
+ n.gyro_x = gyro_x;
+ n.gyro_y = gyro_y;
+ n.gyro_z = gyro_z;
+ return n;
+ }
+
+ static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException {
+ try {
+ AltosIMU imu = new AltosIMU(link);
+
+ if (imu != null)
+ state.set_imu(imu);
+ } catch (TimeoutException te) {
+ }
+ }
+
+ public AltosIMU() {
+ accel_x = AltosLib.MISSING;
+ accel_y = AltosLib.MISSING;
+ accel_z = AltosLib.MISSING;
+
+ gyro_x = AltosLib.MISSING;
+ gyro_y = AltosLib.MISSING;
+ gyro_z = AltosLib.MISSING;
+ }
+
+ public AltosIMU(AltosLink link) throws InterruptedException, TimeoutException {
+ this();
+ link.printf("I\n");
+ for (;;) {
+ String line = link.get_reply_no_dialog(5000);
+ if (line == null) {
+ throw new TimeoutException();
+ }
+ if (parse_string(line))
+ break;
+ }
+ }
}
- \ No newline at end of file
diff --git a/altoslib/AltosIMUQuery.java b/altoslib/AltosIMUQuery.java
deleted file mode 100644
index 4ea5d963..00000000
--- a/altoslib/AltosIMUQuery.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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_1;
-
-import java.util.concurrent.TimeoutException;
-
-class AltosIMUQuery extends AltosIMU {
-
- public AltosIMUQuery (AltosLink link) throws InterruptedException, TimeoutException {
- link.printf("I\n");
- for (;;) {
- String line = link.get_reply_no_dialog(5000);
- if (line == null) {
- throw new TimeoutException();
- }
- if (!line.startsWith("Accel:"))
- continue;
- String[] items = line.split("\\s+");
- if (items.length >= 8) {
- accel_x = Integer.parseInt(items[1]);
- accel_y = Integer.parseInt(items[2]);
- accel_z = Integer.parseInt(items[3]);
- gyro_x = Integer.parseInt(items[5]);
- gyro_y = Integer.parseInt(items[6]);
- gyro_z = Integer.parseInt(items[7]);
- }
- break;
- }
- }
-}
-
diff --git a/altoslib/AltosIdle.java b/altoslib/AltosIdle.java
new file mode 100644
index 00000000..456a9247
--- /dev/null
+++ b/altoslib/AltosIdle.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright © 2013 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_2;
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.util.concurrent.*;
+
+public abstract class AltosIdle {
+ AltosLink link;
+ AltosConfigData config_data;
+
+ public void printf(String format, Object ... arguments) {
+ link.printf(format, arguments);
+ }
+
+ public abstract void update_state(AltosState state) throws InterruptedException, TimeoutException;
+
+ public AltosIdle(AltosLink link, AltosConfigData config_data) {
+ this.link = link;
+ this.config_data = config_data;
+ }
+}
diff --git a/altoslib/AltosIdleFetch.java b/altoslib/AltosIdleFetch.java
new file mode 100644
index 00000000..4adc6c41
--- /dev/null
+++ b/altoslib/AltosIdleFetch.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright © 2013 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_2;
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.util.concurrent.*;
+
+class AltosIdler {
+ String prefix;
+ int[] idlers;
+
+ static final int idle_gps = 0;
+ static final int idle_imu = 1;
+ static final int idle_mag = 2;
+ static final int idle_ms5607 = 3;
+ static final int idle_mma655x = 4;
+
+
+ static final int idle_sensor_tm = 10;
+ static final int idle_sensor_metrum = 11;
+ static final int idle_sensor_mega = 12;
+ static final int idle_sensor_emini = 13;
+ static final int idle_sensor_tmini = 14;
+
+ public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException, TimeoutException {
+ for (int idler : idlers) {
+ AltosIdle idle = null;
+ switch (idler) {
+ case idle_gps:
+ AltosGPS.update_state(state, link, config_data);
+ break;
+ case idle_imu:
+ AltosIMU.update_state(state, link, config_data);
+ break;
+ case idle_mag:
+ AltosMag.update_state(state, link, config_data);
+ break;
+ case idle_ms5607:
+ AltosMs5607.update_state(state, link, config_data);
+ break;
+ case idle_mma655x:
+ AltosMma655x.update_state(state, link, config_data);
+ break;
+ case idle_sensor_tm:
+ AltosSensorTM.update_state(state, link, config_data);
+ break;
+ case idle_sensor_metrum:
+ AltosSensorMetrum.update_state(state, link, config_data);
+ break;
+ case idle_sensor_mega:
+ AltosSensorMega.update_state(state, link, config_data);
+ break;
+ case idle_sensor_emini:
+ AltosSensorEMini.update_state(state, link, config_data);
+ break;
+ case idle_sensor_tmini:
+ AltosSensorTMini.update_state(state, link, config_data);
+ }
+ if (idle != null)
+ idle.update_state(state);
+ }
+ }
+
+ public boolean matches(AltosConfigData config_data) {
+ return config_data.product.startsWith(prefix);
+ }
+
+ public AltosIdler(String prefix, int ... idlers) {
+ this.prefix = prefix;
+ this.idlers = idlers;
+ }
+}
+
+
+public class AltosIdleFetch implements AltosStateUpdate {
+
+ static final AltosIdler[] idlers = {
+
+ new AltosIdler("EasyMini",
+ AltosIdler.idle_ms5607,
+ AltosIdler.idle_sensor_emini),
+
+ new AltosIdler("TeleMini-v1",
+ AltosIdler.idle_sensor_tm),
+
+ new AltosIdler("TeleMini-v2",
+ AltosIdler.idle_ms5607,
+ AltosIdler.idle_sensor_tmini),
+
+ new AltosIdler("TeleMetrum-v1",
+ AltosIdler.idle_gps,
+ AltosIdler.idle_sensor_tm),
+
+ new AltosIdler("TeleMetrum-v2",
+ AltosIdler.idle_gps,
+ AltosIdler.idle_ms5607, AltosIdler.idle_mma655x,
+ AltosIdler.idle_sensor_metrum),
+
+ new AltosIdler("TeleMega",
+ AltosIdler.idle_gps,
+ AltosIdler.idle_ms5607, AltosIdler.idle_mma655x,
+ AltosIdler.idle_imu, AltosIdler.idle_mag,
+ AltosIdler.idle_sensor_mega),
+ };
+
+ AltosLink link;
+
+ double frequency;
+ String callsign;
+
+ public void update_state(AltosState state) throws InterruptedException {
+ try {
+ AltosConfigData config_data = new AltosConfigData(link);
+ state.set_state(AltosLib.ao_flight_startup);
+ state.set_serial(config_data.serial);
+ state.set_callsign(config_data.callsign);
+ state.set_ground_accel(config_data.accel_cal_plus);
+ state.set_accel_g(config_data.accel_cal_plus, config_data.accel_cal_minus);
+ for (AltosIdler idler : idlers) {
+ if (idler.matches(config_data)) {
+ idler.update_state(state, link, config_data);
+ break;
+ }
+ }
+ state.set_received_time(System.currentTimeMillis());
+ } catch (TimeoutException te) {
+ }
+
+ }
+
+ public AltosIdleFetch(AltosLink link) {
+ this.link = link;
+ }
+}
diff --git a/altoslib/AltosIdleMonitor.java b/altoslib/AltosIdleMonitor.java
index b3ce5b20..d9d71143 100644
--- a/altoslib/AltosIdleMonitor.java
+++ b/altoslib/AltosIdleMonitor.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
import java.io.*;
import java.util.concurrent.*;
@@ -24,11 +24,13 @@ import java.util.concurrent.*;
public class AltosIdleMonitor extends Thread {
AltosLink link;
AltosIdleMonitorListener listener;
- AltosState state;
+
+ AltosIdleFetch fetch;
+
boolean remote;
double frequency;
String callsign;
- AltosState previous_state;
+
AltosListenerState listener_state;
AltosConfigData config_data;
AltosGPS gps;
@@ -47,86 +49,35 @@ public class AltosIdleMonitor extends Thread {
return rssi;
}
- boolean has_sensor_tm(AltosConfigData config_data) {
- return config_data.product.startsWith("TeleMetrum") || config_data.product.startsWith("TeleMini");
- }
-
- boolean has_sensor_mm(AltosConfigData config_data) {
- return config_data.product.startsWith("TeleMega");
+ void start_link() throws InterruptedException, TimeoutException {
+ if (remote) {
+ link.set_radio_frequency(frequency);
+ link.set_callsign(callsign);
+ link.start_remote();
+ } else
+ link.flush_input();
}
- boolean has_gps(AltosConfigData config_data) {
- return config_data.product.startsWith("TeleMetrum") || config_data.product.startsWith("TeleMega");
- }
-
- AltosRecord sensor_mm(AltosConfigData config_data) throws InterruptedException, TimeoutException {
- AltosRecordMM record_mm = new AltosRecordMM();
- AltosSensorMM sensor = new AltosSensorMM(link);
- AltosMs5607 ms5607 = new AltosMs5607Query(link);
- AltosIMU imu = new AltosIMUQuery(link);
-
- record_mm.accel_plus_g = config_data.accel_cal_plus;
- record_mm.accel_minus_g = config_data.accel_cal_minus;
-
- record_mm.ground_accel = sensor.accel;
- record_mm.accel = sensor.accel;
- record_mm.ground_pres = ms5607.pa;
- record_mm.pres = ms5607.pa;
- record_mm.temp = ms5607.cc;
-
- record_mm.v_batt = sensor.v_batt;
- record_mm.v_pyro = sensor.v_pyro;
- record_mm.sense = sensor.sense;
-
- record_mm.imu = imu;
-
- return record_mm;
+ void stop_link() throws InterruptedException, TimeoutException {
+ if (remote)
+ link.stop_remote();
}
- void update_state() throws InterruptedException, TimeoutException {
- AltosRecord record = null;
+ void update_state(AltosState state) throws InterruptedException, TimeoutException {
+ boolean worked = false;
try {
- if (remote) {
- link.set_radio_frequency(frequency);
- link.set_callsign(callsign);
- link.start_remote();
- } else
- link.flush_input();
- config_data = new AltosConfigData(link);
-
- if (has_sensor_tm(config_data))
- record = new AltosSensorTM(link, config_data);
- else if (has_sensor_mm(config_data))
- record = sensor_mm(config_data);
- else
- record = new AltosRecordNone();
-
- if (has_gps(config_data))
- gps = new AltosGPSQuery(link, config_data);
-
- record.version = 0;
- record.callsign = config_data.callsign;
- record.serial = config_data.serial;
- record.flight = config_data.log_available() > 0 ? 255 : 0;
- record.status = 0;
- record.state = AltosLib.ao_flight_idle;
- record.gps = gps;
- record.gps_sequence++;
- state = new AltosState (record, state);
+ start_link();
+ fetch.update_state(state);
+ worked = true;
} finally {
- if (remote) {
- link.stop_remote();
- if (record != null) {
- record.rssi = link.rssi();
- listener_state.battery = link.monitor_battery();
- }
- } else {
- if (record != null)
- record.rssi = 0;
+ stop_link();
+ if (worked) {
+ if (remote)
+ state.set_rssi(link.rssi(), 0);
+ listener_state.battery = link.monitor_battery();
}
}
-
}
public void set_frequency(double in_frequency) {
@@ -139,33 +90,32 @@ public class AltosIdleMonitor extends Thread {
link.abort_reply();
}
- public void post_state() {
- listener.update(state, listener_state);
- }
-
- public void abort() {
- if (isAlive()) {
+ public void abort() throws InterruptedException {
+ while (isAlive()) {
interrupt();
link.abort_reply();
- try {
- join();
- } catch (InterruptedException ie) {
- }
+ Thread.sleep(100);
}
+ join();
}
public void run() {
+ AltosState state = new AltosState();
try {
- for (;;) {
+ while (!link.has_error) {
try {
- update_state();
- post_state();
+ link.config_data();
+ update_state(state);
+ listener.update(state, listener_state);
} catch (TimeoutException te) {
}
Thread.sleep(1000);
}
} catch (InterruptedException ie) {
+ }
+ try {
link.close();
+ } catch (InterruptedException ie) {
}
}
@@ -174,7 +124,7 @@ public class AltosIdleMonitor extends Thread {
listener = in_listener;
link = in_link;
remote = in_remote;
- state = null;
listener_state = new AltosListenerState();
+ fetch = new AltosIdleFetch(link);
}
}
diff --git a/altoslib/AltosIdleMonitorListener.java b/altoslib/AltosIdleMonitorListener.java
index 27e36dea..0b03b897 100644
--- a/altoslib/AltosIdleMonitorListener.java
+++ b/altoslib/AltosIdleMonitorListener.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
public interface AltosIdleMonitorListener {
public void update(AltosState state, AltosListenerState listener_state);
diff --git a/altoslib/AltosIgnite.java b/altoslib/AltosIgnite.java
index 85905900..fc9599b6 100644
--- a/altoslib/AltosIgnite.java
+++ b/altoslib/AltosIgnite.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
import java.io.*;
import java.util.concurrent.*;
@@ -141,7 +141,7 @@ public class AltosIgnite {
}
}
- public void fire(int igniter) {
+ public void fire(int igniter) throws InterruptedException {
if (link == null)
return;
try {
@@ -154,21 +154,14 @@ public class AltosIgnite {
link.printf("i DoIt drogue\n");
break;
}
- } catch (InterruptedException ie) {
} catch (TimeoutException te) {
} finally {
- try {
- stop_link();
- } catch (InterruptedException ie) {
- }
+ stop_link();
}
}
- public void close() {
- try {
- stop_link();
- } catch (InterruptedException ie) {
- }
+ public void close() throws InterruptedException {
+ stop_link();
link.close();
link = null;
}
diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java
index 25d17e72..efbc3ddb 100644
--- a/altoslib/AltosLib.java
+++ b/altoslib/AltosLib.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
import java.util.*;
import java.io.*;
@@ -28,6 +28,7 @@ public class AltosLib {
public static final int AO_LOG_TEMP_VOLT = 'T';
public static final int AO_LOG_DEPLOY = 'D';
public static final int AO_LOG_STATE = 'S';
+ public static final int AO_LOG_GPS_POS = 'P';
public static final int AO_LOG_GPS_TIME = 'G';
public static final int AO_LOG_GPS_LAT = 'N';
public static final int AO_LOG_GPS_LON = 'W';
@@ -62,6 +63,8 @@ public class AltosLib {
public static final int AO_LOG_SOFTWARE_VERSION = 9999;
+ public final static int MISSING = 0x7fffffff;
+
/* Added to flag invalid records */
public static final int AO_LOG_INVALID = -1;
@@ -92,16 +95,59 @@ public class AltosLib {
public final static int product_telemega = 0x0023;
public final static int product_megadongle = 0x0024;
public final static int product_telegps = 0x0025;
+ public final static int product_easymini = 0x0026;
+ public final static int product_telemini = 0x0027;
public final static int product_altusmetrum_min = 0x000a;
- public final static int product_altusmetrum_max = 0x0025;
+ public final static int product_altusmetrum_max = 0x002c;
public final static int product_any = 0x10000;
public final static int product_basestation = 0x10000 + 1;
public final static int product_altimeter = 0x10000 + 2;
+ private static class Product {
+ final String name;
+ final int product;
+
+ Product (String name, int product) {
+ this.name = name;
+ this.product = product;
+ }
+ }
+
+ private static Product[] products = {
+ new Product("telemetrum", product_telemetrum),
+ new Product("teleballoon", product_telemetrum),
+ new Product("teledongle", product_teledongle),
+ new Product("teleterra", product_teledongle),
+ new Product("telebt", product_telebt),
+ new Product("telelaunch", product_telelaunch),
+ new Product("telelco", product_telelco),
+ new Product("telescience", product_telescience),
+ new Product("telepyro", product_telepyro),
+ new Product("telemega", product_telemega),
+ new Product("megadongle", product_megadongle),
+ new Product("telegps", product_telegps),
+ new Product("easymini", product_easymini),
+ new Product("telemini", product_telemini)
+ };
+
+ public static int name_to_product(String name) {
+ String low = name.toLowerCase();
+
+ for (int i = 0; i < products.length; i++)
+ if (low.startsWith(products[i].name))
+ return products[i].product;
+ return product_any;
+ }
+
/* Bluetooth "identifier" (bluetooth sucks) */
public final static String bt_product_telebt = "TeleBT";
+ /* "good" voltages */
+
+ public final static double ao_battery_good = 3.8;
+ public final static double ao_igniter_good = 3.5;
+
/* Telemetry modes */
public static final int ao_telemetry_off = 0;
public static final int ao_telemetry_min = 1;
@@ -216,6 +262,9 @@ public class AltosLib {
public static final int AO_LOG_FORMAT_TELEMETRY = 3;
public static final int AO_LOG_FORMAT_TELESCIENCE = 4;
public static final int AO_LOG_FORMAT_TELEMEGA = 5;
+ public static final int AO_LOG_FORMAT_EASYMINI = 6;
+ public static final int AO_LOG_FORMAT_TELEMETRUM = 7;
+ public static final int AO_LOG_FORMAT_TELEMINI = 8;
public static final int AO_LOG_FORMAT_NONE = 127;
public static boolean isspace(int c) {
@@ -410,4 +459,24 @@ public class AltosLib {
public static File replace_extension(File input, String extension) {
return new File(replace_extension(input.getPath(), extension));
}
+
+ public static String product_name(int product_id) {
+ switch (product_id) {
+ case product_altusmetrum: return "AltusMetrum";
+ case product_telemetrum: return "TeleMetrum";
+ case product_teledongle: return "TeleDongle";
+ case product_teleterra: return "TeleTerra";
+ case product_telebt: return "TeleBT";
+ case product_telelaunch: return "TeleLaunch";
+ case product_telelco: return "TeleLco";
+ case product_telescience: return "Telescience";
+ case product_telepyro: return "TelePyro";
+ case product_telemega: return "TeleMega";
+ case product_megadongle: return "MegaDongle";
+ case product_telegps: return "TeleGPS";
+ case product_easymini: return "EasyMini";
+ case product_telemini: return "TeleMini";
+ default: return "unknown";
+ }
+ }
}
diff --git a/altoslib/AltosLine.java b/altoslib/AltosLine.java
index b3bd20f9..e5dd13fc 100644
--- a/altoslib/AltosLine.java
+++ b/altoslib/AltosLine.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
public class AltosLine {
public String line;
diff --git a/altoslib/AltosLink.java b/altoslib/AltosLink.java
index 159ebfe1..ee1f9785 100644
--- a/altoslib/AltosLink.java
+++ b/altoslib/AltosLink.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
import java.io.*;
import java.util.concurrent.*;
@@ -26,23 +26,28 @@ public abstract class AltosLink implements Runnable {
public final static int ERROR = -1;
public final static int TIMEOUT = -2;
- public abstract int getchar();
- public abstract void print(String data);
- public abstract void close();
+ public abstract int getchar() throws InterruptedException;
+ public abstract void print(String data) throws InterruptedException;
+ public abstract void putchar(byte c);
+ public abstract void close() throws InterruptedException;
public static boolean debug = false;
public static void set_debug(boolean in_debug) { debug = in_debug; }
+
+ public boolean has_error;
+
LinkedList<String> pending_output = new LinkedList<String>();
public LinkedList<LinkedBlockingQueue<AltosLine>> monitors = new LinkedList<LinkedBlockingQueue<AltosLine>> ();;
public LinkedBlockingQueue<AltosLine> reply_queue = new LinkedBlockingQueue<AltosLine>();
+ public LinkedBlockingQueue<byte[]> binary_queue = new LinkedBlockingQueue<byte[]>();
- public void add_monitor(LinkedBlockingQueue<AltosLine> q) {
+ public synchronized void add_monitor(LinkedBlockingQueue<AltosLine> q) {
set_monitor(true);
monitors.add(q);
}
- public void remove_monitor(LinkedBlockingQueue<AltosLine> q) {
+ public synchronized void remove_monitor(LinkedBlockingQueue<AltosLine> q) {
monitors.remove(q);
if (monitors.isEmpty())
set_monitor(false);
@@ -52,7 +57,11 @@ public abstract class AltosLink implements Runnable {
String line = String.format(format, arguments);
if (debug)
pending_output.add(line);
- print(line);
+ try {
+ print(line);
+ } catch (InterruptedException ie) {
+
+ }
}
public String get_reply_no_dialog(int timeout) throws InterruptedException, TimeoutException {
@@ -90,6 +99,7 @@ public abstract class AltosLink implements Runnable {
}
}
+ private int len_read = 0;
public void run () {
int c;
@@ -100,13 +110,12 @@ public abstract class AltosLink implements Runnable {
for (;;) {
c = getchar();
if (Thread.interrupted()) {
- if (debug)
- System.out.printf("INTERRUPTED\n");
break;
}
if (c == ERROR) {
if (debug)
System.out.printf("ERROR\n");
+ has_error = true;
add_telem (new AltosLine());
add_reply (new AltosLine());
break;
@@ -116,10 +125,10 @@ public abstract class AltosLink implements Runnable {
System.out.printf("TIMEOUT\n");
continue;
}
- if (c == '\r')
+ if (c == '\r' && len_read == 0)
continue;
synchronized(this) {
- if (c == '\n') {
+ if (c == '\n' && len_read == 0) {
if (line_count != 0) {
add_bytes(line_bytes, line_count);
line_count = 0;
@@ -134,6 +143,11 @@ public abstract class AltosLink implements Runnable {
}
line_bytes[line_count] = (byte) c;
line_count++;
+ if (len_read !=0 && line_count == len_read) {
+ add_binary(line_bytes, line_count);
+ line_count = 0;
+ len_read = 0;
+ }
}
}
}
@@ -141,6 +155,7 @@ public abstract class AltosLink implements Runnable {
}
}
+
public String get_reply(int timeout) throws InterruptedException {
boolean can_cancel = can_cancel_reply();
String reply = null;
@@ -175,6 +190,38 @@ public abstract class AltosLink implements Runnable {
return reply;
}
+ public byte[] get_binary_reply(int timeout, int len) throws InterruptedException {
+ boolean can_cancel = can_cancel_reply();
+ byte[] bytes = null;
+
+ synchronized(this) {
+ len_read = len;
+ }
+ try {
+ ++in_reply;
+
+ flush_output();
+
+ reply_abort = false;
+ reply_timeout_shown = false;
+ for (;;) {
+ bytes = binary_queue.poll(timeout, TimeUnit.MILLISECONDS);
+ if (bytes != null) {
+ cleanup_reply_timeout();
+ break;
+ }
+ if (!remote || !can_cancel || check_reply_timeout()) {
+ bytes = null;
+ break;
+ }
+ }
+
+ } finally {
+ --in_reply;
+ }
+ return bytes;
+ }
+
public void add_telem(AltosLine line) throws InterruptedException {
for (int e = 0; e < monitors.size(); e++) {
LinkedBlockingQueue<AltosLine> q = monitors.get(e);
@@ -190,7 +237,7 @@ public abstract class AltosLink implements Runnable {
try {
add_telem (new AltosLine());
add_reply (new AltosLine());
- } catch (InterruptedException e) {
+ } catch (InterruptedException ie) {
}
}
@@ -216,6 +263,22 @@ public abstract class AltosLink implements Runnable {
add_string(line);
}
+ public void add_binary(byte[] bytes, int len) throws InterruptedException {
+ byte[] dup = new byte[len];
+
+ if (debug)
+ System.out.printf ("\t\t\t\t\t%d:", len);
+ for(int i = 0; i < len; i++) {
+ dup[i] = bytes[i];
+ if (debug)
+ System.out.printf(" %02x", dup[i]);
+ }
+ if (debug)
+ System.out.printf("\n");
+
+ binary_queue.put(dup);
+ }
+
public void flush_output() {
for (String s : pending_output)
System.out.print(s);
@@ -252,6 +315,8 @@ public abstract class AltosLink implements Runnable {
public String callsign;
AltosConfigData config_data;
+ private Object config_data_lock = new Object();
+
private int telemetry_len() {
return AltosLib.telemetry_len(telemetry);
}
@@ -325,9 +390,11 @@ public abstract class AltosLink implements Runnable {
}
public AltosConfigData config_data() throws InterruptedException, TimeoutException {
- if (config_data == null)
- config_data = new AltosConfigData(this);
- return config_data;
+ synchronized(config_data_lock) {
+ if (config_data == null)
+ config_data = new AltosConfigData(this);
+ return config_data;
+ }
}
public void set_callsign(String callsign) {
@@ -336,6 +403,29 @@ public abstract class AltosLink implements Runnable {
flush_output();
}
+ public boolean is_loader() throws InterruptedException {
+ boolean ret = false;
+ printf("v\n");
+ for (;;) {
+ String line = get_reply();
+
+ if (line == null)
+ return false;
+ if (line.startsWith("software-version"))
+ break;
+ if (line.startsWith("altos-loader"))
+ ret = true;
+ }
+ return ret;
+ }
+
+ public void to_loader() throws InterruptedException {
+ printf("X\n");
+ flush_output();
+ close();
+ Thread.sleep(1000);
+ }
+
public boolean remote;
public int serial;
public String name;
@@ -398,8 +488,8 @@ public abstract class AltosLink implements Runnable {
return config_data.has_monitor_battery();
}
- public double monitor_battery() {
- int monitor_batt = AltosRecord.MISSING;
+ public double monitor_battery() throws InterruptedException {
+ int monitor_batt = AltosLib.MISSING;
if (config_data.has_monitor_battery()) {
try {
@@ -412,16 +502,16 @@ public abstract class AltosLink implements Runnable {
}
i++;
}
- } catch (InterruptedException ie) {
} catch (TimeoutException te) {
}
}
- if (monitor_batt == AltosRecord.MISSING)
- return AltosRecord.MISSING;
+ if (monitor_batt == AltosLib.MISSING)
+ return AltosLib.MISSING;
return AltosConvert.cc_battery_to_voltage(monitor_batt);
}
public AltosLink() {
callsign = "";
+ has_error = false;
}
}
diff --git a/altoslib/AltosListenerState.java b/altoslib/AltosListenerState.java
index 2fb4673e..01dd7afb 100644
--- a/altoslib/AltosListenerState.java
+++ b/altoslib/AltosListenerState.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
public class AltosListenerState {
public int crc_errors;
@@ -23,6 +23,6 @@ public class AltosListenerState {
public AltosListenerState() {
crc_errors = 0;
- battery = AltosRecord.MISSING;
+ battery = AltosLib.MISSING;
}
}
diff --git a/altoslib/AltosLog.java b/altoslib/AltosLog.java
index 974c9f0f..d4fbee97 100644
--- a/altoslib/AltosLog.java
+++ b/altoslib/AltosLog.java
@@ -15,11 +15,11 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
import java.io.*;
-import java.text.ParseException;
-import java.util.concurrent.LinkedBlockingQueue;
+import java.text.*;
+import java.util.concurrent.*;
/*
* This creates a thread to capture telemetry data and write it to
@@ -31,9 +31,11 @@ public class AltosLog implements Runnable {
LinkedBlockingQueue<String> pending_queue;
int serial;
int flight;
+ int receiver_serial;
FileWriter log_file;
Thread log_thread;
AltosFile file;
+ AltosLink link;
private void close_log_file() {
if (log_file != null) {
@@ -57,18 +59,15 @@ public class AltosLog implements Runnable {
return file;
}
- boolean open (AltosRecord telem) throws IOException {
- AltosFile a = new AltosFile(telem);
+ boolean open (AltosState state) throws IOException, InterruptedException {
+ AltosFile a = new AltosFile(state);
log_file = new FileWriter(a, true);
if (log_file != null) {
while (!pending_queue.isEmpty()) {
- try {
- String s = pending_queue.take();
- log_file.write(s);
- log_file.write('\n');
- } catch (InterruptedException ie) {
- }
+ String s = pending_queue.take();
+ log_file.write(s);
+ log_file.write('\n');
}
log_file.flush();
file = a;
@@ -78,22 +77,25 @@ public class AltosLog implements Runnable {
public void run () {
try {
- AltosRecord previous = null;
+ AltosState state = new AltosState();
+ AltosConfigData receiver_config = link.config_data();
+ state.set_receiver_serial(receiver_config.serial);
for (;;) {
AltosLine line = input_queue.take();
if (line.line == null)
continue;
try {
- AltosRecord telem = AltosTelemetry.parse(line.line, previous);
- if ((telem.seen & AltosRecord.seen_flight) != 0 &&
- (telem.serial != serial || telem.flight != flight || log_file == null))
+ AltosTelemetry telem = AltosTelemetry.parse(line.line);
+ state = state.clone();
+ telem.update_state(state);
+ if (state.serial != serial || state.flight != flight || log_file == null)
{
close_log_file();
- serial = telem.serial;
- flight = telem.flight;
- open(telem);
+ serial = state.serial;
+ flight = state.flight;
+ if (state.serial != AltosLib.MISSING && state.flight != AltosLib.MISSING)
+ open(state);
}
- previous = telem;
} catch (ParseException pe) {
} catch (AltosCRCException ce) {
}
@@ -105,6 +107,7 @@ public class AltosLog implements Runnable {
pending_queue.put(line.line);
}
} catch (InterruptedException ie) {
+ } catch (TimeoutException te) {
} catch (IOException ie) {
}
close();
@@ -116,6 +119,7 @@ public class AltosLog implements Runnable {
link.add_monitor(input_queue);
serial = -1;
flight = -1;
+ this.link = link;
log_file = null;
log_thread = new Thread(this);
log_thread.start();
diff --git a/altoslib/AltosMag.java b/altoslib/AltosMag.java
index b3bbd92f..89e72bd6 100644
--- a/altoslib/AltosMag.java
+++ b/altoslib/AltosMag.java
@@ -15,11 +15,70 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
-public class AltosMag {
+import java.util.concurrent.*;
+
+public class AltosMag implements Cloneable {
public int x;
public int y;
public int z;
+
+ public boolean parse_string(String line) {
+// if (line.startsWith("Syntax error")) {
+// x = y = z = 0;
+// return true;
+// }
+
+ if (!line.startsWith("X:"))
+ return false;
+
+ String[] items = line.split("\\s+");
+
+ if (items.length >= 6) {
+ x = Integer.parseInt(items[1]);
+ y = Integer.parseInt(items[3]);
+ z = Integer.parseInt(items[5]);
+ }
+ return true;
+ }
+
+ public AltosMag clone() {
+ AltosMag n = new AltosMag();
+
+ n.x = x;
+ n.y = y;
+ n.z = z;
+ return n;
+ }
+
+ public AltosMag() {
+ x = AltosLib.MISSING;
+ y = AltosLib.MISSING;
+ z = AltosLib.MISSING;
+ }
+
+ static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException {
+ try {
+ AltosMag mag = new AltosMag(link);
+
+ if (mag != null)
+ state.set_mag(mag);
+ } catch (TimeoutException te) {
+ }
+ }
+
+ public AltosMag(AltosLink link) throws InterruptedException, TimeoutException {
+ this();
+ link.printf("M\n");
+ for (;;) {
+ String line = link.get_reply_no_dialog(5000);
+ if (line == null) {
+ throw new TimeoutException();
+ }
+ if (parse_string(line))
+ break;
+ }
+ }
}
\ No newline at end of file
diff --git a/altoslib/AltosMma655x.java b/altoslib/AltosMma655x.java
new file mode 100644
index 00000000..f8256190
--- /dev/null
+++ b/altoslib/AltosMma655x.java
@@ -0,0 +1,68 @@
+/*
+ * 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_2;
+
+import java.util.concurrent.*;
+
+public class AltosMma655x implements Cloneable {
+
+ int accel;
+
+ public boolean parse_line(String line) {
+ String[] items = line.split("\\s+");
+ if (line.startsWith("MMA655X value:")) {
+ if (items.length >= 3)
+ accel = Integer.parseInt(items[1]);
+ } else
+ return false;
+ return true;
+ }
+
+ public AltosMma655x() {
+ accel = AltosLib.MISSING;
+ }
+
+ public AltosMma655x clone() {
+ AltosMma655x n = new AltosMma655x();
+
+ n.accel = accel;
+ return n;
+ }
+
+ static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException {
+ try {
+ AltosMma655x mma655x = new AltosMma655x(link);
+
+ if (mma655x != null)
+ state.set_accel(mma655x.accel);
+ } catch (TimeoutException te) {
+ }
+ }
+
+ public AltosMma655x(AltosLink link) throws InterruptedException, TimeoutException {
+ this();
+ link.printf("A\n");
+ for (;;) {
+ String line = link.get_reply_no_dialog(5000);
+ if (line == null)
+ throw new TimeoutException();
+ if (!parse_line(line))
+ break;
+ }
+ }
+}
diff --git a/altoslib/AltosMs5607.java b/altoslib/AltosMs5607.java
index 606916b7..2319d5b8 100644
--- a/altoslib/AltosMs5607.java
+++ b/altoslib/AltosMs5607.java
@@ -15,7 +15,9 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
+
+import java.util.concurrent.*;
public class AltosMs5607 {
public int reserved;
@@ -85,8 +87,9 @@ public class AltosMs5607 {
public boolean parse_line(String line) {
String[] items = line.split("\\s+");
if (line.startsWith("Pressure:")) {
- if (items.length >= 2)
+ if (items.length >= 2) {
raw_pres = Integer.parseInt(items[1]);
+ }
} else if (line.startsWith("Temperature:")) {
if (items.length >= 2)
raw_temp = Integer.parseInt(items[1]);
@@ -94,8 +97,9 @@ public class AltosMs5607 {
if (items.length >= 3)
reserved = Integer.parseInt(items[2]);
} else if (line.startsWith("ms5607 sens:")) {
- if (items.length >= 3)
+ if (items.length >= 3) {
sens = Integer.parseInt(items[2]);
+ }
} else if (line.startsWith("ms5607 off:")) {
if (items.length >= 3)
off = Integer.parseInt(items[2]);
@@ -114,15 +118,43 @@ public class AltosMs5607 {
} else if (line.startsWith("ms5607 crc:")) {
if (items.length >= 3)
crc = Integer.parseInt(items[2]);
- } else if (line.startsWith("Altitude"))
+ } else if (line.startsWith("Altitude:")) {
return false;
+ }
return true;
}
+ static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException {
+ try {
+ AltosMs5607 ms5607 = new AltosMs5607(link);
+
+ if (ms5607 != null) {
+ state.set_ms5607(ms5607);
+ return;
+ }
+ } catch (TimeoutException te) {
+ }
+ }
+
public AltosMs5607() {
- raw_pres = AltosRecord.MISSING;
- raw_temp = AltosRecord.MISSING;
- pa = AltosRecord.MISSING;
- cc = AltosRecord.MISSING;
+ raw_pres = AltosLib.MISSING;
+ raw_temp = AltosLib.MISSING;
+ pa = AltosLib.MISSING;
+ cc = AltosLib.MISSING;
+ }
+
+ public AltosMs5607 (AltosLink link) throws InterruptedException, TimeoutException {
+ this();
+ link.printf("c s\nB\n");
+ for (;;) {
+ String line = link.get_reply_no_dialog(5000);
+ if (line == null) {
+ throw new TimeoutException();
+ }
+ if (!parse_line(line)) {
+ break;
+ }
+ }
+ convert();
}
}
diff --git a/altoslib/AltosNoSymbol.java b/altoslib/AltosNoSymbol.java
new file mode 100644
index 00000000..e94687cd
--- /dev/null
+++ b/altoslib/AltosNoSymbol.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright © 2013 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_2;
+
+public class AltosNoSymbol extends Exception {
+ public AltosNoSymbol(String name) {
+ super(String.format("No such symbol \"%s\"", name));
+ }
+}
diff --git a/altoslib/AltosOrderedMegaRecord.java b/altoslib/AltosOrderedMegaRecord.java
deleted file mode 100644
index b20a5bbd..00000000
--- a/altoslib/AltosOrderedMegaRecord.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright © 2010 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.altoslib_1;
-
-import java.text.ParseException;
-
-/*
- * AltosRecords with an index field so they can be sorted by tick while preserving
- * the original ordering for elements with matching ticks
- */
-class AltosOrderedMegaRecord extends AltosEepromMega implements Comparable<AltosOrderedMegaRecord> {
-
- public int index;
-
- public AltosOrderedMegaRecord(String line, int in_index, int prev_tick, boolean prev_tick_valid)
- throws ParseException {
- super(line);
- if (prev_tick_valid) {
- tick |= (prev_tick & ~0xffff);
- if (tick < prev_tick) {
- if (prev_tick - tick > 0x8000)
- tick += 0x10000;
- } else {
- if (tick - prev_tick > 0x8000)
- tick -= 0x10000;
- }
- }
- index = in_index;
- }
-
- public int compareTo(AltosOrderedMegaRecord o) {
- int tick_diff = tick - o.tick;
- if (tick_diff != 0)
- return tick_diff;
- return index - o.index;
- }
-}
diff --git a/altoslib/AltosOrderedRecord.java b/altoslib/AltosOrderedRecord.java
deleted file mode 100644
index 63507d39..00000000
--- a/altoslib/AltosOrderedRecord.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright © 2010 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.altoslib_1;
-
-import java.text.ParseException;
-
-/*
- * AltosRecords with an index field so they can be sorted by tick while preserving
- * the original ordering for elements with matching ticks
- */
-class AltosOrderedRecord extends AltosEepromRecord implements Comparable<AltosOrderedRecord> {
-
- public int index;
-
- public AltosOrderedRecord(String line, int in_index, int prev_tick, boolean prev_tick_valid)
- throws ParseException {
- super(line);
- if (prev_tick_valid) {
- tick |= (prev_tick & ~0xffff);
- if (tick < prev_tick) {
- if (prev_tick - tick > 0x8000)
- tick += 0x10000;
- } else {
- if (tick - prev_tick > 0x8000)
- tick -= 0x10000;
- }
- }
- index = in_index;
- }
-
- public AltosOrderedRecord(int in_cmd, int in_tick, int in_a, int in_b, int in_index) {
- super(in_cmd, in_tick, in_a, in_b);
- index = in_index;
- }
-
- public String toString() {
- return String.format("%d.%d %04x %04x %04x",
- cmd, index, tick, a, b);
- }
-
- public int compareTo(AltosOrderedRecord o) {
- int tick_diff = tick - o.tick;
- if (tick_diff != 0)
- return tick_diff;
- return index - o.index;
- }
-}
-
diff --git a/altoslib/AltosParse.java b/altoslib/AltosParse.java
index 66bbeed5..ca96a8f9 100644
--- a/altoslib/AltosParse.java
+++ b/altoslib/AltosParse.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
import java.text.*;
diff --git a/altoslib/AltosPreferences.java b/altoslib/AltosPreferences.java
index 088ca3d7..c4051f9b 100644
--- a/altoslib/AltosPreferences.java
+++ b/altoslib/AltosPreferences.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
import java.io.*;
import java.util.*;
diff --git a/altoslib/AltosPreferencesBackend.java b/altoslib/AltosPreferencesBackend.java
index fb8a235a..1ea28b01 100644
--- a/altoslib/AltosPreferencesBackend.java
+++ b/altoslib/AltosPreferencesBackend.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
import java.io.File;
diff --git a/altoslib/AltosProgrammer.java b/altoslib/AltosProgrammer.java
new file mode 100644
index 00000000..b010d564
--- /dev/null
+++ b/altoslib/AltosProgrammer.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright © 2013 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_2;
+
+import java.io.*;
+
+public abstract class AltosProgrammer {
+
+ abstract public void flash();
+
+ abstract public void close();
+
+ abstract public void abort();
+
+ abstract public AltosRomconfig romconfig() throws InterruptedException;
+
+ abstract public void set_romconfig(AltosRomconfig config);
+} \ No newline at end of file
diff --git a/altoslib/AltosPyro.java b/altoslib/AltosPyro.java
index 4dbb4223..a219468c 100644
--- a/altoslib/AltosPyro.java
+++ b/altoslib/AltosPyro.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
import java.util.*;
import java.text.*;
@@ -28,24 +28,24 @@ public class AltosPyro {
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 String pyro_accel_less_name = "Acceleration less than";
+ public static final String pyro_accel_greater_name = "Acceleration greater than";
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 String pyro_speed_less_name = "Speed less than";
+ public static final String pyro_speed_greater_name = "Speed greater than";
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 String pyro_height_less_name = "Height less than";
+ public static final String pyro_height_greater_name = "Height greater than";
public static final double pyro_height_scale = 1.0;
public static final int pyro_orient_less = 0x00000040;
@@ -102,12 +102,16 @@ public class AltosPyro {
private static HashMap<Integer,String> pyro_to_name = new HashMap<Integer,String>();
+ private static HashMap<Integer,AltosUnits> pyro_to_units = new HashMap<Integer,AltosUnits>();
+
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) {
+ private static void insert_map(int flag, String string, String name, AltosUnits units, double scale) {
string_to_pyro.put(string, flag);
pyro_to_string.put(flag, string);
pyro_to_name.put(flag, name);
+ if (units != null)
+ pyro_to_units.put(flag, units);
pyro_to_scale.put(flag, scale);
}
@@ -124,8 +128,22 @@ public class AltosPyro {
}
public static String pyro_to_name(int flag) {
- if (pyro_to_name.containsKey(flag))
- return pyro_to_name.get(flag);
+ String name;
+ AltosUnits units = null;
+ if (!pyro_to_name.containsKey(flag))
+ return null;
+
+ name = pyro_to_name.get(flag);
+ if (pyro_to_units.containsKey(flag))
+ units = pyro_to_units.get(flag);
+ if (units == null)
+ return name;
+ return String.format ("%s (%s)", name, units.show_units());
+ }
+
+ public static AltosUnits pyro_to_units(int flag) {
+ if (pyro_to_units.containsKey(flag))
+ return pyro_to_units.get(flag);
return null;
}
@@ -136,29 +154,29 @@ public class AltosPyro {
}
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_accel_less, pyro_accel_less_string, pyro_accel_less_name, AltosConvert.accel, pyro_accel_scale);
+ insert_map(pyro_accel_greater, pyro_accel_greater_string, pyro_accel_greater_name, AltosConvert.accel, 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_speed_less, pyro_speed_less_string, pyro_speed_less_name, AltosConvert.speed, pyro_speed_scale);
+ insert_map(pyro_speed_greater, pyro_speed_greater_string, pyro_speed_greater_name, AltosConvert.speed, 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_height_less, pyro_height_less_string, pyro_height_less_name, AltosConvert.height, pyro_height_scale);
+ insert_map(pyro_height_greater, pyro_height_greater_string, pyro_height_greater_name, AltosConvert.height, 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_orient_less, pyro_orient_less_string, pyro_orient_less_name, null, pyro_orient_scale);
+ insert_map(pyro_orient_greater, pyro_orient_greater_string, pyro_orient_greater_name, null, 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_time_less, pyro_time_less_string, pyro_time_less_name, null, pyro_time_scale);
+ insert_map(pyro_time_greater, pyro_time_greater_string, pyro_time_greater_name, null, 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_ascending, pyro_ascending_string, pyro_ascending_name, null, 1.0);
+ insert_map(pyro_descending, pyro_descending_string, pyro_descending_name, null, 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_after_motor, pyro_after_motor_string, pyro_after_motor_name, null, 1.0);
+ insert_map(pyro_delay, pyro_delay_string, pyro_delay_name, null, 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);
+ insert_map(pyro_state_less, pyro_state_less_string, pyro_state_less_name, null, 1.0);
+ insert_map(pyro_state_greater_or_equal, pyro_state_greater_or_equal_string, pyro_state_greater_or_equal_name, null, 1.0);
}
{
diff --git a/altoslib/AltosRecord.java b/altoslib/AltosRecord.java
deleted file mode 100644
index 5e4ed927..00000000
--- a/altoslib/AltosRecord.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright © 2010 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.altoslib_1;
-
-public class AltosRecord implements Comparable <AltosRecord>, Cloneable {
-
- public static final int seen_flight = 1;
- public static final int seen_sensor = 2;
- public static final int seen_temp_volt = 4;
- public static final int seen_deploy = 8;
- public static final int seen_gps_time = 16;
- public static final int seen_gps_lat = 32;
- public static final int seen_gps_lon = 64;
- public static final int seen_companion = 128;
-
- public int seen;
-
- public final static int MISSING = 0x7fffffff;
-
- /* Every AltosRecord implementation provides these fields */
-
- public int version;
- public String callsign;
- public int serial;
- public int flight;
- public int rssi;
- public int status;
- public int state;
- public int tick;
-
- public AltosGPS gps;
- public int gps_sequence;
-
- public double time; /* seconds since boost */
-
- public int device_type;
- public int config_major;
- public int config_minor;
- public int apogee_delay;
- public int main_deploy;
- public int flight_log_max;
- public String firmware_version;
-
- 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:
- *
- * pressure: Pa
- * voltage: V
- * acceleration: m/s²
- * speed: m/s
- * height: m
- * temperature: °C
- */
-
- public double pressure() { return MISSING; }
- public double ground_pressure() { return MISSING; }
- public double acceleration() { return MISSING; }
-
- public double altitude() {
- double p = pressure();
-
- if (p == MISSING)
- return MISSING;
- return AltosConvert.pressure_to_altitude(p);
- }
-
- public double ground_altitude() {
- double p = ground_pressure();
-
- if (p == MISSING)
- return MISSING;
- return AltosConvert.pressure_to_altitude(p);
- }
-
- public double height() {
- double g = ground_altitude();
- double a = altitude();
-
- if (g == MISSING)
- return MISSING;
- if (a == MISSING)
- return MISSING;
- return a - g;
- }
-
- public double battery_voltage() { return MISSING; }
-
- public double main_voltage() { return MISSING; }
-
- public double drogue_voltage() { return MISSING; }
-
- public double temperature() { return MISSING; }
-
- public AltosIMU imu() { return null; }
-
- public AltosMag mag() { return null; }
-
- public String state() {
- return AltosLib.state_name(state);
- }
-
- public int compareTo(AltosRecord o) {
- return tick - o.tick;
- }
-
- public AltosRecord clone() {
- AltosRecord n = new AltosRecord();
- n.copy(this);
- return n;
- }
-
- public void copy(AltosRecord old) {
- seen = old.seen;
- version = old.version;
- callsign = old.callsign;
- serial = old.serial;
- flight = old.flight;
- rssi = old.rssi;
- status = old.status;
- state = old.state;
- tick = old.tick;
- gps = new AltosGPS(old.gps);
- gps_sequence = old.gps_sequence;
- companion = old.companion;
- kalman_acceleration = old.kalman_acceleration;
- kalman_speed = old.kalman_speed;
- kalman_height = old.kalman_height;
- }
-
- public AltosRecord() {
- seen = 0;
- version = 0;
- callsign = "N0CALL";
- serial = MISSING;
- flight = MISSING;
- rssi = 0;
- status = 0;
- state = AltosLib.ao_flight_startup;
- tick = 0;
- gps = null;
- gps_sequence = 0;
- companion = null;
-
- kalman_acceleration = MISSING;
- kalman_speed = MISSING;
- kalman_height = MISSING;
- }
-}
diff --git a/altoslib/AltosRecordMM.java b/altoslib/AltosRecordMM.java
deleted file mode 100644
index d697111c..00000000
--- a/altoslib/AltosRecordMM.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * 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_1;
-
-public class AltosRecordMM extends AltosRecord {
-
- /* Sensor values */
- public int accel;
- public int pres;
- public int temp;
-
- public int v_batt;
- public int v_pyro;
- public int sense[];
-
- public int ground_accel;
- public int ground_pres;
- public int accel_plus_g;
- public int accel_minus_g;
-
- public int flight_accel;
- public int flight_vel;
- public int flight_pres;
-
- public final static int num_sense = 6;
-
- public AltosIMU imu;
- public AltosMag mag;
-
- static double adc(int raw) {
- return raw / 4095.0;
- }
-
- public double pressure() {
- if (pres != MISSING)
- return pres;
- return MISSING;
- }
-
- public double ground_pressure() {
- if (ground_pres != MISSING)
- return ground_pres;
- return MISSING;
- }
-
- public double battery_voltage() {
- if (v_batt != MISSING)
- return 3.3 * adc(v_batt) * (15.0 + 27.0) / 27.0;
- return MISSING;
- }
-
- static double pyro(int raw) {
- if (raw != MISSING)
- return 3.3 * adc(raw) * (100.0 + 27.0) / 27.0;
- return MISSING;
- }
-
- public double main_voltage() {
- return pyro(sense[5]);
- }
-
- public double drogue_voltage() {
- return pyro(sense[4]);
- }
-
- public double temperature() {
- if (temp != MISSING)
- return temp / 100.0;
- return MISSING;
- }
-
- public AltosIMU imu() { return imu; }
-
- public AltosMag mag() { return mag; }
-
- double accel_counts_per_mss() {
- double counts_per_g = Math.abs(accel_minus_g - accel_plus_g) / 2;
-
- return counts_per_g / 9.80665;
- }
-
- public double acceleration() {
- if (ground_accel == MISSING || accel == MISSING)
- return MISSING;
-
- if (accel_minus_g == MISSING || accel_plus_g == MISSING)
- return MISSING;
-
- return (ground_accel - accel) / accel_counts_per_mss();
- }
-
- public void copy (AltosRecordMM old) {
- super.copy(old);
-
- accel = old.accel;
- pres = old.pres;
- temp = old.temp;
-
- v_batt = old.v_batt;
- v_pyro = old.v_pyro;
- sense = new int[num_sense];
-
- for (int i = 0; i < num_sense; i++)
- sense[i] = old.sense[i];
-
- ground_accel = old.ground_accel;
- ground_pres = old.ground_pres;
- accel_plus_g = old.accel_plus_g;
- accel_minus_g = old.accel_minus_g;
-
- flight_accel = old.flight_accel;
- flight_vel = old.flight_vel;
- flight_pres = old.flight_pres;
-
- imu = old.imu;
- mag = old.mag;
- }
-
-
-
- public AltosRecordMM clone() {
- return new AltosRecordMM(this);
- }
-
- void make_missing() {
-
- accel = MISSING;
- pres = MISSING;
- temp = MISSING;
-
- v_batt = MISSING;
- v_pyro = MISSING;
- sense = new int[num_sense];
- for (int i = 0; i < num_sense; i++)
- sense[i] = MISSING;
-
- ground_accel = MISSING;
- ground_pres = MISSING;
- accel_plus_g = MISSING;
- accel_minus_g = MISSING;
-
- flight_accel = 0;
- flight_vel = 0;
- flight_pres = 0;
-
- imu = new AltosIMU();
- mag = new AltosMag();
- }
-
- public AltosRecordMM(AltosRecord old) {
- super.copy(old);
- make_missing();
- }
-
- public AltosRecordMM(AltosRecordMM old) {
- copy(old);
- }
-
- public AltosRecordMM() {
- super();
- make_missing();
- }
-}
diff --git a/altoslib/AltosRecordTM.java b/altoslib/AltosRecordTM.java
deleted file mode 100644
index c6cf3646..00000000
--- a/altoslib/AltosRecordTM.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * 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_1;
-
-public class AltosRecordTM extends AltosRecord {
-
- /* Sensor values */
- public int accel;
- public int pres;
- public int temp;
- public int batt;
- public int drogue;
- public int main;
-
- public int ground_accel;
- public int ground_pres;
- public int accel_plus_g;
- public int accel_minus_g;
-
- public int flight_accel;
- public int flight_vel;
- public int flight_pres;
-
- /*
- * Values for our MP3H6115A pressure sensor
- *
- * From the data sheet:
- *
- * Pressure range: 15-115 kPa
- * Voltage at 115kPa: 2.82
- * Output scale: 27mV/kPa
- *
- *
- * 27 mV/kPa * 2047 / 3300 counts/mV = 16.75 counts/kPa
- * 2.82V * 2047 / 3.3 counts/V = 1749 counts/115 kPa
- */
-
- static final double counts_per_kPa = 27 * 2047 / 3300;
- static final double counts_at_101_3kPa = 1674.0;
-
- static double
- barometer_to_pressure(double count)
- {
- return ((count / 16.0) / 2047.0 + 0.095) / 0.009 * 1000.0;
- }
-
- public double pressure() {
- if (pres == MISSING)
- return MISSING;
- return barometer_to_pressure(pres);
- }
-
- public double ground_pressure() {
- if (ground_pres == MISSING)
- return MISSING;
- return barometer_to_pressure(ground_pres);
- }
-
- public double battery_voltage() {
- if (batt == MISSING)
- return MISSING;
- return AltosConvert.cc_battery_to_voltage(batt);
- }
-
- public double main_voltage() {
- if (main == MISSING)
- return MISSING;
- return AltosConvert.cc_ignitor_to_voltage(main);
- }
-
- public double drogue_voltage() {
- if (drogue == MISSING)
- return MISSING;
- return AltosConvert.cc_ignitor_to_voltage(drogue);
- }
-
- /* Value for the CC1111 built-in temperature sensor
- * Output voltage at 0°C = 0.755V
- * Coefficient = 0.00247V/°C
- * Reference voltage = 1.25V
- *
- * temp = ((value / 32767) * 1.25 - 0.755) / 0.00247
- * = (value - 19791.268) / 32768 * 1.25 / 0.00247
- */
-
- static double
- thermometer_to_temperature(double thermo)
- {
- return (thermo - 19791.268) / 32728.0 * 1.25 / 0.00247;
- }
-
- public double temperature() {
- if (temp == MISSING)
- return MISSING;
- return thermometer_to_temperature(temp);
- }
-
- double accel_counts_per_mss() {
- double counts_per_g = Math.abs(accel_minus_g - accel_plus_g) / 2;
-
- return counts_per_g / 9.80665;
- }
-
- public double acceleration() {
- if (ground_accel == MISSING || accel == MISSING)
- return MISSING;
- return (ground_accel - accel) / accel_counts_per_mss();
- }
-
- public void copy(AltosRecordTM old) {
- super.copy(old);
-
- version = old.version;
- callsign = old.callsign;
- serial = old.serial;
- flight = old.flight;
- rssi = old.rssi;
- status = old.status;
- state = old.state;
- tick = old.tick;
- accel = old.accel;
- pres = old.pres;
- temp = old.temp;
- batt = old.batt;
- drogue = old.drogue;
- main = old.main;
- flight_accel = old.flight_accel;
- ground_accel = old.ground_accel;
- flight_vel = old.flight_vel;
- flight_pres = old.flight_pres;
- ground_pres = old.ground_pres;
- accel_plus_g = old.accel_plus_g;
- accel_minus_g = old.accel_minus_g;
- }
-
- public AltosRecordTM clone() {
- return new AltosRecordTM(this);
- }
-
- void make_missing() {
- accel = MISSING;
- pres = MISSING;
- temp = MISSING;
- batt = MISSING;
- drogue = MISSING;
- main = MISSING;
-
- flight_accel = MISSING;
- flight_vel = MISSING;
- flight_pres = MISSING;
-
- ground_accel = MISSING;
- ground_pres = MISSING;
- accel_plus_g = MISSING;
- accel_minus_g = MISSING;
- }
-
- public AltosRecordTM(AltosRecord old) {
- super.copy(old);
- make_missing();
- }
-
- public AltosRecordTM(AltosRecordTM old) {
- copy(old);
- }
-
- public AltosRecordTM() {
- super();
- make_missing();
- }
-}
diff --git a/altoslib/AltosReplayReader.java b/altoslib/AltosReplayReader.java
index a7e30370..19091d3d 100644
--- a/altoslib/AltosReplayReader.java
+++ b/altoslib/AltosReplayReader.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
import java.io.*;
import java.util.*;
@@ -25,10 +25,10 @@ import java.util.*;
*/
public class AltosReplayReader extends AltosFlightReader {
- Iterator<AltosRecord> iterator;
+ Iterator<AltosState> iterator;
File file;
- public AltosRecord read() {
+ public AltosState read() {
if (iterator.hasNext())
return iterator.next();
return null;
@@ -41,11 +41,12 @@ public class AltosReplayReader extends AltosFlightReader {
/* Make it run in realtime after the rocket leaves the pad */
if (state.state > AltosLib.ao_flight_pad)
Thread.sleep((int) (Math.min(state.time_change,10) * 1000));
+ state.set_received_time(System.currentTimeMillis());
}
public File backing_file() { return file; }
- public AltosReplayReader(Iterator<AltosRecord> in_iterator, File in_file) {
+ public AltosReplayReader(Iterator<AltosState> in_iterator, File in_file) {
iterator = in_iterator;
file = in_file;
name = file.getName();
diff --git a/altoslib/AltosRomconfig.java b/altoslib/AltosRomconfig.java
index 0800a2c4..2f106deb 100644
--- a/altoslib/AltosRomconfig.java
+++ b/altoslib/AltosRomconfig.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
import java.io.*;
@@ -26,7 +26,20 @@ public class AltosRomconfig {
public int serial_number;
public int radio_calibration;
- static int get_int(byte[] bytes, int start, int len) {
+ static private int find_offset(AltosHexfile hexfile, String name, int len) throws AltosNoSymbol {
+ AltosHexsym symbol = hexfile.lookup_symbol(name);
+ if (symbol == null)
+ throw new AltosNoSymbol(name);
+ int offset = (int) symbol.address - hexfile.address;
+ if (offset < 0 || hexfile.data.length < offset + len)
+ throw new AltosNoSymbol(name);
+ return offset;
+ }
+
+ static int get_int(AltosHexfile hexfile, String name, int len) throws AltosNoSymbol {
+ byte[] bytes = hexfile.data;
+ int start = find_offset(hexfile, name, len);
+
int v = 0;
int o = 0;
while (len > 0) {
@@ -38,7 +51,10 @@ public class AltosRomconfig {
return v;
}
- static void put_int(int value, byte[] bytes, int start, int len) {
+ static void put_int(int value, AltosHexfile hexfile, String name, int len) throws AltosNoSymbol, IOException {
+ byte[] bytes = hexfile.data;
+ int start = find_offset(hexfile, name, len);
+
while (len > 0) {
bytes[start] = (byte) (value & 0xff);
start++;
@@ -47,86 +63,155 @@ public class AltosRomconfig {
}
}
- static void put_string(String value, byte[] bytes, int start) {
+ static void put_string(String value, AltosHexfile hexfile, String name) throws AltosNoSymbol {
+ byte[] bytes = hexfile.data;
+ int start = find_offset(hexfile, name, value.length());
+
for (int i = 0; i < value.length(); i++)
bytes[start + i] = (byte) value.charAt(i);
}
static final int AO_USB_DESC_STRING = 3;
- static void put_usb_serial(int value, byte[] bytes, int start) {
- int offset = start + 0xa;
+ static void put_usb_serial(int value, AltosHexfile hexfile, String name) throws AltosNoSymbol {
+ byte[] bytes = hexfile.data;
+ int start = find_offset(hexfile, name, 2);
+
int string_num = 0;
- while (offset < bytes.length && bytes[offset] != 0) {
- if (bytes[offset + 1] == AO_USB_DESC_STRING) {
+ while (start < bytes.length && bytes[start] != 0) {
+ if (bytes[start + 1] == AO_USB_DESC_STRING) {
++string_num;
if (string_num == 4)
break;
}
- offset += ((int) bytes[offset]) & 0xff;
+ start += ((int) bytes[start]) & 0xff;
}
- if (offset >= bytes.length || bytes[offset] == 0)
- return;
- int len = ((((int) bytes[offset]) & 0xff) - 2) / 2;
+ if (start >= bytes.length || bytes[start] == 0)
+ throw new AltosNoSymbol(name);
+
+ int len = ((((int) bytes[start]) & 0xff) - 2) / 2;
String fmt = String.format("%%0%dd", len);
String s = String.format(fmt, value);
- if (s.length() != len) {
- System.out.printf("weird usb length issue %s isn't %d\n",
- s, len);
- return;
- }
+ if (s.length() != len)
+ throw new AltosNoSymbol(String.format("weird usb length issue %s isn't %d\n", s, len));
+
for (int i = 0; i < len; i++) {
- bytes[offset + 2 + i*2] = (byte) s.charAt(i);
- bytes[offset + 2 + i*2+1] = 0;
+ bytes[start + 2 + i*2] = (byte) s.charAt(i);
+ bytes[start + 2 + i*2+1] = 0;
}
}
- public AltosRomconfig(byte[] bytes, int offset) {
- version = get_int(bytes, offset + 0, 2);
- check = get_int(bytes, offset + 2, 2);
- if (check == (~version & 0xffff)) {
- switch (version) {
- case 2:
- case 1:
- serial_number = get_int(bytes, offset + 4, 2);
- radio_calibration = get_int(bytes, offset + 6, 4);
- valid = true;
- break;
+ final static String ao_romconfig_version = "ao_romconfig_version";
+ final static String ao_romconfig_check = "ao_romconfig_check";
+ final static String ao_serial_number = "ao_serial_number";
+ final static String ao_radio_cal = "ao_radio_cal";
+ final static String ao_usb_descriptors = "ao_usb_descriptors";
+
+ public AltosRomconfig(AltosHexfile hexfile) {
+ try {
+ version = get_int(hexfile, ao_romconfig_version, 2);
+ check = get_int(hexfile, ao_romconfig_check, 2);
+ if (check == (~version & 0xffff)) {
+ switch (version) {
+ case 2:
+ case 1:
+ serial_number = get_int(hexfile, ao_serial_number, 2);
+ try {
+ radio_calibration = get_int(hexfile, ao_radio_cal, 4);
+ } catch (AltosNoSymbol missing) {
+ radio_calibration = 0;
+ }
+ valid = true;
+ break;
+ }
}
+ } catch (AltosNoSymbol missing) {
+ valid = false;
}
}
- public AltosRomconfig(AltosHexfile hexfile) {
- this(hexfile.data, 0xa0 - hexfile.address);
+ private final static String[] fetch_names = {
+ ao_romconfig_version,
+ ao_romconfig_check,
+ ao_serial_number,
+ ao_radio_cal
+ };
+
+ private final static String[] required_names = {
+ ao_romconfig_version,
+ ao_romconfig_check,
+ ao_serial_number
+ };
+
+ private static boolean name_required(String name) {
+ for (String required : required_names)
+ if (name.equals(required))
+ return true;
+ return false;
}
- public void write(byte[] bytes, int offset) throws IOException {
+ public static int fetch_base(AltosHexfile hexfile) throws AltosNoSymbol {
+ int base = 0x7fffffff;
+ for (String name : fetch_names) {
+ try {
+ int addr = find_offset(hexfile, name, 2) + hexfile.address;
+ if (addr < base)
+ base = addr;
+ } catch (AltosNoSymbol ns) {
+ if (name_required(name))
+ throw (ns);
+ }
+ }
+ return base;
+ }
+
+ public static int fetch_bounds(AltosHexfile hexfile) throws AltosNoSymbol {
+ int bounds = 0;
+ for (String name : fetch_names) {
+ try {
+ int addr = find_offset(hexfile, name, 2) + hexfile.address;
+ if (addr > bounds)
+ bounds = addr;
+ } catch (AltosNoSymbol ns) {
+ if (name_required(name))
+ throw (ns);
+ }
+ }
+ return bounds + 2;
+ }
+
+ public void write (AltosHexfile hexfile) throws IOException {
if (!valid)
throw new IOException("rom configuration invalid");
- if (offset < 0 || bytes.length < offset + 10)
- throw new IOException("image cannot contain rom config");
-
- AltosRomconfig existing = new AltosRomconfig(bytes, offset);
+ AltosRomconfig existing = new AltosRomconfig(hexfile);
if (!existing.valid)
throw new IOException("image does not contain existing rom config");
- switch (existing.version) {
- case 2:
- put_usb_serial(serial_number, bytes, offset);
- case 1:
- put_int(serial_number, bytes, offset + 4, 2);
- put_int(radio_calibration, bytes, offset + 6, 4);
- break;
+ try {
+ switch (existing.version) {
+ case 2:
+ try {
+ put_usb_serial(serial_number, hexfile, ao_usb_descriptors);
+ } catch (AltosNoSymbol missing) {
+ }
+ /* fall through ... */
+ case 1:
+ put_int(serial_number, hexfile, ao_serial_number, 2);
+ try {
+ put_int(radio_calibration, hexfile, ao_radio_cal, 4);
+ } catch (AltosNoSymbol missing) {
+ }
+ break;
+ }
+ } catch (AltosNoSymbol missing) {
+ throw new IOException(missing.getMessage());
}
- }
- public void write (AltosHexfile hexfile) throws IOException {
- write(hexfile.data, 0xa0 - hexfile.address);
AltosRomconfig check = new AltosRomconfig(hexfile);
- if (!check.valid())
+ if (!check.valid)
throw new IOException("writing new rom config failed\n");
}
diff --git a/altoslib/AltosSelfFlash.java b/altoslib/AltosSelfFlash.java
new file mode 100644
index 00000000..3bf7ce41
--- /dev/null
+++ b/altoslib/AltosSelfFlash.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright © 2013 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_2;
+
+import java.io.*;
+
+public class AltosSelfFlash extends AltosProgrammer {
+ File file;
+ FileInputStream input;
+ AltosHexfile image;
+ AltosLink link;
+ boolean aborted;
+ AltosFlashListener listener;
+ AltosRomconfig rom_config;
+
+ void action(String s, int percent) {
+ if (listener != null && !aborted)
+ listener.position(s, percent);
+ }
+
+ void action(int part, int total) {
+ int percent = 100 * part / total;
+ action(String.format("%d/%d (%d%%)",
+ part, total, percent),
+ percent);
+ }
+
+ byte[] read_memory(long addr, int len) throws InterruptedException, IOException {
+ int b;
+ byte[] data = new byte[len];
+
+ for (int offset = 0; offset < len; offset += 0x100) {
+ link.printf("R %x\n", addr + offset);
+ byte[] reply = link.get_binary_reply(5000, 0x100);
+
+ if (reply == null)
+ throw new IOException("Read device memory timeout");
+ for (b = 0; b < len; b++)
+ data[b+offset] = reply[b];
+ }
+ return data;
+ }
+
+ void write_memory(long addr, byte[] data, int start, int len) {
+ int b;
+ link.printf("W %x\n", addr);
+ link.flush_output();
+ for (b = 0; b < len; b++)
+ link.putchar(data[start + b]);
+ for (; b < 0x100; b++)
+ link.putchar((byte) 0xff);
+ }
+
+ void reboot() {
+ link.printf("a\n");
+ link.flush_output();
+ }
+
+ public void flash() {
+ try {
+ if (!check_rom_config())
+ throw new IOException("Invalid rom config settings");
+
+ /*
+ * Store desired config values into image
+ */
+ rom_config.write(image);
+
+ int remain = image.data.length;
+ long flash_addr = image.address;
+ int image_start = 0;
+
+ action("start", 0);
+ action(0, image.data.length);
+ while (remain > 0 && !aborted) {
+ int this_time = remain;
+ if (this_time > 0x100)
+ this_time = 0x100;
+
+ if (link != null) {
+ /* write the data */
+ write_memory(flash_addr, image.data, image_start, this_time);
+
+ byte[] check = read_memory(flash_addr, this_time);
+ for (int i = 0; i < this_time; i++)
+ if (check[i] != image.data[image_start + i])
+ throw new IOException(String.format("Flash write failed at 0x%x (%02x != %02x)",
+ image.address + image_start + i,
+ check[i], image.data[image_start + i]));
+ } else {
+ Thread.sleep(100);
+ }
+
+ remain -= this_time;
+ flash_addr += this_time;
+ image_start += this_time;
+
+ action(image.data.length - remain, image.data.length);
+ }
+ if (!aborted) {
+ action("done", 100);
+ }
+ close();
+ } catch (IOException ie) {
+ action(ie.getMessage(), -1);
+ abort();
+ } catch (InterruptedException ie) {
+ abort();
+ }
+ }
+
+ public void close() {
+ if (link != null) {
+ reboot();
+ try {
+ link.close();
+ } catch (InterruptedException ie) {
+ }
+ link = null;
+ }
+ }
+
+ synchronized public void abort() {
+ aborted = true;
+ close();
+ }
+
+ private AltosHexfile get_rom() throws InterruptedException {
+ try {
+ int base = AltosRomconfig.fetch_base(image);
+ int bounds = AltosRomconfig.fetch_bounds(image);
+ byte[] data = read_memory(base, bounds - base);
+ AltosHexfile hexfile = new AltosHexfile(data, base);
+ hexfile.add_symbols(image);
+ return hexfile;
+ } catch (AltosNoSymbol none) {
+ return null;
+ } catch (IOException ie) {
+ return null;
+ }
+
+ }
+
+ public boolean check_rom_config() throws InterruptedException {
+ if (link == null) {
+ return true;
+ }
+ if (rom_config == null) {
+ AltosHexfile hexfile = get_rom();
+ if (hexfile != null)
+ rom_config = new AltosRomconfig(hexfile);
+ }
+ return rom_config != null && rom_config.valid();
+ }
+
+ public void set_romconfig (AltosRomconfig romconfig) {
+ rom_config = romconfig;
+ }
+
+ public AltosRomconfig romconfig() throws InterruptedException {
+ if (!check_rom_config())
+ return null;
+ return rom_config;
+ }
+
+ public AltosSelfFlash(File file, AltosLink link, AltosFlashListener listener)
+ throws IOException, FileNotFoundException, InterruptedException {
+ this.file = file;
+ this.link = link;
+ this.listener = listener;
+ input = new FileInputStream(file);
+ image = new AltosHexfile(input);
+ }
+} \ No newline at end of file
diff --git a/altoslib/AltosSensorEMini.java b/altoslib/AltosSensorEMini.java
new file mode 100644
index 00000000..5f9eed55
--- /dev/null
+++ b/altoslib/AltosSensorEMini.java
@@ -0,0 +1,69 @@
+/*
+ * 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_2;
+
+import java.util.concurrent.TimeoutException;
+
+public class AltosSensorEMini {
+ public int tick;
+ public int apogee;
+ public int main;
+ public int batt;
+
+ static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException {
+ try {
+ AltosSensorEMini sensor_emini = new AltosSensorEMini(link);
+
+ if (sensor_emini == null)
+ return;
+ state.set_battery_voltage(AltosConvert.easy_mini_voltage(sensor_emini.batt));
+ state.set_apogee_voltage(AltosConvert.easy_mini_voltage(sensor_emini.apogee));
+ state.set_main_voltage(AltosConvert.easy_mini_voltage(sensor_emini.main));
+
+ } catch (TimeoutException te) {
+ }
+ }
+
+ public AltosSensorEMini(AltosLink link) throws InterruptedException, TimeoutException {
+ String[] items = link.adc();
+ for (int i = 0; i < items.length;) {
+ if (items[i].equals("tick:")) {
+ tick = Integer.parseInt(items[i+1]);
+ i += 2;
+ continue;
+ }
+ if (items[i].equals("apogee:")) {
+ apogee = Integer.parseInt(items[i+1]);
+ i += 2;
+ continue;
+ }
+ if (items[i].equals("main:")) {
+ main = Integer.parseInt(items[i+1]);
+ i += 2;
+ continue;
+ }
+ if (items[i].equals("batt:")) {
+ batt = Integer.parseInt(items[i+1]);
+ i += 2;
+ continue;
+ }
+ i++;
+ }
+ }
+}
+
diff --git a/altoslib/AltosSensorMM.java b/altoslib/AltosSensorMM.java
index 6d1b61c0..0ef42cf6 100644
--- a/altoslib/AltosSensorMM.java
+++ b/altoslib/AltosSensorMM.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
import java.util.concurrent.TimeoutException;
diff --git a/altoslib/AltosSensorMega.java b/altoslib/AltosSensorMega.java
new file mode 100644
index 00000000..e715242a
--- /dev/null
+++ b/altoslib/AltosSensorMega.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright © 2013 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_2;
+
+import java.util.concurrent.TimeoutException;
+
+class AltosSensorMega {
+ int tick;
+ int[] sense;
+ int v_batt;
+ int v_pbatt;
+ int temp;
+
+ public AltosSensorMega() {
+ sense = new int[6];
+ }
+
+ public AltosSensorMega(AltosLink link) throws InterruptedException, TimeoutException {
+ this();
+ String[] items = link.adc();
+ for (int i = 0; i < items.length;) {
+ if (items[i].equals("tick:")) {
+ tick = Integer.parseInt(items[i+1]);
+ i += 2;
+ continue;
+ }
+ if (items[i].equals("A:")) {
+ sense[0] = Integer.parseInt(items[i+1]);
+ i += 2;
+ continue;
+ }
+ if (items[i].equals("B:")) {
+ sense[1] = Integer.parseInt(items[i+1]);
+ i += 2;
+ continue;
+ }
+ if (items[i].equals("C:")) {
+ sense[2] = Integer.parseInt(items[i+1]);
+ i += 2;
+ continue;
+ }
+ if (items[i].equals("D:")) {
+ sense[3] = Integer.parseInt(items[i+1]);
+ i += 2;
+ continue;
+ }
+ if (items[i].equals("drogue:")) {
+ sense[4] = Integer.parseInt(items[i+1]);
+ i += 2;
+ continue;
+ }
+ if (items[i].equals("main:")) {
+ sense[5] = Integer.parseInt(items[i+1]);
+ i += 2;
+ continue;
+ }
+ if (items[i].equals("batt:")) {
+ v_batt = Integer.parseInt(items[i+1]);
+ i += 2;
+ continue;
+ }
+ if (items[i].equals("pbatt:")) {
+ v_pbatt = Integer.parseInt(items[i+1]);
+ i += 2;
+ continue;
+ }
+ if (items[i].equals("temp:")) {
+ temp = Integer.parseInt(items[i+1]);
+ i += 2;
+ continue;
+ }
+ i++;
+ }
+ }
+
+ static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException {
+ try {
+ AltosSensorMega sensor_mega = new AltosSensorMega(link);
+
+ state.set_battery_voltage(AltosConvert.mega_battery_voltage(sensor_mega.v_batt));
+ state.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sensor_mega.sense[4]));
+ state.set_main_voltage(AltosConvert.mega_pyro_voltage(sensor_mega.sense[5]));
+
+ double[] ignitor_voltage = new double[4];
+ for (int i = 0; i < 4; i++)
+ ignitor_voltage[i] = AltosConvert.mega_pyro_voltage(sensor_mega.sense[i]);
+ state.set_ignitor_voltage(ignitor_voltage);
+
+ } catch (TimeoutException te) {
+ }
+ }
+}
+
diff --git a/altoslib/AltosSensorMetrum.java b/altoslib/AltosSensorMetrum.java
new file mode 100644
index 00000000..c30eaebd
--- /dev/null
+++ b/altoslib/AltosSensorMetrum.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright © 2013 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_2;
+
+import java.util.concurrent.TimeoutException;
+
+class AltosSensorMetrum {
+ int tick;
+ int sense_a;
+ int sense_m;
+ int v_batt;
+
+ public AltosSensorMetrum(AltosLink link) throws InterruptedException, TimeoutException {
+ String[] items = link.adc();
+ for (int i = 0; i < items.length;) {
+ if (items[i].equals("tick:")) {
+ tick = Integer.parseInt(items[i+1]);
+ i += 2;
+ continue;
+ }
+ if (items[i].equals("drogue:")) {
+ sense_a = Integer.parseInt(items[i+1]);
+ i += 2;
+ continue;
+ }
+ if (items[i].equals("main:")) {
+ sense_m = Integer.parseInt(items[i+1]);
+ i += 2;
+ continue;
+ }
+ if (items[i].equals("batt:")) {
+ v_batt = Integer.parseInt(items[i+1]);
+ i += 2;
+ continue;
+ }
+ i++;
+ }
+ }
+
+ static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException {
+ try {
+ AltosSensorMetrum sensor_metrum = new AltosSensorMetrum(link);
+ state.set_battery_voltage(AltosConvert.mega_battery_voltage(sensor_metrum.v_batt));
+ state.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sensor_metrum.sense_a));
+ state.set_main_voltage(AltosConvert.mega_pyro_voltage(sensor_metrum.sense_m));
+ } catch (TimeoutException te) {
+ }
+ }
+}
+
diff --git a/altoslib/AltosSensorTM.java b/altoslib/AltosSensorTM.java
index 754dc5bb..f867de4b 100644
--- a/altoslib/AltosSensorTM.java
+++ b/altoslib/AltosSensorTM.java
@@ -15,14 +15,37 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
import java.util.concurrent.TimeoutException;
-class AltosSensorTM extends AltosRecordTM {
+public class AltosSensorTM {
+ public int tick;
+ public int accel;
+ public int pres;
+ public int temp;
+ public int batt;
+ public int drogue;
+ public int main;
- public AltosSensorTM(AltosLink link, AltosConfigData config_data) throws InterruptedException, TimeoutException {
- super();
+ static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException {
+ try {
+ AltosSensorTM sensor_tm = new AltosSensorTM(link);
+
+ if (sensor_tm == null)
+ return;
+ state.set_accel(sensor_tm.accel);
+ state.set_pressure(AltosConvert.barometer_to_pressure(sensor_tm.pres));
+ state.set_temperature(AltosConvert.thermometer_to_temperature(sensor_tm.temp));
+ state.set_battery_voltage(AltosConvert.cc_battery_to_voltage(sensor_tm.batt));
+ state.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(sensor_tm.drogue));
+ state.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(sensor_tm.main));
+
+ } catch (TimeoutException te) {
+ }
+ }
+
+ public AltosSensorTM(AltosLink link) throws InterruptedException, TimeoutException {
String[] items = link.adc();
for (int i = 0; i < items.length;) {
if (items[i].equals("tick:")) {
@@ -62,10 +85,6 @@ class AltosSensorTM extends AltosRecordTM {
}
i++;
}
- ground_accel = config_data.accel_cal_plus;
- ground_pres = pres;
- accel_plus_g = config_data.accel_cal_plus;
- accel_minus_g = config_data.accel_cal_minus;
}
}
diff --git a/altoslib/AltosSensorTMini.java b/altoslib/AltosSensorTMini.java
new file mode 100644
index 00000000..ee030910
--- /dev/null
+++ b/altoslib/AltosSensorTMini.java
@@ -0,0 +1,69 @@
+/*
+ * 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_2;
+
+import java.util.concurrent.TimeoutException;
+
+public class AltosSensorTMini {
+ public int tick;
+ public int apogee;
+ public int main;
+ public int batt;
+
+ static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException {
+ try {
+ AltosSensorTMini sensor_tmini = new AltosSensorTMini(link);
+
+ if (sensor_tmini == null)
+ return;
+ state.set_battery_voltage(AltosConvert.easy_mini_voltage(sensor_tmini.batt));
+ state.set_apogee_voltage(AltosConvert.easy_mini_voltage(sensor_tmini.apogee));
+ state.set_main_voltage(AltosConvert.easy_mini_voltage(sensor_tmini.main));
+
+ } catch (TimeoutException te) {
+ }
+ }
+
+ public AltosSensorTMini(AltosLink link) throws InterruptedException, TimeoutException {
+ String[] items = link.adc();
+ for (int i = 0; i < items.length;) {
+ if (items[i].equals("tick:")) {
+ tick = Integer.parseInt(items[i+1]);
+ i += 2;
+ continue;
+ }
+ if (items[i].equals("apogee:")) {
+ apogee = Integer.parseInt(items[i+1]);
+ i += 2;
+ continue;
+ }
+ if (items[i].equals("main:")) {
+ main = Integer.parseInt(items[i+1]);
+ i += 2;
+ continue;
+ }
+ if (items[i].equals("batt:")) {
+ batt = Integer.parseInt(items[i+1]);
+ i += 2;
+ continue;
+ }
+ i++;
+ }
+ }
+}
+
diff --git a/altoslib/AltosSpeed.java b/altoslib/AltosSpeed.java
index 6fb624fb..6618c539 100644
--- a/altoslib/AltosSpeed.java
+++ b/altoslib/AltosSpeed.java
@@ -15,29 +15,35 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
public class AltosSpeed extends AltosUnits {
- public double value(double v) {
- if (AltosConvert.imperial_units)
+ public double value(double v, boolean imperial_units) {
+ if (imperial_units)
return AltosConvert.meters_to_mph(v);
return v;
}
- public String show_units() {
- if (AltosConvert.imperial_units)
+ public double inverse(double v, boolean imperial_units) {
+ if (imperial_units)
+ return AltosConvert.mph_to_meters(v);
+ return v;
+ }
+
+ public String show_units(boolean imperial_units) {
+ if (imperial_units)
return "mph";
return "m/s";
}
- public String say_units() {
- if (AltosConvert.imperial_units)
+ public String say_units(boolean imperial_units) {
+ if (imperial_units)
return "miles per hour";
return "meters per second";
}
- public int show_fraction(int width) {
+ public int show_fraction(int width, boolean imperial_units) {
return width / 9;
}
} \ No newline at end of file
diff --git a/altoslib/AltosState.java b/altoslib/AltosState.java
index 825306be..6d55b833 100644
--- a/altoslib/AltosState.java
+++ b/altoslib/AltosState.java
@@ -19,41 +19,471 @@
* Track flight state from telemetry or eeprom data stream
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
-public class AltosState {
- public AltosRecord data;
+public class AltosState implements Cloneable {
+
+ public static final int set_position = 1;
+ public static final int set_gps = 2;
+ public static final int set_data = 4;
+
+ public int set;
+
+ static final double ascent_filter_len = 0.5;
+ static final double descent_filter_len = 0.5;
/* derived data */
- public long report_time;
+ public long received_time;
public double time;
+ public double prev_time;
public double time_change;
public int tick;
+ private int prev_tick;
+ public int boost_tick;
+
+ class AltosValue {
+ private double value;
+ private double prev_value;
+ private double max_value;
+ private double set_time;
+ private double prev_set_time;
+
+ void set(double new_value, double time) {
+ if (new_value != AltosLib.MISSING) {
+ value = new_value;
+ if (max_value == AltosLib.MISSING || value > max_value) {
+ max_value = value;
+ }
+ set_time = time;
+ }
+ }
+
+ void set_filtered(double new_value, double time) {
+ if (prev_value != AltosLib.MISSING)
+ new_value = (prev_value * 15.0 + new_value) / 16.0;
+ set(new_value, time);
+ }
+
+ double value() {
+ return value;
+ }
+
+ double max() {
+ return max_value;
+ }
+
+ double prev() {
+ return prev_value;
+ }
+
+ double change() {
+ if (value != AltosLib.MISSING && prev_value != AltosLib.MISSING)
+ return value - prev_value;
+ return AltosLib.MISSING;
+ }
+
+ double rate() {
+ double c = change();
+ double t = set_time - prev_set_time;
+
+ if (c != AltosLib.MISSING && t != 0)
+ return c / t;
+ return AltosLib.MISSING;
+ }
+
+ double integrate() {
+ if (value == AltosLib.MISSING)
+ return AltosLib.MISSING;
+ if (prev_value == AltosLib.MISSING)
+ return AltosLib.MISSING;
+
+ return (value + prev_value) / 2 * (set_time - prev_set_time);
+ }
+
+ double time() {
+ return set_time;
+ }
+
+ void set_derivative(AltosValue in) {
+ double n = in.rate();
+
+ if (n == AltosLib.MISSING)
+ return;
+
+ double p = prev_value;
+ double pt = prev_set_time;
+
+ if (p == AltosLib.MISSING) {
+ p = 0;
+ pt = in.time() - 0.01;
+ }
+
+ /* Clip changes to reduce noise */
+ double ddt = in.time() - pt;
+ double ddv = (n - p) / ddt;
+
+ final double max = 100000;
+
+ /* 100gs */
+ if (Math.abs(ddv) > max) {
+ if (n > p)
+ n = p + ddt * max;
+ else
+ n = p - ddt * max;
+ }
+
+ double filter_len;
+
+ if (ascent)
+ filter_len = ascent_filter_len;
+ else
+ filter_len = descent_filter_len;
+
+ double f = 1/Math.exp(ddt/ filter_len);
+ n = p * f + n * (1-f);
+
+ set(n, in.time());
+ }
+
+ void set_integral(AltosValue in) {
+ double change = in.integrate();
+
+ if (change != AltosLib.MISSING) {
+ double prev = prev_value;
+ if (prev == AltosLib.MISSING)
+ prev = 0;
+ set(prev + change, in.time());
+ }
+ }
+
+ void copy(AltosValue old) {
+ value = old.value;
+ set_time = old.set_time;
+ prev_value = old.value;
+ prev_set_time = old.set_time;
+ max_value = old.max_value;
+ }
+
+ void finish_update() {
+ prev_value = value;
+ prev_set_time = set_time;
+ }
+
+ AltosValue() {
+ value = AltosLib.MISSING;
+ prev_value = AltosLib.MISSING;
+ max_value = AltosLib.MISSING;
+ }
+ }
+
+ class AltosCValue {
+ AltosValue measured;
+ AltosValue computed;
+
+ double value() {
+ double v = measured.value();
+ if (v != AltosLib.MISSING)
+ return v;
+ return computed.value();
+ }
+
+ boolean is_measured() {
+ return measured.value() != AltosLib.MISSING;
+ }
+
+ double max() {
+ double m = measured.max();
+
+ if (m != AltosLib.MISSING)
+ return m;
+ return computed.max();
+ }
+
+ double prev_value() {
+ if (measured.value != AltosLib.MISSING && measured.prev_value != AltosLib.MISSING)
+ return measured.prev_value;
+ return computed.prev_value;
+ }
+
+ AltosValue altos_value() {
+ if (measured.value() != AltosLib.MISSING)
+ return measured;
+ return computed;
+ }
+
+ double change() {
+ double c = measured.change();
+ if (c == AltosLib.MISSING)
+ c = computed.change();
+ return c;
+ }
+
+ double rate() {
+ double r = measured.rate();
+ if (r == AltosLib.MISSING)
+ r = computed.rate();
+ return r;
+ }
+
+ void set_measured(double new_value, double time) {
+ measured.set(new_value, time);
+ }
+
+ void set_computed(double new_value, double time) {
+ computed.set(new_value, time);
+ }
+
+ void set_derivative(AltosValue in) {
+ computed.set_derivative(in);
+ }
+
+ void set_derivative(AltosCValue in) {
+ set_derivative(in.altos_value());
+ }
+
+ void set_integral(AltosValue in) {
+ computed.set_integral(in);
+ }
+
+ void set_integral(AltosCValue in) {
+ set_integral(in.altos_value());
+ }
+
+ void copy(AltosCValue old) {
+ measured.copy(old.measured);
+ computed.copy(old.computed);
+ }
+
+ void finish_update() {
+ measured.finish_update();
+ computed.finish_update();
+ }
+
+ AltosCValue() {
+ measured = new AltosValue();
+ computed = new AltosValue();
+ }
+ }
public int state;
+ public int flight;
+ public int serial;
+ public int receiver_serial;
public boolean landed;
public boolean ascent; /* going up? */
- public boolean boost; /* under power */
+ public boolean boost; /* under power */
+ public int rssi;
+ public int status;
+ public int device_type;
+ public int config_major;
+ public int config_minor;
+ public int apogee_delay;
+ public int main_deploy;
+ public int flight_log_max;
+
+ private double pressure_to_altitude(double p) {
+ if (p == AltosLib.MISSING)
+ return AltosLib.MISSING;
+ return AltosConvert.pressure_to_altitude(p);
+ }
+
+ private AltosCValue ground_altitude;
- public double ground_altitude;
- public double altitude;
- public double height;
- public double acceleration;
- public double battery;
+ public double ground_altitude() {
+ return ground_altitude.value();
+ }
+
+ public void set_ground_altitude(double a) {
+ ground_altitude.set_measured(a, time);
+ }
+
+ class AltosGroundPressure extends AltosCValue {
+ void set_filtered(double p, double time) {
+ computed.set_filtered(p, time);
+ if (!is_measured())
+ ground_altitude.set_computed(pressure_to_altitude(computed.value()), time);
+ }
+
+ void set_measured(double p, double time) {
+ super.set_measured(p, time);
+ ground_altitude.set_computed(pressure_to_altitude(p), time);
+ }
+ }
+
+ private AltosGroundPressure ground_pressure;
+
+ public double ground_pressure() {
+ return ground_pressure.value();
+ }
+
+ public void set_ground_pressure (double pressure) {
+ ground_pressure.set_measured(pressure, time);
+ }
+
+ class AltosAltitude extends AltosCValue {
+
+ private void set_speed(AltosValue v) {
+ if (!acceleration.is_measured() || !ascent)
+ speed.set_derivative(this);
+ }
+
+ void set_computed(double a, double time) {
+ super.set_computed(a,time);
+ set_speed(computed);
+ set |= set_position;
+ }
+
+ void set_measured(double a, double time) {
+ super.set_measured(a,time);
+ set_speed(measured);
+ set |= set_position;
+ }
+ }
+
+ private AltosAltitude altitude;
+
+ public double altitude() {
+ double a = altitude.value();
+ if (a != AltosLib.MISSING)
+ return a;
+ if (gps != null)
+ return gps.alt;
+ return AltosLib.MISSING;
+ }
+
+ public double max_altitude() {
+ double a = altitude.max();
+ if (a != AltosLib.MISSING)
+ return a;
+ return AltosLib.MISSING;
+ }
+
+ public void set_altitude(double new_altitude) {
+ altitude.set_measured(new_altitude, time);
+ }
+
+ class AltosPressure extends AltosValue {
+ void set(double p, double time) {
+ super.set(p, time);
+ if (state == AltosLib.ao_flight_pad)
+ ground_pressure.set_filtered(p, time);
+ double a = pressure_to_altitude(p);
+ altitude.set_computed(a, time);
+ }
+ }
+
+ private AltosPressure pressure;
+
+ public double pressure() {
+ return pressure.value();
+ }
+
+ public void set_pressure(double p) {
+ pressure.set(p, time);
+ }
+
+ public double height() {
+ double k = kalman_height.value();
+ if (k != AltosLib.MISSING)
+ return k;
+
+ double a = altitude();
+ double g = ground_altitude();
+ if (a != AltosLib.MISSING && g != AltosLib.MISSING)
+ return a - g;
+ return AltosLib.MISSING;
+ }
+
+ public double max_height() {
+ double k = kalman_height.max();
+ if (k != AltosLib.MISSING)
+ return k;
+
+ double a = altitude.max();
+ double g = ground_altitude();
+ if (a != AltosLib.MISSING && g != AltosLib.MISSING)
+ return a - g;
+ return AltosLib.MISSING;
+ }
+
+ class AltosSpeed extends AltosCValue {
+
+ void set_accel() {
+ acceleration.set_derivative(this);
+ }
+
+ void set_derivative(AltosCValue in) {
+ super.set_derivative(in);
+ set_accel();
+ }
+
+ void set_computed(double new_value, double time) {
+ super.set_computed(new_value, time);
+ set_accel();
+ }
+
+ void set_measured(double new_value, double time) {
+ super.set_measured(new_value, time);
+ set_accel();
+ }
+ }
+
+ private AltosSpeed speed;
+
+ public double speed() {
+ double v = kalman_speed.value();
+ if (v != AltosLib.MISSING)
+ return v;
+ return speed.value();
+ }
+
+ public double max_speed() {
+ double v = kalman_speed.max();
+ if (v != AltosLib.MISSING)
+ return v;
+ return speed.max();
+ }
+
+ class AltosAccel extends AltosCValue {
+ void set_measured(double a, double time) {
+ super.set_measured(a, time);
+ if (ascent)
+ speed.set_integral(this.measured);
+ }
+ }
+
+ AltosAccel acceleration;
+
+ public double acceleration() {
+ return acceleration.value();
+ }
+
+ public double max_acceleration() {
+ return acceleration.max();
+ }
+
+ public AltosValue kalman_height, kalman_speed, kalman_acceleration;
+
+ public void set_kalman(double height, double speed, double acceleration) {
+ kalman_height.set(height, time);
+ kalman_speed.set(speed, time);
+ kalman_acceleration.set(acceleration, time);
+ }
+
+ public double battery_voltage;
+ public double pyro_voltage;
public double temperature;
- public double main_sense;
- public double drogue_sense;
- public double accel_speed;
- public double baro_speed;
+ public double apogee_voltage;
+ public double main_voltage;
- public double max_height;
- public double max_acceleration;
- public double max_accel_speed;
- public double max_baro_speed;
+ public double ignitor_voltage[];
public AltosGPS gps;
+ public AltosGPS temp_gps;
+ public int temp_gps_sat_tick;
+ public boolean gps_pending;
public int gps_sequence;
public AltosIMU imu;
@@ -62,10 +492,11 @@ public class AltosState {
public static final int MIN_PAD_SAMPLES = 10;
public int npad;
- public int ngps;
public int gps_waiting;
public boolean gps_ready;
+ public int ngps;
+
public AltosGreatCircle from_pad;
public double elevation; /* from pad */
public double range; /* total distance */
@@ -77,202 +508,554 @@ public class AltosState {
public int speak_tick;
public double speak_altitude;
- public double speed() {
- if (ascent)
- return accel_speed;
- else
- return baro_speed;
+ public String callsign;
+ public String firmware_version;
+
+ public double accel_plus_g;
+ public double accel_minus_g;
+ public double accel;
+ public double ground_accel;
+ public double ground_accel_avg;
+
+ public int log_format;
+
+ public AltosMs5607 baro;
+
+ public AltosCompanion companion;
+
+ public void set_npad(int npad) {
+ this.npad = npad;
+ gps_waiting = MIN_PAD_SAMPLES - npad;
+ if (this.gps_waiting < 0)
+ gps_waiting = 0;
+ gps_ready = gps_waiting == 0;
}
- 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;
-
- /* Discard previous state if it was for a different board */
- if (prev_state != null && prev_state.data.serial != data.serial)
- prev_state = null;
- ground_altitude = data.ground_altitude();
-
- altitude = data.altitude();
- if (altitude == AltosRecord.MISSING && data.gps != null)
- altitude = data.gps.alt;
-
- height = AltosRecord.MISSING;
- if (data.kalman_height != AltosRecord.MISSING)
- height = data.kalman_height;
- else {
- if (altitude != AltosRecord.MISSING && ground_altitude != AltosRecord.MISSING) {
- double cur_height = altitude - ground_altitude;
- if (prev_state == null || prev_state.height == AltosRecord.MISSING)
- height = cur_height;
- else
- height = (prev_state.height * 15 + cur_height) / 16.0;
- }
+ public void init() {
+ set = 0;
+
+ received_time = System.currentTimeMillis();
+ time = AltosLib.MISSING;
+ time_change = AltosLib.MISSING;
+ prev_time = AltosLib.MISSING;
+ tick = AltosLib.MISSING;
+ prev_tick = AltosLib.MISSING;
+ boost_tick = AltosLib.MISSING;
+ state = AltosLib.ao_flight_invalid;
+ flight = AltosLib.MISSING;
+ landed = false;
+ boost = false;
+ rssi = AltosLib.MISSING;
+ status = 0;
+ device_type = AltosLib.MISSING;
+ config_major = AltosLib.MISSING;
+ config_minor = AltosLib.MISSING;
+ apogee_delay = AltosLib.MISSING;
+ main_deploy = AltosLib.MISSING;
+ flight_log_max = AltosLib.MISSING;
+
+ ground_altitude = new AltosCValue();
+ ground_pressure = new AltosGroundPressure();
+ altitude = new AltosAltitude();
+ pressure = new AltosPressure();
+ speed = new AltosSpeed();
+ acceleration = new AltosAccel();
+
+ temperature = AltosLib.MISSING;
+ battery_voltage = AltosLib.MISSING;
+ pyro_voltage = AltosLib.MISSING;
+ apogee_voltage = AltosLib.MISSING;
+ main_voltage = AltosLib.MISSING;
+ ignitor_voltage = null;
+
+ kalman_height = new AltosValue();
+ kalman_speed = new AltosValue();
+ kalman_acceleration = new AltosValue();
+
+ gps = null;
+ temp_gps = null;
+ temp_gps_sat_tick = 0;
+ gps_sequence = 0;
+ gps_pending = false;
+
+ imu = null;
+ mag = null;
+
+ set_npad(0);
+ ngps = 0;
+
+ from_pad = null;
+ elevation = AltosLib.MISSING;
+ range = AltosLib.MISSING;
+ gps_height = AltosLib.MISSING;
+
+ pad_lat = AltosLib.MISSING;
+ pad_lon = AltosLib.MISSING;
+ pad_alt = AltosLib.MISSING;
+
+ speak_tick = AltosLib.MISSING;
+ speak_altitude = AltosLib.MISSING;
+
+ callsign = null;
+
+ accel_plus_g = AltosLib.MISSING;
+ accel_minus_g = AltosLib.MISSING;
+ accel = AltosLib.MISSING;
+
+ ground_accel = AltosLib.MISSING;
+ ground_accel_avg = AltosLib.MISSING;
+
+ log_format = AltosLib.MISSING;
+ serial = AltosLib.MISSING;
+ receiver_serial = AltosLib.MISSING;
+
+ baro = null;
+ companion = null;
+ }
+
+ void finish_update() {
+ prev_tick = tick;
+
+ ground_altitude.finish_update();
+ altitude.finish_update();
+ pressure.finish_update();
+ speed.finish_update();
+ acceleration.finish_update();
+
+ kalman_height.finish_update();
+ kalman_speed.finish_update();
+ kalman_acceleration.finish_update();
+ }
+
+ void copy(AltosState old) {
+
+ if (old == null) {
+ init();
+ return;
}
- report_time = System.currentTimeMillis();
+ received_time = old.received_time;
+ time = old.time;
+ time_change = old.time_change;
+ prev_time = old.time;
+
+ tick = old.tick;
+ prev_tick = old.tick;
+ boost_tick = old.boost_tick;
+
+ state = old.state;
+ flight = old.flight;
+ landed = old.landed;
+ ascent = old.ascent;
+ boost = old.boost;
+ rssi = old.rssi;
+ status = old.status;
+ device_type = old.device_type;
+ config_major = old.config_major;
+ config_minor = old.config_minor;
+ apogee_delay = old.apogee_delay;
+ main_deploy = old.main_deploy;
+ flight_log_max = old.flight_log_max;
+
+ set = 0;
+
+ ground_pressure.copy(old.ground_pressure);
+ ground_altitude.copy(old.ground_altitude);
+ altitude.copy(old.altitude);
+ pressure.copy(old.pressure);
+ speed.copy(old.speed);
+ acceleration.copy(old.acceleration);
+
+ battery_voltage = old.battery_voltage;
+ pyro_voltage = old.pyro_voltage;
+ temperature = old.temperature;
+ apogee_voltage = old.apogee_voltage;
+ main_voltage = old.main_voltage;
+ ignitor_voltage = old.ignitor_voltage;
+
+ kalman_height.copy(old.kalman_height);
+ kalman_speed.copy(old.kalman_speed);
+ kalman_acceleration.copy(old.kalman_acceleration);
- if (data.kalman_acceleration != AltosRecord.MISSING)
- acceleration = data.kalman_acceleration;
+ if (old.gps != null)
+ gps = old.gps.clone();
else
- acceleration = data.acceleration();
- temperature = data.temperature();
- drogue_sense = data.drogue_voltage();
- main_sense = data.main_voltage();
- battery = data.battery_voltage();
- tick = data.tick;
- state = data.state;
-
- if (prev_state != null) {
-
- /* Preserve any existing gps data */
- npad = prev_state.npad;
- ngps = prev_state.ngps;
- gps = prev_state.gps;
- gps_sequence = prev_state.gps_sequence;
- pad_lat = prev_state.pad_lat;
- pad_lon = prev_state.pad_lon;
- pad_alt = prev_state.pad_alt;
- max_height = prev_state.max_height;
- max_acceleration = prev_state.max_acceleration;
- max_accel_speed = prev_state.max_accel_speed;
- max_baro_speed = prev_state.max_baro_speed;
- imu = prev_state.imu;
- mag = prev_state.mag;
-
- /* make sure the clock is monotonic */
- while (tick < prev_state.tick)
- tick += 65536;
-
- time_change = (tick - prev_state.tick) / 100.0;
-
- if (data.kalman_speed != AltosRecord.MISSING) {
- baro_speed = accel_speed = data.kalman_speed;
- } else {
- /* compute barometric speed */
-
- double height_change = height - prev_state.height;
-
- double prev_baro_speed = prev_state.baro_speed;
- if (prev_baro_speed == AltosRecord.MISSING)
- prev_baro_speed = 0;
-
- if (time_change > 0)
- baro_speed = (prev_baro_speed * 3 + (height_change / time_change)) / 4.0;
- else
- baro_speed = prev_state.baro_speed;
+ gps = null;
+ if (old.temp_gps != null)
+ temp_gps = old.temp_gps.clone();
+ else
+ temp_gps = null;
+ temp_gps_sat_tick = old.temp_gps_sat_tick;
+ gps_sequence = old.gps_sequence;
+ gps_pending = old.gps_pending;
- double prev_accel_speed = prev_state.accel_speed;
+ if (old.imu != null)
+ imu = old.imu.clone();
+ else
+ imu = null;
- if (prev_accel_speed == AltosRecord.MISSING)
- prev_accel_speed = 0;
+ if (old.mag != null)
+ mag = old.mag.clone();
+ else
+ mag = null;
- if (acceleration == AltosRecord.MISSING) {
- /* Fill in mising acceleration value */
- accel_speed = baro_speed;
+ npad = old.npad;
+ gps_waiting = old.gps_waiting;
+ gps_ready = old.gps_ready;
+ ngps = old.ngps;
- if (time_change > 0 && accel_speed != AltosRecord.MISSING)
- acceleration = (accel_speed - prev_accel_speed) / time_change;
- else
- acceleration = prev_state.acceleration;
- } else {
- /* compute accelerometer speed */
- accel_speed = prev_accel_speed + acceleration * time_change;
+ if (old.from_pad != null)
+ from_pad = old.from_pad.clone();
+ else
+ from_pad = null;
+
+ elevation = old.elevation;
+ range = old.range;
+
+ gps_height = old.gps_height;
+ pad_lat = old.pad_lat;
+ pad_lon = old.pad_lon;
+ pad_alt = old.pad_alt;
+
+ speak_tick = old.speak_tick;
+ speak_altitude = old.speak_altitude;
+
+ callsign = old.callsign;
+
+ accel_plus_g = old.accel_plus_g;
+ accel_minus_g = old.accel_minus_g;
+ accel = old.accel;
+ ground_accel = old.ground_accel;
+ ground_accel_avg = old.ground_accel_avg;
+
+ log_format = old.log_format;
+ serial = old.serial;
+ receiver_serial = old.receiver_serial;
+
+ baro = old.baro;
+ companion = old.companion;
+ }
+
+ void update_time() {
+ }
+
+ void update_gps() {
+ elevation = 0;
+ range = -1;
+ gps_height = 0;
+
+ if (gps == null)
+ return;
+
+ if (gps.locked && gps.nsat >= 4) {
+ /* Track consecutive 'good' gps reports, waiting for 10 of them */
+ if (state == AltosLib.ao_flight_pad) {
+ set_npad(npad+1);
+ if (pad_lat != AltosLib.MISSING) {
+ pad_lat = (pad_lat * 31 + gps.lat) / 32;
+ pad_lon = (pad_lon * 31 + gps.lon) / 32;
+ pad_alt = (pad_alt * 31 + gps.alt) / 32;
}
}
- } else {
- npad = 0;
- ngps = 0;
- gps = null;
- gps_sequence = 0;
- baro_speed = AltosRecord.MISSING;
- accel_speed = AltosRecord.MISSING;
- pad_alt = AltosRecord.MISSING;
- max_baro_speed = 0;
- max_accel_speed = 0;
- max_height = 0;
- max_acceleration = 0;
- time_change = 0;
+ if (pad_lat == AltosLib.MISSING) {
+ pad_lat = gps.lat;
+ pad_lon = gps.lon;
+ pad_alt = gps.alt;
+ }
}
+ if (gps.lat != 0 && gps.lon != 0 &&
+ pad_lat != AltosLib.MISSING &&
+ pad_lon != AltosLib.MISSING)
+ {
+ double h = height();
- time = tick / 100.0;
-
- if (data.gps != null && data.gps_sequence != gps_sequence && (state < AltosLib.ao_flight_boost)) {
+ if (h == AltosLib.MISSING)
+ h = 0;
+ from_pad = new AltosGreatCircle(pad_lat, pad_lon, 0, gps.lat, gps.lon, h);
+ elevation = from_pad.elevation;
+ range = from_pad.range;
+ gps_height = gps.alt - pad_alt;
+ }
+ }
- /* Track consecutive 'good' gps reports, waiting for 10 of them */
- if (data.gps != null && data.gps.locked && data.gps.nsat >= 4)
- npad++;
- else
- npad = 0;
-
- /* Average GPS data while on the pad */
- if (data.gps != null && data.gps.locked && data.gps.nsat >= 4) {
- if (ngps > 1 && state == AltosLib.ao_flight_pad) {
- /* filter pad position */
- pad_lat = (pad_lat * 31.0 + data.gps.lat) / 32.0;
- pad_lon = (pad_lon * 31.0 + data.gps.lon) / 32.0;
- pad_alt = (pad_alt * 31.0 + data.gps.alt) / 32.0;
- } else {
- pad_lat = data.gps.lat;
- pad_lon = data.gps.lon;
- pad_alt = data.gps.alt;
+ public void set_tick(int new_tick) {
+ if (new_tick != AltosLib.MISSING) {
+ if (prev_tick != AltosLib.MISSING) {
+ while (new_tick < prev_tick - 1000) {
+ new_tick += 65536;
}
- ngps++;
}
- } else {
- if (ngps == 0 && ground_altitude != AltosRecord.MISSING)
- pad_alt = ground_altitude;
+ tick = new_tick;
+ time = tick / 100.0;
+ time_change = time - prev_time;
}
+ }
- gps_sequence = data.gps_sequence;
+ public void set_boost_tick(int boost_tick) {
+ if (boost_tick != AltosLib.MISSING)
+ this.boost_tick = boost_tick;
+ }
- gps_waiting = MIN_PAD_SAMPLES - npad;
- if (gps_waiting < 0)
- gps_waiting = 0;
+ public String state_name() {
+ return AltosLib.state_name(state);
+ }
- gps_ready = gps_waiting == 0;
+ public void set_state(int state) {
+ if (state != AltosLib.ao_flight_invalid) {
+ this.state = state;
+ ascent = (AltosLib.ao_flight_boost <= state &&
+ state <= AltosLib.ao_flight_coast);
+ boost = (AltosLib.ao_flight_boost == state);
+ }
- ascent = (AltosLib.ao_flight_boost <= state &&
- state <= AltosLib.ao_flight_coast);
- boost = (AltosLib.ao_flight_boost == state);
+ }
- /* Only look at accelerometer data under boost */
- if (boost && acceleration != AltosRecord.MISSING && (max_acceleration == AltosRecord.MISSING || acceleration > max_acceleration))
- max_acceleration = acceleration;
- if (boost && accel_speed != AltosRecord.MISSING && accel_speed > max_accel_speed)
- max_accel_speed = accel_speed;
- if (boost && baro_speed != AltosRecord.MISSING && baro_speed > max_baro_speed)
- max_baro_speed = baro_speed;
+ public void set_device_type(int device_type) {
+ this.device_type = device_type;
+ }
- if (height != AltosRecord.MISSING && height > max_height)
- max_height = height;
- elevation = 0;
- range = -1;
- gps_height = 0;
- if (data.gps != null) {
- gps = data.gps;
- if (ngps > 0 && gps.locked) {
- double h = height;
-
- if (h == AltosRecord.MISSING) h = 0;
- from_pad = new AltosGreatCircle(pad_lat, pad_lon, 0, gps.lat, gps.lon, h);
- elevation = from_pad.elevation;
- range = from_pad.range;
- gps_height = gps.alt - pad_alt;
+ public void set_config(int major, int minor, int apogee_delay, int main_deploy, int flight_log_max) {
+ config_major = major;
+ config_minor = minor;
+ this.apogee_delay = apogee_delay;
+ this.main_deploy = main_deploy;
+ this.flight_log_max = flight_log_max;
+ }
+
+ public void set_callsign(String callsign) {
+ this.callsign = callsign;
+ }
+
+ public void set_firmware_version(String version) {
+ firmware_version = version;
+ }
+
+ public void set_flight(int flight) {
+
+ /* When the flight changes, reset the state */
+ if (flight != AltosLib.MISSING && flight != 0) {
+ if (this.flight != AltosLib.MISSING &&
+ this.flight != flight) {
+ int bt = boost_tick;
+ init();
+ boost_tick = bt;
+ }
+ this.flight = flight;
+ }
+ }
+
+ public void set_serial(int serial) {
+ /* When the serial changes, reset the state */
+ if (serial != AltosLib.MISSING) {
+ if (this.serial != AltosLib.MISSING &&
+ this.serial != serial) {
+ int bt = boost_tick;
+ init();
+ boost_tick = bt;
+ }
+ this.serial = serial;
+ }
+ }
+
+ public void set_receiver_serial(int serial) {
+ if (serial != AltosLib.MISSING)
+ receiver_serial = serial;
+ }
+
+ public int rssi() {
+ if (rssi == AltosLib.MISSING)
+ return 0;
+ return rssi;
+ }
+
+ public void set_rssi(int rssi, int status) {
+ if (rssi != AltosLib.MISSING) {
+ this.rssi = rssi;
+ this.status = status;
+ }
+ }
+
+ public void set_received_time(long ms) {
+ received_time = ms;
+ }
+
+ public void set_gps(AltosGPS gps, int sequence) {
+ if (gps != null) {
+ this.gps = gps.clone();
+ gps_sequence = sequence;
+ update_gps();
+ set |= set_gps;
+ }
+ }
+
+ public void set_imu(AltosIMU imu) {
+ if (imu != null)
+ imu = imu.clone();
+ this.imu = imu;
+ }
+
+ public void set_mag(AltosMag mag) {
+ this.mag = mag.clone();
+ }
+
+ public AltosMs5607 make_baro() {
+ if (baro == null)
+ baro = new AltosMs5607();
+ return baro;
+ }
+
+ public void set_ms5607(AltosMs5607 ms5607) {
+ baro = ms5607;
+
+ if (baro != null) {
+ set_pressure(baro.pa);
+ set_temperature(baro.cc / 100.0);
+ }
+ }
+
+ public void set_ms5607(int pres, int temp) {
+ if (baro != null) {
+ baro.set(pres, temp);
+
+ set_pressure(baro.pa);
+ set_temperature(baro.cc / 100.0);
+ }
+ }
+
+ public void make_companion (int nchannels) {
+ if (companion == null)
+ companion = new AltosCompanion(nchannels);
+ }
+
+ public void set_companion(AltosCompanion companion) {
+ this.companion = companion;
+ }
+
+ void update_accel() {
+ double ground = ground_accel;
+
+ if (ground == AltosLib.MISSING)
+ ground = ground_accel_avg;
+ if (accel == AltosLib.MISSING)
+ return;
+ if (ground == AltosLib.MISSING)
+ return;
+ if (accel_plus_g == AltosLib.MISSING)
+ return;
+ if (accel_minus_g == AltosLib.MISSING)
+ return;
+
+ double counts_per_g = (accel_minus_g - accel_plus_g) / 2.0;
+ double counts_per_mss = counts_per_g / 9.80665;
+ acceleration.set_measured((ground - accel) / counts_per_mss, time);
+ }
+
+ public void set_accel_g(double accel_plus_g, double accel_minus_g) {
+ if (accel_plus_g != AltosLib.MISSING) {
+ this.accel_plus_g = accel_plus_g;
+ this.accel_minus_g = accel_minus_g;
+ update_accel();
+ }
+ }
+
+ public void set_ground_accel(double ground_accel) {
+ if (ground_accel != AltosLib.MISSING) {
+ this.ground_accel = ground_accel;
+ update_accel();
+ }
+ }
+
+ public void set_accel(double accel) {
+ if (accel != AltosLib.MISSING) {
+ this.accel = accel;
+ if (state == AltosLib.ao_flight_pad) {
+ if (ground_accel_avg == AltosLib.MISSING)
+ ground_accel_avg = accel;
+ else
+ ground_accel_avg = (ground_accel_avg * 7 + accel) / 8;
}
}
+ update_accel();
+ }
+
+ public void set_temperature(double temperature) {
+ if (temperature != AltosLib.MISSING) {
+ this.temperature = temperature;
+ set |= set_data;
+ }
+ }
+
+ public void set_battery_voltage(double battery_voltage) {
+ if (battery_voltage != AltosLib.MISSING) {
+ this.battery_voltage = battery_voltage;
+ set |= set_data;
+ }
+ }
+
+ public void set_pyro_voltage(double pyro_voltage) {
+ if (pyro_voltage != AltosLib.MISSING) {
+ this.pyro_voltage = pyro_voltage;
+ set |= set_data;
+ }
+ }
+
+ public void set_apogee_voltage(double apogee_voltage) {
+ if (apogee_voltage != AltosLib.MISSING) {
+ this.apogee_voltage = apogee_voltage;
+ set |= set_data;
+ }
+ }
+
+ public void set_main_voltage(double main_voltage) {
+ if (main_voltage != AltosLib.MISSING) {
+ this.main_voltage = main_voltage;
+ set |= set_data;
+ }
+ }
+
+ public void set_ignitor_voltage(double[] voltage) {
+ this.ignitor_voltage = voltage;
+ }
+
+ public double time_since_boost() {
+ if (tick == AltosLib.MISSING)
+ return 0.0;
+
+ if (boost_tick == AltosLib.MISSING)
+ return tick / 100.0;
+ return (tick - boost_tick) / 100.0;
+ }
+
+ public boolean valid() {
+ return tick != AltosLib.MISSING && serial != AltosLib.MISSING;
+ }
+
+ public AltosGPS make_temp_gps(boolean sats) {
+ if (temp_gps == null) {
+ temp_gps = new AltosGPS(gps);
+ }
+ gps_pending = true;
+ if (sats) {
+ if (tick != temp_gps_sat_tick)
+ temp_gps.cc_gps_sat = null;
+ temp_gps_sat_tick = tick;
+ }
+ return temp_gps;
+ }
+
+ public void set_temp_gps() {
+ set_gps(temp_gps, gps_sequence + 1);
+ gps_pending = false;
+ temp_gps = null;
}
- public AltosState(AltosRecord cur) {
- init(cur, null);
+ public AltosState clone() {
+ AltosState s = new AltosState();
+ s.copy(this);
+ return s;
}
- public AltosState (AltosRecord cur, AltosState prev) {
- init(cur, prev);
+ public AltosState () {
+ init();
}
}
diff --git a/altoslib/AltosRecordIterable.java b/altoslib/AltosStateIterable.java
index 62dbdfe3..6d637419 100644
--- a/altoslib/AltosRecordIterable.java
+++ b/altoslib/AltosStateIterable.java
@@ -1,5 +1,5 @@
/*
- * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ * Copyright © 2013 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
@@ -15,15 +15,15 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
import java.io.*;
import java.util.*;
-public abstract class AltosRecordIterable implements Iterable<AltosRecord> {
- public abstract Iterator<AltosRecord> iterator();
- public void write_comments(PrintStream out) { }
- public boolean has_accel() { return false; }
- public boolean has_gps() { return false; }
- public boolean has_ignite() { return false; };
+public abstract class AltosStateIterable implements Iterable<AltosState> {
+
+ public void write_comments (PrintStream out) {
+ }
+
+ public abstract void write(PrintStream out);
}
diff --git a/altoslib/AltosStateUpdate.java b/altoslib/AltosStateUpdate.java
new file mode 100644
index 00000000..97a5dfe2
--- /dev/null
+++ b/altoslib/AltosStateUpdate.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright © 2013 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_2;
+
+public interface AltosStateUpdate {
+ public void update_state(AltosState state) throws InterruptedException;
+} \ No newline at end of file
diff --git a/altoslib/AltosTelemetry.java b/altoslib/AltosTelemetry.java
index e7322349..03ca9f80 100644
--- a/altoslib/AltosTelemetry.java
+++ b/altoslib/AltosTelemetry.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
import java.text.*;
@@ -23,217 +23,114 @@ import java.text.*;
* Telemetry data contents
*/
+public abstract class AltosTelemetry implements AltosStateUpdate {
-/*
- * The packet format is a simple hex dump of the raw telemetry frame.
- * It starts with 'TELEM', then contains hex digits with a checksum as the last
- * byte on the line.
- *
- * Version 4 is a replacement with consistent syntax. Each telemetry line
- * contains a sequence of space-separated names and values, the values are
- * either integers or strings. The names are all unique. All values are
- * optional
- *
- * VERSION 4 c KD7SQG n 236 f 18 r -25 s pad t 513 r_a 15756 r_b 26444 r_t 20944
- * r_v 26640 r_d 512 r_m 208 c_a 15775 c_b 26439 c_p 15749 c_m 16281 a_a 15764
- * a_s 0 a_b 26439 g_s u g_n 0 s_n 0
- *
- * VERSION 4 c KD7SQG n 19 f 0 r -23 s pad t 513 r_b 26372 r_t 21292 r_v 26788
- * r_d 136 r_m 140 c_b 26370 k_h 0 k_s 0 k_a 0
- *
- * General header fields
- *
- * Name Value
- *
- * VERSION Telemetry version number (4 or more). Must be first.
- * c Callsign (string, no spaces allowed)
- * n Flight unit serial number (integer)
- * f Flight number (integer)
- * r Packet RSSI value (integer)
- * s Flight computer state (string, no spaces allowed)
- * t Flight computer clock (integer in centiseconds)
- *
- * Version 3 is Version 2 with fixed RSSI numbers -- the radio reports
- * in 1/2dB increments while this protocol provides only integers. So,
- * the syntax didn't change just the interpretation of the RSSI
- * values.
- *
- * Version 2 of the telemetry data stream is a bit of a mess, with no
- * consistent formatting. In particular, the GPS data is formatted for
- * viewing instead of parsing. However, the key feature is that every
- * telemetry line contains all of the information necessary to
- * describe the current rocket state, including the calibration values
- * for accelerometer and barometer.
- *
- * GPS unlocked:
- *
- * VERSION 2 CALL KB0G SERIAL 51 FLIGHT 2 RSSI -68 STATUS ff STATE pad 1001 \
- * a: 16032 p: 21232 t: 20284 v: 25160 d: 204 m: 204 fa: 16038 ga: 16032 fv: 0 \
- * fp: 21232 gp: 21230 a+: 16049 a-: 16304 GPS 0 sat unlocked SAT 1 15 30
- *
- * GPS locked:
- *
- * VERSION 2 CALL KB0G SERIAL 51 FLIGHT 2 RSSI -71 STATUS ff STATE pad 2504 \
- * a: 16028 p: 21220 t: 20360 v: 25004 d: 208 m: 200 fa: 16031 ga: 16032 fv: 330 \
- * fp: 21231 gp: 21230 a+: 16049 a-: 16304 \
- * GPS 9 sat 2010-02-13 17:16:51 35°20.0803'N 106°45.2235'W 1790m \
- * 0.00m/s(H) 0° 0.00m/s(V) 1.0(hdop) 0(herr) 0(verr) \
- * SAT 10 29 30 24 28 5 25 21 20 15 33 1 23 30 24 18 26 10 29 2 26
- *
- */
+ /* All telemetry packets have these fields */
+ public int tick;
+ public int serial;
+ public int rssi;
+ public int status;
+
+ /* Mark when we received the packet */
+ long received_time;
+
+ static boolean cksum(int[] bytes) {
+ int sum = 0x5a;
+ for (int i = 1; i < bytes.length - 1; i++)
+ sum += bytes[i];
+ sum &= 0xff;
+ return sum == bytes[bytes.length - 1];
+ }
+
+ public void update_state(AltosState state) {
+ if (state.state == AltosLib.ao_flight_invalid)
+ state.set_state(AltosLib.ao_flight_startup);
+ state.set_serial(serial);
+ state.set_tick(tick);
+ state.set_rssi(rssi, status);
+ state.set_received_time(received_time);
+ }
+
+ final static int PKT_APPEND_STATUS_1_CRC_OK = (1 << 7);
+ final static int PKT_APPEND_STATUS_1_LQI_MASK = (0x7f);
+ final static int PKT_APPEND_STATUS_1_LQI_SHIFT = 0;
+
+ final static int packet_type_TM_sensor = 0x01;
+ final static int packet_type_Tm_sensor = 0x02;
+ final static int packet_type_Tn_sensor = 0x03;
+ final static int packet_type_configuration = 0x04;
+ final static int packet_type_location = 0x05;
+ final static int packet_type_satellite = 0x06;
+ final static int packet_type_companion = 0x07;
+ final static int packet_type_mega_sensor = 0x08;
+ final static int packet_type_mega_data = 0x09;
+ final static int packet_type_metrum_sensor = 0x0a;
+ final static int packet_type_metrum_data = 0x0b;
+ final static int packet_type_mini = 0x10;
+
+ static AltosTelemetry parse_hex(String hex) throws ParseException, AltosCRCException {
+ AltosTelemetry telem = null;
+
+ int[] bytes;
+ try {
+ bytes = AltosLib.hexbytes(hex);
+ } catch (NumberFormatException ne) {
+ throw new ParseException(ne.getMessage(), 0);
+ }
+
+ /* one for length, one for checksum */
+ if (bytes[0] != bytes.length - 2)
+ throw new ParseException(String.format("invalid length %d != %d\n",
+ bytes[0],
+ bytes.length - 2), 0);
+ if (!cksum(bytes))
+ throw new ParseException(String.format("invalid line \"%s\"", hex), 0);
+
+ int rssi = AltosLib.int8(bytes, bytes.length - 3) / 2 - 74;
+ int status = AltosLib.uint8(bytes, bytes.length - 2);
+
+ if ((status & PKT_APPEND_STATUS_1_CRC_OK) == 0)
+ throw new AltosCRCException(rssi);
+
+ /* length, data ..., rssi, status, checksum -- 4 bytes extra */
+ switch (bytes.length) {
+ case AltosLib.ao_telemetry_standard_len + 4:
+ telem = AltosTelemetryStandard.parse_hex(bytes);
+ break;
+ case AltosLib.ao_telemetry_0_9_len + 4:
+ telem = new AltosTelemetryLegacy(bytes);
+ break;
+ case AltosLib.ao_telemetry_0_8_len + 4:
+ telem = new AltosTelemetryLegacy(bytes);
+ break;
+ default:
+ throw new ParseException(String.format("Invalid packet length %d", bytes.length), 0);
+ }
+ if (telem != null) {
+ telem.received_time = System.currentTimeMillis();
+ telem.rssi = rssi;
+ telem.status = status;
+ }
+ return telem;
+ }
+
+ public static AltosTelemetry parse(String line) throws ParseException, AltosCRCException {
+ String[] word = line.split("\\s+");
+ int i =0;
+
+ if (word[i].equals("CRC") && word[i+1].equals("INVALID")) {
+ i += 2;
+ AltosParse.word(word[i++], "RSSI");
+ throw new AltosCRCException(AltosParse.parse_int(word[i++]));
+ }
+
+ AltosTelemetry telem;
-public abstract class AltosTelemetry extends AltosRecord {
-
- /*
- * General header fields
- *
- * Name Value
- *
- * VERSION Telemetry version number (4 or more). Must be first.
- * c Callsign (string, no spaces allowed)
- * n Flight unit serial number (integer)
- * f Flight number (integer)
- * r Packet RSSI value (integer)
- * s Flight computer state (string, no spaces allowed)
- * t Flight computer clock (integer in centiseconds)
- */
-
- final static String AO_TELEM_VERSION = "VERSION";
- final static String AO_TELEM_CALL = "c";
- final static String AO_TELEM_SERIAL = "n";
- final static String AO_TELEM_FLIGHT = "f";
- final static String AO_TELEM_RSSI = "r";
- final static String AO_TELEM_STATE = "s";
- final static String AO_TELEM_TICK = "t";
-
- /*
- * Raw sensor values
- *
- * Name Value
- * r_a Accelerometer reading (integer)
- * r_b Barometer reading (integer)
- * r_t Thermometer reading (integer)
- * r_v Battery reading (integer)
- * r_d Drogue continuity (integer)
- * r_m Main continuity (integer)
- */
-
- final static String AO_TELEM_RAW_ACCEL = "r_a";
- final static String AO_TELEM_RAW_BARO = "r_b";
- final static String AO_TELEM_RAW_THERMO = "r_t";
- final static String AO_TELEM_RAW_BATT = "r_v";
- final static String AO_TELEM_RAW_DROGUE = "r_d";
- final static String AO_TELEM_RAW_MAIN = "r_m";
-
- /*
- * Sensor calibration values
- *
- * Name Value
- * c_a Ground accelerometer reading (integer)
- * c_b Ground barometer reading (integer)
- * c_p Accelerometer reading for +1g
- * c_m Accelerometer reading for -1g
- */
-
- final static String AO_TELEM_CAL_ACCEL_GROUND = "c_a";
- final static String AO_TELEM_CAL_BARO_GROUND = "c_b";
- final static String AO_TELEM_CAL_ACCEL_PLUS = "c_p";
- final static String AO_TELEM_CAL_ACCEL_MINUS = "c_m";
-
- /*
- * Kalman state values
- *
- * Name Value
- * k_h Height above pad (integer, meters)
- * k_s Vertical speeed (integer, m/s * 16)
- * k_a Vertical acceleration (integer, m/s² * 16)
- */
-
- final static String AO_TELEM_KALMAN_HEIGHT = "k_h";
- final static String AO_TELEM_KALMAN_SPEED = "k_s";
- final static String AO_TELEM_KALMAN_ACCEL = "k_a";
-
- /*
- * Ad-hoc flight values
- *
- * Name Value
- * a_a Acceleration (integer, sensor units)
- * a_s Speed (integer, integrated acceleration value)
- * a_b Barometer reading (integer, sensor units)
- */
-
- final static String AO_TELEM_ADHOC_ACCEL = "a_a";
- final static String AO_TELEM_ADHOC_SPEED = "a_s";
- final static String AO_TELEM_ADHOC_BARO = "a_b";
-
- /*
- * GPS values
- *
- * Name Value
- * g_s GPS state (string):
- * l locked
- * u unlocked
- * e error (missing or broken)
- * g_n Number of sats used in solution
- * g_ns Latitude (degrees * 10e7)
- * g_ew Longitude (degrees * 10e7)
- * g_a Altitude (integer meters)
- * g_Y GPS year (integer)
- * g_M GPS month (integer - 1-12)
- * g_D GPS day (integer - 1-31)
- * g_h GPS hour (integer - 0-23)
- * g_m GPS minute (integer - 0-59)
- * g_s GPS second (integer - 0-59)
- * g_v GPS vertical speed (integer, cm/sec)
- * g_s GPS horizontal speed (integer, cm/sec)
- * g_c GPS course (integer, 0-359)
- * g_hd GPS hdop (integer * 10)
- * g_vd GPS vdop (integer * 10)
- * g_he GPS h error (integer)
- * g_ve GPS v error (integer)
- */
-
- final static String AO_TELEM_GPS_STATE = "g";
- final static String AO_TELEM_GPS_STATE_LOCKED = "l";
- final static String AO_TELEM_GPS_STATE_UNLOCKED = "u";
- final static String AO_TELEM_GPS_STATE_ERROR = "e";
- final static String AO_TELEM_GPS_NUM_SAT = "g_n";
- final static String AO_TELEM_GPS_LATITUDE = "g_ns";
- final static String AO_TELEM_GPS_LONGITUDE = "g_ew";
- final static String AO_TELEM_GPS_ALTITUDE = "g_a";
- final static String AO_TELEM_GPS_YEAR = "g_Y";
- final static String AO_TELEM_GPS_MONTH = "g_M";
- final static String AO_TELEM_GPS_DAY = "g_D";
- final static String AO_TELEM_GPS_HOUR = "g_h";
- final static String AO_TELEM_GPS_MINUTE = "g_m";
- final static String AO_TELEM_GPS_SECOND = "g_s";
- final static String AO_TELEM_GPS_VERTICAL_SPEED = "g_v";
- final static String AO_TELEM_GPS_HORIZONTAL_SPEED = "g_g";
- final static String AO_TELEM_GPS_COURSE = "g_c";
- final static String AO_TELEM_GPS_HDOP = "g_hd";
- final static String AO_TELEM_GPS_VDOP = "g_vd";
- final static String AO_TELEM_GPS_HERROR = "g_he";
- final static String AO_TELEM_GPS_VERROR = "g_ve";
-
- /*
- * GPS satellite values
- *
- * Name Value
- * s_n Number of satellites reported (integer)
- * s_v0 Space vehicle ID (integer) for report 0
- * s_c0 C/N0 number (integer) for report 0
- * s_v1 Space vehicle ID (integer) for report 1
- * s_c1 C/N0 number (integer) for report 1
- * ...
- */
-
- final static String AO_TELEM_SAT_NUM = "s_n";
- final static String AO_TELEM_SAT_SVID = "s_v";
- final static String AO_TELEM_SAT_C_N_0 = "s_c";
-
- static public AltosRecord parse(String line, AltosRecord previous) throws ParseException, AltosCRCException {
- AltosTelemetryRecord r = AltosTelemetryRecord.parse(line);
-
- return r.update_state(previous);
+ if (word[i].equals("TELEM")) {
+ telem = parse_hex(word[i+1]);
+ } else {
+ telem = new AltosTelemetryLegacy(line);
+ }
+ return telem;
}
}
diff --git a/altoslib/AltosTelemetryRecordConfiguration.java b/altoslib/AltosTelemetryConfiguration.java
index 47fc3488..e5d444dd 100644
--- a/altoslib/AltosTelemetryRecordConfiguration.java
+++ b/altoslib/AltosTelemetryConfiguration.java
@@ -15,10 +15,10 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
-public class AltosTelemetryRecordConfiguration extends AltosTelemetryRecordRaw {
+public class AltosTelemetryConfiguration extends AltosTelemetryStandard {
int device_type;
int flight;
int config_major;
@@ -29,8 +29,8 @@ public class AltosTelemetryRecordConfiguration extends AltosTelemetryRecordRaw {
String callsign;
String version;
- public AltosTelemetryRecordConfiguration(int[] in_bytes, int rssi) {
- super(in_bytes, rssi);
+ public AltosTelemetryConfiguration(int[] bytes) {
+ super(bytes);
device_type = uint8(5);
flight = uint16(6);
@@ -43,22 +43,13 @@ public class AltosTelemetryRecordConfiguration extends AltosTelemetryRecordRaw {
version = string(24, 8);
}
- public AltosRecord update_state(AltosRecord previous) {
- AltosRecord next = super.update_state(previous);
+ public void update_state(AltosState state) {
+ super.update_state(state);
+ state.set_device_type(device_type);
+ state.set_flight(flight);
+ state.set_config(config_major, config_minor, apogee_delay, main_deploy, flight_log_max);
- next.device_type = device_type;
- next.flight = flight;
- next.config_major = config_major;
- next.config_minor = config_minor;
- next.apogee_delay = apogee_delay;
- next.main_deploy = main_deploy;
- next.flight_log_max = flight_log_max;
-
- next.callsign = callsign;
- next.firmware_version = version;
-
- next.seen |= AltosRecord.seen_deploy | AltosRecord.seen_flight;
-
- return next;
+ state.set_callsign(callsign);
+ state.set_firmware_version(version);
}
}
diff --git a/altoslib/AltosTelemetryFile.java b/altoslib/AltosTelemetryFile.java
new file mode 100644
index 00000000..7566d946
--- /dev/null
+++ b/altoslib/AltosTelemetryFile.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright © 2013 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_2;
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
+class AltosTelemetryIterator implements Iterator<AltosState> {
+ AltosState state;
+ Iterator<AltosTelemetry> telems;
+ AltosTelemetry next;
+ boolean seen;
+
+ public boolean hasNext() {
+ return !seen || telems.hasNext();
+ }
+
+ public AltosState next() {
+ if (seen) {
+ AltosState n = state.clone();
+ AltosTelemetry t = telems.next();
+
+ t.update_state(n);
+ state = n;
+ }
+ seen = true;
+ return state;
+ }
+
+ public void remove () {
+ }
+
+ public AltosTelemetryIterator(AltosState start, Iterator<AltosTelemetry> telems) {
+ this.state = start;
+ this.telems = telems;
+ this.seen = false;
+ }
+}
+
+public class AltosTelemetryFile extends AltosStateIterable {
+
+ AltosTelemetryIterable telems;
+ AltosState start;
+
+ public void write_comments(PrintStream out) {
+ }
+
+ public void write(PrintStream out) {
+
+ }
+
+ public AltosTelemetryFile(FileInputStream input) {
+ telems = new AltosTelemetryIterable(input);
+ start = new AltosState();
+
+ /* Find boost tick */
+ AltosState state = start.clone();
+
+ for (AltosTelemetry telem : telems) {
+ telem.update_state(state);
+ state.finish_update();
+ if (state.state != AltosLib.ao_flight_invalid && state.state >= AltosLib.ao_flight_boost) {
+ start.set_boost_tick(state.tick);
+ break;
+ }
+ }
+ }
+
+ public Iterator<AltosState> iterator() {
+ AltosState state = start.clone();
+ Iterator<AltosTelemetry> i = telems.iterator();
+
+ while (i.hasNext() && !state.valid()) {
+ AltosTelemetry t = i.next();
+ t.update_state(state);
+ state.finish_update();
+ }
+ return new AltosTelemetryIterator(state, i);
+ }
+} \ No newline at end of file
diff --git a/altoslib/AltosTelemetryIterable.java b/altoslib/AltosTelemetryIterable.java
index 57033638..bf30b4c8 100644
--- a/altoslib/AltosTelemetryIterable.java
+++ b/altoslib/AltosTelemetryIterable.java
@@ -15,33 +15,74 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
import java.io.*;
import java.util.*;
import java.text.*;
-public class AltosTelemetryIterable extends AltosRecordIterable {
- TreeSet<AltosRecord> records;
+class AltosTelemetryOrdered implements Comparable<AltosTelemetryOrdered> {
+ AltosTelemetry telem;
+ int index;
+ int tick;
- public Iterator<AltosRecord> iterator () {
- return records.iterator();
+ public int compareTo(AltosTelemetryOrdered o) {
+ int tick_diff = tick - o.tick;
+
+ if (tick_diff != 0)
+ return tick_diff;
+ return index - o.index;
}
- boolean has_gps = false;
- boolean has_accel = false;
- boolean has_ignite = false;
- public boolean has_gps() { return has_gps; }
- public boolean has_accel() { return has_accel; }
- public boolean has_ignite() { return has_ignite; };
+ AltosTelemetryOrdered (AltosTelemetry telem, int index, int tick) {
+ this.telem = telem;
+ this.index = index;
+ this.tick = tick;
+ }
+}
- public AltosTelemetryIterable (FileInputStream input) {
- boolean saw_boost = false;
- int current_tick = 0;
- int boost_tick = 0;
+class AltosTelemetryOrderedIterator implements Iterator<AltosTelemetry> {
+ Iterator<AltosTelemetryOrdered> iterator;
+
+ public AltosTelemetryOrderedIterator(TreeSet<AltosTelemetryOrdered> telems) {
+ iterator = telems.iterator();
+ }
+
+ public boolean hasNext() {
+ return iterator.hasNext();
+ }
- AltosRecord previous = null;
- records = new TreeSet<AltosRecord> ();
+ public AltosTelemetry next() {
+ return iterator.next().telem;
+ }
+
+ public void remove () {
+ }
+}
+
+public class AltosTelemetryIterable implements Iterable<AltosTelemetry> {
+ TreeSet<AltosTelemetryOrdered> telems;
+ int tick;
+ int index;
+
+ public void add (AltosTelemetry telem) {
+ int t = telem.tick;
+ if (!telems.isEmpty()) {
+ while (t < tick - 1000)
+ t += 65536;
+ }
+ tick = t;
+ telems.add(new AltosTelemetryOrdered(telem, index++, tick));
+ }
+
+ public Iterator<AltosTelemetry> iterator () {
+ return new AltosTelemetryOrderedIterator(telems);
+ }
+
+ public AltosTelemetryIterable (FileInputStream input) {
+ telems = new TreeSet<AltosTelemetryOrdered> ();
+ tick = 0;
+ index = 0;
try {
for (;;) {
@@ -50,32 +91,10 @@ public class AltosTelemetryIterable extends AltosRecordIterable {
break;
}
try {
- AltosRecord record = AltosTelemetry.parse(line, previous);
- if (record == null)
+ AltosTelemetry telem = AltosTelemetry.parse(line);
+ if (telem == null)
break;
- if (records.isEmpty()) {
- current_tick = record.tick;
- } else {
- int tick = record.tick;
- while (tick < current_tick - 0x1000)
- tick += 0x10000;
- current_tick = tick;
- record.tick = current_tick;
- }
- if (!saw_boost && record.state >= AltosLib.ao_flight_boost)
- {
- saw_boost = true;
- boost_tick = record.tick;
- }
- if (record.acceleration() != AltosRecord.MISSING)
- has_accel = true;
- if (record.gps != null)
- has_gps = true;
- if (record.main_voltage() != AltosRecord.MISSING)
- has_ignite = true;
- if (previous != null && previous.tick != record.tick)
- records.add(previous);
- previous = record;
+ add(telem);
} catch (ParseException pe) {
System.out.printf("parse exception %s\n", pe.getMessage());
} catch (AltosCRCException ce) {
@@ -84,26 +103,5 @@ public class AltosTelemetryIterable extends AltosRecordIterable {
} catch (IOException io) {
System.out.printf("io exception\n");
}
-
- if (previous != null)
- records.add(previous);
-
- /* Adjust all tick counts to match expected eeprom values,
- * which starts with a 16-bit tick count 16 samples before boost
- */
-
- int tick_adjust = (boost_tick - 16) & 0xffff0000;
- for (AltosRecord r : this)
- r.tick -= tick_adjust;
- boost_tick -= tick_adjust;
-
- /* adjust all tick counts to be relative to boost time */
- for (AltosRecord r : this)
- r.time = (r.tick - boost_tick) / 100.0;
-
- try {
- input.close();
- } catch (IOException ie) {
- }
}
}
diff --git a/altoslib/AltosTelemetryRecordLegacy.java b/altoslib/AltosTelemetryLegacy.java
index f2d3f868..132b9e80 100644
--- a/altoslib/AltosTelemetryRecordLegacy.java
+++ b/altoslib/AltosTelemetryLegacy.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
import java.text.*;
@@ -82,7 +82,7 @@ import java.text.*;
*
*/
-public class AltosTelemetryRecordLegacy extends AltosTelemetryRecord {
+public class AltosTelemetryLegacy extends AltosTelemetry {
/*
* General header fields
*
@@ -230,156 +230,184 @@ public class AltosTelemetryRecordLegacy extends AltosTelemetryRecord {
final static String AO_TELEM_SAT_SVID = "s_v";
final static String AO_TELEM_SAT_C_N_0 = "s_c";
- AltosRecordTM record;
+ public int version;
+ public String callsign;
+ public int flight;
+ public int state;
+
+ public AltosGPS gps;
+ public int gps_sequence;
+
+ /* Telemetry sources have these values recorded from the flight computer */
+ public double kalman_height;
+ public double kalman_speed;
+ public double kalman_acceleration;
+
+ /* Sensor values */
+ public int accel;
+ public int pres;
+ public int temp;
+ public int batt;
+ public int apogee;
+ public int main;
+
+ public int ground_accel;
+ public int ground_pres;
+ public int accel_plus_g;
+ public int accel_minus_g;
+
+ public int flight_accel;
+ public int flight_vel;
+ public int flight_pres;
private void parse_v4(String[] words, int i) throws ParseException {
AltosTelemetryMap map = new AltosTelemetryMap(words, i);
- record.callsign = map.get_string(AO_TELEM_CALL, "N0CALL");
- record.serial = map.get_int(AO_TELEM_SERIAL, AltosRecord.MISSING);
- record.flight = map.get_int(AO_TELEM_FLIGHT, AltosRecord.MISSING);
- record.rssi = map.get_int(AO_TELEM_RSSI, AltosRecord.MISSING);
- record.state = AltosLib.state(map.get_string(AO_TELEM_STATE, "invalid"));
- record.tick = map.get_int(AO_TELEM_TICK, 0);
+ callsign = map.get_string(AO_TELEM_CALL, "N0CALL");
+ serial = map.get_int(AO_TELEM_SERIAL, AltosLib.MISSING);
+ flight = map.get_int(AO_TELEM_FLIGHT, AltosLib.MISSING);
+ rssi = map.get_int(AO_TELEM_RSSI, AltosLib.MISSING);
+ state = AltosLib.state(map.get_string(AO_TELEM_STATE, "invalid"));
+ tick = map.get_int(AO_TELEM_TICK, 0);
/* raw sensor values */
- record.accel = map.get_int(AO_TELEM_RAW_ACCEL, AltosRecord.MISSING);
- record.pres = map.get_int(AO_TELEM_RAW_BARO, AltosRecord.MISSING);
- record.temp = map.get_int(AO_TELEM_RAW_THERMO, AltosRecord.MISSING);
- record.batt = map.get_int(AO_TELEM_RAW_BATT, AltosRecord.MISSING);
- record.drogue = map.get_int(AO_TELEM_RAW_DROGUE, AltosRecord.MISSING);
- record.main = map.get_int(AO_TELEM_RAW_MAIN, AltosRecord.MISSING);
+ accel = map.get_int(AO_TELEM_RAW_ACCEL, AltosLib.MISSING);
+ pres = map.get_int(AO_TELEM_RAW_BARO, AltosLib.MISSING);
+ temp = map.get_int(AO_TELEM_RAW_THERMO, AltosLib.MISSING);
+ batt = map.get_int(AO_TELEM_RAW_BATT, AltosLib.MISSING);
+ apogee = map.get_int(AO_TELEM_RAW_DROGUE, AltosLib.MISSING);
+ main = map.get_int(AO_TELEM_RAW_MAIN, AltosLib.MISSING);
/* sensor calibration information */
- record.ground_accel = map.get_int(AO_TELEM_CAL_ACCEL_GROUND, AltosRecord.MISSING);
- record.ground_pres = map.get_int(AO_TELEM_CAL_BARO_GROUND, AltosRecord.MISSING);
- record.accel_plus_g = map.get_int(AO_TELEM_CAL_ACCEL_PLUS, AltosRecord.MISSING);
- record.accel_minus_g = map.get_int(AO_TELEM_CAL_ACCEL_MINUS, AltosRecord.MISSING);
+ ground_accel = map.get_int(AO_TELEM_CAL_ACCEL_GROUND, AltosLib.MISSING);
+ ground_pres = map.get_int(AO_TELEM_CAL_BARO_GROUND, AltosLib.MISSING);
+ accel_plus_g = map.get_int(AO_TELEM_CAL_ACCEL_PLUS, AltosLib.MISSING);
+ accel_minus_g = map.get_int(AO_TELEM_CAL_ACCEL_MINUS, AltosLib.MISSING);
/* flight computer values */
- 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);
+ kalman_acceleration = map.get_double(AO_TELEM_KALMAN_ACCEL, AltosLib.MISSING, 1/16.0);
+ kalman_speed = map.get_double(AO_TELEM_KALMAN_SPEED, AltosLib.MISSING, 1/16.0);
+ kalman_height = map.get_int(AO_TELEM_KALMAN_HEIGHT, AltosLib.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);
- record.flight_pres = map.get_int(AO_TELEM_ADHOC_BARO, AltosRecord.MISSING);
+ flight_accel = map.get_int(AO_TELEM_ADHOC_ACCEL, AltosLib.MISSING);
+ flight_vel = map.get_int(AO_TELEM_ADHOC_SPEED, AltosLib.MISSING);
+ flight_pres = map.get_int(AO_TELEM_ADHOC_BARO, AltosLib.MISSING);
- if (map.has(AO_TELEM_GPS_STATE)) {
- record.gps = new AltosGPS(map);
- record.gps_sequence++;
- }
+ if (map.has(AO_TELEM_GPS_STATE))
+ gps = new AltosGPS(map);
else
- record.gps = null;
+ gps = null;
}
private void parse_legacy(String[] words, int i) throws ParseException {
AltosParse.word (words[i++], "CALL");
- record.callsign = words[i++];
+ callsign = words[i++];
AltosParse.word (words[i++], "SERIAL");
- record.serial = AltosParse.parse_int(words[i++]);
+ serial = AltosParse.parse_int(words[i++]);
- if (record.version >= 2) {
+ if (version >= 2) {
AltosParse.word (words[i++], "FLIGHT");
- record.flight = AltosParse.parse_int(words[i++]);
+ flight = AltosParse.parse_int(words[i++]);
} else
- record.flight = 0;
+ flight = 0;
AltosParse.word(words[i++], "RSSI");
- record.rssi = AltosParse.parse_int(words[i++]);
+ rssi = AltosParse.parse_int(words[i++]);
/* Older telemetry data had mis-computed RSSI value */
- if (record.version <= 2)
- record.rssi = (record.rssi + 74) / 2 - 74;
+ if (version <= 2)
+ rssi = (rssi + 74) / 2 - 74;
AltosParse.word(words[i++], "STATUS");
- record.status = AltosParse.parse_hex(words[i++]);
+ status = AltosParse.parse_hex(words[i++]);
AltosParse.word(words[i++], "STATE");
- record.state = AltosLib.state(words[i++]);
+ state = AltosLib.state(words[i++]);
- record.tick = AltosParse.parse_int(words[i++]);
+ tick = AltosParse.parse_int(words[i++]);
AltosParse.word(words[i++], "a:");
- record.accel = AltosParse.parse_int(words[i++]);
+ accel = AltosParse.parse_int(words[i++]);
AltosParse.word(words[i++], "p:");
- record.pres = AltosParse.parse_int(words[i++]);
+ pres = AltosParse.parse_int(words[i++]);
AltosParse.word(words[i++], "t:");
- record.temp = AltosParse.parse_int(words[i++]);
+ temp = AltosParse.parse_int(words[i++]);
AltosParse.word(words[i++], "v:");
- record.batt = AltosParse.parse_int(words[i++]);
+ batt = AltosParse.parse_int(words[i++]);
AltosParse.word(words[i++], "d:");
- record.drogue = AltosParse.parse_int(words[i++]);
+ apogee = AltosParse.parse_int(words[i++]);
AltosParse.word(words[i++], "m:");
- record.main = AltosParse.parse_int(words[i++]);
+ main = AltosParse.parse_int(words[i++]);
AltosParse.word(words[i++], "fa:");
- record.flight_accel = AltosParse.parse_int(words[i++]);
+ flight_accel = AltosParse.parse_int(words[i++]);
AltosParse.word(words[i++], "ga:");
- record.ground_accel = AltosParse.parse_int(words[i++]);
+ ground_accel = AltosParse.parse_int(words[i++]);
AltosParse.word(words[i++], "fv:");
- record.flight_vel = AltosParse.parse_int(words[i++]);
+ flight_vel = AltosParse.parse_int(words[i++]);
AltosParse.word(words[i++], "fp:");
- record.flight_pres = AltosParse.parse_int(words[i++]);
+ flight_pres = AltosParse.parse_int(words[i++]);
/* Old TeleDongle code with kalman-reporting TeleMetrum code */
- if ((record.flight_vel & 0xffff0000) == 0x80000000) {
- 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;
+ if ((flight_vel & 0xffff0000) == 0x80000000) {
+ kalman_speed = ((short) flight_vel) / 16.0;
+ kalman_acceleration = flight_accel / 16.0;
+ kalman_height = flight_pres;
+ flight_vel = AltosLib.MISSING;
+ flight_pres = AltosLib.MISSING;
+ flight_accel = AltosLib.MISSING;
+ } else {
+ kalman_speed = AltosLib.MISSING;
+ kalman_acceleration = AltosLib.MISSING;
+ kalman_height = AltosLib.MISSING;
}
AltosParse.word(words[i++], "gp:");
- record.ground_pres = AltosParse.parse_int(words[i++]);
+ ground_pres = AltosParse.parse_int(words[i++]);
- if (record.version >= 1) {
+ if (version >= 1) {
AltosParse.word(words[i++], "a+:");
- record.accel_plus_g = AltosParse.parse_int(words[i++]);
+ accel_plus_g = AltosParse.parse_int(words[i++]);
AltosParse.word(words[i++], "a-:");
- record.accel_minus_g = AltosParse.parse_int(words[i++]);
+ accel_minus_g = AltosParse.parse_int(words[i++]);
} else {
- record.accel_plus_g = record.ground_accel;
- record.accel_minus_g = record.ground_accel + 530;
+ accel_plus_g = ground_accel;
+ accel_minus_g = ground_accel + 530;
}
- record.gps = new AltosGPS(words, i, record.version);
- record.gps_sequence++;
+ gps = new AltosGPS(words, i, version);
+ gps_sequence++;
}
- public AltosTelemetryRecordLegacy(String line) throws ParseException, AltosCRCException {
+ public AltosTelemetryLegacy(String line) throws ParseException, AltosCRCException {
String[] words = line.split("\\s+");
int i = 0;
- record = new AltosRecordTM();
-
if (words[i].equals("CRC") && words[i+1].equals("INVALID")) {
i += 2;
AltosParse.word(words[i++], "RSSI");
- record.rssi = AltosParse.parse_int(words[i++]);
- throw new AltosCRCException(record.rssi);
+ rssi = AltosParse.parse_int(words[i++]);
+ throw new AltosCRCException(rssi);
}
if (words[i].equals("CALL")) {
- record.version = 0;
+ version = 0;
} else {
AltosParse.word (words[i++], "VERSION");
- record.version = AltosParse.parse_int(words[i++]);
+ version = AltosParse.parse_int(words[i++]);
}
- if (record.version < 4)
+ if (version < 4)
parse_legacy(words, i);
else
parse_v4(words, i);
@@ -421,75 +449,68 @@ public class AltosTelemetryRecordLegacy extends AltosTelemetryRecord {
static final int AO_GPS_DATE_VALID = (1 << 6);
static final int AO_GPS_COURSE_VALID = (1 << 7);
- public AltosTelemetryRecordLegacy(int[] in_bytes, int in_rssi, int in_status) {
- record = new AltosRecordTM();
-
+ public AltosTelemetryLegacy(int[] in_bytes) {
bytes = in_bytes;
- record.version = 4;
+ version = 4;
adjust = 0;
if (bytes.length == AltosLib.ao_telemetry_0_8_len + 4) {
- record.serial = uint8(0);
+ serial = uint8(0);
adjust = -1;
} else
- record.serial = uint16(0);
-
- record.seen = AltosRecord.seen_flight | AltosRecord.seen_sensor | AltosRecord.seen_temp_volt | AltosRecord.seen_deploy;
-
- record.callsign = string(62, 8);
- record.flight = uint16(2);
- record.rssi = in_rssi;
- record.status = in_status;
- record.state = uint8(4);
- record.tick = uint16(21);
- record.accel = int16(23);
- record.pres = int16(25);
- record.temp = int16(27);
- record.batt = int16(29);
- record.drogue = int16(31);
- record.main = int16(33);
+ serial = uint16(0);
+
+ callsign = string(62, 8);
+ flight = uint16(2);
+ state = uint8(4);
+ tick = uint16(21);
+ accel = int16(23);
+ pres = int16(25);
+ temp = int16(27);
+ batt = int16(29);
+ apogee = int16(31);
+ main = int16(33);
- record.ground_accel = int16(7);
- record.ground_pres = int16(15);
- record.accel_plus_g = int16(17);
- record.accel_minus_g = int16(19);
+ ground_accel = int16(7);
+ ground_pres = int16(15);
+ accel_plus_g = int16(17);
+ accel_minus_g = int16(19);
if (uint16(11) == 0x8000) {
- 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;
+ kalman_acceleration = int16(5);
+ kalman_speed = int16(9);
+ kalman_height = int16(13);
+ flight_accel = AltosLib.MISSING;
+ flight_vel = AltosLib.MISSING;
+ flight_pres = AltosLib.MISSING;
} else {
- record.flight_accel = int16(5);
- record.flight_vel = uint32(9);
- record.flight_pres = int16(13);
- record.kalman_acceleration = AltosRecord.MISSING;
- record.kalman_speed = AltosRecord.MISSING;
- record.kalman_height = AltosRecord.MISSING;
+ flight_accel = int16(5);
+ flight_vel = uint32(9);
+ flight_pres = int16(13);
+ kalman_acceleration = AltosLib.MISSING;
+ kalman_speed = AltosLib.MISSING;
+ kalman_height = AltosLib.MISSING;
}
- record.gps = null;
+ gps = null;
int gps_flags = uint8(41);
if ((gps_flags & (AO_GPS_VALID|AO_GPS_RUNNING)) != 0) {
- record.gps = new AltosGPS();
- record.gps_sequence++;
-
- record.seen |= AltosRecord.seen_gps_time | AltosRecord.seen_gps_lat | AltosRecord.seen_gps_lon;
- record.gps.nsat = (gps_flags & AO_GPS_NUM_SAT_MASK);
- record.gps.locked = (gps_flags & AO_GPS_VALID) != 0;
- record.gps.connected = true;
- record.gps.lat = uint32(42) / 1.0e7;
- record.gps.lon = uint32(46) / 1.0e7;
- record.gps.alt = int16(50);
- record.gps.ground_speed = uint16(52) / 100.0;
- record.gps.course = uint8(54) * 2;
- record.gps.hdop = uint8(55) / 5.0;
- record.gps.h_error = uint16(58);
- record.gps.v_error = uint16(60);
+ gps = new AltosGPS();
+ gps_sequence++;
+
+ gps.nsat = (gps_flags & AO_GPS_NUM_SAT_MASK);
+ gps.locked = (gps_flags & AO_GPS_VALID) != 0;
+ gps.connected = true;
+ gps.lat = uint32(42) / 1.0e7;
+ gps.lon = uint32(46) / 1.0e7;
+ gps.alt = int16(50);
+ gps.ground_speed = uint16(52) / 100.0;
+ gps.course = uint8(54) * 2;
+ gps.hdop = uint8(55) / 5.0;
+ gps.h_error = uint16(58);
+ gps.v_error = uint16(60);
int n_tracking_reported = uint8(70);
if (n_tracking_reported > 12)
@@ -500,22 +521,36 @@ public class AltosTelemetryRecordLegacy extends AltosTelemetryRecord {
n_tracking_actual++;
}
if (n_tracking_actual > 0) {
- record.gps.cc_gps_sat = new AltosGPSSat[n_tracking_actual];
+ gps.cc_gps_sat = new AltosGPSSat[n_tracking_actual];
n_tracking_actual = 0;
for (int i = 0; i < n_tracking_reported; i++) {
int svid = uint8(71 + i*2);
int c_n0 = uint8(72 + i*2);
if (svid != 0)
- record.gps.cc_gps_sat[n_tracking_actual++] = new AltosGPSSat(svid, c_n0);
+ gps.cc_gps_sat[n_tracking_actual++] = new AltosGPSSat(svid, c_n0);
}
}
}
-
- record.time = 0.0;
}
- public AltosRecord update_state(AltosRecord previous) {
- return record;
+ public void update_state(AltosState state) {
+ state.set_tick(tick);
+ state.set_state(this.state);
+ state.set_flight(flight);
+ state.set_serial(serial);
+ state.set_rssi(rssi, status);
+
+ state.set_pressure(AltosConvert.barometer_to_pressure(pres));
+ state.set_accel_g(accel_plus_g, accel_minus_g);
+ state.set_accel(accel);
+ if (kalman_height != AltosLib.MISSING)
+ state.set_kalman(kalman_height, kalman_speed, kalman_acceleration);
+ state.set_temperature(AltosConvert.thermometer_to_temperature(temp));
+ state.set_battery_voltage(AltosConvert.cc_battery_to_voltage(batt));
+ state.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(apogee));
+ state.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(main));
+ if (gps != null)
+ state.set_gps(gps, gps_sequence);
}
}
diff --git a/altoslib/AltosTelemetryRecordLocation.java b/altoslib/AltosTelemetryLocation.java
index 0236d291..6e880914 100644
--- a/altoslib/AltosTelemetryRecordLocation.java
+++ b/altoslib/AltosTelemetryLocation.java
@@ -15,10 +15,10 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
-public class AltosTelemetryRecordLocation extends AltosTelemetryRecordRaw {
+public class AltosTelemetryLocation extends AltosTelemetryStandard {
int flags;
int altitude;
int latitude;
@@ -37,8 +37,8 @@ public class AltosTelemetryRecordLocation extends AltosTelemetryRecordRaw {
int climb_rate;
int course;
- public AltosTelemetryRecordLocation(int[] in_bytes, int rssi) {
- super(in_bytes, rssi);
+ public AltosTelemetryLocation(int[] bytes) {
+ super(bytes);
flags = uint8(5);
altitude = int16(6);
@@ -59,35 +59,30 @@ public class AltosTelemetryRecordLocation extends AltosTelemetryRecordRaw {
course = uint8(30);
}
- public AltosRecord update_state(AltosRecord previous) {
- AltosRecord next = super.update_state(previous);
+ public void update_state(AltosState state) {
+ super.update_state(state);
+ AltosGPS gps = state.make_temp_gps(false);
- if (next.gps == null)
- next.gps = new AltosGPS();
+ gps.nsat = flags & 0xf;
+ gps.locked = (flags & (1 << 4)) != 0;
+ gps.connected = (flags & (1 << 5)) != 0;
- next.gps.nsat = flags & 0xf;
- next.gps.locked = (flags & (1 << 4)) != 0;
- next.gps.connected = (flags & (1 << 5)) != 0;
-
- if (next.gps.locked) {
- next.gps.lat = latitude * 1.0e-7;
- next.gps.lon = longitude * 1.0e-7;
- next.gps.alt = altitude;
- next.gps.year = 2000 + year;
- next.gps.month = month;
- next.gps.day = day;
- next.gps.hour = hour;
- next.gps.minute = minute;
- next.gps.second = second;
- next.gps.ground_speed = ground_speed * 1.0e-2;
- next.gps.course = course * 2;
- next.gps.climb_rate = climb_rate * 1.0e-2;
- next.gps.hdop = hdop;
- next.gps.vdop = vdop;
- next.seen |= AltosRecord.seen_gps_time | AltosRecord.seen_gps_lat | AltosRecord.seen_gps_lon;
- next.gps_sequence++;
+ if (gps.locked) {
+ gps.lat = latitude * 1.0e-7;
+ gps.lon = longitude * 1.0e-7;
+ gps.alt = altitude;
+ gps.year = 2000 + year;
+ gps.month = month;
+ gps.day = day;
+ gps.hour = hour;
+ gps.minute = minute;
+ gps.second = second;
+ gps.ground_speed = ground_speed * 1.0e-2;
+ gps.course = course * 2;
+ gps.climb_rate = climb_rate * 1.0e-2;
+ gps.hdop = hdop;
+ gps.vdop = vdop;
}
-
- return next;
+ state.set_temp_gps();
}
}
diff --git a/altoslib/AltosTelemetryMap.java b/altoslib/AltosTelemetryMap.java
index 7cca98b0..37883a1c 100644
--- a/altoslib/AltosTelemetryMap.java
+++ b/altoslib/AltosTelemetryMap.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
import java.text.*;
import java.util.HashMap;
diff --git a/altoslib/AltosTelemetryRecordMegaData.java b/altoslib/AltosTelemetryMegaData.java
index a484ef4e..f5cc01d0 100644
--- a/altoslib/AltosTelemetryRecordMegaData.java
+++ b/altoslib/AltosTelemetryMegaData.java
@@ -15,11 +15,9 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
-
-
-public class AltosTelemetryRecordMegaData extends AltosTelemetryRecordRaw {
+package org.altusmetrum.altoslib_2;
+public class AltosTelemetryMegaData extends AltosTelemetryStandard {
int state;
int v_batt;
@@ -35,8 +33,8 @@ public class AltosTelemetryRecordMegaData extends AltosTelemetryRecordRaw {
int speed;
int height;
- public AltosTelemetryRecordMegaData(int[] in_bytes, int rssi) {
- super(in_bytes, rssi);
+ public AltosTelemetryMegaData(int[] bytes) {
+ super(bytes);
state = int8(5);
@@ -60,35 +58,28 @@ public class AltosTelemetryRecordMegaData extends AltosTelemetryRecordRaw {
height = int16(30);
}
- public AltosRecord update_state(AltosRecord previous) {
- AltosRecord n = super.update_state(previous);
-
- AltosRecordMM next;
- if (!(n instanceof AltosRecordMM)) {
- next = new AltosRecordMM(n);
- } else {
- next = (AltosRecordMM) n;
- }
-
- next.state = state;
+ public void update_state(AltosState state) {
+ super.update_state(state);
- next.v_batt = v_batt;
- next.v_pyro = v_pyro;
+ state.set_state(this.state);
+
+ state.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt));
+ state.set_pyro_voltage(AltosConvert.mega_pyro_voltage(v_pyro));
- for (int i = 0; i < 6; i++)
- next.sense[i] = sense[i];
+ state.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense[4]));
+ state.set_main_voltage(AltosConvert.mega_pyro_voltage(sense[5]));
- next.ground_accel = ground_accel;
- next.ground_pres = ground_pres;
- next.accel_plus_g = accel_plus_g;
- next.accel_minus_g = accel_minus_g;
+ double voltages[] = new double[4];
+ for (int i = 0; i < 4; i++)
+ voltages[i] = AltosConvert.mega_pyro_voltage(sense[i]);
- next.kalman_acceleration = acceleration / 16.0;
- next.kalman_speed = speed / 16.0;
- next.kalman_height = height;
+ state.set_ignitor_voltage(voltages);
- next.seen |= AltosRecord.seen_sensor | AltosRecord.seen_temp_volt;
+ state.set_ground_accel(ground_accel);
+ state.set_ground_pressure(ground_pres);
+ state.set_accel_g(accel_plus_g, accel_minus_g);
- return next;
+ state.set_kalman(height, speed/16.0, acceleration / 16.0);
}
}
+
diff --git a/altoslib/AltosTelemetryRecordMegaSensor.java b/altoslib/AltosTelemetryMegaSensor.java
index 2a4b17a4..23b67af8 100644
--- a/altoslib/AltosTelemetryRecordMegaSensor.java
+++ b/altoslib/AltosTelemetryMegaSensor.java
@@ -15,10 +15,9 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
-
-public class AltosTelemetryRecordMegaSensor extends AltosTelemetryRecordRaw {
+public class AltosTelemetryMegaSensor extends AltosTelemetryStandard {
int accel;
int pres;
int temp;
@@ -35,8 +34,8 @@ public class AltosTelemetryRecordMegaSensor extends AltosTelemetryRecordRaw {
int mag_y;
int mag_z;
- public AltosTelemetryRecordMegaSensor(int[] in_bytes, int rssi) {
- super(in_bytes, rssi);
+ public AltosTelemetryMegaSensor(int[] bytes) {
+ super(bytes);
accel = int16(6);
pres = int32(8);
@@ -55,34 +54,31 @@ public class AltosTelemetryRecordMegaSensor extends AltosTelemetryRecordRaw {
mag_z = int16(30);
}
- public AltosRecord update_state(AltosRecord previous) {
- AltosRecord n = super.update_state(previous);
+ public void update_state(AltosState state) {
+ super.update_state(state);
- AltosRecordMM next;
- if (!(n instanceof AltosRecordMM)) {
- next = new AltosRecordMM(n);
- } else {
- next = (AltosRecordMM) n;
- }
+ state.set_accel(accel);
+ state.set_pressure(pres);
+ state.set_temperature(temp / 100.0);
- next.accel = accel;
- next.pres = pres;
- next.temp = temp;
+ AltosIMU imu = new AltosIMU();
+
+ imu.accel_x = accel_x;
+ imu.accel_y = accel_y;
+ imu.accel_z = accel_z;
- next.imu.accel_x = accel_x;
- next.imu.accel_y = accel_y;
- next.imu.accel_z = accel_z;
+ imu.gyro_x = gyro_x;
+ imu.gyro_y = gyro_y;
+ imu.gyro_z = gyro_z;
- next.imu.gyro_x = gyro_x;
- next.imu.gyro_y = gyro_y;
- next.imu.gyro_z = gyro_z;
+ state.imu = imu;
- next.mag.x = mag_x;
- next.mag.y = mag_y;
- next.mag.z = mag_z;
+ AltosMag mag = new AltosMag();
- next.seen |= AltosRecord.seen_sensor;
+ mag.x = mag_x;
+ mag.y = mag_y;
+ mag.z = mag_z;
- return next;
+ state.mag = mag;
}
}
diff --git a/altoslib/AltosTelemetryRecordGeneral.java b/altoslib/AltosTelemetryMetrumData.java
index 08cd6065..b6239971 100644
--- a/altoslib/AltosTelemetryRecordGeneral.java
+++ b/altoslib/AltosTelemetryMetrumData.java
@@ -15,27 +15,28 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
-import java.text.*;
-public class AltosTelemetryRecordGeneral {
+public class AltosTelemetryMetrumData extends AltosTelemetryStandard {
- static AltosTelemetryRecord parse(String line) throws ParseException, AltosCRCException {
- AltosTelemetryRecord r;
+ int ground_pres;
+ int ground_accel;
+ int accel_plus_g;
+ int accel_minus_g;
- String[] word = line.split("\\s+");
- int i =0;
- if (word[i].equals("CRC") && word[i+1].equals("INVALID")) {
- i += 2;
- AltosParse.word(word[i++], "RSSI");
- throw new AltosCRCException(AltosParse.parse_int(word[i++]));
- }
+ public AltosTelemetryMetrumData(int[] bytes) {
+ super(bytes);
- if (word[i].equals("TELEM"))
- r = AltosTelemetryRecordRaw.parse(word[i+1]);
- else
- r = new AltosTelemetryRecordLegacy(line);
- return r;
+ ground_pres = int32(8);
+ ground_accel = int16(12);
+ accel_plus_g = int16(14);
+ accel_minus_g = int16(16);
+ }
+
+ public void update_state(AltosState state) {
+ state.set_ground_accel(ground_accel);
+ state.set_accel_g(accel_plus_g, accel_minus_g);
+ state.set_ground_pressure(ground_pres);
}
}
diff --git a/altoslib/AltosTelemetryMetrumSensor.java b/altoslib/AltosTelemetryMetrumSensor.java
new file mode 100644
index 00000000..fc047afd
--- /dev/null
+++ b/altoslib/AltosTelemetryMetrumSensor.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altoslib_2;
+
+
+public class AltosTelemetryMetrumSensor extends AltosTelemetryStandard {
+ int state;
+
+ int accel;
+ int pres;
+ int temp;
+
+ int acceleration;
+ int speed;
+ int height;
+
+ int v_batt;
+ int sense_a;
+ int sense_m;
+
+ public AltosTelemetryMetrumSensor(int[] bytes) {
+ super(bytes);
+
+ state = int8(5);
+ accel = int16(6);
+ pres = int32(8);
+ temp = int16(12);
+
+ acceleration = int16(14);
+ speed = int16(16);
+ height = int16(18);
+
+ v_batt = int16(20);
+ sense_a = int16(22);
+ sense_m = int16(24);
+ }
+
+ public void update_state(AltosState state) {
+ super.update_state(state);
+
+ state.set_state(this.state);
+
+ state.set_accel(accel);
+ state.set_pressure(pres);
+ state.set_temperature(temp/100.0);
+
+ state.set_kalman(height, speed/16.0, acceleration/16.0);
+
+ state.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt));
+
+ state.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense_a));
+ state.set_main_voltage(AltosConvert.mega_pyro_voltage(sense_m));
+ }
+}
diff --git a/altoslib/AltosTelemetryMini.java b/altoslib/AltosTelemetryMini.java
new file mode 100644
index 00000000..e7109460
--- /dev/null
+++ b/altoslib/AltosTelemetryMini.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altoslib_2;
+
+
+public class AltosTelemetryMini extends AltosTelemetryStandard {
+ int state;
+
+ int v_batt;
+ int sense_a;
+ int sense_m;
+
+ int pres;
+ int temp;
+
+ int acceleration;
+ int speed;
+ int height;
+
+ int ground_pres;
+
+ public AltosTelemetryMini(int[] bytes) {
+ super(bytes);
+
+ state = int8(5);
+
+ v_batt = int16(6);
+ sense_a = int16(8);
+ sense_m = int16(10);
+
+ pres = int32(12);
+ temp = int16(16);
+
+ acceleration = int16(18);
+ speed = int16(20);
+ height = int16(22);
+
+ ground_pres = int32(24);
+ }
+
+ public void update_state(AltosState state) {
+ super.update_state(state);
+
+ state.set_state(this.state);
+
+ state.set_battery_voltage(AltosConvert.tele_mini_voltage(v_batt));
+ state.set_apogee_voltage(AltosConvert.tele_mini_voltage(sense_a));
+ state.set_main_voltage(AltosConvert.tele_mini_voltage(sense_m));
+
+ state.set_ground_pressure(ground_pres);
+
+ state.set_pressure(pres);
+ state.set_temperature(temp/100.0);
+
+ state.set_kalman(height, speed/16.0, acceleration/16.0);
+ }
+}
diff --git a/altoslib/AltosMs5607Query.java b/altoslib/AltosTelemetryRaw.java
index d39dbf26..dbe70fe9 100644
--- a/altoslib/AltosMs5607Query.java
+++ b/altoslib/AltosTelemetryRaw.java
@@ -1,5 +1,5 @@
/*
- * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,22 +15,14 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
-import java.util.concurrent.TimeoutException;
+public class AltosTelemetryRaw extends AltosTelemetryStandard {
+ public AltosTelemetryRaw(int[] bytes) {
+ super(bytes);
+ }
-class AltosMs5607Query extends AltosMs5607 {
- public AltosMs5607Query (AltosLink link) throws InterruptedException, TimeoutException {
- link.printf("v\nB\n");
- for (;;) {
- String line = link.get_reply_no_dialog(5000);
- if (line == null) {
- throw new TimeoutException();
- }
- if (!parse_line(line))
- break;
- }
- convert();
+ public void update_state(AltosState state) {
+ super.update_state(state);
}
}
-
diff --git a/altoslib/AltosTelemetryReader.java b/altoslib/AltosTelemetryReader.java
index b4293c73..eeb35cb5 100644
--- a/altoslib/AltosTelemetryReader.java
+++ b/altoslib/AltosTelemetryReader.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
import java.text.*;
import java.io.*;
@@ -24,19 +24,23 @@ import java.util.concurrent.*;
public class AltosTelemetryReader extends AltosFlightReader {
AltosLink link;
AltosLog log;
- AltosRecord previous;
double frequency;
int telemetry;
+ AltosState state = null;
LinkedBlockingQueue<AltosLine> telem;
- public AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException {
+ public AltosState read() throws InterruptedException, ParseException, AltosCRCException, IOException {
AltosLine l = telem.take();
if (l.line == null)
throw new IOException("IO error");
- AltosRecord next = AltosTelemetry.parse(l.line, previous);
- previous = next;
- return next;
+ AltosTelemetry telem = AltosTelemetry.parse(l.line);
+ if (state == null)
+ state = new AltosState();
+ else
+ state = state.clone();
+ telem.update_state(state);
+ return state;
}
public void flush() {
@@ -44,14 +48,16 @@ public class AltosTelemetryReader extends AltosFlightReader {
}
public void reset() {
- previous = null;
flush();
}
public void close(boolean interrupted) {
link.remove_monitor(telem);
log.close();
- link.close();
+ try {
+ link.close();
+ } catch (InterruptedException ie) {
+ }
}
public void set_frequency(double in_frequency) throws InterruptedException, TimeoutException {
@@ -80,7 +86,7 @@ public class AltosTelemetryReader extends AltosFlightReader {
else
return false;
} catch (InterruptedException ie) {
- return true;
+ return false;
} catch (TimeoutException te) {
return true;
}
@@ -111,29 +117,27 @@ public class AltosTelemetryReader extends AltosFlightReader {
return link.has_monitor_battery();
}
- public double monitor_battery() {
+ public double monitor_battery() throws InterruptedException {
return link.monitor_battery();
}
public AltosTelemetryReader (AltosLink in_link)
throws IOException, InterruptedException, TimeoutException {
link = in_link;
+ boolean success = false;
try {
log = new AltosLog(link);
name = link.name;
- previous = null;
telem = new LinkedBlockingQueue<AltosLine>();
frequency = AltosPreferences.frequency(link.serial);
set_frequency(frequency);
telemetry = AltosPreferences.telemetry(link.serial);
set_telemetry(telemetry);
link.add_monitor(telem);
- } catch (TimeoutException e) {
- close(true);
- throw(e);
- } catch (InterruptedException e) {
- close(true);
- throw(e);
+ success = true;
+ } finally {
+ if (!success)
+ close(true);
}
}
}
diff --git a/altoslib/AltosTelemetryRecord.java b/altoslib/AltosTelemetryRecord.java
deleted file mode 100644
index fdc3c88e..00000000
--- a/altoslib/AltosTelemetryRecord.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.altoslib_1;
-import java.text.*;
-
-public abstract class AltosTelemetryRecord {
-
- long received_time;
- abstract public AltosRecord update_state(AltosRecord previous);
-
- static boolean cksum(int[] bytes) {
- int sum = 0x5a;
- for (int i = 1; i < bytes.length - 1; i++)
- sum += bytes[i];
- sum &= 0xff;
- return sum == bytes[bytes.length - 1];
- }
-
- final static int PKT_APPEND_STATUS_1_CRC_OK = (1 << 7);
- final static int PKT_APPEND_STATUS_1_LQI_MASK = (0x7f);
- final static int PKT_APPEND_STATUS_1_LQI_SHIFT = 0;
-
- final static int packet_type_TM_sensor = 0x01;
- final static int packet_type_Tm_sensor = 0x02;
- final static int packet_type_Tn_sensor = 0x03;
- final static int packet_type_configuration = 0x04;
- final static int packet_type_location = 0x05;
- final static int packet_type_satellite = 0x06;
- final static int packet_type_companion = 0x07;
- final static int packet_type_MM_sensor = 0x08;
- final static int packet_type_MM_data = 0x09;
-
- static AltosTelemetryRecord parse_hex(String hex) throws ParseException, AltosCRCException {
- AltosTelemetryRecord r;
-
- int[] bytes;
- try {
- bytes = AltosLib.hexbytes(hex);
- } catch (NumberFormatException ne) {
- throw new ParseException(ne.getMessage(), 0);
- }
-
- /* one for length, one for checksum */
- if (bytes[0] != bytes.length - 2)
- throw new ParseException(String.format("invalid length %d != %d\n",
- bytes[0],
- bytes.length - 2), 0);
- if (!cksum(bytes))
- throw new ParseException(String.format("invalid line \"%s\"", hex), 0);
-
- int rssi = AltosLib.int8(bytes, bytes.length - 3) / 2 - 74;
- int status = AltosLib.uint8(bytes, bytes.length - 2);
-
- if ((status & PKT_APPEND_STATUS_1_CRC_OK) == 0)
- throw new AltosCRCException(rssi);
-
- /* length, data ..., rssi, status, checksum -- 4 bytes extra */
- switch (bytes.length) {
- case AltosLib.ao_telemetry_standard_len + 4:
- int type = AltosLib.uint8(bytes, 4 + 1);
- switch (type) {
- case packet_type_TM_sensor:
- case packet_type_Tm_sensor:
- case packet_type_Tn_sensor:
- r = new AltosTelemetryRecordSensor(bytes, rssi);
- break;
- case packet_type_configuration:
- r = new AltosTelemetryRecordConfiguration(bytes, rssi);
- break;
- case packet_type_location:
- r = new AltosTelemetryRecordLocation(bytes, rssi);
- break;
- case packet_type_satellite:
- r = new AltosTelemetryRecordSatellite(bytes, rssi);
- break;
- case packet_type_companion:
- r = new AltosTelemetryRecordCompanion(bytes, rssi);
- break;
- case packet_type_MM_sensor:
- r = new AltosTelemetryRecordMegaSensor(bytes, rssi);
- break;
- case packet_type_MM_data:
- r = new AltosTelemetryRecordMegaData(bytes, rssi);
- break;
- default:
- r = new AltosTelemetryRecordRaw(bytes, rssi);
- break;
- }
- break;
- case AltosLib.ao_telemetry_0_9_len + 4:
- r = new AltosTelemetryRecordLegacy(bytes, rssi, status);
- break;
- case AltosLib.ao_telemetry_0_8_len + 4:
- r = new AltosTelemetryRecordLegacy(bytes, rssi, status);
- break;
- default:
- throw new ParseException(String.format("Invalid packet length %d", bytes.length), 0);
- }
- r.received_time = System.currentTimeMillis();
- return r;
- }
-
- public static AltosTelemetryRecord parse(String line) throws ParseException, AltosCRCException {
- AltosTelemetryRecord r;
-
- String[] word = line.split("\\s+");
- int i =0;
- if (word[i].equals("CRC") && word[i+1].equals("INVALID")) {
- i += 2;
- AltosParse.word(word[i++], "RSSI");
- throw new AltosCRCException(AltosParse.parse_int(word[i++]));
- }
-
- if (word[i].equals("TELEM"))
- r = parse_hex(word[i+1]);
- else
- r = new AltosTelemetryRecordLegacy(line);
- return r;
- }
-}
diff --git a/altoslib/AltosTelemetryRecordCompanion.java b/altoslib/AltosTelemetryRecordCompanion.java
deleted file mode 100644
index 2231df13..00000000
--- a/altoslib/AltosTelemetryRecordCompanion.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.altoslib_1;
-
-public class AltosTelemetryRecordCompanion extends AltosTelemetryRecordRaw {
-
- AltosRecordCompanion companion;
-
- public AltosTelemetryRecordCompanion(int[] in_bytes, int rssi) {
- super(in_bytes, rssi);
-
- int off = 0;
- if (uint8(6) == 0)
- off = 1;
- int channels = uint8(7+off);
-
- if (off != 0 && channels >= 12)
- channels = 11;
-
- companion = new AltosRecordCompanion(channels);
- companion.tick = tick;
- companion.board_id = uint8(5);
- companion.update_period = uint8(6+off);
- for (int i = 0; i < companion.companion_data.length; i++)
- companion.companion_data[i] = uint16(8 + off + i * 2);
- }
-
- public AltosRecord update_state(AltosRecord previous) {
- AltosRecord next = super.update_state(previous);
-
- next.companion = companion;
- next.seen |= AltosRecord.seen_sensor | AltosRecord.seen_temp_volt;
-
- companion.tick = tick;
- return next;
- }
-}
diff --git a/altoslib/AltosTelemetryRecordRaw.java b/altoslib/AltosTelemetryRecordRaw.java
deleted file mode 100644
index f94789bb..00000000
--- a/altoslib/AltosTelemetryRecordRaw.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright © 2011 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.altoslib_1;
-
-public class AltosTelemetryRecordRaw extends AltosTelemetryRecord {
- int[] bytes;
- int serial;
- int tick;
- int type;
- int rssi;
-
- long received_time;
-
- public int int8(int off) {
- return AltosLib.int8(bytes, off + 1);
- }
-
- public int uint8(int off) {
- return AltosLib.uint8(bytes, off + 1);
- }
-
- public int int16(int off) {
- return AltosLib.int16(bytes, off + 1);
- }
-
- public int uint16(int off) {
- return AltosLib.uint16(bytes, off + 1);
- }
-
- public int uint32(int off) {
- return AltosLib.uint32(bytes, off + 1);
- }
-
- public int int32(int off) {
- return AltosLib.int32(bytes, off + 1);
- }
-
- public String string(int off, int l) {
- return AltosLib.string(bytes, off + 1, l);
- }
-
- public AltosTelemetryRecordRaw(int[] in_bytes, int in_rssi) {
- bytes = in_bytes;
- serial = uint16(0);
- tick = uint16(2);
- type = uint8(4);
- rssi = in_rssi;
- }
-
- public AltosRecord update_state(AltosRecord previous) {
- AltosRecord next;
-
- if (previous != null && previous.serial == serial)
- next = previous.clone();
- else
- next = new AltosRecordNone();
- next.serial = serial;
- next.tick = tick;
- next.rssi = rssi;
- return next;
- }
-
- public long received_time() {
- return received_time;
- }
-}
diff --git a/altoslib/AltosTelemetryRecordSatellite.java b/altoslib/AltosTelemetrySatellite.java
index 9835389b..fde3d86d 100644
--- a/altoslib/AltosTelemetryRecordSatellite.java
+++ b/altoslib/AltosTelemetrySatellite.java
@@ -15,14 +15,14 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
-public class AltosTelemetryRecordSatellite extends AltosTelemetryRecordRaw {
+public class AltosTelemetrySatellite extends AltosTelemetryStandard {
int channels;
AltosGPSSat[] sats;
- public AltosTelemetryRecordSatellite(int[] in_bytes, int rssi) {
- super(in_bytes, rssi);
+ public AltosTelemetrySatellite(int[] bytes) {
+ super(bytes);
channels = uint8(5);
if (channels > 12)
@@ -39,14 +39,12 @@ public class AltosTelemetryRecordSatellite extends AltosTelemetryRecordRaw {
}
}
- public AltosRecord update_state(AltosRecord previous) {
- AltosRecord next = super.update_state(previous);
+ public void update_state(AltosState state) {
+ super.update_state(state);
- if (next.gps == null)
- next.gps = new AltosGPS();
-
- next.gps.cc_gps_sat = sats;
-
- return next;
+ AltosGPS gps = state.make_temp_gps(true);
+
+ gps.cc_gps_sat = sats;
+ state.set_temp_gps();
}
}
diff --git a/altoslib/AltosTelemetryRecordSensor.java b/altoslib/AltosTelemetrySensor.java
index e0e92c13..e1106440 100644
--- a/altoslib/AltosTelemetryRecordSensor.java
+++ b/altoslib/AltosTelemetrySensor.java
@@ -15,10 +15,10 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
-public class AltosTelemetryRecordSensor extends AltosTelemetryRecordRaw {
+public class AltosTelemetrySensor extends AltosTelemetryStandard {
int state;
int accel;
int pres;
@@ -36,8 +36,8 @@ public class AltosTelemetryRecordSensor extends AltosTelemetryRecordRaw {
int accel_plus_g;
int accel_minus_g;
- public AltosTelemetryRecordSensor(int[] in_bytes, int rssi) {
- super(in_bytes, rssi);
+ public AltosTelemetrySensor(int[] bytes) {
+ super(bytes);
state = uint8(5);
accel = int16(6);
@@ -57,48 +57,24 @@ public class AltosTelemetryRecordSensor extends AltosTelemetryRecordRaw {
accel_minus_g = int16(30);
}
- public AltosRecord update_state(AltosRecord prev) {
- AltosRecord n = super.update_state(prev);
+ public void update_state(AltosState state) {
+ super.update_state(state);
- AltosRecordTM next;
- if (!(n instanceof AltosRecordTM))
- next = new AltosRecordTM(n);
- else
- next = (AltosRecordTM) n;
-
- next.state = state;
- if (type == packet_type_TM_sensor)
- next.accel = accel;
- else
- next.accel = AltosRecord.MISSING;
- next.pres = pres;
- next.temp = temp;
- next.batt = v_batt;
- if (type == packet_type_TM_sensor || type == packet_type_Tm_sensor) {
- next.drogue = sense_d;
- next.main = sense_m;
- } else {
- next.drogue = AltosRecord.MISSING;
- next.main = AltosRecord.MISSING;
- }
-
- next.kalman_acceleration = acceleration / 16.0;
- next.kalman_speed = speed / 16.0;
- next.kalman_height = height;
-
- next.ground_pres = ground_pres;
+ state.set_state(this.state);
if (type == packet_type_TM_sensor) {
- next.ground_accel = ground_accel;
- next.accel_plus_g = accel_plus_g;
- next.accel_minus_g = accel_minus_g;
- } else {
- next.ground_accel = AltosRecord.MISSING;
- next.accel_plus_g = AltosRecord.MISSING;
- next.accel_minus_g = AltosRecord.MISSING;
+ state.set_ground_accel(ground_accel);
+ state.set_accel_g(accel_plus_g, accel_minus_g);
+ state.set_accel(accel);
+ }
+ state.set_ground_pressure(AltosConvert.barometer_to_pressure(ground_pres));
+ state.set_pressure(AltosConvert.barometer_to_pressure(pres));
+ state.set_temperature(AltosConvert.thermometer_to_temperature(temp));
+ state.set_battery_voltage(AltosConvert.cc_battery_to_voltage(v_batt));
+ if (type == packet_type_TM_sensor || type == packet_type_Tm_sensor) {
+ state.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(sense_d));
+ state.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(sense_m));
}
- next.seen |= AltosRecord.seen_sensor | AltosRecord.seen_temp_volt;
-
- return next;
+ state.set_kalman(height, speed/16.0, acceleration / 16.0);
}
}
diff --git a/altoslib/AltosTelemetryStandard.java b/altoslib/AltosTelemetryStandard.java
new file mode 100644
index 00000000..3186ae09
--- /dev/null
+++ b/altoslib/AltosTelemetryStandard.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altoslib_2;
+
+public abstract class AltosTelemetryStandard extends AltosTelemetry {
+ int[] bytes;
+ int type;
+
+ public int int8(int off) {
+ return AltosLib.int8(bytes, off + 1);
+ }
+
+ public int uint8(int off) {
+ return AltosLib.uint8(bytes, off + 1);
+ }
+
+ public int int16(int off) {
+ return AltosLib.int16(bytes, off + 1);
+ }
+
+ public int uint16(int off) {
+ return AltosLib.uint16(bytes, off + 1);
+ }
+
+ public int uint32(int off) {
+ return AltosLib.uint32(bytes, off + 1);
+ }
+
+ public int int32(int off) {
+ return AltosLib.int32(bytes, off + 1);
+ }
+
+ public String string(int off, int l) {
+ return AltosLib.string(bytes, off + 1, l);
+ }
+
+ public static AltosTelemetry parse_hex(int[] bytes) {
+ int type = AltosLib.uint8(bytes, 4 + 1);
+
+ AltosTelemetry telem;
+ switch (type) {
+ case packet_type_TM_sensor:
+ case packet_type_Tm_sensor:
+ case packet_type_Tn_sensor:
+ telem = new AltosTelemetrySensor(bytes);
+ break;
+ case packet_type_configuration:
+ telem = new AltosTelemetryConfiguration(bytes);
+ break;
+ case packet_type_location:
+ telem = new AltosTelemetryLocation(bytes);
+ break;
+ case packet_type_satellite:
+ telem = new AltosTelemetrySatellite(bytes);
+ break;
+/*
+ case packet_type_companion:
+ telem = new AltosTelemetryCompanion(bytes);
+ break;
+*/
+ case packet_type_mega_sensor:
+ telem = new AltosTelemetryMegaSensor(bytes);
+ break;
+ case packet_type_mega_data:
+ telem = new AltosTelemetryMegaData(bytes);
+ break;
+ case packet_type_metrum_sensor:
+ telem = new AltosTelemetryMetrumSensor(bytes);
+ break;
+ case packet_type_metrum_data:
+ telem = new AltosTelemetryMetrumData(bytes);
+ break;
+ case packet_type_mini:
+ telem = new AltosTelemetryMini(bytes);
+ break;
+ default:
+ telem = new AltosTelemetryRaw(bytes);
+ break;
+ }
+ return telem;
+ }
+
+ public AltosTelemetryStandard(int[] bytes) {
+ this.bytes = bytes;
+
+ serial = uint16(0);
+ tick = uint16(2);
+ type = uint8(4);
+ }
+
+ public void update_state(AltosState state) {
+ super.update_state(state);
+ }
+}
diff --git a/altoslib/AltosTemperature.java b/altoslib/AltosTemperature.java
index 2749eac0..a636533f 100644
--- a/altoslib/AltosTemperature.java
+++ b/altoslib/AltosTemperature.java
@@ -15,29 +15,35 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
public class AltosTemperature extends AltosUnits {
- public double value(double v) {
- if (AltosConvert.imperial_units)
+ public double value(double v, boolean imperial_units) {
+ if (imperial_units)
return AltosConvert.c_to_f(v);
return v;
}
- public String show_units() {
- if (AltosConvert.imperial_units)
+ public double inverse(double v, boolean imperial_units) {
+ if (imperial_units)
+ return AltosConvert.f_to_c(v);
+ return v;
+ }
+
+ public String show_units(boolean imperial_units) {
+ if (imperial_units)
return "°F";
return "°C";
}
- public String say_units() {
- if (AltosConvert.imperial_units)
+ public String say_units(boolean imperial_units) {
+ if (imperial_units)
return "degrees farenheit";
return "degrees celsius";
}
- public int show_fraction(int width) {
+ public int show_fraction(int width, boolean imperial_units) {
return width / 3;
}
}
diff --git a/altoslib/AltosUnits.java b/altoslib/AltosUnits.java
index b8b3254c..8f9ccded 100644
--- a/altoslib/AltosUnits.java
+++ b/altoslib/AltosUnits.java
@@ -15,47 +15,94 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
public abstract class AltosUnits {
- public abstract double value(double v);
+ public abstract double value(double v, boolean imperial_units);
- public abstract String show_units();
+ public abstract double inverse(double v, boolean imperial_units);
- public abstract String say_units();
+ public abstract String show_units(boolean imperial_units);
- public abstract int show_fraction(int width);
+ public abstract String say_units(boolean imperial_units);
- int say_fraction() {
+ public abstract int show_fraction(int width, boolean imperial_units);
+
+ public double parse(String s, boolean imperial_units) throws NumberFormatException {
+ double v = Double.parseDouble(s);
+ return inverse(v, imperial_units);
+ }
+
+ public double parse(String s) throws NumberFormatException {
+ return parse(s, AltosConvert.imperial_units);
+ }
+
+ public double value(double v) {
+ return value(v, AltosConvert.imperial_units);
+ }
+
+ public double inverse(double v) {
+ return inverse(v, AltosConvert.imperial_units);
+ }
+
+ public String show_units() {
+ return show_units(AltosConvert.imperial_units);
+ }
+
+ public String say_units() {
+ return say_units(AltosConvert.imperial_units);
+ }
+
+ public int show_fraction(int width) {
+ return show_fraction(width, AltosConvert.imperial_units);
+ }
+
+ int say_fraction(boolean imperial_units) {
return 0;
}
- private String show_format(int width) {
- return String.format("%%%d.%df %s", width, show_fraction(width), show_units());
+ private String show_format(int width, boolean imperial_units) {
+ return String.format("%%%d.%df %s", width, show_fraction(width, imperial_units), show_units(imperial_units));
+ }
+
+ private String say_format(boolean imperial_units) {
+ return String.format("%%1.%df", say_fraction(imperial_units));
}
- private String say_format() {
- return String.format("%%1.%df", say_fraction());
+ private String say_units_format(boolean imperial_units) {
+ return String.format("%%1.%df %s", say_fraction(imperial_units), say_units(imperial_units));
}
- private String say_units_format() {
- return String.format("%%1.%df %s", say_fraction(), say_units());
+ public String graph_format(int width, boolean imperial_units) {
+ return String.format(String.format("%%%d.%df", width, show_fraction(width, imperial_units)), 0.0);
}
public String graph_format(int width) {
- return String.format(String.format("%%%d.%df", width, show_fraction(width)), 0.0);
+ return graph_format(width, AltosConvert.imperial_units);
+ }
+
+ public String show(int width, double v, boolean imperial_units) {
+ return String.format(show_format(width, imperial_units), value(v, imperial_units));
}
public String show(int width, double v) {
- return String.format(show_format(width), value(v));
+ return show(width, v, AltosConvert.imperial_units);
+ }
+
+ public String say(double v, boolean imperial_units) {
+ return String.format(say_format(imperial_units), value(v, imperial_units));
}
public String say(double v) {
- return String.format(say_format(), value(v));
+ return say(v, AltosConvert.imperial_units);
+ }
+
+ public String say_units(double v, boolean imperial_units) {
+ return String.format(say_units_format(imperial_units), value(v, imperial_units));
}
public String say_units(double v) {
- return String.format(say_units_format(), value(v));
+ return say_units(v, AltosConvert.imperial_units);
}
} \ No newline at end of file
diff --git a/altoslib/AltosUnitsListener.java b/altoslib/AltosUnitsListener.java
index 61a181a4..1e3ad655 100644
--- a/altoslib/AltosUnitsListener.java
+++ b/altoslib/AltosUnitsListener.java
@@ -15,7 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_1;
+package org.altusmetrum.altoslib_2;
public interface AltosUnitsListener {
public void units_changed(boolean imperial_units);
diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am
index 18b028d6..6d396635 100644
--- a/altoslib/Makefile.am
+++ b/altoslib/Makefile.am
@@ -1,4 +1,4 @@
-AM_JAVACFLAGS=-encoding UTF-8 -Xlint:deprecation
+AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -source 6
JAVAROOT=bin
@@ -9,73 +9,100 @@ CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH="bin:$(FREETTS)/*:/usr/share/java/
SRC=.
altoslibdir = $(datadir)/java
+record_files = \
+ AltosEepromRecord.java \
+ AltosEepromTeleScience.java \
+ AltosRecordCompanion.java \
+ AltosRecordIterable.java \
+ AltosOrderedRecord.java \
+ AltosOrderedMegaRecord.java \
+ AltosOrderedMiniRecord.java \
+ AltosRecord.java \
+ AltosRecordNone.java \
+ AltosRecordTM.java \
+ AltosRecordMM.java \
+ AltosRecordMini.java
+
altoslib_JAVA = \
AltosLib.java \
+ AltosCompanion.java \
AltosConfigData.java \
AltosConfigValues.java \
AltosConvert.java \
AltosCRCException.java \
AltosDebug.java \
+ AltosEeprom.java \
AltosEepromChunk.java \
+ AltosEepromDownload.java \
+ AltosEepromFile.java \
+ AltosEepromTM.java \
+ AltosEepromTm.java \
+ AltosEepromHeader.java \
AltosEepromIterable.java \
+ AltosEepromList.java \
AltosEepromLog.java \
AltosEepromMega.java \
- AltosEepromMegaIterable.java \
- AltosEepromRecord.java \
- AltosEepromTeleScience.java \
+ AltosEepromMetrum2.java \
+ AltosEepromMini.java \
+ AltosEepromMonitor.java \
AltosFile.java \
AltosFlash.java \
AltosFlashListener.java \
AltosFlightReader.java \
AltosFrequency.java \
AltosGPS.java \
- AltosGPSQuery.java \
AltosGPSSat.java \
AltosGreatCircle.java \
AltosHexfile.java \
+ AltosHexsym.java \
+ AltosIdle.java \
+ AltosIdleFetch.java \
AltosIdleMonitor.java \
AltosIdleMonitorListener.java \
AltosIgnite.java \
AltosIMU.java \
- AltosIMUQuery.java \
AltosLine.java \
AltosLink.java \
AltosListenerState.java \
AltosLog.java \
+ AltosMag.java \
+ AltosMma655x.java \
AltosMs5607.java \
- AltosMs5607Query.java \
- AltosOrderedRecord.java \
- AltosOrderedMegaRecord.java \
+ AltosNoSymbol.java \
AltosParse.java \
AltosPreferences.java \
AltosPreferencesBackend.java \
- AltosRecordCompanion.java \
- AltosRecordIterable.java \
- AltosRecord.java \
- AltosRecordNone.java \
- AltosRecordTM.java \
- AltosRecordMM.java \
+ AltosProgrammer.java \
AltosReplayReader.java \
AltosRomconfig.java \
+ AltosSelfFlash.java \
AltosSensorMM.java \
+ AltosSensorEMini.java \
AltosSensorTM.java \
+ AltosSensorTMini.java \
+ AltosSensorMega.java \
+ AltosSensorMetrum.java \
AltosState.java \
+ AltosStateIterable.java \
+ AltosStateUpdate.java \
AltosTelemetry.java \
+ AltosTelemetryConfiguration.java \
+ AltosTelemetryFile.java \
AltosTelemetryIterable.java \
+ AltosTelemetryLegacy.java \
+ AltosTelemetryLocation.java \
AltosTelemetryMap.java \
+ AltosTelemetryMegaSensor.java \
+ AltosTelemetryMegaData.java \
+ AltosTelemetryMini.java \
+ AltosTelemetryMetrumSensor.java \
+ AltosTelemetryMetrumData.java \
AltosTelemetryReader.java \
- AltosTelemetryRecordCompanion.java \
- AltosTelemetryRecordConfiguration.java \
- AltosTelemetryRecordGeneral.java \
- AltosTelemetryRecord.java \
- AltosTelemetryRecordLegacy.java \
- AltosTelemetryRecordLocation.java \
- AltosTelemetryRecordRaw.java \
- AltosTelemetryRecordSatellite.java \
- AltosTelemetryRecordSensor.java \
- AltosTelemetryRecordMegaSensor.java \
- AltosTelemetryRecordMegaData.java \
+ AltosTelemetryRaw.java \
+ AltosTelemetrySensor.java \
+ AltosTelemetrySatellite.java \
+ AltosTelemetryStandard.java \
AltosUnitsListener.java \
AltosMs5607.java \
AltosIMU.java \