Merge remote-tracking branch 'origin/master'
authorKeith Packard <keithp@keithp.com>
Tue, 8 Oct 2013 16:26:41 +0000 (09:26 -0700)
committerKeith Packard <keithp@keithp.com>
Tue, 8 Oct 2013 16:26:41 +0000 (09:26 -0700)
Signed-off-by: Keith Packard <keithp@keithp.com>
Conflicts:
configure.ac

264 files changed:
altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java
altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java
altosdroid/src/org/altusmetrum/AltosDroid/Dumper.java
altosdroid/src/org/altusmetrum/AltosDroid/TabAscent.java
altosdroid/src/org/altusmetrum/AltosDroid/TabDescent.java
altosdroid/src/org/altusmetrum/AltosDroid/TabLanded.java
altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java
altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java
altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java
altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java
altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java
altoslib/AltosAccel.java
altoslib/AltosCRCException.java
altoslib/AltosCompanion.java [new file with mode: 0644]
altoslib/AltosConfigData.java
altoslib/AltosConfigValues.java
altoslib/AltosConvert.java
altoslib/AltosDebug.java
altoslib/AltosDistance.java
altoslib/AltosEeprom.java [new file with mode: 0644]
altoslib/AltosEepromChunk.java
altoslib/AltosEepromFile.java [new file with mode: 0644]
altoslib/AltosEepromHeader.java [new file with mode: 0644]
altoslib/AltosEepromIterable.java
altoslib/AltosEepromLog.java
altoslib/AltosEepromMega.java
altoslib/AltosEepromMegaIterable.java [deleted file]
altoslib/AltosEepromMetrum2.java [new file with mode: 0644]
altoslib/AltosEepromMini.java
altoslib/AltosEepromMiniIterable.java [deleted file]
altoslib/AltosEepromRecord.java [deleted file]
altoslib/AltosEepromTM.java [new file with mode: 0644]
altoslib/AltosEepromTeleScience.java [deleted file]
altoslib/AltosEepromTm.java [new file with mode: 0644]
altoslib/AltosFile.java
altoslib/AltosFlash.java
altoslib/AltosFlashListener.java
altoslib/AltosFlightReader.java
altoslib/AltosFrequency.java
altoslib/AltosGPS.java
altoslib/AltosGPSQuery.java [deleted file]
altoslib/AltosGPSSat.java
altoslib/AltosGreatCircle.java
altoslib/AltosHeight.java
altoslib/AltosHexfile.java
altoslib/AltosIMU.java
altoslib/AltosIMUQuery.java [deleted file]
altoslib/AltosIdle.java [new file with mode: 0644]
altoslib/AltosIdleFetch.java [new file with mode: 0644]
altoslib/AltosIdleMonitor.java
altoslib/AltosIdleMonitorListener.java
altoslib/AltosIgnite.java
altoslib/AltosLib.java
altoslib/AltosLine.java
altoslib/AltosLink.java
altoslib/AltosListenerState.java
altoslib/AltosLog.java
altoslib/AltosMag.java
altoslib/AltosMma655x.java [new file with mode: 0644]
altoslib/AltosMs5607.java
altoslib/AltosMs5607Query.java [deleted file]
altoslib/AltosOrderedMegaRecord.java [deleted file]
altoslib/AltosOrderedMiniRecord.java [deleted file]
altoslib/AltosOrderedRecord.java [deleted file]
altoslib/AltosParse.java
altoslib/AltosPreferences.java
altoslib/AltosPreferencesBackend.java
altoslib/AltosPyro.java
altoslib/AltosRecord.java [deleted file]
altoslib/AltosRecordCompanion.java [deleted file]
altoslib/AltosRecordIterable.java [deleted file]
altoslib/AltosRecordMM.java [deleted file]
altoslib/AltosRecordMini.java [deleted file]
altoslib/AltosRecordNone.java [deleted file]
altoslib/AltosRecordTM.java [deleted file]
altoslib/AltosReplayReader.java
altoslib/AltosRomconfig.java
altoslib/AltosSelfFlash.java [new file with mode: 0644]
altoslib/AltosSensorEMini.java [new file with mode: 0644]
altoslib/AltosSensorMM.java
altoslib/AltosSensorMega.java [new file with mode: 0644]
altoslib/AltosSensorMetrum.java [new file with mode: 0644]
altoslib/AltosSensorTM.java
altoslib/AltosSensorTMini.java [new file with mode: 0644]
altoslib/AltosSpeed.java
altoslib/AltosState.java
altoslib/AltosStateIterable.java [new file with mode: 0644]
altoslib/AltosStateUpdate.java [new file with mode: 0644]
altoslib/AltosTelemetry.java
altoslib/AltosTelemetryConfiguration.java [new file with mode: 0644]
altoslib/AltosTelemetryFile.java [new file with mode: 0644]
altoslib/AltosTelemetryIterable.java
altoslib/AltosTelemetryLegacy.java [new file with mode: 0644]
altoslib/AltosTelemetryLocation.java [new file with mode: 0644]
altoslib/AltosTelemetryMap.java
altoslib/AltosTelemetryMegaData.java [new file with mode: 0644]
altoslib/AltosTelemetryMegaSensor.java [new file with mode: 0644]
altoslib/AltosTelemetryMetrumData.java [new file with mode: 0644]
altoslib/AltosTelemetryMetrumSensor.java [new file with mode: 0644]
altoslib/AltosTelemetryMini.java [new file with mode: 0644]
altoslib/AltosTelemetryRaw.java [new file with mode: 0644]
altoslib/AltosTelemetryReader.java
altoslib/AltosTelemetryRecord.java [deleted file]
altoslib/AltosTelemetryRecordCompanion.java [deleted file]
altoslib/AltosTelemetryRecordConfiguration.java [deleted file]
altoslib/AltosTelemetryRecordGeneral.java [deleted file]
altoslib/AltosTelemetryRecordLegacy.java [deleted file]
altoslib/AltosTelemetryRecordLocation.java [deleted file]
altoslib/AltosTelemetryRecordMegaData.java [deleted file]
altoslib/AltosTelemetryRecordMegaSensor.java [deleted file]
altoslib/AltosTelemetryRecordRaw.java [deleted file]
altoslib/AltosTelemetryRecordSatellite.java [deleted file]
altoslib/AltosTelemetryRecordSensor.java [deleted file]
altoslib/AltosTelemetrySatellite.java [new file with mode: 0644]
altoslib/AltosTelemetrySensor.java [new file with mode: 0644]
altoslib/AltosTelemetryStandard.java [new file with mode: 0644]
altoslib/AltosTemperature.java
altoslib/AltosUnits.java
altoslib/AltosUnitsListener.java
altoslib/Makefile.am
altosui/Altos.java
altosui/AltosAscent.java
altosui/AltosBTKnown.java
altosui/AltosCSV.java
altosui/AltosCSVUI.java
altosui/AltosCompanionInfo.java
altosui/AltosConfig.java
altosui/AltosConfigFreqUI.java
altosui/AltosConfigPyroUI.java
altosui/AltosConfigTD.java
altosui/AltosConfigTDUI.java
altosui/AltosConfigUI.java
altosui/AltosDataChooser.java
altosui/AltosDescent.java
altosui/AltosDisplayThread.java
altosui/AltosEepromDelete.java
altosui/AltosEepromDownload.java
altosui/AltosEepromList.java
altosui/AltosEepromManage.java
altosui/AltosEepromSelect.java
altosui/AltosFlashUI.java
altosui/AltosFlightDisplay.java
altosui/AltosFlightStats.java
altosui/AltosFlightStatsTable.java
altosui/AltosFlightStatus.java
altosui/AltosFlightStatusTableModel.java
altosui/AltosFlightStatusUpdate.java
altosui/AltosFlightUI.java
altosui/AltosFreqList.java
altosui/AltosGraph.java
altosui/AltosGraphDataPoint.java
altosui/AltosGraphDataSet.java
altosui/AltosGraphUI.java
altosui/AltosIdleMonitorUI.java
altosui/AltosIgniteUI.java
altosui/AltosInfoTable.java
altosui/AltosKML.java
altosui/AltosLanded.java
altosui/AltosPad.java
altosui/AltosRomconfigUI.java
altosui/AltosScanUI.java
altosui/AltosSerial.java
altosui/AltosSiteMap.java
altosui/AltosSiteMapTile.java
altosui/AltosUI.java
altosui/AltosUIPreferencesBackend.java
altosui/AltosWriter.java
altosuilib/AltosUIAxis.java
altosuilib/AltosUIEnable.java
altosuilib/AltosUIGraph.java
altosuilib/AltosUIGrapher.java
altosuilib/AltosUILib.java
altosuilib/AltosUIMarker.java
altosuilib/AltosUIPreferences.java
altosuilib/AltosUIPreferencesBackend.java
altosuilib/AltosUISeries.java
ao-tools/ao-telem/ao-telem.c
ao-tools/lib/cc-telemetry.h
configure.ac
micropeak/MicroData.java
micropeak/MicroDownload.java
micropeak/MicroExport.java
micropeak/MicroFile.java
micropeak/MicroFileChooser.java
micropeak/MicroGraph.java
micropeak/MicroPeak.java
micropeak/MicroRaw.java
micropeak/MicroSave.java
micropeak/MicroStats.java
micropeak/MicroStatsTable.java
src/Makedefs.in [new file with mode: 0644]
src/Makefile
src/attiny/ao_async.c [new file with mode: 0644]
src/attiny/ao_async.h [new file with mode: 0644]
src/avr-demo/Makefile
src/avr/Makefile.defs [new file with mode: 0644]
src/cc1111/Makefile.cc1111
src/core/ao_flight.c
src/core/ao_log.h
src/core/ao_log_micro.c [new file with mode: 0644]
src/core/ao_log_micro.h [new file with mode: 0644]
src/core/ao_log_mini.c
src/core/ao_microflight.c [new file with mode: 0644]
src/core/ao_microkalman.c [new file with mode: 0644]
src/core/ao_report_micro.c [new file with mode: 0644]
src/core/ao_telemetry.c
src/easymini-v0.1/.gitignore [deleted file]
src/easymini-v0.1/Makefile [deleted file]
src/easymini-v0.1/ao_easymini.c [deleted file]
src/easymini-v0.1/ao_pins.h [deleted file]
src/easymini-v0.1/flash-loader/Makefile [deleted file]
src/easymini-v0.1/flash-loader/ao_pins.h [deleted file]
src/easymini-v1.0/.gitignore [new file with mode: 0644]
src/easymini-v1.0/Makefile [new file with mode: 0644]
src/easymini-v1.0/ao_easymini.c [new file with mode: 0644]
src/easymini-v1.0/ao_pins.h [new file with mode: 0644]
src/easymini-v1.0/flash-loader/Makefile [new file with mode: 0644]
src/easymini-v1.0/flash-loader/ao_pins.h [new file with mode: 0644]
src/lpc/Makefile-flash.defs
src/lpc/Makefile.defs
src/lpc/ao_arch_funcs.h
src/micropeak/Makefile
src/micropeak/ao_async.c [deleted file]
src/micropeak/ao_async.h [deleted file]
src/micropeak/ao_log_micro.c [deleted file]
src/micropeak/ao_log_micro.h [deleted file]
src/micropeak/ao_microflight.c [deleted file]
src/micropeak/ao_microkalman.c [deleted file]
src/micropeak/ao_micropeak.c [deleted file]
src/micropeak/ao_micropeak.h [deleted file]
src/micropeak/ao_report_tiny.c [deleted file]
src/nanopeak-v0.1/.gitignore [new file with mode: 0644]
src/nanopeak-v0.1/Makefile [new file with mode: 0644]
src/nanopeak-v0.1/ao_pins.h [new file with mode: 0644]
src/product/Makefile.teledongle
src/product/Makefile.telelaunch
src/product/Makefile.telemetrum
src/product/Makefile.telemini
src/product/Makefile.telenano
src/product/ao_flash_pins.h
src/product/ao_micropeak.c [new file with mode: 0644]
src/product/ao_micropeak.h [new file with mode: 0644]
src/spiradio-v0.1/Makefile
src/stm/Makefile-flash.defs
src/stm/Makefile.defs
src/stm/ao_arch_funcs.h
src/teleballoon-v1.1/Makefile
src/telebt-v1.0/Makefile
src/telefire-v0.1/Makefile
src/telefire-v0.2/Makefile
src/telegps-v0.3/ao_telegps.c
src/telemetrum-v2.0/ao_telemetrum.c
src/telemini-v2.0/Makefile
src/telemini-v2.0/ao_pins.h
src/telemini-v2.0/ao_telemini.c
src/telepyro-v0.1/Makefile
src/telescience-pwm/Makefile
src/telescience-v0.1/Makefile
src/teleshield-v0.1/Makefile
src/teleterra-v0.2/Makefile
src/tidongle/Makefile

index 0aea06f1cf22a242cf89489768070522caafdf15..0ed314375eb55ccc20957a145a82a606a78a0a58 100644 (file)
@@ -31,7 +31,7 @@ import android.os.Handler;
 //import android.os.Message;
 import android.util.Log;
 
-import org.altusmetrum.altoslib_1.*;
+import org.altusmetrum.altoslib_2.*;
 
 public class AltosBluetooth extends AltosLink {
 
index e10982f7cc8873832c99fa21e2937c260deab64f..92287476b7dbf56fc654c408e5ddeb8c5ba41fd4 100644 (file)
@@ -49,7 +49,7 @@ import android.widget.Toast;
 import android.app.AlertDialog;
 import android.location.Location;
 
-import org.altusmetrum.altoslib_1.*;
+import org.altusmetrum.altoslib_2.*;
 
 public class AltosDroid extends FragmentActivity {
        // Debugging
@@ -147,7 +147,7 @@ public class AltosDroid extends FragmentActivity {
                        case MSG_CRC_ERROR:
                        case MSG_UPDATE_AGE:
                                if (ad.saved_state != null) {
-                                       ad.mAgeView.setText(String.format("%d", (System.currentTimeMillis() - ad.saved_state.report_time + 500) / 1000));
+                                       ad.mAgeView.setText(String.format("%d", (System.currentTimeMillis() - ad.saved_state.received_time + 500) / 1000));
                                }
                                break;
                        }
@@ -243,11 +243,11 @@ public class AltosDroid extends FragmentActivity {
                }
 
                if (state != null) {
-                       mCallsignView.setText(state.data.callsign);
-                       mSerialView.setText(String.format("%d", state.data.serial));
-                       mFlightView.setText(String.format("%d", state.data.flight));
-                       mStateView.setText(state.data.state());
-                       mRSSIView.setText(String.format("%d", state.data.rssi));
+                       mCallsignView.setText(state.callsign);
+                       mSerialView.setText(String.format("%d", state.serial));
+                       mFlightView.setText(String.format("%d", state.flight));
+                       mStateView.setText(state.state_name());
+                       mRSSIView.setText(String.format("%d", state.rssi));
                }
 
                for (AltosDroidTab mTab : mTabs)
@@ -266,7 +266,7 @@ public class AltosDroid extends FragmentActivity {
 
        static String pos(double p, String pos, String neg) {
                String  h = pos;
-               if (p == AltosRecord.MISSING)
+               if (p == AltosLib.MISSING)
                        return "";
                if (p < 0) {
                        h = neg;
@@ -278,13 +278,13 @@ public class AltosDroid extends FragmentActivity {
        }
 
        static String number(String format, double value) {
-               if (value == AltosRecord.MISSING)
+               if (value == AltosLib.MISSING)
                        return "";
                return String.format(format, value);
        }
 
        static String integer(String format, int value) {
-               if (value == AltosRecord.MISSING)
+               if (value == AltosLib.MISSING)
                        return "";
                return String.format(format, value);
        }
index fd4b0768ac33f8d60e55946be7f0d6bb1ad39d09..59fef84279d6c2b6985f9d192e05fd69e894dd48 100644 (file)
@@ -23,7 +23,7 @@ import android.content.Context;
 import android.content.SharedPreferences;
 import android.os.Environment;
 
-import org.altusmetrum.altoslib_1.*;
+import org.altusmetrum.altoslib_2.*;
 
 public class AltosDroidPreferences implements AltosPreferencesBackend {
        public final static String        NAME    = "org.altusmetrum.AltosDroid";
index 6ebb47f74e3b1ff9f3218f5655c5e1d43d6e2237..c652a1694f24b62df27f2ca829f0868ac79b0265 100644 (file)
@@ -17,7 +17,7 @@
 
 package org.altusmetrum.AltosDroid;
 
-import org.altusmetrum.altoslib_1.*;
+import org.altusmetrum.altoslib_2.*;
 import android.location.Location;
 
 public interface AltosDroidTab {
index b3dba62693714403f95f0b312beeb890f6e88b1a..f17cb82171e2f54e34eca4cd799677a95bdc1d2c 100644 (file)
-/*\r
- * Copyright © 2011 Keith Packard <keithp@keithp.com>\r
- * Copyright © 2012 Mike Beattie <mike@ethernal.org>\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; version 2 of the License.\r
- *\r
- * This program is distributed in the hope that it will be useful, but\r
- * WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.\r
- */\r
-\r
-package org.altusmetrum.AltosDroid;\r
-\r
-import android.speech.tts.TextToSpeech;\r
-import android.speech.tts.TextToSpeech.OnInitListener;\r
-\r
-import org.altusmetrum.altoslib_1.*;\r
-\r
-public class AltosVoice {\r
-\r
-       private TextToSpeech tts         = null;\r
-       private boolean      tts_enabled = false;\r
-\r
-       private IdleThread   idle_thread = null;\r
-\r
-       private AltosState   old_state   = null;\r
-\r
-       public AltosVoice(AltosDroid a) {\r
-\r
-               tts = new TextToSpeech(a, new OnInitListener() {\r
-                       public void onInit(int status) {\r
-                               if (status == TextToSpeech.SUCCESS) tts_enabled = true;\r
-                               if (tts_enabled) {\r
-                                       idle_thread = new IdleThread();\r
-                               }\r
-                       }\r
-               });\r
-\r
-       }\r
-\r
-       public void speak(String s) {\r
-               if (!tts_enabled) return;\r
-               tts.speak(s, TextToSpeech.QUEUE_ADD, null);\r
-       }\r
-\r
-       public void stop() {\r
-               if (tts != null) tts.shutdown();\r
-               if (idle_thread != null) {\r
-                       idle_thread.interrupt();\r
-                       idle_thread = null;\r
-               }\r
-       }\r
-\r
-       public void tell(AltosState state) {\r
-               if (!tts_enabled) return;\r
-\r
-               boolean spoke = false;\r
-               if (old_state == null || old_state.state != state.state) {\r
-                       speak(state.data.state());\r
-                       if ((old_state == null || old_state.state <= AltosLib.ao_flight_boost) &&\r
-                           state.state > AltosLib.ao_flight_boost) {\r
-                               speak(String.format("max speed: %d meters per second.", (int) (state.max_speed() + 0.5)));\r
-                               spoke = true;\r
-                       } else if ((old_state == null || old_state.state < AltosLib.ao_flight_drogue) &&\r
-                                  state.state >= AltosLib.ao_flight_drogue) {\r
-                               speak(String.format("max height: %d meters.", (int) (state.max_height + 0.5)));\r
-                               spoke = true;\r
-                       }\r
-               }\r
-               if (old_state == null || old_state.gps_ready != state.gps_ready) {\r
-                       if (state.gps_ready) {\r
-                               speak("GPS ready");\r
-                               spoke = true;\r
-                       } else if (old_state != null) {\r
-                               speak("GPS lost");\r
-                               spoke = true;\r
-                       }\r
-               }\r
-               old_state = state;\r
-               idle_thread.notice(state, spoke);\r
-       }\r
-\r
-\r
-       class IdleThread extends Thread {\r
-               boolean            started;\r
-               private AltosState state;\r
-               int                reported_landing;\r
-               int                report_interval;\r
-               long               report_time;\r
-\r
-               public synchronized void report(boolean last) {\r
-                       if (state == null)\r
-                               return;\r
-\r
-                       /* reset the landing count once we hear about a new flight */\r
-                       if (state.state < AltosLib.ao_flight_drogue)\r
-                               reported_landing = 0;\r
-\r
-                       /* Shut up once the rocket is on the ground */\r
-                       if (reported_landing > 2) {\r
-                               return;\r
-                       }\r
-\r
-                       /* If the rocket isn't on the pad, then report height */\r
-                       if (AltosLib.ao_flight_drogue <= state.state &&\r
-                           state.state < AltosLib.ao_flight_landed &&\r
-                           state.range >= 0)\r
-                       {\r
-                               speak(String.format("Height %d, bearing %s %d, elevation %d, range %d.\n",\r
-                                                   (int) (state.height + 0.5),\r
-                                       state.from_pad.bearing_words(\r
-                                             AltosGreatCircle.BEARING_VOICE),\r
-                                                   (int) (state.from_pad.bearing + 0.5),\r
-                                                   (int) (state.elevation + 0.5),\r
-                                                   (int) (state.range + 0.5)));\r
-                       } else if (state.state > AltosLib.ao_flight_pad) {\r
-                               speak(String.format("%d meters", (int) (state.height + 0.5)));\r
-                       } else {\r
-                               reported_landing = 0;\r
-                       }\r
-\r
-                       /* If the rocket is coming down, check to see if it has landed;\r
-                        * either we've got a landed report or we haven't heard from it in\r
-                        * a long time\r
-                        */\r
-                       if (state.state >= AltosLib.ao_flight_drogue &&\r
-                           (last ||\r
-                            System.currentTimeMillis() - state.report_time >= 15000 ||\r
-                            state.state == AltosLib.ao_flight_landed))\r
-                       {\r
-                               if (Math.abs(state.baro_speed) < 20 && state.height < 100)\r
-                                       speak("rocket landed safely");\r
-                               else\r
-                                       speak("rocket may have crashed");\r
-                               if (state.from_pad != null)\r
-                                       speak(String.format("Bearing %d degrees, range %d meters.",\r
-                                                           (int) (state.from_pad.bearing + 0.5),\r
-                                                           (int) (state.from_pad.distance + 0.5)));\r
-                               ++reported_landing;\r
-                       }\r
-               }\r
-\r
-               long now () {\r
-                       return System.currentTimeMillis();\r
-               }\r
-\r
-               void set_report_time() {\r
-                       report_time = now() + report_interval;\r
-               }\r
-\r
-               public void run () {\r
-                       try {\r
-                               for (;;) {\r
-                                       set_report_time();\r
-                                       for (;;) {\r
-                                               synchronized (this) {\r
-                                                       long sleep_time = report_time - now();\r
-                                                       if (sleep_time <= 0)\r
-                                                               break;\r
-                                                       wait(sleep_time);\r
-                                               }\r
-                                       }\r
-                                       report(false);\r
-                               }\r
-                       } catch (InterruptedException ie) {\r
-                       }\r
-               }\r
-\r
-               public synchronized void notice(AltosState new_state, boolean spoken) {\r
-                       AltosState old_state = state;\r
-                       state = new_state;\r
-                       if (!started && state.state > AltosLib.ao_flight_pad) {\r
-                               started = true;\r
-                               start();\r
-                       }\r
-\r
-                       if (state.state < AltosLib.ao_flight_drogue)\r
-                               report_interval = 10000;\r
-                       else\r
-                               report_interval = 20000;\r
-                       if (old_state != null && old_state.state != state.state) {\r
-                               report_time = now();\r
-                               this.notify();\r
-                       } else if (spoken)\r
-                               set_report_time();\r
-               }\r
-\r
-               public IdleThread() {\r
-                       state = null;\r
-                       reported_landing = 0;\r
-                       report_interval = 10000;\r
-               }\r
-       }\r
-\r
-}\r
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ * Copyright © 2012 Mike Beattie <mike@ethernal.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import android.speech.tts.TextToSpeech;
+import android.speech.tts.TextToSpeech.OnInitListener;
+
+import org.altusmetrum.altoslib_2.*;
+
+public class AltosVoice {
+
+       private TextToSpeech tts         = null;
+       private boolean      tts_enabled = false;
+
+       private IdleThread   idle_thread = null;
+
+       private AltosState   old_state   = null;
+
+       public AltosVoice(AltosDroid a) {
+
+               tts = new TextToSpeech(a, new OnInitListener() {
+                       public void onInit(int status) {
+                               if (status == TextToSpeech.SUCCESS) tts_enabled = true;
+                               if (tts_enabled) {
+                                       idle_thread = new IdleThread();
+                               }
+                       }
+               });
+
+       }
+
+       public void speak(String s) {
+               if (!tts_enabled) return;
+               tts.speak(s, TextToSpeech.QUEUE_ADD, null);
+       }
+
+       public void stop() {
+               if (tts != null) tts.shutdown();
+               if (idle_thread != null) {
+                       idle_thread.interrupt();
+                       idle_thread = null;
+               }
+       }
+
+       public void tell(AltosState state) {
+               if (!tts_enabled) return;
+
+               boolean spoke = false;
+               if (old_state == null || old_state.state != state.state) {
+                       speak(state.state_name());
+                       if ((old_state == null || old_state.state <= AltosLib.ao_flight_boost) &&
+                           state.state > AltosLib.ao_flight_boost) {
+                               speak(String.format("max speed: %d meters per second.", (int) (state.max_speed() + 0.5)));
+                               spoke = true;
+                       } else if ((old_state == null || old_state.state < AltosLib.ao_flight_drogue) &&
+                                  state.state >= AltosLib.ao_flight_drogue) {
+                               speak(String.format("max height: %d meters.", (int) (state.max_height() + 0.5)));
+                               spoke = true;
+                       }
+               }
+               if (old_state == null || old_state.gps_ready != state.gps_ready) {
+                       if (state.gps_ready) {
+                               speak("GPS ready");
+                               spoke = true;
+                       } else if (old_state != null) {
+                               speak("GPS lost");
+                               spoke = true;
+                       }
+               }
+               old_state = state;
+               idle_thread.notice(state, spoke);
+       }
+
+
+       class IdleThread extends Thread {
+               boolean            started;
+               private AltosState state;
+               int                reported_landing;
+               int                report_interval;
+               long               report_time;
+
+               public synchronized void report(boolean last) {
+                       if (state == null)
+                               return;
+
+                       /* reset the landing count once we hear about a new flight */
+                       if (state.state < AltosLib.ao_flight_drogue)
+                               reported_landing = 0;
+
+                       /* Shut up once the rocket is on the ground */
+                       if (reported_landing > 2) {
+                               return;
+                       }
+
+                       /* If the rocket isn't on the pad, then report height */
+                       if (AltosLib.ao_flight_drogue <= state.state &&
+                           state.state < AltosLib.ao_flight_landed &&
+                           state.range >= 0)
+                       {
+                               speak(String.format("Height %d, bearing %s %d, elevation %d, range %d.\n",
+                                                   (int) (state.height() + 0.5),
+                                       state.from_pad.bearing_words(
+                                             AltosGreatCircle.BEARING_VOICE),
+                                                   (int) (state.from_pad.bearing + 0.5),
+                                                   (int) (state.elevation + 0.5),
+                                                   (int) (state.range + 0.5)));
+                       } else if (state.state > AltosLib.ao_flight_pad) {
+                               speak(String.format("%d meters", (int) (state.height() + 0.5)));
+                       } else {
+                               reported_landing = 0;
+                       }
+
+                       /* If the rocket is coming down, check to see if it has landed;
+                        * either we've got a landed report or we haven't heard from it in
+                        * a long time
+                        */
+                       if (state.state >= AltosLib.ao_flight_drogue &&
+                           (last ||
+                            System.currentTimeMillis() - state.received_time >= 15000 ||
+                            state.state == AltosLib.ao_flight_landed))
+                       {
+                               if (Math.abs(state.speed()) < 20 && state.height() < 100)
+                                       speak("rocket landed safely");
+                               else
+                                       speak("rocket may have crashed");
+                               if (state.from_pad != null)
+                                       speak(String.format("Bearing %d degrees, range %d meters.",
+                                                           (int) (state.from_pad.bearing + 0.5),
+                                                           (int) (state.from_pad.distance + 0.5)));
+                               ++reported_landing;
+                       }
+               }
+
+               long now () {
+                       return System.currentTimeMillis();
+               }
+
+               void set_report_time() {
+                       report_time = now() + report_interval;
+               }
+
+               public void run () {
+                       try {
+                               for (;;) {
+                                       set_report_time();
+                                       for (;;) {
+                                               synchronized (this) {
+                                                       long sleep_time = report_time - now();
+                                                       if (sleep_time <= 0)
+                                                               break;
+                                                       wait(sleep_time);
+                                               }
+                                       }
+                                       report(false);
+                               }
+                       } catch (InterruptedException ie) {
+                       }
+               }
+
+               public synchronized void notice(AltosState new_state, boolean spoken) {
+                       AltosState old_state = state;
+                       state = new_state;
+                       if (!started && state.state > AltosLib.ao_flight_pad) {
+                               started = true;
+                               start();
+                       }
+
+                       if (state.state < AltosLib.ao_flight_drogue)
+                               report_interval = 10000;
+                       else
+                               report_interval = 20000;
+                       if (old_state != null && old_state.state != state.state) {
+                               report_time = now();
+                               this.notify();
+                       } else if (spoken)
+                               set_report_time();
+               }
+
+               public IdleThread() {
+                       state = null;
+                       reported_landing = 0;
+                       report_interval = 10000;
+               }
+       }
+
+}
index 17e4cf5b4c4497fc11b53bdaedd3311005d28e8f..2797fc5ee32f22d490aec5e21c5c7f5426dc1ab0 100644 (file)
-package org.altusmetrum.AltosDroid;\r
-\r
-       import java.lang.reflect.Array;\r
-       import java.lang.reflect.Field;\r
-       import java.util.HashMap;\r
-\r
-       public class Dumper {\r
-               private static Dumper instance = new Dumper();\r
-\r
-               protected static Dumper getInstance() {\r
-                       return instance;\r
-               }\r
-\r
-               class DumpContext {\r
-                       int maxDepth = 0;\r
-                       int maxArrayElements = 0;\r
-                       int callCount = 0;\r
-                       HashMap<String, String> ignoreList = new HashMap<String, String>();\r
-                       HashMap<Object, Integer> visited = new HashMap<Object, Integer>();\r
-               }\r
-\r
-               public static String dump(Object o) {\r
-                       return dump(o, 0, 0, null);\r
-               }\r
-\r
-               public static String dump(Object o, int maxDepth, int maxArrayElements, String[] ignoreList) {\r
-                       DumpContext ctx = Dumper.getInstance().new DumpContext();\r
-                       ctx.maxDepth = maxDepth;\r
-                       ctx.maxArrayElements = maxArrayElements;\r
-\r
-                       if (ignoreList != null) {\r
-                               for (int i = 0; i < Array.getLength(ignoreList); i++) {\r
-                                       int colonIdx = ignoreList[i].indexOf(':');\r
-                                       if (colonIdx == -1)\r
-                                               ignoreList[i] = ignoreList[i] + ":";\r
-                                       ctx.ignoreList.put(ignoreList[i], ignoreList[i]);\r
-                               }\r
-                       }\r
-\r
-                       return dump(o, ctx);\r
-               }\r
-\r
-               protected static String dump(Object o, DumpContext ctx) {\r
-                       if (o == null) {\r
-                               return "<null>";\r
-                       }\r
-\r
-                       ctx.callCount++;\r
-                       StringBuffer tabs = new StringBuffer();\r
-                       for (int k = 0; k < ctx.callCount; k++) {\r
-                               tabs.append("\t");\r
-                       }\r
-                       StringBuffer buffer = new StringBuffer();\r
-                       @SuppressWarnings("rawtypes")\r
-                       Class oClass = o.getClass();\r
-\r
-                       String oSimpleName = getSimpleNameWithoutArrayQualifier(oClass);\r
-\r
-                       if (ctx.ignoreList.get(oSimpleName + ":") != null)\r
-                               return "<Ignored>";\r
-\r
-                       if (oClass.isArray()) {\r
-                               buffer.append("\n");\r
-                               buffer.append(tabs.toString().substring(1));\r
-                               buffer.append("[\n");\r
-                               int rowCount = ctx.maxArrayElements == 0 ? Array.getLength(o) : Math.min(ctx.maxArrayElements, Array.getLength(o));\r
-                               for (int i = 0; i < rowCount; i++) {\r
-                                       buffer.append(tabs.toString());\r
-                                       try {\r
-                                               Object value = Array.get(o, i);\r
-                                               buffer.append(dumpValue(value, ctx));\r
-                                       } catch (Exception e) {\r
-                                               buffer.append(e.getMessage());\r
-                                       }\r
-                                       if (i < Array.getLength(o) - 1)\r
-                                               buffer.append(",");\r
-                                       buffer.append("\n");\r
-                               }\r
-                               if (rowCount < Array.getLength(o)) {\r
-                                       buffer.append(tabs.toString());\r
-                                       buffer.append(Array.getLength(o) - rowCount + " more array elements...");\r
-                                       buffer.append("\n");\r
-                               }\r
-                               buffer.append(tabs.toString().substring(1));\r
-                               buffer.append("]");\r
-                       } else {\r
-                               buffer.append("\n");\r
-                               buffer.append(tabs.toString().substring(1));\r
-                               buffer.append("{\n");\r
-                               buffer.append(tabs.toString());\r
-                               buffer.append("hashCode: " + o.hashCode());\r
-                               buffer.append("\n");\r
-                               while (oClass != null && oClass != Object.class) {\r
-                                       Field[] fields = oClass.getDeclaredFields();\r
-\r
-                                       if (ctx.ignoreList.get(oClass.getSimpleName()) == null) {\r
-                                               if (oClass != o.getClass()) {\r
-                                                       buffer.append(tabs.toString().substring(1));\r
-                                                       buffer.append("  Inherited from superclass " + oSimpleName + ":\n");\r
-                                               }\r
-\r
-                                               for (int i = 0; i < fields.length; i++) {\r
-\r
-                                                       String fSimpleName = getSimpleNameWithoutArrayQualifier(fields[i].getType());\r
-                                                       String fName = fields[i].getName();\r
-\r
-                                                       fields[i].setAccessible(true);\r
-                                                       buffer.append(tabs.toString());\r
-                                                       buffer.append(fName + "(" + fSimpleName + ")");\r
-                                                       buffer.append("=");\r
-\r
-                                                       if (ctx.ignoreList.get(":" + fName) == null &&\r
-                                                               ctx.ignoreList.get(fSimpleName + ":" + fName) == null &&\r
-                                                               ctx.ignoreList.get(fSimpleName + ":") == null) {\r
-\r
-                                                               try {\r
-                                                                       Object value = fields[i].get(o);\r
-                                                                       buffer.append(dumpValue(value, ctx));\r
-                                                               } catch (Exception e) {\r
-                                                                       buffer.append(e.getMessage());\r
-                                                               }\r
-                                                               buffer.append("\n");\r
-                                                       } else {\r
-                                                               buffer.append("<Ignored>");\r
-                                                               buffer.append("\n");\r
-                                                       }\r
-                                               }\r
-                                               oClass = oClass.getSuperclass();\r
-                                               oSimpleName = oClass.getSimpleName();\r
-                                       } else {\r
-                                               oClass = null;\r
-                                               oSimpleName = "";\r
-                                       }\r
-                               }\r
-                               buffer.append(tabs.toString().substring(1));\r
-                               buffer.append("}");\r
-                       }\r
-                       ctx.callCount--;\r
-                       return buffer.toString();\r
-               }\r
-\r
-               protected static String dumpValue(Object value, DumpContext ctx) {\r
-                       if (value == null) {\r
-                               return "<null>";\r
-                       }\r
-                       if (value.getClass().isPrimitive() ||\r
-                               value.getClass() == java.lang.Short.class ||\r
-                               value.getClass() == java.lang.Long.class ||\r
-                               value.getClass() == java.lang.String.class ||\r
-                               value.getClass() == java.lang.Integer.class ||\r
-                               value.getClass() == java.lang.Float.class ||\r
-                               value.getClass() == java.lang.Byte.class ||\r
-                               value.getClass() == java.lang.Character.class ||\r
-                               value.getClass() == java.lang.Double.class ||\r
-                               value.getClass() == java.lang.Boolean.class) {\r
-\r
-                               return value.toString();\r
-\r
-                       } else {\r
-\r
-                               Integer visitedIndex = ctx.visited.get(value);\r
-                               if (visitedIndex == null) {\r
-                                       ctx.visited.put(value, ctx.callCount);\r
-                                       if (ctx.maxDepth == 0 || ctx.callCount < ctx.maxDepth) {\r
-                                               return dump(value, ctx);\r
-                                       } else {\r
-                                               return "<Reached max recursion depth>";\r
-                                       }\r
-                               } else {\r
-                                       return "<Previously visited - see hashCode " + value.hashCode() + ">";\r
-                               }\r
-                       }\r
-               }\r
-\r
-\r
-               private static String getSimpleNameWithoutArrayQualifier(@SuppressWarnings("rawtypes") Class clazz) {\r
-                       String simpleName = clazz.getSimpleName();\r
-                       int indexOfBracket = simpleName.indexOf('['); \r
-                       if (indexOfBracket != -1)\r
-                               return simpleName.substring(0, indexOfBracket);\r
-                       return simpleName;\r
-               }\r
-}\r
+package org.altusmetrum.AltosDroid;
+
+       import java.lang.reflect.Array;
+       import java.lang.reflect.Field;
+       import java.util.HashMap;
+
+       public class Dumper {
+               private static Dumper instance = new Dumper();
+
+               protected static Dumper getInstance() {
+                       return instance;
+               }
+
+               class DumpContext {
+                       int maxDepth = 0;
+                       int maxArrayElements = 0;
+                       int callCount = 0;
+                       HashMap<String, String> ignoreList = new HashMap<String, String>();
+                       HashMap<Object, Integer> visited = new HashMap<Object, Integer>();
+               }
+
+               public static String dump(Object o) {
+                       return dump(o, 0, 0, null);
+               }
+
+               public static String dump(Object o, int maxDepth, int maxArrayElements, String[] ignoreList) {
+                       DumpContext ctx = Dumper.getInstance().new DumpContext();
+                       ctx.maxDepth = maxDepth;
+                       ctx.maxArrayElements = maxArrayElements;
+
+                       if (ignoreList != null) {
+                               for (int i = 0; i < Array.getLength(ignoreList); i++) {
+                                       int colonIdx = ignoreList[i].indexOf(':');
+                                       if (colonIdx == -1)
+                                               ignoreList[i] = ignoreList[i] + ":";
+                                       ctx.ignoreList.put(ignoreList[i], ignoreList[i]);
+                               }
+                       }
+
+                       return dump(o, ctx);
+               }
+
+               protected static String dump(Object o, DumpContext ctx) {
+                       if (o == null) {
+                               return "<null>";
+                       }
+
+                       ctx.callCount++;
+                       StringBuffer tabs = new StringBuffer();
+                       for (int k = 0; k < ctx.callCount; k++) {
+                               tabs.append("\t");
+                       }
+                       StringBuffer buffer = new StringBuffer();
+                       @SuppressWarnings("rawtypes")
+                       Class oClass = o.getClass();
+
+                       String oSimpleName = getSimpleNameWithoutArrayQualifier(oClass);
+
+                       if (ctx.ignoreList.get(oSimpleName + ":") != null)
+                               return "<Ignored>";
+
+                       if (oClass.isArray()) {
+                               buffer.append("\n");
+                               buffer.append(tabs.toString().substring(1));
+                               buffer.append("[\n");
+                               int rowCount = ctx.maxArrayElements == 0 ? Array.getLength(o) : Math.min(ctx.maxArrayElements, Array.getLength(o));
+                               for (int i = 0; i < rowCount; i++) {
+                                       buffer.append(tabs.toString());
+                                       try {
+                                               Object value = Array.get(o, i);
+                                               buffer.append(dumpValue(value, ctx));
+                                       } catch (Exception e) {
+                                               buffer.append(e.getMessage());
+                                       }
+                                       if (i < Array.getLength(o) - 1)
+                                               buffer.append(",");
+                                       buffer.append("\n");
+                               }
+                               if (rowCount < Array.getLength(o)) {
+                                       buffer.append(tabs.toString());
+                                       buffer.append(Array.getLength(o) - rowCount + " more array elements...");
+                                       buffer.append("\n");
+                               }
+                               buffer.append(tabs.toString().substring(1));
+                               buffer.append("]");
+                       } else {
+                               buffer.append("\n");
+                               buffer.append(tabs.toString().substring(1));
+                               buffer.append("{\n");
+                               buffer.append(tabs.toString());
+                               buffer.append("hashCode: " + o.hashCode());
+                               buffer.append("\n");
+                               while (oClass != null && oClass != Object.class) {
+                                       Field[] fields = oClass.getDeclaredFields();
+
+                                       if (ctx.ignoreList.get(oClass.getSimpleName()) == null) {
+                                               if (oClass != o.getClass()) {
+                                                       buffer.append(tabs.toString().substring(1));
+                                                       buffer.append("  Inherited from superclass " + oSimpleName + ":\n");
+                                               }
+
+                                               for (int i = 0; i < fields.length; i++) {
+
+                                                       String fSimpleName = getSimpleNameWithoutArrayQualifier(fields[i].getType());
+                                                       String fName = fields[i].getName();
+
+                                                       fields[i].setAccessible(true);
+                                                       buffer.append(tabs.toString());
+                                                       buffer.append(fName + "(" + fSimpleName + ")");
+                                                       buffer.append("=");
+
+                                                       if (ctx.ignoreList.get(":" + fName) == null &&
+                                                               ctx.ignoreList.get(fSimpleName + ":" + fName) == null &&
+                                                               ctx.ignoreList.get(fSimpleName + ":") == null) {
+
+                                                               try {
+                                                                       Object value = fields[i].get(o);
+                                                                       buffer.append(dumpValue(value, ctx));
+                                                               } catch (Exception e) {
+                                                                       buffer.append(e.getMessage());
+                                                               }
+                                                               buffer.append("\n");
+                                                       } else {
+                                                               buffer.append("<Ignored>");
+                                                               buffer.append("\n");
+                                                       }
+                                               }
+                                               oClass = oClass.getSuperclass();
+                                               oSimpleName = oClass.getSimpleName();
+                                       } else {
+                                               oClass = null;
+                                               oSimpleName = "";
+                                       }
+                               }
+                               buffer.append(tabs.toString().substring(1));
+                               buffer.append("}");
+                       }
+                       ctx.callCount--;
+                       return buffer.toString();
+               }
+
+               protected static String dumpValue(Object value, DumpContext ctx) {
+                       if (value == null) {
+                               return "<null>";
+                       }
+                       if (value.getClass().isPrimitive() ||
+                               value.getClass() == java.lang.Short.class ||
+                               value.getClass() == java.lang.Long.class ||
+                               value.getClass() == java.lang.String.class ||
+                               value.getClass() == java.lang.Integer.class ||
+                               value.getClass() == java.lang.Float.class ||
+                               value.getClass() == java.lang.Byte.class ||
+                               value.getClass() == java.lang.Character.class ||
+                               value.getClass() == java.lang.Double.class ||
+                               value.getClass() == java.lang.Boolean.class) {
+
+                               return value.toString();
+
+                       } else {
+
+                               Integer visitedIndex = ctx.visited.get(value);
+                               if (visitedIndex == null) {
+                                       ctx.visited.put(value, ctx.callCount);
+                                       if (ctx.maxDepth == 0 || ctx.callCount < ctx.maxDepth) {
+                                               return dump(value, ctx);
+                                       } else {
+                                               return "<Reached max recursion depth>";
+                                       }
+                               } else {
+                                       return "<Previously visited - see hashCode " + value.hashCode() + ">";
+                               }
+                       }
+               }
+
+
+               private static String getSimpleNameWithoutArrayQualifier(@SuppressWarnings("rawtypes") Class clazz) {
+                       String simpleName = clazz.getSimpleName();
+                       int indexOfBracket = simpleName.indexOf('['); 
+                       if (indexOfBracket != -1)
+                               return simpleName.substring(0, indexOfBracket);
+                       return simpleName;
+               }
+}
index 0e141ae47e942e2983333a1ef526c79b67b13c2d..3eaf12dbd1f53ca0124794c5ebb52990d1136132 100644 (file)
@@ -17,7 +17,7 @@
 
 package org.altusmetrum.AltosDroid;
 
-import org.altusmetrum.altoslib_1.*;
+import org.altusmetrum.altoslib_2.*;
 
 import android.app.Activity;
 import android.os.Bundle;
@@ -87,12 +87,12 @@ public class TabAscent extends Fragment implements AltosDroidTab {
 
        public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver) {
                if (state != null) {
-                       mHeightView.setText(AltosDroid.number("%6.0f m", state.height));
-                       mMaxHeightView.setText(AltosDroid.number("%6.0f m", state.max_height));
+                       mHeightView.setText(AltosDroid.number("%6.0f m", state.height()));
+                       mMaxHeightView.setText(AltosDroid.number("%6.0f m", state.max_height()));
                        mSpeedView.setText(AltosDroid.number("%6.0f m/s", state.speed()));
                        mMaxSpeedView.setText(AltosDroid.number("%6.0f m/s", state.max_speed()));
-                       mAccelView.setText(AltosDroid.number("%6.0f m/s²", state.acceleration));
-                       mMaxAccelView.setText(AltosDroid.number("%6.0f m/s²", state.max_acceleration));
+                       mAccelView.setText(AltosDroid.number("%6.0f m/s²", state.acceleration()));
+                       mMaxAccelView.setText(AltosDroid.number("%6.0f m/s²", state.max_acceleration()));
 
                        if (state.gps != null) {
                                mLatitudeView.setText(AltosDroid.pos(state.gps.lat, "N", "S"));
@@ -102,11 +102,11 @@ public class TabAscent extends Fragment implements AltosDroidTab {
                                mLongitudeView.setText("");
                        }
 
-                       mApogeeVoltageView.setText(AltosDroid.number("%4.2f V", state.drogue_sense));
-                       mApogeeLights.set(state.drogue_sense > 3.2, state.drogue_sense == AltosRecord.MISSING);
+                       mApogeeVoltageView.setText(AltosDroid.number("%4.2f V", state.apogee_voltage));
+                       mApogeeLights.set(state.apogee_voltage > 3.2, state.apogee_voltage == AltosLib.MISSING);
 
-                       mMainVoltageView.setText(AltosDroid.number("%4.2f V", state.main_sense));
-                       mMainLights.set(state.main_sense > 3.2, state.main_sense == AltosRecord.MISSING);
+                       mMainVoltageView.setText(AltosDroid.number("%4.2f V", state.main_voltage));
+                       mMainLights.set(state.main_voltage > 3.2, state.main_voltage == AltosLib.MISSING);
                }
        }
 }
index 09e7169b229ff1c126405ac9f8fe8a3fdbedabc6..e4a954ca1603e7fc38d9ffd46558fe597463f082 100644 (file)
@@ -17,7 +17,7 @@
 
 package org.altusmetrum.AltosDroid;
 
-import org.altusmetrum.altoslib_1.*;
+import org.altusmetrum.altoslib_2.*;
 
 import android.app.Activity;
 import android.os.Bundle;
@@ -92,7 +92,7 @@ public class TabDescent extends Fragment implements AltosDroidTab {
        public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver) {
                if (state != null) {
                        mSpeedView.setText(AltosDroid.number("%6.0f m/s", state.speed()));
-                       mHeightView.setText(AltosDroid.number("%6.0f m", state.height));
+                       mHeightView.setText(AltosDroid.number("%6.0f m", state.height()));
                        if (from_receiver != null) {
                                mElevationView.setText(AltosDroid.number("%3.0f°", from_receiver.elevation));
                                mRangeView.setText(AltosDroid.number("%6.0f m", from_receiver.range));
@@ -111,11 +111,11 @@ public class TabDescent extends Fragment implements AltosDroidTab {
                                mLongitudeView.setText(AltosDroid.pos(state.gps.lon, "W", "E"));
                        }
 
-                       mApogeeVoltageView.setText(AltosDroid.number("%4.2f V", state.drogue_sense));
-                       mApogeeLights.set(state.drogue_sense > 3.2, state.drogue_sense == AltosRecord.MISSING);
+                       mApogeeVoltageView.setText(AltosDroid.number("%4.2f V", state.apogee_voltage));
+                       mApogeeLights.set(state.apogee_voltage > 3.2, state.apogee_voltage == AltosLib.MISSING);
 
-                       mMainVoltageView.setText(AltosDroid.number("%4.2f V", state.main_sense));
-                       mMainLights.set(state.main_sense > 3.2, state.main_sense == AltosRecord.MISSING);
+                       mMainVoltageView.setText(AltosDroid.number("%4.2f V", state.main_voltage));
+                       mMainLights.set(state.main_voltage > 3.2, state.main_voltage == AltosLib.MISSING);
                }
        }
 
index f42b46b55520d7fbf8551e676ddda47dfebafe41..40399f2aed0df4d0fe31ad6e5fec78c0fb814d45 100644 (file)
@@ -17,7 +17,7 @@
 
 package org.altusmetrum.AltosDroid;
 
-import org.altusmetrum.altoslib_1.*;
+import org.altusmetrum.altoslib_2.*;
 
 import android.app.Activity;
 import android.os.Bundle;
@@ -89,8 +89,8 @@ public class TabLanded extends Fragment implements AltosDroidTab {
                }
               
                if (state != null) {
-                       mMaxHeightView.setText(String.format("%6.0f m", state.max_height));
-                       mMaxAccelView.setText(String.format("%6.0f m/s²", state.max_acceleration));
+                       mMaxHeightView.setText(String.format("%6.0f m", state.max_height()));
+                       mMaxAccelView.setText(String.format("%6.0f m/s²", state.max_acceleration()));
                        mMaxSpeedView.setText(String.format("%6.0f m/s", state.max_speed()));
                }
        }
index d831f1172761cfabf52a5b404a8b1ba585d200c9..a4e224aad486ac6f3216f728868c5ce3b00d53c0 100644 (file)
@@ -19,7 +19,7 @@ package org.altusmetrum.AltosDroid;
 
 import java.util.Arrays;
 
-import org.altusmetrum.altoslib_1.*;
+import org.altusmetrum.altoslib_2.*;
 
 import com.google.android.gms.maps.CameraUpdateFactory;
 import com.google.android.gms.maps.GoogleMap;
index 066c1353ef792a87896a18a3522d9623725a0e2d..2c6732e52e9765ec34df56a3f1b1ffeeaff31971 100644 (file)
@@ -17,7 +17,7 @@
 
 package org.altusmetrum.AltosDroid;
 
-import org.altusmetrum.altoslib_1.*;
+import org.altusmetrum.altoslib_2.*;
 
 import android.app.Activity;
 import android.os.Bundle;
@@ -103,26 +103,26 @@ public class TabPad extends Fragment implements AltosDroidTab {
 
        public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver) {
                if (state != null) {
-                       mBatteryVoltageView.setText(AltosDroid.number("%4.2f V", state.battery));
-                       mBatteryLights.set(state.battery > 3.7, state.battery == AltosRecord.MISSING);
+                       mBatteryVoltageView.setText(AltosDroid.number("%4.2f V", state.battery_voltage));
+                       mBatteryLights.set(state.battery_voltage > 3.7, state.battery_voltage == AltosLib.MISSING);
 
-                       mApogeeVoltageView.setText(AltosDroid.number("%4.2f V", state.drogue_sense));
-                       mApogeeLights.set(state.drogue_sense > 3.2, state.drogue_sense == AltosRecord.MISSING);
+                       mApogeeVoltageView.setText(AltosDroid.number("%4.2f V", state.apogee_voltage));
+                       mApogeeLights.set(state.apogee_voltage > 3.2, state.apogee_voltage == AltosLib.MISSING);
 
-                       mMainVoltageView.setText(AltosDroid.number("%4.2f V", state.main_sense));
-                       mMainLights.set(state.main_sense > 3.2, state.main_sense == AltosRecord.MISSING);
+                       mMainVoltageView.setText(AltosDroid.number("%4.2f V", state.main_voltage));
+                       mMainLights.set(state.main_voltage > 3.2, state.main_voltage == AltosLib.MISSING);
 
-                       if (state.data.flight != 0) {
-                               if (state.data.state <= AltosLib.ao_flight_pad)
+                       if (state.flight != 0) {
+                               if (state.state <= AltosLib.ao_flight_pad)
                                        mDataLoggingView.setText("Ready to record");
-                               else if (state.data.state < AltosLib.ao_flight_landed)
+                               else if (state.state < AltosLib.ao_flight_landed)
                                        mDataLoggingView.setText("Recording data");
                                else
                                        mDataLoggingView.setText("Recorded data");
                        } else {
                                mDataLoggingView.setText("Storage full");
                        }
-                       mDataLoggingLights.set(state.data.flight != 0, state.data.flight == AltosRecord.MISSING);
+                       mDataLoggingLights.set(state.flight != 0, state.flight == AltosLib.MISSING);
 
                        if (state.gps != null) {
                                mGPSLockedView.setText(AltosDroid.integer("%4d sats", state.gps.nsat));
index 3ece04ac3e8596b0ef1f64b40f430e5280c13d74..4d793413a8983e3403775b1e6217d03b034c0435 100644 (file)
@@ -1,6 +1,6 @@
 package org.altusmetrum.AltosDroid;
 
-import org.altusmetrum.altoslib_1.*;
+import org.altusmetrum.altoslib_2.*;
 
 import android.content.BroadcastReceiver;
 import android.content.Context;
index 716ec5894c9df42c5e0a975591ba8464c42e91bd..45604284e0767a405de80b2f5d6b8c66d77cb24a 100644 (file)
@@ -1,94 +1,95 @@
-/*\r
- * Copyright © 2011 Keith Packard <keithp@keithp.com>\r
- * Copyright © 2012 Mike Beattie <mike@ethernal.org>\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; version 2 of the License.\r
- *\r
- * This program is distributed in the hope that it will be useful, but\r
- * WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.\r
- */\r
-\r
-\r
-package org.altusmetrum.AltosDroid;\r
-\r
-import java.text.*;\r
-import java.io.*;\r
-import java.util.concurrent.*;\r
-import android.util.Log;\r
-import android.os.Handler;\r
-\r
-import org.altusmetrum.altoslib_1.*;\r
-\r
-\r
-public class TelemetryReader extends Thread {\r
-\r
-       private static final String TAG = "TelemetryReader";\r
-\r
-       int         crc_errors;\r
-\r
-       Handler     handler;\r
-\r
-       AltosLink   link;\r
-       AltosRecord previous;\r
-\r
-       LinkedBlockingQueue<AltosLine> telem;\r
-\r
-       public AltosRecord read() throws ParseException, AltosCRCException, InterruptedException, IOException {\r
-               AltosLine l = telem.take();\r
-               if (l.line == null)\r
-                       throw new IOException("IO error");\r
-               AltosRecord     next = AltosTelemetry.parse(l.line, previous);\r
-               previous = next;\r
-               return next;\r
-       }\r
-\r
-       public void close() {\r
-               previous = null;\r
-               link.remove_monitor(telem);\r
-               link = null;\r
-               telem.clear();\r
-               telem = null;\r
-       }\r
-\r
-       public void run() {\r
-               AltosState  state = null;\r
-\r
-               try {\r
-                       for (;;) {\r
-                               try {\r
-                                       AltosRecord record = read();\r
-                                       if (record == null)\r
-                                               break;\r
-                                       state = new AltosState(record, state);\r
-                                       handler.obtainMessage(TelemetryService.MSG_TELEMETRY, state).sendToTarget();\r
-                               } catch (ParseException pp) {\r
-                                       Log.e(TAG, String.format("Parse error: %d \"%s\"", pp.getErrorOffset(), pp.getMessage()));\r
-                               } catch (AltosCRCException ce) {\r
-                                       ++crc_errors;\r
-                                       handler.obtainMessage(TelemetryService.MSG_CRC_ERROR, new Integer(crc_errors)).sendToTarget();\r
-                               }\r
-                       }\r
-               } catch (InterruptedException ee) {\r
-               } catch (IOException ie) {\r
-               } finally {\r
-                       close();\r
-               }\r
-       }\r
-\r
-       public TelemetryReader (AltosLink in_link, Handler in_handler) {\r
-               link    = in_link;\r
-               handler = in_handler;\r
-\r
-               previous = null;\r
-               telem = new LinkedBlockingQueue<AltosLine>();\r
-               link.add_monitor(telem);\r
-       }\r
-}\r
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ * Copyright © 2012 Mike Beattie <mike@ethernal.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+
+package org.altusmetrum.AltosDroid;
+
+import java.text.*;
+import java.io.*;
+import java.util.concurrent.*;
+import android.util.Log;
+import android.os.Handler;
+
+import org.altusmetrum.altoslib_2.*;
+
+
+public class TelemetryReader extends Thread {
+
+       private static final String TAG = "TelemetryReader";
+
+       int         crc_errors;
+
+       Handler     handler;
+
+       AltosLink   link;
+       AltosState  state = null;
+
+       LinkedBlockingQueue<AltosLine> telemQueue;
+
+       public AltosState read() throws ParseException, AltosCRCException, InterruptedException, IOException {
+               AltosLine l = telemQueue.take();
+               if (l.line == null)
+                       throw new IOException("IO error");
+               AltosTelemetry telem = AltosTelemetryLegacy.parse(l.line);
+               if (state == null)
+                       state = new AltosState();
+               else
+                       state = state.clone();
+               telem.update_state(state);
+               return state;
+       }
+
+       public void close() {
+               state = null;
+               link.remove_monitor(telemQueue);
+               link = null;
+               telemQueue.clear();
+               telemQueue = null;
+       }
+
+       public void run() {
+               AltosState  state = null;
+
+               try {
+                       for (;;) {
+                               try {
+                                       state = read();
+                                       handler.obtainMessage(TelemetryService.MSG_TELEMETRY, state).sendToTarget();
+                               } catch (ParseException pp) {
+                                       Log.e(TAG, String.format("Parse error: %d \"%s\"", pp.getErrorOffset(), pp.getMessage()));
+                               } catch (AltosCRCException ce) {
+                                       ++crc_errors;
+                                       handler.obtainMessage(TelemetryService.MSG_CRC_ERROR, new Integer(crc_errors)).sendToTarget();
+                               }
+                       }
+               } catch (InterruptedException ee) {
+               } catch (IOException ie) {
+               } finally {
+                       close();
+               }
+       }
+
+       public TelemetryReader (AltosLink in_link, Handler in_handler) {
+               link    = in_link;
+               handler = in_handler;
+
+               state = null;
+               telemQueue = new LinkedBlockingQueue<AltosLine>();
+               link.add_monitor(telemQueue);
+       }
+}
index 940ad792df17ff35e6532123d2450ad41481782b..76efa74968ca557627ce2cf5495e7dbecd5b4645 100644 (file)
@@ -44,7 +44,7 @@ import android.location.LocationManager;
 import android.location.LocationListener;
 import android.location.Criteria;
 
-import org.altusmetrum.altoslib_1.*;
+import org.altusmetrum.altoslib_2.*;
 
 
 public class TelemetryService extends Service implements LocationListener {
index d02b32385f348e1dfdf28eabb5afd1219dbcf07b..08eba359c9f6bfb4622be0344d2b957390c8aead 100644 (file)
@@ -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 AltosAccel extends AltosUnits {
 
index 76e79add1255c1cb9157564c59ae7851d15a5864..be2ec4fec48e0bd00e311ea7b6c410718e07c4ac 100644 (file)
@@ -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/AltosCompanion.java b/altoslib/AltosCompanion.java
new file mode 100644 (file)
index 0000000..57bb21a
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * 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 AltosCompanion {
+       public final static int board_id_telescience = 0x0a;
+       public final static int MAX_CHANNELS = 12;
+
+       public int      tick;
+       public int      board_id;
+       public int      update_period;
+       public int      channels;
+       public int[]    companion_data;
+
+       public AltosCompanion(int in_channels) {
+               channels = in_channels;
+               if (channels < 0)
+                       channels = 0;
+               if (channels > MAX_CHANNELS)
+                       channels = MAX_CHANNELS;
+               companion_data = new int[channels];
+       }
+}
index 2ca5a7a56f74093227285d72176f62b51307e304..d92f42c3aeb9b43006784f9375303e4d7f3fe2e3 100644 (file)
@@ -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.*;
index 027d10f4dfb92be98d04d41a5a161b2d48c64dbb..fd5584c2422b0552bc4dfa4086bf288354dd69c3 100644 (file)
@@ -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 */
index 8cd478e2bd5ff6820bc0e5432deb1d8ad70a4082..760d9eb98c273a0501f15aad1e09b4dc6a6dca67 100644 (file)
@@ -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;
 
index 4d8e3ae7cfa994bb7718ac41bbf0691a98111c76..76c13d57a399187079d9d4f0820eaedf4a36fa22 100644 (file)
@@ -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.*;
 
index 25028ac79a2ae255717c901ef41f0460dbdca71c..562571657370a81be5a4d28fb620985e6995e06d 100644 (file)
@@ -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 AltosDistance extends AltosUnits {
 
diff --git a/altoslib/AltosEeprom.java b/altoslib/AltosEeprom.java
new file mode 100644 (file)
index 0000000..dd5993c
--- /dev/null
@@ -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) {
+               }
+       }
+}
index b1bba3bb56d67154c8cc49f23e3ab76c6cd84c02..48d29e1b603e9a9d8fdf558602e226d2495d7e3a 100644 (file)
@@ -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,35 @@ public class AltosEepromChunk {
                return true;
        }
 
+       public AltosEeprom eeprom(int offset, int log_format, AltosState state) {
+               AltosEeprom     eeprom = null;
+               try {
+                       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;
+                       }
+               } catch (ParseException e) {
+               }
+               return eeprom;
+       }
+
        public AltosEepromChunk(AltosLink link, int block, boolean flush)
                throws TimeoutException, InterruptedException {
 
diff --git a/altoslib/AltosEepromFile.java b/altoslib/AltosEepromFile.java
new file mode 100644 (file)
index 0000000..60ab257
--- /dev/null
@@ -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 (file)
index 0000000..0aeb78d
--- /dev/null
@@ -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+"));
+       }
+}
index b84574ef9647261ea724d9510f0946f03469f544..fc793579f41837469a54c8924a6b85025d9c23e9 100644 (file)
@@ -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
  * 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
index 20026c6d33139a76b4c8014f15e284defd0c3b48..95c0c3f6c5bcb272ba8db7b8cfbd89b8640d198c 100644 (file)
@@ -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;
index 0804c3924516f0ed6f8b38e099e930d39fabe1a2..7a4ee52d10680e1e61c3289bb029a12e079b444c 100644 (file)
  * 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,7 +50,7 @@ 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); }
@@ -91,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 (file)
index 5736f93..0000000
+++ /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 (file)
index 0000000..c1d62c0
--- /dev/null
@@ -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;
+       }
+}
index 215cd3d9a99eeb2461cbdf377a07890df55dfe9b..a09a62ceb6adfd4e24e95733a773c672f82367dc 100644 (file)
  * 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 AltosEepromMini {
-       public int      cmd;
-       public int      tick;
-       public boolean  valid;
-       public String   data;
-       public int      config_a, config_b;
-
-       public int      data8[];
-
+public class AltosEepromMini extends AltosEeprom {
        public static final int record_length = 16;
-       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 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 int record_length() { return record_length; }
 
        /* AO_LOG_FLIGHT elements */
        public int flight() { return data16(0); }
@@ -63,126 +41,39 @@ public class AltosEepromMini {
        public int sense_m() { return data16(8); }
        public int v_batt() { return data16(10); }
 
-       public AltosEepromMini (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;
-               }
+       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);
+       }
 
-               tick = chunk.data16(start+2);
+       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;
+               }
+       }
 
-               data8 = new int[data_length];
-               for (int i = 0; i < data_length; i++)
-                       data8[i] = chunk.data(start + header_length + i);
+       public AltosEepromMini (AltosEepromChunk chunk, int start) throws ParseException {
+               parse_chunk(chunk, start);
        }
 
        public AltosEepromMini (String line) {
-               valid = false;
-               tick = 0;
-
-               if (line == null) {
-                       cmd = AltosLib.AO_LOG_INVALID;
-                       line = "";
-               } else {
-                       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;
-                               }
-                       } catch (NumberFormatException ne) {
-                               cmd = AltosLib.AO_LOG_INVALID;
-                               data = line;
-                       }
-               }
+               parse_string(line);
        }
 
        public AltosEepromMini(int in_cmd, int in_tick) {
@@ -190,4 +81,22 @@ public class AltosEepromMini {
                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/AltosEepromMiniIterable.java b/altoslib/AltosEepromMiniIterable.java
deleted file mode 100644 (file)
index 1f22118..0000000
+++ /dev/null
@@ -1,297 +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 AltosEepromMiniIterable extends AltosRecordIterable {
-
-       static final int        seen_flight = 1;
-       static final int        seen_sensor = 2;
-
-       static final int        seen_basic = seen_flight|seen_sensor;
-
-       boolean                 has_accel;
-       boolean                 has_gps;
-       boolean                 has_ignite;
-
-       AltosEepromMini flight_record;
-
-       TreeSet<AltosOrderedMiniRecord> records;
-
-       AltosMs5607             baro;
-
-       LinkedList<AltosRecord> list;
-
-       class EepromState {
-               int     seen;
-               int     n_pad_samples;
-               double  ground_pres;
-               int     boost_tick;
-               int     sensor_tick;
-
-               EepromState() {
-                       seen = 0;
-                       n_pad_samples = 0;
-                       ground_pres = 0.0;
-               }
-       }
-
-       void update_state(AltosRecordMini state, AltosEepromMini record, EepromState eeprom) {
-               state.tick = record.tick;
-               switch (record.cmd) {
-               case AltosLib.AO_LOG_FLIGHT:
-                       eeprom.seen |= seen_flight;
-                       state.ground_pres = record.ground_pres();
-                       state.flight_pres = state.ground_pres;
-                       state.flight = record.data16(0);
-                       eeprom.boost_tick = record.tick;
-                       break;
-               case AltosLib.AO_LOG_SENSOR:
-                       baro.set(record.pres(), record.temp());
-                       state.pres = baro.pa;
-                       state.temp = baro.cc;
-                       state.sense_m = record.sense_m();
-                       state.sense_a = record.sense_a();
-                       state.v_batt = record.v_batt();
-                       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;
-                       }
-                       if ((eeprom.seen & seen_sensor) == 0)
-                               eeprom.sensor_tick = record.tick - 1;
-                       eeprom.seen |= seen_sensor;
-                       eeprom.sensor_tick = record.tick;
-                       break;
-               case AltosLib.AO_LOG_STATE:
-                       state.state = record.state();
-                       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_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<AltosOrderedMiniRecord> iterator = records.iterator();
-               AltosOrderedMiniRecord          record = null;
-               AltosRecordMini                 state = new AltosRecordMini();
-               //boolean                       last_reported = false;
-               EepromState                     eeprom = new EepromState();
-
-               state.state = AltosLib.ao_flight_pad;
-
-               /* Pull in static data from the flight records */
-               if (flight_record != null)
-                       update_state(state, flight_record, eeprom);
-
-               while (iterator.hasNext()) {
-                       record = iterator.next();
-                       if ((eeprom.seen & seen_basic) == seen_basic && record.tick != state.tick) {
-                               AltosRecordMini r = state.clone();
-                               r.time = (r.tick - eeprom.boost_tick) / 100.0;
-                               list.add(r);
-                       }
-                       update_state(state, record, eeprom);
-               }
-               AltosRecordMini 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<AltosOrderedMiniRecord>        iterator = records.iterator();
-               out.printf("# Comments\n");
-               while (iterator.hasNext()) {
-                       AltosOrderedMiniRecord  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
-        */
-       public AltosEepromMiniIterable (FileInputStream input) {
-               records = new TreeSet<AltosOrderedMiniRecord>();
-
-               AltosOrderedMiniRecord 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;
-                               AltosOrderedMiniRecord record = new AltosOrderedMiniRecord(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/AltosEepromRecord.java b/altoslib/AltosEepromRecord.java
deleted file mode 100644 (file)
index 70ac111..0000000
+++ /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 (file)
index 0000000..3680391
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package 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 (file)
index 2a828cf..0000000
+++ /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 (file)
index 0000000..b891413
--- /dev/null
@@ -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);
+                                       }
+