From: Bdale Garbee Date: Fri, 21 Jul 2017 23:44:03 +0000 (-0600) Subject: Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos X-Git-Tag: 1.8~6^2~2 X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=c8dbcaf69cd538a31ab6e2b568237ae7c8656a9a;hp=0cbfa444a9f9159cb509bb47ca5590fc1d709f64;p=fw%2Faltos Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos --- diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java index 8e65e1d0..359b5832 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java @@ -31,7 +31,7 @@ import android.bluetooth.BluetoothSocket; import android.os.Handler; //import android.os.Message; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class AltosBluetooth extends AltosDroidLink { diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDebug.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDebug.java index b8c90773..5906ff98 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDebug.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDebug.java @@ -21,7 +21,7 @@ import java.util.Arrays; import java.io.*; import java.lang.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; import android.app.Activity; import android.graphics.*; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java index 30a949d5..924ab4c9 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java @@ -52,7 +52,30 @@ import android.hardware.usb.*; import android.graphics.*; import android.graphics.drawable.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; + +class SavedState { + long received_time; + int state; + boolean locked; + String callsign; + int serial; + int flight; + int rssi; + + SavedState(AltosState state) { + received_time = state.received_time; + this.state = state.state(); + if (state.gps != null) + locked = state.gps.locked; + else + locked = false; + callsign = state.cal_data().callsign; + serial = state.cal_data().serial; + flight = state.cal_data().flight; + rssi = state.rssi; + } +} public class AltosDroid extends FragmentActivity implements AltosUnitsListener, LocationListener { @@ -114,6 +137,9 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener, public Location location = null; + private AltosState state; + private SavedState saved_state; + // Tabs TabHost mTabHost; AltosViewPager mViewPager; @@ -123,7 +149,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener, // Timer and Saved flight state for Age calculation private Timer timer; - AltosState saved_state; + TelemetryState telemetry_state; Integer[] serials; @@ -307,7 +333,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener, if (telemetry_state.states.containsKey(current_serial)) { state = telemetry_state.states.get(current_serial); - int age = state_age(state); + int age = state_age(state.received_time); if (age < 20) aged = false; if (current_serial == selected_serial) @@ -322,7 +348,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener, for (int serial : telemetry_state.states.keySet()) { AltosState existing = telemetry_state.states.get(serial); - int existing_age = state_age(existing); + int existing_age = state_age(existing.received_time); if (newest_state == null || existing_age < newest_age) { newest_state = existing; @@ -334,7 +360,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener, state = newest_state; } - update_ui(telemetry_state, state); + update_ui(telemetry_state, state, telemetry_state.quiet); start_timer(); } @@ -362,8 +388,8 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener, blend_component(a, b, r, 24, 0xff)); } - int state_age(AltosState state) { - return (int) ((System.currentTimeMillis() - state.received_time + 500) / 1000); + int state_age(long received_time) { + return (int) ((System.currentTimeMillis() - received_time + 500) / 1000); } void set_screen_on(int age) { @@ -375,7 +401,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener, void update_age() { if (saved_state != null) { - int age = state_age(saved_state); + int age = state_age(saved_state.received_time); double age_scale = age / 100.0; @@ -399,17 +425,19 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener, } } - void update_ui(TelemetryState telem_state, AltosState state) { + void update_ui(TelemetryState telem_state, AltosState state, boolean quiet) { + + this.state = state; int prev_state = AltosLib.ao_flight_invalid; AltosGreatCircle from_receiver = null; if (saved_state != null) - prev_state = saved_state.state(); + prev_state = saved_state.state; if (state != null) { - set_screen_on(state_age(state)); + set_screen_on(state_age(state.received_time)); if (state.state() == AltosLib.ao_flight_stateless) { boolean prev_locked = false; @@ -417,8 +445,8 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener, if(state.gps != null) locked = state.gps.locked; - if (saved_state != null && saved_state.gps != null) - prev_locked = saved_state.gps.locked; + if (saved_state != null) + prev_locked = saved_state.locked; if (prev_locked != locked) { String currentTab = mTabHost.getCurrentTabTag(); if (locked) { @@ -456,22 +484,22 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener, state.gps.alt); } - if (saved_state == null || !same_string(saved_state.callsign, state.callsign)) { - mCallsignView.setText(state.callsign); + if (saved_state == null || !same_string(saved_state.callsign, state.cal_data().callsign)) { + mCallsignView.setText(state.cal_data().callsign); } - if (saved_state == null || state.serial != saved_state.serial) { - if (state.serial == AltosLib.MISSING) + if (saved_state == null || state.cal_data().serial != saved_state.serial) { + if (state.cal_data().serial == AltosLib.MISSING) mSerialView.setText(""); else - mSerialView.setText(String.format("%d", state.serial)); + mSerialView.setText(String.format("%d", state.cal_data().serial)); } - if (saved_state == null || state.flight != saved_state.flight) { - if (state.flight == AltosLib.MISSING) + if (saved_state == null || state.cal_data().flight != saved_state.flight) { + if (state.cal_data().flight == AltosLib.MISSING) mFlightView.setText(""); else - mFlightView.setText(String.format("%d", state.flight)); + mFlightView.setText(String.format("%d", state.cal_data().flight)); } - if (saved_state == null || state.state() != saved_state.state()) { + if (saved_state == null || state.state() != saved_state.state) { if (state.state() == AltosLib.ao_flight_stateless) { mStateLayout.setVisibility(View.GONE); } else { @@ -485,15 +513,16 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener, else mRSSIView.setText(String.format("%d", state.rssi)); } + saved_state = new SavedState(state); } for (AltosDroidTab mTab : mTabs) mTab.update_ui(telem_state, state, from_receiver, location, mTab == mTabsAdapter.currentItem()); + AltosDebug.debug("quiet %b\n", quiet); if (mAltosVoice != null) - mAltosVoice.tell(telem_state, state, from_receiver, location, (AltosDroidTab) mTabsAdapter.currentItem()); + mAltosVoice.tell(telem_state, state, from_receiver, location, (AltosDroidTab) mTabsAdapter.currentItem(), quiet); - saved_state = state; } private void onTimerTick() { @@ -567,8 +596,9 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener, // Display the Version mVersion = (TextView) findViewById(R.id.version); mVersion.setText("Version: " + BuildInfo.version + - " Built: " + BuildInfo.builddate + " " + BuildInfo.buildtime + " " + BuildInfo.buildtz + - " (" + BuildInfo.branch + "-" + BuildInfo.commitnum + "-" + BuildInfo.commithash + ")"); + (AltosVersion.has_google_maps_api_key() ? " maps" : "") + + " Built: " + BuildInfo.builddate + " " + BuildInfo.buildtime + " " + BuildInfo.buildtz + + " (" + BuildInfo.branch + "-" + BuildInfo.commitnum + "-" + BuildInfo.commithash + ")"); mCallsignView = (TextView) findViewById(R.id.callsign_value); mRSSIView = (TextView) findViewById(R.id.rssi_value); @@ -703,7 +733,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener, location.getLatitude(), location.getLongitude()); - update_ui(telemetry_state, saved_state); + update_ui(telemetry_state, state, true); } @Override @@ -1094,7 +1124,7 @@ public class AltosDroid extends FragmentActivity implements AltosUnitsListener, AltosDebug.debug("Location changed to %f,%f", location.getLatitude(), location.getLongitude()); - update_ui(telemetry_state, saved_state); + update_ui(telemetry_state, state, false); } public void onStatusChanged(String provider, int status, Bundle extras) { diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidLink.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidLink.java index 23105635..05cb0f6b 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidLink.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidLink.java @@ -25,7 +25,7 @@ import java.util.UUID; import android.os.Handler; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public abstract class AltosDroidLink extends AltosLink { diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapInterface.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapInterface.java index 2b78104d..8730e8ad 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapInterface.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidMapInterface.java @@ -21,7 +21,7 @@ package org.altusmetrum.AltosDroid; import java.util.*; import java.io.*; import android.location.Location; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public interface AltosDroidMapInterface { public void onCreateView(AltosDroid altos_droid); diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java index c7cdc961..0670005a 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferences.java @@ -22,7 +22,7 @@ import java.util.*; import java.text.*; import android.content.Context; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class AltosDroidPreferences extends AltosPreferences { diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java index 2e6ccb34..01ec0af9 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java @@ -25,7 +25,7 @@ import android.content.SharedPreferences; import android.os.Environment; import android.util.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class AltosDroidPreferencesBackend extends AltosPreferencesBackend { public final static String NAME = "org.altusmetrum.AltosDroid"; @@ -77,7 +77,17 @@ public class AltosDroidPreferencesBackend extends AltosPreferencesBackend { } public String getString(String key, String def) { - return prefs.getString(key, def); + String ret; + ret = prefs.getString(key, def); +// AltosDebug.debug("AltosDroidPreferencesBackend get string %s:\n", key); +// if (ret == null) +// AltosDebug.debug(" (null)\n"); +// else { +// String[] lines = ret.split("\n"); +// for (String l : lines) +// AltosDebug.debug(" %s\n", l); +// } + return ret; } public byte[] getBytes(String key, byte[] def) { @@ -103,6 +113,10 @@ public class AltosDroidPreferencesBackend extends AltosPreferencesBackend { } public void putString(String key, String value) { +// AltosDebug.debug("AltosDroidPreferencesBackend put string %s:\n", key); +// String[] lines = value.split("\n"); +// for (String l : lines) +// AltosDebug.debug(" %s\n", l); editor.putString(key, value); } diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java index 11d8f624..71309897 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java @@ -18,7 +18,7 @@ package org.altusmetrum.AltosDroid; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; import android.location.Location; import android.app.Activity; import android.graphics.Color; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOffline.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOffline.java index 76771adc..2a728cf7 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOffline.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOffline.java @@ -21,7 +21,7 @@ package org.altusmetrum.AltosDroid; import java.util.*; import java.io.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; import android.app.Activity; import android.graphics.*; @@ -164,6 +164,7 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal break; case AltosMapTile.forbidden: message = "Too many requests, try later"; + AltosDebug.debug("Forbidden map response %d\n", AltosMapStore.forbidden_response); break; } if (message != null) { @@ -476,11 +477,11 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal if (t_state.gps != null) { AltosLatLon latlon = new AltosLatLon(t_state.gps.lat, t_state.gps.lon); rocket.set_position(latlon, t_state.received_time); - if (state.serial == serial) + if (state.cal_data().serial == serial) there = latlon; } if (state != null) - rocket.set_active(state.serial == serial); + rocket.set_active(state.cal_data().serial == serial); } } if (receiver != null) { diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOnline.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOnline.java index 9e5d6dee..b71cdd62 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOnline.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOnline.java @@ -20,7 +20,7 @@ package org.altusmetrum.AltosDroid; import java.util.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; import com.google.android.gms.maps.*; import com.google.android.gms.maps.model.*; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosUsb.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosUsb.java index 8d0a725a..77947b4b 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosUsb.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosUsb.java @@ -29,7 +29,7 @@ import android.hardware.usb.*; import android.app.*; import android.os.Handler; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class AltosUsb extends AltosDroidLink { diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java index 811b0367..fedfdb52 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java @@ -23,7 +23,7 @@ import android.speech.tts.TextToSpeech; import android.speech.tts.TextToSpeech.OnInitListener; import android.location.Location; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class AltosVoice { @@ -49,6 +49,7 @@ public class AltosVoice { private Location last_receiver; private long last_speak_time; private int last_flight_tell = TELL_FLIGHT_NONE; + private boolean quiet = false; private long now() { return System.currentTimeMillis(); @@ -80,7 +81,8 @@ public class AltosVoice { public synchronized void speak(String s) { if (!tts_enabled) return; last_speak_time = now(); - tts.speak(s, TextToSpeech.QUEUE_ADD, null); + if (!quiet) + tts.speak(s, TextToSpeech.QUEUE_ADD, null); } public synchronized long time_since_speak() { @@ -121,6 +123,8 @@ public class AltosVoice { if (state == null) return false; + AltosDebug.debug("tell_pad lag %b ltm %d\n", last_apogee_good, last_tell_mode); + if (state.apogee_voltage != AltosLib.MISSING) last_apogee_good = tell_gonogo("apogee", state.apogee_voltage >= AltosLib.ao_igniter_good, @@ -239,12 +243,12 @@ public class AltosVoice { if (last_flight_tell == TELL_FLIGHT_HEIGHT) { last_flight_tell = TELL_FLIGHT_TRACK; if (from_receiver != null) { - speak("bearing %s %d, elevation %d, range %s.", + speak("bearing %s %d, elevation %d, distance %s.", from_receiver.bearing_words( AltosGreatCircle.BEARING_VOICE), (int) (from_receiver.bearing + 0.5), (int) (from_receiver.elevation + 0.5), - AltosConvert.distance.say(from_receiver.range)); + AltosConvert.distance.say(from_receiver.distance)); return true; } } @@ -269,7 +273,7 @@ public class AltosVoice { if (direction == null) direction = String.format("Bearing %d", (int) (from_receiver.bearing + 0.5)); - speak("%s, range %s.", direction, + speak("%s, distance %s.", direction, AltosConvert.distance.say_units(from_receiver.distance)); return true; @@ -277,7 +281,9 @@ public class AltosVoice { public void tell(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver, - AltosDroidTab tab) { + AltosDroidTab tab, boolean quiet) { + + this.quiet = quiet; boolean spoken = false; @@ -288,7 +294,7 @@ public class AltosVoice { int tell_serial = last_tell_serial; if (state != null) - tell_serial = state.serial; + tell_serial = state.cal_data().serial; if (tell_serial != last_tell_serial) reset_last(); diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/IdleModeActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/IdleModeActivity.java index 7b3bbb4e..ace0a7d6 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/IdleModeActivity.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/IdleModeActivity.java @@ -35,7 +35,7 @@ import android.view.View.OnClickListener; import android.widget.*; import android.widget.AdapterView.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class IdleModeActivity extends Activity { private EditText callsign; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/IgniterActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/IgniterActivity.java index 4b8dc3e8..eccf5c59 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/IgniterActivity.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/IgniterActivity.java @@ -33,7 +33,7 @@ import android.view.View.*; import android.widget.*; import android.widget.AdapterView.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; class IgniterItem { public String name; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/ManageFrequenciesActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/ManageFrequenciesActivity.java index 0eef129e..ff599fda 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/ManageFrequenciesActivity.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/ManageFrequenciesActivity.java @@ -33,7 +33,7 @@ import android.view.inputmethod.*; import android.widget.*; import android.widget.AdapterView.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; class FrequencyItem { public AltosFrequency frequency; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/MapTypeActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/MapTypeActivity.java index a0c7233f..b93eaa19 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/MapTypeActivity.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/MapTypeActivity.java @@ -35,7 +35,7 @@ import android.view.View.OnClickListener; import android.widget.*; import android.widget.AdapterView.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class MapTypeActivity extends Activity { private Button hybrid; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java index a8e87bf2..9c43870f 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java @@ -42,7 +42,7 @@ import android.location.LocationManager; import android.location.LocationListener; import android.location.Criteria; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; /** * This Activity appears as a dialog. It lists any paired devices and diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/SetupActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/SetupActivity.java index 41c3eb88..d970fc4f 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/SetupActivity.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/SetupActivity.java @@ -31,7 +31,7 @@ import android.view.View.*; import android.widget.*; import android.widget.AdapterView.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class SetupActivity extends Activity { private Spinner select_rate; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabFlight.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabFlight.java index 3143679a..5349612c 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabFlight.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabFlight.java @@ -18,7 +18,7 @@ package org.altusmetrum.AltosDroid; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; import android.app.Activity; import android.os.Bundle; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java index 5db5b85f..d239d988 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java @@ -21,7 +21,7 @@ package org.altusmetrum.AltosDroid; import java.util.*; import java.io.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; import android.app.Activity; import android.graphics.*; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java index 492f7f5f..ba5afba5 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java @@ -18,7 +18,7 @@ package org.altusmetrum.AltosDroid; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; import android.app.Activity; import android.os.Bundle; @@ -178,10 +178,10 @@ public class TabPad extends AltosDroidTab { } main_lights.set(state.main_voltage >= AltosLib.ao_igniter_good, state.main_voltage == AltosLib.MISSING); - int num_igniter = state.ignitor_voltage == null ? 0 : state.ignitor_voltage.length; + int num_igniter = state.igniter_voltage == null ? 0 : state.igniter_voltage.length; for (int i = 0; i < 4; i++) { - double voltage = i >= num_igniter ? AltosLib.MISSING : state.ignitor_voltage[i]; + double voltage = i >= num_igniter ? AltosLib.MISSING : state.igniter_voltage[i]; if (voltage == AltosLib.MISSING) { ignite_row[i].setVisibility(View.GONE); } else { @@ -191,7 +191,7 @@ public class TabPad extends AltosDroidTab { ignite_lights[i].set(voltage >= AltosLib.ao_igniter_good, voltage == AltosLib.MISSING); } - if (state.flight != 0) { + if (state.cal_data().flight != 0) { if (state.state() <= AltosLib.ao_flight_pad) data_logging_view.setText("Ready to record"); else if (state.state() < AltosLib.ao_flight_landed) @@ -201,7 +201,7 @@ public class TabPad extends AltosDroidTab { } else { data_logging_view.setText("Storage full"); } - data_logging_lights.set(state.flight != 0, state.flight == AltosLib.MISSING); + data_logging_lights.set(state.cal_data().flight != 0, state.cal_data().flight == AltosLib.MISSING); if (state.gps != null) { int soln = state.gps.nsat; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabRecover.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabRecover.java index 97a35c9e..ac211230 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabRecover.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabRecover.java @@ -18,7 +18,7 @@ package org.altusmetrum.AltosDroid; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; import android.app.Activity; import android.os.Bundle; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java index c379d3d8..56f235c1 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryLogger.java @@ -1,6 +1,6 @@ package org.altusmetrum.AltosDroid; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; import android.content.BroadcastReceiver; import android.content.Context; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java index bc0b3615..d097a550 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java @@ -26,7 +26,7 @@ import java.util.*; import java.util.concurrent.*; import android.os.Handler; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class TelemetryReader extends Thread { diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java index 34c86ce5..caf288a0 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java @@ -41,7 +41,7 @@ import android.os.Looper; import android.widget.Toast; import android.location.Criteria; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class TelemetryService extends Service implements AltosIdleMonitorListener { @@ -259,14 +259,15 @@ public class TelemetryService extends Service implements AltosIdleMonitorListene private void telemetry(AltosTelemetry telem) { AltosState state; - if (telemetry_state.states.containsKey(telem.serial)) - state = telemetry_state.states.get(telem.serial).clone(); + if (telemetry_state.states.containsKey(telem.serial())) + state = telemetry_state.states.get(telem.serial()); else - state = new AltosState(); - telem.update_state(state); - telemetry_state.states.put(telem.serial, state); + state = new AltosState(new AltosCalData()); + telem.provide_data(state); + telemetry_state.states.put(telem.serial(), state); + telemetry_state.quiet = false; if (state != null) { - AltosPreferences.set_state(state); + AltosPreferences.set_state(state,telem.serial()); } send_to_clients(); } @@ -615,6 +616,8 @@ public class TelemetryService extends Service implements AltosIdleMonitorListene telemetry_state.latest_serial = AltosPreferences.latest_state(); + telemetry_state.quiet = true; + AltosDebug.debug("latest serial %d\n", telemetry_state.latest_serial); for (int serial : serials) { @@ -625,7 +628,7 @@ public class TelemetryService extends Service implements AltosIdleMonitorListene AltosDebug.debug("recovered old state serial %d flight %d", serial, - saved_state.flight); + saved_state.cal_data().flight); if (saved_state.gps != null) AltosDebug.debug("\tposition %f,%f", saved_state.gps.lat, @@ -699,7 +702,7 @@ public class TelemetryService extends Service implements AltosIdleMonitorListene /* AltosIdleMonitorListener */ public void update(AltosState state, AltosListenerState listener_state) { - telemetry_state.states.put(state.serial, state); + telemetry_state.states.put(state.cal_data().serial, state); telemetry_state.receiver_battery = listener_state.battery; send_to_clients(); } diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryState.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryState.java index 32ba1254..77cee787 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryState.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryState.java @@ -19,7 +19,7 @@ package org.altusmetrum.AltosDroid; import java.util.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; import android.location.Location; public class TelemetryState { @@ -36,6 +36,8 @@ public class TelemetryState { double frequency; int telemetry_rate; + boolean quiet; + HashMap states; int latest_serial; diff --git a/altoslib/AltosAccel.java b/altoslib/AltosAccel.java index 31aa7c1b..8fefefc5 100644 --- a/altoslib/AltosAccel.java +++ b/altoslib/AltosAccel.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; diff --git a/altoslib/AltosCRCException.java b/altoslib/AltosCRCException.java index 80dca140..5c398d3c 100644 --- a/altoslib/AltosCRCException.java +++ b/altoslib/AltosCRCException.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosCRCException extends Exception { public int rssi; diff --git a/altoslib/AltosCSV.java b/altoslib/AltosCSV.java index b5199456..f55b4785 100644 --- a/altoslib/AltosCSV.java +++ b/altoslib/AltosCSV.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.util.*; @@ -27,16 +27,17 @@ public class AltosCSV implements AltosWriter { boolean header_written; boolean seen_boost; int boost_tick; - LinkedList pad_states; - AltosState state; - static boolean has_basic; - static boolean has_battery; - static boolean has_flight_state; - static boolean has_advanced; - static boolean has_gps; - static boolean has_gps_sat; - static boolean has_companion; + boolean has_basic; + boolean has_battery; + boolean has_flight_state; + boolean has_advanced; + boolean has_gps; + boolean has_gps_sat; + boolean has_companion; + + AltosFlightSeries series; + int[] indices; static final int ALTOS_CSV_VERSION = 5; @@ -117,71 +118,116 @@ public class AltosCSV implements AltosWriter { out.printf("version,serial,flight,call,time,clock,rssi,lqi"); } - void write_general(AltosState state) { + double time() { + return series.time(indices); + } + + int rssi() { + return (int) series.value(AltosFlightSeries.rssi_name, indices); + } + + int status() { + return (int) series.value(AltosFlightSeries.status_name, indices); + } + + void write_general() { + double time = time(); out.printf("%s, %d, %d, %s, %8.2f, %8.2f, %4d, %3d", - ALTOS_CSV_VERSION, state.serial, state.flight, state.callsign, - (double) state.time_since_boost(), (double) state.tick / 100.0, - state.rssi, - state.status & 0x7f); + ALTOS_CSV_VERSION, series.cal_data().serial, + series.cal_data().flight, series.cal_data().callsign, + time, time, + rssi(), status() & 0x7f); } void write_flight_header() { out.printf("state,state_name"); } - void write_flight(AltosState state) { - out.printf("%d,%8s", state.state(), state.state_name()); + int state() { + return (int) series.value(AltosFlightSeries.state_name, indices); + } + + void write_flight() { + int state = state(); + out.printf("%d,%8s", state, AltosLib.state_name(state)); } void write_basic_header() { out.printf("acceleration,pressure,altitude,height,accel_speed,baro_speed,temperature,drogue_voltage,main_voltage"); } - void write_basic(AltosState state) { + double acceleration() { return series.value(AltosFlightSeries.accel_name, indices); } + double pressure() { return series.value(AltosFlightSeries.pressure_name, indices); } + double altitude() { return series.value(AltosFlightSeries.altitude_name, indices); } + double height() { return series.value(AltosFlightSeries.height_name, indices); } + double speed() { return series.value(AltosFlightSeries.speed_name, indices); } + double temperature() { return series.value(AltosFlightSeries.temperature_name, indices); } + double apogee_voltage() { return series.value(AltosFlightSeries.apogee_voltage_name, indices); } + double main_voltage() { return series.value(AltosFlightSeries.main_voltage_name, indices); } + + void write_basic() { out.printf("%8.2f,%10.2f,%8.2f,%8.2f,%8.2f,%8.2f,%5.1f,%5.2f,%5.2f", - state.acceleration(), - state.pressure(), - state.altitude(), - state.height(), - state.speed(), - state.speed(), - state.temperature, - state.apogee_voltage, - state.main_voltage); + acceleration(), + pressure(), + altitude(), + height(), + speed(), + speed(), + temperature(), + apogee_voltage(), + main_voltage()); } void write_battery_header() { out.printf("battery_voltage"); } - void write_battery(AltosState state) { - out.printf("%5.2f", state.battery_voltage); + double battery_voltage() { return series.value(AltosFlightSeries.battery_voltage_name, indices); } + + void write_battery() { + out.printf("%5.2f", battery_voltage()); } void write_advanced_header() { out.printf("accel_x,accel_y,accel_z,gyro_x,gyro_y,gyro_z,mag_x,mag_y,mag_z"); } - void write_advanced(AltosState state) { + double accel_along() { return series.value(AltosFlightSeries.accel_along_name, indices); } + double accel_across() { return series.value(AltosFlightSeries.accel_across_name, indices); } + double accel_through() { return series.value(AltosFlightSeries.accel_through_name, indices); } + + double gyro_roll() { return series.value(AltosFlightSeries.gyro_roll_name, indices); } + double gyro_pitch() { return series.value(AltosFlightSeries.gyro_pitch_name, indices); } + double gyro_yaw() { return series.value(AltosFlightSeries.gyro_yaw_name, indices); } + + double mag_along() { return series.value(AltosFlightSeries.mag_along_name, indices); } + double mag_across() { return series.value(AltosFlightSeries.mag_across_name, indices); } + double mag_through() { return series.value(AltosFlightSeries.mag_through_name, indices); } + + void write_advanced() { out.printf("%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f", - state.accel_along(), state.accel_across(), state.accel_through(), - state.gyro_roll(), state.gyro_pitch(), state.gyro_yaw(), - state.mag_along(), state.mag_across(), state.mag_through()); + accel_along(), accel_across(), accel_through(), + gyro_roll(), gyro_pitch(), gyro_yaw(), + mag_along(), mag_across(), mag_through()); } void write_gps_header() { out.printf("connected,locked,nsat,latitude,longitude,altitude,year,month,day,hour,minute,second,pad_dist,pad_range,pad_az,pad_el,pdop,hdop,vdop"); } - void write_gps(AltosState state) { - AltosGPS gps = state.gps; - if (gps == null) - gps = new AltosGPS(); + void write_gps() { + AltosGPS gps = series.gps_before(series.time(indices)); + + AltosGreatCircle from_pad; - AltosGreatCircle from_pad = state.from_pad; - if (from_pad == null) + if (series.cal_data().gps_pad != null && gps != null) + from_pad = new AltosGreatCircle(series.cal_data().gps_pad, gps); + else from_pad = new AltosGreatCircle(); + if (gps == null) + gps = new AltosGPS(); + out.printf("%2d,%2d,%3d,%12.7f,%12.7f,%8.1f,%5d,%3d,%3d,%3d,%3d,%3d,%9.0f,%9.0f,%4.0f,%4.0f,%6.1f,%6.1f,%6.1f", gps.connected?1:0, gps.locked?1:0, @@ -196,9 +242,9 @@ public class AltosCSV implements AltosWriter { gps.minute, gps.second, from_pad.distance, - state.range, + from_pad.range, from_pad.bearing, - state.elevation, + from_pad.elevation, gps.pdop, gps.hdop, gps.vdop); @@ -212,8 +258,8 @@ public class AltosCSV implements AltosWriter { } } - void write_gps_sat(AltosState state) { - AltosGPS gps = state.gps; + void write_gps_sat() { + AltosGPS gps = series.gps_before(series.time(indices)); for(int i = 1; i <= 32; i++) { int c_n0 = 0; if (gps != null && gps.cc_gps_sat != null) { @@ -230,12 +276,15 @@ public class AltosCSV implements AltosWriter { } void write_companion_header() { +/* out.printf("companion_id,companion_time,companion_update,companion_channels"); for (int i = 0; i < 12; i++) out.printf(",companion_%02d", i); +*/ } - void write_companion(AltosState state) { + void write_companion() { +/* AltosCompanion companion = state.companion; int channels_written = 0; @@ -252,6 +301,7 @@ public class AltosCSV implements AltosWriter { } for (; channels_written < 12; channels_written++) out.printf(",0"); +*/ } void write_header() { @@ -287,63 +337,47 @@ public class AltosCSV implements AltosWriter { out.printf ("\n"); } - void write_one(AltosState state) { - write_general(state); + void write_one() { + write_general(); if (has_flight_state) { out.printf(","); - write_flight(state); + write_flight(); } if (has_basic) { out.printf(","); - write_basic(state); + write_basic(); } if (has_battery) { out.printf(","); - write_battery(state); + write_battery(); } if (has_advanced) { out.printf(","); - write_advanced(state); + write_advanced(); } if (has_gps) { out.printf(","); - write_gps(state); + write_gps(); } if (has_gps_sat) { out.printf(","); - write_gps_sat(state); + write_gps_sat(); } if (has_companion) { out.printf(","); - write_companion(state); + write_companion(); } out.printf ("\n"); } - private void flush_pad() { - while (!pad_states.isEmpty()) { - write_one (pad_states.remove()); - } - } - - private void write(AltosState state) { - if (state.state() == AltosLib.ao_flight_startup) + private void write() { + if (state() == AltosLib.ao_flight_startup) return; if (!header_written) { write_header(); header_written = true; } - if (!seen_boost) { - if (state.state() >= AltosLib.ao_flight_boost) { - seen_boost = true; - boost_tick = state.tick; - flush_pad(); - } - } - if (seen_boost) - write_one(state); - else - pad_states.add(state); + write_one(); } private PrintStream out() { @@ -351,15 +385,15 @@ public class AltosCSV implements AltosWriter { } public void close() { - if (!pad_states.isEmpty()) { - boost_tick = pad_states.element().tick; - flush_pad(); - } out.close(); } - public void write(AltosStateIterable states) { - states.write_comments(out()); + public void write(AltosFlightSeries series) { +// series.write_comments(out()); + + this.series = series; + + series.finish(); has_flight_state = false; has_basic = false; @@ -368,31 +402,37 @@ public class AltosCSV implements AltosWriter { has_gps = false; has_gps_sat = false; has_companion = false; - for (AltosState state : states) { - if (state.state() != AltosLib.ao_flight_stateless && state.state() != AltosLib.ao_flight_invalid && state.state() != AltosLib.ao_flight_startup) - has_flight_state = true; - if (state.acceleration() != AltosLib.MISSING || state.pressure() != AltosLib.MISSING) - has_basic = true; - if (state.battery_voltage != AltosLib.MISSING) - has_battery = true; - if (state.accel_across() != AltosLib.MISSING) - has_advanced = true; - if (state.gps != null) { - has_gps = true; - if (state.gps.cc_gps_sat != null) - has_gps_sat = true; - } - if (state.companion != null) - has_companion = true; + + if (series.has_series(AltosFlightSeries.state_name)) + has_flight_state = true; + if (series.has_series(AltosFlightSeries.accel_name) || series.has_series(AltosFlightSeries.pressure_name)) + has_basic = true; + if (series.has_series(AltosFlightSeries.battery_voltage_name)) + has_battery = true; + if (series.has_series(AltosFlightSeries.accel_across_name)) + has_advanced = true; + + if (series.gps_series != null) + has_gps = true; + if (series.sats_in_view != null) + has_gps_sat = true; + /* + if (state.companion != null) + has_companion = true; + */ + + indices = series.indices(); + + for (;;) { + write(); + if (!series.step_indices(indices)) + break; } - for (AltosState state : states) - write(state); } public AltosCSV(PrintStream in_out, File in_name) { name = in_name; out = in_out; - pad_states = new LinkedList(); } public AltosCSV(File in_name) throws FileNotFoundException { diff --git a/altoslib/AltosCalData.java b/altoslib/AltosCalData.java new file mode 100644 index 00000000..b49e3792 --- /dev/null +++ b/altoslib/AltosCalData.java @@ -0,0 +1,406 @@ +/* + * Copyright © 2017 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altoslib_12; + +/* + * Calibration and other data needed to construct 'real' values from various data + * sources. + */ + +public class AltosCalData { + public int flight = AltosLib.MISSING; + + public void set_flight(int flight) { + if (flight != AltosLib.MISSING) + this.flight = flight; + } + + public String callsign = null; + + public void set_callsign(String callsign) { + if (callsign != null) + this.callsign = callsign; + } + + public String firmware_version = null; + + public void set_firmware_version(String firmware_version) { + if (firmware_version != null) + this.firmware_version = firmware_version; + } + + public String product = null; + + public void set_product(String product) { + if (product != null) + this.product = product; + } + + public int serial = AltosLib.MISSING; + + public void set_serial(int serial) { + if (serial != AltosLib.MISSING) + this.serial = serial; + } + + public int receiver_serial = AltosLib.MISSING; + + public void set_receiver_serial(int receiver_serial) { + if (receiver_serial != AltosLib.MISSING) + this.receiver_serial = receiver_serial; + } + + public int device_type = AltosLib.MISSING; + + public void set_device_type(int device_type) { + if (device_type != AltosLib.MISSING) { + this.device_type = device_type; + if (product == null) + set_product(AltosLib.product_name(device_type)); + } + } + + public int config_major = AltosLib.MISSING; + public int config_minor = AltosLib.MISSING; + public int flight_log_max = AltosLib.MISSING; + + public void set_config(int major, int minor, int log_max) { + if (major != AltosLib.MISSING) + config_major = major; + if (minor != AltosLib.MISSING) + config_minor = minor; + if (log_max != AltosLib.MISSING) + flight_log_max = log_max; + } + + public double apogee_delay = AltosLib.MISSING; + public double main_deploy = AltosLib.MISSING; + + public void set_flight_params(double apogee_delay, double main_deploy) { + if (apogee_delay != AltosLib.MISSING) + this.apogee_delay = apogee_delay; + if (main_deploy != AltosLib.MISSING) + this.main_deploy = main_deploy; + } + + public double accel_plus_g = AltosLib.MISSING; + public double accel_minus_g = AltosLib.MISSING; + public double ground_accel = AltosLib.MISSING; + + public void set_accel_plus_minus(double plus, double minus) { + if (plus != AltosLib.MISSING && minus != AltosLib.MISSING) { + if (plus == minus) + return; + accel_plus_g = plus; + accel_minus_g = minus; + } + } + + public void set_ground_accel(double ground_accel) { + if (ground_accel != AltosLib.MISSING) + this.ground_accel = ground_accel; + } + + /* Raw acceleration value */ + public double accel = AltosLib.MISSING; + + public void set_accel(double accel) { + this.accel = accel; + } + + public boolean mma655x_inverted = false; + + public void set_mma655x_inverted(boolean inverted) { + mma655x_inverted = inverted; + } + + public int pad_orientation = AltosLib.MISSING; + + public void set_pad_orientation(int orientation) { + if (orientation != AltosLib.MISSING) + pad_orientation = orientation; + } + + /* Compute acceleration */ + public double acceleration(double sensor) { + return AltosConvert.acceleration_from_sensor(sensor, accel_plus_g, accel_minus_g, ground_accel); + } + + public AltosMs5607 ms5607 = null; + + public void set_ms5607(AltosMs5607 ms5607) { + this.ms5607 = ms5607; + } + + public double ground_pressure = AltosLib.MISSING; + public double ground_altitude = AltosLib.MISSING; + + public void set_ground_pressure(double ground_pressure) { + if (ground_pressure != AltosLib.MISSING) { + this.ground_pressure = ground_pressure; + this.ground_altitude = AltosConvert.pressure_to_altitude(ground_pressure); + } + } + + public void set_ground_altitude(double ground_altitude) { + if (ground_altitude != AltosLib.MISSING) + this.ground_altitude = ground_altitude; + } + + /* Compute pressure */ + + public AltosPresTemp pressure_ms5607(int raw_pres, int raw_temp) { + if (ms5607 == null) + return new AltosPresTemp(AltosLib.MISSING, AltosLib.MISSING); + return ms5607.pres_temp(raw_pres, raw_temp); + } + + public int tick = AltosLib.MISSING; + private int first_tick = AltosLib.MISSING; + private int prev_tick = AltosLib.MISSING; + + public void set_tick(int tick) { + if (tick != AltosLib.MISSING) { + if (prev_tick != AltosLib.MISSING) { + while (tick < prev_tick - 1000) { + tick += 65536; + } + } + if (first_tick == AltosLib.MISSING) + first_tick = tick; + prev_tick = tick; + this.tick = tick; + } + } + + /* Reset all values which change during flight + */ + public void reset() { + state = AltosLib.MISSING; + tick = AltosLib.MISSING; + prev_tick = AltosLib.MISSING; + temp_gps = null; + prev_gps = null; + temp_gps_sat_tick = AltosLib.MISSING; + accel = AltosLib.MISSING; + } + + public int boost_tick = AltosLib.MISSING; + + public void set_boost_tick() { + boost_tick = tick; + } + + public double ticks_per_sec = 100.0; + + public void set_ticks_per_sec(double ticks_per_sec) { + this.ticks_per_sec = ticks_per_sec; + } + + public double time() { + if (tick == AltosLib.MISSING) + return AltosLib.MISSING; + if (boost_tick != AltosLib.MISSING) + return (tick - boost_tick) / ticks_per_sec; + if (first_tick != AltosLib.MISSING) + return (tick - first_tick) / ticks_per_sec; + return tick / ticks_per_sec; + } + + public double boost_time() { + if (boost_tick == AltosLib.MISSING) + return AltosLib.MISSING; + return boost_tick / ticks_per_sec; + } + + public int state = AltosLib.MISSING; + + public void set_state(int state) { + if (state >= AltosLib.ao_flight_boost && boost_tick == AltosLib.MISSING) + set_boost_tick(); + this.state = state; + } + + public AltosGPS gps_pad = null; + + public double gps_pad_altitude = AltosLib.MISSING; + + public void set_gps(AltosGPS gps) { + if ((state != AltosLib.MISSING && state < AltosLib.ao_flight_boost) || gps_pad == null) + gps_pad = gps; + if (gps_pad_altitude == AltosLib.MISSING && gps.alt != AltosLib.MISSING) + gps_pad_altitude = gps.alt; + } + + /* + * While receiving GPS data, we construct a temporary GPS state + * object and then deliver the result atomically to the listener + */ + AltosGPS temp_gps = null; + AltosGPS prev_gps = null; + int temp_gps_sat_tick = AltosLib.MISSING; + + public AltosGPS temp_gps() { + return temp_gps; + } + + public void reset_temp_gps() { + if (temp_gps != null) { + if (temp_gps.locked && temp_gps.nsat >= 4) + set_gps(temp_gps); + prev_gps = temp_gps; + temp_gps = null; + } + } + + public boolean gps_pending() { + return temp_gps != null; + } + + public AltosGPS make_temp_gps(int tick, boolean sats) { + if (temp_gps == null) { + if (prev_gps != null) + temp_gps = prev_gps.clone(); + else + temp_gps = new AltosGPS(); + } + if (sats) { + if (tick != temp_gps_sat_tick) + temp_gps.cc_gps_sat = null; + temp_gps_sat_tick = tick; + } + return temp_gps; + } + + public double accel_zero_along, accel_zero_across, accel_zero_through; + + public void set_accel_zero(double zero_along, double zero_across, double zero_through) { + if (zero_along != AltosLib.MISSING) { + accel_zero_along = zero_along; + accel_zero_across = zero_across; + accel_zero_through = zero_through; + } + } + + public double accel_along(double counts) { + return AltosIMU.convert_accel(counts - accel_zero_along); + } + + public double accel_across(double counts) { + return AltosIMU.convert_accel(counts - accel_zero_across); + } + + public double accel_through(double counts) { + return AltosIMU.convert_accel(counts - accel_zero_through); + } + + public double gyro_zero_roll, gyro_zero_pitch, gyro_zero_yaw; + + public void set_gyro_zero(double roll, double pitch, double yaw) { + if (roll != AltosLib.MISSING) { + gyro_zero_roll = roll; + gyro_zero_pitch = pitch; + gyro_zero_yaw = yaw; + imu_wrap_checked = false; + } + } + + public double gyro_roll(double counts) { + if (gyro_zero_roll == AltosLib.MISSING || counts == AltosLib.MISSING) + return AltosLib.MISSING; + + return AltosIMU.gyro_degrees_per_second(counts, gyro_zero_roll); + } + + public double gyro_pitch(double counts) { + if (gyro_zero_pitch == AltosLib.MISSING || counts == AltosLib.MISSING) + return AltosLib.MISSING; + return AltosIMU.gyro_degrees_per_second(counts, gyro_zero_pitch); + } + + public double gyro_yaw(double counts) { + if (gyro_zero_yaw == AltosLib.MISSING || counts == AltosLib.MISSING) + return AltosLib.MISSING; + return AltosIMU.gyro_degrees_per_second(counts, gyro_zero_yaw); + } + + private double gyro_zero_overflow(double first) { + double v = first / 128.0; + if (v < 0) + v = Math.ceil(v); + else + v = Math.floor(v); + if (v != 0) + System.out.printf("Adjusting gyro axis by %g steps\n", v); + return v * 128.0; + } + + /* Initial TeleMega log format had only 16 bits for gyro cal, so the top 9 bits got lost as the + * cal data are scaled by 512. Use the first sample to adjust the cal value, assuming that it is + * from a time of fairly low rotation speed. Fixed in later TeleMega firmware by storing 32 bits + * of cal values. + */ + private boolean imu_wrap_checked = false; + + public void check_imu_wrap(double roll, double pitch, double yaw) { + if (!imu_wrap_checked) { + gyro_zero_roll += gyro_zero_overflow(roll); + gyro_zero_pitch += gyro_zero_overflow(pitch); + gyro_zero_yaw += gyro_zero_overflow(yaw); + imu_wrap_checked = true; + } + } + + public double mag_along(double along) { + if (along == AltosLib.MISSING) + return AltosLib.MISSING; + return AltosMag.convert_gauss(along); + } + + public double mag_across(double across) { + if (across == AltosLib.MISSING) + return AltosLib.MISSING; + return AltosMag.convert_gauss(across); + } + + public double mag_through(double through) { + if (through == AltosLib.MISSING) + return AltosLib.MISSING; + return AltosMag.convert_gauss(through); + } + + public AltosCalData() { + } + + public AltosCalData(AltosConfigData config_data) { + set_serial(config_data.serial); + set_ticks_per_sec(100.0); + set_flight(config_data.flight); + set_callsign(config_data.callsign); + set_config(config_data.config_major, config_data.config_minor, config_data.flight_log_max); + set_firmware_version(config_data.version); + set_flight_params(config_data.apogee_delay / ticks_per_sec, config_data.apogee_lockout / ticks_per_sec); + set_pad_orientation(config_data.pad_orientation); + set_product(config_data.product); + set_accel_plus_minus(config_data.accel_cal_plus, config_data.accel_cal_minus); + set_accel_zero(config_data.accel_zero_along, config_data.accel_zero_across, config_data.accel_zero_through); + set_ms5607(config_data.ms5607); + try { + set_mma655x_inverted(config_data.mma655x_inverted()); + } catch (AltosUnknownProduct up) { + } + set_pad_orientation(config_data.pad_orientation); + } +} diff --git a/altoslib/AltosCompanion.java b/altoslib/AltosCompanion.java index 2c03c922..5ce333f8 100644 --- a/altoslib/AltosCompanion.java +++ b/altoslib/AltosCompanion.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; diff --git a/altoslib/AltosConfigData.java b/altoslib/AltosConfigData.java index 23ab1e11..97a80bcb 100644 --- a/altoslib/AltosConfigData.java +++ b/altoslib/AltosConfigData.java @@ -16,13 +16,13 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.util.*; import java.text.*; import java.util.concurrent.*; -public class AltosConfigData implements Iterable { +public class AltosConfigData { /* Version information */ public String manufacturer; @@ -33,9 +33,7 @@ public class AltosConfigData implements Iterable { public int log_space; public String version; public int altitude_32; - - /* Strings returned */ - public LinkedList __lines; + public int config_major, config_minor; /* Config information */ /* HAS_FLIGHT*/ @@ -96,14 +94,13 @@ public class AltosConfigData implements Iterable { public int accel_zero_along, accel_zero_across, accel_zero_through; /* ms5607 data */ - public int ms5607_reserved; - public int ms5607_sens; - public int ms5607_off; - public int ms5607_tcs; - public int ms5607_tco; - public int ms5607_tref; - public int ms5607_tempsens; - public int ms5607_crc; + AltosMs5607 ms5607; + + public AltosMs5607 ms5607() { + if (ms5607 == null) + ms5607 = new AltosMs5607(); + return ms5607; + } public static String get_string(String line, String label) throws ParseException { if (line.startsWith(label)) { @@ -142,21 +139,17 @@ public class AltosConfigData implements Iterable { throw new ParseException("mismatch", 0); } - public Iterator iterator() { - return __lines.iterator(); - } - public int log_space() { - if (log_space > 0) + if (log_space != AltosLib.MISSING) return log_space; - if (storage_size > 0) { + if (storage_size != AltosLib.MISSING) { int space = storage_size; - if (storage_erase_unit > 0 && use_flash_for_config()) + if (storage_erase_unit != AltosLib.MISSING && use_flash_for_config()) space -= storage_erase_unit; - if (space > 0) + if (space != AltosLib.MISSING) return space; } return 0; @@ -214,6 +207,10 @@ public class AltosConfigData implements Iterable { return r; } + public boolean altitude_32() { + return altitude_32 == 1; + } + public int compare_version(String other) { int[] me = parse_version(version); int[] them = parse_version(other); @@ -233,8 +230,6 @@ public class AltosConfigData implements Iterable { } public void reset() { - __lines = new LinkedList(); - manufacturer = null; product = null; serial = AltosLib.MISSING; @@ -242,6 +237,8 @@ public class AltosConfigData implements Iterable { log_format = AltosLib.AO_LOG_FORMAT_UNKNOWN; log_space = AltosLib.MISSING; version = "unknown"; + config_major = AltosLib.MISSING; + config_minor = AltosLib.MISSING; main_deploy = AltosLib.MISSING; apogee_delay = AltosLib.MISSING; @@ -265,8 +262,8 @@ public class AltosConfigData implements Iterable { aes_key = null; - pyro = 0; - npyro = 0; + pyro = AltosLib.MISSING; + npyro = AltosLib.MISSING; pyros = null; pyro_firing_time = AltosLib.MISSING; @@ -289,7 +286,7 @@ public class AltosConfigData implements Iterable { } public void parse_line(String line) { - __lines.add(line); + /* Version replies */ try { manufacturer = get_string(line, "manufacturer"); } catch (Exception e) {} try { product = get_string(line, "product"); } catch (Exception e) {} @@ -302,17 +299,31 @@ public class AltosConfigData implements Iterable { /* Version also contains MS5607 info, which we ignore here */ - try { ms5607_reserved = get_int(line, "ms5607 reserved:"); } catch (Exception e) {} - try { ms5607_sens = get_int(line, "ms5607 sens:"); } catch (Exception e) {} - try { ms5607_off = get_int(line, "ms5607 off:"); } catch (Exception e) {} - try { ms5607_tcs = get_int(line, "ms5607 tcs:"); } catch (Exception e) {} - try { ms5607_tco = get_int(line, "ms5607 tco:"); } catch (Exception e) {} - try { ms5607_tref = get_int(line, "ms5607 tref:"); } catch (Exception e) {} - try { ms5607_tempsens = get_int(line, "ms5607 tempsens:"); } catch (Exception e) {} - try { ms5607_crc = get_int(line, "ms5607 crc:"); } catch (Exception e) {} + try { ms5607().reserved = get_int(line, "ms5607 reserved:"); } catch (Exception e) {} + try { ms5607().sens = get_int(line, "ms5607 sens:"); } catch (Exception e) {} + try { ms5607().off = get_int(line, "ms5607 off:"); } catch (Exception e) {} + try { ms5607().tcs = get_int(line, "ms5607 tcs:"); } catch (Exception e) {} + try { ms5607().tco = get_int(line, "ms5607 tco:"); } catch (Exception e) {} + try { ms5607().tref = get_int(line, "ms5607 tref:"); } catch (Exception e) {} + try { ms5607().tempsens = get_int(line, "ms5607 tempsens:"); } catch (Exception e) {} + try { ms5607().crc = get_int(line, "ms5607 crc:"); } catch (Exception e) {} /* Config show replies */ + try { + if (line.startsWith("Config version")) { + String[] bits = line.split("\\s+"); + if (bits.length >= 3) { + String[] cfg = bits[2].split("\\."); + + if (cfg.length >= 2) { + config_major = Integer.parseInt(cfg[0]); + config_minor = Integer.parseInt(cfg[1]); + } + } + } + } catch (Exception e) {} + /* HAS_FLIGHT */ try { main_deploy = get_int(line, "Main deploy:"); } catch (Exception e) {} try { apogee_delay = get_int(line, "Apogee delay:"); } catch (Exception e) {} @@ -361,7 +372,7 @@ public class AltosConfigData implements Iterable { pyros = new AltosPyro[npyro]; pyro = 0; } catch (Exception e) {} - if (npyro > 0) { + if (npyro != AltosLib.MISSING) { try { AltosPyro p = new AltosPyro(pyro, line); if (pyro < npyro) @@ -425,24 +436,23 @@ public class AltosConfigData implements Iterable { } public boolean has_frequency() { - return radio_frequency >= 0 || radio_setting >= 0 || radio_channel >= 0; + return radio_frequency != AltosLib.MISSING || radio_setting != AltosLib.MISSING || radio_channel != AltosLib.MISSING; } public boolean has_telemetry_rate() { - return telemetry_rate >= 0; + return telemetry_rate != AltosLib.MISSING; } public void set_frequency(double freq) { int frequency = radio_frequency; int setting = radio_setting; - if (frequency > 0) { + if (frequency != AltosLib.MISSING) { radio_frequency = (int) Math.floor (freq * 1000 + 0.5); - radio_channel = -1; - } else if (setting > 0) { - radio_setting =AltosConvert.radio_frequency_to_setting(freq, - radio_calibration); - radio_channel = -1; + radio_channel = AltosLib.MISSING; + } else if (setting != AltosLib.MISSING) { + radio_setting =AltosConvert.radio_frequency_to_setting(freq, radio_calibration); + radio_channel = AltosLib.MISSING; } else { radio_channel = AltosConvert.radio_frequency_to_channel(freq); } @@ -452,12 +462,12 @@ public class AltosConfigData implements Iterable { int channel = radio_channel; int setting = radio_setting; - if (radio_frequency < 0 && channel < 0 && setting < 0) - return -1; + if (radio_frequency == AltosLib.MISSING && channel == AltosLib.MISSING && setting == AltosLib.MISSING) + return AltosLib.MISSING; - if (channel < 0) + if (channel == AltosLib.MISSING) channel = 0; - if (setting < 0) + if (setting == AltosLib.MISSING) setting = 0; return AltosConvert.radio_to_frequency(radio_frequency, @@ -492,56 +502,56 @@ public class AltosConfigData implements Iterable { public void get_values(AltosConfigValues source) throws AltosConfigDataException { /* HAS_FLIGHT */ - if (main_deploy >= 0) + if (main_deploy != AltosLib.MISSING) main_deploy = source.main_deploy(); - if (apogee_delay >= 0) + if (apogee_delay != AltosLib.MISSING) apogee_delay = source.apogee_delay(); - if (apogee_lockout >= 0) + if (apogee_lockout != AltosLib.MISSING) apogee_lockout = source.apogee_lockout(); /* HAS_RADIO */ if (has_frequency()) set_frequency(source.radio_frequency()); - if (radio_enable >= 0) + if (radio_enable != AltosLib.MISSING) radio_enable = source.radio_enable(); if (callsign != null) callsign = source.callsign(); - if (telemetry_rate >= 0) + if (telemetry_rate != AltosLib.MISSING) telemetry_rate = source.telemetry_rate(); /* HAS_ACCEL */ - if (pad_orientation >= 0) + if (pad_orientation != AltosLib.MISSING) pad_orientation = source.pad_orientation(); /* HAS_LOG */ - if (flight_log_max >= 0) + if (flight_log_max != AltosLib.MISSING) flight_log_max = source.flight_log_max(); /* HAS_IGNITE */ - if (ignite_mode >= 0) + if (ignite_mode != AltosLib.MISSING) ignite_mode = source.ignite_mode(); /* AO_PYRO_NUM */ - if (npyro > 0) + if (npyro != AltosLib.MISSING) pyros = source.pyros(); - if (pyro_firing_time >= 0) + if (pyro_firing_time != AltosLib.MISSING) pyro_firing_time = source.pyro_firing_time(); /* HAS_APRS */ - if (aprs_interval >= 0) + if (aprs_interval != AltosLib.MISSING) aprs_interval = source.aprs_interval(); - if (aprs_ssid >= 0) + if (aprs_ssid != AltosLib.MISSING) aprs_ssid = source.aprs_ssid(); - if (aprs_format >= 0) + if (aprs_format != AltosLib.MISSING) aprs_format = source.aprs_format(); /* HAS_BEEP */ - if (beep >= 0) + if (beep != AltosLib.MISSING) beep = source.beep(); /* HAS_TRACKER */ - if (tracker_motion >= 0) + if (tracker_motion != AltosLib.MISSING) tracker_motion = source.tracker_motion(); - if (tracker_interval >= 0) + if (tracker_interval != AltosLib.MISSING) tracker_interval = source.tracker_interval(); } @@ -561,7 +571,7 @@ public class AltosConfigData implements Iterable { if (log_space() == 0) max_enabled = false; - if (log_fixed > 0) + if (log_fixed != AltosLib.MISSING) max_enabled = false; switch (log_format) { @@ -569,7 +579,7 @@ public class AltosConfigData implements Iterable { max_enabled = false; break; default: - if (stored_flight > 0) + if (stored_flight != AltosLib.MISSING) max_enabled = false; break; } @@ -581,7 +591,7 @@ public class AltosConfigData implements Iterable { dest.set_ignite_mode(ignite_mode); dest.set_pad_orientation(pad_orientation); dest.set_callsign(callsign); - if (npyro > 0) + if (npyro != AltosLib.MISSING) dest.set_pyros(pyros); else dest.set_pyros(null); @@ -605,17 +615,17 @@ public class AltosConfigData implements Iterable { public void save(AltosLink link, boolean remote) throws InterruptedException, TimeoutException { /* HAS_FLIGHT */ - if (main_deploy >= 0) + if (main_deploy != AltosLib.MISSING) link.printf("c m %d\n", main_deploy); - if (apogee_delay >= 0) + if (apogee_delay != AltosLib.MISSING) link.printf("c d %d\n", apogee_delay); - if (apogee_lockout >= 0) + if (apogee_lockout != AltosLib.MISSING) link.printf("c L %d\n", apogee_lockout); /* HAS_RADIO */ if (has_frequency()) { - boolean has_frequency = radio_frequency >= 0; - boolean has_setting = radio_setting > 0; + boolean has_frequency = radio_frequency != AltosLib.MISSING; + boolean has_setting = radio_setting != AltosLib.MISSING; double frequency = frequency(); link.set_radio_frequency(frequency, has_frequency, @@ -631,7 +641,7 @@ public class AltosConfigData implements Iterable { } } - if (telemetry_rate >= 0) { + if (telemetry_rate != AltosLib.MISSING) { link.printf("c T %d\n", telemetry_rate); if (remote) { link.flush_output(); @@ -653,12 +663,12 @@ public class AltosConfigData implements Iterable { } } - if (radio_enable >= 0) + if (radio_enable != AltosLib.MISSING) link.printf("c e %d\n", radio_enable); /* HAS_ACCEL */ /* UI doesn't support accel cal */ - if (pad_orientation >= 0) + if (pad_orientation != AltosLib.MISSING) link.printf("c o %d\n", pad_orientation); /* HAS_LOG */ @@ -666,36 +676,36 @@ public class AltosConfigData implements Iterable { link.printf("c l %d\n", flight_log_max); /* HAS_IGNITE */ - if (ignite_mode >= 0) + if (ignite_mode != AltosLib.MISSING) link.printf("c i %d\n", ignite_mode); /* HAS_AES */ /* UI doesn't support AES key config */ /* AO_PYRO_NUM */ - if (npyro > 0) { + if (npyro != AltosLib.MISSING) { for (int p = 0; p < pyros.length; p++) { link.printf("c P %s\n", pyros[p].toString()); } } - if (pyro_firing_time >= 0) + if (pyro_firing_time != AltosLib.MISSING) link.printf("c I %d\n", (int) (pyro_firing_time * 100.0 + 0.5)); /* HAS_APRS */ - if (aprs_interval >= 0) + if (aprs_interval != AltosLib.MISSING) link.printf("c A %d\n", aprs_interval); - if (aprs_ssid >= 0) + if (aprs_ssid != AltosLib.MISSING) link.printf("c S %d\n", aprs_ssid); - if (aprs_format >= 0) + if (aprs_format != AltosLib.MISSING) link.printf("c C %d\n", aprs_format); /* HAS_BEEP */ - if (beep >= 0) + if (beep != AltosLib.MISSING) link.printf("c b %d\n", beep); /* HAS_TRACKER */ - if (tracker_motion >= 0 && tracker_interval >= 0) + if (tracker_motion != AltosLib.MISSING && tracker_interval != AltosLib.MISSING) link.printf("c t %d %d\n", tracker_motion, tracker_interval); /* HAS_GYRO */ diff --git a/altoslib/AltosConfigDataException.java b/altoslib/AltosConfigDataException.java index 59a8e9c1..fe6336b6 100644 --- a/altoslib/AltosConfigDataException.java +++ b/altoslib/AltosConfigDataException.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosConfigDataException extends Exception { diff --git a/altoslib/AltosConfigValues.java b/altoslib/AltosConfigValues.java index bc20d21d..170b1112 100644 --- a/altoslib/AltosConfigValues.java +++ b/altoslib/AltosConfigValues.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public interface AltosConfigValues { /* set and get all of the dialog values */ diff --git a/altoslib/AltosConvert.java b/altoslib/AltosConvert.java index 3489a609..ed16541a 100644 --- a/altoslib/AltosConvert.java +++ b/altoslib/AltosConvert.java @@ -19,11 +19,14 @@ /* * Sensor data conversion functions */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.util.*; public class AltosConvert { + + public static final double gravity = 9.80665; + /* * Pressure Sensor Model, version 1.1 * @@ -44,20 +47,20 @@ public class AltosConvert { * in Joules/(kilogram-Kelvin). */ - public static final double GRAVITATIONAL_ACCELERATION = -9.80665; - public static final double AIR_GAS_CONSTANT = 287.053; - public static final double NUMBER_OF_LAYERS = 7; - public static final double MAXIMUM_ALTITUDE = 84852.0; - public static final double MINIMUM_PRESSURE = 0.3734; - public static final double LAYER0_BASE_TEMPERATURE = 288.15; - public static final double LAYER0_BASE_PRESSURE = 101325; + private static final double GRAVITATIONAL_ACCELERATION = -gravity; + private static final double AIR_GAS_CONSTANT = 287.053; + private static final double NUMBER_OF_LAYERS = 7; + private static final double MAXIMUM_ALTITUDE = 84852.0; + private static final double MINIMUM_PRESSURE = 0.3734; + private static final double LAYER0_BASE_TEMPERATURE = 288.15; + private static final double LAYER0_BASE_PRESSURE = 101325; /* lapse rate and base altitude for each layer in the atmosphere */ - public static final double[] lapse_rate = { + private static final double[] lapse_rate = { -0.0065, 0.0, 0.001, 0.0028, 0.0, -0.0028, -0.002 }; - public static final int[] base_altitude = { + private static final int[] base_altitude = { 0, 11000, 20000, 32000, 47000, 51000, 71000 }; @@ -181,6 +184,18 @@ public class AltosConvert { return altitude; } + public static double degrees_to_radians(double degrees) { + if (degrees == AltosLib.MISSING) + return AltosLib.MISSING; + return degrees * (Math.PI / 180.0); + } + + public static double radians_to_degrees(double radians) { + if (radians == AltosLib.MISSING) + return AltosLib.MISSING; + return radians * (180.0 / Math.PI); + } + public static double cc_battery_to_voltage(double battery) { @@ -188,7 +203,7 @@ public class AltosConvert { } public static double - cc_ignitor_to_voltage(double ignite) + cc_igniter_to_voltage(double ignite) { return ignite / 32767 * 15.0; } @@ -255,7 +270,15 @@ public class AltosConvert { return 3.3 * mega_adc(raw) * (5.1 + 10.0) / 10.0; } - static double easy_mini_voltage(int sensor, int serial) { + static double easy_mini_2_adc(int raw) { + return raw / 4095.0; + } + + static double easy_mini_1_adc(int raw) { + return raw / 32767.0; + } + + static double easy_mini_1_voltage(int sensor, int serial) { double supply = 3.3; double diode_offset = 0.0; @@ -269,7 +292,13 @@ public class AltosConvert { if (serial < 1665) diode_offset = 0.150; - return sensor / 32767.0 * supply * 127/27 + diode_offset; + return easy_mini_1_adc(sensor) * supply * 127/27 + diode_offset; + } + + static double easy_mini_2_voltage(int sensor) { + double supply = 3.3; + + return easy_mini_2_adc(sensor) * supply * 127/27; } public static double radio_to_frequency(int freq, int setting, int cal, int channel) { @@ -307,6 +336,10 @@ public class AltosConvert { return 434.550 + channel * 0.100; } + public static int telem_to_rssi(int telem) { + return telem / 2 - 74; + } + public static int[] ParseHex(String line) { String[] tokens = line.split("\\s+"); int[] array = new int[tokens.length]; @@ -384,6 +417,26 @@ public class AltosConvert { return lb / 0.22480894; } + public static double acceleration_from_sensor(double sensor, double plus_g, double minus_g, double ground) { + + if (sensor == AltosLib.MISSING) + return AltosLib.MISSING; + + if (plus_g == AltosLib.MISSING || minus_g == AltosLib.MISSING) + return AltosLib.MISSING; + + if (ground == AltosLib.MISSING) + ground = plus_g; + + double counts_per_g = (plus_g - minus_g) / 2.0; + double counts_per_mss = counts_per_g / gravity; + + if (counts_per_mss == 0) + return AltosLib.MISSING; + + return (sensor - ground) / counts_per_mss; + } + public static boolean imperial_units = false; public static AltosDistance distance = new AltosDistance(); @@ -408,6 +461,14 @@ public class AltosConvert { public static AltosLongitude longitude = new AltosLongitude(); + public static AltosRotationRate rotation_rate = new AltosRotationRate(); + + public static AltosStateName state_name = new AltosStateName(); + + public static AltosPyroName pyro_name = new AltosPyroName(); + + public static AltosUnits magnetic_field = null; + public static String show_gs(String format, double a) { a = meters_to_g(a); format = format.concat(" g"); diff --git a/altoslib/AltosDataListener.java b/altoslib/AltosDataListener.java new file mode 100644 index 00000000..5f89b3e4 --- /dev/null +++ b/altoslib/AltosDataListener.java @@ -0,0 +1,95 @@ +/* + * Copyright © 2017 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altoslib_12; + +public abstract class AltosDataListener { + + private AltosCalData cal_data = null; + + public double time = AltosLib.MISSING; + public int state = AltosLib.MISSING; + + public void set_tick(int tick) { + cal_data.set_tick(tick); + set_time(cal_data.time()); + } + + public AltosCalData cal_data() { + if (cal_data == null) + cal_data = new AltosCalData(); + return cal_data; + } + + public void set_time(double time) { + if (time != AltosLib.MISSING) + this.time = time; + } + + public void set_serial(int serial) { + cal_data().set_serial(serial); + } + + public double time() { + return time; + } + + public void set_state(int state) { + cal_data().set_state(state); + if (state != AltosLib.MISSING) + this.state = state; + } + + public void set_flight(int flight) { + cal_data().set_flight(flight); + } + + /* Called after all records are captured */ + public void finish() { + } + + public abstract void set_rssi(int rssi, int status); + public abstract void set_received_time(long received_time); + + public abstract void set_acceleration(double accel); + public abstract void set_pressure(double pa); + public abstract void set_thrust(double N); + + public abstract void set_kalman(double height, double speed, double accel); + + public abstract void set_temperature(double deg_c); + public abstract void set_battery_voltage(double volts); + + public abstract void set_apogee_voltage(double volts); + public abstract void set_main_voltage(double volts); + + public abstract void set_gps(AltosGPS gps); + + public abstract void set_orient(double orient); + public abstract void set_gyro(double roll, double pitch, double yaw); + public abstract void set_accel_ground(double along, double across, double through); + public abstract void set_accel(double along, double across, double through); + public abstract void set_mag(double along, double across, double through); + public abstract void set_pyro_voltage(double volts); + public abstract void set_igniter_voltage(double[] voltage); + public abstract void set_pyro_fired(int pyro_mask); + public abstract void set_companion(AltosCompanion companion); + + public AltosDataListener() { + } + + public AltosDataListener(AltosCalData cal_data) { + this.cal_data = cal_data; + } +} diff --git a/altoslib/AltosDataProvider.java b/altoslib/AltosDataProvider.java new file mode 100644 index 00000000..9589a8e6 --- /dev/null +++ b/altoslib/AltosDataProvider.java @@ -0,0 +1,23 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_12; + +public interface AltosDataProvider { + public void provide_data(AltosDataListener listener) throws InterruptedException, AltosUnknownProduct; +} diff --git a/altoslib/AltosDebug.java b/altoslib/AltosDebug.java index aa1b298f..24a25933 100644 --- a/altoslib/AltosDebug.java +++ b/altoslib/AltosDebug.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; diff --git a/altoslib/AltosDistance.java b/altoslib/AltosDistance.java index 0239c5ce..38efbf1a 100644 --- a/altoslib/AltosDistance.java +++ b/altoslib/AltosDistance.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosDistance extends AltosUnits { @@ -96,7 +96,7 @@ public class AltosDistance extends AltosUnits { } }; - range_imperial[1] = new AltosUnitsRange(AltosConvert.feet_to_meters(1000), + range_imperial[1] = new AltosUnitsRange(AltosConvert.feet_to_meters(5280), "mi", "miles") { double value(double v) { return AltosConvert.meters_to_miles(v); diff --git a/altoslib/AltosEeprom.java b/altoslib/AltosEeprom.java index 6ed14d3a..ad7bf881 100644 --- a/altoslib/AltosEeprom.java +++ b/altoslib/AltosEeprom.java @@ -1,132 +1,291 @@ /* - * Copyright © 2013 Keith Packard + * Copyright © 2017 Keith Packard * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; -import java.io.*; import java.util.*; -import java.text.*; +import java.io.*; + +public class AltosEeprom { -public abstract class AltosEeprom implements AltosStateUpdate { - public int cmd; - public int tick; - public int data8[]; - public boolean valid; + private AltosJson config; + ArrayList data; + private AltosConfigData config_data; - public int data8(int i) { - return data8[i]; + /* + * Public accessor APIs + */ + public int data8(int offset) { + return ((int) data.get(offset)) & 0xff; } - public int data16(int i) { - return ((data8[i] | (data8[i+1] << 8)) << 16) >> 16; + public int data16(int offset) { + return data8(offset) | (data8(offset+1) << 8); } - public int data24(int i) { - return data8[i] | (data8[i+1] << 8) | (data8[i+2] << 16); + public int data24(int offset) { + return (data8(offset) | + (data8(offset+1) << 8) | + (data8(offset+2) << 16)); } - public int data32(int i) { - return data8[i] | (data8[i+1] << 8) | (data8[i+2] << 16) | (data8[i+3] << 24); + public int data32(int offset) { + return (data8(offset) | + (data8(offset+1) << 8) | + (data8(offset+2) << 16) | + (data8(offset+3) << 24)); } - public boolean has_seconds() { return false; } + public int size() { + return data.size(); + } - public int seconds() { return 0; } + public AltosConfigData config_data() { + if (config_data == null) { + config_data = (AltosConfigData) config.make(AltosConfigData.class); + if (config_data == null) + config_data = new AltosConfigData(); - public final static int header_length = 4; + if (config_data.log_format == AltosLib.AO_LOG_FORMAT_UNKNOWN) { + config_data.log_format = AltosLib.AO_LOG_FORMAT_FULL; + if (config_data.product != null) { + if (config_data.product.startsWith("TeleMetrum")) + config_data.log_format = AltosLib.AO_LOG_FORMAT_FULL; + else if (config_data.product.startsWith("TeleMini")) + config_data.log_format = AltosLib.AO_LOG_FORMAT_TINY; + } + } + } + return config_data; + } + + private void write_config(Writer w) throws IOException { + config.write(w, 0, true); + w.append('\n'); + } + + /* + * Private I/O APIs + */ + private void write_data(Writer w) throws IOException { + PrintWriter pw = new PrintWriter(w); - public abstract int record_length(); + for (int i = 0; i < data.size(); i++) { + if (i > 0) { + if ((i & 0x1f) == 0) + pw.printf("\n"); + else + pw.printf(" "); + } + pw.printf("%02x", data.get(i)); + } + w.append('\n'); + } - public void update_state(AltosState state) { - if (cmd == AltosLib.AO_LOG_FLIGHT) - state.set_boost_tick(tick); - else - state.set_tick(tick); + private boolean read_config(InputStream stream) throws IOException { + config = AltosJson.fromInputStream(stream); + if (config == null) + return false; + return true; } - 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]); + private String read_line(InputStream stream) throws IOException { + StringBuffer buffer = null; + int c; + + for (;;) { + c = stream.read(); + if (c == -1 && buffer == null) + return null; + if (buffer == null) + buffer = new StringBuffer(); + if (c == -1 || c == '\n') + return buffer.toString(); + buffer.append((char) c); } - out.printf ("\n"); } - public String string() { - String s; + private boolean read_data(InputStream stream) throws IOException { + String s; + + data = new ArrayList(); + while ((s = read_line(stream)) != null) { - 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); + String[] tokens = s.split("\\s+"); + + for (int i = 0; i < tokens.length; i++) { + if (tokens[i].length() > 0) { + try { + data.add((byte) AltosLib.fromhex(tokens[i])); + } catch (NumberFormatException e) { + throw new IOException(e.toString()); + } + } } } - s = s.concat("\n"); - return s; + return true; } - void parse_chunk(AltosEepromChunk chunk, int start) throws ParseException { - cmd = chunk.data(start); + private boolean read_old_config(InputStream stream) throws IOException { + AltosConfigData cfg = new AltosConfigData(); + for (;;) { + boolean done = false; - int data_length = record_length() - header_length; + /* The data starts with an upper case F character followed by a space */ + stream.mark(2); + int first = stream.read(); + if (first == 'F') { + int second = stream.read(); + if (second == ' ') + done = true; + } + stream.reset(); + if (done) + break; - 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; + String line = read_line(stream); + if (line == null) + return false; + cfg.parse_line(line); } + config = new AltosJson(cfg); + return true; + } - tick = chunk.data16(start+2); + private boolean read_old_data(InputStream stream) throws IOException { + String line; - data8 = new int[data_length]; - for (int i = 0; i < data_length; i++) - data8[i] = chunk.data(start + header_length + i); - } + data = new ArrayList(); + while ((line = read_line(stream)) != null) { + String[] tokens = line.split("\\s+"); - void parse_string(String line) { - valid = false; - tick = 0; - cmd = AltosLib.AO_LOG_INVALID; + /* Make sure there's at least a type and time */ + if (tokens.length < 2) + break; - int data_length = record_length() - header_length; + /* packet type */ + if (tokens[0].length() != 1) + break; + int start = data.size(); - if (line == null) - return; - try { - String[] tokens = line.split("\\s+"); + if (config_data().log_format != AltosLib.AO_LOG_FORMAT_TINY) { + byte cmd = (byte) tokens[0].codePointAt(0); + data.add(cmd); - 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]; + int time = AltosLib.fromhex(tokens[1]); - for (int i = 0; i < data_length; i++) - data8[i] = Integer.parseInt(tokens[2 + i],16); + data.add((byte) 0); + data.add((byte) (time & 0xff)); + data.add((byte) (time >> 8)); + } + if (tokens.length == 4) { + /* Handle ancient log files */ + if (config_data().log_format == AltosLib.AO_LOG_FORMAT_TINY) { + /* + * Ancient TeleMini log files stored "extra" data to pretend + * that it was a TeleMetrum device. Throw that away and + * just save the actual log data. + */ + int a = AltosLib.fromhex(tokens[2]); + int b = AltosLib.fromhex(tokens[3]); + if (a != 0) + b = 0x8000 | a; + data.add((byte) (b & 0xff)); + data.add((byte) ((b >> 8))); + } else { + for (int i = 2; i < tokens.length; i++) { + int v = AltosLib.fromhex(tokens[i]); + data.add((byte) (v & 0xff)); + data.add((byte) ((v >> 8))); + } + /* Re-compute the checksum byte */ + data.set(start + 1, (byte) (256 - AltosConvert.checksum(data, start, data.size() - start))); } + } else { + for (int i = 2; i < tokens.length; i++) + data.add((byte) AltosLib.fromhex(tokens[i])); + /* Re-compute the checksum byte */ + data.set(start + 1, (byte) (256 - AltosConvert.checksum(data, start, data.size() - start))); } - } catch (NumberFormatException ne) { } + return true; + } + + private void read(InputStream stream) throws IOException { + BufferedInputStream bis = new BufferedInputStream(stream); + + bis.mark(1); + int c = bis.read(); + bis.reset(); + + if (c == '{') { + if (!read_config(bis)) + throw new IOException("failed to read config"); + if (!read_data(bis)) + throw new IOException("failed to read data"); + } else { + if (!read_old_config(bis)) + throw new IOException("failed to read old config"); + if (!read_old_data(bis)) + throw new IOException("failed to read old data"); + } + } + + /* + * Public APIs for I/O + */ + public void write(Writer w) throws IOException { + write_config(w); + write_data(w); + } + + public String toString() { + try { + Writer w = new StringWriter(); + + write(w); + return w.toString(); + } catch (Exception e) { + return null; + } + } + + public void print() throws IOException { + System.out.printf("%s", toString()); + } + + /* + * Constructors + */ + public AltosEeprom(InputStream stream) throws IOException { + read(stream); + } + + public AltosEeprom(String s) throws IOException { + read(new AltosStringInputStream(s)); + } + + public AltosEeprom(AltosJson config, ArrayList data) { + this.config = config; + this.data = data; + } + + public AltosEeprom(AltosConfigData config_data, ArrayList data) { + this.config = new AltosJson(config_data); + this.data = data; + } + + public AltosEeprom() { } } diff --git a/altoslib/AltosEepromChunk.java b/altoslib/AltosEepromChunk.java index 1deb0ded..4f12c190 100644 --- a/altoslib/AltosEepromChunk.java +++ b/altoslib/AltosEepromChunk.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.text.*; import java.util.concurrent.*; diff --git a/altoslib/AltosEepromDownload.java b/altoslib/AltosEepromDownload.java index 74912ed4..33f0dd17 100644 --- a/altoslib/AltosEepromDownload.java +++ b/altoslib/AltosEepromDownload.java @@ -16,13 +16,60 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.util.*; import java.text.*; import java.util.concurrent.*; +class AltosEepromNameData extends AltosDataListener { + AltosGPS gps = null; + + public void set_rssi(int rssi, int status) { } + public void set_received_time(long received_time) { } + + public void set_acceleration(double accel) { } + public void set_pressure(double pa) { } + public void set_thrust(double N) { } + + public void set_temperature(double deg_c) { } + public void set_battery_voltage(double volts) { } + + public void set_apogee_voltage(double volts) { } + public void set_main_voltage(double volts) { } + + public void set_gps(AltosGPS gps) { + if (gps != null && + gps.year != AltosLib.MISSING && + gps.month != AltosLib.MISSING && + gps.day != AltosLib.MISSING) { + this.gps = gps; + } + } + + public boolean done() { + if (gps == null) + return false; + return true; + } + + public void set_gyro(double roll, double pitch, double yaw) { } + public void set_accel_ground(double along, double across, double through) { } + public void set_accel(double along, double across, double through) { } + public void set_mag(double along, double across, double through) { } + public void set_pyro_voltage(double volts) { } + public void set_igniter_voltage(double[] voltage) { } + public void set_pyro_fired(int pyro_mask) { } + public void set_companion(AltosCompanion companion) { } + public void set_kalman(double height, double speed, double acceleration) { } + public void set_orient(double new_orient) { } + + public AltosEepromNameData(AltosCalData cal_data) { + super(cal_data); + } +} + public class AltosEepromDownload implements Runnable { AltosLink link; @@ -45,11 +92,11 @@ public class AltosEepromDownload implements Runnable { gps.day != AltosLib.MISSING; } - private AltosFile MakeFile(int serial, int flight, AltosState state) throws IOException { + private AltosFile MakeFile(int serial, int flight, AltosEepromNameData name_data) throws IOException { AltosFile eeprom_name; - if (has_gps_date(state)) { - AltosGPS gps = state.gps; + if (name_data.gps != null) { + AltosGPS gps = name_data.gps; eeprom_name = new AltosFile(gps.year, gps.month, gps.day, serial, flight, "eeprom"); } else @@ -134,24 +181,23 @@ public class AltosEepromDownload implements Runnable { } /* Construct our internal representation of the eeprom data */ - AltosEepromNew eeprom = new AltosEepromNew(flights.config_data, data); + AltosEeprom eeprom = new AltosEeprom(flights.config_data, data); /* Now see if we can't actually parse the resulting * file to generate a better filename. Note that this * doesn't need to work; we'll still save the data using * a less accurate name. */ - AltosEepromRecordSet set = new AltosEepromRecordSet(eeprom); - - AltosState state = new AltosState(); + AltosEepromRecordSet set = new AltosEepromRecordSet(eeprom); + AltosEepromNameData name_data = new AltosEepromNameData(set.cal_data()); - for (AltosState s : set) { - state = s; - if (state.gps != null) + for (AltosEepromRecord record : set.ordered) { + record.provide_data(name_data, set.cal_data()); + if (name_data.done()) break; } - AltosFile f = MakeFile(flights.config_data.serial, log.flight, state); + AltosFile f = MakeFile(flights.config_data.serial, log.flight, name_data); monitor.set_filename(f.toString()); diff --git a/altoslib/AltosEepromFile.java b/altoslib/AltosEepromFile.java index 4606e780..067f0302 100644 --- a/altoslib/AltosEepromFile.java +++ b/altoslib/AltosEepromFile.java @@ -16,20 +16,16 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.util.*; import java.text.*; -public class AltosEepromFile extends AltosStateIterable { +public class AltosEepromFile implements AltosRecordSet { AltosEepromRecordSet set; - public AltosConfigData config_data() { - return set.eeprom.config_data(); - } - public void write_comments(PrintStream out) { } @@ -37,11 +33,19 @@ public class AltosEepromFile extends AltosStateIterable { out.printf("%s\n", set.eeprom.toString()); } - public AltosEepromFile(Reader input) throws IOException { + public AltosEepromFile(InputStream input) throws IOException { set = new AltosEepromRecordSet(input); } - public Iterator iterator() { - return set.iterator(); + public AltosConfigData config_data() { + return set.config_data(); + } + + public AltosCalData cal_data() { + return set.cal_data(); + } + + public void capture_series(AltosDataListener series) { + set.capture_series(series); } } diff --git a/altoslib/AltosEepromList.java b/altoslib/AltosEepromList.java index fc72fd95..55d47e20 100644 --- a/altoslib/AltosEepromList.java +++ b/altoslib/AltosEepromList.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.util.*; diff --git a/altoslib/AltosEepromLog.java b/altoslib/AltosEepromLog.java index 63e4a1f8..8d1f3fc4 100644 --- a/altoslib/AltosEepromLog.java +++ b/altoslib/AltosEepromLog.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.text.*; import java.util.concurrent.*; diff --git a/altoslib/AltosEepromMonitor.java b/altoslib/AltosEepromMonitor.java index 250568ac..a99ec687 100644 --- a/altoslib/AltosEepromMonitor.java +++ b/altoslib/AltosEepromMonitor.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public interface AltosEepromMonitor { diff --git a/altoslib/AltosEepromNew.java b/altoslib/AltosEepromNew.java deleted file mode 100644 index 4e3ee416..00000000 --- a/altoslib/AltosEepromNew.java +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright © 2017 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - */ - -package org.altusmetrum.altoslib_11; - -import java.util.*; -import java.io.*; - -public class AltosEepromNew { - - private AltosJson config; - ArrayList data; - private AltosConfigData config_data; - - /* - * Public accessor APIs - */ - public int data8(int offset) { - return ((int) data.get(offset)) & 0xff; - } - - public int data16(int offset) { - return data8(offset) | (data8(offset+1) << 8); - } - - public int data24(int offset) { - return (data8(offset) | - (data8(offset+1) << 8) | - (data8(offset+2) << 16)); - } - - public int data32(int offset) { - return (data8(offset) | - (data8(offset+1) << 8) | - (data8(offset+2) << 16) | - (data8(offset+3) << 24)); - } - - public int size() { - return data.size(); - } - - public AltosConfigData config_data() { - if (config_data == null) { - config_data = (AltosConfigData) config.make(AltosConfigData.class); - if (config_data == null) - config_data = new AltosConfigData(); - - if (config_data.log_format == AltosLib.AO_LOG_FORMAT_UNKNOWN) { - config_data.log_format = AltosLib.AO_LOG_FORMAT_FULL; - if (config_data.product != null) { - if (config_data.product.startsWith("TeleMetrum")) - config_data.log_format = AltosLib.AO_LOG_FORMAT_FULL; - else if (config_data.product.startsWith("TeleMini")) - config_data.log_format = AltosLib.AO_LOG_FORMAT_TINY; - } - } - } - return config_data; - } - - public void reset_config_data() { - config_data = null; - } - - private void write_config(Writer w) throws IOException { - config.write(w, 0, true); - w.append('\n'); - } - - /* - * Private I/O APIs - */ - private void write_data(Writer w) throws IOException { - PrintWriter pw = new PrintWriter(w); - - for (int i = 0; i < data.size(); i++) { - if (i > 0) { - if ((i & 0x1f) == 0) - pw.printf("\n"); - else - pw.printf(" "); - } - pw.printf("%02x", data.get(i)); - } - w.append('\n'); - } - - private boolean read_config(Reader r) throws IOException { - config = AltosJson.fromReader(r); - if (config == null) - return false; - return true; - } - - private boolean read_data(Reader r) throws IOException { - BufferedReader br = new BufferedReader(r); - String s; - - data = new ArrayList(); - while ((s = br.readLine()) != null) { - - String[] tokens = s.split("\\s+"); - - for (int i = 0; i < tokens.length; i++) { - if (tokens[i].length() > 0) { - try { - data.add((byte) AltosLib.fromhex(tokens[i])); - } catch (NumberFormatException e) { - throw new IOException(e.toString()); - } - } - } - } - return true; - } - - private boolean read_old_config(BufferedReader r) throws IOException { - AltosConfigData cfg = new AltosConfigData(); - for (;;) { - boolean done = false; - - /* The data starts with an upper case F character followed by a space */ - r.mark(2); - int first = r.read(); - if (first == 'F') { - int second = r.read(); - if (second == ' ') - done = true; - } - r.reset(); - if (done) - break; - - String line = r.readLine(); - if (line == null) - return false; - cfg.parse_line(line); - } - config = new AltosJson(cfg); - return true; - } - - private boolean read_old_data(BufferedReader r) throws IOException { - String line; - - data = new ArrayList(); - while ((line = r.readLine()) != null) { - String[] tokens = line.split("\\s+"); - - /* Make sure there's at least a type and time */ - if (tokens.length < 2) - break; - - /* packet type */ - if (tokens[0].length() != 1) - break; - int start = data.size(); - - if (config_data().log_format != AltosLib.AO_LOG_FORMAT_TINY) { - data.add((byte) tokens[0].codePointAt(0)); - - int time = AltosLib.fromhex(tokens[1]); - - data.add((byte) 0); - data.add((byte) (time & 0xff)); - data.add((byte) (time >> 8)); - } - if (tokens.length == 4) { - /* Handle ancient log files */ - if (config_data().log_format == AltosLib.AO_LOG_FORMAT_TINY) { - /* - * Ancient TeleMini log files stored "extra" data to pretend - * that it was a TeleMetrum device. Throw that away and - * just save the actual log data. - */ - int a = AltosLib.fromhex(tokens[2]); - int b = AltosLib.fromhex(tokens[3]); - if (a != 0) - b = 0x8000 | a; - data.add((byte) (b & 0xff)); - data.add((byte) ((b >> 8))); - } else { - for (int i = 2; i < tokens.length; i++) { - int v = AltosLib.fromhex(tokens[i]); - data.add((byte) (v & 0xff)); - data.add((byte) ((v >> 8))); - } - /* Re-compute the checksum byte */ - data.set(start + 1, (byte) (256 - AltosConvert.checksum(data, start, data.size() - start))); - } - } else { - for (int i = 2; i < tokens.length; i++) - data.add((byte) AltosLib.fromhex(tokens[i])); - /* Re-compute the checksum byte */ - data.set(start + 1, (byte) (256 - AltosConvert.checksum(data, start, data.size() - start))); - } - } - return true; - } - - private void read(Reader r) throws IOException { - BufferedReader br = new BufferedReader(r); - - br.mark(1); - int c = br.read(); - br.reset(); - - if (c == '{') { - if (!read_config(br)) - throw new IOException("failed to read config"); - if (!read_data(br)) - throw new IOException("failed to read data"); - } else { - if (!read_old_config(br)) - throw new IOException("failed to read old config"); - if (!read_old_data(br)) - throw new IOException("failed to read old data"); - } - } - - /* - * Public APIs for I/O - */ - public void write(Writer w) throws IOException { - write_config(w); - write_data(w); - } - - public String toString() { - try { - Writer w = new StringWriter(); - - write(w); - return w.toString(); - } catch (Exception e) { - return null; - } - } - - public void print() throws IOException { - System.out.printf("%s", toString()); - } - - /* - * Constructors - */ - public AltosEepromNew(Reader r) throws IOException { - read(r); - } - - public AltosEepromNew(String s) throws IOException { - read(new StringReader(s)); - } - - public AltosEepromNew(AltosJson config, ArrayList data) { - this.config = config; - this.data = data; - } - - public AltosEepromNew(AltosConfigData config_data, ArrayList data) { - this.config = new AltosJson(config_data); - this.data = data; - } - - public AltosEepromNew() { - } -} diff --git a/altoslib/AltosEepromRecord.java b/altoslib/AltosEepromRecord.java index c0edb952..094584fe 100644 --- a/altoslib/AltosEepromRecord.java +++ b/altoslib/AltosEepromRecord.java @@ -12,12 +12,11 @@ * General Public License for more details. */ -package org.altusmetrum.altoslib_11; - +package org.altusmetrum.altoslib_12; public abstract class AltosEepromRecord implements Comparable { - AltosEepromNew eeprom; + AltosEeprom eeprom; int wide_tick; @@ -65,30 +64,44 @@ public abstract class AltosEepromRecord implements Comparable return 1; } + public AltosConfigData config_data() { + return eeprom.config_data(); + } + public int compareTo(AltosEepromRecord o) { int cmd_diff = cmdi() - o.cmdi(); if (cmd_diff != 0) return cmd_diff; - int tick_diff = tick() - o.tick(); + int tick_diff = wide_tick - o.wide_tick; if (tick_diff != 0) return tick_diff; return start - o.start; } - public void update_state(AltosState state) { + /* AltosDataProvider */ + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + cal_data.set_tick(tick()); if (cmd() == AltosLib.AO_LOG_FLIGHT) - state.set_boost_tick(tick()); - else - state.set_tick(tick()); + cal_data.set_boost_tick(); + listener.set_time(cal_data.time()); + + /* Flush any pending GPS changes */ + if (!AltosLib.is_gps_cmd(cmd())) { + AltosGPS gps = cal_data.temp_gps(); + if (gps != null) { + listener.set_gps(gps); + cal_data.reset_temp_gps(); + } + } } public int next_start() { int s = start + length; - while (s + length < eeprom.data.size()) { + while (s + length <= eeprom.data.size()) { if (valid(s)) return s; s += length; @@ -102,7 +115,7 @@ public abstract class AltosEepromRecord implements Comparable public abstract AltosEepromRecord next(); - public AltosEepromRecord(AltosEepromNew eeprom, int start, int length) { + public AltosEepromRecord(AltosEeprom eeprom, int start, int length) { this.eeprom = eeprom; this.start = start; this.length = length; diff --git a/altoslib/AltosEepromRecordFireTwo.java b/altoslib/AltosEepromRecordFireTwo.java index 8c03cd56..d6b74d1b 100644 --- a/altoslib/AltosEepromRecordFireTwo.java +++ b/altoslib/AltosEepromRecordFireTwo.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.util.*; @@ -68,21 +68,19 @@ public class AltosEepromRecordFireTwo extends AltosEepromRecord { return AltosConvert.lb_to_n(v * 298 * 9.807); } - public void update_state(AltosState state) { - super.update_state(state); + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + super.provide_data(listener, cal_data); switch (cmd()) { case AltosLib.AO_LOG_FLIGHT: - state.set_flight(flight()); - state.set_ground_pressure(0.0); - state.set_accel_g(0, -1); + cal_data.set_flight(flight()); break; case AltosLib.AO_LOG_STATE: - state.set_state(state()); + listener.set_state(state()); break; case AltosLib.AO_LOG_SENSOR: - state.set_pressure(adc_to_pa(pres())); - state.set_accel(adc_to_n(thrust())); + listener.set_pressure(adc_to_pa(pres())); + listener.set_thrust(adc_to_n(thrust())); break; } } @@ -94,11 +92,11 @@ public class AltosEepromRecordFireTwo extends AltosEepromRecord { return new AltosEepromRecordFireTwo(eeprom, s); } - public AltosEepromRecordFireTwo(AltosEepromNew eeprom, int start) { + public AltosEepromRecordFireTwo(AltosEeprom eeprom, int start) { super(eeprom, start, record_length); } - public AltosEepromRecordFireTwo(AltosEepromNew eeprom) { + public AltosEepromRecordFireTwo(AltosEeprom eeprom) { this(eeprom, 0); } } diff --git a/altoslib/AltosEepromRecordFull.java b/altoslib/AltosEepromRecordFull.java index fbb8fbd9..85709f73 100644 --- a/altoslib/AltosEepromRecordFull.java +++ b/altoslib/AltosEepromRecordFull.java @@ -12,7 +12,7 @@ * General Public License for more details. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosEepromRecordFull extends AltosEepromRecord { public static final int record_length = 8; @@ -21,53 +21,39 @@ public class AltosEepromRecordFull extends AltosEepromRecord { public static final int two_g_default = 16294 - 15758; - public void update_state(AltosState state) { - super.update_state(state); - AltosGPS gps; + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { - /* 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; - } - } + super.provide_data(listener, cal_data); + AltosGPS gps; switch (cmd()) { case AltosLib.AO_LOG_FLIGHT: - state.set_state(AltosLib.ao_flight_pad); - state.set_ground_accel(data16(0)); - state.set_flight(data16(2)); - if (state.accel_plus_g == AltosLib.MISSING) - state.set_accel_g(data16(0), data16(0) + two_g_default); + listener.set_state(AltosLib.ao_flight_pad); + cal_data.set_ground_accel(data16(0)); + cal_data.set_flight(data16(2)); + if (cal_data.accel_plus_g == AltosLib.MISSING) + cal_data.set_accel_plus_minus(data16(0), data16(0) + two_g_default); break; case AltosLib.AO_LOG_SENSOR: - state.set_accel(data16(0)); - state.set_pressure(AltosConvert.barometer_to_pressure(data16(2))); + listener.set_acceleration(cal_data.acceleration(data16(0))); + listener.set_pressure(AltosConvert.barometer_to_pressure(data16(2))); break; case AltosLib.AO_LOG_PRESSURE: - state.set_pressure(AltosConvert.barometer_to_pressure(data16(2))); + listener.set_pressure(AltosConvert.barometer_to_pressure(data16(2))); break; case AltosLib.AO_LOG_TEMP_VOLT: - state.set_temperature(AltosConvert.thermometer_to_temperature(data16(0))); - state.set_battery_voltage(AltosConvert.cc_battery_to_voltage(data16(2))); + listener.set_temperature(AltosConvert.thermometer_to_temperature(data16(0))); + listener.set_battery_voltage(AltosConvert.cc_battery_to_voltage(data16(2))); break; case AltosLib.AO_LOG_DEPLOY: - state.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(data16(0))); - state.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(data16(2))); + listener.set_apogee_voltage(AltosConvert.cc_igniter_to_voltage(data16(0))); + listener.set_main_voltage(AltosConvert.cc_igniter_to_voltage(data16(2))); break; case AltosLib.AO_LOG_STATE: - state.set_state(data16(0)); + listener.set_state(data16(0)); break; case AltosLib.AO_LOG_GPS_TIME: - gps = state.make_temp_gps(false); + gps = cal_data.make_temp_gps(tick(),false); gps.hour = data8(0); gps.minute = data8(1); @@ -81,29 +67,29 @@ public class AltosEepromRecordFull extends AltosEepromRecord { AltosLib.AO_GPS_NUM_SAT_SHIFT; break; case AltosLib.AO_LOG_GPS_LAT: - gps = state.make_temp_gps(false); + gps = cal_data.make_temp_gps(tick(),false); int lat32 = data32(0); gps.lat = (double) lat32 / 1e7; break; case AltosLib.AO_LOG_GPS_LON: - gps = state.make_temp_gps(false); + gps = cal_data.make_temp_gps(tick(),false); int lon32 = data32(0); gps.lon = (double) lon32 / 1e7; break; case AltosLib.AO_LOG_GPS_ALT: - gps = state.make_temp_gps(false); + gps = cal_data.make_temp_gps(tick(),false); gps.alt = data16(0); break; case AltosLib.AO_LOG_GPS_SAT: - gps = state.make_temp_gps(true); + gps = cal_data.make_temp_gps(tick(),true); int svid = data16(0); int c_n0 = data16(3); gps.add_sat(svid, c_n0); break; case AltosLib.AO_LOG_GPS_DATE: - gps = state.make_temp_gps(false); + gps = cal_data.make_temp_gps(tick(),false); gps.year = data8(0) + 2000; gps.month = data8(1); gps.day = data8(2); @@ -118,11 +104,11 @@ public class AltosEepromRecordFull extends AltosEepromRecord { return new AltosEepromRecordFull(eeprom, s); } - public AltosEepromRecordFull(AltosEepromNew eeprom, int start) { + public AltosEepromRecordFull(AltosEeprom eeprom, int start) { super(eeprom, start, record_length); } - public AltosEepromRecordFull(AltosEepromNew eeprom) { + public AltosEepromRecordFull(AltosEeprom eeprom) { this(eeprom, 0); } } diff --git a/altoslib/AltosEepromRecordGps.java b/altoslib/AltosEepromRecordGps.java index 1312d3ec..5cf5db39 100644 --- a/altoslib/AltosEepromRecordGps.java +++ b/altoslib/AltosEepromRecordGps.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.util.*; @@ -71,36 +71,19 @@ public class AltosEepromRecordGps extends AltosEepromRecord { return start - o.start; } - public void update_state(AltosState state) { - super.update_state(state); - - AltosGPS gps; - - /* Flush any pending RecordGps 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; - } - } + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + super.provide_data(listener, cal_data); switch (cmd()) { case AltosLib.AO_LOG_FLIGHT: - if (state.flight == AltosLib.MISSING) { - state.set_boost_tick(tick()); - state.set_flight(flight()); + if (cal_data.flight == AltosLib.MISSING) { + cal_data.set_boost_tick(); + cal_data.set_flight(flight()); } /* no place to log start lat/lon yet */ break; case AltosLib.AO_LOG_GPS_TIME: - gps = state.make_temp_gps(false); + AltosGPS gps = new AltosGPS(); gps.lat = latitude() / 1e7; gps.lon = longitude() / 1e7; if (eeprom.config_data().altitude_32 == 1) @@ -140,6 +123,7 @@ public class AltosEepromRecordGps extends AltosEepromRecord { if (gps.vdop < 0.8) gps.vdop += 2.56; } + listener.set_gps(gps); break; } } @@ -151,11 +135,11 @@ public class AltosEepromRecordGps extends AltosEepromRecord { return new AltosEepromRecordGps(eeprom, s); } - public AltosEepromRecordGps(AltosEepromNew eeprom, int start) { + public AltosEepromRecordGps(AltosEeprom eeprom, int start) { super(eeprom, start, record_length); } - public AltosEepromRecordGps(AltosEepromNew eeprom) { + public AltosEepromRecordGps(AltosEeprom eeprom) { this(eeprom, 0); } } diff --git a/altoslib/AltosEepromRecordMega.java b/altoslib/AltosEepromRecordMega.java index 1c6d1aee..ad3e23fd 100644 --- a/altoslib/AltosEepromRecordMega.java +++ b/altoslib/AltosEepromRecordMega.java @@ -12,7 +12,7 @@ * General Public License for more details. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosEepromRecordMega extends AltosEepromRecord { public static final int record_length = 32; @@ -73,8 +73,8 @@ public class AltosEepromRecordMega extends AltosEepromRecord { private int gyro_y() { return data16(16); } private int gyro_z() { return data16(18); } private int mag_x() { return data16(20); } - private int mag_y() { return data16(22); } - private int mag_z() { return data16(24); } + private int mag_z() { return data16(22); } + private int mag_y() { return data16(24); } private int accel() { return data16(26); } /* AO_LOG_TEMP_VOLT elements */ @@ -109,84 +109,90 @@ public class AltosEepromRecordMega extends AltosEepromRecord { private int svid(int n) { return data8(2 + n * 2); } private int c_n(int n) { return data8(2 + n * 2 + 1); } - public void update_state(AltosState state) { - super.update_state(state); - AltosGPS gps; + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + super.provide_data(listener, cal_data); - /* 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; - } - } + AltosGPS gps; 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_accel_ground(ground_accel_along(), - ground_accel_across(), - ground_accel_through()); - state.set_gyro_zero(ground_roll() / 512.0, - ground_pitch() / 512.0, - ground_yaw() / 512.0); + cal_data.set_flight(flight()); + cal_data.set_ground_accel(ground_accel()); + cal_data.set_ground_pressure(ground_pres()); + listener.set_accel_ground(ground_accel_along(), + ground_accel_across(), + ground_accel_through()); + cal_data.set_gyro_zero(ground_roll() / 512.0, + ground_pitch() / 512.0, + ground_yaw() / 512.0); break; case AltosLib.AO_LOG_STATE: - state.set_state(state()); + listener.set_state(state()); break; case AltosLib.AO_LOG_SENSOR: - state.set_ms5607(pres(), temp()); - - AltosIMU imu = new AltosIMU(accel_y(), /* along */ - accel_x(), /* across */ - accel_z(), /* through */ - gyro_y(), /* roll */ - gyro_x(), /* pitch */ - gyro_z()); /* yaw */ + AltosConfigData config_data = eeprom.config_data(); + AltosPresTemp pt = config_data.ms5607().pres_temp(pres(), temp());; + listener.set_pressure(pt.pres); + listener.set_temperature(pt.temp); + + int accel_along = accel_y(); + int accel_across = accel_x(); + int accel_through = accel_z(); + int gyro_roll = gyro_y(); + int gyro_pitch = gyro_x(); + int gyro_yaw = gyro_z(); + + int mag_along = mag_y(); + int mag_across = mag_x(); + int mag_through = mag_z(); if (log_format == AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD) - state.check_imu_wrap(imu); + cal_data.check_imu_wrap(gyro_roll, gyro_pitch, gyro_yaw); + + listener.set_accel(cal_data.accel_along(accel_along), + cal_data.accel_across(accel_across), + cal_data.accel_through(accel_through)); + listener.set_gyro(cal_data.gyro_roll(gyro_roll), + cal_data.gyro_pitch(gyro_pitch), + cal_data.gyro_yaw(gyro_yaw)); + + listener.set_mag(cal_data.mag_along(mag_along), + cal_data.mag_across(mag_across), + cal_data.mag_through(mag_through)); - state.set_imu(imu); - state.set_mag(new AltosMag(mag_x(), - mag_y(), - mag_z())); + final double lsb_per_g = 1920.0/105.5; - state.set_accel(accel()); + double acceleration = AltosConvert.acceleration_from_sensor( + accel(), + cal_data.ground_accel, + cal_data.ground_accel + 2 * lsb_per_g, + cal_data.ground_accel); + listener.set_acceleration(acceleration); 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())); + listener.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt())); + listener.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))); + listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense(nsense-2))); + listener.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); - state.set_pyro_fired(pyro()); + listener.set_igniter_voltage(voltages); + listener.set_pyro_fired(pyro()); break; case AltosLib.AO_LOG_GPS_TIME: - gps = state.make_temp_gps(false); + gps = cal_data.make_temp_gps(tick(), false); gps.lat = latitude() / 1e7; gps.lon = longitude() / 1e7; - if (state.altitude_32()) + if (config_data().altitude_32()) gps.alt = (altitude_low() & 0xffff) | (altitude_high() << 16); else gps.alt = altitude_low(); @@ -208,7 +214,7 @@ public class AltosEepromRecordMega extends AltosEepromRecord { gps.ground_speed = ground_speed() * 1.0e-2; gps.course = course() * 2; gps.climb_rate = climb_rate() * 1.0e-2; - if (state.compare_version("1.4.9") >= 0) { + if (config_data().compare_version("1.4.9") >= 0) { gps.pdop = pdop() / 10.0; gps.hdop = hdop() / 10.0; gps.vdop = vdop() / 10.0; @@ -225,7 +231,7 @@ public class AltosEepromRecordMega extends AltosEepromRecord { } break; case AltosLib.AO_LOG_GPS_SAT: - gps = state.make_temp_gps(true); + gps = cal_data.make_temp_gps(tick(), true); int n = nsat(); if (n > max_sat) @@ -243,12 +249,12 @@ public class AltosEepromRecordMega extends AltosEepromRecord { return new AltosEepromRecordMega(eeprom, s); } - public AltosEepromRecordMega(AltosEepromNew eeprom, int start) { + public AltosEepromRecordMega(AltosEeprom eeprom, int start) { super(eeprom, start, record_length); log_format = eeprom.config_data().log_format; } - public AltosEepromRecordMega(AltosEepromNew eeprom) { + public AltosEepromRecordMega(AltosEeprom eeprom) { this(eeprom, 0); } } diff --git a/altoslib/AltosEepromRecordMetrum.java b/altoslib/AltosEepromRecordMetrum.java index c11b6aac..3da50544 100644 --- a/altoslib/AltosEepromRecordMetrum.java +++ b/altoslib/AltosEepromRecordMetrum.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosEepromRecordMetrum extends AltosEepromRecord { public static final int record_length = 16; @@ -65,59 +65,42 @@ public class AltosEepromRecordMetrum extends AltosEepromRecord { public int svid(int n) { return data8(2 + n * 2); } public int c_n(int n) { return data8(2 + n * 2 + 1); } - public void update_state(AltosState state) { - super.update_state(state); + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + super.provide_data(listener, cal_data); 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()); + cal_data.set_flight(flight()); + cal_data.set_ground_accel(ground_accel()); + cal_data.set_ground_pressure(ground_pres()); break; case AltosLib.AO_LOG_STATE: - state.set_state(state()); + listener.set_state(state()); break; case AltosLib.AO_LOG_SENSOR: - state.set_ms5607(pres(), temp()); - state.set_accel(accel()); - + AltosPresTemp pt = eeprom.config_data().ms5607().pres_temp(pres(), temp()); + listener.set_pressure(pt.pres); + listener.set_temperature(pt.temp); + listener.set_acceleration(cal_data.acceleration(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())); - + listener.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt())); + listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense_a())); + listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sense_m())); break; case AltosLib.AO_LOG_GPS_POS: - gps = state.make_temp_gps(false); + gps = cal_data.make_temp_gps(tick(), false); gps.lat = latitude() / 1e7; gps.lon = longitude() / 1e7; - if (state.altitude_32()) + if (config_data().altitude_32()) gps.alt = (altitude_low() & 0xffff) | (altitude_high() << 16); else gps.alt = altitude_low(); break; case AltosLib.AO_LOG_GPS_TIME: - gps = state.make_temp_gps(false); + gps = cal_data.make_temp_gps(tick(), false); gps.hour = hour(); gps.minute = minute(); @@ -136,7 +119,7 @@ public class AltosEepromRecordMetrum extends AltosEepromRecord { gps.pdop = pdop() / 10.0; break; case AltosLib.AO_LOG_GPS_SAT: - gps = state.make_temp_gps(true); + gps = cal_data.make_temp_gps(tick(), true); int n = nsat(); for (int i = 0; i < n; i++) @@ -152,11 +135,11 @@ public class AltosEepromRecordMetrum extends AltosEepromRecord { return new AltosEepromRecordMetrum(eeprom, s); } - public AltosEepromRecordMetrum(AltosEepromNew eeprom, int start) { + public AltosEepromRecordMetrum(AltosEeprom eeprom, int start) { super(eeprom, start, record_length); } - public AltosEepromRecordMetrum(AltosEepromNew eeprom) { + public AltosEepromRecordMetrum(AltosEeprom eeprom) { this(eeprom, 0); } } diff --git a/altoslib/AltosEepromRecordMini.java b/altoslib/AltosEepromRecordMini.java index f0fc61ad..55696693 100644 --- a/altoslib/AltosEepromRecordMini.java +++ b/altoslib/AltosEepromRecordMini.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosEepromRecordMini extends AltosEepromRecord { public static final int record_length = 16; @@ -42,8 +42,10 @@ public class AltosEepromRecordMini extends AltosEepromRecord { private double battery_voltage(int sensor) { int log_format = log_format(); - if (log_format == AltosLib.AO_LOG_FORMAT_EASYMINI) - return AltosConvert.easy_mini_voltage(sensor, eeprom.config_data().serial); + if (log_format == AltosLib.AO_LOG_FORMAT_EASYMINI1) + return AltosConvert.easy_mini_1_voltage(sensor, eeprom.config_data().serial); + if (log_format == AltosLib.AO_LOG_FORMAT_EASYMINI2) + return AltosConvert.easy_mini_2_voltage(sensor); if (log_format == AltosLib.AO_LOG_FORMAT_TELEMINI2) return AltosConvert.tele_mini_2_voltage(sensor); if (log_format == AltosLib.AO_LOG_FORMAT_TELEMINI3) @@ -53,8 +55,10 @@ public class AltosEepromRecordMini extends AltosEepromRecord { private double pyro_voltage(int sensor) { int log_format = log_format(); - if (log_format == AltosLib.AO_LOG_FORMAT_EASYMINI) - return AltosConvert.easy_mini_voltage(sensor, eeprom.config_data().serial); + if (log_format == AltosLib.AO_LOG_FORMAT_EASYMINI1) + return AltosConvert.easy_mini_1_voltage(sensor, eeprom.config_data().serial); + if (log_format == AltosLib.AO_LOG_FORMAT_EASYMINI2) + return AltosConvert.easy_mini_2_voltage(sensor); if (log_format == AltosLib.AO_LOG_FORMAT_TELEMINI2) return AltosConvert.tele_mini_2_voltage(sensor); if (log_format == AltosLib.AO_LOG_FORMAT_TELEMINI3) @@ -62,22 +66,24 @@ public class AltosEepromRecordMini extends AltosEepromRecord { return -1; } - public void update_state(AltosState state) { - super.update_state(state); + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + super.provide_data(listener, cal_data); switch (cmd()) { case AltosLib.AO_LOG_FLIGHT: - state.set_flight(flight()); - state.set_ground_pressure(ground_pres()); + cal_data.set_flight(flight()); + cal_data.set_ground_pressure(ground_pres()); break; case AltosLib.AO_LOG_STATE: - state.set_state(state()); + listener.set_state(state()); break; case AltosLib.AO_LOG_SENSOR: - state.set_ms5607(pres(), temp()); - state.set_apogee_voltage(pyro_voltage(sense_a())); - state.set_main_voltage(pyro_voltage(sense_m())); - state.set_battery_voltage(battery_voltage(v_batt())); + AltosPresTemp pt = eeprom.config_data().ms5607().pres_temp(pres(), temp()); + listener.set_pressure(pt.pres); + listener.set_temperature(pt.temp); + listener.set_apogee_voltage(pyro_voltage(sense_a())); + listener.set_main_voltage(pyro_voltage(sense_m())); + listener.set_battery_voltage(battery_voltage(v_batt())); break; } } @@ -89,11 +95,11 @@ public class AltosEepromRecordMini extends AltosEepromRecord { return new AltosEepromRecordMini(eeprom, s); } - public AltosEepromRecordMini(AltosEepromNew eeprom, int start) { + public AltosEepromRecordMini(AltosEeprom eeprom, int start) { super(eeprom, start, record_length); } - public AltosEepromRecordMini(AltosEepromNew eeprom) { + public AltosEepromRecordMini(AltosEeprom eeprom) { this(eeprom, 0); } } diff --git a/altoslib/AltosEepromRecordSet.java b/altoslib/AltosEepromRecordSet.java index 911b90b9..48e90c05 100644 --- a/altoslib/AltosEepromRecordSet.java +++ b/altoslib/AltosEepromRecordSet.java @@ -12,47 +12,45 @@ * General Public License for more details. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.util.*; -public class AltosEepromRecordSet implements Iterable { - AltosEepromNew eeprom; +public class AltosEepromRecordSet implements AltosRecordSet { + AltosEeprom eeprom; TreeSet ordered; - AltosState start_state; + AltosCalData cal_data; - class RecordIterator implements Iterator { - Iterator riterator; - AltosState state; - boolean started; - - public boolean hasNext() { - return state == null || riterator.hasNext(); - } + public AltosConfigData config_data() { + return eeprom.config_data(); + } - public AltosState next() { - if (state == null) - state = start_state.clone(); - else { - state = state.clone(); - AltosEepromRecord r = riterator.next(); - r.update_state(state); + public AltosCalData cal_data() { + if (cal_data == null) { + cal_data = new AltosCalData(config_data()); + for (AltosEepromRecord record : ordered) { + if (record.cmd() == AltosLib.AO_LOG_FLIGHT) { + cal_data.set_tick(record.tick()); + cal_data.set_boost_tick(); + break; + } } - return state; - } - - public RecordIterator() { - riterator = ordered.iterator(); - state = null; } + return cal_data; } - public Iterator iterator() { - return new RecordIterator(); + public void capture_series(AltosDataListener listener) { + AltosCalData cal_data = cal_data(); + + cal_data.reset(); + for (AltosEepromRecord record : ordered) { + record.provide_data(listener, cal_data); + } + listener.finish(); } - public AltosEepromRecordSet(AltosEepromNew eeprom) { + public AltosEepromRecordSet(AltosEeprom eeprom) { this.eeprom = eeprom; AltosConfigData config_data = eeprom.config_data(); @@ -77,7 +75,8 @@ public class AltosEepromRecordSet implements Iterable { break; case AltosLib.AO_LOG_FORMAT_TELEMINI2: case AltosLib.AO_LOG_FORMAT_TELEMINI3: - case AltosLib.AO_LOG_FORMAT_EASYMINI: + case AltosLib.AO_LOG_FORMAT_EASYMINI1: + case AltosLib.AO_LOG_FORMAT_EASYMINI2: record = new AltosEepromRecordMini(eeprom); break; case AltosLib.AO_LOG_FORMAT_TELEGPS: @@ -96,9 +95,6 @@ public class AltosEepromRecordSet implements Iterable { int tick = 0; boolean first = true; - start_state = new AltosState(); - start_state.set_config_data(record.eeprom.config_data()); - for (;;) { int t = record.tick(); @@ -118,7 +114,7 @@ public class AltosEepromRecordSet implements Iterable { } } - public AltosEepromRecordSet(Reader input) throws IOException { - this(new AltosEepromNew(input)); + public AltosEepromRecordSet(InputStream input) throws IOException { + this(new AltosEeprom(input)); } } diff --git a/altoslib/AltosEepromRecordTiny.java b/altoslib/AltosEepromRecordTiny.java index fda6ddff..06ee9d54 100644 --- a/altoslib/AltosEepromRecordTiny.java +++ b/altoslib/AltosEepromRecordTiny.java @@ -12,9 +12,9 @@ * General Public License for more details. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; -public class AltosEepromRecordTiny extends AltosEepromRecord { +public class AltosEepromRecordTiny extends AltosEepromRecord implements AltosDataProvider { public static final int record_length = 2; private int value() { @@ -50,21 +50,21 @@ public class AltosEepromRecordTiny extends AltosEepromRecord { return tick; } - public void update_state(AltosState state) { + public void provide_data(AltosDataListener listener) { int value = data16(-header_length); - state.set_tick(tick()); + listener.set_tick(tick()); switch (cmd()) { case AltosLib.AO_LOG_FLIGHT: - state.set_state(AltosLib.ao_flight_pad); - state.set_flight(value); - state.set_boost_tick(0); + listener.set_state(AltosLib.ao_flight_pad); + listener.cal_data().set_flight(value); + listener.cal_data().set_boost_tick(); break; case AltosLib.AO_LOG_STATE: - state.set_state(value & 0x7fff); + listener.set_state(value & 0x7fff); break; case AltosLib.AO_LOG_SENSOR: - state.set_pressure(AltosConvert.barometer_to_pressure(value)); + listener.set_pressure(AltosConvert.barometer_to_pressure(value)); break; } } @@ -76,11 +76,11 @@ public class AltosEepromRecordTiny extends AltosEepromRecord { return new AltosEepromRecordTiny(eeprom, s); } - public AltosEepromRecordTiny(AltosEepromNew eeprom, int start) { + public AltosEepromRecordTiny(AltosEeprom eeprom, int start) { super(eeprom, start, record_length); } - public AltosEepromRecordTiny(AltosEepromNew eeprom) { + public AltosEepromRecordTiny(AltosEeprom eeprom) { this(eeprom, 0); } } diff --git a/altoslib/AltosFile.java b/altoslib/AltosFile.java index ef75762a..69f779c1 100644 --- a/altoslib/AltosFile.java +++ b/altoslib/AltosFile.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.File; import java.util.*; @@ -66,7 +66,7 @@ public class AltosFile extends File { extension); } - public AltosFile(AltosState state) { - this(state.serial, state.flight, state.receiver_serial, "telem"); + public AltosFile(AltosCalData cal_data) { + this(cal_data.serial, cal_data.flight, cal_data.receiver_serial, "telem"); } } diff --git a/altoslib/AltosFlash.java b/altoslib/AltosFlash.java index ad573305..c8db1f77 100644 --- a/altoslib/AltosFlash.java +++ b/altoslib/AltosFlash.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; diff --git a/altoslib/AltosFlashListener.java b/altoslib/AltosFlashListener.java index e15d7ac3..60052133 100644 --- a/altoslib/AltosFlashListener.java +++ b/altoslib/AltosFlashListener.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public interface AltosFlashListener { public void position(String label, int percent); diff --git a/altoslib/AltosFlightDisplay.java b/altoslib/AltosFlightDisplay.java index c395dc45..8fe33c5e 100644 --- a/altoslib/AltosFlightDisplay.java +++ b/altoslib/AltosFlightDisplay.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public interface AltosFlightDisplay extends AltosUnitsListener, AltosFontListener { void reset(); diff --git a/altoslib/AltosFlightListener.java b/altoslib/AltosFlightListener.java new file mode 100644 index 00000000..d61831a9 --- /dev/null +++ b/altoslib/AltosFlightListener.java @@ -0,0 +1,162 @@ +/* + * Copyright © 2017 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altoslib_12; + +public abstract class AltosFlightListener { + + public int flight; + public int serial; + public int tick; + public int boost_tick; + public int state; + + public double accel_plus_g; + public double accel_minus_g; + public double accel; + + public double ground_pressure; + public double ground_altitude; + + AltosGPS temp_gps; + int temp_gps_sat_tick; + int gps_sequence; + + /* AltosEepromRecord */ + public void set_boost_tick(int boost_tick) { + if (boost_tick != AltosLib.MISSING) + this.boost_tick = boost_tick; + } + + public void set_tick(int tick) { + if (tick != AltosLib.MISSING) + this.tick = tick; + } + + public double time() { + if (tick == AltosLib.MISSING) + return AltosLib.MISSING; + if (boost_tick != AltosLib.MISSING) + return (tick - boost_tick) / 100.0; + else + return tick / 100.0; + } + + public double boost_time() { + if (boost_tick == AltosLib.MISSING) + return AltosLib.MISSING; + return boost_tick / 100.0; + } + + public abstract void set_rssi(int rssi, int status); + public abstract void set_received_time(long received_time); + + /* AltosEepromRecordFull */ + + public void set_serial(int serial) { + if (serial != AltosLib.MISSING) + this.serial = serial; + } + + public void set_state(int state) { + if (state != AltosLib.MISSING) + this.state = state; + } + + public int state() { return state; } + + public abstract void set_ground_accel(double ground_accel); + public void set_flight(int flight) { + if (flight != AltosLib.MISSING) + this.flight = flight; + } + public int flight() { + return flight; + } + + public abstract void set_accel(double accel); + public abstract void set_acceleration(double accel); + public abstract void set_accel_g(double accel_plus_g, double accel_minus_g); + public abstract void set_pressure(double pa); + public abstract void set_thrust(double N); + + public abstract void set_temperature(double deg_c); + public abstract void set_battery_voltage(double volts); + + public abstract void set_apogee_voltage(double volts); + public abstract void set_main_voltage(double volts); + + public void set_temp_gps() { + temp_gps = null; + } + + public boolean gps_pending() { + return temp_gps != null; + } + + public AltosGPS make_temp_gps(boolean sats) { + if (temp_gps == null) { + temp_gps = new AltosGPS(); + } + if (sats) { + if (tick != temp_gps_sat_tick) + temp_gps.cc_gps_sat = null; + temp_gps_sat_tick = tick; + } + return temp_gps; + } + + public void set_ground_pressure(double ground_pressure) { + if (ground_pressure != AltosLib.MISSING) { + this.ground_pressure = ground_pressure; + this.ground_altitude = AltosConvert.pressure_to_altitude(ground_pressure); + } + } + + public abstract void set_accel_ground(double along, double across, double through); + public abstract void set_gyro_zero(double roll, double pitch, double yaw); + public abstract void check_imu_wrap(AltosIMU imu); + public abstract void set_imu(AltosIMU imu); + public abstract void set_mag(AltosMag mag); + public abstract void set_pyro_voltage(double volts); + public abstract void set_igniter_voltage(double[] voltage); + public abstract void set_pyro_fired(int pyro_mask); + + public void copy(AltosFlightListener old) { + flight = old.flight; + serial = old.serial; + tick = old.tick; + boost_tick = old.boost_tick; + accel_plus_g = old.accel_plus_g; + accel_minus_g = old.accel_minus_g; + ground_pressure = old.ground_pressure; + ground_altitude = old.ground_altitude; + temp_gps = old.temp_gps; + temp_gps_sat_tick = old.temp_gps_sat_tick; + } + + public void init() { + flight = AltosLib.MISSING; + serial = AltosLib.MISSING; + tick = AltosLib.MISSING; + boost_tick = AltosLib.MISSING; + accel_plus_g = AltosLib.MISSING; + accel_minus_g = AltosLib.MISSING; + accel = AltosLib.MISSING; + ground_pressure = AltosLib.MISSING; + ground_altitude = AltosLib.MISSING; + temp_gps = null; + temp_gps_sat_tick = AltosLib.MISSING; + } +} diff --git a/altoslib/AltosFlightReader.java b/altoslib/AltosFlightReader.java index 250e2236..671bf638 100644 --- a/altoslib/AltosFlightReader.java +++ b/altoslib/AltosFlightReader.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.text.*; import java.io.*; @@ -31,6 +31,8 @@ public abstract class AltosFlightReader { public abstract AltosState read() throws InterruptedException, ParseException, AltosCRCException, IOException; + public abstract AltosCalData cal_data(); + public abstract void close(boolean interrupted); public void set_frequency(double frequency) throws InterruptedException, TimeoutException { } @@ -45,8 +47,6 @@ public abstract class AltosFlightReader { public void save_telemetry_rate() { } - public void update(AltosState state) throws InterruptedException { } - public boolean supports_telemetry(int telemetry) { return false; } public boolean supports_telemetry_rate(int telemetry_rate) { return false; } diff --git a/altoslib/AltosFlightSeries.java b/altoslib/AltosFlightSeries.java new file mode 100644 index 00000000..57f1a491 --- /dev/null +++ b/altoslib/AltosFlightSeries.java @@ -0,0 +1,697 @@ +/* + * Copyright © 2017 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altoslib_12; + +import java.util.*; + +public class AltosFlightSeries extends AltosDataListener { + + public ArrayList series = new ArrayList(); + + public double speed_filter_width = 4.0; + public double accel_filter_width = 4.0; + + public int[] indices() { + int[] indices = new int[series.size()]; + for (int i = 0; i < indices.length; i++) + indices[i] = -1; + step_indices(indices); + return indices; + } + + private double time(int id, int index) { + AltosTimeSeries s = series.get(id); + + if (index < 0) + return Double.NEGATIVE_INFINITY; + + if (index < s.values.size()) + return s.values.get(index).time; + return Double.POSITIVE_INFINITY; + } + + public boolean step_indices(int[] indices) { + double min_next = time(0, indices[0]+1); + + for (int i = 1; i < indices.length; i++) { + double next = time(i, indices[i]+1); + if (next < min_next) + min_next = next; + } + + if (min_next == Double.POSITIVE_INFINITY) + return false; + + for (int i = 0; i < indices.length; i++) { + double t = time(i, indices[i] + 1); + + if (t <= min_next) + indices[i]++; + } + return true; + } + + public double time(int[] indices) { + double max = time(0, indices[0]); + + for (int i = 1; i < indices.length; i++) { + double t = time(i, indices[i]); + if (t >= max) + max = t; + } + return max; + } + + public double value(String name, int[] indices) { + for (int i = 0; i < indices.length; i++) { + AltosTimeSeries s = series.get(i); + if (s.label.equals(name)) { + int index = indices[i]; + if (index < 0) + index = 0; + if (index >= s.values.size()) + index = s.values.size() - 1; + return s.values.get(index).value; + } + } + return AltosLib.MISSING; + } + + public double value(String name, double time) { + for (AltosTimeSeries s : series) { + if (s.label.equals(name)) + return s.value(time); + } + return AltosLib.MISSING; + } + + public double value_before(String name, double time) { + for (AltosTimeSeries s : series) { + if (s.label.equals(name)) + return s.value_before(time); + } + return AltosLib.MISSING; + } + + public double value_after(String name, double time) { + for (AltosTimeSeries s : series) { + if (s.label.equals(name)) + return s.value_after(time); + } + return AltosLib.MISSING; + } + + public AltosTimeSeries make_series(String label, AltosUnits units) { + return new AltosTimeSeries(label, units); + } + + public void add_series(AltosTimeSeries s) { + for (int e = 0; e < series.size(); e++) { + if (s.compareTo(series.get(e)) < 0){ + series.add(e, s); + return; + } + } + series.add(s); + } + + public AltosTimeSeries add_series(String label, AltosUnits units) { + AltosTimeSeries s = make_series(label, units); + add_series(s); + return s; + } + + public void remove_series(AltosTimeSeries s) { + series.remove(s); + } + + public boolean has_series(String label) { + for (AltosTimeSeries s : series) + if (s.label.equals(label)) + return true; + return false; + } + + public AltosTimeSeries state_series; + + public static final String state_name = "State"; + + public void set_state(int state) { + + if (state == AltosLib.ao_flight_pad) + return; + + if (state_series == null) + state_series = add_series(state_name, AltosConvert.state_name); + else if (this.state == state) + return; + this.state = state; + state_series.add(time(), state); + } + + public AltosTimeSeries accel_series; + + public static final String accel_name = "Accel"; + + public AltosTimeSeries vert_accel_series; + + public static final String vert_accel_name = "Vertical Accel"; + + public void set_acceleration(double acceleration) { + if (acceleration == AltosLib.MISSING) + return; + if (accel_series == null) + accel_series = add_series(accel_name, AltosConvert.accel); + + accel_series.add(time(), acceleration); + } + + private void compute_accel() { + if (accel_series != null) + return; + + if (speed_series != null) { + AltosTimeSeries temp_series = make_series(speed_name, AltosConvert.speed); + speed_series.filter(temp_series, accel_filter_width); + accel_series = add_series(accel_name, AltosConvert.accel); + temp_series.differentiate(accel_series); + } + } + + public void set_received_time(long received_time) { + } + + public AltosTimeSeries rssi_series; + + public static final String rssi_name = "RSSI"; + + public AltosTimeSeries status_series; + + public static final String status_name = "Radio Status"; + + public void set_rssi(int rssi, int status) { + if (rssi_series == null) { + rssi_series = add_series(rssi_name, null); + status_series = add_series(status_name, null); + } + rssi_series.add(time(), rssi); + status_series.add(time(), status); + } + + public AltosTimeSeries pressure_series; + + public static final String pressure_name = "Pressure"; + + public AltosTimeSeries altitude_series; + + public static final String altitude_name = "Altitude"; + + public AltosTimeSeries height_series; + + public static final String height_name = "Height"; + + public void set_pressure(double pa) { + if (pa == AltosLib.MISSING) + return; + + if (pressure_series == null) + pressure_series = add_series(pressure_name, AltosConvert.pressure); + pressure_series.add(time(), pa); + if (altitude_series == null) + altitude_series = add_series(altitude_name, AltosConvert.height); + + if (cal_data().ground_pressure == AltosLib.MISSING) + cal_data().set_ground_pressure(pa); + + double altitude = AltosConvert.pressure_to_altitude(pa); + altitude_series.add(time(), altitude); + } + + private void compute_height() { + double ground_altitude = cal_data().ground_altitude; + if (height_series == null && ground_altitude != AltosLib.MISSING && altitude_series != null) { + height_series = add_series(height_name, AltosConvert.height); + for (AltosTimeValue alt : altitude_series) + height_series.add(alt.time, alt.value - ground_altitude); + } + + if (gps_height == null && cal_data().gps_pad != null && cal_data().gps_pad.alt != AltosLib.MISSING && gps_altitude != null) { + double gps_ground_altitude = cal_data().gps_pad.alt; + gps_height = add_series(gps_height_name, AltosConvert.height); + for (AltosTimeValue gps_alt : gps_altitude) + gps_height.add(gps_alt.time, gps_alt.value - gps_ground_altitude); + } + } + + public AltosTimeSeries speed_series; + + public static final String speed_name = "Speed"; + + private void compute_speed() { + if (speed_series != null) + return; + + AltosTimeSeries alt_speed_series = null; + AltosTimeSeries accel_speed_series = null; + + if (altitude_series != null) { + AltosTimeSeries temp_series = make_series(altitude_name, AltosConvert.height); + altitude_series.filter(temp_series, speed_filter_width); + + alt_speed_series = make_series(speed_name, AltosConvert.speed); + temp_series.differentiate(alt_speed_series); + } + if (accel_series != null) { + + if (orient_series != null) { + vert_accel_series = add_series(vert_accel_name, AltosConvert.accel); + + for (AltosTimeValue a : accel_series) { + double orient = orient_series.value(a.time); + double a_abs = a.value + AltosConvert.gravity; + double v_a = a_abs * Math.cos(AltosConvert.degrees_to_radians(orient)) - AltosConvert.gravity; + + vert_accel_series.add(a.time, v_a); + } + } + + AltosTimeSeries temp_series = make_series(speed_name, AltosConvert.speed); + + if (vert_accel_series != null) + vert_accel_series.integrate(temp_series); + else + accel_series.integrate(temp_series); + + accel_speed_series = make_series(speed_name, AltosConvert.speed); + temp_series.filter(accel_speed_series, 0.1); + } + + if (alt_speed_series != null && accel_speed_series != null) { + double apogee_time = AltosLib.MISSING; + if (state_series != null) { + for (AltosTimeValue d : state_series) { + if (d.value >= AltosLib.ao_flight_drogue){ + apogee_time = d.time; + break; + } + } + } + if (apogee_time == AltosLib.MISSING) { + speed_series = alt_speed_series; + } else { + speed_series = make_series(speed_name, AltosConvert.speed); + for (AltosTimeValue d : accel_speed_series) { + if (d.time <= apogee_time) + speed_series.add(d); + } + for (AltosTimeValue d : alt_speed_series) { + if (d.time > apogee_time) + speed_series.add(d); + } + + } + } else if (alt_speed_series != null) { + speed_series = alt_speed_series; + } else if (accel_speed_series != null) { + speed_series = accel_speed_series; + } + if (speed_series != null) + add_series(speed_series); + } + + public AltosTimeSeries orient_series; + + public static final String orient_name = "Tilt Angle"; + + private void compute_orient() { + + if (orient_series != null) + return; + + if (accel_ground_across == AltosLib.MISSING) + return; + + if (cal_data().pad_orientation == AltosLib.MISSING) + return; + + if (cal_data().accel_zero_across == AltosLib.MISSING) + return; + + AltosRotation rotation = new AltosRotation(AltosIMU.convert_accel(accel_ground_across - cal_data().accel_zero_across), + AltosIMU.convert_accel(accel_ground_through - cal_data().accel_zero_through), + AltosIMU.convert_accel(accel_ground_along - cal_data().accel_zero_along), + cal_data().pad_orientation); + double prev_time = ground_time; + + orient_series = add_series(orient_name, AltosConvert.orient); + orient_series.add(ground_time, rotation.tilt()); + + for (AltosTimeValue roll_v : gyro_roll) { + double time = roll_v.time; + double dt = time - prev_time; + + if (dt > 0) { + double roll = AltosConvert.degrees_to_radians(roll_v.value) * dt; + double pitch = AltosConvert.degrees_to_radians(gyro_pitch.value(time)) * dt; + double yaw = AltosConvert.degrees_to_radians(gyro_yaw.value(time)) * dt; + + rotation.rotate(pitch, yaw, roll); + orient_series.add(time, rotation.tilt()); + } + prev_time = time; + } + } + + public AltosTimeSeries kalman_height_series, kalman_speed_series, kalman_accel_series; + + public static final String kalman_height_name = "Kalman Height"; + public static final String kalman_speed_name = "Kalman Speed"; + public static final String kalman_accel_name = "Kalman Accel"; + + public void set_kalman(double height, double speed, double acceleration) { + if (kalman_height_series == null) { + kalman_height_series = add_series(kalman_height_name, AltosConvert.height); + kalman_speed_series = add_series(kalman_speed_name, AltosConvert.speed); + kalman_accel_series = add_series(kalman_accel_name, AltosConvert.accel); + } + kalman_height_series.add(time(), height); + kalman_speed_series.add(time(), speed); + kalman_accel_series.add(time(), acceleration); + } + + public AltosTimeSeries thrust_series; + + public static final String thrust_name = "Thrust"; + + public void set_thrust(double N) { + if (thrust_series == null) + thrust_series = add_series(thrust_name, AltosConvert.force); + thrust_series.add(time(), N); + } + + public AltosTimeSeries temperature_series; + + public static final String temperature_name = "Temperature"; + + public void set_temperature(double deg_c) { + if (temperature_series == null) + temperature_series = add_series(temperature_name, AltosConvert.temperature); + temperature_series.add(time(), deg_c); + } + + public AltosTimeSeries battery_voltage_series; + + public static final String battery_voltage_name = "Battery Voltage"; + + public void set_battery_voltage(double volts) { + if (volts == AltosLib.MISSING) + return; + if (battery_voltage_series == null) + battery_voltage_series = add_series(battery_voltage_name, AltosConvert.voltage); + battery_voltage_series.add(time(), volts); + } + + public AltosTimeSeries apogee_voltage_series; + + public static final String apogee_voltage_name = "Apogee Voltage"; + + public void set_apogee_voltage(double volts) { + if (volts == AltosLib.MISSING) + return; + if (apogee_voltage_series == null) + apogee_voltage_series = add_series(apogee_voltage_name, AltosConvert.voltage); + apogee_voltage_series.add(time(), volts); + } + + public AltosTimeSeries main_voltage_series; + + public static final String main_voltage_name = "Main Voltage"; + + public void set_main_voltage(double volts) { + if (volts == AltosLib.MISSING) + return; + if (main_voltage_series == null) + main_voltage_series = add_series(main_voltage_name, AltosConvert.voltage); + main_voltage_series.add(time(), volts); + } + + public ArrayList gps_series; + + public AltosGPS gps_before(double time) { + AltosGPS gps = null; + for (AltosGPSTimeValue gtv : gps_series) + if (gtv.time <= time) + gps = gtv.gps; + else + break; + return gps; + } + + public AltosTimeSeries sats_in_view; + public AltosTimeSeries sats_in_soln; + public AltosTimeSeries gps_altitude; + public AltosTimeSeries gps_height; + public AltosTimeSeries gps_ground_speed; + public AltosTimeSeries gps_ascent_rate; + public AltosTimeSeries gps_course; + public AltosTimeSeries gps_speed; + public AltosTimeSeries gps_pdop, gps_vdop, gps_hdop; + + public static final String sats_in_view_name = "Satellites in view"; + public static final String sats_in_soln_name = "Satellites in solution"; + public static final String gps_altitude_name = "GPS Altitude"; + public static final String gps_height_name = "GPS Height"; + public static final String gps_ground_speed_name = "GPS Ground Speed"; + public static final String gps_ascent_rate_name = "GPS Ascent Rate"; + public static final String gps_course_name = "GPS Course"; + public static final String gps_speed_name = "GPS Speed"; + public static final String gps_pdop_name = "GPS Dilution of Precision"; + public static final String gps_vdop_name = "GPS Vertical Dilution of Precision"; + public static final String gps_hdop_name = "GPS Horizontal Dilution of Precision"; + + public void set_gps(AltosGPS gps) { + if (gps_series == null) + gps_series = new ArrayList(); + gps_series.add(new AltosGPSTimeValue(time(), gps)); + + if (sats_in_soln == null) { + sats_in_soln = add_series(sats_in_soln_name, null); + } + sats_in_soln.add(time(), gps.nsat); + if (gps.pdop != AltosLib.MISSING) { + if (gps_pdop == null) + gps_pdop = add_series(gps_pdop_name, null); + gps_pdop.add(time(), gps.pdop); + } + if (gps.hdop != AltosLib.MISSING) { + if (gps_hdop == null) + gps_hdop = add_series(gps_hdop_name, null); + gps_hdop.add(time(), gps.hdop); + } + if (gps.vdop != AltosLib.MISSING) { + if (gps_vdop == null) + gps_vdop = add_series(gps_vdop_name, null); + gps_vdop.add(time(), gps.vdop); + } + if (gps.locked) { + if (gps.alt != AltosLib.MISSING) { + if (gps_altitude == null) + gps_altitude = add_series(gps_altitude_name, AltosConvert.height); + gps_altitude.add(time(), gps.alt); + } + if (gps.ground_speed != AltosLib.MISSING) { + if (gps_ground_speed == null) + gps_ground_speed = add_series(gps_ground_speed_name, AltosConvert.speed); + gps_ground_speed.add(time(), gps.ground_speed); + } + if (gps.climb_rate != AltosLib.MISSING) { + if (gps_ascent_rate == null) + gps_ascent_rate = add_series(gps_ascent_rate_name, AltosConvert.speed); + gps_ascent_rate.add(time(), gps.climb_rate); + } + if (gps.course != AltosLib.MISSING) { + if (gps_course == null) + gps_course = add_series(gps_course_name, null); + gps_course.add(time(), gps.course); + } + if (gps.ground_speed != AltosLib.MISSING && gps.climb_rate != AltosLib.MISSING) { + if (gps_speed == null) + gps_speed = add_series(gps_speed_name, null); + gps_speed.add(time(), Math.sqrt(gps.ground_speed * gps.ground_speed + + gps.climb_rate * gps.climb_rate)); + } + } + if (gps.cc_gps_sat != null) { + if (sats_in_view == null) + sats_in_view = add_series(sats_in_view_name, null); + sats_in_view.add(time(), gps.cc_gps_sat.length); + } + } + + public static final String accel_along_name = "Accel Along"; + public static final String accel_across_name = "Accel Across"; + public static final String accel_through_name = "Accel Through"; + + public AltosTimeSeries accel_along, accel_across, accel_through; + + public static final String gyro_roll_name = "Roll Rate"; + public static final String gyro_pitch_name = "Pitch Rate"; + public static final String gyro_yaw_name = "Yaw Rate"; + + public AltosTimeSeries gyro_roll, gyro_pitch, gyro_yaw; + + public static final String mag_along_name = "Magnetic Field Along"; + public static final String mag_across_name = "Magnetic Field Across"; + public static final String mag_through_name = "Magnetic Field Through"; + + public AltosTimeSeries mag_along, mag_across, mag_through; + + public void set_accel(double along, double across, double through) { + if (accel_along == null) { + accel_along = add_series(accel_along_name, AltosConvert.accel); + accel_across = add_series(accel_across_name, AltosConvert.accel); + accel_through = add_series(accel_through_name, AltosConvert.accel); + } + accel_along.add(time(), along); + accel_across.add(time(), across); + accel_through.add(time(), through); + } + + private double accel_ground_along = AltosLib.MISSING; + private double accel_ground_across = AltosLib.MISSING; + private double accel_ground_through = AltosLib.MISSING; + + private double ground_time; + + public void set_accel_ground(double along, double across, double through) { + accel_ground_along = along; + accel_ground_across = across; + accel_ground_through = through; + ground_time = time(); + } + + public void set_gyro(double roll, double pitch, double yaw) { + if (gyro_roll == null) { + gyro_roll = add_series(gyro_roll_name, AltosConvert.rotation_rate); + gyro_pitch = add_series(gyro_pitch_name, AltosConvert.rotation_rate); + gyro_yaw = add_series(gyro_yaw_name, AltosConvert.rotation_rate); + } + gyro_roll.add(time(), roll); + gyro_pitch.add(time(), pitch); + gyro_yaw.add(time(), yaw); + } + + public void set_mag(double along, double across, double through) { + if (mag_along == null) { + mag_along = add_series(mag_along_name, AltosConvert.magnetic_field); + mag_across = add_series(mag_across_name, AltosConvert.magnetic_field); + mag_through = add_series(mag_through_name, AltosConvert.magnetic_field); + } + mag_along.add(time(), along); + mag_across.add(time(), across); + mag_through.add(time(), through); + } + + public void set_orient(double orient) { + if (orient_series == null) + orient_series = add_series(orient_name, AltosConvert.orient); + orient_series.add(time(), orient); + } + + public static final String pyro_voltage_name = "Pyro Voltage"; + + public AltosTimeSeries pyro_voltage; + + public void set_pyro_voltage(double volts) { + if (pyro_voltage == null) + pyro_voltage = add_series(pyro_voltage_name, AltosConvert.voltage); + pyro_voltage.add(time(), volts); + } + + private static String[] igniter_voltage_names; + + public String igniter_voltage_name(int channel) { + if (igniter_voltage_names == null || igniter_voltage_names.length <= channel) { + String[] new_igniter_voltage_names = new String[channel + 1]; + int i = 0; + + if (igniter_voltage_names != null) { + for (; i < igniter_voltage_names.length; i++) + new_igniter_voltage_names[i] = igniter_voltage_names[i]; + } + for (; i < channel+1; i++) + new_igniter_voltage_names[i] = AltosLib.igniter_name(i); + igniter_voltage_names = new_igniter_voltage_names; + } + return igniter_voltage_names[channel]; + } + + public AltosTimeSeries[] igniter_voltage; + + public void set_igniter_voltage(double[] voltage) { + int channels = voltage.length; + if (igniter_voltage == null || igniter_voltage.length <= channels) { + AltosTimeSeries[] new_igniter_voltage = new AltosTimeSeries[channels + 1]; + int i = 0; + + if (igniter_voltage != null) { + for (; i < igniter_voltage.length; i++) + new_igniter_voltage[i] = igniter_voltage[i]; + } + for (; i < channels; i++) + new_igniter_voltage[i] = add_series(igniter_voltage_name(i), AltosConvert.voltage); + igniter_voltage = new_igniter_voltage; + } + for (int channel = 0; channel < voltage.length; channel++) + igniter_voltage[channel].add(time(), voltage[channel]); + } + + public static final String pyro_fired_name = "Pyro Channel State"; + + public AltosTimeSeries pyro_fired_series; + + int last_pyro_mask; + + public void set_pyro_fired(int pyro_mask) { + if (pyro_fired_series == null) + pyro_fired_series = add_series(pyro_fired_name, AltosConvert.pyro_name); + for (int channel = 0; channel < 32; channel++) { + if ((last_pyro_mask & (1 << channel)) == 0 && + (pyro_mask & (1 << channel)) != 0) { + pyro_fired_series.add(time(), channel); + } + } + last_pyro_mask = pyro_mask; + } + + public void set_companion(AltosCompanion companion) { + } + + public void finish() { + compute_orient(); + compute_speed(); + compute_accel(); + compute_height(); + } + + public AltosTimeSeries[] series() { + finish(); + return series.toArray(new AltosTimeSeries[0]); + } + + public AltosFlightSeries(AltosCalData cal_data) { + super(cal_data); + } +} diff --git a/altoslib/AltosFlightStats.java b/altoslib/AltosFlightStats.java index 98f13dac..6f8732cf 100644 --- a/altoslib/AltosFlightStats.java +++ b/altoslib/AltosFlightStats.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; @@ -25,15 +25,17 @@ public class AltosFlightStats { public double max_gps_height; public double max_speed; public double max_acceleration; - public double[] state_speed = new double[AltosLib.ao_flight_invalid + 1]; - public double[] state_accel = new double[AltosLib.ao_flight_invalid + 1]; - public int[] state_count = new int[AltosLib.ao_flight_invalid + 1]; - public double[] state_start = new double[AltosLib.ao_flight_invalid + 1]; - public double[] state_end = new double[AltosLib.ao_flight_invalid + 1]; + public double[] state_speed = new double[AltosLib.ao_flight_invalid + 1]; + public double[] state_accel = new double[AltosLib.ao_flight_invalid + 1]; + public double[] state_time = new double[AltosLib.ao_flight_invalid + 1]; + public String product; + public String firmware_version; public int serial; public int flight; public int year, month, day; public int hour, minute, second; + public double boost_time; + public double landed_time; public double lat, lon; public double pad_lat, pad_lon; public boolean has_flight_data; @@ -46,65 +48,133 @@ public class AltosFlightStats { public boolean has_imu; public boolean has_mag; public boolean has_orient; - public int num_ignitor; + public int num_igniter; - double landed_time(AltosStateIterable states) { - AltosState state = null; + double landed_time(AltosFlightSeries series) { + double landed_state_time = AltosLib.MISSING; - for (AltosState s : states) { - state = s; - if (state.state() == AltosLib.ao_flight_landed) - break; + double prev_state_time = AltosLib.MISSING; + if (series.state_series != null) { + for (AltosTimeValue state : series.state_series) { + if (state.value == AltosLib.ao_flight_landed) { + landed_state_time = state.time; + break; + } else { + prev_state_time = state.time; + } + } } - if (state == null) - return AltosLib.MISSING; + if (landed_state_time == AltosLib.MISSING && series.height_series != null) + landed_state_time = series.height_series.get(series.height_series.size()-1).time; - double landed_height = state.height(); + double landed_height = AltosLib.MISSING; + + if (series.height_series != null) { + for (AltosTimeValue height : series.height_series) { + landed_height = height.value; + if (height.time >= landed_state_time) + break; + } + } - state = null; + if (landed_height == AltosLib.MISSING) + return AltosLib.MISSING; boolean above = true; double landed_time = AltosLib.MISSING; - for (AltosState s : states) { - state = s; - - if (state.height() > landed_height + 10) { - above = true; - } else { - if (above && Math.abs(state.height() - landed_height) < 2) { - above = false; - landed_time = state.time; + if (series.height_series != null) { + for (AltosTimeValue height : series.height_series) { + if (height.value > landed_height + 10) { + above = true; + } else { + if (above && Math.abs(height.value - landed_height) < 2) { + above = false; + landed_time = height.time; + } } } } + + if (landed_time == AltosLib.MISSING || (prev_state_time != AltosLib.MISSING && landed_time < prev_state_time)) + landed_time = landed_state_time; return landed_time; } - double boost_time(AltosStateIterable states) { - double boost_time = AltosLib.MISSING; - AltosState state = null; + double boost_time(AltosFlightSeries series) { + double boost_time = AltosLib.MISSING; + double boost_state_time = AltosLib.MISSING; - for (AltosState s : states) { - state = s; - if (state.acceleration() < 1) - boost_time = state.time; - if (state.state() >= AltosLib.ao_flight_boost && state.state() <= AltosLib.ao_flight_landed) - break; + if (series.state_series != null) { + for (AltosTimeValue state : series.state_series) { + if (state.value >= AltosLib.ao_flight_boost && state.value <= AltosLib.ao_flight_landed) { + boost_state_time = state.time; + break; + } + } } - if (state == null) - return AltosLib.MISSING; - + if (series.accel_series != null) { + for (AltosTimeValue accel : series.accel_series) { + if (accel.value < 1) + boost_time = accel.time; + if (boost_state_time != AltosLib.MISSING && accel.time >= boost_state_time) + break; + } + } + if (boost_time == AltosLib.MISSING) + boost_time = boost_state_time; return boost_time; } + private void add_times(AltosFlightSeries series, int state, double start_time, double end_time) { + double delta_time = end_time - start_time; + if (0 <= state && state <= AltosLib.ao_flight_invalid && delta_time > 0) { + speeds[state].value += series.speed_series.average(start_time, end_time) * delta_time; + speeds[state].time += delta_time; + accels[state].value += series.accel_series.average(start_time, end_time) * delta_time; + accels[state].time += delta_time; + state_time[state] += delta_time; + + if (state == AltosLib.ao_flight_boost) { + AltosTimeValue tv_speed = series.speed_series.max(start_time, end_time); + if (tv_speed != null && (max_speed == AltosLib.MISSING || tv_speed.value > max_speed)) + max_speed = tv_speed.value; + AltosTimeValue tv_accel = series.accel_series.max(start_time, end_time); + if (tv_accel != null && (max_acceleration == AltosLib.MISSING || tv_accel.value > max_acceleration)) + max_acceleration = tv_accel.value; + } + } + } + + AltosTimeValue[] speeds = new AltosTimeValue[AltosLib.ao_flight_invalid + 1]; + AltosTimeValue[] accels = new AltosTimeValue[AltosLib.ao_flight_invalid + 1]; - public AltosFlightStats(AltosStateIterable states) throws InterruptedException, IOException { - double boost_time = boost_time(states); - double end_time = 0; - double landed_time = landed_time(states); + public AltosFlightStats(AltosFlightSeries series) { + AltosCalData cal_data = series.cal_data(); + + series.finish(); + + boost_time = boost_time(series); + landed_time = landed_time(series); + + if (series.state_series != null){ + boolean fixed_boost = false; + boolean fixed_landed = false; + for (AltosTimeValue state : series.state_series) { + if ((int) state.value == AltosLib.ao_flight_boost) + if (boost_time != AltosLib.MISSING && !fixed_boost) { + state.time = boost_time; + fixed_boost = true; + } + if ((int) state.value == AltosLib.ao_flight_landed) + if (landed_time != AltosLib.MISSING && !fixed_landed) { + state.time = landed_time; + fixed_landed = true; + } + } + } year = month = day = AltosLib.MISSING; hour = minute = second = AltosLib.MISSING; @@ -120,96 +190,75 @@ public class AltosFlightStats { has_mag = false; has_orient = false; - for (int s = AltosLib.ao_flight_startup; s <= AltosLib.ao_flight_landed; s++) { - state_count[s] = 0; - state_speed[s] = 0.0; - state_accel[s] = 0.0; + for (int s = 0; s < AltosLib.ao_flight_invalid + 1; s++) { + state_speed[s] = AltosLib.MISSING; + state_accel[s] = AltosLib.MISSING; + state_time[s] = 0; + speeds[s] = new AltosTimeValue(0, 0); + accels[s] = new AltosTimeValue(0, 0); } - for (AltosState state : states) { - if (serial == AltosLib.MISSING && state.serial != AltosLib.MISSING) - serial = state.serial; - if (flight == AltosLib.MISSING && state.flight != AltosLib.MISSING) - flight = state.flight; - if (state.battery_voltage != AltosLib.MISSING) - has_battery = true; - if (state.main_voltage != AltosLib.MISSING) - has_flight_adc = true; - if (state.rssi != AltosLib.MISSING) - has_rssi = true; - end_time = state.time; - - if (state.pressure() != AltosLib.MISSING) - has_flight_data = true; - - int state_id = state.state(); - if (boost_time != AltosLib.MISSING && state.time >= boost_time && state_id < AltosLib.ao_flight_boost) { - state_id = AltosLib.ao_flight_boost; - } - if (landed_time != AltosLib.MISSING && state.time >= landed_time && state_id < AltosLib.ao_flight_landed) { - state_id = AltosLib.ao_flight_landed; - } + max_speed = AltosLib.MISSING; + max_acceleration = AltosLib.MISSING; - if (state.gps != null && state.gps.locked) { - year = state.gps.year; - month = state.gps.month; - day = state.gps.day; - hour = state.gps.hour; - minute = state.gps.minute; - second = state.gps.second; + if (series.state_series != null) { + AltosTimeValue prev = null; + for (AltosTimeValue state : series.state_series) { + if (prev != null) + add_times(series, (int) prev.value, prev.time, state.time); + prev = state; } - max_height = state.max_height(); - max_speed = state.max_speed(); - max_acceleration = state.max_acceleration(); - max_gps_height = state.max_gps_height(); - - if (0 <= state_id && state_id < AltosLib.ao_flight_invalid) { - double acceleration = state.acceleration(); - double speed = state.speed(); - if (acceleration != AltosLib.MISSING && speed != AltosLib.MISSING) { - state_accel[state_id] += acceleration; - state_speed[state_id] += speed; - state_count[state_id]++; + if (prev != null) + add_times(series, (int) prev.value, prev.time, series.accel_series.last().time); + } + + for (int s = 0; s <= AltosLib.ao_flight_invalid; s++) { + if (speeds[s].time > 0) + state_speed[s] = speeds[s].value / speeds[s].time; + if (accels[s].time > 0) + state_accel[s] = accels[s].value / accels[s].time; + } + + product = cal_data.product; + firmware_version = cal_data.firmware_version; + serial = cal_data.serial; + flight = cal_data.flight; + + has_battery = series.battery_voltage_series != null; + has_flight_adc = series.main_voltage_series != null; + has_rssi = series.rssi_series != null; + has_flight_data = series.pressure_series != null; + + AltosGPS gps = series.cal_data().gps_pad; + + if (gps != null) { + year = gps.year; + month = gps.month; + day = gps.day; + hour = gps.hour; + minute = gps.minute; + second = gps.second; + has_gps = true; + lat = pad_lat = gps.lat; + lon = pad_lon = gps.lon; + for (AltosGPSTimeValue gtv : series.gps_series) { + gps = gtv.gps; + if (gps.locked && gps.nsat >= 4) { + lat = gps.lat; + lon = gps.lon; } - if (state_start[state_id] == 0.0) - state_start[state_id] = state.time; - if (state_end[state_id] < state.time) - state_end[state_id] = state.time; - } - if (state.pad_lat != AltosLib.MISSING) { - pad_lat = state.pad_lat; - pad_lon = state.pad_lon; } - if (state.gps != null && state.gps.locked && state.gps.nsat >= 4) { - lat = state.gps.lat; - lon = state.gps.lon; - has_gps = true; - if (state.gps.cc_gps_sat != null) - has_gps_sats = true; - if (state.gps.course != AltosLib.MISSING) - has_gps_detail = true; - } - if (state.imu != null) - has_imu = true; - if (state.mag != null) - has_mag = true; - if (state.orient() != AltosLib.MISSING) - has_orient = true; - if (state.ignitor_voltage != null && state.ignitor_voltage.length > num_ignitor) - num_ignitor = state.ignitor_voltage.length; + } - for (int s = AltosLib.ao_flight_startup; s <= AltosLib.ao_flight_landed; s++) { - if (state_count[s] > 0) { - state_speed[s] /= state_count[s]; - state_accel[s] /= state_count[s]; - } else { - state_speed[s] = AltosLib.MISSING; - state_accel[s] = AltosLib.MISSING; - } - if (state_start[s] == 0) - state_start[s] = end_time; - if (state_end[s] == 0) - state_end[s] = end_time; + + max_height = AltosLib.MISSING; + if (series.height_series != null) + max_height = series.height_series.max().value; + max_gps_height = AltosLib.MISSING; + if (series.gps_height != null) { + AltosTimeValue tv = series.gps_height.max(); + if (tv != null) + max_gps_height = tv.value; } } } diff --git a/altoslib/AltosFontListener.java b/altoslib/AltosFontListener.java index c7f339a0..97947d0b 100644 --- a/altoslib/AltosFontListener.java +++ b/altoslib/AltosFontListener.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public interface AltosFontListener { void font_size_changed(int font_size); diff --git a/altoslib/AltosForce.java b/altoslib/AltosForce.java index 229d04f3..47fb900c 100644 --- a/altoslib/AltosForce.java +++ b/altoslib/AltosForce.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosForce extends AltosUnits { diff --git a/altoslib/AltosFrequency.java b/altoslib/AltosFrequency.java index 3b2a445a..6838be8a 100644 --- a/altoslib/AltosFrequency.java +++ b/altoslib/AltosFrequency.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.util.*; diff --git a/altoslib/AltosGPS.java b/altoslib/AltosGPS.java index 0b30ed45..b6ca3576 100644 --- a/altoslib/AltosGPS.java +++ b/altoslib/AltosGPS.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.text.*; import java.util.concurrent.*; @@ -383,17 +383,13 @@ public class AltosGPS implements Cloneable { } } - static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { + static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException { try { - AltosGPS gps = new AltosGPS(link, config_data); - - if (gps != null) { - state.set_gps(gps, state.gps_sequence++); - return; - } + AltosGPS gps = new AltosGPS(link, link.config_data()); + if (gps != null) + listener.set_gps(gps); } catch (TimeoutException te) { } - state.set_gps(null, 0); } public AltosGPS (AltosLink link, AltosConfigData config_data) throws TimeoutException, InterruptedException { diff --git a/altoslib/AltosGPSSat.java b/altoslib/AltosGPSSat.java index e2f0f380..8d3b316a 100644 --- a/altoslib/AltosGPSSat.java +++ b/altoslib/AltosGPSSat.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.text.*; diff --git a/altoslib/AltosGPSTimeValue.java b/altoslib/AltosGPSTimeValue.java new file mode 100644 index 00000000..e15c60e3 --- /dev/null +++ b/altoslib/AltosGPSTimeValue.java @@ -0,0 +1,28 @@ +/* + * Copyright © 2017 Keith Packard + * + * 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_12; + +public class AltosGPSTimeValue { + public double time; + public AltosGPS gps; + + public AltosGPSTimeValue(double time, AltosGPS gps) { + this.time = time; + this.gps = gps; + } +} diff --git a/altoslib/AltosGreatCircle.java b/altoslib/AltosGreatCircle.java index 6e5bd362..f1cb1940 100644 --- a/altoslib/AltosGreatCircle.java +++ b/altoslib/AltosGreatCircle.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.lang.Math; import java.io.*; diff --git a/altoslib/AltosHeight.java b/altoslib/AltosHeight.java index 0cd495fb..668080f1 100644 --- a/altoslib/AltosHeight.java +++ b/altoslib/AltosHeight.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosHeight extends AltosUnits { diff --git a/altoslib/AltosHexfile.java b/altoslib/AltosHexfile.java index e746b649..7ab121ad 100644 --- a/altoslib/AltosHexfile.java +++ b/altoslib/AltosHexfile.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.util.LinkedList; diff --git a/altoslib/AltosHexsym.java b/altoslib/AltosHexsym.java index 2eb08f75..4f56af9a 100644 --- a/altoslib/AltosHexsym.java +++ b/altoslib/AltosHexsym.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosHexsym { String name; diff --git a/altoslib/AltosIMU.java b/altoslib/AltosIMU.java index f6cadf1d..dee28a92 100644 --- a/altoslib/AltosIMU.java +++ b/altoslib/AltosIMU.java @@ -16,30 +16,32 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.util.concurrent.*; import java.io.*; public class AltosIMU implements Cloneable { - public int accel_along; - public int accel_across; - public int accel_through; + public int accel_x; + public int accel_y; + public int accel_z; - public int gyro_roll; - public int gyro_pitch; - public int gyro_yaw; + public int gyro_x; + public int gyro_y; + public int gyro_z; public static final double counts_per_g = 2048.0; public static double convert_accel(double counts) { - return counts / counts_per_g * (-AltosConvert.GRAVITATIONAL_ACCELERATION); + return counts / counts_per_g * AltosConvert.gravity; } - public static final double counts_per_degsec = 16.4; + /* In radians */ + public static final double GYRO_FULLSCALE_DEGREES = 2000.0; + public static final double GYRO_COUNTS = 32767.0; - public static double convert_gyro(double counts) { - return counts / counts_per_degsec; + public static double gyro_degrees_per_second(double counts, double cal) { + return (counts - cal) * GYRO_FULLSCALE_DEGREES / GYRO_COUNTS; } public boolean parse_string(String line) { @@ -49,12 +51,12 @@ public class AltosIMU implements Cloneable { String[] items = line.split("\\s+"); if (items.length >= 8) { - accel_along = Integer.parseInt(items[1]); - accel_across = Integer.parseInt(items[2]); - accel_through = Integer.parseInt(items[3]); - gyro_roll = Integer.parseInt(items[5]); - gyro_pitch = Integer.parseInt(items[6]); - gyro_yaw = Integer.parseInt(items[7]); + accel_x = Integer.parseInt(items[1]); + accel_y = Integer.parseInt(items[2]); + accel_z = Integer.parseInt(items[3]); + gyro_x = Integer.parseInt(items[5]); + gyro_y = Integer.parseInt(items[6]); + gyro_z = Integer.parseInt(items[7]); } return true; } @@ -62,46 +64,41 @@ public class AltosIMU implements Cloneable { public AltosIMU clone() { AltosIMU n = new AltosIMU(); - n.accel_along = accel_along; - n.accel_across = accel_across; - n.accel_through = accel_through; + n.accel_x = accel_x; + n.accel_y = accel_y; + n.accel_z = accel_z; - n.gyro_roll = gyro_roll; - n.gyro_pitch = gyro_pitch; - n.gyro_yaw = gyro_yaw; + n.gyro_x = gyro_x; + n.gyro_y = gyro_y; + n.gyro_z = gyro_z; return n; } - static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { + static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException { try { AltosIMU imu = new AltosIMU(link); - - if (imu != null) - state.set_imu(imu); + AltosCalData cal_data = listener.cal_data(); + + if (imu != null) { + listener.set_gyro(cal_data.gyro_roll(imu.gyro_y), + cal_data.gyro_pitch(imu.gyro_x), + cal_data.gyro_yaw(imu.gyro_z)); + listener.set_accel_ground(cal_data.accel_along(imu.accel_y), + cal_data.accel_across(imu.accel_x), + cal_data.accel_through(imu.accel_z)); + } } catch (TimeoutException te) { } } public AltosIMU() { - accel_along = AltosLib.MISSING; - accel_across = AltosLib.MISSING; - accel_through = AltosLib.MISSING; - - gyro_roll = AltosLib.MISSING; - gyro_pitch = AltosLib.MISSING; - gyro_yaw = AltosLib.MISSING; - } - - public AltosIMU(int accel_along, int accel_across, int accel_through, - int gyro_roll, int gyro_pitch, int gyro_yaw) { - - this.accel_along = accel_along; - this.accel_across = accel_across; - this.accel_through = accel_through; + accel_x = AltosLib.MISSING; + accel_y = AltosLib.MISSING; + accel_z = AltosLib.MISSING; - this.gyro_roll = gyro_roll; - this.gyro_pitch = gyro_pitch; - this.gyro_yaw = gyro_yaw; + gyro_x = AltosLib.MISSING; + gyro_y = AltosLib.MISSING; + gyro_z = AltosLib.MISSING; } public AltosIMU(AltosLink link) throws InterruptedException, TimeoutException { diff --git a/altoslib/AltosIdle.java b/altoslib/AltosIdle.java index d37af966..b5ee20d0 100644 --- a/altoslib/AltosIdle.java +++ b/altoslib/AltosIdle.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.util.*; diff --git a/altoslib/AltosIdleFetch.java b/altoslib/AltosIdleFetch.java index 73717e17..058df0a1 100644 --- a/altoslib/AltosIdleFetch.java +++ b/altoslib/AltosIdleFetch.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.util.*; @@ -30,61 +30,62 @@ class AltosIdler { static final int idle_gps = 0; static final int idle_imu = 1; static final int idle_mag = 2; - static final int idle_ms5607 = 3; static final int idle_mma655x = 4; + static final int idle_ms5607 = 5; static final int idle_sensor_tm = 10; static final int idle_sensor_metrum = 11; static final int idle_sensor_mega = 12; - static final int idle_sensor_emini = 13; - static final int idle_sensor_tmini2 = 14; - static final int idle_sensor_tgps = 15; - static final int idle_sensor_tmini3 = 16; + static final int idle_sensor_emini1 = 13; + static final int idle_sensor_emini2 = 14; + static final int idle_sensor_tmini2 = 15; + static final int idle_sensor_tgps = 16; + static final int idle_sensor_tmini3 = 17; - public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException, TimeoutException, AltosUnknownProduct { + public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException, TimeoutException, AltosUnknownProduct { for (int idler : idlers) { - AltosIdle idle = null; switch (idler) { case idle_gps: - AltosGPS.update_state(state, link, config_data); + AltosGPS.provide_data(listener, link); break; case idle_imu: - AltosIMU.update_state(state, link, config_data); + AltosIMU.provide_data(listener, link); break; case idle_mag: - AltosMag.update_state(state, link, config_data); - break; - case idle_ms5607: - AltosMs5607.update_state(state, link, config_data); + AltosMag.provide_data(listener, link); break; case idle_mma655x: - AltosMma655x.update_state(state, link, config_data); + AltosMma655x.provide_data(listener, link); + break; + case idle_ms5607: + AltosMs5607.provide_data(listener, link); break; case idle_sensor_tm: - AltosSensorTM.update_state(state, link, config_data); + AltosSensorTM.provide_data(listener, link); break; case idle_sensor_metrum: - AltosSensorMetrum.update_state(state, link, config_data); + AltosSensorMetrum.provide_data(listener, link); break; case idle_sensor_mega: - AltosSensorMega.update_state(state, link, config_data); + AltosSensorMega.provide_data(listener, link); + break; + case idle_sensor_emini1: + AltosSensorEMini.provide_data(listener, link, 1); break; - case idle_sensor_emini: - AltosSensorEMini.update_state(state, link, config_data); + case idle_sensor_emini2: + AltosSensorEMini.provide_data(listener, link, 2); break; case idle_sensor_tmini2: - AltosSensorTMini2.update_state(state, link, config_data); + AltosSensorTMini2.provide_data(listener, link); break; case idle_sensor_tgps: - AltosSensorTGPS.update_state(state, link, config_data); + AltosSensorTGPS.provide_data(listener, link); break; case idle_sensor_tmini3: - AltosSensorTMini3.update_state(state, link, config_data); + AltosSensorTMini3.provide_data(listener, link); break; } - if (idle != null) - idle.update_state(state); } } @@ -99,13 +100,17 @@ class AltosIdler { } -public class AltosIdleFetch implements AltosStateUpdate { +public class AltosIdleFetch implements AltosDataProvider { static final AltosIdler[] idlers = { - new AltosIdler("EasyMini", + new AltosIdler("EasyMini-v1", AltosIdler.idle_ms5607, - AltosIdler.idle_sensor_emini), + AltosIdler.idle_sensor_emini1), + + new AltosIdler("EasyMini-v2", + AltosIdler.idle_ms5607, + AltosIdler.idle_sensor_emini2), new AltosIdler("TeleMini-v1", AltosIdler.idle_sensor_tm), @@ -124,16 +129,19 @@ public class AltosIdleFetch implements AltosStateUpdate { new AltosIdler("TeleMetrum-v2", AltosIdler.idle_gps, - AltosIdler.idle_ms5607, AltosIdler.idle_mma655x, + AltosIdler.idle_mma655x, + AltosIdler.idle_ms5607, AltosIdler.idle_sensor_metrum), new AltosIdler("TeleMega", AltosIdler.idle_gps, - AltosIdler.idle_ms5607, AltosIdler.idle_mma655x, + AltosIdler.idle_mma655x, + AltosIdler.idle_ms5607, AltosIdler.idle_imu, AltosIdler.idle_mag, AltosIdler.idle_sensor_mega), new AltosIdler("EasyMega", - AltosIdler.idle_ms5607, AltosIdler.idle_mma655x, + AltosIdler.idle_mma655x, + AltosIdler.idle_ms5607, AltosIdler.idle_imu, AltosIdler.idle_mag, AltosIdler.idle_sensor_mega), new AltosIdler("TeleGPS", @@ -143,29 +151,22 @@ public class AltosIdleFetch implements AltosStateUpdate { AltosLink link; - public void update_state(AltosState state) throws InterruptedException, AltosUnknownProduct { + public void provide_data(AltosDataListener listener) throws InterruptedException, AltosUnknownProduct { try { boolean matched = false; /* Fetch config data from remote */ AltosConfigData config_data = new AltosConfigData(link); - state.set_state(AltosLib.ao_flight_stateless); - state.set_serial(config_data.serial); - state.set_callsign(config_data.callsign); - state.set_ground_accel(config_data.accel_cal_plus); - state.set_accel_g(config_data.accel_cal_plus, config_data.accel_cal_minus); - state.set_product(config_data.product); - state.set_firmware_version(config_data.version); - state.set_log_space(config_data.log_space); + listener.set_state(AltosLib.ao_flight_stateless); for (AltosIdler idler : idlers) { if (idler.matches(config_data)) { - idler.update_state(state, link, config_data); + idler.provide_data(listener, link); matched = true; break; } } if (!matched) throw new AltosUnknownProduct(config_data.product); - state.set_received_time(System.currentTimeMillis()); + listener.set_received_time(System.currentTimeMillis()); } catch (TimeoutException te) { } diff --git a/altoslib/AltosIdleMonitor.java b/altoslib/AltosIdleMonitor.java index c374b601..fc5d4cc8 100644 --- a/altoslib/AltosIdleMonitor.java +++ b/altoslib/AltosIdleMonitor.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.util.concurrent.*; @@ -52,20 +52,20 @@ public class AltosIdleMonitor extends Thread { return link.reply_abort; } - boolean update_state(AltosState state) throws InterruptedException, TimeoutException, AltosUnknownProduct { + boolean provide_data(AltosDataListener listener) throws InterruptedException, TimeoutException, AltosUnknownProduct { boolean worked = false; boolean aborted = false; try { start_link(); - fetch.update_state(state); + fetch.provide_data(listener); if (!link.has_error && !link.reply_abort) worked = true; } finally { aborted = stop_link(); if (worked) { if (remote) - state.set_rssi(link.rssi(), 0); + listener.set_rssi(link.rssi(), 0); listener_state.battery = link.monitor_battery(); } } @@ -92,12 +92,14 @@ public class AltosIdleMonitor extends Thread { } public void run() { - AltosState state = new AltosState(); + AltosState state = null; try { for (;;) { try { link.config_data(); - update_state(state); + if (state == null) + state = new AltosState(new AltosCalData(link.config_data())); + provide_data(state); listener.update(state, listener_state); } catch (TimeoutException te) { } catch (AltosUnknownProduct ae) { diff --git a/altoslib/AltosIdleMonitorListener.java b/altoslib/AltosIdleMonitorListener.java index 3349e9c4..1ddec09a 100644 --- a/altoslib/AltosIdleMonitorListener.java +++ b/altoslib/AltosIdleMonitorListener.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public interface AltosIdleMonitorListener { public void update(AltosState state, AltosListenerState listener_state); diff --git a/altoslib/AltosIdleReader.java b/altoslib/AltosIdleReader.java index 5903c968..d15e2174 100644 --- a/altoslib/AltosIdleReader.java +++ b/altoslib/AltosIdleReader.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.text.*; import java.io.*; @@ -25,6 +25,7 @@ import java.util.concurrent.*; public class AltosIdleReader extends AltosFlightReader { AltosLink link; boolean remote; + AltosCalData cal_data = null; AltosState state = null; AltosIdleFetch fetch; long next_millis; @@ -44,15 +45,23 @@ public class AltosIdleReader extends AltosFlightReader { return link.reply_abort; } + public AltosCalData cal_data() { + if (cal_data == null) { + try { + cal_data = new AltosCalData(link.config_data()); + } catch (InterruptedException ie) { + } catch (TimeoutException te) { + } + if (cal_data == null) + cal_data = new AltosCalData(); + } + return cal_data; + } + public AltosState read() throws InterruptedException, ParseException, AltosCRCException, IOException { boolean worked = false; boolean aborted = false; - if (state == null) - state = new AltosState(); - else - state = state.clone(); - long delay = next_millis - System.currentTimeMillis(); if (delay > 0) @@ -61,7 +70,9 @@ public class AltosIdleReader extends AltosFlightReader { try { try { start_link(); - fetch.update_state(state); + if (state == null) + state = new AltosState(cal_data()); + fetch.provide_data(state); if (!link.has_error && !link.reply_abort) worked = true; } catch (TimeoutException te) { diff --git a/altoslib/AltosIgnite.java b/altoslib/AltosIgnite.java index cdc5c614..767c00fb 100644 --- a/altoslib/AltosIgnite.java +++ b/altoslib/AltosIgnite.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.util.*; import java.io.*; @@ -102,7 +102,7 @@ public class AltosIgnite { private void get_npyro() throws InterruptedException, TimeoutException { if (config_data == null) config_data = new AltosConfigData(link); - if (config_data != null) + if (config_data != null && config_data.npyro != AltosLib.MISSING) npyro = config_data.npyro; else npyro = 0; @@ -174,6 +174,7 @@ public class AltosIgnite { try { start_link(); link.printf("i DoIt %s\n", igniter); + link.flush_output(); } catch (TimeoutException te) { } finally { stop_link(); diff --git a/altoslib/AltosImage.java b/altoslib/AltosImage.java index 2e32b720..abe9d56f 100644 --- a/altoslib/AltosImage.java +++ b/altoslib/AltosImage.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; diff --git a/altoslib/AltosJson.java b/altoslib/AltosJson.java index 9191be68..52c9b41e 100644 --- a/altoslib/AltosJson.java +++ b/altoslib/AltosJson.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.util.*; @@ -255,7 +255,7 @@ class JsonToken { * Lexer for json */ class JsonLexer extends JsonUtil { - Reader f; + InputStream f; int line; int ungot = -2; StringBuffer pending_token; @@ -445,12 +445,12 @@ class JsonLexer extends JsonUtil { } JsonLexer(String s) { - f = new StringReader(s); + f = new AltosStringInputStream(s); line = 1; token = null; } - JsonLexer(Reader f) { + JsonLexer(InputStream f) { this.f = f; line = 1; token = null; @@ -570,7 +570,7 @@ class JsonParse { lexer = new JsonLexer(s); } - JsonParse(Reader f) { + JsonParse(InputStream f) { lexer = new JsonLexer(f); } } @@ -670,7 +670,7 @@ public class AltosJson extends JsonUtil { } } - public static AltosJson fromReader(Reader f) { + public static AltosJson fromInputStream(InputStream f) { JsonParse parse = new JsonParse(f); try { return parse.parse(); diff --git a/altoslib/AltosKML.java b/altoslib/AltosKML.java index 25108bf9..1c025ef4 100644 --- a/altoslib/AltosKML.java +++ b/altoslib/AltosKML.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.util.*; @@ -36,8 +36,9 @@ public class AltosKML implements AltosWriter { File name; PrintWriter out; int flight_state = -1; - AltosState prev = null; - double gps_start_altitude; + AltosGPS prev = null; + double gps_start_altitude = AltosLib.MISSING; + AltosFlightStats stats; static final String[] kml_state_colors = { "FF000000", // startup @@ -101,42 +102,47 @@ public class AltosKML implements AltosWriter { "\n" + "\n"; - void start (AltosState record) { - out.printf(kml_header_start, record.flight, record.serial); + void start (AltosCalData cal_data) { + AltosGPS gps = cal_data.gps_pad; + + gps_start_altitude = cal_data.gps_pad_altitude; + out.printf(kml_header_start, cal_data.flight, cal_data.serial); out.printf("Date: %04d-%02d-%02d\n", - record.gps.year, record.gps.month, record.gps.day); + gps.year, gps.month, gps.day); out.printf("Time: %2d:%02d:%02d\n", - record.gps.hour, record.gps.minute, record.gps.second); + gps.hour, gps.minute, gps.second); out.printf("%s", kml_header_end); } boolean started = false; - void state_start(AltosState state) { - String state_name = AltosLib.state_name(state.state()); - String state_color = state_color(state.state()); + void state_start(int state) { + String state_name = AltosLib.state_name(state); + String state_color = state_color(state); out.printf(kml_style_start, state_name, state_color); - out.printf("\tState: %s\n", state_name); + out.printf("State: %s\n", state_name); + out.printf("Time: %6.2f s\n", stats.state_end[state] - stats.state_start[state]); + out.printf("Average speed: %s\n", AltosConvert.speed.show(6, stats.state_speed[state])); + out.printf("Average accel: %s\n", AltosConvert.accel.show(6, stats.state_accel[state])); out.printf("%s", kml_style_end); out.printf(kml_placemark_start, state_name, state_name); } - void state_end(AltosState state) { + void state_end() { out.printf("%s", kml_placemark_end); } - void coord(AltosState state) { - AltosGPS gps = state.gps; + void coord(double time, AltosGPS gps, int state, double height) { double altitude; - if (state.height() != AltosLib.MISSING) - altitude = state.height() + gps_start_altitude; + if (height != AltosLib.MISSING) + altitude = height + gps_start_altitude; else altitude = gps.alt; out.printf(kml_coord_fmt, gps.lon, gps.lat, altitude, (double) gps.alt, - state.time, gps.nsat); + time, gps.nsat); } void end() { @@ -145,7 +151,7 @@ public class AltosKML implements AltosWriter { public void close() { if (prev != null) { - state_end(prev); + state_end(); end(); prev = null; } @@ -155,40 +161,37 @@ public class AltosKML implements AltosWriter { } } - public void write(AltosState state) { - AltosGPS gps = state.gps; - - if (gps == null) - return; - + public void write(AltosGPSTimeValue gtv, AltosCalData cal_data, int state, double height) { + AltosGPS gps = gtv.gps; if (gps.lat == AltosLib.MISSING) return; if (gps.lon == AltosLib.MISSING) return; - if (!started) { - start(state); - started = true; - gps_start_altitude = gps.alt; - } - if (prev != null && prev.gps_sequence == state.gps_sequence) - return; - if (state.state() != flight_state) { - flight_state = state.state(); + if (state != flight_state) { + flight_state = state; if (prev != null) { - coord(state); - state_end(prev); + coord(gtv.time, gps, state, height); + state_end(); } state_start(state); } - coord(state); - prev = state; + coord(0, gps, state, height); + prev = gps; } - public void write(AltosStateIterable states) { - for (AltosState state : states) { - if ((state.set & AltosState.set_gps) != 0) - write(state); - } + private int state(AltosFlightSeries series, double time) { + return (int) series.value_before(AltosFlightSeries.state_name, time); + } + + private double height(AltosFlightSeries series, double time) { + return series.value(AltosFlightSeries.height_name, time); + } + + public void write(AltosFlightSeries series) { + stats = new AltosFlightStats(series); + start(series.cal_data()); + for (AltosGPSTimeValue gtv : series.gps_series) + write(gtv, series.cal_data(), state(series, gtv.time), height(series, gtv.time)); } public AltosKML(File in_name) throws FileNotFoundException { diff --git a/altoslib/AltosLatLon.java b/altoslib/AltosLatLon.java index 5865d3cc..6fcc43fe 100644 --- a/altoslib/AltosLatLon.java +++ b/altoslib/AltosLatLon.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosLatLon { public double lat; diff --git a/altoslib/AltosLatitude.java b/altoslib/AltosLatitude.java index 4663cd09..f43397d0 100644 --- a/altoslib/AltosLatitude.java +++ b/altoslib/AltosLatitude.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosLatitude extends AltosLocation { public String pos() { return "N"; } diff --git a/altoslib/AltosLaunchSite.java b/altoslib/AltosLaunchSite.java index 8a06cdb2..19fb4858 100644 --- a/altoslib/AltosLaunchSite.java +++ b/altoslib/AltosLaunchSite.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.lang.*; diff --git a/altoslib/AltosLaunchSiteListener.java b/altoslib/AltosLaunchSiteListener.java index d2ee601e..0d926353 100644 --- a/altoslib/AltosLaunchSiteListener.java +++ b/altoslib/AltosLaunchSiteListener.java @@ -15,7 +15,7 @@ * 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_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.lang.*; diff --git a/altoslib/AltosLaunchSites.java b/altoslib/AltosLaunchSites.java index d5c41c82..365f19e3 100644 --- a/altoslib/AltosLaunchSites.java +++ b/altoslib/AltosLaunchSites.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.lang.*; diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java index a3f164d4..d1063509 100644 --- a/altoslib/AltosLib.java +++ b/altoslib/AltosLib.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.util.*; import java.io.*; @@ -38,6 +38,20 @@ public class AltosLib { public static final int AO_LOG_GPS_DATE = 'Y'; public static final int AO_LOG_PRESSURE = 'P'; + public static boolean is_gps_cmd(int cmd) { + switch (cmd) { + case AltosLib.AO_LOG_GPS_POS: + case AltosLib.AO_LOG_GPS_TIME: + 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: + return true; + } + return false; + } + /* Added for header fields in eeprom files */ public static final int AO_LOG_CONFIG_VERSION = 1000; public static final int AO_LOG_MAIN_DEPLOY = 1001; @@ -162,6 +176,16 @@ public class AltosLib { return product_any; } + public static boolean has_9dof(int device_type) { + return device_type == product_telemega || device_type == product_easymega; + } + + public static boolean has_gps(int device_type) { + return device_type == product_telemetrum || + device_type == product_telemega || + device_type == product_telegps; + } + /* Bluetooth "identifier" (bluetooth sucks) */ public final static String bt_product_telebt = "TeleBT"; @@ -330,7 +354,7 @@ public class AltosLib { public static final int AO_LOG_FORMAT_TELEMETRY = 3; public static final int AO_LOG_FORMAT_TELESCIENCE = 4; public static final int AO_LOG_FORMAT_TELEMEGA_OLD = 5; - public static final int AO_LOG_FORMAT_EASYMINI = 6; + public static final int AO_LOG_FORMAT_EASYMINI1 = 6; public static final int AO_LOG_FORMAT_TELEMETRUM = 7; public static final int AO_LOG_FORMAT_TELEMINI2 = 8; public static final int AO_LOG_FORMAT_TELEGPS = 9; @@ -338,6 +362,7 @@ public class AltosLib { public static final int AO_LOG_FORMAT_DETHERM = 11; public static final int AO_LOG_FORMAT_TELEMINI3 = 12; public static final int AO_LOG_FORMAT_TELEFIRETWO = 13; + public static final int AO_LOG_FORMAT_EASYMINI2 = 14; public static final int AO_LOG_FORMAT_NONE = 127; public static boolean isspace(int c) { @@ -561,7 +586,31 @@ public class AltosLib { } } - public static String ignitor_name(int i) { + public static String igniter_name(int i) { return String.format("Ignitor %c", 'A' + i); } + + public static AltosRecordSet record_set(File file) throws FileNotFoundException, IOException { + FileInputStream in; + in = new FileInputStream(file); + if (file.getName().endsWith("telem")) { + return new AltosTelemetryFile(in); + } else if (file.getName().endsWith("eeprom")) { + return new AltosEepromFile(in); + } else { + String name = file.getName(); + int dot = name.lastIndexOf('.'); + String extension; + + if (dot == -1) + throw new IOException(String.format("%s (Missing extension)", file.toString())); + else { + extension = name.substring(dot); + throw new IOException(String.format("%s (Invalid extension '%s')", + file.toString(), + extension)); + } + } + } + } diff --git a/altoslib/AltosLine.java b/altoslib/AltosLine.java index 952a21e3..b3833f64 100644 --- a/altoslib/AltosLine.java +++ b/altoslib/AltosLine.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosLine { public String line; diff --git a/altoslib/AltosLink.java b/altoslib/AltosLink.java index d75c9aa0..5a802ef1 100644 --- a/altoslib/AltosLink.java +++ b/altoslib/AltosLink.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.util.concurrent.*; diff --git a/altoslib/AltosListenerState.java b/altoslib/AltosListenerState.java index 80bc0df2..949d2271 100644 --- a/altoslib/AltosListenerState.java +++ b/altoslib/AltosListenerState.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; diff --git a/altoslib/AltosLocation.java b/altoslib/AltosLocation.java index c612caaa..45831004 100644 --- a/altoslib/AltosLocation.java +++ b/altoslib/AltosLocation.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public abstract class AltosLocation extends AltosUnits { diff --git a/altoslib/AltosLog.java b/altoslib/AltosLog.java index 6d873d78..44bea646 100644 --- a/altoslib/AltosLog.java +++ b/altoslib/AltosLog.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.text.*; @@ -61,8 +61,8 @@ public class AltosLog implements Runnable { return file; } - boolean open (AltosState state) throws IOException, InterruptedException { - AltosFile a = new AltosFile(state); + boolean open (AltosCalData cal_data) throws IOException, InterruptedException { + AltosFile a = new AltosFile(cal_data); log_file = new FileWriter(a, true); if (log_file != null) { @@ -80,24 +80,31 @@ public class AltosLog implements Runnable { public void run () { try { - AltosState state = new AltosState(); AltosConfigData receiver_config = link.config_data(); - state.set_receiver_serial(receiver_config.serial); + AltosCalData cal_data = new AltosCalData(); + AltosState state = null; + cal_data.set_receiver_serial(receiver_config.serial); for (;;) { AltosLine line = input_queue.take(); if (line.line == null) continue; try { AltosTelemetry telem = AltosTelemetry.parse(line.line); - state = state.clone(); - telem.update_state(state); - if (state.serial != serial || state.flight != flight || log_file == null) + if (state == null) + state = new AltosState(cal_data); + telem.provide_data(state); + + if (cal_data.serial != serial || + cal_data.flight != flight || + log_file == null) { close_log_file(); - serial = state.serial; - flight = state.flight; - if (state.serial != AltosLib.MISSING && state.flight != AltosLib.MISSING) - open(state); + serial = cal_data.serial; + flight = cal_data.flight; + state = null; + if (cal_data.serial != AltosLib.MISSING && + cal_data.flight != AltosLib.MISSING) + open(cal_data); } } catch (ParseException pe) { } catch (AltosCRCException ce) { diff --git a/altoslib/AltosLongitude.java b/altoslib/AltosLongitude.java index 4c6d1857..b2134cbb 100644 --- a/altoslib/AltosLongitude.java +++ b/altoslib/AltosLongitude.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosLongitude extends AltosLocation { public String pos() { return "E"; } diff --git a/altoslib/AltosMag.java b/altoslib/AltosMag.java index e89ec0de..0d8ec69f 100644 --- a/altoslib/AltosMag.java +++ b/altoslib/AltosMag.java @@ -16,15 +16,15 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.util.concurrent.*; import java.io.*; public class AltosMag implements Cloneable { - public int along; - public int across; - public int through; + public int x; + public int z; + public int y; public static final double counts_per_gauss = 1090; @@ -33,10 +33,6 @@ public class AltosMag implements Cloneable { } public boolean parse_string(String line) { -// if (line.startsWith("Syntax error")) { -// along = across = through = 0; -// return true; -// } if (!line.startsWith("X:")) return false; @@ -44,9 +40,9 @@ public class AltosMag implements Cloneable { String[] items = line.split("\\s+"); if (items.length >= 6) { - along = Integer.parseInt(items[1]); - across = Integer.parseInt(items[3]); - through = Integer.parseInt(items[5]); + x = Integer.parseInt(items[1]); + z = Integer.parseInt(items[3]); + y = Integer.parseInt(items[5]); } return true; } @@ -54,30 +50,27 @@ public class AltosMag implements Cloneable { public AltosMag clone() { AltosMag n = new AltosMag(); - n.along = along; - n.across = across; - n.through = through; + n.x = x; + n.z = z; + n.y = y; return n; } public AltosMag() { - along = AltosLib.MISSING; - across = AltosLib.MISSING; - through = AltosLib.MISSING; + x = AltosLib.MISSING; + z = AltosLib.MISSING; + y = AltosLib.MISSING; } - public AltosMag(int along, int across, int through) { - this.along = along; - this.across = across; - this.through = through; - } - - static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { + static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException { try { AltosMag mag = new AltosMag(link); + AltosCalData cal_data = listener.cal_data(); if (mag != null) - state.set_mag(mag); + listener.set_mag(cal_data.mag_along(mag.y), + cal_data.mag_across(mag.x), + cal_data.mag_through(mag.z)); } catch (TimeoutException te) { } } diff --git a/altoslib/AltosMap.java b/altoslib/AltosMap.java index e3c4a6a7..286cf1bb 100644 --- a/altoslib/AltosMap.java +++ b/altoslib/AltosMap.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.lang.*; @@ -220,11 +220,11 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener { return false; } - public void show(AltosState state, AltosListenerState listener_state) { + public void show(AltosGPS gps, int state) { - /* If insufficient gps data, nothing to update + /* + * If insufficient gps data, nothing to update */ - AltosGPS gps = state.gps; if (gps == null) return; @@ -232,23 +232,23 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener { if (!gps.locked && gps.nsat < 4) return; - switch (state.state()) { + switch (state) { case AltosLib.ao_flight_boost: if (!have_boost) { - add_mark(gps.lat, gps.lon, state.state()); + add_mark(gps.lat, gps.lon, state); have_boost = true; } break; case AltosLib.ao_flight_landed: if (!have_landed) { - add_mark(gps.lat, gps.lon, state.state()); + add_mark(gps.lat, gps.lon, state); have_landed = true; } break; } if (path != null) { - AltosMapRectangle damage = path.add(gps.lat, gps.lon, state.state()); + AltosMapRectangle damage = path.add(gps.lat, gps.lon, state); if (damage != null) repaint(damage, AltosMapPath.stroke_width); @@ -259,6 +259,10 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener { maybe_centre(gps.lat, gps.lon); } + public void show(AltosState state, AltosListenerState listener_state) { + show(state.gps, state.state()); + } + public void centre(AltosLatLon lat_lon) { centre = lat_lon; set_transform(); @@ -268,10 +272,14 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener { centre(new AltosLatLon(lat, lon)); } - public void centre(AltosState state) { - if (!state.gps.locked && state.gps.nsat < 4) + public void centre(AltosGPS gps) { + if (!gps.locked && gps.nsat < 4) return; - centre(state.gps.lat, state.gps.lon); + centre(gps.lat, gps.lon); + } + + public void centre(AltosState state) { + centre(state.gps); } public void maybe_centre(double lat, double lon) { diff --git a/altoslib/AltosMapCache.java b/altoslib/AltosMapCache.java index 4e529177..54d2dbdd 100644 --- a/altoslib/AltosMapCache.java +++ b/altoslib/AltosMapCache.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.net.*; diff --git a/altoslib/AltosMapCacheListener.java b/altoslib/AltosMapCacheListener.java index 057d1c43..8c07e3c1 100644 --- a/altoslib/AltosMapCacheListener.java +++ b/altoslib/AltosMapCacheListener.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public interface AltosMapCacheListener { public void map_cache_changed(int map_cache); diff --git a/altoslib/AltosMapInterface.java b/altoslib/AltosMapInterface.java index a2ea81db..5089db64 100644 --- a/altoslib/AltosMapInterface.java +++ b/altoslib/AltosMapInterface.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.net.*; diff --git a/altoslib/AltosMapLine.java b/altoslib/AltosMapLine.java index c475f52d..f2174935 100644 --- a/altoslib/AltosMapLine.java +++ b/altoslib/AltosMapLine.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.lang.Math; @@ -44,39 +44,9 @@ public abstract class AltosMapLine { } public String line_dist() { - String format; AltosGreatCircle g = new AltosGreatCircle(start.lat, start.lon, end.lat, end.lon); - double distance = g.distance; - if (AltosConvert.imperial_units) { - distance = AltosConvert.meters_to_feet(distance); - if (distance < 1000) { - format = "%4.0fft"; - } else { - distance /= 5280; - if (distance < 10) - format = "%5.3fmi"; - else if (distance < 100) - format = "%5.2fmi"; - else if (distance < 1000) - format = "%5.1fmi"; - else - format = "%5.0fmi"; - } - } else { - if (distance < 1000) { - format = "%4.0fm"; - } else { - distance /= 1000; - if (distance < 100) - format = "%5.2fkm"; - else if (distance < 1000) - format = "%5.1fkm"; - else - format = "%5.0fkm"; - } - } - return String.format(format, distance); + return AltosConvert.distance.show(7, g.distance); } } diff --git a/altoslib/AltosMapLoader.java b/altoslib/AltosMapLoader.java index 17e88bf4..b57591df 100644 --- a/altoslib/AltosMapLoader.java +++ b/altoslib/AltosMapLoader.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.util.*; diff --git a/altoslib/AltosMapLoaderListener.java b/altoslib/AltosMapLoaderListener.java index 07624f80..7f36c002 100644 --- a/altoslib/AltosMapLoaderListener.java +++ b/altoslib/AltosMapLoaderListener.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public interface AltosMapLoaderListener { public abstract void loader_start(int max); diff --git a/altoslib/AltosMapMark.java b/altoslib/AltosMapMark.java index cbe7bebe..4ef179ef 100644 --- a/altoslib/AltosMapMark.java +++ b/altoslib/AltosMapMark.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.lang.Math; diff --git a/altoslib/AltosMapPath.java b/altoslib/AltosMapPath.java index c2335169..1542a4e9 100644 --- a/altoslib/AltosMapPath.java +++ b/altoslib/AltosMapPath.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.lang.Math; diff --git a/altoslib/AltosMapPathPoint.java b/altoslib/AltosMapPathPoint.java index 5182ecfd..409a6a5c 100644 --- a/altoslib/AltosMapPathPoint.java +++ b/altoslib/AltosMapPathPoint.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.lang.Math; diff --git a/altoslib/AltosMapRectangle.java b/altoslib/AltosMapRectangle.java index a2321e19..0751aa33 100644 --- a/altoslib/AltosMapRectangle.java +++ b/altoslib/AltosMapRectangle.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosMapRectangle { AltosLatLon ul, lr; diff --git a/altoslib/AltosMapStore.java b/altoslib/AltosMapStore.java index 7cce05a5..4eba3a04 100644 --- a/altoslib/AltosMapStore.java +++ b/altoslib/AltosMapStore.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.net.*; @@ -91,6 +91,7 @@ public class AltosMapStore { static Object forbidden_lock = new Object(); static long forbidden_time; static boolean forbidden_set; + public static int forbidden_response; private int fetch_url() { URL u; @@ -116,6 +117,7 @@ public class AltosMapStore { synchronized (forbidden_lock) { forbidden_time = System.nanoTime(); forbidden_set = true; + forbidden_response = response; return AltosMapTile.forbidden; } } diff --git a/altoslib/AltosMapStoreListener.java b/altoslib/AltosMapStoreListener.java index e3935201..1fb7194a 100644 --- a/altoslib/AltosMapStoreListener.java +++ b/altoslib/AltosMapStoreListener.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public interface AltosMapStoreListener { abstract void notify_store(AltosMapStore store, int status); diff --git a/altoslib/AltosMapTile.java b/altoslib/AltosMapTile.java index 4d6dc8d1..4b01e437 100644 --- a/altoslib/AltosMapTile.java +++ b/altoslib/AltosMapTile.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.util.*; diff --git a/altoslib/AltosMapTileListener.java b/altoslib/AltosMapTileListener.java index 219dcd07..3c6275a0 100644 --- a/altoslib/AltosMapTileListener.java +++ b/altoslib/AltosMapTileListener.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public interface AltosMapTileListener { abstract public void notify_tile(AltosMapTile tile, int status); diff --git a/altoslib/AltosMapTransform.java b/altoslib/AltosMapTransform.java index 266557b6..b6d4f435 100644 --- a/altoslib/AltosMapTransform.java +++ b/altoslib/AltosMapTransform.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.lang.Math; diff --git a/altoslib/AltosMapTypeListener.java b/altoslib/AltosMapTypeListener.java index 1d5e2b47..94401a00 100644 --- a/altoslib/AltosMapTypeListener.java +++ b/altoslib/AltosMapTypeListener.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public interface AltosMapTypeListener { public void map_type_changed(int map_type); diff --git a/altoslib/AltosMapZoomListener.java b/altoslib/AltosMapZoomListener.java index 93c26cbb..c4a0acd6 100644 --- a/altoslib/AltosMapZoomListener.java +++ b/altoslib/AltosMapZoomListener.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public interface AltosMapZoomListener { abstract public void zoom_changed(int zoom); diff --git a/altoslib/AltosMma655x.java b/altoslib/AltosMma655x.java index 503eb5fd..0f6022ac 100644 --- a/altoslib/AltosMma655x.java +++ b/altoslib/AltosMma655x.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.util.concurrent.*; @@ -46,17 +46,18 @@ public class AltosMma655x implements Cloneable { return n; } - static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException, AltosUnknownProduct { + static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException, AltosUnknownProduct { try { AltosMma655x mma655x = new AltosMma655x(link); + AltosCalData cal_data = listener.cal_data(); if (mma655x != null) { int accel = mma655x.accel; - if (config_data.mma655x_inverted()) + if (cal_data.mma655x_inverted) accel = 4095 - accel; - if (config_data.pad_orientation == 1) + if (cal_data.pad_orientation == 1) accel = 4095 - accel; - state.set_accel(accel); + listener.set_acceleration(cal_data.acceleration(accel)); } } catch (TimeoutException te) { } catch (NumberFormatException ne) { diff --git a/altoslib/AltosMs5607.java b/altoslib/AltosMs5607.java index c598d01e..5b3ba65d 100644 --- a/altoslib/AltosMs5607.java +++ b/altoslib/AltosMs5607.java @@ -16,34 +16,42 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.util.concurrent.*; import java.io.*; public class AltosMs5607 { - public int reserved; - public int sens; - public int off; - public int tcs; - public int tco; - public int tref; - public int tempsens; - public int crc; - - public int raw_pres; - public int raw_temp; - public int pa; - public int cc; - - static final boolean ms5611 = false; - - void convert() { + public int reserved = AltosLib.MISSING; + public int sens = AltosLib.MISSING; + public int off = AltosLib.MISSING; + public int tcs = AltosLib.MISSING; + public int tco = AltosLib.MISSING; + public int tref = AltosLib.MISSING; + public int tempsens = AltosLib.MISSING; + public int crc = AltosLib.MISSING; + private boolean ms5611 = false; + + public boolean valid_config() { + return reserved != AltosLib.MISSING && + sens != AltosLib.MISSING && + off != AltosLib.MISSING && + tcs != AltosLib.MISSING && + tco != AltosLib.MISSING && + tref != AltosLib.MISSING && + tempsens != AltosLib.MISSING && + crc != AltosLib.MISSING; + } + + public AltosPresTemp pres_temp(int raw_pres, int raw_temp) { int dT; - int TEMP; - long OFF; - long SENS; - //int P; + int TEMP; + long OFF; + long SENS; + int P; + + if (raw_pres == AltosLib.MISSING || raw_temp == AltosLib.MISSING) + return new AltosPresTemp(AltosLib.MISSING, AltosLib.MISSING); dT = raw_temp - ((int) tref << 8); @@ -75,111 +83,75 @@ public class AltosMs5607 { SENS -= SENS2; } - pa = (int) (((((long) raw_pres * SENS) >> 21) - OFF) >> 15); - cc = TEMP; - } + P = (int) (((((long) raw_pres * SENS) >> 21) - OFF) >> 15); - public int set(int in_pres, int in_temp) { - raw_pres = in_pres; - raw_temp = in_temp; - convert(); - return pa; + return new AltosPresTemp(P, TEMP / 100.0); } - public boolean parse_line(String line) { - String[] items = line.split("\\s+"); - if (line.startsWith("Pressure:")) { - if (items.length >= 2) { - raw_pres = Integer.parseInt(items[1]); - } - } else if (line.startsWith("Temperature:")) { - if (items.length >= 2) - raw_temp = Integer.parseInt(items[1]); - } else if (line.startsWith("ms5607 reserved:")) { - if (items.length >= 3) - reserved = Integer.parseInt(items[2]); - } else if (line.startsWith("ms5607 sens:")) { - if (items.length >= 3) { - sens = Integer.parseInt(items[2]); + public AltosPresTemp pres_temp(AltosLink link) throws InterruptedException, TimeoutException { + int raw_pres = AltosLib.MISSING; + int raw_temp = AltosLib.MISSING; + boolean done = false; + + link.printf("B\n"); + while (!done) { + String line = link.get_reply_no_dialog(5000); + if (line == null) + throw new TimeoutException(); + + String[] items = line.split("\\s+"); + if (line.startsWith("Pressure:")) { + if (items.length >= 2) { + raw_pres = Integer.parseInt(items[1]); + } + } else if (line.startsWith("Temperature:")) { + if (items.length >= 2) + raw_temp = Integer.parseInt(items[1]); + } else if (line.startsWith("Altitude:")) { + done = true; } - } else if (line.startsWith("ms5607 off:")) { - if (items.length >= 3) - off = Integer.parseInt(items[2]); - } else if (line.startsWith("ms5607 tcs:")) { - if (items.length >= 3) - tcs = Integer.parseInt(items[2]); - } else if (line.startsWith("ms5607 tco:")) { - if (items.length >= 3) - tco = Integer.parseInt(items[2]); - } else if (line.startsWith("ms5607 tref:")) { - if (items.length >= 3) - tref = Integer.parseInt(items[2]); - } else if (line.startsWith("ms5607 tempsens:")) { - if (items.length >= 3) - tempsens = Integer.parseInt(items[2]); - } else if (line.startsWith("ms5607 crc:")) { - if (items.length >= 3) - crc = Integer.parseInt(items[2]); - } else if (line.startsWith("Altitude:")) { - return false; } - return true; + return pres_temp(raw_pres, raw_temp); + } + + public AltosMs5607(boolean ms5611) { + this.ms5611 = ms5611; } - static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { + public AltosMs5607() { + this(false); + } + + public AltosMs5607(AltosMs5607 old) { + reserved = old.reserved; + sens = old.sens; + off = old.off; + tcs = old.tcs; + tco = old.tco; + tref = old.tref; + tempsens = old.tempsens; + crc = old.crc; + } + + static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException { try { - AltosMs5607 ms5607 = new AltosMs5607(link, config_data); + AltosCalData cal_data = listener.cal_data(); + AltosMs5607 ms5607 = cal_data.ms5607; if (ms5607 != null) { - state.set_ms5607(ms5607); - return; + AltosPresTemp pt = ms5607.pres_temp(link); + listener.set_temperature(pt.temp); + listener.set_pressure(pt.pres); } } catch (TimeoutException te) { } } - public boolean valid_config() { - return reserved != AltosLib.MISSING && - sens != AltosLib.MISSING && - off != AltosLib.MISSING && - tcs != AltosLib.MISSING && - tco != AltosLib.MISSING && - tref != AltosLib.MISSING && - tempsens != AltosLib.MISSING && - crc != AltosLib.MISSING; - } - - public AltosMs5607() { - raw_pres = AltosLib.MISSING; - raw_temp = AltosLib.MISSING; - pa = AltosLib.MISSING; - cc = AltosLib.MISSING; - } - public AltosMs5607(AltosConfigData config_data) { - this(); - reserved = config_data.ms5607_reserved; - sens = config_data.ms5607_sens; - off = config_data.ms5607_off; - tcs = config_data.ms5607_tcs; - tco = config_data.ms5607_tco; - tref = config_data.ms5607_tref; - tempsens = config_data.ms5607_tempsens; - crc = config_data.ms5607_crc; + this(config_data.ms5607()); } public AltosMs5607 (AltosLink link, AltosConfigData config_data) throws InterruptedException, TimeoutException { this(config_data); - link.printf("B\n"); - for (;;) { - String line = link.get_reply_no_dialog(5000); - if (line == null) { - throw new TimeoutException(); - } - if (!parse_line(line)) { - break; - } - } - convert(); } } diff --git a/altoslib/AltosNoSymbol.java b/altoslib/AltosNoSymbol.java index 37542cf0..8372d396 100644 --- a/altoslib/AltosNoSymbol.java +++ b/altoslib/AltosNoSymbol.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosNoSymbol extends Exception { public AltosNoSymbol(String name) { diff --git a/altoslib/AltosOrient.java b/altoslib/AltosOrient.java index 8b3a3541..4546a798 100644 --- a/altoslib/AltosOrient.java +++ b/altoslib/AltosOrient.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosOrient extends AltosUnits { diff --git a/altoslib/AltosParse.java b/altoslib/AltosParse.java index b4b6f875..77cf969d 100644 --- a/altoslib/AltosParse.java +++ b/altoslib/AltosParse.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.util.*; import java.text.*; diff --git a/altoslib/AltosPointDouble.java b/altoslib/AltosPointDouble.java index 31b03b1f..301d07b0 100644 --- a/altoslib/AltosPointDouble.java +++ b/altoslib/AltosPointDouble.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosPointDouble { public double x, y; diff --git a/altoslib/AltosPointInt.java b/altoslib/AltosPointInt.java index 233a8d31..25f5dd2a 100644 --- a/altoslib/AltosPointInt.java +++ b/altoslib/AltosPointInt.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosPointInt { public int x, y; diff --git a/altoslib/AltosPreferences.java b/altoslib/AltosPreferences.java index 35d44631..0c388f1b 100644 --- a/altoslib/AltosPreferences.java +++ b/altoslib/AltosPreferences.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.util.*; @@ -363,11 +363,11 @@ public class AltosPreferences { } } - public static void set_state(AltosState state) { + public static void set_state(AltosState state, int serial) { synchronized(backend) { - backend.putJson(String.format(statePreferenceFormat, state.serial), new AltosJson(state)); - backend.putInt(statePreferenceLatest, state.serial); + backend.putJson(String.format(statePreferenceFormat, serial), new AltosJson(state)); + backend.putInt(statePreferenceLatest, serial); flush_preferences(); } } diff --git a/altoslib/AltosPreferencesBackend.java b/altoslib/AltosPreferencesBackend.java index 327b534c..00fd2c6d 100644 --- a/altoslib/AltosPreferencesBackend.java +++ b/altoslib/AltosPreferencesBackend.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.util.*; diff --git a/altoslib/AltosPresTemp.java b/altoslib/AltosPresTemp.java new file mode 100644 index 00000000..4cd382c8 --- /dev/null +++ b/altoslib/AltosPresTemp.java @@ -0,0 +1,25 @@ +/* + * Copyright © 2017 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altoslib_12; + +public class AltosPresTemp { + double pres = AltosLib.MISSING; + double temp = AltosLib.MISSING; + + public AltosPresTemp(double pres, double temp) { + this.pres = pres; + this.temp = temp; + } +} diff --git a/altoslib/AltosPressure.java b/altoslib/AltosPressure.java index 2de26820..507a4cee 100644 --- a/altoslib/AltosPressure.java +++ b/altoslib/AltosPressure.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosPressure extends AltosUnits { diff --git a/altoslib/AltosProgrammer.java b/altoslib/AltosProgrammer.java index ba04107b..0a828a32 100644 --- a/altoslib/AltosProgrammer.java +++ b/altoslib/AltosProgrammer.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; diff --git a/altoslib/AltosPyro.java b/altoslib/AltosPyro.java index 80884b9f..0ea3bfc1 100644 --- a/altoslib/AltosPyro.java +++ b/altoslib/AltosPyro.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.util.*; import java.text.*; diff --git a/altoslib/AltosPyroName.java b/altoslib/AltosPyroName.java new file mode 100644 index 00000000..0152e479 --- /dev/null +++ b/altoslib/AltosPyroName.java @@ -0,0 +1,32 @@ +/* + * Copyright © 2017 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altoslib_12; + +public class AltosPyroName extends AltosUnits { + + public double value(double v, boolean imperial_units) { return v; } + + public double inverse(double v, boolean imperial_units) { return v; } + + public String string_value(double v, boolean imperial_units) { + return AltosLib.igniter_name((int) v); + } + + public String show_units(boolean imperial_units) { return "state"; } + + public String say_units(boolean imperial_units) { return "state"; } + + public int show_fraction(int width, boolean imperial_units) { return 0; } +} diff --git a/altoslib/AltosQuaternion.java b/altoslib/AltosQuaternion.java index 40786e32..6d6bc12c 100644 --- a/altoslib/AltosQuaternion.java +++ b/altoslib/AltosQuaternion.java @@ -16,12 +16,13 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosQuaternion { double r; /* real bit */ double x, y, z; /* imaginary bits */ + /* Multiply by b */ public AltosQuaternion multiply(AltosQuaternion b) { return new AltosQuaternion( this.r * b.r - this.x * b.x - this.y * b.y - this.z * b.z, @@ -31,35 +32,36 @@ public class AltosQuaternion { } public AltosQuaternion conjugate() { - return new AltosQuaternion( - this.r, - -this.x, - -this.y, - -this.z); + return new AltosQuaternion(this.r, + -this.x, + -this.y, + -this.z); } public double normal() { - return (this.r * this.r + - this.x * this.x + - this.y * this.y + - this.z * this.z); + return Math.sqrt(this.r * this.r + + this.x * this.x + + this.y * this.y + + this.z * this.z); } + /* Scale by a real value */ public AltosQuaternion scale(double b) { - return new AltosQuaternion( - this.r * b, - this.x * b, - this.y * b, - this.z * b); + return new AltosQuaternion(this.r * b, + this.x * b, + this.y * b, + this.z * b); } + /* Divide by the length to end up with a quaternion of length 1 */ public AltosQuaternion normalize() { double n = normal(); if (n <= 0) return this; - return scale(1/Math.sqrt(n)); + return scale(1/n); } + /* dot product */ public double dot(AltosQuaternion b) { return (this.r * b.r + this.x * b.x + @@ -67,10 +69,14 @@ public class AltosQuaternion { this.z * b.z); } + /* Rotate 'this' by 'b' */ public AltosQuaternion rotate(AltosQuaternion b) { return (b.multiply(this)).multiply(b.conjugate()); } + /* Given two vectors (this and b), compute a quaternion + * representing the rotation between them + */ public AltosQuaternion vectors_to_rotation(AltosQuaternion b) { /* * The cross product will point orthogonally to the two @@ -145,7 +151,13 @@ public class AltosQuaternion { return new AltosQuaternion(1, 0, 0, 0); } - static public AltosQuaternion half_euler(double x, double y, double z) { + static public AltosQuaternion euler(double x, double y, double z) { + + /* Halve the euler angles */ + x = x / 2.0; + y = y / 2.0; + z = z / 2.0; + double s_x = Math.sin(x), c_x = Math.cos(x); double s_y = Math.sin(y), c_y = Math.cos(y); double s_z = Math.sin(z), c_z = Math.cos(z);; diff --git a/altoslib/AltosRecordSet.java b/altoslib/AltosRecordSet.java new file mode 100644 index 00000000..91cce624 --- /dev/null +++ b/altoslib/AltosRecordSet.java @@ -0,0 +1,22 @@ +/* + * Copyright © 2017 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altoslib_12; + +import java.util.*; + +public interface AltosRecordSet { + public AltosCalData cal_data(); + public void capture_series(AltosDataListener listener); +} diff --git a/altoslib/AltosRectangle.java b/altoslib/AltosRectangle.java index 50b3caa6..810388ed 100644 --- a/altoslib/AltosRectangle.java +++ b/altoslib/AltosRectangle.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosRectangle { public int x, y, width, height; diff --git a/altoslib/AltosReplayReader.java b/altoslib/AltosReplayReader.java index 59ade871..24b425b7 100644 --- a/altoslib/AltosReplayReader.java +++ b/altoslib/AltosReplayReader.java @@ -16,40 +16,139 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.util.*; +import java.util.concurrent.*; /* * Open an existing telemetry file and replay it in realtime */ +class AltosReplay extends AltosDataListener implements Runnable { + + AltosState state; + AltosRecordSet record_set; + double last_time = AltosLib.MISSING; + Semaphore semaphore = new Semaphore(1);; + boolean done = false; + + public void set_time(double time) { + if (last_time != AltosLib.MISSING) { + semaphore.release(); + double delay = Math.min(time - last_time,10); + if (delay > 0) { + try { + Thread.sleep((int) (delay * 1000)); + } catch (InterruptedException ie) { + } + } + } + last_time = time; + super.set_time(time); + state.set_time(time); + } + + public void set_state(int state) { + super.set_state(state); + this.state.set_state(state); + } + + public void set_rssi(int rssi, int status) { state.set_rssi(rssi, status); } + public void set_received_time(long received_time) { } + + public void set_acceleration(double accel) { state.set_acceleration(accel); } + public void set_pressure(double pa) { state.set_pressure(pa); } + public void set_thrust(double N) { state.set_thrust(N); } + + public void set_kalman(double height, double speed, double accel) { state.set_kalman(height, speed, accel); } + + public void set_temperature(double deg_c) { state.set_temperature(deg_c); } + public void set_battery_voltage(double volts) { state.set_battery_voltage(volts); } + + public void set_apogee_voltage(double volts) { state.set_apogee_voltage(volts); } + public void set_main_voltage(double volts) { state.set_main_voltage(volts); } + + public void set_gps(AltosGPS gps) { state.set_gps(gps); } + + public void set_orient(double orient) { state.set_orient(orient); } + public void set_gyro(double roll, double pitch, double yaw) { state.set_gyro(roll, pitch, yaw); } + public void set_accel_ground(double along, double across, double through) { state.set_accel_ground(along, across, through); } + public void set_accel(double along, double across, double through) { state.set_accel(along, across, through); } + public void set_mag(double along, double across, double through) { state.set_mag(along, across, through); } + public void set_pyro_voltage(double volts) { state.set_pyro_voltage(volts); } + public void set_igniter_voltage(double[] voltage) { state.set_igniter_voltage(voltage); } + public void set_pyro_fired(int pyro_mask) { state.set_pyro_fired(pyro_mask); } + public void set_companion(AltosCompanion companion) { state.set_companion(companion); } + + public void run () { + /* Run the flight */ + record_set.capture_series(this); + /* All done, signal that it's over */ + done = true; + semaphore.release(); + } + + public AltosReplay(AltosRecordSet record_set) { + super(record_set.cal_data()); + state = new AltosState(record_set.cal_data()); + this.record_set = record_set; + try { + semaphore.acquire(); + } catch (InterruptedException ie) { + } + } +} + public class AltosReplayReader extends AltosFlightReader { - Iterator iterator; - File file; + File file; + AltosReplay replay; + Thread t; + int reads; - public AltosState read() { - if (iterator.hasNext()) - return iterator.next(); - return null; + public AltosCalData cal_data() { + return replay.state.cal_data(); } - public void close (boolean interrupted) { + public AltosState read() { + switch (reads) { + case 0: + /* Tell the display that we're in pad mode */ + replay.state.set_state(AltosLib.ao_flight_pad); + break; + case 1: + t = new Thread(replay); + t.start(); + /* fall through */ + default: + /* Wait for something to change */ + try { + replay.semaphore.acquire(); + } catch (InterruptedException ie) { + } + break; + } + reads++; + + /* When done, let the display know */ + if (replay.done) + return null; + + /* Fake out the received time */ + replay.state.set_received_time(System.currentTimeMillis()); + return replay.state; } - public void update(AltosState state) throws InterruptedException { - /* Make it run in realtime after the rocket leaves the pad */ - if (state.state() > AltosLib.ao_flight_pad && state.time_change > 0) - Thread.sleep((int) (Math.min(state.time_change,10) * 1000)); - state.set_received_time(System.currentTimeMillis()); + public void close (boolean interrupted) { } public File backing_file() { return file; } - public AltosReplayReader(Iterator in_iterator, File in_file) { - iterator = in_iterator; + public AltosReplayReader(AltosRecordSet record_set, File in_file) { + reads = 0; file = in_file; name = file.getName(); + replay = new AltosReplay(record_set); } } diff --git a/altoslib/AltosRomconfig.java b/altoslib/AltosRomconfig.java index dcfbda32..46ee2b6e 100644 --- a/altoslib/AltosRomconfig.java +++ b/altoslib/AltosRomconfig.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; diff --git a/altoslib/AltosRotation.java b/altoslib/AltosRotation.java index 1235d86b..eec8c529 100644 --- a/altoslib/AltosRotation.java +++ b/altoslib/AltosRotation.java @@ -16,11 +16,33 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosRotation extends AltosQuaternion { private AltosQuaternion rotation; + /* Compute pitch angle from vertical by taking the pad + * orientation vector and rotating it by the current total + * rotation value. That will be a unit vector pointing along + * the airframe axis. The Z value will be the cosine of the + * angle from vertical. + * + * rot = ao_rotation * vertical * ao_rotation° + * rot = ao_rotation * (0,0,0,1) * ao_rotation° + * = ((a.z, a.y, -a.x, a.r) * (a.r, -a.x, -a.y, -a.z)) .z + * + * = (-a.z * -a.z) + (a.y * -a.y) - (-a.x * -a.x) + (a.r * a.r) + * = a.z² - a.y² - a.x² + a.r² + * + * rot = ao_rotation * (0, 0, 0, -1) * ao_rotation° + * = ((-a.z, -a.y, a.x, -a.r) * (a.r, -a.x, -a.y, -a.z)) .z + * + * = (a.z * -a.z) + (-a.y * -a.y) - (a.x * -a.x) + (-a.r * a.r) + * = -a.z² + a.y² + a.x² - a.r² + * + * tilt = acos(rot) (in radians) + */ + public double tilt() { double rotz = rotation.z * rotation.z - rotation.y * rotation.y - rotation.x * rotation.x + rotation.r * rotation.r; @@ -28,8 +50,11 @@ public class AltosRotation extends AltosQuaternion { return tilt; } - public void rotate(double dt, double x, double y, double z) { - AltosQuaternion rot = AltosQuaternion.half_euler(x * dt / 2.0, y * dt / 2.0, z * dt / 2.0); + /* Given euler rotations in three axes, perform a combined rotation using + * quaternions + */ + public void rotate(double x, double y, double z) { + AltosQuaternion rot = AltosQuaternion.euler(x, y, z); rotation = rot.multiply(rotation).normalize(); } diff --git a/altoslib/AltosRotationRate.java b/altoslib/AltosRotationRate.java new file mode 100644 index 00000000..492f1217 --- /dev/null +++ b/altoslib/AltosRotationRate.java @@ -0,0 +1,38 @@ +/* + * Copyright © 2017 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altoslib_12; + +public class AltosRotationRate extends AltosUnits { + + public double value(double p, boolean imperial_units) { + return p; + } + + public double inverse(double p, boolean imperial_units) { + return p; + } + + public String show_units(boolean imperial_units) { + return "°/sec"; + } + + public String say_units(boolean imperial_units) { + return "degrees per second"; + } + + public int show_fraction(int width, boolean imperial_units) { + return 1; + } +} diff --git a/altoslib/AltosSavedState.java b/altoslib/AltosSavedState.java index 76d12faf..66876864 100644 --- a/altoslib/AltosSavedState.java +++ b/altoslib/AltosSavedState.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; diff --git a/altoslib/AltosSelfFlash.java b/altoslib/AltosSelfFlash.java index ae7cd69a..53782172 100644 --- a/altoslib/AltosSelfFlash.java +++ b/altoslib/AltosSelfFlash.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; diff --git a/altoslib/AltosSensorEMini.java b/altoslib/AltosSensorEMini.java index 2581685f..1bdbb60c 100644 --- a/altoslib/AltosSensorEMini.java +++ b/altoslib/AltosSensorEMini.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.util.concurrent.TimeoutException; @@ -26,15 +26,25 @@ public class AltosSensorEMini { public int main; public int batt; - static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { + static public void provide_data(AltosDataListener listener, AltosLink link, int version) throws InterruptedException { try { AltosSensorEMini sensor_emini = new AltosSensorEMini(link); + AltosCalData cal_data = listener.cal_data(); if (sensor_emini == null) return; - state.set_battery_voltage(AltosConvert.easy_mini_voltage(sensor_emini.batt, config_data.serial)); - state.set_apogee_voltage(AltosConvert.easy_mini_voltage(sensor_emini.apogee, config_data.serial)); - state.set_main_voltage(AltosConvert.easy_mini_voltage(sensor_emini.main, config_data.serial)); + switch (version) { + case 1: + listener.set_battery_voltage(AltosConvert.easy_mini_1_voltage(sensor_emini.batt, cal_data.serial)); + listener.set_apogee_voltage(AltosConvert.easy_mini_1_voltage(sensor_emini.apogee, cal_data.serial)); + listener.set_main_voltage(AltosConvert.easy_mini_1_voltage(sensor_emini.main, cal_data.serial)); + break; + case 2: + listener.set_battery_voltage(AltosConvert.easy_mini_2_voltage(sensor_emini.batt)); + listener.set_apogee_voltage(AltosConvert.easy_mini_2_voltage(sensor_emini.apogee)); + listener.set_main_voltage(AltosConvert.easy_mini_2_voltage(sensor_emini.main)); + break; + } } catch (TimeoutException te) { } diff --git a/altoslib/AltosSensorMM.java b/altoslib/AltosSensorMM.java index d79c0805..00873afe 100644 --- a/altoslib/AltosSensorMM.java +++ b/altoslib/AltosSensorMM.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.util.concurrent.TimeoutException; diff --git a/altoslib/AltosSensorMega.java b/altoslib/AltosSensorMega.java index 63c7a0ce..e58b03a1 100644 --- a/altoslib/AltosSensorMega.java +++ b/altoslib/AltosSensorMega.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.util.concurrent.TimeoutException; @@ -89,18 +89,18 @@ class AltosSensorMega { } } - static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { + static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException { try { AltosSensorMega sensor_mega = new AltosSensorMega(link); - state.set_battery_voltage(AltosConvert.mega_battery_voltage(sensor_mega.v_batt)); - state.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sensor_mega.sense[4])); - state.set_main_voltage(AltosConvert.mega_pyro_voltage(sensor_mega.sense[5])); + listener.set_battery_voltage(AltosConvert.mega_battery_voltage(sensor_mega.v_batt)); + listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sensor_mega.sense[4])); + listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sensor_mega.sense[5])); - double[] ignitor_voltage = new double[4]; + double[] igniter_voltage = new double[4]; for (int i = 0; i < 4; i++) - ignitor_voltage[i] = AltosConvert.mega_pyro_voltage(sensor_mega.sense[i]); - state.set_ignitor_voltage(ignitor_voltage); + igniter_voltage[i] = AltosConvert.mega_pyro_voltage(sensor_mega.sense[i]); + listener.set_igniter_voltage(igniter_voltage); } catch (TimeoutException te) { } diff --git a/altoslib/AltosSensorMetrum.java b/altoslib/AltosSensorMetrum.java index cb163911..e01d57cc 100644 --- a/altoslib/AltosSensorMetrum.java +++ b/altoslib/AltosSensorMetrum.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.util.concurrent.TimeoutException; @@ -53,12 +53,12 @@ class AltosSensorMetrum { } } - static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { + static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException { try { AltosSensorMetrum sensor_metrum = new AltosSensorMetrum(link); - state.set_battery_voltage(AltosConvert.mega_battery_voltage(sensor_metrum.v_batt)); - state.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sensor_metrum.sense_a)); - state.set_main_voltage(AltosConvert.mega_pyro_voltage(sensor_metrum.sense_m)); + listener.set_battery_voltage(AltosConvert.mega_battery_voltage(sensor_metrum.v_batt)); + listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sensor_metrum.sense_a)); + listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sensor_metrum.sense_m)); } catch (TimeoutException te) { } } diff --git a/altoslib/AltosSensorTGPS.java b/altoslib/AltosSensorTGPS.java index 9c2bcb10..14514413 100644 --- a/altoslib/AltosSensorTGPS.java +++ b/altoslib/AltosSensorTGPS.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.util.concurrent.TimeoutException; @@ -24,13 +24,13 @@ public class AltosSensorTGPS { public int tick; public int batt; - static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { + static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException { try { AltosSensorTGPS sensor_tgps = new AltosSensorTGPS(link); if (sensor_tgps == null) return; - state.set_battery_voltage(AltosConvert.tele_gps_voltage(sensor_tgps.batt)); + listener.set_battery_voltage(AltosConvert.tele_gps_voltage(sensor_tgps.batt)); } catch (TimeoutException te) { } diff --git a/altoslib/AltosSensorTM.java b/altoslib/AltosSensorTM.java index 5d1b1b7f..bdedaa9c 100644 --- a/altoslib/AltosSensorTM.java +++ b/altoslib/AltosSensorTM.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.util.concurrent.TimeoutException; @@ -29,18 +29,19 @@ public class AltosSensorTM { public int drogue; public int main; - static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { + static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException { try { AltosSensorTM sensor_tm = new AltosSensorTM(link); + AltosCalData cal_data = listener.cal_data(); if (sensor_tm == null) return; - state.set_accel(sensor_tm.accel); - state.set_pressure(AltosConvert.barometer_to_pressure(sensor_tm.pres)); - state.set_temperature(AltosConvert.thermometer_to_temperature(sensor_tm.temp)); - state.set_battery_voltage(AltosConvert.cc_battery_to_voltage(sensor_tm.batt)); - state.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(sensor_tm.drogue)); - state.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(sensor_tm.main)); + listener.set_acceleration(cal_data.acceleration((sensor_tm.accel))); + listener.set_pressure(AltosConvert.barometer_to_pressure(sensor_tm.pres)); + listener.set_temperature(AltosConvert.thermometer_to_temperature(sensor_tm.temp)); + listener.set_battery_voltage(AltosConvert.cc_battery_to_voltage(sensor_tm.batt)); + listener.set_apogee_voltage(AltosConvert.cc_igniter_to_voltage(sensor_tm.drogue)); + listener.set_main_voltage(AltosConvert.cc_igniter_to_voltage(sensor_tm.main)); } catch (TimeoutException te) { } diff --git a/altoslib/AltosSensorTMini2.java b/altoslib/AltosSensorTMini2.java index 7e00abd0..9b5a1854 100644 --- a/altoslib/AltosSensorTMini2.java +++ b/altoslib/AltosSensorTMini2.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.util.concurrent.TimeoutException; @@ -26,15 +26,15 @@ public class AltosSensorTMini2 { public int main; public int batt; - static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { + static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException { try { AltosSensorTMini2 sensor_tmini = new AltosSensorTMini2(link); if (sensor_tmini == null) return; - state.set_battery_voltage(AltosConvert.tele_mini_2_voltage(sensor_tmini.batt)); - state.set_apogee_voltage(AltosConvert.tele_mini_2_voltage(sensor_tmini.apogee)); - state.set_main_voltage(AltosConvert.tele_mini_2_voltage(sensor_tmini.main)); + listener.set_battery_voltage(AltosConvert.tele_mini_2_voltage(sensor_tmini.batt)); + listener.set_apogee_voltage(AltosConvert.tele_mini_2_voltage(sensor_tmini.apogee)); + listener.set_main_voltage(AltosConvert.tele_mini_2_voltage(sensor_tmini.main)); } catch (TimeoutException te) { } diff --git a/altoslib/AltosSensorTMini3.java b/altoslib/AltosSensorTMini3.java index 19d514d7..b92def03 100644 --- a/altoslib/AltosSensorTMini3.java +++ b/altoslib/AltosSensorTMini3.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.util.concurrent.TimeoutException; @@ -26,15 +26,15 @@ public class AltosSensorTMini3 { public int main; public int batt; - static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { + static public void provide_data(AltosDataListener listener, AltosLink link) throws InterruptedException { try { AltosSensorTMini3 sensor_tmini = new AltosSensorTMini3(link); if (sensor_tmini == null) return; - state.set_battery_voltage(AltosConvert.tele_mini_3_battery_voltage(sensor_tmini.batt)); - state.set_apogee_voltage(AltosConvert.tele_mini_3_pyro_voltage(sensor_tmini.apogee)); - state.set_main_voltage(AltosConvert.tele_mini_3_pyro_voltage(sensor_tmini.main)); + listener.set_battery_voltage(AltosConvert.tele_mini_3_battery_voltage(sensor_tmini.batt)); + listener.set_apogee_voltage(AltosConvert.tele_mini_3_pyro_voltage(sensor_tmini.apogee)); + listener.set_main_voltage(AltosConvert.tele_mini_3_pyro_voltage(sensor_tmini.main)); } catch (TimeoutException te) { } diff --git a/altoslib/AltosSpeed.java b/altoslib/AltosSpeed.java index 465c190c..2a8ccedc 100644 --- a/altoslib/AltosSpeed.java +++ b/altoslib/AltosSpeed.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosSpeed extends AltosUnits { diff --git a/altoslib/AltosState.java b/altoslib/AltosState.java index 8c3f93f0..9ee3d57d 100644 --- a/altoslib/AltosState.java +++ b/altoslib/AltosState.java @@ -20,11 +20,9 @@ * Track flight state from telemetry or eeprom data stream */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; -import java.io.*; - -public class AltosState implements Cloneable { +public class AltosState extends AltosDataListener { public static final int set_position = 1; public static final int set_gps = 2; @@ -40,12 +38,8 @@ public class AltosState implements Cloneable { public long received_time; - public double time; - public double prev_time; - public double time_change; - public int tick; - private int prev_tick; - public int boost_tick; + public int rssi; + public int status; class AltosValue { double value; @@ -290,22 +284,9 @@ public class AltosState implements Cloneable { } } - private int state; - public int flight; - public int serial; - public int altitude_32; - public int receiver_serial; public boolean landed; public boolean ascent; /* going up? */ public boolean boost; /* under power */ - public int rssi; - public int status; - public int device_type; - public int config_major; - public int config_minor; - public int apogee_delay; - public int main_deploy; - public int flight_log_max; private double pressure_to_altitude(double p) { if (p == AltosLib.MISSING) @@ -448,6 +429,11 @@ public class AltosState implements Cloneable { } public void set_altitude(double new_altitude) { + double old_altitude = altitude.value(); + if (old_altitude != AltosLib.MISSING) { + while (old_altitude - new_altitude > 32000) + new_altitude += 65536.0; + } altitude.set_measured(new_altitude, time); } @@ -515,6 +501,9 @@ public class AltosState implements Cloneable { pressure.set(p, time); } + public void set_thrust(double N) { + } + public double baro_height() { double a = altitude(); double g = ground_altitude(); @@ -667,6 +656,11 @@ public class AltosState implements Cloneable { public AltosValue kalman_height, kalman_speed, kalman_acceleration; public void set_kalman(double height, double speed, double acceleration) { + double old_height = kalman_height.value(); + if (old_height != AltosLib.MISSING) { + while (old_height - height > 32000) + height += 65536; + } kalman_height.set(height, time); kalman_speed.set(speed, time); kalman_acceleration.set(acceleration, time); @@ -678,16 +672,10 @@ public class AltosState implements Cloneable { public double apogee_voltage; public double main_voltage; - public double ignitor_voltage[]; + public double igniter_voltage[]; public AltosGPS gps; - public AltosGPS temp_gps; - public int temp_gps_sat_tick; public boolean gps_pending; - public int gps_sequence; - - public AltosIMU imu; - public AltosMag mag; public static final int MIN_PAD_SAMPLES = 10; @@ -699,6 +687,7 @@ public class AltosState implements Cloneable { public AltosGreatCircle from_pad; public double elevation; /* from pad */ + public double distance; /* distance along ground */ public double range; /* total distance */ public double gps_height; @@ -708,20 +697,7 @@ public class AltosState implements Cloneable { public int speak_tick; public double speak_altitude; - public String callsign; - public String firmware_version; - - public double accel_plus_g; - public double accel_minus_g; - public double accel; public double ground_accel; - public double ground_accel_avg; - - public int log_format; - public int log_space; - public String product; - - public AltosMs5607 baro; public AltosCompanion companion; @@ -740,23 +716,11 @@ public class AltosState implements Cloneable { received_time = System.currentTimeMillis(); time = AltosLib.MISSING; - time_change = AltosLib.MISSING; - prev_time = AltosLib.MISSING; - tick = AltosLib.MISSING; - prev_tick = AltosLib.MISSING; - boost_tick = AltosLib.MISSING; state = AltosLib.ao_flight_invalid; - flight = AltosLib.MISSING; landed = false; boost = false; rssi = AltosLib.MISSING; status = 0; - device_type = AltosLib.MISSING; - config_major = AltosLib.MISSING; - config_minor = AltosLib.MISSING; - apogee_delay = AltosLib.MISSING; - main_deploy = AltosLib.MISSING; - flight_log_max = AltosLib.MISSING; ground_altitude = new AltosCValue(); ground_pressure = new AltosGroundPressure(); @@ -771,43 +735,40 @@ public class AltosState implements Cloneable { pyro_voltage = AltosLib.MISSING; apogee_voltage = AltosLib.MISSING; main_voltage = AltosLib.MISSING; - ignitor_voltage = null; + igniter_voltage = null; kalman_height = new AltosValue(); kalman_speed = new AltosValue(); kalman_acceleration = new AltosValue(); gps = null; - temp_gps = null; - temp_gps_sat_tick = 0; - gps_sequence = 0; gps_pending = false; - imu = null; last_imu_time = AltosLib.MISSING; rotation = null; - ground_rotation = null; - - mag = null; - accel_zero_along = AltosLib.MISSING; - accel_zero_across = AltosLib.MISSING; - accel_zero_through = AltosLib.MISSING; accel_ground_along = AltosLib.MISSING; accel_ground_across = AltosLib.MISSING; accel_ground_through = AltosLib.MISSING; - pad_orientation = AltosLib.MISSING; + accel_along = AltosLib.MISSING; + accel_across = AltosLib.MISSING; + accel_through = AltosLib.MISSING; - gyro_zero_roll = AltosLib.MISSING; - gyro_zero_pitch = AltosLib.MISSING; - gyro_zero_yaw = AltosLib.MISSING; + gyro_roll = AltosLib.MISSING; + gyro_pitch = AltosLib.MISSING; + gyro_yaw = AltosLib.MISSING; + + mag_along = AltosLib.MISSING; + mag_across = AltosLib.MISSING; + mag_through = AltosLib.MISSING; set_npad(0); ngps = 0; from_pad = null; elevation = AltosLib.MISSING; + distance = AltosLib.MISSING; range = AltosLib.MISSING; gps_height = AltosLib.MISSING; @@ -825,32 +786,14 @@ public class AltosState implements Cloneable { speak_tick = AltosLib.MISSING; speak_altitude = AltosLib.MISSING; - callsign = null; - firmware_version = null; - - accel_plus_g = AltosLib.MISSING; - accel_minus_g = AltosLib.MISSING; - accel = AltosLib.MISSING; - ground_accel = AltosLib.MISSING; - ground_accel_avg = AltosLib.MISSING; - - log_format = AltosLib.MISSING; - log_space = AltosLib.MISSING; - product = null; - serial = AltosLib.MISSING; - receiver_serial = AltosLib.MISSING; - altitude_32 = AltosLib.MISSING; - baro = null; companion = null; pyro_fired = 0; } void finish_update() { - prev_tick = tick; - ground_altitude.finish_update(); altitude.finish_update(); pressure.finish_update(); @@ -863,156 +806,12 @@ public class AltosState implements Cloneable { kalman_acceleration.finish_update(); } - void copy(AltosState old) { - - if (old == null) { - init(); - return; - } - - received_time = old.received_time; - time = old.time; - time_change = old.time_change; - prev_time = old.time; - - tick = old.tick; - prev_tick = old.tick; - boost_tick = old.boost_tick; - - state = old.state; - flight = old.flight; - landed = old.landed; - ascent = old.ascent; - boost = old.boost; - rssi = old.rssi; - status = old.status; - device_type = old.device_type; - config_major = old.config_major; - config_minor = old.config_minor; - apogee_delay = old.apogee_delay; - main_deploy = old.main_deploy; - flight_log_max = old.flight_log_max; - - set = 0; - - ground_pressure.copy(old.ground_pressure); - ground_altitude.copy(old.ground_altitude); - altitude.copy(old.altitude); - pressure.copy(old.pressure); - speed.copy(old.speed); - acceleration.copy(old.acceleration); - orient.copy(old.orient); - - battery_voltage = old.battery_voltage; - pyro_voltage = old.pyro_voltage; - temperature = old.temperature; - apogee_voltage = old.apogee_voltage; - main_voltage = old.main_voltage; - ignitor_voltage = old.ignitor_voltage; - - kalman_height.copy(old.kalman_height); - kalman_speed.copy(old.kalman_speed); - kalman_acceleration.copy(old.kalman_acceleration); - - if (old.gps != null) - gps = old.gps.clone(); - else - gps = null; - if (old.temp_gps != null) - temp_gps = old.temp_gps.clone(); - else - temp_gps = null; - temp_gps_sat_tick = old.temp_gps_sat_tick; - gps_sequence = old.gps_sequence; - gps_pending = old.gps_pending; - - if (old.imu != null) - imu = old.imu.clone(); - else - imu = null; - last_imu_time = old.last_imu_time; - - if (old.rotation != null) - rotation = new AltosRotation (old.rotation); - - if (old.ground_rotation != null) { - ground_rotation = new AltosRotation(old.ground_rotation); - } - - accel_zero_along = old.accel_zero_along; - accel_zero_across = old.accel_zero_across; - accel_zero_through = old.accel_zero_through; - - accel_ground_along = old.accel_ground_along; - accel_ground_across = old.accel_ground_across; - accel_ground_through = old.accel_ground_through; - pad_orientation = old.pad_orientation; - - gyro_zero_roll = old.gyro_zero_roll; - gyro_zero_pitch = old.gyro_zero_pitch; - gyro_zero_yaw = old.gyro_zero_yaw; - - if (old.mag != null) - mag = old.mag.clone(); - else - mag = null; - - npad = old.npad; - gps_waiting = old.gps_waiting; - gps_ready = old.gps_ready; - ngps = old.ngps; - - if (old.from_pad != null) - from_pad = old.from_pad.clone(); - else - from_pad = null; - - elevation = old.elevation; - range = old.range; - - gps_height = old.gps_height; - - gps_altitude.copy(old.gps_altitude); - gps_ground_altitude.copy(old.gps_ground_altitude); - gps_ground_speed.copy(old.gps_ground_speed); - gps_ascent_rate.copy(old.gps_ascent_rate); - gps_course.copy(old.gps_course); - gps_speed.copy(old.gps_speed); - - pad_lat = old.pad_lat; - pad_lon = old.pad_lon; - pad_alt = old.pad_alt; - - speak_tick = old.speak_tick; - speak_altitude = old.speak_altitude; - - callsign = old.callsign; - firmware_version = old.firmware_version; - - accel_plus_g = old.accel_plus_g; - accel_minus_g = old.accel_minus_g; - accel = old.accel; - ground_accel = old.ground_accel; - ground_accel_avg = old.ground_accel_avg; - - log_format = old.log_format; - log_space = old.log_space; - product = old.product; - serial = old.serial; - receiver_serial = old.receiver_serial; - altitude_32 = old.altitude_32; - - baro = old.baro; - companion = old.companion; - - pyro_fired = old.pyro_fired; - } - void update_time() { } void update_gps() { elevation = AltosLib.MISSING; + distance = AltosLib.MISSING; range = AltosLib.MISSING; if (gps == null) @@ -1054,36 +853,15 @@ public class AltosState implements Cloneable { h = 0; from_pad = new AltosGreatCircle(pad_lat, pad_lon, 0, gps.lat, gps.lon, h); elevation = from_pad.elevation; + distance = from_pad.distance; range = from_pad.range; } } - public void set_tick(int new_tick) { - if (new_tick != AltosLib.MISSING) { - if (prev_tick != AltosLib.MISSING) { - while (new_tick < prev_tick - 1000) { - new_tick += 65536; - } - } - tick = new_tick; - time = tick / 100.0; - time_change = time - prev_time; - } - } - - public void set_boost_tick(int boost_tick) { - if (boost_tick != AltosLib.MISSING) - this.boost_tick = boost_tick; - } - public String state_name() { return AltosLib.state_name(state); } - public void set_product(String product) { - this.product = product; - } - public void set_state(int state) { if (state != AltosLib.ao_flight_invalid) { this.state = state; @@ -1097,96 +875,8 @@ public class AltosState implements Cloneable { return state; } - public void set_device_type(int device_type) { - this.device_type = device_type; - switch (device_type) { - case AltosLib.product_telegps: - this.state = AltosLib.ao_flight_stateless; - break; - } - } - - public void set_log_format(int log_format) { - this.log_format = log_format; - switch (log_format) { - case AltosLib.AO_LOG_FORMAT_TELEGPS: - this.state = AltosLib.ao_flight_stateless; - break; - } - } - - public void set_log_space(int log_space) { - this.log_space = log_space; - } - - public void set_flight_params(int apogee_delay, int main_deploy) { - this.apogee_delay = apogee_delay; - this.main_deploy = main_deploy; - } - - public void set_config(int major, int minor, int flight_log_max) { - config_major = major; - config_minor = minor; - this.flight_log_max = flight_log_max; - } - - public void set_callsign(String callsign) { - this.callsign = callsign; - } - - public void set_firmware_version(String version) { - firmware_version = version; - } - - public int compare_version(String other_version) { - if (firmware_version == null) - return AltosLib.MISSING; - return AltosLib.compare_version(firmware_version, other_version); - } - private void re_init() { - int bt = boost_tick; - int rs = receiver_serial; init(); - boost_tick = bt; - receiver_serial = rs; - } - - public void set_flight(int flight) { - - /* When the flight changes, reset the state */ - if (flight != AltosLib.MISSING) { - if (this.flight != AltosLib.MISSING && - this.flight != flight) { - re_init(); - } - this.flight = flight; - } - } - - public void set_serial(int serial) { - /* When the serial changes, reset the state */ - if (serial != AltosLib.MISSING) { - if (this.serial != AltosLib.MISSING && - this.serial != serial) { - re_init(); - } - this.serial = serial; - } - } - - public void set_receiver_serial(int serial) { - if (serial != AltosLib.MISSING) - receiver_serial = serial; - } - - public boolean altitude_32() { - return altitude_32 == 1; - } - - public void set_altitude_32(int altitude_32) { - if (altitude_32 != AltosLib.MISSING) - this.altitude_32 = altitude_32; } public int rssi() { @@ -1206,42 +896,24 @@ public class AltosState implements Cloneable { received_time = ms; } - public void set_gps(AltosGPS gps, int sequence) { + public void set_gps(AltosGPS gps) { if (gps != null) { - this.gps = gps.clone(); - gps_sequence = sequence; + this.gps = gps; update_gps(); set |= set_gps; } } - - public double accel_zero_along; - public double accel_zero_across; - public double accel_zero_through; - public AltosRotation rotation; - public AltosRotation ground_rotation; - - public void set_accel_zero(double zero_along, double zero_across, double zero_through) { - if (zero_along != AltosLib.MISSING) { - accel_zero_along = zero_along; - accel_zero_across = zero_across; - accel_zero_through = zero_through; - } - } - - public int pad_orientation; public double accel_ground_along, accel_ground_across, accel_ground_through; void update_pad_rotation() { - if (pad_orientation != AltosLib.MISSING && accel_ground_along != AltosLib.MISSING) { - rotation = new AltosRotation(AltosIMU.convert_accel(accel_ground_across - accel_zero_across), - AltosIMU.convert_accel(accel_ground_through - accel_zero_through), - AltosIMU.convert_accel(accel_ground_along - accel_zero_along), - pad_orientation); - ground_rotation = rotation; + if (cal_data().pad_orientation != AltosLib.MISSING && accel_ground_along != AltosLib.MISSING) { + rotation = new AltosRotation(AltosIMU.convert_accel(accel_ground_across - cal_data().accel_zero_across), + AltosIMU.convert_accel(accel_ground_through - cal_data().accel_zero_through), + AltosIMU.convert_accel(accel_ground_along - cal_data().accel_zero_along), + cal_data().pad_orientation); orient.set_computed(rotation.tilt(), time); } } @@ -1253,197 +925,95 @@ public class AltosState implements Cloneable { update_pad_rotation(); } - public void set_pad_orientation(int pad_orientation) { - this.pad_orientation = pad_orientation; - update_pad_rotation(); - } - - public double gyro_zero_roll; - public double gyro_zero_pitch; - public double gyro_zero_yaw; - - public void set_gyro_zero(double roll, double pitch, double yaw) { - if (roll != AltosLib.MISSING) { - gyro_zero_roll = roll; - gyro_zero_pitch = pitch; - gyro_zero_yaw = yaw; - } - } - public double last_imu_time; - private double radians(double degrees) { - if (degrees == AltosLib.MISSING) - return AltosLib.MISSING; - return degrees * Math.PI / 180.0; - } - private void update_orient() { if (last_imu_time != AltosLib.MISSING) { double t = time - last_imu_time; - double pitch = radians(gyro_pitch()); - double yaw = radians(gyro_yaw()); - double roll = radians(gyro_roll()); + if (t > 0 && gyro_pitch != AltosLib.MISSING && rotation != null) { + double pitch = AltosConvert.degrees_to_radians(gyro_pitch) * t; + double yaw = AltosConvert.degrees_to_radians(gyro_yaw) * t; + double roll = AltosConvert.degrees_to_radians(gyro_roll) * t; - if (t > 0 & pitch != AltosLib.MISSING && rotation != null) { - rotation.rotate(t, pitch, yaw, roll); + rotation.rotate(pitch, yaw, roll); orient.set_computed(rotation.tilt(), time); } } last_imu_time = time; } - public void set_imu(AltosIMU imu) { - if (imu != null) - imu = imu.clone(); - this.imu = imu; + private double gyro_roll, gyro_pitch, gyro_yaw; + + public void set_gyro(double roll, double pitch, double yaw) { + gyro_roll = roll; + gyro_pitch = pitch; + gyro_yaw = yaw; update_orient(); } - private double gyro_zero_overflow(double first) { - double v = first / 128.0; - if (v < 0) - v = Math.ceil(v); - else - v = Math.floor(v); - return v * 128.0; - } + private double accel_along, accel_across, accel_through; - public void check_imu_wrap(AltosIMU imu) { - if (this.imu == null) { - gyro_zero_roll += gyro_zero_overflow(imu.gyro_roll); - gyro_zero_pitch += gyro_zero_overflow(imu.gyro_pitch); - gyro_zero_yaw += gyro_zero_overflow(imu.gyro_yaw); - } + public void set_accel(double along, double across, double through) { + accel_along = along; + accel_across = across; + accel_through = through; + update_orient(); } public double accel_along() { - if (imu != null && accel_zero_along != AltosLib.MISSING) - return AltosIMU.convert_accel(imu.accel_along - accel_zero_along); - return AltosLib.MISSING; + return accel_along; } public double accel_across() { - if (imu != null && accel_zero_across != AltosLib.MISSING) - return AltosIMU.convert_accel(imu.accel_across - accel_zero_across); - return AltosLib.MISSING; + return accel_across; } public double accel_through() { - if (imu != null && accel_zero_through != AltosLib.MISSING) - return AltosIMU.convert_accel(imu.accel_through - accel_zero_through); - return AltosLib.MISSING; + return accel_through; } public double gyro_roll() { - if (imu != null && gyro_zero_roll != AltosLib.MISSING) { - return AltosIMU.convert_gyro(imu.gyro_roll - gyro_zero_roll); - } - return AltosLib.MISSING; + return gyro_roll; } public double gyro_pitch() { - if (imu != null && gyro_zero_pitch != AltosLib.MISSING) { - return AltosIMU.convert_gyro(imu.gyro_pitch - gyro_zero_pitch); - } - return AltosLib.MISSING; + return gyro_pitch; } public double gyro_yaw() { - if (imu != null && gyro_zero_yaw != AltosLib.MISSING) { - return AltosIMU.convert_gyro(imu.gyro_yaw - gyro_zero_yaw); - } - return AltosLib.MISSING; + return gyro_yaw; } - public void set_mag(AltosMag mag) { - this.mag = mag.clone(); + private double mag_along, mag_across, mag_through; + + public void set_mag(double along, double across, double through) { + mag_along = along; + mag_across = across; + mag_through = through; } public double mag_along() { - if (mag != null) - return AltosMag.convert_gauss(mag.along); - return AltosLib.MISSING; + return mag_along; } public double mag_across() { - if (mag != null) - return AltosMag.convert_gauss(mag.across); - return AltosLib.MISSING; + return mag_across; } public double mag_through() { - if (mag != null) - return AltosMag.convert_gauss(mag.through); - return AltosLib.MISSING; - } - - public AltosMs5607 make_baro() { - if (baro == null) - baro = new AltosMs5607(); - return baro; - } - - public void set_ms5607(AltosMs5607 ms5607) { - baro = ms5607; - - if (baro != null && baro.pa != AltosLib.MISSING && baro.cc != AltosLib.MISSING) { - set_pressure(baro.pa); - set_temperature(baro.cc / 100.0); - } - } - - public void set_ms5607(int pres, int temp) { - if (baro != null) { - baro.set(pres, temp); - - set_pressure(baro.pa); - set_temperature(baro.cc / 100.0); - } + return mag_through; } public void set_companion(AltosCompanion companion) { this.companion = companion; } - void update_accel() { - if (accel == AltosLib.MISSING) - return; - if (accel_plus_g == AltosLib.MISSING) - return; - if (accel_minus_g == AltosLib.MISSING) - return; - - double counts_per_g = (accel_minus_g - accel_plus_g) / 2.0; - double counts_per_mss = counts_per_g / 9.80665; - acceleration.set_measured((accel_plus_g - accel) / counts_per_mss, time); - } - - public void set_accel_g(double accel_plus_g, double accel_minus_g) { - if (accel_plus_g != AltosLib.MISSING) { - this.accel_plus_g = accel_plus_g; - this.accel_minus_g = accel_minus_g; - update_accel(); - } - } - - public void set_ground_accel(double ground_accel) { - if (ground_accel != AltosLib.MISSING) - this.ground_accel = ground_accel; - } - - public void set_accel(double accel) { - if (accel != AltosLib.MISSING) { - this.accel = accel; - if (state == AltosLib.ao_flight_pad) { - if (ground_accel_avg == AltosLib.MISSING) - ground_accel_avg = accel; - else - ground_accel_avg = (ground_accel_avg * 7 + accel) / 8; - } + public void set_acceleration(double acceleration) { + if (acceleration != AltosLib.MISSING) { + this.acceleration.set_measured(acceleration, time); + set |= set_data; } - update_accel(); } public void set_temperature(double temperature) { @@ -1481,95 +1051,21 @@ public class AltosState implements Cloneable { } } - public void set_ignitor_voltage(double[] voltage) { - this.ignitor_voltage = voltage; + public void set_igniter_voltage(double[] voltage) { + this.igniter_voltage = voltage; } public void set_pyro_fired(int fired) { this.pyro_fired = fired; } - public double time_since_boost() { - if (tick == AltosLib.MISSING) - return 0.0; - - if (boost_tick == AltosLib.MISSING) - return tick / 100.0; - return (tick - boost_tick) / 100.0; - } - - public boolean valid() { - return tick != AltosLib.MISSING && serial != AltosLib.MISSING; - } - - public AltosGPS make_temp_gps(boolean sats) { - if (temp_gps == null) { - temp_gps = new AltosGPS(gps); - } - gps_pending = true; - if (sats) { - if (tick != temp_gps_sat_tick) - temp_gps.cc_gps_sat = null; - temp_gps_sat_tick = tick; - } - return temp_gps; - } - - public void set_temp_gps() { - set_gps(temp_gps, gps_sequence + 1); - gps_pending = false; - temp_gps = null; - } - - public void set_config_data(AltosConfigData config_data) { - if (config_data.callsign != null) - set_callsign(config_data.callsign); - if (config_data.accel_cal_plus != AltosLib.MISSING && - config_data.accel_cal_minus != AltosLib.MISSING) - set_accel_g(config_data.accel_cal_plus, config_data.accel_cal_minus); - if (config_data.product != null) - set_product(config_data.product); - if (config_data.log_format != AltosLib.MISSING) - set_log_format(config_data.log_format); - if (config_data.serial != AltosLib.MISSING) - set_serial(config_data.serial); - AltosMs5607 ms5607 = new AltosMs5607(config_data); - if (ms5607.valid_config()) - set_ms5607(ms5607); - } - - public AltosState clone() { - AltosState s = new AltosState(); - s.copy(this); - - /* Code to test state save/restore. Enable only for that purpose - */ - if (false) { - AltosJson json = new AltosJson(this); - String onetrip = json.toPrettyString(); - AltosJson back = AltosJson.fromString(onetrip); - AltosState tripstate = (AltosState) back.make(this.getClass()); - AltosJson tripjson = new AltosJson(tripstate); - String twotrip = tripjson.toPrettyString(); - - if (!onetrip.equals(twotrip)) { - try { - FileWriter one_file = new FileWriter("one.json", true); - one_file.write(onetrip); - one_file.flush(); - FileWriter two_file = new FileWriter("two.json", true); - two_file.write(twotrip); - two_file.flush(); - } catch (Exception e) { - } - System.out.printf("json error\n"); - System.exit(1); - } - } - return s; + public AltosState() { + Thread.dumpStack(); + init(); } - public AltosState () { + public AltosState (AltosCalData cal_data) { + super(cal_data); init(); } } diff --git a/altoslib/AltosStateIterable.java b/altoslib/AltosStateIterable.java deleted file mode 100644 index ec3d944d..00000000 --- a/altoslib/AltosStateIterable.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright © 2013 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.altoslib_11; - -import java.io.*; -import java.util.*; - -public abstract class AltosStateIterable implements Iterable { - - public void write_comments (PrintStream out) { - } - - public abstract void write(PrintStream out); - - public static AltosStateIterable iterable(File file) { - try { - if (file.getName().endsWith("telem")) - return new AltosTelemetryFile(new FileInputStream(file)); - else - return new AltosEepromFile(new FileReader(file)); - } catch (Exception e) { - return null; - } - } -} diff --git a/altoslib/AltosStateName.java b/altoslib/AltosStateName.java new file mode 100644 index 00000000..5ba21f27 --- /dev/null +++ b/altoslib/AltosStateName.java @@ -0,0 +1,32 @@ +/* + * Copyright © 2017 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altoslib_12; + +public class AltosStateName extends AltosUnits { + + public double value(double v, boolean imperial_units) { return v; } + + public double inverse(double v, boolean imperial_units) { return v; } + + public String string_value(double v, boolean imperial_units) { + return AltosLib.state_name((int) v); + } + + public String show_units(boolean imperial_units) { return "state"; } + + public String say_units(boolean imperial_units) { return "state"; } + + public int show_fraction(int width, boolean imperial_units) { return 0; } +} diff --git a/altoslib/AltosStateUpdate.java b/altoslib/AltosStateUpdate.java deleted file mode 100644 index e9698cba..00000000 --- a/altoslib/AltosStateUpdate.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright © 2013 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.altoslib_11; - -public interface AltosStateUpdate { - public void update_state(AltosState state) throws InterruptedException, AltosUnknownProduct; -} diff --git a/altoslib/AltosStringInputStream.java b/altoslib/AltosStringInputStream.java new file mode 100644 index 00000000..48fff3ea --- /dev/null +++ b/altoslib/AltosStringInputStream.java @@ -0,0 +1,61 @@ +/* + * Copyright © 2017 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altoslib_12; + +import java.util.*; +import java.io.*; + +public class AltosStringInputStream extends InputStream { + + String s; + int at; + int mark; + + public int available() { + return s.length() - at; + } + + public void mark(int read_limit) { + mark = at; + } + + public boolean markSupported() { + return true; + } + + public int read() { + if (at == s.length()) + return -1; + return (int) s.charAt(at++); + } + + public void reset() { + at = mark; + } + + public long skip(long n) throws IOException { + if (n < 0) n = 0; + + if (at + n > s.length()) + n = s.length() - at; + at += n; + return n; + } + + public AltosStringInputStream(String s) { + this.s = s; + this.at = 0; + } +} diff --git a/altoslib/AltosTelemetry.java b/altoslib/AltosTelemetry.java index f830bf35..7d576942 100644 --- a/altoslib/AltosTelemetry.java +++ b/altoslib/AltosTelemetry.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.text.*; @@ -24,13 +24,16 @@ import java.text.*; * Telemetry data contents */ -public abstract class AltosTelemetry implements AltosStateUpdate { +public abstract class AltosTelemetry implements AltosDataProvider { + int[] bytes; /* All telemetry packets have these fields */ - public int tick; - public int serial; - public int rssi; - public int status; + public int rssi() { return AltosConvert.telem_to_rssi(AltosLib.int8(bytes, bytes.length - 3)); } + public int status() { return AltosLib.uint8(bytes, bytes.length - 2); } + + /* All telemetry packets report these fields in some form */ + public abstract int serial(); + public abstract int tick(); /* Mark when we received the packet */ long received_time; @@ -43,13 +46,13 @@ public abstract class AltosTelemetry implements AltosStateUpdate { return sum == bytes[bytes.length - 1]; } - public void update_state(AltosState state) { - state.set_serial(serial); - if (state.state() == AltosLib.ao_flight_invalid) - state.set_state(AltosLib.ao_flight_startup); - state.set_tick(tick); - state.set_rssi(rssi, status); - state.set_received_time(received_time); + public void provide_data(AltosDataListener listener) { + listener.set_serial(serial()); + if (listener.state == AltosLib.ao_flight_invalid) + listener.set_state(AltosLib.ao_flight_startup); + listener.set_tick(tick()); + listener.set_rssi(rssi(), status()); + listener.set_received_time(received_time); } final static int PKT_APPEND_STATUS_1_CRC_OK = (1 << 7); @@ -88,12 +91,6 @@ public abstract class AltosTelemetry implements AltosStateUpdate { if (!cksum(bytes)) throw new ParseException(String.format("invalid line \"%s\"", hex), 0); - int rssi = AltosLib.int8(bytes, bytes.length - 3) / 2 - 74; - int status = AltosLib.uint8(bytes, bytes.length - 2); - - if ((status & PKT_APPEND_STATUS_1_CRC_OK) == 0) - throw new AltosCRCException(rssi); - /* length, data ..., rssi, status, checksum -- 4 bytes extra */ switch (bytes.length) { case AltosLib.ao_telemetry_standard_len + 4: @@ -108,35 +105,18 @@ public abstract class AltosTelemetry implements AltosStateUpdate { default: throw new ParseException(String.format("Invalid packet length %d", bytes.length), 0); } - if (telem != null) { - telem.received_time = System.currentTimeMillis(); - telem.rssi = rssi; - telem.status = status; - } return telem; } - public static int extend_height(AltosState state, int height_16) { - double compare_height; - int height = height_16; - - if (state.gps != null && state.gps.alt != AltosLib.MISSING) { - compare_height = state.gps_height(); - } else { - compare_height = state.height(); - } - - if (compare_height != AltosLib.MISSING) { - int high_bits = (int) Math.floor (compare_height / 65536.0); - - height = (high_bits << 16) | (height_16 & 0xffff); + public AltosTelemetry() { + this.received_time = System.currentTimeMillis(); + } - if (Math.abs(height + 65536 - compare_height) < Math.abs(height - compare_height)) - height += 65536; - else if (Math.abs(height - 65536 - compare_height) < Math.abs(height - compare_height)) - height -= 65536; - } - return height; + public AltosTelemetry(int[] bytes) throws AltosCRCException { + this(); + this.bytes = bytes; + if ((status() & PKT_APPEND_STATUS_1_CRC_OK) == 0) + throw new AltosCRCException(rssi()); } public static AltosTelemetry parse(String line) throws ParseException, AltosCRCException { @@ -149,7 +129,7 @@ public abstract class AltosTelemetry implements AltosStateUpdate { throw new AltosCRCException(AltosParse.parse_int(word[i++])); } - AltosTelemetry telem; + AltosTelemetry telem = null; if (word[i].equals("TELEM")) { telem = parse_hex(word[i+1]); diff --git a/altoslib/AltosTelemetryCompanion.java b/altoslib/AltosTelemetryCompanion.java index a97fda2d..c6dfe3eb 100644 --- a/altoslib/AltosTelemetryCompanion.java +++ b/altoslib/AltosTelemetryCompanion.java @@ -16,24 +16,19 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosTelemetryCompanion extends AltosTelemetryStandard { - AltosCompanion companion; - - static final public int max_channels = 12; - - public AltosTelemetryCompanion(int[] bytes) { - super(bytes); + AltosCompanion companion() { int channels = uint8(7); if (channels > max_channels) channels = max_channels; - companion = new AltosCompanion(channels); + AltosCompanion companion = new AltosCompanion(channels); - companion.tick = tick; + companion.tick = tick(); companion.board_id = uint8(5); companion.update_period = uint8(6); @@ -45,11 +40,17 @@ public class AltosTelemetryCompanion extends AltosTelemetryStandard { for (int i = 0; i < channels; i++) companion.companion_data[i] = uint16(8 + i * 2); } + return companion; } - public void update_state(AltosState state) { - super.update_state(state); + static final public int max_channels = 12; + + public AltosTelemetryCompanion(int[] bytes) throws AltosCRCException { + super(bytes); + } - state.set_companion(companion); + public void provide_data(AltosDataListener listener) { + super.provide_data(listener); + listener.set_companion(companion()); } } diff --git a/altoslib/AltosTelemetryConfiguration.java b/altoslib/AltosTelemetryConfiguration.java index 6ded5461..ea307442 100644 --- a/altoslib/AltosTelemetryConfiguration.java +++ b/altoslib/AltosTelemetryConfiguration.java @@ -16,47 +16,39 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosTelemetryConfiguration extends AltosTelemetryStandard { - int device_type; - int flight; - int config_major; - int config_minor; - int apogee_delay; - int main_deploy; - int v_batt; - int flight_log_max; - String callsign; - String version; - - public AltosTelemetryConfiguration(int[] bytes) { - super(bytes); + int device_type() { return uint8(5); } + int flight() { return uint16(6); } + int config_major() { return uint8(8); } + int config_minor() { return uint8(9); } + int apogee_delay() { return uint16(10); } + int main_deploy() { return uint16(12); } + int v_batt() { return uint16(10); } + int flight_log_max() { return uint16(14); } + String callsign() { return string(16, 8); } + String version() { return string(24, 8); } - device_type = uint8(5); - flight = uint16(6); - config_major = uint8(8); - config_minor = uint8(9); - v_batt = uint16(10); - apogee_delay = uint16(10); - main_deploy = uint16(12); - flight_log_max = uint16(14); - callsign = string(16, 8); - version = string(24, 8); + public AltosTelemetryConfiguration(int[] bytes) throws AltosCRCException { + super(bytes); } - public void update_state(AltosState state) { - super.update_state(state); - state.set_device_type(device_type); - state.set_flight(flight); - state.set_config(config_major, config_minor, flight_log_max); - if (device_type == AltosLib.product_telegps) - state.set_battery_voltage(AltosConvert.tele_gps_voltage(v_batt)); + public void provide_data(AltosDataListener listener) { + super.provide_data(listener); + + AltosCalData cal_data = listener.cal_data(); + + cal_data.set_device_type(device_type()); + cal_data.set_flight(flight()); + cal_data.set_config(config_major(), config_minor(), flight_log_max()); + if (device_type() == AltosLib.product_telegps) + listener.set_battery_voltage(AltosConvert.tele_gps_voltage(v_batt())); else - state.set_flight_params(apogee_delay, main_deploy); + cal_data.set_flight_params(apogee_delay() / 100.0, main_deploy()); - state.set_callsign(callsign); - state.set_firmware_version(version); + cal_data.set_callsign(callsign()); + cal_data.set_firmware_version(version()); } } diff --git a/altoslib/AltosTelemetryFile.java b/altoslib/AltosTelemetryFile.java index 9c5f8dae..135b0284 100644 --- a/altoslib/AltosTelemetryFile.java +++ b/altoslib/AltosTelemetryFile.java @@ -16,82 +16,125 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.util.*; import java.text.*; -class AltosTelemetryIterator implements Iterator { - AltosState state; - Iterator telems; - AltosTelemetry next; - boolean seen; - - public boolean hasNext() { - return !seen || telems.hasNext(); - } - - public AltosState next() { - if (seen) { - AltosState n = state.clone(); - AltosTelemetry t = telems.next(); - - t.update_state(n); - state = n; - } - seen = true; - return state; +class AltosTelemetryNullListener extends AltosDataListener { + public void set_rssi(int rssi, int status) { } + public void set_received_time(long received_time) { } + + public void set_acceleration(double accel) { } + public void set_pressure(double pa) { } + public void set_thrust(double N) { } + + public void set_kalman(double height, double speed, double accel) { } + + public void set_temperature(double deg_c) { } + public void set_battery_voltage(double volts) { } + + public void set_apogee_voltage(double volts) { } + public void set_main_voltage(double volts) { } + + public void set_gps(AltosGPS gps) { } + + public void set_orient(double orient) { } + public void set_gyro(double roll, double pitch, double yaw) { } + public void set_accel_ground(double along, double across, double through) { } + public void set_accel(double along, double across, double through) { } + public void set_mag(double along, double across, double through) { } + public void set_pyro_voltage(double volts) { } + public void set_igniter_voltage(double[] voltage) { } + public void set_pyro_fired(int pyro_mask) { } + public void set_companion(AltosCompanion companion) { } + + public boolean cal_data_complete() { + /* All telemetry packets */ + AltosCalData cal_data = cal_data(); + + if (cal_data.serial == AltosLib.MISSING) + return false; + + if (cal_data.boost_tick == AltosLib.MISSING) + return false; + + /* + * TelemetryConfiguration: + * + * device_type, flight, config version, log max, + * flight params, callsign and version + */ + if (cal_data.device_type == AltosLib.MISSING) + return false; + + /* + * TelemetrySensor or TelemetryMegaData: + * + * ground_accel, accel+/-, ground pressure + */ + if (cal_data.ground_pressure == AltosLib.MISSING) + return false; + + /* + * TelemetryLocation + */ + if (AltosLib.has_gps(cal_data.device_type) && cal_data.gps_pad == null) + return false; + + return true; } - public void remove () { - } - - public AltosTelemetryIterator(AltosState start, Iterator telems) { - this.state = start; - this.telems = telems; - this.seen = false; + public AltosTelemetryNullListener(AltosCalData cal_data) { + super(cal_data); } } -public class AltosTelemetryFile extends AltosStateIterable { +public class AltosTelemetryFile implements AltosRecordSet { AltosTelemetryIterable telems; - AltosState start; + AltosCalData cal_data; public void write_comments(PrintStream out) { } public void write(PrintStream out) { - } - public AltosTelemetryFile(FileInputStream input) { - telems = new AltosTelemetryIterable(input); - start = new AltosState(); - - /* Find boost tick */ - AltosState state = start.clone(); + /* Construct cal data by walking through the telemetry data until we've found everything available */ + public AltosCalData cal_data() { + if (cal_data == null) { + cal_data = new AltosCalData(); + AltosTelemetryNullListener l = new AltosTelemetryNullListener(cal_data); - for (AltosTelemetry telem : telems) { - telem.update_state(state); - state.finish_update(); - if (state.state() != AltosLib.ao_flight_invalid && state.state() >= AltosLib.ao_flight_boost) { - start.set_boost_tick(state.tick); - break; + for (AltosTelemetry telem : telems) { + telem.provide_data(l); + if (l.cal_data_complete()) + break; } } + return cal_data; } - public Iterator iterator() { - AltosState state = start.clone(); - Iterator i = telems.iterator(); + public void capture_series(AltosDataListener listener) { + AltosCalData cal_data = cal_data(); + + cal_data.reset(); + for (AltosTelemetry telem : telems) { + int tick = telem.tick(); + cal_data.set_tick(tick); - while (i.hasNext() && !state.valid()) { - AltosTelemetry t = i.next(); - t.update_state(state); - state.finish_update(); + /* Try to pick up at least one pre-boost value */ + if (cal_data.time() >= -2) + telem.provide_data(listener); + if (listener.state == AltosLib.ao_flight_landed) + break; } - return new AltosTelemetryIterator(state, i); + listener.finish(); + } + + public AltosTelemetryFile(FileInputStream input) throws IOException { + telems = new AltosTelemetryIterable(input); } } diff --git a/altoslib/AltosTelemetryIterable.java b/altoslib/AltosTelemetryIterable.java index 0cba86a3..d3e4ce67 100644 --- a/altoslib/AltosTelemetryIterable.java +++ b/altoslib/AltosTelemetryIterable.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.io.*; import java.util.*; @@ -67,7 +67,7 @@ public class AltosTelemetryIterable implements Iterable { int index; public void add (AltosTelemetry telem) { - int t = telem.tick; + int t = telem.tick(); if (!telems.isEmpty()) { while (t < tick - 1000) t += 65536; @@ -80,29 +80,25 @@ public class AltosTelemetryIterable implements Iterable { return new AltosTelemetryOrderedIterator(telems); } - public AltosTelemetryIterable (FileInputStream input) { + public AltosTelemetryIterable (FileInputStream input) throws IOException { telems = new TreeSet (); tick = 0; index = 0; - try { - for (;;) { - String line = AltosLib.gets(input); - if (line == null) { + for (;;) { + String line = AltosLib.gets(input); + if (line == null) { + break; + } + try { + AltosTelemetry telem = AltosTelemetry.parse(line); + if (telem == null) break; - } - try { - AltosTelemetry telem = AltosTelemetry.parse(line); - if (telem == null) - break; - add(telem); - } catch (ParseException pe) { - System.out.printf("parse exception %s\n", pe.getMessage()); - } catch (AltosCRCException ce) { - } + add(telem); + } catch (ParseException pe) { + System.out.printf("parse exception %s\n", pe.getMessage()); + } catch (AltosCRCException ce) { } - } catch (IOException io) { - System.out.printf("io exception\n"); } } } diff --git a/altoslib/AltosTelemetryLegacy.java b/altoslib/AltosTelemetryLegacy.java index 08c52986..027f601e 100644 --- a/altoslib/AltosTelemetryLegacy.java +++ b/altoslib/AltosTelemetryLegacy.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.text.*; @@ -233,6 +233,17 @@ public class AltosTelemetryLegacy extends AltosTelemetry { final static String AO_TELEM_SAT_SVID = "s_v"; final static String AO_TELEM_SAT_C_N_0 = "s_c"; + public int tick; + public int serial; + public int rssi; + public int status; + + public int tick() { return tick; } + public int serial() { return serial; } + + public int rssi() { return rssi; } + public int status() { return status; } + public int version; public String callsign; public int flight; @@ -271,7 +282,6 @@ public class AltosTelemetryLegacy extends AltosTelemetry { flight = map.get_int(AO_TELEM_FLIGHT, AltosLib.MISSING); rssi = map.get_int(AO_TELEM_RSSI, AltosLib.MISSING); state = AltosLib.state(map.get_string(AO_TELEM_STATE, "invalid")); - tick = map.get_int(AO_TELEM_TICK, 0); /* raw sensor values */ accel = map.get_int(AO_TELEM_RAW_ACCEL, AltosLib.MISSING); @@ -420,7 +430,6 @@ public class AltosTelemetryLegacy extends AltosTelemetry { * Given a hex dump of a legacy telemetry line, construct an AltosRecordTM from that */ - int[] bytes; int adjust; /* @@ -452,8 +461,9 @@ public class AltosTelemetryLegacy extends AltosTelemetry { static final int AO_GPS_DATE_VALID = (1 << 6); static final int AO_GPS_COURSE_VALID = (1 << 7); - public AltosTelemetryLegacy(int[] in_bytes) { - bytes = in_bytes; + public AltosTelemetryLegacy(int[] in_bytes) throws AltosCRCException { + super(in_bytes); + version = 4; adjust = 0; @@ -463,6 +473,7 @@ public class AltosTelemetryLegacy extends AltosTelemetry { } else serial = uint16(0); + rssi = super.rssi(); callsign = string(62, 8); flight = uint16(2); state = uint8(4); @@ -537,23 +548,26 @@ public class AltosTelemetryLegacy extends AltosTelemetry { } } - public void update_state(AltosState state) { - state.set_tick(tick); - state.set_state(this.state); - state.set_flight(flight); - state.set_serial(serial); - state.set_rssi(rssi, status); + public void provide_data(AltosDataListener listener) { + listener.set_serial(serial); + listener.set_tick(tick); + listener.set_state(this.state); + listener.set_flight(flight); + listener.set_rssi(rssi, status); + + listener.set_pressure(AltosConvert.barometer_to_pressure(pres)); + + AltosCalData cal_data = listener.cal_data(); - state.set_pressure(AltosConvert.barometer_to_pressure(pres)); - state.set_accel_g(accel_plus_g, accel_minus_g); - state.set_accel(accel); + cal_data.set_accel_plus_minus(accel_plus_g, accel_minus_g); + listener.set_acceleration(cal_data.acceleration(accel)); if (kalman_height != AltosLib.MISSING) - state.set_kalman(kalman_height, kalman_speed, kalman_acceleration); - state.set_temperature(AltosConvert.thermometer_to_temperature(temp)); - state.set_battery_voltage(AltosConvert.cc_battery_to_voltage(batt)); - state.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(apogee)); - state.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(main)); + listener.set_kalman(kalman_height, kalman_speed, kalman_acceleration); + listener.set_temperature(AltosConvert.thermometer_to_temperature(temp)); + listener.set_battery_voltage(AltosConvert.cc_battery_to_voltage(batt)); + listener.set_apogee_voltage(AltosConvert.cc_igniter_to_voltage(apogee)); + listener.set_main_voltage(AltosConvert.cc_igniter_to_voltage(main)); if (gps != null) - state.set_gps(gps, gps_sequence); + listener.set_gps(gps); } } diff --git a/altoslib/AltosTelemetryLocation.java b/altoslib/AltosTelemetryLocation.java index 11995640..f4366e33 100644 --- a/altoslib/AltosTelemetryLocation.java +++ b/altoslib/AltosTelemetryLocation.java @@ -16,81 +16,73 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosTelemetryLocation extends AltosTelemetryStandard { - int flags; - int altitude; - int latitude; - int longitude; - int year; - int month; - int day; - int hour; - int minute; - int second; - int pdop; - int hdop; - int vdop; - int mode; - int ground_speed; - int climb_rate; - int course; + int flags() { return uint8(5); } + int altitude() { + if ((mode() & AO_GPS_MODE_ALTITUDE_24) != 0) + return (int8(31) << 16) | uint16(6); + else + return int16(6); + } + int latitude() { return uint32(8); } + int longitude() { return uint32(12); } + int year() { return uint8(16); } + int month() { return uint8(17); } + int day() { return uint8(18); } + int hour() { return uint8(19); } + int minute() { return uint8(20); } + int second() { return uint8(21); } + int pdop() { return uint8(22); } + int hdop() { return uint8(23); } + int vdop() { return uint8(24); } + int mode() { return uint8(25); } + int ground_speed() { return uint16(26); } + int climb_rate() { return int16(28); } + int course() { return uint8(30); } public static final int AO_GPS_MODE_ALTITUDE_24 = (1 << 0); /* Reports 24-bits of altitude */ - public AltosTelemetryLocation(int[] bytes) { + public AltosTelemetryLocation(int[] bytes) throws AltosCRCException { super(bytes); + } - flags = uint8(5); - latitude = uint32(8); - longitude = uint32(12); - year = uint8(16); - month = uint8(17); - day = uint8(18); - hour = uint8(19); - minute = uint8(20); - second = uint8(21); - pdop = uint8(22); - hdop = uint8(23); - vdop = uint8(24); - mode = uint8(25); - ground_speed = uint16(26); - climb_rate = int16(28); - course = uint8(30); + public void provide_data(AltosDataListener listener) { + super.provide_data(listener); - if ((mode & AO_GPS_MODE_ALTITUDE_24) != 0) { - altitude = (int8(31) << 16) | uint16(6); - } else - altitude = int16(6); - } + AltosCalData cal_data = listener.cal_data(); - public void update_state(AltosState state) { - super.update_state(state); - AltosGPS gps = state.make_temp_gps(false); + AltosGPS gps = cal_data.make_temp_gps(tick(), false); + int flags = flags(); gps.nsat = flags & 0xf; gps.locked = (flags & (1 << 4)) != 0; gps.connected = (flags & (1 << 5)) != 0; + gps.pdop = pdop() / 10.0; + gps.hdop = hdop() / 10.0; + gps.vdop = vdop() / 10.0; if (gps.locked) { - gps.lat = latitude * 1.0e-7; - gps.lon = longitude * 1.0e-7; - gps.alt = altitude; - gps.year = 2000 + year; - gps.month = month; - gps.day = day; - gps.hour = hour; - gps.minute = minute; - gps.second = second; - gps.ground_speed = ground_speed * 1.0e-2; - gps.course = course * 2; - gps.climb_rate = climb_rate * 1.0e-2; - gps.pdop = pdop / 10.0; - gps.hdop = hdop / 10.0; - gps.vdop = vdop / 10.0; + gps.lat = latitude() * 1.0e-7; + gps.lon = longitude() * 1.0e-7; + gps.alt = altitude(); + gps.year = 2000 + year(); + gps.month = month(); + gps.day = day(); + gps.hour = hour(); + gps.minute = minute(); + gps.second = second(); + gps.ground_speed = ground_speed() * 1.0e-2; + gps.course = course() * 2; + gps.climb_rate = climb_rate() * 1.0e-2; + + if (gps.nsat >= 4) + cal_data.set_gps(gps); } - state.set_temp_gps(); + listener.set_gps(gps); + cal_data.set_gps(gps); + cal_data.reset_temp_gps(); } } diff --git a/altoslib/AltosTelemetryMap.java b/altoslib/AltosTelemetryMap.java index c8185434..a7ddc684 100644 --- a/altoslib/AltosTelemetryMap.java +++ b/altoslib/AltosTelemetryMap.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.text.*; import java.util.HashMap; diff --git a/altoslib/AltosTelemetryMegaData.java b/altoslib/AltosTelemetryMegaData.java index 6ea5ec89..7ef9c637 100644 --- a/altoslib/AltosTelemetryMegaData.java +++ b/altoslib/AltosTelemetryMegaData.java @@ -16,78 +16,58 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosTelemetryMegaData extends AltosTelemetryStandard { - int state; - int v_batt; - int v_pyro; - int sense[]; + int state() { return uint8(5); } - int ground_pres; - int ground_accel; - int accel_plus_g; - int accel_minus_g; + int v_batt() { return int16(6); } + int v_pyro() { return int16(8); } + int sense(int i) { int v = uint8(10+i); return v << 4 | v >> 8; } - int acceleration; - int speed; - int height_16; + int ground_pres() { return int32(16); } + int ground_accel() { return int16(20); } + int accel_plus_g() { return int16(22); } + int accel_minus_g() { return int16(24);} - public AltosTelemetryMegaData(int[] bytes) { - super(bytes); - - state = uint8(5); - - v_batt = int16(6); - v_pyro = int16(8); - - sense = new int[6]; - - for (int i = 0; i < 6; i++) { - sense[i] = uint8(10 + i) << 4; - sense[i] |= sense[i] >> 8; - } + int acceleration() { return int16(26); } + int speed() { return int16(28); } + int height_16() { return int16(30); } - ground_pres = int32(16); - ground_accel = int16(20); - accel_plus_g = int16(22); - accel_minus_g = int16(24); - - acceleration = int16(26); - speed = int16(28); - - height_16 = int16(30); + public AltosTelemetryMegaData(int[] bytes) throws AltosCRCException { + super(bytes); } - public void update_state(AltosState state) { - super.update_state(state); + public void provide_data(AltosDataListener listener) { + super.provide_data(listener); - state.set_state(this.state); + listener.set_state(state()); - state.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt)); - state.set_pyro_voltage(AltosConvert.mega_pyro_voltage(v_pyro)); + listener.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt())); + listener.set_pyro_voltage(AltosConvert.mega_pyro_voltage(v_pyro())); - state.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense[4])); - state.set_main_voltage(AltosConvert.mega_pyro_voltage(sense[5])); + listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense(4))); + listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sense(5))); double voltages[] = new double[4]; for (int i = 0; i < 4; i++) - voltages[i] = AltosConvert.mega_pyro_voltage(sense[i]); + voltages[i] = AltosConvert.mega_pyro_voltage(sense(i)); + + listener.set_igniter_voltage(voltages); - state.set_ignitor_voltage(voltages); + AltosCalData cal_data = listener.cal_data(); - state.set_ground_accel(ground_accel); - state.set_ground_pressure(ground_pres); - state.set_accel_g(accel_plus_g, accel_minus_g); + cal_data.set_ground_accel(ground_accel()); + cal_data.set_ground_pressure(ground_pres()); + cal_data.set_accel_plus_minus(accel_plus_g(), accel_minus_g()); /* Fill in the high bits of height from recent GPS * data if available, otherwise guess using the * previous kalman height */ - state.set_kalman(extend_height(state, height_16), - speed/16.0, acceleration / 16.0); + listener.set_kalman(height_16(), speed()/16.0, acceleration() / 16.0); } } diff --git a/altoslib/AltosTelemetryMegaSensor.java b/altoslib/AltosTelemetryMegaSensor.java index 2dfc455a..4c64b554 100644 --- a/altoslib/AltosTelemetryMegaSensor.java +++ b/altoslib/AltosTelemetryMegaSensor.java @@ -16,64 +16,68 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosTelemetryMegaSensor extends AltosTelemetryStandard { - int accel; - int pres; - int temp; + int orient() { return int8(5); } - int accel_x; - int accel_y; - int accel_z; + int accel() { return int16(6); } + int pres() { return int32(8); } + int temp() { return int16(12); } - int gyro_x; - int gyro_y; - int gyro_z; + int accel_x() { return int16(14); } + int accel_y() { return int16(16); } + int accel_z() { return int16(18); } - int mag_x; - int mag_y; - int mag_z; + int gyro_x() { return int16(20); } + int gyro_y() { return int16(22); } + int gyro_z() { return int16(24); } - int orient; + int mag_x() { return int16(26); } + int mag_z() { return int16(28); } + int mag_y() { return int16(30); } - public AltosTelemetryMegaSensor(int[] bytes) { + public AltosTelemetryMegaSensor(int[] bytes) throws AltosCRCException { super(bytes); + } - orient = int8(5); - accel = int16(6); - pres = int32(8); - temp = int16(12); + public void provide_data(AltosDataListener listener) { + super.provide_data(listener); - accel_x = int16(14); - accel_y = int16(16); - accel_z = int16(18); + AltosCalData cal_data = listener.cal_data(); - gyro_x = int16(20); - gyro_y = int16(22); - gyro_z = int16(24); + listener.set_acceleration(cal_data.acceleration(accel())); + listener.set_pressure(pres()); + listener.set_temperature(temp() / 100.0); - mag_x = int16(26); - mag_y = int16(28); - mag_z = int16(30); - } + listener.set_orient(orient()); - public void update_state(AltosState state) { - super.update_state(state); + /* XXX we have no calibration data for these values */ - state.set_accel(accel); - state.set_pressure(pres); - state.set_temperature(temp / 100.0); + if (cal_data.accel_zero_along == AltosLib.MISSING) + cal_data.set_accel_zero(0, 0, 0); + if (cal_data.gyro_zero_roll == AltosLib.MISSING) + cal_data.set_gyro_zero(0, 0, 0); - state.set_orient(orient); + int accel_along = accel_y(); + int accel_across = accel_x(); + int accel_through = accel_z(); + int gyro_roll = gyro_y(); + int gyro_pitch = gyro_x(); + int gyro_yaw = gyro_z(); - state.set_imu(new AltosIMU(accel_y, /* along */ - accel_x, /* across */ - accel_z, /* through */ - gyro_y, /* along */ - gyro_x, /* across */ - gyro_z)); /* through */ + int mag_along = mag_y(); + int mag_across = mag_x(); + int mag_through = mag_z(); - state.set_mag(new AltosMag(mag_x, mag_y, mag_z)); + listener.set_accel(cal_data.accel_along(accel_along), + cal_data.accel_across(accel_across), + cal_data.accel_through(accel_through)); + listener.set_gyro(cal_data.gyro_roll(gyro_roll), + cal_data.gyro_pitch(gyro_pitch), + cal_data.gyro_yaw(gyro_yaw)); + listener.set_mag(cal_data.mag_along(mag_along), + cal_data.mag_across(mag_across), + cal_data.mag_through(mag_through)); } } diff --git a/altoslib/AltosTelemetryMetrumData.java b/altoslib/AltosTelemetryMetrumData.java index 53a10cc4..8cd09b41 100644 --- a/altoslib/AltosTelemetryMetrumData.java +++ b/altoslib/AltosTelemetryMetrumData.java @@ -16,28 +16,23 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosTelemetryMetrumData extends AltosTelemetryStandard { - int ground_pres; - int ground_accel; - int accel_plus_g; - int accel_minus_g; + int ground_pres() { return int32(8); } + int ground_accel() { return int16(12); } + int accel_plus_g() { return int16(14); } + int accel_minus_g() { return int16(16); } - public AltosTelemetryMetrumData(int[] bytes) { + public AltosTelemetryMetrumData(int[] bytes) throws AltosCRCException { super(bytes); - - ground_pres = int32(8); - ground_accel = int16(12); - accel_plus_g = int16(14); - accel_minus_g = int16(16); } - public void update_state(AltosState state) { - state.set_ground_accel(ground_accel); - state.set_accel_g(accel_plus_g, accel_minus_g); - state.set_ground_pressure(ground_pres); + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + cal_data.set_ground_accel(ground_accel()); + cal_data.set_accel_plus_minus(accel_plus_g(), accel_minus_g()); + cal_data.set_ground_pressure(ground_pres()); } } diff --git a/altoslib/AltosTelemetryMetrumSensor.java b/altoslib/AltosTelemetryMetrumSensor.java index e15043b4..79d3a499 100644 --- a/altoslib/AltosTelemetryMetrumSensor.java +++ b/altoslib/AltosTelemetryMetrumSensor.java @@ -16,56 +16,42 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosTelemetryMetrumSensor extends AltosTelemetryStandard { - int state; + int state() { return uint8(5); } - int accel; - int pres; - int temp; + int accel() { return int16(6); } + int pres() { return int32(8); } + int temp() { return int16(12); } - int acceleration; - int speed; - int height_16; + int acceleration() { return int16(14); } + int speed() { return int16(16); } + int height_16() { return int16(18); } - int v_batt; - int sense_a; - int sense_m; + int v_batt() { return int16(20); } + int sense_a() { return int16(22); } + int sense_m() { return int16(24); } - public AltosTelemetryMetrumSensor(int[] bytes) { + public AltosTelemetryMetrumSensor(int[] bytes) throws AltosCRCException { super(bytes); - - state = int8(5); - accel = int16(6); - pres = int32(8); - temp = int16(12); - - acceleration = int16(14); - speed = int16(16); - height_16 = int16(18); - - v_batt = int16(20); - sense_a = int16(22); - sense_m = int16(24); } - public void update_state(AltosState state) { - super.update_state(state); + public void provide_data(AltosDataListener listener) { + super.provide_data(listener); - state.set_state(this.state); + listener.set_state(state()); - state.set_accel(accel); - state.set_pressure(pres); - state.set_temperature(temp/100.0); + listener.set_acceleration(listener.cal_data().acceleration(accel())); + listener.set_pressure(pres()); + listener.set_temperature(temp()/100.0); - state.set_kalman(extend_height(state, height_16), - speed/16.0, acceleration/16.0); + listener.set_kalman(height_16(), speed()/16.0, acceleration()/16.0); - state.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt)); + listener.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)); + listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense_a())); + listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sense_m())); } } diff --git a/altoslib/AltosTelemetryMini2.java b/altoslib/AltosTelemetryMini2.java index 50ec504d..3ea287ac 100644 --- a/altoslib/AltosTelemetryMini2.java +++ b/altoslib/AltosTelemetryMini2.java @@ -16,58 +16,46 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosTelemetryMini2 extends AltosTelemetryStandard { - int state; - int v_batt; - int sense_a; - int sense_m; + int state() { return uint8(5); } - int pres; - int temp; + int v_batt() { return int16(6); } + int sense_a() { return int16(8); } + int sense_m() { return int16(10); } - int acceleration; - int speed; - int height; + int pres() { return int32(12); } + int temp() { return int16(16); } - int ground_pres; + int acceleration() { return int16(18); } + int speed() { return int16(20); } + int height() { return int16(22); } - public AltosTelemetryMini2(int[] bytes) { - super(bytes); - - state = int8(5); - - v_batt = int16(6); - sense_a = int16(8); - sense_m = int16(10); - - pres = int32(12); - temp = int16(16); + int ground_pres() { return int32(24); } - acceleration = int16(18); - speed = int16(20); - height = int16(22); - - ground_pres = int32(24); + public AltosTelemetryMini2(int[] bytes) throws AltosCRCException { + super(bytes); } - public void update_state(AltosState state) { - super.update_state(state); + public void provide_data(AltosDataListener listener) { + super.provide_data(listener); + + listener.set_state(state()); - state.set_state(this.state); + listener.set_battery_voltage(AltosConvert.tele_mini_2_voltage(v_batt())); + listener.set_apogee_voltage(AltosConvert.tele_mini_2_voltage(sense_a())); + listener.set_main_voltage(AltosConvert.tele_mini_2_voltage(sense_m())); - state.set_battery_voltage(AltosConvert.tele_mini_2_voltage(v_batt)); - state.set_apogee_voltage(AltosConvert.tele_mini_2_voltage(sense_a)); - state.set_main_voltage(AltosConvert.tele_mini_2_voltage(sense_m)); + AltosCalData cal_data = listener.cal_data(); - state.set_ground_pressure(ground_pres); + cal_data.set_ground_pressure(ground_pres()); - state.set_pressure(pres); - state.set_temperature(temp/100.0); + listener.set_pressure(pres()); + listener.set_temperature(temp()/100.0); - state.set_kalman(height, speed/16.0, acceleration/16.0); + listener.set_kalman(height(), speed()/16.0, acceleration()/16.0); } } diff --git a/altoslib/AltosTelemetryMini3.java b/altoslib/AltosTelemetryMini3.java index 21f8c485..c66f8e61 100644 --- a/altoslib/AltosTelemetryMini3.java +++ b/altoslib/AltosTelemetryMini3.java @@ -16,61 +16,45 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosTelemetryMini3 extends AltosTelemetryStandard { - int state; + int state() { return uint8(5); } - int v_batt; - int sense_a; - int sense_m; + int v_batt() { return int16(6); } + int sense_a() { return int16(8); } + int sense_m() { return int16(10); } - int pres; - int temp; + int pres() { return int32(12); } + int temp() { return int16(16); } - int acceleration; - int speed; - int height_16; + int acceleration() { return int16(18); } + int speed() { return int16(20); } + int height_16() { return int16(22); } - int ground_pres; + int ground_pres() { return int32(24); } - public AltosTelemetryMini3(int[] bytes) { + public AltosTelemetryMini3(int[] bytes) throws AltosCRCException { super(bytes); - - state = int8(5); - - v_batt = int16(6); - sense_a = int16(8); - sense_m = int16(10); - - pres = int32(12); - temp = int16(16); - - acceleration = int16(18); - speed = int16(20); - height_16 = int16(22); - - ground_pres = int32(24); } - public void update_state(AltosState state) { - super.update_state(state); + public void provide_data(AltosDataListener listener) { + super.provide_data(listener); - state.set_state(this.state); + listener.set_state(state()); - state.set_battery_voltage(AltosConvert.tele_mini_3_battery_voltage(v_batt)); + listener.set_battery_voltage(AltosConvert.tele_mini_3_battery_voltage(v_batt())); - state.set_apogee_voltage(AltosConvert.tele_mini_3_pyro_voltage(sense_a)); - state.set_main_voltage(AltosConvert.tele_mini_3_pyro_voltage(sense_m)); + listener.set_apogee_voltage(AltosConvert.tele_mini_3_pyro_voltage(sense_a())); + listener.set_main_voltage(AltosConvert.tele_mini_3_pyro_voltage(sense_m())); - state.set_pressure(pres); - state.set_temperature(temp/100.0); + listener.cal_data().set_ground_pressure(ground_pres()); - state.set_kalman(extend_height(state, height_16), - speed/16.0, acceleration/16.0); + listener.set_pressure(pres()); + listener.set_temperature(temp()/100.0); - state.set_ground_pressure(ground_pres); + listener.set_kalman(height_16(), speed()/16.0, acceleration()/16.0); } } diff --git a/altoslib/AltosTelemetryRaw.java b/altoslib/AltosTelemetryRaw.java index 339043a6..f2108d68 100644 --- a/altoslib/AltosTelemetryRaw.java +++ b/altoslib/AltosTelemetryRaw.java @@ -16,14 +16,14 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosTelemetryRaw extends AltosTelemetryStandard { - public AltosTelemetryRaw(int[] bytes) { + public AltosTelemetryRaw(int[] bytes) throws AltosCRCException { super(bytes); } - public void update_state(AltosState state) { - super.update_state(state); + public void provide_data(AltosDataListener listener) { + super.provide_data(listener); } } diff --git a/altoslib/AltosTelemetryReader.java b/altoslib/AltosTelemetryReader.java index 6a93c2c3..26fe4f26 100644 --- a/altoslib/AltosTelemetryReader.java +++ b/altoslib/AltosTelemetryReader.java @@ -16,19 +16,20 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.text.*; import java.io.*; import java.util.concurrent.*; public class AltosTelemetryReader extends AltosFlightReader { - AltosLink link; - AltosLog log; - double frequency; - int telemetry; - int telemetry_rate; - AltosState state = null; + AltosLink link; + AltosLog log; + double frequency; + int telemetry; + int telemetry_rate; + private AltosState state = null; + private AltosCalData cal_data = null; LinkedBlockingQueue telem; @@ -40,14 +41,22 @@ public class AltosTelemetryReader extends AltosFlightReader { throw new IOException("IO error"); } while (!link.get_monitor()); AltosTelemetry telem = AltosTelemetry.parse(l.line); - if (state == null) - state = new AltosState(); - else - state = state.clone(); - telem.update_state(state); + if (state == null) { + System.out.printf("Make state\n"); + state = new AltosState(cal_data()); + } + telem.provide_data(state); return state; } + public AltosCalData cal_data() { + if (cal_data == null) { + System.out.printf("Make cal data\n"); + cal_data = new AltosCalData(); + } + return cal_data; + } + public void flush() { telem.clear(); } @@ -55,6 +64,7 @@ public class AltosTelemetryReader extends AltosFlightReader { public void reset() { flush(); state = null; + cal_data = null; } public void close(boolean interrupted) { diff --git a/altoslib/AltosTelemetrySatellite.java b/altoslib/AltosTelemetrySatellite.java index 6897f0e6..60bc4a51 100644 --- a/altoslib/AltosTelemetrySatellite.java +++ b/altoslib/AltosTelemetrySatellite.java @@ -16,16 +16,15 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosTelemetrySatellite extends AltosTelemetryStandard { - int channels; - AltosGPSSat[] sats; + int channels() { return uint8(5); } - public AltosTelemetrySatellite(int[] bytes) { - super(bytes); + AltosGPSSat[] sats() { + int channels = channels(); + AltosGPSSat[] sats = null; - channels = uint8(5); if (channels > 12) channels = 12; if (channels == 0) @@ -38,14 +37,22 @@ public class AltosTelemetrySatellite extends AltosTelemetryStandard { sats[i] = new AltosGPSSat(svid, c_n_1); } } + return sats; } - public void update_state(AltosState state) { - super.update_state(state); + public AltosTelemetrySatellite(int[] bytes) throws AltosCRCException { + super(bytes); + } + + public void provide_data(AltosDataListener listener) { + super.provide_data(listener); + + AltosCalData cal_data = listener.cal_data(); - AltosGPS gps = state.make_temp_gps(true); + AltosGPS gps = cal_data.make_temp_gps(tick(), true); - gps.cc_gps_sat = sats; - state.set_temp_gps(); + gps.cc_gps_sat = sats(); + listener.set_gps(gps); + cal_data.reset_temp_gps(); } } diff --git a/altoslib/AltosTelemetrySensor.java b/altoslib/AltosTelemetrySensor.java index 3c3e6a01..dc8efa9b 100644 --- a/altoslib/AltosTelemetrySensor.java +++ b/altoslib/AltosTelemetrySensor.java @@ -16,66 +16,52 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosTelemetrySensor extends AltosTelemetryStandard { - int state; - int accel; - int pres; - int temp; - int v_batt; - int sense_d; - int sense_m; + int state() { return uint8(5); } + int accel() { return int16(6); } + int pres() { return int16(8); } + int temp() { return int16(10); } + int v_batt() { return int16(12); } + int sense_d() { return int16(14); } + int sense_m() { return int16(16); } - int acceleration; - int speed; - int height; + int acceleration() { return int16(18); } + int speed() { return int16(20); } + int height_16() { return int16(22); } - int ground_accel; - int ground_pres; - int accel_plus_g; - int accel_minus_g; + int ground_accel() { return int16(24); } + int ground_pres() { return int16(26); } + int accel_plus_g() { return int16(28); } + int accel_minus_g() { return int16(30); } - public AltosTelemetrySensor(int[] bytes) { + public AltosTelemetrySensor(int[] bytes) throws AltosCRCException { super(bytes); - state = uint8(5); - - accel = int16(6); - pres = int16(8); - temp = int16(10); - v_batt = int16(12); - sense_d = int16(14); - sense_m = int16(16); + } - acceleration = int16(18); - speed = int16(20); - height = int16(22); + public void provide_data(AltosDataListener listener) { + super.provide_data(listener); - ground_pres = int16(24); - ground_accel = int16(26); - accel_plus_g = int16(28); - accel_minus_g = int16(30); - } + listener.set_state(state()); - public void update_state(AltosState state) { - super.update_state(state); + AltosCalData cal_data = listener.cal_data(); - state.set_state(this.state); - if (type == packet_type_TM_sensor) { - state.set_ground_accel(ground_accel); - state.set_accel_g(accel_plus_g, accel_minus_g); - state.set_accel(accel); + if (type() == packet_type_TM_sensor) { + cal_data.set_ground_accel(ground_accel()); + cal_data.set_accel_plus_minus(accel_plus_g(), accel_minus_g()); + listener.set_acceleration(cal_data.acceleration(accel())); } - state.set_ground_pressure(AltosConvert.barometer_to_pressure(ground_pres)); - state.set_pressure(AltosConvert.barometer_to_pressure(pres)); - state.set_temperature(AltosConvert.thermometer_to_temperature(temp)); - state.set_battery_voltage(AltosConvert.cc_battery_to_voltage(v_batt)); - if (type == packet_type_TM_sensor || type == packet_type_Tm_sensor) { - state.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(sense_d)); - state.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(sense_m)); + cal_data.set_ground_pressure(AltosConvert.barometer_to_pressure(ground_pres())); + listener.set_pressure(AltosConvert.barometer_to_pressure(pres())); + listener.set_temperature(AltosConvert.thermometer_to_temperature(temp())); + listener.set_battery_voltage(AltosConvert.cc_battery_to_voltage(v_batt())); + if (type() == packet_type_TM_sensor || type() == packet_type_Tm_sensor) { + listener.set_apogee_voltage(AltosConvert.cc_igniter_to_voltage(sense_d())); + listener.set_main_voltage(AltosConvert.cc_igniter_to_voltage(sense_m())); } - state.set_kalman(height, speed/16.0, acceleration / 16.0); + listener.set_kalman(height_16(), speed()/16.0, acceleration()/16.0); } } diff --git a/altoslib/AltosTelemetryStandard.java b/altoslib/AltosTelemetryStandard.java index 35d315c7..2a1c9365 100644 --- a/altoslib/AltosTelemetryStandard.java +++ b/altoslib/AltosTelemetryStandard.java @@ -16,12 +16,9 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public abstract class AltosTelemetryStandard extends AltosTelemetry { - int[] bytes; - int type; - public int int8(int off) { return AltosLib.int8(bytes, off + 1); } @@ -50,10 +47,16 @@ public abstract class AltosTelemetryStandard extends AltosTelemetry { return AltosLib.string(bytes, off + 1, l); } - public static AltosTelemetry parse_hex(int[] bytes) { - int type = AltosLib.uint8(bytes, 4 + 1); + public int type() { return uint8(4); } + + public int serial() { return uint16(0); } + + public int tick() { return uint16(2); } + public static AltosTelemetry parse_hex(int[] bytes) throws AltosCRCException { AltosTelemetry telem; + + int type = AltosLib.uint8(bytes, 4+1); switch (type) { case packet_type_TM_sensor: case packet_type_Tm_sensor: @@ -97,15 +100,11 @@ public abstract class AltosTelemetryStandard extends AltosTelemetry { return telem; } - public AltosTelemetryStandard(int[] bytes) { - this.bytes = bytes; - - serial = uint16(0); - tick = uint16(2); - type = uint8(4); + public AltosTelemetryStandard(int[] bytes) throws AltosCRCException { + super(bytes); } - public void update_state(AltosState state) { - super.update_state(state); + public void provide_data(AltosDataListener listener) { + super.provide_data(listener); } } diff --git a/altoslib/AltosTemperature.java b/altoslib/AltosTemperature.java index d63e81d1..efc6d5e1 100644 --- a/altoslib/AltosTemperature.java +++ b/altoslib/AltosTemperature.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosTemperature extends AltosUnits { diff --git a/altoslib/AltosTime.java b/altoslib/AltosTime.java new file mode 100644 index 00000000..5c6ab037 --- /dev/null +++ b/altoslib/AltosTime.java @@ -0,0 +1,33 @@ +/* + * Copyright © 2017 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altoslib_12; + +public class AltosTime extends AltosUnits { + public double value(double v, boolean imperial_units) { return v; } + + public double inverse(double v, boolean imperial_unis) { return v; } + + public String show_units(boolean imperial_units) { return "s"; } + + public String say_units(boolean imperial_units) { return "seconds"; } + + public int show_fraction(int width, boolean imperial_units) { + if (width < 5) + return 0; + return width - 5; + } + + public int say_fraction(boolean imperial_units) { return 0; } +} diff --git a/altoslib/AltosTimeSeries.java b/altoslib/AltosTimeSeries.java new file mode 100644 index 00000000..b3c432fc --- /dev/null +++ b/altoslib/AltosTimeSeries.java @@ -0,0 +1,307 @@ +/* + * Copyright © 2017 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altoslib_12; + +import java.util.*; + +public class AltosTimeSeries implements Iterable, Comparable { + public String label; + public AltosUnits units; + ArrayList values; + + public int compareTo(AltosTimeSeries other) { + return label.compareTo(other.label); + } + + public void add(AltosTimeValue tv) { + values.add(tv); + } + + public void add(double time, double value) { + add(new AltosTimeValue(time, value)); + } + + public AltosTimeValue get(int i) { + return values.get(i); + } + + private double lerp(AltosTimeValue v0, AltosTimeValue v1, double t) { + /* degenerate case */ + if (v0.time == v1.time) + return (v0.value + v1.value) / 2; + + return (v0.value * (v1.time - t) + v1.value * (t - v0.time)) / (v1.time - v0.time); + } + + private int after_index(double time) { + int lo = 0; + int hi = values.size() - 1; + + while (lo <= hi) { + int mid = (lo + hi) / 2; + + if (values.get(mid).time < time) + lo = mid + 1; + else + hi = mid - 1; + } + return lo; + } + + /* Compute a value for an arbitrary time */ + public double value(double time) { + int after = after_index(time); + double ret; + + if (after == 0) + ret = values.get(0).value; + else if (after == values.size()) + ret = values.get(after - 1).value; + else { + AltosTimeValue b = values.get(after-1); + AltosTimeValue a = values.get(after); + ret = lerp(b, a, time); + } + return ret; + } + + /* Find the value just before an arbitrary time */ + public double value_before(double time) { + int after = after_index(time); + + if (after == 0) + return values.get(0).value; + return values.get(after-1).value; + } + + /* Find the value just after an arbitrary time */ + public double value_after(double time) { + int after = after_index(time); + + if (after == values.size()) + return values.get(after-1).value; + return values.get(after).value; + } + + public double time_of(double value) { + double last = AltosLib.MISSING; + for (AltosTimeValue v : values) { + if (v.value >= value) + return v.time; + last = v.time; + } + return last; + } + + public int size() { + return values.size(); + } + + public Iterator iterator() { + return values.iterator(); + } + + public AltosTimeValue max() { + AltosTimeValue max = null; + for (AltosTimeValue tv : values) + if (max == null || tv.value > max.value) + max = tv; + return max; + } + + public AltosTimeValue max(double start_time, double end_time) { + AltosTimeValue max = null; + for (AltosTimeValue tv : values) { + if (start_time <= tv.time && tv.time <= end_time) + if (max == null || tv.value > max.value) + max = tv; + } + return max; + } + + public AltosTimeValue min() { + AltosTimeValue min = null; + for (AltosTimeValue tv : values) { + if (min == null || tv.value < min.value) + min = tv; + } + return min; + } + + public AltosTimeValue min(double start_time, double end_time) { + AltosTimeValue min = null; + for (AltosTimeValue tv : values) { + if (start_time <= tv.time && tv.time <= end_time) + if (min == null || tv.value < min.value) + min = tv; + } + return min; + } + + public AltosTimeValue first() { + return values.get(0); + } + + public AltosTimeValue last() { + return values.get(values.size() - 1); + } + + public double average() { + double total_value = 0; + double total_time = 0; + AltosTimeValue prev = null; + for (AltosTimeValue tv : values) { + if (prev != null) { + total_value += (tv.value + prev.value) / 2 * (tv.time - prev.time); + total_time += (tv.time - prev.time); + } + prev = tv; + } + if (total_time == 0) + return AltosLib.MISSING; + return total_value / total_time; + } + + public double average(double start_time, double end_time) { + double total_value = 0; + double total_time = 0; + AltosTimeValue prev = null; + for (AltosTimeValue tv : values) { + if (start_time <= tv.time && tv.time <= end_time) { + if (prev != null) { + total_value += (tv.value + prev.value) / 2 * (tv.time - start_time); + total_time += (tv.time - start_time); + } + start_time = tv.time; + } + prev = tv; + } + if (total_time == 0) + return AltosLib.MISSING; + return total_value / total_time; + } + + public AltosTimeSeries integrate(AltosTimeSeries integral) { + double value = 0.0; + double pvalue = 0.0; + double time = 0.0; + boolean start = true; + + for (AltosTimeValue v : values) { + if (start) { + value = 0.0; + start = false; + } else { + value += (pvalue + v.value) / 2.0 * (v.time - time); + } + pvalue = v.value; + time = v.time; + integral.add(time, value); + + } + return integral; + } + + public AltosTimeSeries differentiate(AltosTimeSeries diff) { + double value = 0.0; + double time = 0.0; + boolean start = true; + + for (AltosTimeValue v: values) { + if (start) { + value = v.value; + time = v.time; + start = false; + } else { + double dx = v.time - time; + double dy = v.value - value; + + if (dx != 0) + diff.add(time, dy/dx); + + time = v.time; + value = v.value; + } + } + return diff; + } + + private int find_left(int i, double dt) { + int j; + double t = values.get(i).time - dt; + for (j = i; j >= 0; j--) { + if (values.get(j).time < t) + break; + } + return j + 1; + + } + + private int find_right(int i, double dt) { + int j; + double t = values.get(i).time + dt; + for (j = i; j < values.size(); j++) { + if (values.get(j).time > t) + break; + } + return j - 1; + + } + + private double filter_coeff(double dist, double width) { + double ratio = dist / (width / 2); + + return Math.cos(ratio * Math.PI / 2); + } + + public AltosTimeSeries filter(AltosTimeSeries f, double width) { + double half_width = width/2; + for (int i = 0; i < values.size(); i++) { + double center_time = values.get(i).time; + double left_time = center_time - half_width; + double right_time = center_time + half_width; + double total_coeff = 0.0; + double total_value = 0.0; + + int left = find_left(i, half_width); + int right = find_right(i, half_width); + + for (int j = left; j <= right; j++) { + double j_time = values.get(j).time; + + if (left_time <= j_time && j_time <= right_time) { + double j_left = j == left ? left_time : values.get(j-1).time; + double j_right = j == right ? right_time : values.get(j+1).time; + double interval = (j_right - j_left) / 2.0; + double coeff = filter_coeff(j_time - center_time, width) * interval; + double value = values.get(j).value; + double partial = value * coeff; + + total_coeff += coeff; + total_value += partial; + } + } + if (total_coeff != 0.0) + f.add(center_time, total_value / total_coeff); + } + return f; + } + + public AltosTimeSeries(String label, AltosUnits units) { + this.label = label; + this.units = units; + this.values = new ArrayList(); + } +} diff --git a/altoslib/AltosTimeValue.java b/altoslib/AltosTimeValue.java new file mode 100644 index 00000000..298ac7f0 --- /dev/null +++ b/altoslib/AltosTimeValue.java @@ -0,0 +1,28 @@ +/* + * Copyright © 2017 Keith Packard + * + * 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_12; + +public class AltosTimeValue { + public double time; + public double value; + + public AltosTimeValue(double time, double value) { + this.time = time; + this.value = value; + } +} diff --git a/altoslib/AltosUnits.java b/altoslib/AltosUnits.java index 717a106a..e1194487 100644 --- a/altoslib/AltosUnits.java +++ b/altoslib/AltosUnits.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.text.*; @@ -41,6 +41,10 @@ public abstract class AltosUnits { public abstract double inverse(double v, boolean imperial_units); + public String string_value(double v, boolean imperial_units) { + return new Double(value(v, imperial_units)).toString(); + } + public abstract String show_units(boolean imperial_units); public abstract String say_units(boolean imperial_units); @@ -113,6 +117,10 @@ public abstract class AltosUnits { return say_units(v, AltosConvert.imperial_units); } + public String string_value(double v) { + return string_value(v, AltosConvert.imperial_units); + } + /* Parsing functions. Use the first range of the type */ public String parse_units(boolean imperial_units) { return first_range(imperial_units).show_units; diff --git a/altoslib/AltosUnitsListener.java b/altoslib/AltosUnitsListener.java index e094810c..1f06afbf 100644 --- a/altoslib/AltosUnitsListener.java +++ b/altoslib/AltosUnitsListener.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public interface AltosUnitsListener { public void units_changed(boolean imperial_units); diff --git a/altoslib/AltosUnitsRange.java b/altoslib/AltosUnitsRange.java index 9f56001d..6bf0d91f 100644 --- a/altoslib/AltosUnitsRange.java +++ b/altoslib/AltosUnitsRange.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import java.text.*; diff --git a/altoslib/AltosUnknownProduct.java b/altoslib/AltosUnknownProduct.java index 114abc76..e4bebcd4 100644 --- a/altoslib/AltosUnknownProduct.java +++ b/altoslib/AltosUnknownProduct.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosUnknownProduct extends Exception { public String product; diff --git a/altoslib/AltosVersion.java.in b/altoslib/AltosVersion.java.in index a48c532b..c8399f2e 100644 --- a/altoslib/AltosVersion.java.in +++ b/altoslib/AltosVersion.java.in @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosVersion { public final static String version = "@VERSION@"; diff --git a/altoslib/AltosVoltage.java b/altoslib/AltosVoltage.java index 8031c805..ef53ac11 100644 --- a/altoslib/AltosVoltage.java +++ b/altoslib/AltosVoltage.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public class AltosVoltage extends AltosUnits { diff --git a/altoslib/AltosWriter.java b/altoslib/AltosWriter.java index 691dc4de..c77e48b0 100644 --- a/altoslib/AltosWriter.java +++ b/altoslib/AltosWriter.java @@ -16,11 +16,11 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; public interface AltosWriter { - public void write(AltosStateIterable states); + public void write(AltosFlightSeries series); public void close(); } diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index b93d1f88..11b5d562 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -26,6 +26,7 @@ record_files = \ altoslib_JAVA = \ AltosLib.java \ + AltosCalData.java \ AltosCompanion.java \ AltosConfigData.java \ AltosConfigDataException.java \ @@ -34,7 +35,8 @@ altoslib_JAVA = \ AltosCRCException.java \ AltosCSV.java \ AltosDebug.java \ - AltosEepromNew.java \ + AltosEeprom.java \ + AltosRecordSet.java \ AltosEepromRecord.java \ AltosEepromRecordFull.java \ AltosEepromRecordTiny.java \ @@ -44,7 +46,6 @@ altoslib_JAVA = \ AltosEepromRecordGps.java \ AltosEepromRecordFireTwo.java \ AltosEepromRecordSet.java \ - AltosEeprom.java \ AltosEepromChunk.java \ AltosEepromDownload.java \ AltosEepromMonitor.java \ @@ -54,11 +55,15 @@ altoslib_JAVA = \ AltosFile.java \ AltosFlash.java \ AltosFlashListener.java \ + AltosDataListener.java \ + AltosDataProvider.java \ + AltosFlightSeries.java \ AltosFlightReader.java \ AltosFlightStats.java \ AltosForce.java \ AltosFrequency.java \ AltosGPS.java \ + AltosGPSTimeValue.java \ AltosGPSSat.java \ AltosGreatCircle.java \ AltosHexfile.java \ @@ -82,9 +87,11 @@ altoslib_JAVA = \ AltosOrient.java \ AltosParse.java \ AltosPressure.java \ + AltosPresTemp.java \ AltosPreferences.java \ AltosPreferencesBackend.java \ AltosProgrammer.java \ + AltosPyroName.java \ AltosReplayReader.java \ AltosRomconfig.java \ AltosSavedState.java \ @@ -98,8 +105,8 @@ altoslib_JAVA = \ AltosSensorMetrum.java \ AltosSensorTGPS.java \ AltosState.java \ - AltosStateIterable.java \ - AltosStateUpdate.java \ + AltosStateName.java \ + AltosStringInputStream.java \ AltosTelemetry.java \ AltosTelemetryConfiguration.java \ AltosTelemetryCompanion.java \ @@ -119,6 +126,9 @@ altoslib_JAVA = \ AltosTelemetrySensor.java \ AltosTelemetrySatellite.java \ AltosTelemetryStandard.java \ + AltosTime.java \ + AltosTimeSeries.java \ + AltosTimeValue.java \ AltosUnitsListener.java \ AltosUnknownProduct.java \ AltosMs5607.java \ @@ -135,6 +145,7 @@ altoslib_JAVA = \ AltosLocation.java \ AltosLatitude.java \ AltosLongitude.java \ + AltosRotationRate.java \ AltosPyro.java \ AltosWriter.java \ AltosQuaternion.java \ diff --git a/altosui/Altos.java b/altosui/Altos.java index c2cf4090..9f176c4b 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -21,8 +21,8 @@ package altosui; import java.awt.*; import libaltosJNI.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class Altos extends AltosUILib { diff --git a/altosui/AltosAscent.java b/altosui/AltosAscent.java index a4f475cb..ab052e5f 100644 --- a/altosui/AltosAscent.java +++ b/altosui/AltosAscent.java @@ -22,8 +22,8 @@ import java.util.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class AltosAscent extends AltosUIFlightTab { JLabel cur, max; diff --git a/altosui/AltosCompanionInfo.java b/altosui/AltosCompanionInfo.java index 52815d6f..95e1d2d9 100644 --- a/altosui/AltosCompanionInfo.java +++ b/altosui/AltosCompanionInfo.java @@ -20,8 +20,8 @@ package altosui; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class AltosCompanionInfo extends JTable implements AltosFlightDisplay { private AltosFlightInfoTableModel model; diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index 07802247..bf2b8166 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -23,8 +23,8 @@ import javax.swing.*; import java.io.*; import java.util.concurrent.*; import java.text.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class AltosConfig implements ActionListener { diff --git a/altosui/AltosConfigPyroUI.java b/altosui/AltosConfigPyroUI.java index 2d4b216c..5016ea63 100644 --- a/altosui/AltosConfigPyroUI.java +++ b/altosui/AltosConfigPyroUI.java @@ -23,8 +23,8 @@ import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class AltosConfigPyroUI extends AltosUIDialog diff --git a/altosui/AltosConfigTD.java b/altosui/AltosConfigTD.java index 621db3c0..9fedc56d 100644 --- a/altosui/AltosConfigTD.java +++ b/altosui/AltosConfigTD.java @@ -22,8 +22,8 @@ import java.awt.event.*; import javax.swing.*; import java.io.*; import java.util.concurrent.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class AltosConfigTD implements ActionListener { diff --git a/altosui/AltosConfigTDUI.java b/altosui/AltosConfigTDUI.java index 529c2fa2..3ff56218 100644 --- a/altosui/AltosConfigTDUI.java +++ b/altosui/AltosConfigTDUI.java @@ -22,8 +22,8 @@ import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class AltosConfigTDUI extends AltosUIDialog diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java index e5f1949a..270131b8 100644 --- a/altosui/AltosConfigUI.java +++ b/altosui/AltosConfigUI.java @@ -23,8 +23,8 @@ import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import java.text.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class AltosConfigUI extends AltosUIDialog @@ -193,46 +193,46 @@ public class AltosConfigUI } void set_radio_enable_tool_tip() { - if (radio_enable_value.isEnabled()) + if (radio_enable_value.isVisible()) radio_enable_value.setToolTipText("Enable/Disable telemetry and RDF transmissions"); else radio_enable_value.setToolTipText("Firmware version does not support disabling radio"); } void set_rate_tool_tip() { - if (rate_value.isEnabled()) + if (rate_value.isVisible()) rate_value.setToolTipText("Select telemetry baud rate"); else rate_value.setToolTipText("Firmware version does not support variable telemetry rates"); } void set_aprs_interval_tool_tip() { - if (aprs_interval_value.isEnabled()) + if (aprs_interval_value.isVisible()) aprs_interval_value.setToolTipText("Enable APRS and set the interval between APRS reports"); else aprs_interval_value.setToolTipText("Hardware doesn't support APRS"); } void set_aprs_ssid_tool_tip() { - if (aprs_ssid_value.isEnabled()) + if (aprs_ssid_value.isVisible()) aprs_ssid_value.setToolTipText("Set the APRS SSID (secondary station identifier)"); - else if (aprs_ssid_value.isEnabled()) + else if (aprs_ssid_value.isVisible()) aprs_ssid_value.setToolTipText("Software version doesn't support setting the APRS SSID"); else aprs_ssid_value.setToolTipText("Hardware doesn't support APRS"); } void set_aprs_format_tool_tip() { - if (aprs_format_value.isEnabled()) + if (aprs_format_value.isVisible()) aprs_format_value.setToolTipText("Set the APRS format (compressed/uncompressed)"); - else if (aprs_format_value.isEnabled()) + else if (aprs_format_value.isVisible()) aprs_format_value.setToolTipText("Software version doesn't support setting the APRS format"); else aprs_format_value.setToolTipText("Hardware doesn't support APRS"); } void set_flight_log_max_tool_tip() { - if (flight_log_max_value.isEnabled()) + if (flight_log_max_value.isVisible()) flight_log_max_value.setToolTipText("Size reserved for each flight log (in kB)"); else { if (is_telemini_v1()) @@ -243,14 +243,14 @@ public class AltosConfigUI } void set_ignite_mode_tool_tip() { - if (ignite_mode_value.isEnabled()) + if (ignite_mode_value.isVisible()) ignite_mode_value.setToolTipText("Select when igniters will be fired"); else ignite_mode_value.setToolTipText("Older firmware could not select ignite mode"); } void set_pad_orientation_tool_tip() { - if (pad_orientation_value.isEnabled()) + if (pad_orientation_value.isVisible()) pad_orientation_value.setToolTipText("How will the computer be mounted in the airframe"); else { if (is_telemetrum()) @@ -263,7 +263,7 @@ public class AltosConfigUI } void set_beep_tool_tip() { - if (beep_value.isEnabled()) + if (beep_value.isVisible()) beep_value.setToolTipText("What frequency the beeper will sound at"); else beep_value.setToolTipText("Older firmware could not select beeper frequency"); @@ -959,12 +959,10 @@ public class AltosConfigUI } public void set_main_deploy(int new_main_deploy) { - main_deploy_value.setSelectedItem(AltosConvert.height.say(new_main_deploy)); - main_deploy_value.setEnabled(new_main_deploy >= 0); - - main_deploy_value.setVisible(new_main_deploy >= 0); - main_deploy_label.setVisible(new_main_deploy >= 0); - + if (new_main_deploy != AltosLib.MISSING) + main_deploy_value.setSelectedItem(AltosConvert.height.say(new_main_deploy)); + main_deploy_value.setVisible(new_main_deploy != AltosLib.MISSING); + main_deploy_label.setVisible(new_main_deploy != AltosLib.MISSING); } public int main_deploy() throws AltosConfigDataException { @@ -1008,7 +1006,7 @@ public class AltosConfigUI } catch (ParseException pe) { } - if (tracker_motion_value.isEnabled()) { + if (tracker_motion_value.isVisible()) { String motion = tracker_motion_value.getSelectedItem().toString(); tracker_motion_label.setText(get_tracker_motion_label()); set_tracker_motion_values(); @@ -1024,11 +1022,10 @@ public class AltosConfigUI } public void set_apogee_delay(int new_apogee_delay) { - apogee_delay_value.setVisible(new_apogee_delay >= 0); - apogee_delay_label.setVisible(new_apogee_delay >= 0); - - apogee_delay_value.setSelectedItem(Integer.toString(new_apogee_delay)); - apogee_delay_value.setEnabled(new_apogee_delay >= 0); + if (new_apogee_delay != AltosLib.MISSING) + apogee_delay_value.setSelectedItem(Integer.toString(new_apogee_delay)); + apogee_delay_value.setVisible(new_apogee_delay != AltosLib.MISSING); + apogee_delay_label.setVisible(new_apogee_delay != AltosLib.MISSING); } private int parse_int(String name, String s, boolean split) throws AltosConfigDataException { @@ -1047,11 +1044,11 @@ public class AltosConfigUI } public void set_apogee_lockout(int new_apogee_lockout) { - apogee_lockout_value.setSelectedItem(Integer.toString(new_apogee_lockout)); - apogee_lockout_value.setEnabled(new_apogee_lockout >= 0); + if (new_apogee_lockout != AltosLib.MISSING) + apogee_lockout_value.setSelectedItem(Integer.toString(new_apogee_lockout)); - apogee_lockout_value.setVisible(new_apogee_lockout >= 0); - apogee_lockout_label.setVisible(new_apogee_lockout >= 0); + apogee_lockout_value.setVisible(new_apogee_lockout != AltosLib.MISSING); + apogee_lockout_label.setVisible(new_apogee_lockout != AltosLib.MISSING); } public int apogee_lockout() throws AltosConfigDataException { @@ -1059,8 +1056,10 @@ public class AltosConfigUI } public void set_radio_frequency(double new_radio_frequency) { - radio_frequency_label.setVisible(new_radio_frequency >= 0); - radio_frequency_value.set_frequency(new_radio_frequency); + if (new_radio_frequency != AltosLib.MISSING) + radio_frequency_value.set_frequency(new_radio_frequency); + radio_frequency_label.setVisible(new_radio_frequency != AltosLib.MISSING); + radio_frequency_value.setVisible(new_radio_frequency != AltosLib.MISSING); } public double radio_frequency() { @@ -1068,40 +1067,33 @@ public class AltosConfigUI } public void set_radio_calibration(int new_radio_calibration) { - radio_calibration_value.setVisible(new_radio_calibration >= 0); - radio_calibration_label.setVisible(new_radio_calibration >= 0); - - if (new_radio_calibration < 0) - radio_calibration_value.setText("Disabled"); - else + if (new_radio_calibration != AltosLib.MISSING) radio_calibration_value.setText(String.format("%d", new_radio_calibration)); + radio_calibration_value.setVisible(new_radio_calibration != AltosLib.MISSING); + radio_calibration_label.setVisible(new_radio_calibration != AltosLib.MISSING); } public void set_radio_enable(int new_radio_enable) { - radio_enable_label.setVisible(new_radio_enable >= 0); - radio_enable_value.setVisible(new_radio_enable >= 0); - - if (new_radio_enable >= 0) { - radio_enable_value.setSelected(new_radio_enable > 0); - radio_enable_value.setEnabled(true); - } else { - radio_enable_value.setSelected(true); - radio_enable_value.setEnabled(false); - } + if (new_radio_enable != AltosLib.MISSING) + radio_enable_value.setSelected(new_radio_enable != 0); + radio_enable_label.setVisible(new_radio_enable != AltosLib.MISSING); + radio_enable_value.setVisible(new_radio_enable != AltosLib.MISSING); set_radio_enable_tool_tip(); } public int radio_enable() { - if (radio_enable_value.isEnabled()) + if (radio_enable_value.isVisible()) return radio_enable_value.isSelected() ? 1 : 0; else - return -1; + return AltosLib.MISSING; } public void set_telemetry_rate(int new_rate) { - rate_label.setVisible(new_rate >= 0); - - rate_value.set_rate(new_rate); + if (new_rate != AltosLib.MISSING) + rate_value.set_rate(new_rate); + rate_label.setVisible(new_rate != AltosLib.MISSING); + rate_value.setVisible(new_rate != AltosLib.MISSING); + set_rate_tool_tip(); } public int telemetry_rate() { @@ -1109,14 +1101,16 @@ public class AltosConfigUI } public void set_callsign(String new_callsign) { + if (new_callsign != null) + callsign_value.setText(new_callsign); callsign_value.setVisible(new_callsign != null); callsign_label.setVisible(new_callsign != null); - - callsign_value.setText(new_callsign); } public String callsign() { - return callsign_value.getText(); + if (callsign_value.isVisible()) + return callsign_value.getText(); + return null; } int flight_log_max_limit; @@ -1133,11 +1127,12 @@ public class AltosConfigUI } public void set_flight_log_max(int new_flight_log_max) { - flight_log_max_value.setVisible(new_flight_log_max >= 0); - flight_log_max_label.setVisible(new_flight_log_max >= 0); - - flight_log_max_value.setSelectedItem(flight_log_max_label(new_flight_log_max)); - flight_log_max = new_flight_log_max; + if (new_flight_log_max != AltosLib.MISSING) { + flight_log_max_value.setSelectedItem(flight_log_max_label(new_flight_log_max)); + flight_log_max = new_flight_log_max; + } + flight_log_max_value.setVisible(new_flight_log_max != AltosLib.MISSING); + flight_log_max_label.setVisible(new_flight_log_max != AltosLib.MISSING); set_flight_log_max_tool_tip(); } @@ -1147,84 +1142,92 @@ public class AltosConfigUI } public int flight_log_max() throws AltosConfigDataException { - return parse_int("flight log max", flight_log_max_value.getSelectedItem().toString(), true); + if (flight_log_max_value.isVisible()) + return parse_int("flight log max", flight_log_max_value.getSelectedItem().toString(), true); + return AltosLib.MISSING; } public void set_flight_log_max_limit(int new_flight_log_max_limit) { flight_log_max_limit = new_flight_log_max_limit; - flight_log_max_value.removeAllItems(); - for (int i = 8; i >= 1; i--) { - int size = flight_log_max_limit / i; - flight_log_max_value.addItem(String.format("%d (%d flights)", size, i)); + if (new_flight_log_max_limit != AltosLib.MISSING) { + flight_log_max_value.removeAllItems(); + for (int i = 8; i >= 1; i--) { + int size = flight_log_max_limit / i; + flight_log_max_value.addItem(String.format("%d (%d flights)", size, i)); + } } if (flight_log_max != 0) set_flight_log_max(flight_log_max); } public void set_ignite_mode(int new_ignite_mode) { - ignite_mode_value.setVisible(new_ignite_mode >= 0); - ignite_mode_label.setVisible(new_ignite_mode >= 0); - - if (new_ignite_mode >= ignite_mode_values.length) - new_ignite_mode = 0; - if (new_ignite_mode < 0) { - ignite_mode_value.setEnabled(false); - new_ignite_mode = 0; - } else { - ignite_mode_value.setEnabled(true); + if (new_ignite_mode != AltosLib.MISSING) { + if (new_ignite_mode >= ignite_mode_values.length) + new_ignite_mode = 0; + if (new_ignite_mode < 0) { + ignite_mode_value.setEnabled(false); + new_ignite_mode = 0; + } else { + ignite_mode_value.setEnabled(true); + } + ignite_mode_value.setSelectedIndex(new_ignite_mode); } - ignite_mode_value.setSelectedIndex(new_ignite_mode); + ignite_mode_value.setVisible(new_ignite_mode != AltosLib.MISSING); + ignite_mode_label.setVisible(new_ignite_mode != AltosLib.MISSING); + set_ignite_mode_tool_tip(); } public int ignite_mode() { - if (ignite_mode_value.isEnabled()) + if (ignite_mode_value.isVisible()) return ignite_mode_value.getSelectedIndex(); else - return -1; + return AltosLib.MISSING; } public void set_pad_orientation(int new_pad_orientation) { - pad_orientation_value.setVisible(new_pad_orientation >= 0); - pad_orientation_label.setVisible(new_pad_orientation >= 0); - - if (new_pad_orientation >= pad_orientation_values.length) - new_pad_orientation = 0; - if (new_pad_orientation < 0) - new_pad_orientation = 0; - pad_orientation_value.setSelectedIndex(new_pad_orientation); + if (new_pad_orientation != AltosLib.MISSING) { + if (new_pad_orientation >= pad_orientation_values.length) + new_pad_orientation = 0; + if (new_pad_orientation < 0) + new_pad_orientation = 0; + pad_orientation_value.setSelectedIndex(new_pad_orientation); + } + pad_orientation_value.setVisible(new_pad_orientation != AltosLib.MISSING); + pad_orientation_label.setVisible(new_pad_orientation != AltosLib.MISSING); + set_pad_orientation_tool_tip(); } public int pad_orientation() { - if (pad_orientation_value.isEnabled()) + if (pad_orientation_value.isVisible()) return pad_orientation_value.getSelectedIndex(); else - return -1; + return AltosLib.MISSING; } public void set_beep(int new_beep) { - beep_value.setVisible(new_beep >= 0); - beep_label.setVisible(new_beep >= 0); - - int new_freq = (int) Math.floor (AltosConvert.beep_value_to_freq(new_beep) + 0.5); - for (int i = 0; i < beep_values.length; i++) - if (new_beep == AltosConvert.beep_freq_to_value(Integer.parseInt(beep_values[i]))) { - beep_value.setSelectedIndex(i); - set_beep_tool_tip(); - return; - } - beep_value.setSelectedItem(String.format("%d", new_freq)); - beep_value.setEnabled(new_beep >= 0); + if (new_beep != AltosLib.MISSING) { + int new_freq = (int) Math.floor (AltosConvert.beep_value_to_freq(new_beep) + 0.5); + for (int i = 0; i < beep_values.length; i++) + if (new_beep == AltosConvert.beep_freq_to_value(Integer.parseInt(beep_values[i]))) { + beep_value.setSelectedIndex(i); + set_beep_tool_tip(); + return; + } + beep_value.setSelectedItem(String.format("%d", new_freq)); + } + beep_value.setVisible(new_beep != AltosLib.MISSING); + beep_label.setVisible(new_beep != AltosLib.MISSING); set_beep_tool_tip(); } public int beep() { - if (beep_value.isEnabled()) + if (beep_value.isVisible()) return AltosConvert.beep_freq_to_value(Integer.parseInt(beep_value.getSelectedItem().toString())); else - return -1; + return AltosLib.MISSING; } String[] tracker_motion_values() { @@ -1248,58 +1251,53 @@ public class AltosConfigUI } void set_tracker_tool_tip() { - if (tracker_motion_value.isEnabled()) + if (tracker_motion_value.isVisible()) tracker_motion_value.setToolTipText("How far the device must move before logging"); else tracker_motion_value.setToolTipText("This device doesn't disable logging when stationary"); - if (tracker_interval_value.isEnabled()) + if (tracker_interval_value.isVisible()) tracker_interval_value.setToolTipText("How often to report GPS position"); else tracker_interval_value.setToolTipText("This device can't configure interval"); } public void set_tracker_motion(int tracker_motion) { - tracker_motion_label.setVisible(tracker_motion >= 0); - tracker_motion_value.setVisible(tracker_motion >= 0); - - if (tracker_motion < 0) { - tracker_motion_value.setEnabled(false); - } else { - tracker_motion_value.setEnabled(true); + if (tracker_motion != AltosLib.MISSING) tracker_motion_value.setSelectedItem(AltosConvert.height.say(tracker_motion)); - } + tracker_motion_label.setVisible(tracker_motion != AltosLib.MISSING); + tracker_motion_value.setVisible(tracker_motion != AltosLib.MISSING); } public int tracker_motion() throws AltosConfigDataException { - String str = tracker_motion_value.getSelectedItem().toString(); - try { - return (int) (AltosConvert.height.parse_locale(str) + 0.5); - } catch (ParseException pe) { - throw new AltosConfigDataException("invalid tracker motion %s", str); + if (tracker_motion_value.isVisible()) { + String str = tracker_motion_value.getSelectedItem().toString(); + try { + return (int) (AltosConvert.height.parse_locale(str) + 0.5); + } catch (ParseException pe) { + throw new AltosConfigDataException("invalid tracker motion %s", str); + } } + return AltosLib.MISSING; } public void set_tracker_interval(int tracker_interval) { - tracker_interval_label.setVisible(tracker_interval >= 0); - tracker_interval_value.setVisible(tracker_interval >= 0); - - if (tracker_interval< 0) { - tracker_interval_value.setEnabled(false); - } else { - tracker_interval_value.setEnabled(true); + if (tracker_interval != AltosLib.MISSING) tracker_interval_value.setSelectedItem(String.format("%d", tracker_interval)); - } + tracker_interval_label.setVisible(tracker_interval != AltosLib.MISSING); + tracker_interval_value.setVisible(tracker_interval != AltosLib.MISSING); } public int tracker_interval() throws AltosConfigDataException { - return parse_int ("tracker interval", tracker_interval_value.getSelectedItem().toString(), false); + if (tracker_interval_value.isVisible()) + return parse_int ("tracker interval", tracker_interval_value.getSelectedItem().toString(), false); + return AltosLib.MISSING; } public void set_pyros(AltosPyro[] new_pyros) { pyros = new_pyros; - pyro.setVisible(pyros != null); if (pyros != null && pyro_ui != null) pyro_ui.set_pyros(pyros); + pyro.setVisible(pyros != null); } public AltosPyro[] pyros() throws AltosConfigDataException { @@ -1310,9 +1308,9 @@ public class AltosConfigUI public void set_pyro_firing_time(double new_pyro_firing_time) { pyro_firing_time = new_pyro_firing_time; - pyro.setVisible(pyro_firing_time >= 0); - if (pyro_firing_time >= 0 && pyro_ui != null) + if (pyro_firing_time != AltosLib.MISSING && pyro_ui != null) pyro_ui.set_pyro_firing_time(pyro_firing_time); + pyro.setVisible(pyro_firing_time != AltosLib.MISSING); } public double pyro_firing_time() throws AltosConfigDataException { @@ -1322,49 +1320,49 @@ public class AltosConfigUI } public void set_aprs_interval(int new_aprs_interval) { - aprs_interval_value.setVisible(new_aprs_interval >= 0); - aprs_interval_label.setVisible(new_aprs_interval >= 0); - - String s; - - if (new_aprs_interval <= 0) - s = "Disabled"; - else - s = Integer.toString(new_aprs_interval); - aprs_interval_value.setSelectedItem(s); + if (new_aprs_interval != AltosLib.MISSING) + aprs_interval_value.setSelectedItem(Integer.toString(new_aprs_interval)); + aprs_interval_value.setVisible(new_aprs_interval != AltosLib.MISSING); + aprs_interval_label.setVisible(new_aprs_interval != AltosLib.MISSING); set_aprs_interval_tool_tip(); } public int aprs_interval() throws AltosConfigDataException { - String s = aprs_interval_value.getSelectedItem().toString(); + if (aprs_interval_value.isVisible()) { + String s = aprs_interval_value.getSelectedItem().toString(); - if (s.equals("Disabled")) - return 0; - return parse_int("aprs interval", s, false); + return parse_int("aprs interval", s, false); + } + return AltosLib.MISSING; } public void set_aprs_ssid(int new_aprs_ssid) { - aprs_ssid_value.setVisible(new_aprs_ssid >= 0); - aprs_ssid_label.setVisible(new_aprs_ssid >= 0); - - aprs_ssid_value.setSelectedItem(Math.max(0,new_aprs_ssid)); + if (new_aprs_ssid != AltosLib.MISSING) + aprs_ssid_value.setSelectedItem(new_aprs_ssid); + aprs_ssid_value.setVisible(new_aprs_ssid != AltosLib.MISSING); + aprs_ssid_label.setVisible(new_aprs_ssid != AltosLib.MISSING); set_aprs_ssid_tool_tip(); } public int aprs_ssid() throws AltosConfigDataException { - Integer i = (Integer) aprs_ssid_value.getSelectedItem(); - return i; + if (aprs_ssid_value.isVisible()) { + Integer i = (Integer) aprs_ssid_value.getSelectedItem(); + return i; + } + return AltosLib.MISSING; } public void set_aprs_format(int new_aprs_format) { - aprs_format_value.setVisible(new_aprs_format >= 0); - aprs_format_label.setVisible(new_aprs_format >= 0); - - aprs_format_value.setSelectedIndex(Math.max(0,new_aprs_format)); + if (new_aprs_format != AltosLib.MISSING) + aprs_format_value.setSelectedIndex(new_aprs_format); + aprs_format_value.setVisible(new_aprs_format != AltosLib.MISSING); + aprs_format_label.setVisible(new_aprs_format != AltosLib.MISSING); set_aprs_format_tool_tip(); } public int aprs_format() throws AltosConfigDataException { - return aprs_format_value.getSelectedIndex(); + if (aprs_format_value.isVisible()) + return aprs_format_value.getSelectedIndex(); + return AltosLib.MISSING; } } diff --git a/altosui/AltosConfigureUI.java b/altosui/AltosConfigureUI.java index 6aefb3a6..acafc659 100644 --- a/altosui/AltosConfigureUI.java +++ b/altosui/AltosConfigureUI.java @@ -23,7 +23,7 @@ import java.awt.event.*; import java.beans.*; import javax.swing.*; import javax.swing.event.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altosuilib_12.*; public class AltosConfigureUI extends AltosUIConfigure diff --git a/altosui/AltosDescent.java b/altosui/AltosDescent.java index 0c3a8e9e..2cc65b08 100644 --- a/altosui/AltosDescent.java +++ b/altosui/AltosDescent.java @@ -22,8 +22,8 @@ import java.util.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class AltosDescent extends AltosUIFlightTab { diff --git a/altosui/AltosFlightStatus.java b/altosui/AltosFlightStatus.java index 4288fc9f..a5e5a4ef 100644 --- a/altosui/AltosFlightStatus.java +++ b/altosui/AltosFlightStatus.java @@ -20,8 +20,8 @@ package altosui; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class AltosFlightStatus extends JComponent implements AltosFlightDisplay { GridBagLayout layout; @@ -93,14 +93,14 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay } void show(AltosState state, AltosListenerState listener_state) { - if (!same_call(state.callsign)) { + if (!same_call(state.cal_data().callsign)) { show(); - value.setText(state.callsign); - if (state.callsign == null) + value.setText(state.cal_data().callsign); + if (state.cal_data().callsign == null) setVisible(false); else setVisible(true); - last_call = state.callsign; + last_call = state.cal_data().callsign; } } @@ -120,13 +120,14 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay int last_serial = -1; void show(AltosState state, AltosListenerState listener_state) { - if (state.serial != last_serial) { + AltosCalData cal_data = state.cal_data(); + if (cal_data.serial != last_serial) { show(); - if (state.serial == AltosLib.MISSING) + if (cal_data.serial == AltosLib.MISSING) value.setText("none"); else - value.setText(String.format("%d", state.serial)); - last_serial = state.serial; + value.setText(String.format("%d", cal_data.serial)); + last_serial = cal_data.serial; } } @@ -147,13 +148,14 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay int last_flight = -1; void show(AltosState state, AltosListenerState listener_state) { - if (state.flight != last_flight) { + AltosCalData cal_data = state.cal_data(); + if (cal_data.flight != last_flight) { show(); - if (state.flight == AltosLib.MISSING) + if (cal_data.flight == AltosLib.MISSING) value.setText("none"); else - value.setText(String.format("%d", state.flight)); - last_flight = state.flight; + value.setText(String.format("%d", cal_data.flight)); + last_flight = cal_data.flight; } } diff --git a/altosui/AltosFlightStatusTableModel.java b/altosui/AltosFlightStatusTableModel.java index 7b872df9..9c4e1bee 100644 --- a/altosui/AltosFlightStatusTableModel.java +++ b/altosui/AltosFlightStatusTableModel.java @@ -28,7 +28,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class AltosFlightStatusTableModel extends AbstractTableModel { private String[] columnNames = { diff --git a/altosui/AltosFlightStatusUpdate.java b/altosui/AltosFlightStatusUpdate.java index 82ef43c2..b8b0d38a 100644 --- a/altosui/AltosFlightStatusUpdate.java +++ b/altosui/AltosFlightStatusUpdate.java @@ -19,7 +19,7 @@ package altosui; import java.awt.event.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class AltosFlightStatusUpdate implements ActionListener { diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index cf03d2dc..44e995be 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -23,8 +23,8 @@ import java.awt.event.*; import javax.swing.*; import java.util.*; import java.util.concurrent.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay { AltosVoice voice; @@ -36,7 +36,7 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay { JTabbedPane pane; AltosPad pad; - AltosIgnitor ignitor; + AltosIgnitor igniter; AltosAscent ascent; AltosDescent descent; AltosLanded landed; @@ -45,7 +45,7 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay { boolean has_map; boolean has_companion; boolean has_state; - boolean has_ignitor; + boolean has_igniter; private AltosFlightStatus flightStatus; private AltosInfoTable flightInfo; @@ -101,7 +101,7 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay { status_update.saved_listener_state = listener_state; if (state == null) - state = new AltosState(); + state = new AltosState(new AltosCalData()); if (state.state() != Altos.ao_flight_startup) { if (!has_state) { @@ -115,21 +115,20 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay { JComponent tab = which_tab(state); if (tab != cur_tab) { - if (cur_tab == pane.getSelectedComponent()) { + if (cur_tab == pane.getSelectedComponent()) pane.setSelectedComponent(tab); - } cur_tab = tab; } - if (ignitor.should_show(state)) { - if (!has_ignitor) { - pane.add("Ignitor", ignitor); - has_ignitor = true; + if (igniter.should_show(state)) { + if (!has_igniter) { + pane.add("Ignitor", igniter); + has_igniter = true; } } else { - if (has_ignitor) { - pane.remove(ignitor); - has_ignitor = false; + if (has_igniter) { + pane.remove(igniter); + has_igniter = false; } } @@ -145,7 +144,7 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay { } } - if (state.gps != null && state.gps.connected) { + if (state.gps != null) { if (!has_map) { pane.add("Site Map", sitemap); has_map = true; @@ -272,8 +271,8 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay { displays.add(pad); pane.add("Status", pad); - ignitor = new AltosIgnitor(); - displays.add(ignitor); + igniter = new AltosIgnitor(); + displays.add(igniter); ascent = new AltosAscent(); displays.add(ascent); descent = new AltosDescent(); diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java index 4ca2b77c..f6c906c6 100644 --- a/altosui/AltosGraphUI.java +++ b/altosui/AltosGraphUI.java @@ -24,8 +24,8 @@ import java.util.ArrayList; import java.awt.*; import java.awt.event.*; import javax.swing.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; @@ -37,22 +37,35 @@ public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, Alt AltosGraph graph; AltosUIEnable enable; AltosUIMap map; - AltosState state; - AltosGraphDataSet graphDataSet; AltosFlightStats stats; AltosFlightStatsTable statsTable; + AltosGPS gps; boolean has_gps; - void fill_map(AltosStateIterable states) { - boolean any_gps = false; - for (AltosState state : states) { - if (state.gps != null && state.gps.locked && state.gps.nsat >= 4) { - if (map == null) - map = new AltosUIMap(); - map.show(state, null); - has_gps = true; + void fill_map(AltosFlightSeries flight_series) { + boolean any_gps = false; + AltosGPSTimeValue gtv_last = null; + + if (flight_series.gps_series != null) { + for (AltosGPSTimeValue gtv : flight_series.gps_series) { + gtv_last = gtv; + AltosGPS gps = gtv.gps; + if (gps != null && + gps.locked && + gps.nsat >= 4) { + if (map == null) + map = new AltosUIMap(); + map.show(gps, (int) flight_series.value_before(AltosFlightSeries.state_name, gtv.time)); + this.gps = gps; + has_gps = true; + } } } + if (gtv_last != null) { + int state = (int) flight_series.value_after(AltosFlightSeries.state_name, gtv_last.time); + if (state == AltosLib.ao_flight_landed) + map.show(gtv_last.gps, state); + } } public void font_size_changed(int font_size) { @@ -69,18 +82,24 @@ public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, Alt enable.units_changed(imperial_units); } - AltosGraphUI(AltosStateIterable states, File file) throws InterruptedException, IOException { + AltosGraphUI(AltosRecordSet set, File file) throws InterruptedException, IOException { super(file.getName()); - state = null; + AltosCalData cal_data = set.cal_data(); + pane = new JTabbedPane(); enable = new AltosUIEnable(); - stats = new AltosFlightStats(states); - graphDataSet = new AltosGraphDataSet(states); + AltosUIFlightSeries flight_series = new AltosUIFlightSeries(cal_data); + + set.capture_series(flight_series); + + flight_series.finish(); + + stats = new AltosFlightStats(flight_series); - graph = new AltosGraph(enable, stats, graphDataSet); + graph = new AltosGraph(enable, stats, flight_series); statsTable = new AltosFlightStatsTable(stats); @@ -89,7 +108,7 @@ public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, Alt pane.add("Flight Statistics", statsTable); has_gps = false; - fill_map(states); + fill_map(flight_series); if (has_gps) pane.add("Map", map); @@ -108,7 +127,7 @@ public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, Alt pack(); setVisible(true); - if (state != null && has_gps) - map.centre(state); + if (gps != null) + map.centre(gps); } } diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java index 4d5c3b2d..a2696f15 100644 --- a/altosui/AltosIdleMonitorUI.java +++ b/altosui/AltosIdleMonitorUI.java @@ -25,8 +25,8 @@ import javax.swing.event.*; import java.io.*; import java.util.concurrent.*; import java.util.Arrays; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDisplay, AltosIdleMonitorListener, DocumentListener { AltosDevice device; @@ -34,12 +34,12 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl AltosPad pad; AltosInfoTable flightInfo; AltosFlightStatus flightStatus; - AltosIgnitor ignitor; + AltosIgnitor igniter; AltosIdleMonitor thread; AltosUIMap sitemap; int serial; boolean remote; - boolean has_ignitor; + boolean has_igniter; boolean has_map; void stop_display() { @@ -75,15 +75,15 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl public void show(AltosState state, AltosListenerState listener_state) { status_update.saved_state = state; - if (ignitor.should_show(state)) { - if (!has_ignitor) { - pane.add("Ignitor", ignitor); - has_ignitor = true; + if (igniter.should_show(state)) { + if (!has_igniter) { + pane.add("Ignitor", igniter); + has_igniter = true; } } else { - if (has_ignitor) { - pane.remove(ignitor); - has_ignitor = false; + if (has_igniter) { + pane.remove(igniter); + has_igniter = false; } } if (state.gps != null && state.gps.connected) { @@ -102,8 +102,8 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl pad.show(state, listener_state); flightStatus.show(state, listener_state); flightInfo.show(state, listener_state); - if (has_ignitor) - ignitor.show(state, listener_state); + if (has_igniter) + igniter.show(state, listener_state); if (has_map) sitemap.show(state, listener_state); // } catch (Exception e) { @@ -274,7 +274,7 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl flightInfo = new AltosInfoTable(); pane.add("Table", new JScrollPane(flightInfo)); - ignitor = new AltosIgnitor(); + igniter = new AltosIgnitor(); sitemap = new AltosUIMap(); diff --git a/altosui/AltosIgniteUI.java b/altosui/AltosIgniteUI.java index 15493b8a..debbf763 100644 --- a/altosui/AltosIgniteUI.java +++ b/altosui/AltosIgniteUI.java @@ -25,8 +25,8 @@ import java.io.*; import java.text.*; import java.util.*; import java.util.concurrent.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class AltosIgniteUI extends AltosUIDialog @@ -213,6 +213,8 @@ public class AltosIgniteUI fired(); } else if (reply.startsWith("npyro")) { npyro = Integer.parseInt(reply.substring(6)); + if (npyro == AltosLib.MISSING) + npyro = 0; make_ui(); } } @@ -255,15 +257,11 @@ public class AltosIgniteUI boolean getting_status = false; - boolean visible = false; - void set_ignite_status() { getting_status = false; poll_remaining = 2; - if (!visible) { - visible = true; + if (!isVisible()) setVisible(true); - } } void poll_ignite_status() { diff --git a/altosui/AltosIgnitor.java b/altosui/AltosIgnitor.java index fabf4320..7c7d1fba 100644 --- a/altosui/AltosIgnitor.java +++ b/altosui/AltosIgnitor.java @@ -21,65 +21,65 @@ package altosui; import java.awt.*; import java.awt.event.*; import javax.swing.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class AltosIgnitor extends AltosUIFlightTab { public class Ignitor extends AltosUIUnitsIndicator { - int ignitor; + int igniter; public double value(AltosState state, int i) { - if (state.ignitor_voltage == null || - state.ignitor_voltage.length < ignitor) + if (state.igniter_voltage == null || + state.igniter_voltage.length < igniter) return AltosLib.MISSING; - return state.ignitor_voltage[ignitor]; + return state.igniter_voltage[igniter]; } public double good() { return AltosLib.ao_igniter_good; } public Ignitor (AltosUIFlightTab container, int y) { - super(container, y, AltosConvert.voltage, String.format ("%s Voltage", AltosLib.ignitor_name(y)), 1, true, 1); - ignitor = y; + super(container, y, AltosConvert.voltage, String.format ("%s Voltage", AltosLib.igniter_name(y)), 1, true, 1); + igniter = y; } } - Ignitor[] ignitors; + Ignitor[] igniters; public void show(AltosState state, AltosListenerState listener_state) { if (isShowing()) - make_ignitors(state); + make_igniters(state); super.show(state, listener_state); } public boolean should_show(AltosState state) { if (state == null) return false; - if (state.ignitor_voltage == null) + if (state.igniter_voltage == null) return false; - return state.ignitor_voltage.length > 0; + return state.igniter_voltage.length > 0; } - void make_ignitors(AltosState state) { - int n = (state == null || state.ignitor_voltage == null) ? 0 : state.ignitor_voltage.length; - int old_n = ignitors == null ? 0 : ignitors.length; + void make_igniters(AltosState state) { + int n = (state == null || state.igniter_voltage == null) ? 0 : state.igniter_voltage.length; + int old_n = igniters == null ? 0 : igniters.length; if (n != old_n) { - if (ignitors != null) { - for (int i = 0; i < ignitors.length; i++) { - remove(ignitors[i]); - ignitors[i].remove(this); - ignitors = null; + if (igniters != null) { + for (int i = 0; i < igniters.length; i++) { + remove(igniters[i]); + igniters[i].remove(this); + igniters = null; } } if (n > 0) { setVisible(true); - ignitors = new Ignitor[n]; + igniters = new Ignitor[n]; for (int i = 0; i < n; i++) { - ignitors[i] = new Ignitor(this, i); - add(ignitors[i]); + igniters[i] = new Ignitor(this, i); + add(igniters[i]); } } else setVisible(false); diff --git a/altosui/AltosLanded.java b/altosui/AltosLanded.java index 25d4fcc8..c2e14923 100644 --- a/altosui/AltosLanded.java +++ b/altosui/AltosLanded.java @@ -22,8 +22,8 @@ import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.io.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class AltosLanded extends AltosUIFlightTab implements ActionListener { @@ -123,18 +123,17 @@ public class AltosLanded extends AltosUIFlightTab implements ActionListener { if (file != null) { String filename = file.getName(); try { - AltosStateIterable states = null; + AltosRecordSet record_set = null; + FileInputStream in = new FileInputStream(file); if (filename.endsWith("eeprom")) { - FileReader in = new FileReader(file); - states = new AltosEepromFile(in); + record_set = new AltosEepromRecordSet(in); } else if (filename.endsWith("telem")) { - FileInputStream in = new FileInputStream(file); - states = new AltosTelemetryFile(in); + record_set = new AltosTelemetryFile(in); } else { throw new FileNotFoundException(filename); } try { - new AltosGraphUI(states, file); + new AltosGraphUI(record_set, file); } catch (InterruptedException ie) { } catch (IOException ie) { } diff --git a/altosui/AltosLaunch.java b/altosui/AltosLaunch.java index d4e73b3e..f1893cf5 100644 --- a/altosui/AltosLaunch.java +++ b/altosui/AltosLaunch.java @@ -21,7 +21,7 @@ package altosui; import java.io.*; import java.util.concurrent.*; import java.awt.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altosuilib_12.*; public class AltosLaunch { AltosDevice device; diff --git a/altosui/AltosLaunchUI.java b/altosui/AltosLaunchUI.java index 835858e2..8a24ed3e 100644 --- a/altosui/AltosLaunchUI.java +++ b/altosui/AltosLaunchUI.java @@ -24,7 +24,7 @@ import javax.swing.*; import java.io.*; import java.text.*; import java.util.concurrent.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altosuilib_12.*; class FireButton extends JButton { protected void processMouseEvent(MouseEvent e) { diff --git a/altosui/AltosPad.java b/altosui/AltosPad.java index d411c969..0aeef8e1 100644 --- a/altosui/AltosPad.java +++ b/altosui/AltosPad.java @@ -19,8 +19,8 @@ package altosui; import java.util.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class AltosPad extends AltosUIFlightTab { @@ -46,10 +46,11 @@ public class AltosPad extends AltosUIFlightTab { class LoggingReady extends AltosUIIndicator { public void show (AltosState state, AltosListenerState listener_state) { - if (state == null || state.flight == AltosLib.MISSING) { + AltosCalData cal_data = state.cal_data(); + if (state == null || cal_data.flight == AltosLib.MISSING) { hide(); } else { - if (state.flight != 0) { + if (cal_data.flight != 0) { if (state.state() <= Altos.ao_flight_pad) show("Ready to record"); else if (state.state() < Altos.ao_flight_landed || @@ -59,7 +60,7 @@ public class AltosPad extends AltosUIFlightTab { show("Recorded data"); } else show("Storage full"); - set_lights(state.flight != 0); + set_lights(cal_data.flight != 0); } } public LoggingReady (AltosUIFlightTab container, int y) { @@ -128,10 +129,8 @@ public class AltosPad extends AltosUIFlightTab { } boolean report_pad(AltosState state) { - if ((state.state() == AltosLib.ao_flight_stateless || - state.state() < AltosLib.ao_flight_pad) && - state.gps != null && - state.gps.lat != AltosLib.MISSING) + if (state.state() == AltosLib.ao_flight_stateless || + state.state() < AltosLib.ao_flight_pad) { return false; } @@ -150,7 +149,7 @@ public class AltosPad extends AltosUIFlightTab { if (report_pad(state)) { lat = state.pad_lat; label = "Pad Latitude"; - } else { + } else if (state.gps != null) { lat = state.gps.lat; label = "Latitude"; } @@ -187,7 +186,7 @@ public class AltosPad extends AltosUIFlightTab { if (report_pad(state)) { lon = state.pad_lon; label = "Pad Longitude"; - } else { + } else if (state.gps != null) { lon = state.gps.lon; label = "Longitude"; } @@ -217,8 +216,10 @@ public class AltosPad extends AltosUIFlightTab { public double value(AltosState state, int i) { if (report_pad(state)) return state.pad_alt; - else + else if (state.gps != null) return state.gps.alt; + else + return state.altitude(); } public void show (AltosState state, AltosListenerState listener_state) { diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 72c3c161..26591738 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -23,8 +23,8 @@ import java.awt.event.*; import javax.swing.*; import java.io.*; import java.util.concurrent.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class AltosUI extends AltosUIFrame { public AltosVoice voice = new AltosVoice(); @@ -310,10 +310,9 @@ public class AltosUI extends AltosUIFrame { AltosDataChooser chooser = new AltosDataChooser( AltosUI.this); - Iterable states = chooser.runDialog(); - if (states != null) { - AltosFlightReader reader = new AltosReplayReader(states.iterator(), - chooser.file()); + AltosRecordSet set = chooser.runDialog(); + if (set != null) { + AltosReplayReader reader = new AltosReplayReader(set, chooser.file()); new AltosFlightUI(voice, reader); } } @@ -325,6 +324,13 @@ public class AltosUI extends AltosUIFrame { new AltosEepromManage(AltosUI.this, AltosLib.product_any); } + private static AltosFlightSeries make_series(AltosRecordSet set) { + AltosFlightSeries series = new AltosFlightSeries(set.cal_data()); + set.capture_series(series); + series.finish(); + return series; + } + /* Load a flight log file and write out a CSV file containing * all of the data in standard units */ @@ -332,10 +338,11 @@ public class AltosUI extends AltosUIFrame { private void ExportData() { AltosDataChooser chooser; chooser = new AltosDataChooser(this); - AltosStateIterable states = chooser.runDialog(); - if (states == null) + AltosRecordSet set = chooser.runDialog(); + if (set == null) return; - new AltosCSVUI(AltosUI.this, states, chooser.file()); + AltosFlightSeries series = make_series(set); + new AltosCSVUI(AltosUI.this, series, chooser.file()); } /* Load a flight log CSV file and display a pretty graph. @@ -344,11 +351,11 @@ public class AltosUI extends AltosUIFrame { private void GraphData() { AltosDataChooser chooser; chooser = new AltosDataChooser(this); - AltosStateIterable states = chooser.runDialog(); - if (states == null) + AltosRecordSet set = chooser.runDialog(); + if (set == null) return; try { - new AltosGraphUI(states, chooser.file()); + new AltosGraphUI(set, chooser.file()); } catch (InterruptedException ie) { } catch (IOException ie) { } @@ -365,21 +372,6 @@ public class AltosUI extends AltosUIFrame { } } - static AltosStateIterable open_logfile(File file) { - try { - if (file.getName().endsWith("telem")) - return new AltosTelemetryFile(new FileInputStream(file)); - else - return new AltosEepromFile(new FileReader(file)); - } catch (FileNotFoundException fe) { - System.out.printf("%s\n", fe.getMessage()); - return null; - } catch (IOException ie) { - System.out.printf("%s\n", ie.getMessage()); - return null; - } - } - static AltosWriter open_csv(File file) { try { return new AltosCSV(file); @@ -398,17 +390,28 @@ public class AltosUI extends AltosUIFrame { } } + static AltosRecordSet record_set(File input) { + try { + return AltosLib.record_set(input); + } catch (IOException ie) { + String message = ie.getMessage(); + if (message == null) + message = String.format("%s (I/O error)", input.toString()); + System.err.printf("%s\n", message); + } + return null; + } + static final int process_none = 0; static final int process_csv = 1; static final int process_kml = 2; static final int process_graph = 3; static final int process_replay = 4; static final int process_summary = 5; - static final int process_cat = 6; static boolean process_csv(File input) { - AltosStateIterable states = open_logfile(input); - if (states == null) + AltosRecordSet set = record_set(input); + if (set == null) return false; File output = Altos.replace_extension(input,".csv"); @@ -420,15 +423,16 @@ public class AltosUI extends AltosUIFrame { AltosWriter writer = open_csv(output); if (writer == null) return false; - writer.write(states); + AltosFlightSeries series = make_series(set); + writer.write(series); writer.close(); } return true; } static boolean process_kml(File input) { - AltosStateIterable states = open_logfile(input); - if (states == null) + AltosRecordSet set = record_set(input); + if (set == null) return false; File output = Altos.replace_extension(input,".kml"); @@ -440,38 +444,19 @@ public class AltosUI extends AltosUIFrame { AltosWriter writer = open_kml(output); if (writer == null) return false; - writer.write(states); + AltosFlightSeries series = make_series(set); + series.finish(); + writer.write(series); writer.close(); return true; } } - static AltosStateIterable record_iterable(File file) { - FileInputStream in; - if (file.getName().endsWith("telem")) { - try { - in = new FileInputStream(file); - return new AltosTelemetryFile(in); - } catch (Exception e) { - System.out.printf("Failed to open file '%s'\n", file); - } - } else { - - try { - AltosEepromFile f = new AltosEepromFile(new FileReader(file)); - return f; - } catch (Exception e) { - System.out.printf("Failed to open file '%s'\n", file); - } - } - return null; - } - static AltosReplayReader replay_file(File file) { - AltosStateIterable states = record_iterable(file); - if (states == null) + AltosRecordSet set = record_set(file); + if (set == null) return null; - return new AltosReplayReader(states.iterator(), file); + return new AltosReplayReader(set, file); } static boolean process_replay(File file) { @@ -483,11 +468,11 @@ public class AltosUI extends AltosUIFrame { } static boolean process_graph(File file) { - AltosStateIterable states = record_iterable(file); - if (states == null) + AltosRecordSet set = record_set(file); + if (set == null) return false; try { - new AltosGraphUI(states, file); + new AltosGraphUI(set, file); return true; } catch (InterruptedException ie) { } catch (IOException ie) { @@ -496,85 +481,51 @@ public class AltosUI extends AltosUIFrame { } static boolean process_summary(File file) { - AltosStateIterable states = record_iterable(file); - if (states == null) - return false; - try { - System.out.printf("%s:\n", file.toString()); - AltosFlightStats stats = new AltosFlightStats(states); - if (stats.serial != AltosLib.MISSING) - System.out.printf("Serial: %5d\n", stats.serial); - if (stats.flight != AltosLib.MISSING) - System.out.printf("Flight: %5d\n", stats.flight); - if (stats.year != AltosLib.MISSING) - System.out.printf("Date: %04d-%02d-%02d\n", - stats.year, stats.month, stats.day); - if (stats.hour != AltosLib.MISSING) - System.out.printf("Time: %02d:%02d:%02d UTC\n", - stats.hour, stats.minute, stats.second); - if (stats.max_height != AltosLib.MISSING) - System.out.printf("Max height: %6.0f m %6.0f ft\n", - stats.max_height, - AltosConvert.meters_to_feet(stats.max_height)); - if (stats.max_speed != AltosLib.MISSING) - System.out.printf("Max speed: %6.0f m/s %6.0f ft/s %6.4f Mach\n", - stats.max_speed, - AltosConvert.meters_to_feet(stats.max_speed), - AltosConvert.meters_to_mach(stats.max_speed)); - if (stats.max_acceleration != AltosLib.MISSING) { - System.out.printf("Max accel: %6.0f m/s² %6.0f ft/s² %6.2f g\n", - stats.max_acceleration, - AltosConvert.meters_to_feet(stats.max_acceleration), - AltosConvert.meters_to_g(stats.max_acceleration)); - } - if (stats.state_speed[Altos.ao_flight_drogue] != AltosLib.MISSING) - System.out.printf("Drogue rate: %6.0f m/s %6.0f ft/s\n", - stats.state_speed[Altos.ao_flight_drogue], - AltosConvert.meters_to_feet(stats.state_speed[Altos.ao_flight_drogue])); - if (stats.state_speed[Altos.ao_flight_main] != AltosLib.MISSING) - System.out.printf("Main rate: %6.0f m/s %6.0f ft/s\n", - stats.state_speed[Altos.ao_flight_main], - AltosConvert.meters_to_feet(stats.state_speed[Altos.ao_flight_main])); - if (stats.state_end[Altos.ao_flight_main] != AltosLib.MISSING && - stats.state_start[Altos.ao_flight_boost] != AltosLib.MISSING) - System.out.printf("Flight time: %6.0f s\n", - stats.state_end[Altos.ao_flight_main] - - stats.state_start[Altos.ao_flight_boost]); - System.out.printf("\n"); - return true; - } catch (InterruptedException ie) { - } catch (IOException ie) { - } - return false; - } - - static boolean process_cat(File file) { - try { - AltosStateIterable eef = record_iterable(file); - - for (AltosState state : eef) { - if ((state.set & AltosState.set_gps) != 0) { - System.out.printf ("time %d %d-%d-%d %d:%d:%d lat %g lon %g alt %g\n", - state.gps.seconds(), - state.gps.year, - state.gps.month, - state.gps.day, - state.gps.hour, - state.gps.minute, - state.gps.second, - state.gps.lat, - state.gps.lon, - state.gps.alt); - } else { - System.out.printf ("tick %d state %d height %g\n", - state.tick, state.state(), state.height()); - } - } - - } catch (Exception e) { - System.out.printf("Failed to open file '%s'\n", file); + AltosRecordSet set = record_set(file); + if (set == null) return false; + System.out.printf("%s:\n", file.toString()); + AltosFlightSeries series = make_series(set); + AltosFlightStats stats = new AltosFlightStats(series); + if (stats.serial != AltosLib.MISSING) + System.out.printf("Serial: %5d\n", stats.serial); + if (stats.flight != AltosLib.MISSING) + System.out.printf("Flight: %5d\n", stats.flight); + if (stats.year != AltosLib.MISSING) + System.out.printf("Date: %04d-%02d-%02d\n", + stats.year, stats.month, stats.day); + if (stats.hour != AltosLib.MISSING) + System.out.printf("Time: %02d:%02d:%02d UTC\n", + stats.hour, stats.minute, stats.second); + if (stats.max_height != AltosLib.MISSING) + System.out.printf("Max height: %6.0f m %6.0f ft\n", + stats.max_height, + AltosConvert.meters_to_feet(stats.max_height)); + if (stats.max_speed != AltosLib.MISSING) + System.out.printf("Max speed: %6.0f m/s %6.0f ft/s %6.4f Mach\n", + stats.max_speed, + AltosConvert.meters_to_feet(stats.max_speed), + AltosConvert.meters_to_mach(stats.max_speed)); + if (stats.max_acceleration != AltosLib.MISSING) { + System.out.printf("Max accel: %6.0f m/s² %6.0f ft/s² %6.2f g\n", + stats.max_acceleration, + AltosConvert.meters_to_feet(stats.max_acceleration), + AltosConvert.meters_to_g(stats.max_acceleration)); } + if (stats.state_speed[Altos.ao_flight_drogue] != AltosLib.MISSING) + System.out.printf("Drogue rate: %6.0f m/s %6.0f ft/s\n", + stats.state_speed[Altos.ao_flight_drogue], + AltosConvert.meters_to_feet(stats.state_speed[Altos.ao_flight_drogue])); + if (stats.state_speed[Altos.ao_flight_main] != AltosLib.MISSING) + System.out.printf("Main rate: %6.0f m/s %6.0f ft/s\n", + stats.state_speed[Altos.ao_flight_main], + AltosConvert.meters_to_feet(stats.state_speed[Altos.ao_flight_main])); + if (stats.state_end[Altos.ao_flight_main] != AltosLib.MISSING && + stats.state_start[Altos.ao_flight_boost] != AltosLib.MISSING) + System.out.printf("Flight time: %6.0f s\n", + stats.state_end[Altos.ao_flight_main] - + stats.state_start[Altos.ao_flight_boost]); + System.out.printf("\n"); return true; } @@ -620,8 +571,6 @@ public class AltosUI extends AltosUIFrame { process = process_graph; else if (args[i].equals("--summary")) process = process_summary; - else if (args[i].equals("--cat")) - process = process_cat; else if (args[i].startsWith("--")) help(1); else { @@ -650,9 +599,6 @@ public class AltosUI extends AltosUIFrame { if (!process_summary(file)) ++errors; break; - case process_cat: - if (!process_cat(file)) - ++errors; } } } diff --git a/altosuilib/AltosBTDevice.java b/altosuilib/AltosBTDevice.java index 313cf0a0..5b9ab06a 100644 --- a/altosuilib/AltosBTDevice.java +++ b/altosuilib/AltosBTDevice.java @@ -16,10 +16,10 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import libaltosJNI.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class AltosBTDevice extends altos_bt_device implements AltosDevice { diff --git a/altosuilib/AltosBTDeviceIterator.java b/altosuilib/AltosBTDeviceIterator.java index 1ea31950..ac9068d0 100644 --- a/altosuilib/AltosBTDeviceIterator.java +++ b/altosuilib/AltosBTDeviceIterator.java @@ -16,11 +16,11 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.util.*; import libaltosJNI.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class AltosBTDeviceIterator implements Iterator { AltosBTDevice current; diff --git a/altosuilib/AltosBTKnown.java b/altosuilib/AltosBTKnown.java index 32cc05d7..56f1991f 100644 --- a/altosuilib/AltosBTKnown.java +++ b/altosuilib/AltosBTKnown.java @@ -16,10 +16,10 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.util.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class AltosBTKnown implements Iterable { LinkedList devices = new LinkedList(); diff --git a/altosuilib/AltosBTManage.java b/altosuilib/AltosBTManage.java index 14e0a056..aec4c34d 100644 --- a/altosuilib/AltosBTManage.java +++ b/altosuilib/AltosBTManage.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.awt.*; import java.awt.event.*; @@ -24,7 +24,7 @@ import javax.swing.*; import javax.swing.plaf.basic.*; import java.util.*; import java.util.concurrent.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class AltosBTManage extends AltosUIDialog implements ActionListener, Iterable { LinkedBlockingQueue found_devices; diff --git a/altosuilib/AltosCSVUI.java b/altosuilib/AltosCSVUI.java index 1b769740..442e3de3 100644 --- a/altosuilib/AltosCSVUI.java +++ b/altosuilib/AltosCSVUI.java @@ -16,13 +16,13 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.io.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class AltosCSVUI extends AltosUIDialog @@ -31,7 +31,8 @@ public class AltosCSVUI JFileChooser csv_chooser; JPanel accessory; JComboBox combo_box; - Iterable states; + AltosFlightSeries series; + AltosCalData cal_data; AltosWriter writer; static String[] combo_box_items = { "Comma Separated Values (.CSV)", "Googleearth Data (.KML)" }; @@ -55,8 +56,9 @@ public class AltosCSVUI set_default_file(); } - public AltosCSVUI(JFrame frame, AltosStateIterable states, File source_file) { - this.states = states; + public AltosCSVUI(JFrame frame, AltosFlightSeries series, File source_file) { + this.series = series; + this.cal_data = series.cal_data(); csv_chooser = new JFileChooser(source_file); accessory = new JPanel(); @@ -91,7 +93,7 @@ public class AltosCSVUI writer = new AltosCSV(file); else writer = new AltosKML(file); - writer.write(states); + writer.write(series); writer.close(); } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(frame, diff --git a/altosuilib/AltosConfigFreqUI.java b/altosuilib/AltosConfigFreqUI.java index c4d2abba..055d34f9 100644 --- a/altosuilib/AltosConfigFreqUI.java +++ b/altosuilib/AltosConfigFreqUI.java @@ -16,14 +16,14 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.awt.*; import java.text.*; import java.awt.event.*; import javax.swing.*; import java.util.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; class AltosEditFreqUI extends AltosUIDialog implements ActionListener { Frame frame; diff --git a/altosuilib/AltosDataChooser.java b/altosuilib/AltosDataChooser.java index a8c74926..b417c732 100644 --- a/altosuilib/AltosDataChooser.java +++ b/altosuilib/AltosDataChooser.java @@ -16,12 +16,12 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import java.io.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class AltosDataChooser extends JFileChooser { JFrame frame; @@ -36,7 +36,7 @@ public class AltosDataChooser extends JFileChooser { return file; } - public AltosStateIterable runDialog() { + public AltosRecordSet runDialog() { int ret; ret = showOpenDialog(frame); @@ -44,22 +44,8 @@ public class AltosDataChooser extends JFileChooser { file = getSelectedFile(); if (file == null) return null; - filename = file.getName(); try { - if (filename.endsWith("eeprom")) { - FileReader in = new FileReader(file); - return new AltosEepromFile(in); - } else if (filename.endsWith("telem")) { - FileInputStream in = new FileInputStream(file); - return new AltosTelemetryFile(in); - } else { - throw new FileNotFoundException(); - } - } catch (FileNotFoundException fe) { - JOptionPane.showMessageDialog(frame, - fe.getMessage(), - "Cannot open file", - JOptionPane.ERROR_MESSAGE); + return AltosLib.record_set(file); } catch (IOException ie) { JOptionPane.showMessageDialog(frame, ie.getMessage(), diff --git a/altosuilib/AltosDevice.java b/altosuilib/AltosDevice.java index f9878fe9..44f71f7a 100644 --- a/altosuilib/AltosDevice.java +++ b/altosuilib/AltosDevice.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import libaltosJNI.*; diff --git a/altosuilib/AltosDeviceDialog.java b/altosuilib/AltosDeviceDialog.java index 5d8ff570..77249bfc 100644 --- a/altosuilib/AltosDeviceDialog.java +++ b/altosuilib/AltosDeviceDialog.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import javax.swing.*; import java.awt.*; diff --git a/altosuilib/AltosDeviceUIDialog.java b/altosuilib/AltosDeviceUIDialog.java index c2d6f4f3..f3409cce 100644 --- a/altosuilib/AltosDeviceUIDialog.java +++ b/altosuilib/AltosDeviceUIDialog.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import javax.swing.*; import java.awt.*; diff --git a/altosuilib/AltosDisplayThread.java b/altosuilib/AltosDisplayThread.java index 52414c62..3fcc02da 100644 --- a/altosuilib/AltosDisplayThread.java +++ b/altosuilib/AltosDisplayThread.java @@ -16,13 +16,13 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.awt.*; import javax.swing.*; import java.io.*; import java.text.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class AltosDisplayThread extends Thread { @@ -30,7 +30,9 @@ public class AltosDisplayThread extends Thread { IdleThread idle_thread; AltosVoice voice; AltosFlightReader reader; - AltosState old_state, state; + AltosState state; + int old_state = AltosLib.ao_flight_invalid; + boolean old_gps_ready = false; AltosListenerState listener_state; AltosFlightDisplay display; @@ -93,13 +95,13 @@ public class AltosDisplayThread extends Thread { state.from_pad != null && state.range >= 0) { - voice.speak("Height %s, bearing %s %d, elevation %d, range %s.\n", + voice.speak("Height %s, bearing %s %d, elevation %d, distance %s.\n", AltosConvert.height.say(state.height()), state.from_pad.bearing_words( AltosGreatCircle.BEARING_VOICE), (int) (state.from_pad.bearing + 0.5), (int) (state.elevation + 0.5), - AltosConvert.distance.say(state.range)); + AltosConvert.distance.say(state.distance)); } else if (state.state() > AltosLib.ao_flight_pad && state.height() != AltosLib.MISSING) { voice.speak(AltosConvert.height.say_units(state.height())); } else { @@ -121,7 +123,7 @@ public class AltosDisplayThread extends Thread { else voice.speak("rocket may have crashed"); if (state.from_pad != null) - voice.speak("Bearing %d degrees, range %s.", + voice.speak("Bearing %d degrees, distance %s.", (int) (state.from_pad.bearing + 0.5), AltosConvert.distance.say_units(state.from_pad.distance)); ++reported_landing; @@ -164,7 +166,7 @@ public class AltosDisplayThread extends Thread { } public synchronized void notice(boolean spoken) { - if (old_state != null && old_state.state() != state.state()) { + if (old_state != state.state()) { report_time = now(); this.notify(); } else if (spoken) @@ -179,16 +181,16 @@ public class AltosDisplayThread extends Thread { synchronized boolean tell() { boolean ret = false; - if (old_state == null || old_state.state() != state.state()) { + if (old_state != state.state()) { if (state.state() != AltosLib.ao_flight_stateless) voice.speak(state.state_name()); - if ((old_state == null || old_state.state() <= AltosLib.ao_flight_boost) && + if ((old_state == AltosLib.ao_flight_invalid || old_state <= AltosLib.ao_flight_boost) && state.state() > AltosLib.ao_flight_boost) { if (state.max_speed() != AltosLib.MISSING) voice.speak("max speed: %s.", AltosConvert.speed.say_units(state.max_speed() + 0.5)); ret = true; - } else if ((old_state == null || old_state.state() < AltosLib.ao_flight_drogue) && + } else if ((old_state == AltosLib.ao_flight_invalid || old_state < AltosLib.ao_flight_drogue) && state.state() >= AltosLib.ao_flight_drogue) { if (state.max_height() != AltosLib.MISSING) voice.speak("max height: %s.", @@ -196,17 +198,18 @@ public class AltosDisplayThread extends Thread { ret = true; } } - if (old_state == null || old_state.gps_ready != state.gps_ready) { + if (old_gps_ready != state.gps_ready) { if (state.gps_ready) { voice.speak("GPS ready"); ret = true; } - else if (old_state != null) { + else if (old_gps_ready) { voice.speak("GPS lost"); ret = true; } } - old_state = state; + old_state = state.state(); + old_gps_ready = state.gps_ready; return ret; } @@ -220,14 +223,11 @@ public class AltosDisplayThread extends Thread { try { for (;;) { try { - AltosState new_state = reader.read(); - if (new_state == null) { - state = null; + state = reader.read(); + if (state == null) { listener_state.running = false; break; } - reader.update(new_state); - state = new_state; show_safely(); told = tell(); idle_thread.notice(told); diff --git a/altosuilib/AltosEepromDelete.java b/altosuilib/AltosEepromDelete.java index 24337be4..87e80a51 100644 --- a/altosuilib/AltosEepromDelete.java +++ b/altosuilib/AltosEepromDelete.java @@ -16,13 +16,13 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.awt.event.*; import javax.swing.*; import java.io.*; import java.util.concurrent.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class AltosEepromDelete implements Runnable { AltosEepromList flights; diff --git a/altosuilib/AltosEepromManage.java b/altosuilib/AltosEepromManage.java index a6636c4f..93827139 100644 --- a/altosuilib/AltosEepromManage.java +++ b/altosuilib/AltosEepromManage.java @@ -16,13 +16,13 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.awt.event.*; import javax.swing.*; import java.io.*; import java.util.concurrent.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class AltosEepromManage implements ActionListener { diff --git a/altosuilib/AltosEepromMonitor.java b/altosuilib/AltosEepromMonitor.java deleted file mode 100644 index d61169f4..00000000 --- a/altosuilib/AltosEepromMonitor.java +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.altosuilib_11; - -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; - -public class AltosEepromMonitor extends AltosUIDialog { - - Container pane; - Box box; - JLabel serial_label; - JLabel flight_label; - JLabel file_label; - JLabel serial_value; - JLabel flight_value; - JLabel file_value; - JButton cancel; - JProgressBar pbar; - int min_state, max_state; - - public AltosEepromMonitor(JFrame owner, int in_min_state, int in_max_state) { - super (owner, "Download Flight Data", false); - - GridBagConstraints c; - Insets il = new Insets(4,4,4,4); - Insets ir = new Insets(4,4,4,4); - - pane = getContentPane(); - pane.setLayout(new GridBagLayout()); - - c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 0; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.LINE_START; - c.insets = il; - serial_label = new JLabel("Serial:"); - pane.add(serial_label, c); - - c = new GridBagConstraints(); - c.gridx = 1; c.gridy = 0; - c.fill = GridBagConstraints.HORIZONTAL; - c.weightx = 1; - c.anchor = GridBagConstraints.LINE_START; - c.insets = ir; - serial_value = new JLabel(""); - pane.add(serial_value, c); - - c = new GridBagConstraints(); - c.fill = GridBagConstraints.NONE; - c.gridx = 0; c.gridy = 1; - c.anchor = GridBagConstraints.LINE_START; - c.insets = il; - flight_label = new JLabel("Flight:"); - pane.add(flight_label, c); - - c = new GridBagConstraints(); - c.fill = GridBagConstraints.HORIZONTAL; - c.weightx = 1; - c.gridx = 1; c.gridy = 1; - c.anchor = GridBagConstraints.LINE_START; - c.insets = ir; - flight_value = new JLabel(""); - pane.add(flight_value, c); - - c = new GridBagConstraints(); - c.fill = GridBagConstraints.NONE; - c.gridx = 0; c.gridy = 2; - c.anchor = GridBagConstraints.LINE_START; - c.insets = il; - file_label = new JLabel("File:"); - pane.add(file_label, c); - - c = new GridBagConstraints(); - c.fill = GridBagConstraints.HORIZONTAL; - c.weightx = 1; - c.gridx = 1; c.gridy = 2; - c.anchor = GridBagConstraints.LINE_START; - c.insets = ir; - file_value = new JLabel(""); - pane.add(file_value, c); - - min_state = in_min_state; - max_state = in_max_state; - pbar = new JProgressBar(); - pbar.setMinimum(0); - pbar.setMaximum(1000); - pbar.setValue(0); - pbar.setString("startup"); - pbar.setStringPainted(true); - pbar.setPreferredSize(new Dimension(600, 20)); - c = new GridBagConstraints(); - c.fill = GridBagConstraints.HORIZONTAL; - c.anchor = GridBagConstraints.CENTER; - c.gridx = 0; c.gridy = 3; - c.gridwidth = GridBagConstraints.REMAINDER; - Insets ib = new Insets(4,4,4,4); - c.insets = ib; - pane.add(pbar, c); - - - cancel = new JButton("Cancel"); - c = new GridBagConstraints(); - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.gridx = 0; c.gridy = 4; - c.gridwidth = GridBagConstraints.REMAINDER; - Insets ic = new Insets(4,4,4,4); - c.insets = ic; - pane.add(cancel, c); - - pack(); - setLocationRelativeTo(owner); - setVisible(true); - } - - public void addActionListener (ActionListener l) { - cancel.addActionListener(l); - } - - private void set_value_internal(String state_name, int state, int state_block, int block) { - if (state_block > 100) - state_block = 100; - if (state < min_state) state = min_state; - if (state >= max_state) state = max_state - 1; - state -= min_state; - - int pos = state * 100 + state_block; - - pbar.setString(String.format("block %d state %s", block, state_name)); - pbar.setValue(pos); - } - - public void set_value(String in_state_name, int in_state, int in_state_block, int in_block) { - final String state_name = in_state_name; - final int state = in_state; - final int state_block = in_state_block; - final int block = in_block; - Runnable r = new Runnable() { - public void run() { - try { - set_value_internal(state_name, state, state_block, block); - } catch (Exception ex) { - } - } - }; - SwingUtilities.invokeLater(r); - } - - private void set_serial_internal(int serial) { - serial_value.setText(String.format("%d", serial)); - } - - public void set_serial(int in_serial) { - final int serial = in_serial; - Runnable r = new Runnable() { - public void run() { - try { - set_serial_internal(serial); - } catch (Exception ex) { - } - } - }; - SwingUtilities.invokeLater(r); - } - - private void set_flight_internal(int flight) { - flight_value.setText(String.format("%d", flight)); - } - - public void set_flight(int in_flight) { - final int flight = in_flight; - Runnable r = new Runnable() { - public void run() { - try { - set_flight_internal(flight); - } catch (Exception ex) { - } - } - }; - SwingUtilities.invokeLater(r); - } - - private void set_file_internal(String file) { - file_value.setText(String.format("%s", file)); - } - - public void set_file(String in_file) { - final String file = in_file; - Runnable r = new Runnable() { - public void run() { - try { - set_file_internal(file); - } catch (Exception ex) { - } - } - }; - SwingUtilities.invokeLater(r); - } - - private void done_internal() { - setVisible(false); - dispose(); - } - - public void done() { - Runnable r = new Runnable() { - public void run() { - try { - done_internal(); - } catch (Exception ex) { - } - } - }; - SwingUtilities.invokeLater(r); - } - - private void reset_internal() { - set_value_internal("startup",min_state,0, 0); - set_flight_internal(0); - set_file_internal(""); - } - - public void reset() { - Runnable r = new Runnable() { - public void run() { - try { - reset_internal(); - } catch (Exception ex) { - } - } - }; - SwingUtilities.invokeLater(r); - } -} diff --git a/altosuilib/AltosEepromMonitorUI.java b/altosuilib/AltosEepromMonitorUI.java index 03661662..3427fe0f 100644 --- a/altosuilib/AltosEepromMonitorUI.java +++ b/altosuilib/AltosEepromMonitorUI.java @@ -16,12 +16,12 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.awt.*; import java.awt.event.*; import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMonitor { JFrame owner; diff --git a/altosuilib/AltosEepromSelect.java b/altosuilib/AltosEepromSelect.java index 2c6ee6d7..0c890c8b 100644 --- a/altosuilib/AltosEepromSelect.java +++ b/altosuilib/AltosEepromSelect.java @@ -16,13 +16,13 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import javax.swing.*; import javax.swing.border.*; import java.awt.*; import java.awt.event.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; class AltosEepromItem implements ActionListener { AltosEepromLog log; diff --git a/altosuilib/AltosFlashUI.java b/altosuilib/AltosFlashUI.java index da36397a..ca089ca8 100644 --- a/altosuilib/AltosFlashUI.java +++ b/altosuilib/AltosFlashUI.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.awt.*; import java.awt.event.*; @@ -24,7 +24,7 @@ import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import java.io.*; import java.util.concurrent.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class AltosFlashUI extends AltosUIDialog diff --git a/altosuilib/AltosFlightInfoTableModel.java b/altosuilib/AltosFlightInfoTableModel.java index 2d371101..943c9207 100644 --- a/altosuilib/AltosFlightInfoTableModel.java +++ b/altosuilib/AltosFlightInfoTableModel.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import javax.swing.table.*; diff --git a/altosuilib/AltosFlightStatsTable.java b/altosuilib/AltosFlightStatsTable.java index 2f46f231..415c0244 100644 --- a/altosuilib/AltosFlightStatsTable.java +++ b/altosuilib/AltosFlightStatsTable.java @@ -16,12 +16,12 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.awt.*; import javax.swing.*; import java.util.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class AltosFlightStatsTable extends JComponent implements AltosFontListener { GridBagLayout layout; @@ -87,13 +87,19 @@ public class AltosFlightStatsTable extends JComponent implements AltosFontListen return String.format("%s %4d° %9.6f'", h, deg, min); } - public AltosFlightStatsTable(AltosFlightStats stats) { - layout = new GridBagLayout(); - - setLayout(layout); + public void set_stats(AltosFlightStats stats) { int y = 0; - new FlightStat(layout, y++, "Serial", String.format("%d", stats.serial)); - new FlightStat(layout, y++, "Flight", String.format("%d", stats.flight)); + if (stats.serial != AltosLib.MISSING) { + if (stats.product != null && stats.firmware_version != null) + new FlightStat(layout, y++, "Device", + stats.product, + String.format("version %s", stats.firmware_version), + String.format("serial %d", stats.serial)); + else + new FlightStat(layout, y++, "Serial", String.format("%d", stats.serial)); + } + if (stats.flight != AltosLib.MISSING) + new FlightStat(layout, y++, "Flight", String.format("%d", stats.flight)); if (stats.year != AltosLib.MISSING && stats.hour != AltosLib.MISSING) new FlightStat(layout, y++, "Date/Time", String.format("%04d-%02d-%02d", stats.year, stats.month, stats.day), @@ -108,61 +114,112 @@ public class AltosFlightStatsTable extends JComponent implements AltosFontListen } if (stats.max_height != AltosLib.MISSING) { new FlightStat(layout, y++, "Maximum height", - String.format("%5.0f m", stats.max_height), + String.format("%6.1f m", stats.max_height), String.format("%5.0f ft", AltosConvert.meters_to_feet(stats.max_height))); } if (stats.max_gps_height != AltosLib.MISSING) { new FlightStat(layout, y++, "Maximum GPS height", - String.format("%5.0f m", stats.max_gps_height), + String.format("%6.1f m", stats.max_gps_height), String.format("%5.0f ft", AltosConvert.meters_to_feet(stats.max_gps_height))); } - new FlightStat(layout, y++, "Maximum speed", - String.format("%5.0f m/s", stats.max_speed), - String.format("%5.0f fps", AltosConvert.mps_to_fps(stats.max_speed)), - String.format("Mach %4.1f", AltosConvert.meters_to_mach(stats.max_speed))); + if (stats.max_speed != AltosLib.MISSING) { + new FlightStat(layout, y++, "Maximum speed", + String.format("%6.1f m/s", stats.max_speed), + String.format("%5.0f fps", AltosConvert.mps_to_fps(stats.max_speed)), + String.format("Mach %4.1f", AltosConvert.meters_to_mach(stats.max_speed))); + } if (stats.max_acceleration != AltosLib.MISSING) new FlightStat(layout, y++, "Maximum boost acceleration", - String.format("%5.0f m/s²", stats.max_acceleration), + String.format("%6.1f m/s²", stats.max_acceleration), String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.max_acceleration)), - String.format("%5.0f G", AltosConvert.meters_to_g(stats.max_acceleration))); + String.format("%6.2f G", AltosConvert.meters_to_g(stats.max_acceleration))); if (stats.state_accel[AltosLib.ao_flight_boost] != AltosLib.MISSING) new FlightStat(layout, y++, "Average boost acceleration", - String.format("%5.0f m/s²", stats.state_accel[AltosLib.ao_flight_boost]), + String.format("%6.1f m/s²", stats.state_accel[AltosLib.ao_flight_boost]), String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.state_accel[AltosLib.ao_flight_boost])), - String.format("%5.0f G", AltosConvert.meters_to_g(stats.state_accel[AltosLib.ao_flight_boost]))); - if (stats.state_speed[AltosLib.ao_flight_drogue] != AltosLib.MISSING) - new FlightStat(layout, y++, "Drogue descent rate", - String.format("%5.0f m/s", stats.state_speed[AltosLib.ao_flight_drogue]), - String.format("%5.0f ft/s", AltosConvert.meters_to_feet(stats.state_speed[AltosLib.ao_flight_drogue]))); + String.format("%6.2f G", AltosConvert.meters_to_g(stats.state_accel[AltosLib.ao_flight_boost]))); + if (stats.state_time[AltosLib.ao_flight_boost] != 0 || stats.state_time[AltosLib.ao_flight_fast] != 0 || stats.state_time[AltosLib.ao_flight_coast] != 0) { + + double boost_time = stats.state_time[AltosLib.ao_flight_boost]; + double fast_time = stats.state_time[AltosLib.ao_flight_fast]; + double coast_time = stats.state_time[AltosLib.ao_flight_coast]; + + if (fast_time > 0) { + new FlightStat(layout, y++, "Ascent time", + String.format("%6.1f s %s", boost_time, + AltosLib.state_name(AltosLib.ao_flight_boost)), + String.format("%6.1f s %s", fast_time, + AltosLib.state_name(AltosLib.ao_flight_fast)), + String.format("%6.1f s %s", coast_time, + AltosLib.state_name(AltosLib.ao_flight_coast))); + } else { + new FlightStat(layout, y++, "Ascent time", + String.format("%6.1f s %s", boost_time, + AltosLib.state_name(AltosLib.ao_flight_boost)), + String.format("%6.1f s %s", coast_time, + AltosLib.state_name(AltosLib.ao_flight_coast))); + } + } + if (stats.state_speed[AltosLib.ao_flight_drogue] != AltosLib.MISSING) { + String label; + + if (stats.state_speed[AltosLib.ao_flight_main] == AltosLib.MISSING) + label = "Descent rate"; + else + label = "Drogue descent rate"; + new FlightStat(layout, y++, label, + String.format("%6.1f m/s", -stats.state_speed[AltosLib.ao_flight_drogue]), + String.format("%5.0f ft/s", -AltosConvert.meters_to_feet(stats.state_speed[AltosLib.ao_flight_drogue]))); + } if (stats.state_speed[AltosLib.ao_flight_main] != AltosLib.MISSING) new FlightStat(layout, y++, "Main descent rate", - String.format("%5.0f m/s", stats.state_speed[AltosLib.ao_flight_main]), - String.format("%5.0f ft/s", AltosConvert.meters_to_feet(stats.state_speed[AltosLib.ao_flight_main]))); - if (stats.state_start[AltosLib.ao_flight_boost] < stats.state_end[AltosLib.ao_flight_coast]) - new FlightStat(layout, y++, "Ascent time", - String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_boost] - stats.state_start[AltosLib.ao_flight_boost], - AltosLib.state_name(AltosLib.ao_flight_boost)), - String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_fast] - stats.state_start[AltosLib.ao_flight_fast], - AltosLib.state_name(AltosLib.ao_flight_fast)), - String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_coast] - stats.state_start[AltosLib.ao_flight_coast], - AltosLib.state_name(AltosLib.ao_flight_coast))); - if (stats.state_start[AltosLib.ao_flight_drogue] < stats.state_end[AltosLib.ao_flight_main]) - new FlightStat(layout, y++, "Descent time", - String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_drogue] - stats.state_start[AltosLib.ao_flight_drogue], - AltosLib.state_name(AltosLib.ao_flight_drogue)), - String.format("%6.1f s %s", stats.state_end[AltosLib.ao_flight_main] - stats.state_start[AltosLib.ao_flight_main], - AltosLib.state_name(AltosLib.ao_flight_main))); - if (stats.state_start[AltosLib.ao_flight_boost] < stats.state_end[AltosLib.ao_flight_main]) + String.format("%6.1f m/s", -stats.state_speed[AltosLib.ao_flight_main]), + String.format("%5.0f ft/s", -AltosConvert.meters_to_feet(stats.state_speed[AltosLib.ao_flight_main]))); + if (stats.state_time[AltosLib.ao_flight_drogue] != 0 || stats.state_time[AltosLib.ao_flight_main] != 0) { + double drogue_duration = stats.state_time[AltosLib.ao_flight_drogue]; + double main_duration = stats.state_time[AltosLib.ao_flight_main]; + double duration = drogue_duration + main_duration; + + if (drogue_duration > 0 && main_duration > 0) { + new FlightStat(layout, y++, "Descent time", + String.format("%6.1f s %s", drogue_duration, + AltosLib.state_name(AltosLib.ao_flight_drogue)), + String.format("%6.1f s %s", main_duration, + AltosLib.state_name(AltosLib.ao_flight_main))); + } else if (duration > 0) { + new FlightStat(layout, y++, "Descent time", + String.format("%6.1f s", duration)); + } + } + if (stats.landed_time > stats.boost_time) new FlightStat(layout, y++, "Flight time", - String.format("%6.1f s", stats.state_end[AltosLib.ao_flight_main] - - stats.state_start[AltosLib.ao_flight_boost])); - if (stats.has_gps) { + String.format("%6.1f s", stats.landed_time - stats.boost_time)); + if (stats.has_gps && stats.pad_lat != AltosLib.MISSING) { new FlightStat(layout, y++, "Pad location", pos(stats.pad_lat,"N","S"), pos(stats.pad_lon,"E","W")); + } + if (stats.has_gps && stats.lat != AltosLib.MISSING) { new FlightStat(layout, y++, "Last reported location", pos(stats.lat,"N","S"), pos(stats.lon,"E","W")); } } + + public void tell_closing() { + AltosUIPreferences.unregister_font_listener(this); + } + + public AltosFlightStatsTable() { + layout = new GridBagLayout(); + + setLayout(layout); + + AltosUIPreferences.register_font_listener(this); + } + + public AltosFlightStatsTable(AltosFlightStats stats) { + this(); + set_stats(stats); + } } diff --git a/altosuilib/AltosGraph.java b/altosuilib/AltosGraph.java index 2dbd1612..31042abb 100644 --- a/altosuilib/AltosGraph.java +++ b/altosuilib/AltosGraph.java @@ -16,14 +16,14 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.io.*; import java.util.ArrayList; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; import org.jfree.ui.*; import org.jfree.chart.*; @@ -35,162 +35,32 @@ import org.jfree.chart.labels.*; import org.jfree.data.xy.*; import org.jfree.data.*; -class AltosVoltage extends AltosUnits { - - public double value(double v, boolean imperial_units) { - return v; - } - - public double inverse(double v, boolean imperial_units) { - return v; - } - - public String show_units(boolean imperial_units) { - return "V"; - } - - public String say_units(boolean imperial_units) { - return "volts"; - } - - public int show_fraction(int width, boolean imperial_units) { - return width / 2; - } -} - -class AltosNsat extends AltosUnits { - - public double value(double v, boolean imperial_units) { - return v; - } - - public double inverse(double v, boolean imperial_units) { - return v; - } - - public String show_units(boolean imperial_units) { - return "Sats"; - } - - public String say_units(boolean imperial_units) { - return "Satellites"; - } - - public int show_fraction(int width, boolean imperial_units) { - return 0; - } -} - -class AltosDbm extends AltosUnits { - - public double value(double d, boolean imperial_units) { - return d; - } - - public double inverse(double d, boolean imperial_units) { - return d; - } - - public String show_units(boolean imperial_units) { - return "dBm"; - } - - public String say_units(boolean imperial_units) { - return "D B M"; - } - - public int show_fraction(int width, boolean imperial_units) { - return 0; - } -} - -class AltosGyroUnits extends AltosUnits { - - public double value(double p, boolean imperial_units) { - return p; - } - - public double inverse(double p, boolean imperial_units) { - return p; - } - - public String show_units(boolean imperial_units) { - return "°/sec"; - } - - public String say_units(boolean imperial_units) { - return "degrees per second"; - } - - public int show_fraction(int width, boolean imperial_units) { - return 1; - } -} - -class AltosMagUnits extends AltosUnits { - - public double value(double p, boolean imperial_units) { - return p; - } - - public double inverse(double p, boolean imperial_units) { - return p; - } - - public String show_units(boolean imperial_units) { - return "Ga"; - } - - public String say_units(boolean imperial_units) { - return "gauss"; - } - - public int show_fraction(int width, boolean imperial_units) { - return 2; - } -} - -class AltosDopUnits extends AltosUnits { - - public double value(double p, boolean imperial_units) { - return p; - } - - public double inverse(double p, boolean imperial_units) { - return p; - } - - public String show_units(boolean imperial_units) { - return null; - } - - public String say_units(boolean imperial_units) { - return null; - } - - public int show_fraction(int width, boolean imperial_units) { - return 1; - } -} - public class AltosGraph extends AltosUIGraph { static final private Color height_color = new Color(194,31,31); + static final private Color kalman_height_color = new Color(255,0,0); static final private Color gps_height_color = new Color(150,31,31); static final private Color pressure_color = new Color (225,31,31); static final private Color range_color = new Color(100, 31, 31); static final private Color distance_color = new Color(100, 31, 194); static final private Color speed_color = new Color(31,194,31); + static final private Color kalman_speed_color = new Color(0,255,0); + static final private Color thrust_color = new Color(31,194,31); static final private Color accel_color = new Color(31,31,194); + static final private Color vert_accel_color = new Color(64,164,164); + static final private Color kalman_accel_color = new Color(0,0,255); static final private Color voltage_color = new Color(194, 194, 31); static final private Color battery_voltage_color = new Color(194, 194, 31); static final private Color drogue_voltage_color = new Color(150, 150, 31); static final private Color main_voltage_color = new Color(100, 100, 31); + static final private Color igniter_voltage_color = new Color(80, 80, 31); + static final private Color igniter_marker_color = new Color(255, 0, 0); static final private Color gps_nsat_color = new Color (194, 31, 194); static final private Color gps_nsat_solution_color = new Color (194, 31, 194); static final private Color gps_nsat_view_color = new Color (150, 31, 150); static final private Color gps_course_color = new Color (100, 31, 112); static final private Color gps_ground_speed_color = new Color (31, 112, 100); + static final private Color gps_speed_color = new Color (31, 112, 100); static final private Color gps_climb_rate_color = new Color (31, 31, 112); static final private Color gps_pdop_color = new Color(50, 194, 0); static final private Color gps_hdop_color = new Color(50, 0, 194); @@ -198,278 +68,268 @@ public class AltosGraph extends AltosUIGraph { static final private Color temperature_color = new Color (31, 194, 194); static final private Color dbm_color = new Color(31, 100, 100); static final private Color state_color = new Color(0,0,0); - static final private Color accel_x_color = new Color(255, 0, 0); - static final private Color accel_y_color = new Color(0, 255, 0); - static final private Color accel_z_color = new Color(0, 0, 255); - static final private Color gyro_x_color = new Color(192, 0, 0); - static final private Color gyro_y_color = new Color(0, 192, 0); - static final private Color gyro_z_color = new Color(0, 0, 192); - static final private Color mag_x_color = new Color(128, 0, 0); - static final private Color mag_y_color = new Color(0, 128, 0); - static final private Color mag_z_color = new Color(0, 0, 128); + static final private Color accel_along_color = new Color(255, 0, 0); + static final private Color accel_across_color = new Color(0, 255, 0); + static final private Color accel_through_color = new Color(0, 0, 255); + static final private Color gyro_roll_color = new Color(192, 0, 0); + static final private Color gyro_pitch_color = new Color(0, 192, 0); + static final private Color gyro_yaw_color = new Color(0, 0, 192); + static final private Color mag_along_color = new Color(128, 0, 0); + static final private Color mag_across_color = new Color(0, 128, 0); + static final private Color mag_through_color = new Color(0, 0, 128); static final private Color orient_color = new Color(31, 31, 31); - static AltosVoltage voltage_units = new AltosVoltage(); - static AltosPressure pressure_units = new AltosPressure(); - static AltosNsat nsat_units = new AltosNsat(); - static AltosDbm dbm_units = new AltosDbm(); - static AltosGyroUnits gyro_units = new AltosGyroUnits(); - static AltosOrient orient_units = new AltosOrient(); - static AltosMagUnits mag_units = new AltosMagUnits(); - static AltosDopUnits dop_units = new AltosDopUnits(); + static AltosUnits dop_units = null; + + AltosUIFlightSeries flight_series; - AltosUIAxis height_axis, speed_axis, accel_axis, voltage_axis, temperature_axis, nsat_axis, dbm_axis; - AltosUIAxis distance_axis, pressure_axis; - AltosUIAxis gyro_axis, orient_axis, mag_axis; - AltosUIAxis course_axis, dop_axis; + AltosUITimeSeries[] setup(AltosFlightStats stats, AltosUIFlightSeries flight_series) { + AltosCalData cal_data = flight_series.cal_data(); - public AltosGraph(AltosUIEnable enable, AltosFlightStats stats, AltosGraphDataSet dataSet) { - super(enable); + AltosUIAxis height_axis, speed_axis, accel_axis, voltage_axis, temperature_axis, nsat_axis, dbm_axis; + AltosUIAxis distance_axis, pressure_axis, thrust_axis; + AltosUIAxis gyro_axis, orient_axis, mag_axis; + AltosUIAxis course_axis, dop_axis; + + if (stats.serial != AltosLib.MISSING && stats.product != null && stats.flight != AltosLib.MISSING) + setName(String.format("%s %d flight %d\n", stats.product, stats.serial, stats.flight)); height_axis = newAxis("Height", AltosConvert.height, height_color); - pressure_axis = newAxis("Pressure", pressure_units, pressure_color, 0); + pressure_axis = newAxis("Pressure", AltosConvert.pressure, pressure_color, 0); speed_axis = newAxis("Speed", AltosConvert.speed, speed_color); + thrust_axis = newAxis("Thrust", AltosConvert.force, thrust_color); accel_axis = newAxis("Acceleration", AltosConvert.accel, accel_color); - voltage_axis = newAxis("Voltage", voltage_units, voltage_color); + voltage_axis = newAxis("Voltage", AltosConvert.voltage, voltage_color); temperature_axis = newAxis("Temperature", AltosConvert.temperature, temperature_color, 0); - nsat_axis = newAxis("Satellites", nsat_units, gps_nsat_color, + nsat_axis = newAxis("Satellites", null, gps_nsat_color, AltosUIAxis.axis_include_zero | AltosUIAxis.axis_integer); - dbm_axis = newAxis("Signal Strength", dbm_units, dbm_color, 0); + dbm_axis = newAxis("Signal Strength", null, dbm_color, 0); distance_axis = newAxis("Distance", AltosConvert.distance, range_color); - gyro_axis = newAxis("Rotation Rate", gyro_units, gyro_z_color, 0); - orient_axis = newAxis("Tilt Angle", orient_units, orient_color, 0); - mag_axis = newAxis("Magnetic Field", mag_units, mag_x_color, 0); - course_axis = newAxis("Course", orient_units, gps_course_color, 0); + gyro_axis = newAxis("Rotation Rate", AltosConvert.rotation_rate, gyro_roll_color, 0); + orient_axis = newAxis("Tilt Angle", AltosConvert.orient, orient_color, 0); + mag_axis = newAxis("Magnetic Field", AltosConvert.magnetic_field, mag_along_color, 0); + course_axis = newAxis("Course", AltosConvert.orient, gps_course_color, 0); dop_axis = newAxis("Dilution of Precision", dop_units, gps_pdop_color, 0); - addMarker("State", AltosGraphDataPoint.data_state, state_color); - - if (stats.has_flight_data) { - addSeries("Height", - AltosGraphDataPoint.data_height, - AltosConvert.height, - height_color, - true, - height_axis); - addSeries("Pressure", - AltosGraphDataPoint.data_pressure, - pressure_units, - pressure_color, - false, - pressure_axis); - addSeries("Speed", - AltosGraphDataPoint.data_speed, - AltosConvert.speed, - speed_color, - true, - speed_axis); - addSeries("Acceleration", - AltosGraphDataPoint.data_accel, - AltosConvert.accel, - accel_color, - true, - accel_axis); - } - if (stats.has_gps) { - boolean enable_gps = false; - - if (!stats.has_flight_data) - enable_gps = true; - - addSeries("Range", - AltosGraphDataPoint.data_range, - AltosConvert.distance, - range_color, - false, - distance_axis); - addSeries("Distance", - AltosGraphDataPoint.data_distance, - AltosConvert.distance, - distance_color, - enable_gps, - distance_axis); - addSeries("GPS Height", - AltosGraphDataPoint.data_gps_height, - AltosConvert.height, - gps_height_color, - enable_gps, - height_axis); - addSeries("GPS Altitude", - AltosGraphDataPoint.data_gps_altitude, - AltosConvert.height, - gps_height_color, - false, - height_axis); - addSeries("GPS Satellites in Solution", - AltosGraphDataPoint.data_gps_nsat_solution, - nsat_units, - gps_nsat_solution_color, - false, - nsat_axis); - if (stats.has_gps_sats) { - addSeries("GPS Satellites in View", - AltosGraphDataPoint.data_gps_nsat_view, - nsat_units, - gps_nsat_view_color, - false, - nsat_axis); - } - if (stats.has_gps_detail) { - addSeries("GPS Course", - AltosGraphDataPoint.data_gps_course, - orient_units, - gps_course_color, - false, - course_axis); - addSeries("GPS Ground Speed", - AltosGraphDataPoint.data_gps_ground_speed, - AltosConvert.speed, - gps_ground_speed_color, - enable_gps, - speed_axis); - addSeries("GPS Climb Rate", - AltosGraphDataPoint.data_gps_climb_rate, - AltosConvert.speed, - gps_climb_rate_color, - enable_gps, - speed_axis); - } - addSeries("GPS Position DOP", - AltosGraphDataPoint.data_gps_pdop, - dop_units, - gps_pdop_color, - false, - dop_axis); - if (stats.has_gps_detail) { - addSeries("GPS Horizontal DOP", - AltosGraphDataPoint.data_gps_hdop, - dop_units, - gps_hdop_color, - false, - dop_axis); - addSeries("GPS Vertical DOP", - AltosGraphDataPoint.data_gps_vdop, - dop_units, - gps_vdop_color, - false, - dop_axis); - } - } - if (stats.has_rssi) - addSeries("Received Signal Strength", - AltosGraphDataPoint.data_rssi, - dbm_units, - dbm_color, - false, - dbm_axis); - - if (stats.has_battery) - addSeries("Battery Voltage", - AltosGraphDataPoint.data_battery_voltage, - voltage_units, - battery_voltage_color, - false, - voltage_axis); - - if (stats.has_flight_adc) { - addSeries("Temperature", - AltosGraphDataPoint.data_temperature, - AltosConvert.temperature, - temperature_color, - false, - temperature_axis); - addSeries("Drogue Voltage", - AltosGraphDataPoint.data_drogue_voltage, - voltage_units, - drogue_voltage_color, - false, - voltage_axis); - addSeries("Main Voltage", - AltosGraphDataPoint.data_main_voltage, - voltage_units, - main_voltage_color, - false, - voltage_axis); + flight_series.register_axis("default", + speed_color, + false, + speed_axis); + + flight_series.register_marker(AltosUIFlightSeries.state_name, + state_color, + true, + plot, + true); + + flight_series.register_marker(AltosUIFlightSeries.pyro_fired_name, + igniter_marker_color, + true, + plot, + false); + + flight_series.register_axis(AltosUIFlightSeries.accel_name, + accel_color, + true, + accel_axis); + + flight_series.register_axis(AltosUIFlightSeries.vert_accel_name, + vert_accel_color, + true, + accel_axis); + + flight_series.register_axis(AltosUIFlightSeries.kalman_accel_name, + kalman_accel_color, + false, + accel_axis); + + flight_series.register_axis(AltosUIFlightSeries.rssi_name, + dbm_color, + false, + dbm_axis); + + flight_series.register_axis(AltosUIFlightSeries.speed_name, + speed_color, + true, + speed_axis); + + flight_series.register_axis(AltosUIFlightSeries.kalman_speed_name, + kalman_speed_color, + true, + speed_axis); + + flight_series.register_axis(AltosUIFlightSeries.pressure_name, + pressure_color, + false, + pressure_axis); + + flight_series.register_axis(AltosUIFlightSeries.height_name, + height_color, + true, + height_axis); + + flight_series.register_axis(AltosUIFlightSeries.altitude_name, + height_color, + false, + height_axis); + + flight_series.register_axis(AltosUIFlightSeries.kalman_height_name, + kalman_height_color, + false, + height_axis); + + + flight_series.register_axis(AltosUIFlightSeries.temperature_name, + temperature_color, + false, + temperature_axis); + + flight_series.register_axis(AltosUIFlightSeries.battery_voltage_name, + battery_voltage_color, + false, + voltage_axis); + + flight_series.register_axis(AltosUIFlightSeries.apogee_voltage_name, + drogue_voltage_color, + false, + voltage_axis); + + flight_series.register_axis(AltosUIFlightSeries.main_voltage_name, + main_voltage_color, + false, + voltage_axis); + + flight_series.register_axis(AltosUIFlightSeries.sats_in_view_name, + gps_nsat_view_color, + false, + nsat_axis); + + flight_series.register_axis(AltosUIFlightSeries.sats_in_soln_name, + gps_nsat_solution_color, + false, + nsat_axis); + + flight_series.register_axis(AltosUIFlightSeries.gps_pdop_name, + gps_pdop_color, + false, + dop_axis); + + flight_series.register_axis(AltosUIFlightSeries.gps_hdop_name, + gps_hdop_color, + false, + dop_axis); + + flight_series.register_axis(AltosUIFlightSeries.gps_vdop_name, + gps_vdop_color, + false, + dop_axis); + + flight_series.register_axis(AltosUIFlightSeries.gps_altitude_name, + gps_height_color, + false, + height_axis); + + flight_series.register_axis(AltosUIFlightSeries.gps_height_name, + gps_height_color, + false, + height_axis); + + flight_series.register_axis(AltosUIFlightSeries.gps_ground_speed_name, + gps_ground_speed_color, + false, + speed_axis); + + flight_series.register_axis(AltosUIFlightSeries.gps_ascent_rate_name, + gps_climb_rate_color, + false, + speed_axis); + + flight_series.register_axis(AltosUIFlightSeries.gps_course_name, + gps_course_color, + false, + course_axis); + + flight_series.register_axis(AltosUIFlightSeries.gps_speed_name, + gps_speed_color, + false, + speed_axis); + + flight_series.register_axis(AltosUIFlightSeries.accel_along_name, + accel_along_color, + false, + accel_axis); + + flight_series.register_axis(AltosUIFlightSeries.accel_across_name, + accel_across_color, + false, + accel_axis); + + flight_series.register_axis(AltosUIFlightSeries.accel_through_name, + accel_through_color, + false, + accel_axis); + + flight_series.register_axis(AltosUIFlightSeries.gyro_roll_name, + gyro_roll_color, + false, + gyro_axis); + + flight_series.register_axis(AltosUIFlightSeries.gyro_pitch_name, + gyro_pitch_color, + false, + gyro_axis); + + flight_series.register_axis(AltosUIFlightSeries.gyro_yaw_name, + gyro_yaw_color, + false, + gyro_axis); + + flight_series.register_axis(AltosUIFlightSeries.mag_along_name, + mag_along_color, + false, + mag_axis); + + flight_series.register_axis(AltosUIFlightSeries.mag_across_name, + mag_across_color, + false, + mag_axis); + + flight_series.register_axis(AltosUIFlightSeries.mag_through_name, + mag_through_color, + false, + mag_axis); + + flight_series.register_axis(AltosUIFlightSeries.orient_name, + orient_color, + false, + orient_axis); + + for (int channel = 0; channel < 26; channel++) { + flight_series.register_axis(flight_series.igniter_voltage_name(channel), + igniter_voltage_color, + false, + voltage_axis); } - if (stats.has_imu) { - addSeries("Acceleration Along", - AltosGraphDataPoint.data_accel_along, - AltosConvert.accel, - accel_x_color, - false, - accel_axis); - addSeries("Acceleration Across", - AltosGraphDataPoint.data_accel_across, - AltosConvert.accel, - accel_y_color, - false, - accel_axis); - addSeries("Acceleration Through", - AltosGraphDataPoint.data_accel_through, - AltosConvert.accel, - accel_z_color, - false, - accel_axis); - addSeries("Roll Rate", - AltosGraphDataPoint.data_gyro_roll, - gyro_units, - gyro_x_color, - false, - gyro_axis); - addSeries("Pitch Rate", - AltosGraphDataPoint.data_gyro_pitch, - gyro_units, - gyro_y_color, - false, - gyro_axis); - addSeries("Yaw Rate", - AltosGraphDataPoint.data_gyro_yaw, - gyro_units, - gyro_z_color, - false, - gyro_axis); - } - if (stats.has_mag) { - addSeries("Magnetometer Along", - AltosGraphDataPoint.data_mag_along, - mag_units, - mag_x_color, - false, - mag_axis); - addSeries("Magnetometer Across", - AltosGraphDataPoint.data_mag_across, - mag_units, - mag_y_color, - false, - mag_axis); - addSeries("Magnetometer Through", - AltosGraphDataPoint.data_mag_through, - mag_units, - mag_z_color, - false, - mag_axis); - } - if (stats.has_orient) - addSeries("Tilt Angle", - AltosGraphDataPoint.data_orient, - orient_units, - orient_color, - false, - orient_axis); - if (stats.num_ignitor > 0) { - for (int i = 0; i < stats.num_ignitor; i++) - addSeries(AltosLib.ignitor_name(i), - AltosGraphDataPoint.data_ignitor_0 + i, - voltage_units, - main_voltage_color, - false, - voltage_axis); - for (int i = 0; i < stats.num_ignitor; i++) - addMarker(AltosLib.ignitor_name(i), AltosGraphDataPoint.data_ignitor_fired_0 + i, state_color); - } + flight_series.register_axis(AltosUIFlightSeries.thrust_name, + thrust_color, + true, + thrust_axis); + + return flight_series.series(cal_data); + } + + public void set_data(AltosFlightStats stats, AltosUIFlightSeries flight_series) { + set_series(setup(stats, flight_series)); + } + + public AltosGraph(AltosUIEnable enable) { + super(enable, "Flight"); + } - setDataSet(dataSet); + public AltosGraph(AltosUIEnable enable, AltosFlightStats stats, AltosUIFlightSeries flight_series) { + this(enable); + set_series(setup(stats, flight_series)); } } diff --git a/altosuilib/AltosGraphDataPoint.java b/altosuilib/AltosGraphDataPoint.java deleted file mode 100644 index 0012d96a..00000000 --- a/altosuilib/AltosGraphDataPoint.java +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright © 2013 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.altosuilib_11; - -import org.altusmetrum.altoslib_11.*; - -public class AltosGraphDataPoint implements AltosUIDataPoint { - - AltosState state; - - public static final int data_height = 0; - public static final int data_speed = 1; - public static final int data_accel = 2; - public static final int data_temp = 3; - public static final int data_battery_voltage = 4; - public static final int data_drogue_voltage = 5; - public static final int data_main_voltage = 6; - public static final int data_rssi = 7; - public static final int data_state = 8; - public static final int data_gps_height = 9; - public static final int data_gps_nsat_solution = 10; - public static final int data_gps_nsat_view = 11; - public static final int data_gps_altitude = 12; - public static final int data_temperature = 13; - public static final int data_range = 14; - public static final int data_distance = 15; - public static final int data_pressure = 16; - public static final int data_accel_along = 17; - public static final int data_accel_across = 18; - public static final int data_accel_through = 19; - public static final int data_gyro_roll = 20; - public static final int data_gyro_pitch = 21; - public static final int data_gyro_yaw = 22; - public static final int data_mag_along = 23; - public static final int data_mag_across = 24; - public static final int data_mag_through = 25; - public static final int data_orient = 26; - public static final int data_gps_course = 27; - public static final int data_gps_ground_speed = 28; - public static final int data_gps_climb_rate = 29; - public static final int data_gps_pdop = 30; - public static final int data_gps_hdop = 31; - public static final int data_gps_vdop = 32; - public static final int data_ignitor_0 = 33; - public static final int data_ignitor_num = 32; - public static final int data_ignitor_max = data_ignitor_0 + data_ignitor_num - 1; - public static final int data_ignitor_fired_0 = data_ignitor_0 + data_ignitor_num; - public static final int data_ignitor_fired_max = data_ignitor_fired_0 + data_ignitor_num - 1; - - public double x() throws AltosUIDataMissing { - double time = state.time_since_boost(); - if (time < -2) - throw new AltosUIDataMissing(-1); - return time; - } - - public double y(int index) throws AltosUIDataMissing { - double y = AltosLib.MISSING; - switch (index) { - case data_height: - y = state.height(); - break; - case data_speed: - y = state.speed(); - break; - case data_accel: - y = state.acceleration(); - break; - case data_temp: - y = state.temperature; - break; - case data_battery_voltage: - y = state.battery_voltage; - break; - case data_drogue_voltage: - y = state.apogee_voltage; - break; - case data_main_voltage: - y = state.main_voltage; - break; - case data_rssi: - y = state.rssi; - break; - case data_gps_height: - y = state.gps_height; - break; - case data_gps_nsat_solution: - if (state.gps != null) - y = state.gps.nsat; - break; - case data_gps_nsat_view: - if (state.gps != null) { - if (state.gps.cc_gps_sat != null) - y = state.gps.cc_gps_sat.length; - else - y = 0; - } - break; - case data_gps_altitude: - y = state.gps_altitude(); - break; - case data_temperature: - y = state.temperature; - break; - case data_range: - y = state.range; - break; - case data_distance: - if (state.from_pad != null) - y = state.from_pad.distance; - break; - case data_pressure: - y = state.pressure(); - break; - - case data_accel_along: - y = state.accel_along(); - break; - case data_accel_across: - y = state.accel_across(); - break; - case data_accel_through: - y = state.accel_through(); - break; - case data_gyro_roll: - y = state.gyro_roll(); - break; - case data_gyro_pitch: - y = state.gyro_pitch(); - break; - case data_gyro_yaw: - y = state.gyro_yaw(); - break; - case data_mag_along: - y = state.mag_along(); - break; - case data_mag_across: - y = state.mag_across(); - break; - case data_mag_through: - y = state.mag_through(); - break; - case data_orient: - y = state.orient(); - break; - case data_gps_course: - if (state.gps != null) - y = state.gps.course; - else - y = AltosLib.MISSING; - break; - case data_gps_ground_speed: - if (state.gps != null) - y = state.gps.ground_speed; - else - y = AltosLib.MISSING; - break; - case data_gps_climb_rate: - if (state.gps != null) - y = state.gps.climb_rate; - else - y = AltosLib.MISSING; - break; - case data_gps_pdop: - if (state.gps != null) - y = state.gps.pdop; - else - y = AltosLib.MISSING; - break; - case data_gps_hdop: - if (state.gps != null) - y = state.gps.hdop; - else - y = AltosLib.MISSING; - break; - case data_gps_vdop: - if (state.gps != null) - y = state.gps.vdop; - else - y = AltosLib.MISSING; - break; - default: - if (data_ignitor_0 <= index && index <= data_ignitor_max) { - int ignitor = index - data_ignitor_0; - if (state.ignitor_voltage != null && ignitor < state.ignitor_voltage.length) - y = state.ignitor_voltage[ignitor]; - } else if (data_ignitor_fired_0 <= index && index <= data_ignitor_fired_max) { - int ignitor = index - data_ignitor_fired_0; - if (state.ignitor_voltage != null && ignitor < state.ignitor_voltage.length) { - if ((state.pyro_fired & (1 << ignitor)) != 0) - y = 1; - else - y = 0; - } - } - break; - } - if (y == AltosLib.MISSING) - throw new AltosUIDataMissing(index); - return y; - } - - public int id(int index) { - if (index == data_state) { - int s = state.state(); - if (AltosLib.ao_flight_boost <= s && s <= AltosLib.ao_flight_landed) - return s; - } else if (data_ignitor_fired_0 <= index && index <= data_ignitor_fired_max) { - int ignitor = index - data_ignitor_fired_0; - if (state.ignitor_voltage != null && ignitor < state.ignitor_voltage.length) { - if (state.ignitor_voltage != null && ignitor < state.ignitor_voltage.length) { - if ((state.pyro_fired & (1 << ignitor)) != 0) - return 1; - } - } - } - return -1; - } - - public String id_name(int index) { - if (index == data_state) { - return state.state_name(); - } else if (data_ignitor_fired_0 <= index && index <= data_ignitor_fired_max) { - int ignitor = index - data_ignitor_fired_0; - if (state.ignitor_voltage != null && ignitor < state.ignitor_voltage.length) - return AltosLib.ignitor_name(ignitor); - } - return ""; - } - - public AltosGraphDataPoint (AltosState state) { - this.state = state; - } -} diff --git a/altosuilib/AltosGraphDataSet.java b/altosuilib/AltosGraphDataSet.java deleted file mode 100644 index 065a7815..00000000 --- a/altosuilib/AltosGraphDataSet.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright © 2013 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.altosuilib_11; - -import java.lang.*; -import java.io.*; -import java.util.*; -import org.altusmetrum.altoslib_11.*; - -class AltosGraphIterator implements Iterator { - AltosGraphDataSet dataSet; - Iterator iterator; - - public boolean hasNext() { - return iterator.hasNext(); - } - - public AltosUIDataPoint next() { - AltosState state = iterator.next(); - - if (state.flight != AltosLib.MISSING) { - if (dataSet.callsign == null && state.callsign != null) - dataSet.callsign = state.callsign; - - if (dataSet.serial == 0 && state.serial != 0) - dataSet.serial = state.serial; - - if (dataSet.flight == 0 && state.flight != 0) - dataSet.flight = state.flight; - } - - return new AltosGraphDataPoint(state); - } - - public AltosGraphIterator (Iterator iterator, AltosGraphDataSet dataSet) { - this.iterator = iterator; - this.dataSet = dataSet; - } - - public void remove() { - } -} - -class AltosGraphIterable implements Iterable { - AltosGraphDataSet dataSet; - - public Iterator iterator() { - return new AltosGraphIterator(dataSet.states.iterator(), dataSet); - } - - public AltosGraphIterable(AltosGraphDataSet dataSet) { - this.dataSet = dataSet; - } -} - -public class AltosGraphDataSet implements AltosUIDataSet { - String callsign; - int serial; - int flight; - AltosStateIterable states; - - public String name() { - if (callsign != null) - return String.format("%s - %d/%d", callsign, serial, flight); - else - return String.format("%d/%d", serial, flight); - } - - public Iterable dataPoints() { - return new AltosGraphIterable(this); - } - - public AltosGraphDataSet (AltosStateIterable states) { - this.states = states; - this.callsign = null; - this.serial = 0; - this.flight = 0; - } -} diff --git a/altosuilib/AltosInfoTable.java b/altosuilib/AltosInfoTable.java index 7ede2824..9e528b1f 100644 --- a/altosuilib/AltosInfoTable.java +++ b/altosuilib/AltosInfoTable.java @@ -16,13 +16,13 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.table.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class AltosInfoTable extends JTable implements AltosFlightDisplay, HierarchyListener { private AltosFlightInfoTableModel model; @@ -128,6 +128,8 @@ public class AltosInfoTable extends JTable implements AltosFlightDisplay, Hierar public void show(AltosState state, AltosListenerState listener_state) { + AltosCalData cal_data = state.cal_data(); + if (!isShowing()) { last_state = state; last_listener_state = listener_state; @@ -136,14 +138,14 @@ public class AltosInfoTable extends JTable implements AltosFlightDisplay, Hierar reset(); if (state != null) { - if (state.device_type != AltosLib.MISSING) - info_add_row(0, "Device", "%s", AltosLib.product_name(state.device_type)); - else if (state.product != null) - info_add_row(0, "Device", "%s", state.product); + if (cal_data.device_type != AltosLib.MISSING) + info_add_row(0, "Device", "%s", AltosLib.product_name(cal_data.device_type)); + else if (cal_data.product != null) + info_add_row(0, "Device", "%s", cal_data.product); if (state.altitude() != AltosLib.MISSING) info_add_row(0, "Altitude", "%6.0f m", state.altitude()); - if (state.ground_altitude() != AltosLib.MISSING) - info_add_row(0, "Pad altitude", "%6.0f m", state.ground_altitude()); + if (cal_data.ground_altitude != AltosLib.MISSING) + info_add_row(0, "Pad altitude", "%6.0f m", cal_data.ground_altitude); if (state.height() != AltosLib.MISSING) info_add_row(0, "Height", "%6.0f m", state.height()); if (state.max_height() != AltosLib.MISSING) diff --git a/altosuilib/AltosLed.java b/altosuilib/AltosLed.java index c06e45e5..b53e7604 100644 --- a/altosuilib/AltosLed.java +++ b/altosuilib/AltosLed.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import javax.swing.*; diff --git a/altosuilib/AltosLights.java b/altosuilib/AltosLights.java index 394cfc67..7b02d770 100644 --- a/altosuilib/AltosLights.java +++ b/altosuilib/AltosLights.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.awt.*; import javax.swing.*; diff --git a/altosuilib/AltosPositionListener.java b/altosuilib/AltosPositionListener.java index 8c4d2516..f44735e2 100644 --- a/altosuilib/AltosPositionListener.java +++ b/altosuilib/AltosPositionListener.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; public interface AltosPositionListener { public void position_changed(int position); diff --git a/altosuilib/AltosRomconfigUI.java b/altosuilib/AltosRomconfigUI.java index c1b8ac26..74323218 100644 --- a/altosuilib/AltosRomconfigUI.java +++ b/altosuilib/AltosRomconfigUI.java @@ -16,12 +16,12 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.awt.*; import java.awt.event.*; import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class AltosRomconfigUI extends AltosUIDialog diff --git a/altosuilib/AltosScanUI.java b/altosuilib/AltosScanUI.java index 8843429a..c63f027c 100644 --- a/altosuilib/AltosScanUI.java +++ b/altosuilib/AltosScanUI.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.awt.*; import java.awt.event.*; @@ -26,7 +26,7 @@ import java.io.*; import java.util.*; import java.text.*; import java.util.concurrent.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; class AltosScanResult { String callsign; @@ -213,10 +213,11 @@ public class AltosScanUI if (state == null) continue; packet_count++; - if (state.flight != AltosLib.MISSING) { - final AltosScanResult result = new AltosScanResult(state.callsign, - state.serial, - state.flight, + AltosCalData cal_data = state.cal_data(); + if (cal_data.flight != AltosLib.MISSING) { + final AltosScanResult result = new AltosScanResult(cal_data.callsign, + cal_data.serial, + cal_data.flight, frequencies[frequency_index], telemetry, rate); diff --git a/altosuilib/AltosSerial.java b/altosuilib/AltosSerial.java index 5c32a7d8..d7c6129c 100644 --- a/altosuilib/AltosSerial.java +++ b/altosuilib/AltosSerial.java @@ -20,13 +20,13 @@ * Deal with TeleDongle on a serial port */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.io.*; import java.util.*; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; import libaltosJNI.*; /* diff --git a/altosuilib/AltosSerialInUseException.java b/altosuilib/AltosSerialInUseException.java index e0de8ad7..c8ca4d56 100644 --- a/altosuilib/AltosSerialInUseException.java +++ b/altosuilib/AltosSerialInUseException.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; public class AltosSerialInUseException extends Exception { public AltosDevice device; diff --git a/altosuilib/AltosUIAxis.java b/altosuilib/AltosUIAxis.java index e41667ef..fe94f161 100644 --- a/altosuilib/AltosUIAxis.java +++ b/altosuilib/AltosUIAxis.java @@ -16,14 +16,14 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.io.*; import java.util.ArrayList; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; import org.jfree.ui.*; import org.jfree.chart.*; @@ -49,11 +49,14 @@ public class AltosUIAxis extends NumberAxis { public final static int axis_default = axis_include_zero; public void set_units() { - String u = units.parse_units(); - if (u != null) - setLabel(String.format("%s (%s)", label, u)); - else - setLabel(label); + if (units != null) { + String u = units.parse_units(); + if (u != null) { + setLabel(String.format("%s (%s)", label, u)); + return; + } + } + setLabel(label); } public void set_enable(boolean enable) { diff --git a/altosuilib/AltosUIConfigure.java b/altosuilib/AltosUIConfigure.java index 19512f49..e3d86724 100644 --- a/altosuilib/AltosUIConfigure.java +++ b/altosuilib/AltosUIConfigure.java @@ -16,14 +16,14 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.awt.*; import java.awt.event.*; import java.beans.*; import javax.swing.*; import javax.swing.event.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; class DelegatingRenderer implements ListCellRenderer { diff --git a/altosuilib/AltosUIDataMissing.java b/altosuilib/AltosUIDataMissing.java index a59cc0a0..05227e1d 100644 --- a/altosuilib/AltosUIDataMissing.java +++ b/altosuilib/AltosUIDataMissing.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; public class AltosUIDataMissing extends Exception { public int id; diff --git a/altosuilib/AltosUIDataPoint.java b/altosuilib/AltosUIDataPoint.java index 4107feae..36fadeaf 100644 --- a/altosuilib/AltosUIDataPoint.java +++ b/altosuilib/AltosUIDataPoint.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; public interface AltosUIDataPoint { public abstract double x() throws AltosUIDataMissing; diff --git a/altosuilib/AltosUIDataSet.java b/altosuilib/AltosUIDataSet.java index ffab46c1..ddda3d3d 100644 --- a/altosuilib/AltosUIDataSet.java +++ b/altosuilib/AltosUIDataSet.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; public interface AltosUIDataSet { public abstract String name(); diff --git a/altosuilib/AltosUIDialog.java b/altosuilib/AltosUIDialog.java index 85b40229..5eafa457 100644 --- a/altosuilib/AltosUIDialog.java +++ b/altosuilib/AltosUIDialog.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.awt.*; import java.awt.event.*; diff --git a/altosuilib/AltosUIEnable.java b/altosuilib/AltosUIEnable.java index 4c733b96..0c23fa8d 100644 --- a/altosuilib/AltosUIEnable.java +++ b/altosuilib/AltosUIEnable.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.awt.*; import java.awt.event.*; @@ -24,7 +24,7 @@ import javax.swing.*; import java.io.*; import java.util.concurrent.*; import java.util.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; import org.jfree.ui.*; import org.jfree.chart.*; diff --git a/altosuilib/AltosUIFlightSeries.java b/altosuilib/AltosUIFlightSeries.java new file mode 100644 index 00000000..19bed609 --- /dev/null +++ b/altosuilib/AltosUIFlightSeries.java @@ -0,0 +1,124 @@ +/* + * Copyright © 2017 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +package org.altusmetrum.altosuilib_12; + +import java.util.*; +import java.awt.*; +import javax.swing.*; +import org.altusmetrum.altoslib_12.*; + +import org.jfree.ui.*; +import org.jfree.chart.*; +import org.jfree.chart.plot.*; +import org.jfree.chart.axis.*; +import org.jfree.chart.renderer.*; +import org.jfree.chart.renderer.xy.*; +import org.jfree.chart.labels.*; +import org.jfree.data.xy.*; +import org.jfree.data.*; + +class AltosUITimeSeriesAxis { + Color color; + boolean enabled; + boolean marker; + boolean marker_top; + AltosUIAxis axis; + XYPlot plot; + + public AltosUITimeSeriesAxis(Color color, boolean enabled, AltosUIAxis axis, XYPlot plot, boolean marker, boolean marker_top) { + this.color = color; + this.enabled = enabled; + this.axis = axis; + this.plot = plot; + this.marker = marker; + this.marker_top = marker_top; + } +} + +public class AltosUIFlightSeries extends AltosFlightSeries { + + Hashtable axes; + + AltosUIFlightSeries flight_series; + + void fill_axes(String label, AltosUITimeSeriesAxis axis) { + for (AltosTimeSeries ts : series) { + AltosUITimeSeries uts = (AltosUITimeSeries) ts; + + if (label.equals(ts.label) || (label.equals("default") && uts.color == null)) { + if (axis.marker) + uts.set_marker(axis.color, axis.enabled, axis.plot, axis.marker_top); + else + uts.set_axis(axis.color, axis.enabled, axis.axis); + } + } + } + + public void register_axis(String label, + Color color, + boolean enabled, + AltosUIAxis axis) { + AltosUITimeSeriesAxis tsa = new AltosUITimeSeriesAxis(color, + enabled, + axis, + null, + false, + false); + axes.put(label, tsa); + fill_axes(label, tsa); + } + + public void register_marker(String label, + Color color, + boolean enabled, + XYPlot plot, + boolean marker_top) { + AltosUITimeSeriesAxis tsa = new AltosUITimeSeriesAxis(color, + enabled, + null, + plot, + true, + marker_top); + axes.put(label, tsa); + fill_axes(label, tsa); + } + + public AltosTimeSeries make_series(String label, AltosUnits units) { + + + AltosUITimeSeries time_series = new AltosUITimeSeries(label, units); + + AltosUITimeSeriesAxis tsa = axes.get(label); + if (tsa == null) + tsa = axes.get("default"); + if (tsa != null) { + if (tsa.marker) + time_series.set_marker(tsa.color, tsa.enabled, tsa.plot, tsa.marker_top); + else + time_series.set_axis(tsa.color, tsa.enabled, tsa.axis); + } + return time_series; + } + + public AltosUITimeSeries[] series(AltosCalData cal_data) { + finish(); + return series.toArray(new AltosUITimeSeries[0]); + } + + public AltosUIFlightSeries (AltosCalData cal_data) { + super(cal_data); + axes = new Hashtable(); + } +} diff --git a/altosuilib/AltosUIFlightTab.java b/altosuilib/AltosUIFlightTab.java index 3adbdb33..cf6a0c74 100644 --- a/altosuilib/AltosUIFlightTab.java +++ b/altosuilib/AltosUIFlightTab.java @@ -16,13 +16,13 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.util.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public abstract class AltosUIFlightTab extends JComponent implements AltosFlightDisplay, HierarchyListener { public GridBagLayout layout; diff --git a/altosuilib/AltosUIFrame.java b/altosuilib/AltosUIFrame.java index e5007fff..b7eee664 100644 --- a/altosuilib/AltosUIFrame.java +++ b/altosuilib/AltosUIFrame.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.awt.*; import java.awt.event.*; diff --git a/altosuilib/AltosUIFreqList.java b/altosuilib/AltosUIFreqList.java index 4dd9fece..7a5c3543 100644 --- a/altosuilib/AltosUIFreqList.java +++ b/altosuilib/AltosUIFreqList.java @@ -16,10 +16,10 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class AltosUIFreqList extends JComboBox { diff --git a/altosuilib/AltosUIGraph.java b/altosuilib/AltosUIGraph.java index d3760384..0caabcfa 100644 --- a/altosuilib/AltosUIGraph.java +++ b/altosuilib/AltosUIGraph.java @@ -16,14 +16,15 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.io.*; +import java.util.*; import java.util.ArrayList; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; import org.jfree.ui.*; import org.jfree.chart.*; @@ -42,10 +43,10 @@ public class AltosUIGraph implements AltosUnitsListener { public ChartPanel panel; NumberAxis xAxis; AltosUIEnable enable; - ArrayList graphers; - AltosUIDataSet dataSet; + AltosUITimeSeries[] series; int axis_index; int series_index; + Hashtable axes_added; static final private Color gridline_color = new Color(0, 0, 0); static final private Color border_color = new Color(255, 255, 255); @@ -65,70 +66,65 @@ public class AltosUIGraph implements AltosUnitsListener { return newAxis(label, units, color, AltosUIAxis.axis_default); } - public void addSeries(String label, int fetch, AltosUnits units, Color color, - boolean enabled, AltosUIAxis axis) { - AltosUISeries series = new AltosUISeries(label, fetch, units, color, enabled, axis); - XYSeriesCollection dataset = new XYSeriesCollection(series); + void addAxis(AltosUIAxis axis) { + if (!axes_added.containsKey(axis.index)) { + axes_added.put(axis.index, true); + plot.setRangeAxis(axis.index, axis); + } + } + + public void addSeries(AltosUITimeSeries series) { + XYSeriesCollection dataset = new XYSeriesCollection(series.xy_series()); + + addAxis(series.axis); series.renderer.setPlot(plot); plot.setDataset(series_index, dataset); plot.setRenderer(series_index, series.renderer); - plot.mapDatasetToRangeAxis(series_index, axis.index); + plot.mapDatasetToRangeAxis(series_index, series.axis.index); if (enable != null) - enable.add(label, series, enabled); - this.graphers.add(series); + enable.add(series.label, series, series.enable); series_index++; } - public void addSeries(String label, int fetch, AltosUnits units, Color color) { - addSeries(label, fetch, units, color, true, newAxis(label, units, color)); - } - - public void addMarker(String label, int fetch, Color color) { - AltosUIMarker marker = new AltosUIMarker(fetch, color, plot); - this.graphers.add(marker); - } - - public void resetData() { - for (AltosUIGrapher g : graphers) { - g.clear(); - g.setNotify(false); - } - if (dataSet != null) { - for (AltosUIDataPoint dataPoint : dataSet.dataPoints()) - for (AltosUIGrapher g : graphers) - g.add(dataPoint); - } - for (AltosUIGrapher g : graphers) { - g.setNotify(true); - g.fireSeriesChanged(); - } + public void addMarker(AltosUITimeSeries series) { } public void units_changed(boolean imperial_units) { - for (AltosUIGrapher g : graphers) - g.set_units(); - resetData(); + for (AltosUITimeSeries s : series) + s.set_units(); } public void setName (String name) { chart.setTitle(name); } - public void setDataSet (AltosUIDataSet dataSet) { - this.dataSet = dataSet; - resetData(); - if (dataSet != null) - setName(dataSet.name()); + public void set_series(AltosUITimeSeries[] series) { + this.series = series; + boolean any_enabled = false; + + for (AltosUITimeSeries s : series) + if (s.enable) + any_enabled = true; + + if (!any_enabled) + for (AltosUITimeSeries s : series) + s.set_enable(true); + + for (AltosUITimeSeries s : series) + addSeries(s); + + units_changed(false); } - public AltosUIGraph(AltosUIEnable enable) { + public AltosUIGraph(AltosUIEnable enable, String title) { this.enable = enable; - this.graphers = new ArrayList(); - this.series_index = 0; + this.series = null; this.axis_index = 0; + axes_added = new Hashtable(); + xAxis = new NumberAxis("Time (s)"); xAxis.setAutoRangeIncludesZero(true); @@ -139,7 +135,7 @@ public class AltosUIGraph implements AltosUnitsListener { plot.setDomainPannable(true); plot.setRangePannable(true); - chart = new JFreeChart("Flight", JFreeChart.DEFAULT_TITLE_FONT, + chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, true); ChartUtilities.applyCurrentTheme(chart); @@ -156,5 +152,6 @@ public class AltosUIGraph implements AltosUnitsListener { panel.setPreferredSize(new java.awt.Dimension(800, 500)); AltosPreferences.register_units_listener(this); + } } diff --git a/altosuilib/AltosUIGrapher.java b/altosuilib/AltosUIGrapher.java index 07358144..916d0b3f 100644 --- a/altosuilib/AltosUIGrapher.java +++ b/altosuilib/AltosUIGrapher.java @@ -16,14 +16,14 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.io.*; import java.util.ArrayList; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; import org.jfree.ui.*; import org.jfree.chart.*; @@ -39,6 +39,8 @@ interface AltosUIGrapher { public abstract void set_units(); + public abstract boolean need_reset(); + public abstract void clear(); public abstract void add(AltosUIDataPoint dataPoint); diff --git a/altosuilib/AltosUIImage.java b/altosuilib/AltosUIImage.java index b157a2ce..f23b50bc 100644 --- a/altosuilib/AltosUIImage.java +++ b/altosuilib/AltosUIImage.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; import javax.swing.*; import javax.imageio.ImageIO; diff --git a/altosuilib/AltosUIIndicator.java b/altosuilib/AltosUIIndicator.java index f47a2f29..ac2e6f06 100644 --- a/altosuilib/AltosUIIndicator.java +++ b/altosuilib/AltosUIIndicator.java @@ -16,11 +16,11 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public abstract class AltosUIIndicator implements AltosFontListener, AltosUnitsListener { JLabel label; diff --git a/altosuilib/AltosUILib.java b/altosuilib/AltosUILib.java index 0c5fa1c7..ef706e36 100644 --- a/altosuilib/AltosUILib.java +++ b/altosuilib/AltosUILib.java @@ -16,12 +16,12 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.awt.*; import libaltosJNI.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class AltosUILib extends AltosLib { diff --git a/altosuilib/AltosUIListener.java b/altosuilib/AltosUIListener.java index 55ce584a..54a00661 100644 --- a/altosuilib/AltosUIListener.java +++ b/altosuilib/AltosUIListener.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; public interface AltosUIListener { public void ui_changed(String look_and_feel); diff --git a/altosuilib/AltosUIMap.java b/altosuilib/AltosUIMap.java index 3e4cbe9b..2e1e8f16 100644 --- a/altosuilib/AltosUIMap.java +++ b/altosuilib/AltosUIMap.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.awt.*; import java.awt.event.*; @@ -28,7 +28,7 @@ import java.awt.geom.*; import java.util.*; import java.util.concurrent.*; import javax.imageio.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosMapInterface { @@ -413,6 +413,10 @@ public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosM map.show(state, listener_state); } + public void show(AltosGPS gps, int state) { + map.show(gps, state); + } + public String getName() { return "Map"; } @@ -422,6 +426,10 @@ public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosM map.centre(state); } + public void centre(AltosGPS gps) { + map.centre(gps); + } + /* internal layout bits */ private GridBagLayout layout = new GridBagLayout(); diff --git a/altosuilib/AltosUIMapPreload.java b/altosuilib/AltosUIMapPreload.java index 06c4c59b..81cda0d2 100644 --- a/altosuilib/AltosUIMapPreload.java +++ b/altosuilib/AltosUIMapPreload.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.awt.*; import java.awt.event.*; @@ -27,7 +27,7 @@ import java.text.*; import java.lang.Math; import java.net.URL; import java.net.URLConnection; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; class AltosUIMapPos extends Box implements ActionListener { AltosUIMapPreload preload; diff --git a/altosuilib/AltosUIMarker.java b/altosuilib/AltosUIMarker.java index 9d8dde60..90cdb291 100644 --- a/altosuilib/AltosUIMarker.java +++ b/altosuilib/AltosUIMarker.java @@ -16,14 +16,14 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.io.*; import java.util.ArrayList; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; import org.jfree.ui.*; import org.jfree.chart.*; @@ -56,6 +56,8 @@ public class AltosUIMarker implements AltosUIGrapher { public void set_units() { } + public boolean need_reset() { return true; } + public void set_enable(boolean enable) { if (enabled == enable) return; @@ -110,4 +112,4 @@ public class AltosUIMarker implements AltosUIGrapher { public AltosUIMarker (int fetch, Color color, XYPlot plot) { this(fetch, color, plot, true); } -} \ No newline at end of file +} diff --git a/altosuilib/AltosUIPreferences.java b/altosuilib/AltosUIPreferences.java index c8ae9a7d..a2014065 100644 --- a/altosuilib/AltosUIPreferences.java +++ b/altosuilib/AltosUIPreferences.java @@ -16,13 +16,13 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.io.*; import java.util.*; import java.awt.Component; import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class AltosUIPreferences extends AltosPreferences { diff --git a/altosuilib/AltosUIPreferencesBackend.java b/altosuilib/AltosUIPreferencesBackend.java index 6dd2baaf..163ba173 100644 --- a/altosuilib/AltosUIPreferencesBackend.java +++ b/altosuilib/AltosUIPreferencesBackend.java @@ -16,11 +16,11 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.io.File; import java.util.prefs.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; import javax.swing.filechooser.FileSystemView; public class AltosUIPreferencesBackend extends AltosPreferencesBackend { diff --git a/altosuilib/AltosUIRateList.java b/altosuilib/AltosUIRateList.java index 187977d3..d1c15ce0 100644 --- a/altosuilib/AltosUIRateList.java +++ b/altosuilib/AltosUIRateList.java @@ -16,10 +16,10 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class AltosUIRateList extends JComboBox { @@ -27,10 +27,9 @@ public class AltosUIRateList extends JComboBox { int serial; public void set_rate(int new_rate) { - int i; - - setVisible(new_rate >= 0); - setSelectedIndex(new_rate); + if (new_rate != AltosLib.MISSING) + setSelectedIndex(new_rate); + setVisible(new_rate != AltosLib.MISSING); } public void set_product(String new_product) { diff --git a/altosuilib/AltosUISeries.java b/altosuilib/AltosUISeries.java deleted file mode 100644 index 66cc7d69..00000000 --- a/altosuilib/AltosUISeries.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright © 2013 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.altosuilib_11; - -import java.io.*; -import java.util.ArrayList; - -import java.awt.*; -import javax.swing.*; -import org.altusmetrum.altoslib_11.*; - -import org.jfree.ui.*; -import org.jfree.chart.*; -import org.jfree.chart.plot.*; -import org.jfree.chart.axis.*; -import org.jfree.chart.renderer.*; -import org.jfree.chart.renderer.xy.*; -import org.jfree.chart.labels.*; -import org.jfree.data.xy.*; -import org.jfree.data.*; - -class AltosUITime extends AltosUnits { - public double value(double v, boolean imperial_units) { return v; } - - public double inverse(double v, boolean imperial_unis) { return v; } - - public String show_units(boolean imperial_units) { return "s"; } - - public String say_units(boolean imperial_units) { return "seconds"; } - - public int show_fraction(int width, boolean imperial_units) { - if (width < 5) - return 0; - return width - 5; - } - - public int say_fraction(boolean imperial_units) { return 0; } -} - -public class AltosUISeries extends XYSeries implements AltosUIGrapher { - AltosUIAxis axis; - String label; - AltosUnits units; - Color color; - XYItemRenderer renderer; - int fetch; - boolean enable; - - public void set_units() { - axis.set_units(); - StandardXYToolTipGenerator ttg; - - String time_example = (new AltosUITime()).graph_format(7); - String example = units.graph_format(7); - - ttg = new StandardXYToolTipGenerator(String.format("{1}s: {2}%s ({0})", - units.graph_units()), - new java.text.DecimalFormat(time_example), - new java.text.DecimalFormat(example)); - renderer.setBaseToolTipGenerator(ttg); - } - - public void set_enable(boolean enable) { - if (this.enable != enable) { - this.enable = enable; - renderer.setSeriesVisible(0, enable); - axis.set_enable(enable); - } - } - - public void add(AltosUIDataPoint dataPoint) { - try { - super.add(dataPoint.x(), units.graph_value(dataPoint.y(fetch))); - } catch (AltosUIDataMissing dm) { - } - } - - public AltosUISeries (String label, int fetch, AltosUnits units, Color color, - boolean enable, AltosUIAxis axis) { - super(label); - this.label = label; - this.fetch = fetch; - this.units = units; - this.color = color; - this.enable = enable; - this.axis = axis; - - axis.ref(this.enable); - - renderer = new XYLineAndShapeRenderer(true, false); - renderer.setSeriesPaint(0, color); - renderer.setSeriesStroke(0, new BasicStroke(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); - renderer.setSeriesVisible(0, enable); - set_units(); - } -} diff --git a/altosuilib/AltosUITelemetryList.java b/altosuilib/AltosUITelemetryList.java index f02d2f7f..f884cd41 100644 --- a/altosuilib/AltosUITelemetryList.java +++ b/altosuilib/AltosUITelemetryList.java @@ -16,11 +16,11 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.util.*; import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class AltosUITelemetryList extends JComboBox { diff --git a/altosuilib/AltosUITimeSeries.java b/altosuilib/AltosUITimeSeries.java new file mode 100644 index 00000000..08f95ca7 --- /dev/null +++ b/altosuilib/AltosUITimeSeries.java @@ -0,0 +1,200 @@ +/* + * Copyright © 2017 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_12; + +import java.io.*; +import java.util.ArrayList; + +import java.awt.*; +import javax.swing.*; +import org.altusmetrum.altoslib_12.*; + +import org.jfree.ui.*; +import org.jfree.chart.*; +import org.jfree.chart.plot.*; +import org.jfree.chart.axis.*; +import org.jfree.chart.renderer.*; +import org.jfree.chart.renderer.xy.*; +import org.jfree.chart.labels.*; +import org.jfree.data.xy.*; +import org.jfree.data.*; + +class AltosUITime extends AltosUnits { + public double value(double v, boolean imperial_units) { return v; } + + public double inverse(double v, boolean imperial_unis) { return v; } + + public String show_units(boolean imperial_units) { return "s"; } + + public String say_units(boolean imperial_units) { return "seconds"; } + + public int show_fraction(int width, boolean imperial_units) { + if (width < 5) + return 0; + return width - 5; + } + + public int say_fraction(boolean imperial_units) { return 0; } +} + +class AltosXYSeries extends XYSeries { + + public AltosXYSeries(String label) { + super(label); + } +} + +public class AltosUITimeSeries extends AltosTimeSeries implements AltosUIGrapher { + Color color; + boolean enable; + AltosUIAxis axis; + boolean marker; + boolean marker_top; + XYItemRenderer renderer; + XYPlot plot; + AltosXYSeries xy_series; + ArrayList markers; + + + /* AltosUIGrapher interface */ + public boolean need_reset() { + return false; + } + + public void clear() { + } + + public void add(AltosUIDataPoint dataPoint) { + } + + public void setNotify(boolean notify) { + } + + public void fireSeriesChanged() { + } + + void set_data() { + if (marker) { + if (markers != null) { + for (ValueMarker marker : markers) + plot.removeDomainMarker(marker); + } + markers = new ArrayList(); + for (AltosTimeValue v : this) { + String s = units.string_value(v.value); + ValueMarker marker = new ValueMarker(v.time); + marker.setLabel(s); + if (marker_top) { + marker.setLabelAnchor(RectangleAnchor.TOP_RIGHT); + marker.setLabelTextAnchor(TextAnchor.TOP_LEFT); + } else { + marker.setLabelAnchor(RectangleAnchor.BOTTOM_RIGHT); + marker.setLabelTextAnchor(TextAnchor.BOTTOM_LEFT); + } + marker.setPaint(color); + if (enable) + plot.addDomainMarker(marker); + markers.add(marker); + } + } else { + xy_series.clear(); + + xy_series.setNotify(false); + for (AltosTimeValue v : this) { + double value = v.value; + if (units != null) + value = units.graph_value(value); + xy_series.add(v.time, value); + } + xy_series.setNotify(true); + } + } + + public void set_units() { + axis.set_units(); + StandardXYToolTipGenerator ttg; + + if (units != null) { + String time_example = (new AltosUITime()).graph_format(7); + String example = units.graph_format(7); + + ttg = new StandardXYToolTipGenerator(String.format("{1}s: {2}%s ({0})", + units.graph_units()), + new java.text.DecimalFormat(time_example), + new java.text.DecimalFormat(example)); + renderer.setBaseToolTipGenerator(ttg); + } + set_data(); + } + + public AltosXYSeries xy_series() { + return xy_series; + } + + public void set_enable(boolean enable) { + if (this.enable != enable) { + this.enable = enable; + if (marker) { + for (ValueMarker marker : markers) { + if (enable) + plot.addDomainMarker(marker); + else + plot.removeDomainMarker(marker); + } + } else { + renderer.setSeriesVisible(0, enable); + axis.set_enable(enable); + } + } + } + + public void set_axis(Color color, boolean enable, AltosUIAxis axis) { + this.color = color; + this.enable = enable; + this.axis = axis; + this.marker = false; + + axis.ref(this.enable); + + renderer = new XYLineAndShapeRenderer(true, false); + renderer.setSeriesPaint(0, color); + renderer.setSeriesStroke(0, new BasicStroke(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); + renderer.setSeriesVisible(0, enable); + xy_series = new AltosXYSeries(label); + } + + public void set_marker(Color color, boolean enable, XYPlot plot, boolean marker_top) { + this.color = color; + this.enable = enable; + this.marker = true; + this.plot = plot; + this.marker_top = marker_top; + } + + public AltosUITimeSeries(String label, AltosUnits units) { + super(label, units); + } + + public AltosUITimeSeries(String label, AltosUnits units, + Color color, boolean enable, + AltosUIAxis axis) { + this(label, units); + set_axis(color, enable, axis); + } +} diff --git a/altosuilib/AltosUIUnitsIndicator.java b/altosuilib/AltosUIUnitsIndicator.java index d4dd18db..bbfebef6 100644 --- a/altosuilib/AltosUIUnitsIndicator.java +++ b/altosuilib/AltosUIUnitsIndicator.java @@ -16,11 +16,11 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public abstract class AltosUIUnitsIndicator extends AltosUIIndicator { diff --git a/altosuilib/AltosUIVoltageIndicator.java b/altosuilib/AltosUIVoltageIndicator.java index 299c6114..297a6531 100644 --- a/altosuilib/AltosUIVoltageIndicator.java +++ b/altosuilib/AltosUIVoltageIndicator.java @@ -16,11 +16,11 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public abstract class AltosUIVoltageIndicator extends AltosUIUnitsIndicator { diff --git a/altosuilib/AltosUSBDevice.java b/altosuilib/AltosUSBDevice.java index 221ac829..49f966f3 100644 --- a/altosuilib/AltosUSBDevice.java +++ b/altosuilib/AltosUSBDevice.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.util.*; import libaltosJNI.*; diff --git a/altosuilib/AltosVoice.java b/altosuilib/AltosVoice.java index c651aa35..1d579a16 100644 --- a/altosuilib/AltosVoice.java +++ b/altosuilib/AltosVoice.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import com.sun.speech.freetts.Voice; import com.sun.speech.freetts.VoiceManager; diff --git a/altosuilib/GrabNDrag.java b/altosuilib/GrabNDrag.java index 0e57fe4d..665ef89e 100644 --- a/altosuilib/GrabNDrag.java +++ b/altosuilib/GrabNDrag.java @@ -16,7 +16,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.awt.*; import java.awt.event.*; diff --git a/altosuilib/Makefile.am b/altosuilib/Makefile.am index d18006b5..4b5eb524 100644 --- a/altosuilib/Makefile.am +++ b/altosuilib/Makefile.am @@ -18,7 +18,6 @@ altosuilib_JAVA = \ AltosUIDataMissing.java \ AltosUIDataPoint.java \ AltosUIDataSet.java \ - AltosUIGraph.java \ AltosUIGrapher.java \ AltosUIDialog.java \ AltosUIEnable.java \ @@ -28,7 +27,9 @@ altosuilib_JAVA = \ AltosUIMarker.java \ AltosUIPreferencesBackend.java \ AltosUIPreferences.java \ - AltosUISeries.java \ + AltosUIFlightSeries.java \ + AltosUIGraph.java \ + AltosGraph.java \ AltosUSBDevice.java \ AltosVoice.java \ AltosDisplayThread.java \ @@ -50,9 +51,6 @@ altosuilib_JAVA = \ AltosInfoTable.java \ AltosFlightInfoTableModel.java \ AltosFlightStatsTable.java \ - AltosGraph.java \ - AltosGraphDataPoint.java \ - AltosGraphDataSet.java \ AltosBTDevice.java \ AltosBTDeviceIterator.java \ AltosBTManage.java \ @@ -67,6 +65,7 @@ altosuilib_JAVA = \ AltosUITelemetryList.java \ AltosUIRateList.java \ AltosUIImage.java \ + AltosUITimeSeries.java \ OSXAdapter.java JAR=altosuilib_$(ALTOSUILIB_VERSION).jar diff --git a/altosuilib/OSXAdapter.java b/altosuilib/OSXAdapter.java index de5d5836..c338396f 100755 --- a/altosuilib/OSXAdapter.java +++ b/altosuilib/OSXAdapter.java @@ -55,7 +55,7 @@ Copyright © 2003-2007 Apple, Inc., All Rights Reserved */ -package org.altusmetrum.altosuilib_11; +package org.altusmetrum.altosuilib_12; import java.lang.reflect.*; import java.util.HashMap; diff --git a/ao-bringup/turnon_chaoskey b/ao-bringup/turnon_chaoskey index 990382f4..1a8fe13f 100755 --- a/ao-bringup/turnon_chaoskey +++ b/ao-bringup/turnon_chaoskey @@ -7,8 +7,8 @@ else exit 1 fi -if [ -x /usr/bin/ao-usbload ]; then - USBLOAD=/usr/bin/ao-usbload +if [ -x `which ao-usbload` ]; then + USBLOAD=`which ao-usbload` else echo "Can't find ao-usbload! Aborting." exit 1 diff --git a/configure.ac b/configure.ac index 3e6658e9..f6de573e 100644 --- a/configure.ac +++ b/configure.ac @@ -18,13 +18,13 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 1.7) +AC_INIT([altos], 1.7.1) ANDROID_VERSION=14 AC_CONFIG_SRCDIR([src/kernel/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE -RELEASE_DATE=2017-04-24 +RELEASE_DATE=2017-07-21 AC_SUBST(RELEASE_DATE) VERSION_DASH=`echo $VERSION | sed 's/\./-/g'` @@ -34,8 +34,8 @@ AC_SUBST(ANDROID_VERSION) dnl ========================================================================== dnl Java library versions -ALTOSUILIB_VERSION=11 -ALTOSLIB_VERSION=11 +ALTOSUILIB_VERSION=12 +ALTOSLIB_VERSION=12 AC_SUBST(ALTOSLIB_VERSION) AC_DEFINE(ALTOSLIB_VERSION,$ALTOSLIB_VERSION,[Version of the AltosLib package]) diff --git a/doc/Makefile b/doc/Makefile index 0d01279f..bbda6301 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -167,7 +167,8 @@ OUTLINE_TXT_FILES=\ telemega-outline.txt \ telemetrum-outline.txt \ telemini-v1-outline.txt \ - telemini-v3-outline.txt + telemini-v3-outline.txt \ + telegps-outline.txt OUTLINE_RAW_FILES=$(OUTLINE_TXT_FILES:.txt=.raw) diff --git a/doc/telegps-outline.txt b/doc/telegps-outline.txt new file mode 100644 index 00000000..bd1495be --- /dev/null +++ b/doc/telegps-outline.txt @@ -0,0 +1,9 @@ += TeleGPS Outline and Hole Pattern +:doctype: article + + This image, when printed, provides a precise template for the + mounting holes in TeleGPS. TeleGPS has overall dimensions + of 1.000 x 1.500 inches, and the mounting holes are sized for + use with 4-40 or M3 screws. + + image::telegps.svg[align="center"] diff --git a/doc/telegps.svg b/doc/telegps.svg new file mode 100644 index 00000000..702265cc --- /dev/null +++ b/doc/telegps.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + TeleGPS + + UP + + + diff --git a/libaltos/Makefile.am b/libaltos/Makefile.am index 8f69c1ad..69fe7a57 100644 --- a/libaltos/Makefile.am +++ b/libaltos/Makefile.am @@ -24,11 +24,15 @@ WINDOWS_SRC=\ WINDOWS_H=\ libaltos.h -noinst_PROGRAMS=cjnitest +noinst_PROGRAMS=cjnitest btletest cjnitest_SOURCES=cjnitest.c cjnitest_LDADD=libaltos.la +btletest_SOURCES=btletest.c + +btletest_LDADD=-lbluetooth + if MULTI_ARCH altoslib_LTLIBRARIES+=libaltos32.la libaltos64.la diff --git a/libaltos/btletest.c b/libaltos/btletest.c new file mode 100644 index 00000000..0e325415 --- /dev/null +++ b/libaltos/btletest.c @@ -0,0 +1,183 @@ +/* + * Copyright © 2017 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ATT_OP_MTU_REQ 0x02 +#define ATT_OP_MTU_RESP 0x03 +#define ATT_OP_WRITE_CMD 0x52 +#define ATT_OP_HANDLE_NOTIFY 0x1b +#define CID_ATT 0x0004 +#define TX_ENDPOINT 0x003a +#define RX_ENDPOINT 0x0037 +#define RX_NOTIFY 0x0038 + +int +main(int argc, char **argv) +{ + int sk; + int psm; + struct sockaddr_l2 src_addr = { 0 }; + struct sockaddr_l2 dst_addr = { 0 }; + char buf[1024]; + struct pollfd fd[2]; + int n, i; + char *btaddr; + int mtu; + + btaddr = argc > 1 ? argv[1] : "D8:80:39:F3:4E:A5"; + + sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); + if (sk < 0) { + perror("socket"); + exit(1); + } + + src_addr.l2_family = AF_BLUETOOTH; + /* Leave src_addr.l2_bdaddr all zeros */ + src_addr.l2_cid = htobs(CID_ATT); + src_addr.l2_bdaddr_type = BDADDR_LE_PUBLIC; + if (bind(sk, (struct sockaddr *) &src_addr, sizeof (src_addr)) < 0) { + perror("bind"); + exit(1); + } + + dst_addr.l2_family = AF_BLUETOOTH; + str2ba(btaddr, &dst_addr.l2_bdaddr); + dst_addr.l2_cid = htobs(CID_ATT); + dst_addr.l2_bdaddr_type = BDADDR_LE_PUBLIC; + + if (connect(sk, (struct sockaddr *) &dst_addr, sizeof(dst_addr)) < 0) { + perror("connect"); + exit(1); + } + + buf[0] = ATT_OP_MTU_REQ; + buf[1] = sizeof(buf) & 0xff; + buf[2] = sizeof(buf) >> 8; + n = write(sk, buf, 3); + if (n != 3) { + perror("write mtu\n"); + exit(1); + } + + fd[0].fd = sk; + fd[0].events = POLLIN; + for (;;) { + n = poll(fd, 1, 3000); + if (n <= 0) { + printf("timeout waiting for MTU response\n"); + exit(1); + } + if (fd[0].revents & POLLIN) { + n = read(sk, buf, sizeof(buf)); + printf("read %d\n", n); + for (i = 0; i < n; i++) + printf("%02x\n", buf[i]); + if (buf[0] == ATT_OP_MTU_RESP) { + mtu = (buf[1] & 0xff) | ((buf[2] & 0xff) << 8); + break; + } + } + } + printf("mtu %d\n", mtu); + + buf[0] = ATT_OP_WRITE_CMD; + buf[1] = RX_NOTIFY & 0xff; + buf[2] = RX_NOTIFY >> 8; + buf[3] = 1; + n = write(sk, buf, 4); + if (n != 4) { + perror("write notify"); + exit(1); + } + + fd[0].fd = 0; + fd[0].events = POLLIN; + fd[1].fd = sk; + fd[1].events = POLLIN; + + for (;;) { + n = poll(fd, 2, -1); + if (n == 0) + continue; + if (fd[0].revents & POLLIN) { + char *b; + n = read(0, buf+3, sizeof(buf)-3); + if (n < 0) { + perror("read stdin"); + exit(1); + } + if (n == 0) + break; + + b = buf; + while (n > 0) { + int this = n; + if (this > mtu - 3) + this = mtu - 3; + + b[0] = ATT_OP_WRITE_CMD; + b[1] = TX_ENDPOINT; + b[2] = TX_ENDPOINT >> 8; + if (write(sk, b, this + 3) != this + 3) { + perror("write sk"); + exit(1); + } + b += this; + n -= this; + } + } + if (fd[1].revents & POLLIN) { + uint16_t ch; + + n = read(sk, buf, sizeof(buf)); + if (n < 0) { + perror("read sk"); + exit(1); + } + if (n == 0) + continue; + ch = buf[1] | (buf[2] << 8); + switch (buf[0]) { + case ATT_OP_HANDLE_NOTIFY: + if (ch == RX_ENDPOINT) + write(1, buf+3, n-3); + break; + } + } + if (fd[1].revents & (POLLERR|POLLHUP)) + break; + } + close(sk); + + return 0; +} diff --git a/micropeak/Makefile.am b/micropeak/Makefile.am index 7ad2c102..52b62358 100644 --- a/micropeak/Makefile.am +++ b/micropeak/Makefile.am @@ -14,18 +14,14 @@ micropeakdir=$(datadir)/java micropeak_JAVA= \ MicroPeak.java \ MicroData.java \ - MicroDataPoint.java \ MicroDownload.java \ MicroExport.java \ MicroFile.java \ MicroFrame.java \ - MicroGraph.java \ MicroRaw.java \ MicroSave.java \ MicroSerial.java \ MicroSerialLog.java \ - MicroStats.java \ - MicroStatsTable.java \ MicroFileChooser.java \ MicroDeviceDialog.java \ MicroUSB.java diff --git a/micropeak/MicroData.java b/micropeak/MicroData.java index d502b9f7..70492a07 100644 --- a/micropeak/MicroData.java +++ b/micropeak/MicroData.java @@ -21,86 +21,21 @@ package org.altusmetrum.micropeak; import java.lang.*; import java.io.*; import java.util.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; -class MicroIterator implements Iterator { - int i; - MicroData data; - - public boolean hasNext() { - return i < data.pressures.length; - } - - public MicroDataPoint next() { - return new MicroDataPoint(data, i++); - } - - public MicroIterator (MicroData data) { - this.data = data; - i = 0; - } - - public void remove() { - } -} - -class MicroIterable implements Iterable { - - MicroData data; - - public Iterator iterator() { - return new MicroIterator(data); - } - - public MicroIterable(MicroData data) { - this.data = data; - } -} - -class MicroUIIterator implements Iterator { - int i; - MicroData data; - - public boolean hasNext() { - return i < data.pressures.length; - } - - public AltosUIDataPoint next() { - return new MicroDataPoint(data, i++); - } - - public MicroUIIterator (MicroData data) { - this.data = data; - i = 0; - } - - public void remove() { - } -} - -class MicroUIIterable implements Iterable { - MicroData data; - - public Iterator iterator() { - return new MicroUIIterator(data); - } - - public MicroUIIterable(MicroData data) { - this.data = data; - } -} - -public class MicroData implements AltosUIDataSet { +public class MicroData { public int ground_pressure; public int min_pressure; - public int[] pressures; + + AltosUIFlightSeries flight_series; + AltosFlightStats flight_stats; + AltosCalData cal_data; + private double time_step; - private double ground_altitude; private ArrayList bytes; public int log_id; String name; - MicroStats stats; public static final int LOG_ID_MICROPEAK = 0; public static final int LOG_ID_MICROKITE = 1; @@ -213,69 +148,45 @@ public class MicroData implements AltosUIDataSet { return Math.abs (target - a) < Math.abs(target - b); } + public double altitude(double time) { + if (flight_series.altitude_series == null) + return 0.0; + return flight_series.altitude_series.value(time); + } + public double altitude(int i) { - return AltosConvert.pressure_to_altitude(pressures[i]); + return altitude(time(i)); } public String name() { return name; } - public Iterable dataPoints() { - return new MicroUIIterable(this); - } - - public Iterable points() { - return new MicroIterable(this); - } - - int fact(int n) { - if (n == 0) - return 1; - return n * fact(n-1); - } + public double pressure(int i) { + if (flight_series.pressure_series == null) + return 0.0; - int choose(int n, int k) { - return fact(n) / (fact(k) * fact(n-k)); + return flight_series.pressure_series.value(time(i)); } + public double height(double time) { + if (flight_series.height_series == null) + return 0.0; - public double avg_altitude(int center, int dist) { - int start = center - dist; - int stop = center + dist; - - if (start < 0) - start = 0; - if (stop >= pressures.length) - stop = pressures.length - 1; - - double sum = 0; - double div = 0; - - int n = dist * 2; - - for (int i = start; i <= stop; i++) { - int k = i - (center - dist); - int c = choose (n, k); - - sum += c * pressures[i]; - div += c; - } - - double pres = sum / div; - - double alt = AltosConvert.pressure_to_altitude(pres); - return alt; + return flight_series.height_series.value(time); } - public double pressure(int i) { - return pressures[i]; + public double height(int i) { + return height(time(i)); } - public double height(int i) { - return altitude(i) - ground_altitude; + public int length() { + if (flight_series.pressure_series == null) + return 0; + return flight_series.pressure_series.size(); } + /* Use the recorded apogee pressure for stats so that it agrees with the device */ public double apogee_pressure() { return min_pressure; } @@ -285,31 +196,27 @@ public class MicroData implements AltosUIDataSet { } public double apogee_height() { - return apogee_altitude() - ground_altitude; + return apogee_altitude() - cal_data.ground_altitude; } - static final int speed_avg = 3; - static final int accel_avg = 5; - - private double avg_speed(int center, int dist) { - if (center == 0) - return 0; - - double ai = avg_altitude(center, dist); - double aj = avg_altitude(center - 1, dist); - double s = (ai - aj) / time_step; - - return s; + public double speed(double time) { + if (flight_series.speed_series == null) + return 0.0; + return flight_series.speed_series.value(time); } public double speed(int i) { - return avg_speed(i, speed_avg); + return speed(time(i)); + } + + public double acceleration(double time) { + if (flight_series.accel_series == null) + return 0.0; + return flight_series.accel_series.value(time); } public double acceleration(int i) { - if (i == 0) - return 0; - return (avg_speed(i, accel_avg) - avg_speed(i-1, accel_avg)) / time_step; + return acceleration(time(i)); } public double time(int i) { @@ -325,18 +232,24 @@ public class MicroData implements AltosUIDataSet { public void export (Writer f) throws IOException { PrintWriter pw = new PrintWriter(f); pw.printf(" Time, Press(Pa), Height(m), Height(f), Speed(m/s), Speed(mph), Speed(mach), Accel(m/s²), Accel(ft/s²), Accel(g)\n"); - for (MicroDataPoint point : points()) { + + for (AltosTimeValue ptv : flight_series.pressure_series) { + + double height = height(ptv.time); + double speed = speed(ptv.time); + double accel = acceleration(ptv.time); + pw.printf("%6.3f,%10.0f,%10.1f,%10.1f,%11.2f,%11.2f,%12.4f,%12.2f,%13.2f,%10.4f\n", - point.time, - point.pressure, - point.height, - AltosConvert.meters_to_feet(point.height), - point.speed, - AltosConvert.meters_to_mph(point.speed), - AltosConvert.meters_to_mach(point.speed), - point.accel, - AltosConvert.meters_to_feet(point.accel), - AltosConvert.meters_to_g(point.accel)); + ptv.time, + ptv.value, + height, + AltosConvert.meters_to_feet(height), + speed, + AltosConvert.meters_to_mph(speed), + AltosConvert.meters_to_mach(speed), + accel, + AltosConvert.meters_to_feet(accel), + AltosConvert.meters_to_g(accel)); } } @@ -344,9 +257,20 @@ public class MicroData implements AltosUIDataSet { this.name = name; } + public MicroData() { + ground_pressure = 101000; + min_pressure = 101000; + cal_data = new AltosCalData(); + flight_series = new AltosUIFlightSeries(cal_data); + } + public MicroData (InputStream f, String name) throws IOException, InterruptedException, NonHexcharException, FileEndedException { this.name = name; bytes = new ArrayList(); + + cal_data = new AltosCalData(); + flight_series = new AltosUIFlightSeries(cal_data); + if (!find_header(f)) throw new IOException("No MicroPeak data header found"); try { @@ -357,11 +281,30 @@ public class MicroData implements AltosUIDataSet { log_id = nsamples >> 12; nsamples &= 0xfff; - pressures = new int[nsamples + 1]; - ground_altitude = AltosConvert.pressure_to_altitude(ground_pressure); + cal_data.set_ground_pressure(ground_pressure); + + switch (log_id) { + case LOG_ID_MICROPEAK: + time_step = 2 * CLOCK_MP1; + break; + case LOG_ID_MICROKITE: + time_step = 200 * CLOCK_MP1; + break; + case LOG_ID_MICROPEAK2: + time_step = CLOCK_MP2; + break; + default: + throw new IOException(String.format("Unknown device type: %d", log_id)); + } + cal_data.set_ticks_per_sec(1/time_step); + cal_data.set_tick(0); + cal_data.set_boost_tick(); + int cur = ground_pressure; - pressures[0] = cur; + cal_data.set_tick(0); + flight_series.set_time(cal_data.time()); + flight_series.set_pressure(cur); for (int i = 0; i < nsamples; i++) { int k = get_16(f); int same = mix_in(cur, k); @@ -380,38 +323,40 @@ public class MicroData implements AltosUIDataSet { cur = down; } - pressures[i+1] = cur; + cal_data.set_tick(i+1); + flight_series.set_time(cal_data.time()); + flight_series.set_pressure(cur); } + flight_series.finish(); + + /* Build states */ + + flight_series.set_time(0); + flight_series.set_state(AltosLib.ao_flight_boost); + + flight_series.set_time(flight_series.speed_series.max().time); + flight_series.set_state(AltosLib.ao_flight_coast); + + flight_series.set_time(flight_series.height_series.max().time); + flight_series.set_state(AltosLib.ao_flight_drogue); + + cal_data.set_tick(nsamples); + flight_series.set_time(cal_data.time()); + flight_series.set_state(AltosLib.ao_flight_landed); + + flight_series.finish(); + + flight_stats = new AltosFlightStats(flight_series); + int current_crc = swap16(~file_crc & 0xffff); int crc = get_16(f); crc_valid = crc == current_crc; - switch (log_id) { - case LOG_ID_MICROPEAK: - time_step = 2 * CLOCK_MP1; - break; - case LOG_ID_MICROKITE: - time_step = 200 * CLOCK_MP1; - break; - case LOG_ID_MICROPEAK2: - time_step = CLOCK_MP2; - break; - default: - throw new IOException(String.format("Unknown device type: %d", log_id)); - } - stats = new MicroStats(this); } catch (FileEndedException fe) { throw new IOException("File Ended Unexpectedly"); } } - public MicroData() { - ground_pressure = 101000; - min_pressure = 101000; - pressures = new int[1]; - pressures[0] = 101000; - } - } diff --git a/micropeak/MicroDataPoint.java b/micropeak/MicroDataPoint.java deleted file mode 100644 index 42079291..00000000 --- a/micropeak/MicroDataPoint.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.micropeak; - -import org.altusmetrum.altosuilib_11.*; - -public class MicroDataPoint implements AltosUIDataPoint { - public double time; - public double pressure; - public double height; - public double speed; - public double accel; - public MicroStats stats; - - public static final int data_height = 0; - public static final int data_speed = 1; - public static final int data_accel = 2; - public static final int data_state = 3; - - public double x() { - return time; - } - - public double y(int index) { - switch (index) { - case data_height: - return height; - case data_speed: - return speed; - case data_accel: - return accel; - default: - return 0; - } - } - - public int id(int index) { - if (index == data_state) { - return stats.state(time); - } - return 0; - } - - public String id_name(int index) { - if (index == data_state) - return stats.state_name(time); - return ""; - } - - public MicroDataPoint (double pressure, double height, double speed, double accel, double time, MicroStats stats) { - this.pressure = pressure; - this.height = height; - this.speed = speed; - this.accel = accel; - this.time = time; - this.stats = stats; - } - - public MicroDataPoint(MicroData data, int i) { - this(data.pressure(i), - data.height(i), - data.speed(i), - data.acceleration(i), - data.time(i), - data.stats); - } -} \ No newline at end of file diff --git a/micropeak/MicroDeviceDialog.java b/micropeak/MicroDeviceDialog.java index 010612a0..db2662a0 100644 --- a/micropeak/MicroDeviceDialog.java +++ b/micropeak/MicroDeviceDialog.java @@ -22,7 +22,7 @@ import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altosuilib_12.*; public class MicroDeviceDialog extends AltosDeviceDialog { diff --git a/micropeak/MicroDownload.java b/micropeak/MicroDownload.java index 2326ea08..e5f54821 100644 --- a/micropeak/MicroDownload.java +++ b/micropeak/MicroDownload.java @@ -24,8 +24,8 @@ import javax.swing.*; import java.io.*; import java.util.concurrent.*; import java.util.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class MicroDownload extends AltosUIDialog implements Runnable, ActionListener, MicroSerialLog, WindowListener { MicroPeak owner; diff --git a/micropeak/MicroExport.java b/micropeak/MicroExport.java index f1062681..36700e75 100644 --- a/micropeak/MicroExport.java +++ b/micropeak/MicroExport.java @@ -24,8 +24,8 @@ import java.util.ArrayList; import java.awt.*; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class MicroExport extends JFileChooser { diff --git a/micropeak/MicroFile.java b/micropeak/MicroFile.java index b341f350..20f6db55 100644 --- a/micropeak/MicroFile.java +++ b/micropeak/MicroFile.java @@ -20,8 +20,8 @@ package org.altusmetrum.micropeak; import java.io.*; import java.util.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class MicroFile { diff --git a/micropeak/MicroFileChooser.java b/micropeak/MicroFileChooser.java index c068244b..85f7aed4 100644 --- a/micropeak/MicroFileChooser.java +++ b/micropeak/MicroFileChooser.java @@ -21,8 +21,8 @@ package org.altusmetrum.micropeak; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import java.io.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class MicroFileChooser extends JFileChooser { JFrame frame; diff --git a/micropeak/MicroFrame.java b/micropeak/MicroFrame.java index b6f1f76d..d9ad8404 100644 --- a/micropeak/MicroFrame.java +++ b/micropeak/MicroFrame.java @@ -22,7 +22,7 @@ import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altosuilib_12.*; public class MicroFrame extends AltosUIFrame { static String[] micro_icon_names = { diff --git a/micropeak/MicroGraph.java b/micropeak/MicroGraph.java deleted file mode 100644 index 64a43bd8..00000000 --- a/micropeak/MicroGraph.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.micropeak; - -import java.io.*; -import java.util.ArrayList; - -import java.awt.*; -import javax.swing.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; - -import org.jfree.ui.*; -import org.jfree.chart.*; -import org.jfree.chart.plot.*; -import org.jfree.chart.axis.*; -import org.jfree.chart.renderer.*; -import org.jfree.chart.renderer.xy.*; -import org.jfree.chart.labels.*; -import org.jfree.data.xy.*; -import org.jfree.data.*; - -public class MicroGraph extends AltosUIGraph { - - static final private Color height_color = new Color(194,31,31); - static final private Color speed_color = new Color(31,194,31); - static final private Color accel_color = new Color(31,31,194); - static final private Color state_color = new Color(3,3,3); - - public MicroGraph(AltosUIEnable enable) { - super(enable); - - addSeries("Height", MicroDataPoint.data_height, AltosConvert.height, height_color); - addSeries("Speed", MicroDataPoint.data_speed, AltosConvert.speed, speed_color); - addSeries("Acceleration", MicroDataPoint.data_accel, AltosConvert.accel, accel_color); - addMarker("State", MicroDataPoint.data_state, state_color); - } -} \ No newline at end of file diff --git a/micropeak/MicroPeak.java b/micropeak/MicroPeak.java index 9023f452..607bf20c 100644 --- a/micropeak/MicroPeak.java +++ b/micropeak/MicroPeak.java @@ -24,18 +24,17 @@ import javax.swing.*; import java.io.*; import java.util.concurrent.*; import java.util.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class MicroPeak extends MicroFrame implements ActionListener, ItemListener { File filename; - MicroGraph graph; + AltosGraph graph; AltosUIEnable enable; - MicroStatsTable statsTable; + AltosFlightStatsTable statsTable; MicroRaw raw; MicroData data; - MicroStats stats; Container container; JTabbedPane pane; static int number_of_windows; @@ -47,9 +46,12 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene return mp.SetData(data); } this.data = data; - stats = new MicroStats(data); - graph.setDataSet(data); - statsTable.setStats(stats); + if (data.flight_series == null) + System.out.printf("no data in flight\n"); + if (data.flight_stats == null) + System.out.printf("no stats in flight\n"); + graph.set_data(data.flight_stats, data.flight_series); + statsTable.set_stats(data.flight_stats); raw.setData(data); setTitle(data.name); return this; @@ -265,8 +267,9 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene }); enable = new AltosUIEnable(); - graph = new MicroGraph(enable); - statsTable = new MicroStatsTable(); + + graph = new AltosGraph(enable); + statsTable = new AltosFlightStatsTable(); raw = new MicroRaw(); pane.add(graph.panel, "Graph"); pane.add(enable, "Configure Graph"); @@ -324,8 +327,9 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene CommandExport(file); opened = true; } catch (Exception e) { - System.err.printf("Error processing \"%s\": %s\n", - file.getName(), e.getMessage()); + System.err.printf("Error processing \"%s\": %s %s\n", + file.getName(), e.toString(), e.getMessage()); + e.printStackTrace(); } } } diff --git a/micropeak/MicroRaw.java b/micropeak/MicroRaw.java index f00d7ea3..d1d5d076 100644 --- a/micropeak/MicroRaw.java +++ b/micropeak/MicroRaw.java @@ -21,8 +21,8 @@ package org.altusmetrum.micropeak; import java.awt.*; import java.io.*; import javax.swing.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class MicroRaw extends JTextArea { @@ -30,7 +30,7 @@ public class MicroRaw extends JTextArea { StringWriter sw = new StringWriter(); try { data.export(sw); - setRows(data.pressures.length + 1); + setRows(data.length()); setText(sw.toString()); } catch (IOException ie) { setText(String.format("Error writing data: %s", ie.getMessage())); diff --git a/micropeak/MicroSave.java b/micropeak/MicroSave.java index 5dda5b8c..9da76914 100644 --- a/micropeak/MicroSave.java +++ b/micropeak/MicroSave.java @@ -25,8 +25,8 @@ import javax.swing.filechooser.FileNameExtensionFilter; import java.io.*; import java.util.concurrent.*; import java.util.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class MicroSave extends JFileChooser { diff --git a/micropeak/MicroSerial.java b/micropeak/MicroSerial.java index 43dfd18b..c1b2a7ad 100644 --- a/micropeak/MicroSerial.java +++ b/micropeak/MicroSerial.java @@ -21,7 +21,7 @@ package org.altusmetrum.micropeak; import java.util.*; import java.io.*; import libaltosJNI.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altosuilib_12.*; public class MicroSerial extends InputStream { SWIGTYPE_p_altos_file file; diff --git a/micropeak/MicroSerialLog.java b/micropeak/MicroSerialLog.java index 2e6dd236..d33a36b3 100644 --- a/micropeak/MicroSerialLog.java +++ b/micropeak/MicroSerialLog.java @@ -21,7 +21,7 @@ package org.altusmetrum.micropeak; import java.util.*; import java.io.*; import libaltosJNI.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altosuilib_12.*; public interface MicroSerialLog { diff --git a/micropeak/MicroStats.java b/micropeak/MicroStats.java deleted file mode 100644 index b9637536..00000000 --- a/micropeak/MicroStats.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.micropeak; - -import java.io.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; - -public class MicroStats { - double coast_height; - double coast_time; - - double apogee_height; - double apogee_time; - - double landed_height; - double landed_time; - - double max_speed; - double max_accel; - - MicroData data; - - void find_landing() { - landed_height = 0; - - for (MicroDataPoint point : data.points()) { - landed_height = point.height; - landed_time = point.time; - } - - boolean above = false; - for (MicroDataPoint point : data.points()) { - if (point.height > landed_height + 10) { - above = true; - } else { - if (above && point.height < landed_height + 2) { - above = false; - landed_time = point.time; - } - } - } - } - - void find_apogee() { - apogee_height = data.apogee_height(); - double searched_apogee = 0; - apogee_time = 0; - - /* This just finds the apogee time -- we've recorded the - * peak altitude separately in eeprom, and that could - * have occurred after the eeprom was full. - */ - for (MicroDataPoint point : data.points()) { - if (point.height > searched_apogee) { - searched_apogee = point.height; - apogee_time = point.time; - } - } - } - - void find_coast() { - coast_height = 0; - coast_time = 0; - - for (MicroDataPoint point : data.points()) { - if (point.accel < -9.8) - break; - coast_time = point.time; - coast_height = point.height; - } - } - - void find_max_speed() { - max_speed = 0; - for (MicroDataPoint point : data.points()) { - if (point.time > apogee_time) - break; - if (point.speed > max_speed) - max_speed = point.speed; - } - } - - void find_max_accel() { - max_accel = 0; - for (MicroDataPoint point : data.points()) { - if (point.time > apogee_time) - break; - if (point.accel > max_accel) - max_accel = point.accel; - } - } - - double boost_duration() { - return coast_time; - } - - double boost_height() { - return coast_height; - } - - double boost_speed() { - return coast_height / coast_time; - } - - double boost_accel() { - return boost_speed() / boost_duration(); - } - - double coast_duration() { - return apogee_time - coast_time; - } - - double coast_height() { - return apogee_height - coast_height; - } - - double coast_speed() { - return coast_height() / coast_duration(); - } - - double coast_accel() { - return coast_speed() / coast_duration(); - } - - double descent_duration() { - return landed_time - apogee_time; - } - - double descent_height() { - return apogee_height - landed_height; - } - - double descent_speed() { - return descent_height() / descent_duration(); - } - - public static final int state_startup = -1; - public static final int state_pad = 0; - public static final int state_boost = 1; - public static final int state_coast = 2; - public static final int state_descent = 3; - public static final int state_landed = 4; - - static final String state_names[] = { - "pad", - "boost", - "coast", - "descent", - "landed" - }; - - public int state(double t) { - if (t >= landed_time) - return state_landed; - if (t >= apogee_time) - return state_descent; - if (t >= coast_time) - return state_coast; - if (t >= 0) - return state_boost; - return state_pad; - } - - public static String state_name(int state) { - if (state < 0 || state > state_landed) - return "unknown"; - return state_names[state]; - } - - public String state_name(double t) { - return state_name(state(t)); - } - - public MicroStats(MicroData data) { - - this.data = data; - - find_coast(); - find_apogee(); - find_landing(); - find_max_speed(); - find_max_accel(); - } - - public MicroStats() { - this(new MicroData()); - } -} diff --git a/micropeak/MicroStatsTable.java b/micropeak/MicroStatsTable.java deleted file mode 100644 index e095e3a4..00000000 --- a/micropeak/MicroStatsTable.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.micropeak; - -import java.awt.*; -import javax.swing.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; - -public class MicroStatsTable extends JComponent implements AltosFontListener { - GridBagLayout layout; - - class MicroStat { - JLabel label; - JTextField[] texts; - - public void set_values(String ... values) { - for (int j = 0; j < values.length; j++) { - texts[j].setText(values[j]); - } - } - - public void set_font() { - for (int j = 0; j < texts.length; j++) - texts[j].setFont(AltosUILib.value_font); - label.setFont(AltosUILib.label_font); - } - - public MicroStat(GridBagLayout layout, int y, String label_text, String ... values) { - GridBagConstraints c = new GridBagConstraints(); - c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad); - c.weighty = 1; - - label = new JLabel(label_text); - label.setFont(AltosUILib.label_font); - label.setHorizontalAlignment(SwingConstants.LEFT); - c.gridx = 0; c.gridy = y; - c.anchor = GridBagConstraints.WEST; - c.fill = GridBagConstraints.VERTICAL; - c.weightx = 0; - layout.setConstraints(label, c); - add(label); - - texts = new JTextField[values.length]; - for (int j = 0; j < values.length; j++) { - JTextField value = new JTextField(values[j]); - value.setEditable(false); - value.setFont(AltosUILib.value_font); - value.setHorizontalAlignment(SwingConstants.RIGHT); - texts[j] = value; - c.gridx = j+1; c.gridy = y; - c.anchor = GridBagConstraints.EAST; - c.fill = GridBagConstraints.BOTH; - c.weightx = 1; - layout.setConstraints(value, c); - add(value); - } - } - } - - MicroStat max_height, max_speed; - MicroStat max_accel, avg_accel; - MicroStat boost_duration; - MicroStat coast_duration; - MicroStat descent_speed; - MicroStat descent_duration; - MicroStat flight_time; - - public void setStats(MicroStats stats) { - max_height.set_values(String.format("%7.1f m", stats.apogee_height), - String.format("%7.1f ft", AltosConvert.meters_to_feet(stats.apogee_height))); - max_speed.set_values(String.format("%7.1f m/s", stats.max_speed), - String.format("%7.1f mph", AltosConvert.meters_to_mph(stats.max_speed)), - String.format("Mach %7.3f", AltosConvert.meters_to_mach(stats.max_speed))); - max_accel.set_values(String.format("%7.1f m/s²", stats.max_accel), - String.format("%7.1f ft/s²", AltosConvert.meters_to_feet(stats.max_accel)), - String.format("%7.3f G", AltosConvert.meters_to_g(stats.max_accel))); - avg_accel.set_values(String.format("%7.1f m/s²", stats.boost_accel(), - String.format("%7.1f ft/s²", AltosConvert.meters_to_feet(stats.boost_accel())), - String.format("%7.3f G", AltosConvert.meters_to_g(stats.boost_accel())))); - boost_duration.set_values(String.format("%6.1f s", stats.boost_duration())); - coast_duration.set_values(String.format("%6.1f s", stats.coast_duration())); - descent_speed.set_values(String.format("%7.1f m/s", stats.descent_speed()), - String.format("%7.1f ft/s", AltosConvert.meters_to_feet(stats.descent_speed()))); - descent_duration.set_values(String.format("%6.1f s", stats.descent_duration())); - flight_time.set_values(String.format("%6.1f s", stats.landed_time)); - } - - public void set_font() { - max_height.set_font(); - max_speed.set_font(); - max_accel.set_font(); - avg_accel.set_font(); - boost_duration.set_font(); - coast_duration.set_font(); - descent_speed.set_font(); - descent_duration.set_font(); - flight_time.set_font(); - } - - public void font_size_changed(int font_size) { - set_font(); - } - - public MicroStatsTable(MicroStats stats) { - layout = new GridBagLayout(); - - setLayout(layout); - int y = 0; - max_height = new MicroStat(layout, y++, "Maximum height", - String.format("%7.1f m", stats.apogee_height), - String.format("%7.1f ft", AltosConvert.meters_to_feet(stats.apogee_height))); - max_speed = new MicroStat(layout, y++, "Maximum speed", - String.format("%7.1f m/s", stats.max_speed), - String.format("%7.1f mph", AltosConvert.meters_to_mph(stats.max_speed)), - String.format("Mach %4.1f", AltosConvert.meters_to_mach(stats.max_speed))); - max_accel = new MicroStat(layout, y++, "Maximum boost acceleration", - String.format("%7.1f m/s²", stats.max_accel), - String.format("%7.1f ft/s²", AltosConvert.meters_to_feet(stats.max_accel)), - String.format("%7.3f G", AltosConvert.meters_to_g(stats.max_accel))); - avg_accel = new MicroStat(layout, y++, "Average boost acceleration", - String.format("%7.1f m/s²", stats.boost_accel(), - String.format("%7.1f ft/s²", AltosConvert.meters_to_feet(stats.boost_accel())), - String.format("%7.3f G", AltosConvert.meters_to_g(stats.boost_accel())))); - boost_duration = new MicroStat(layout, y++, "Boost duration", - String.format("%6.1f s", stats.boost_duration())); - coast_duration = new MicroStat(layout, y++, "Coast duration", - String.format("%6.1f s", stats.coast_duration())); - descent_speed = new MicroStat(layout, y++, "Descent rate", - String.format("%7.1f m/s", stats.descent_speed()), - String.format("%7.1f ft/s", AltosConvert.meters_to_feet(stats.descent_speed()))); - descent_duration = new MicroStat(layout, y++, "Descent duration", - String.format("%6.1f s", stats.descent_duration())); - flight_time = new MicroStat(layout, y++, "Flight Time", - String.format("%6.1f s", stats.landed_time)); - set_font(); - - AltosUIPreferences.register_font_listener(this); - } - - public void tell_closing() { - AltosUIPreferences.unregister_font_listener(this); - } - - public MicroStatsTable() { - this(new MicroStats()); - } - -} diff --git a/micropeak/MicroUSB.java b/micropeak/MicroUSB.java index 4ab5fcc9..a2db3835 100644 --- a/micropeak/MicroUSB.java +++ b/micropeak/MicroUSB.java @@ -20,8 +20,8 @@ package org.altusmetrum.micropeak; import java.util.*; import libaltosJNI.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class MicroUSB extends altos_device implements AltosDevice { diff --git a/src/drivers/ao_hmc5883.c b/src/drivers/ao_hmc5883.c index f668fb66..c33aa536 100644 --- a/src/drivers/ao_hmc5883.c +++ b/src/drivers/ao_hmc5883.c @@ -126,13 +126,15 @@ struct ao_hmc5883_sample ao_hmc5883_current; static void ao_hmc5883(void) { + struct ao_hmc5883_sample sample; ao_hmc5883_setup(); for (;;) { - ao_hmc5883_sample(&ao_hmc5883_current); - ao_arch_critical( - AO_DATA_PRESENT(AO_DATA_HMC5883); - AO_DATA_WAIT(); - ); + ao_hmc5883_sample(&sample); + ao_arch_block_interrupts(); + ao_hmc5883_current = sample; + AO_DATA_PRESENT(AO_DATA_HMC5883); + AO_DATA_WAIT(); + ao_arch_release_interrupts(); } } @@ -141,10 +143,8 @@ static struct ao_task ao_hmc5883_task; static void ao_hmc5883_show(void) { - struct ao_data sample; - ao_data_get(&sample); - printf ("X: %d Y: %d Z: %d missed irq: %lu\n", - sample.hmc5883.x, sample.hmc5883.y, sample.hmc5883.z, ao_hmc5883_missed_irq); + printf ("X: %d Z: %d Y: %d missed irq: %lu\n", + ao_hmc5883_current.x, ao_hmc5883_current.z, ao_hmc5883_current.y, ao_hmc5883_missed_irq); } static const struct ao_cmds ao_hmc5883_cmds[] = { diff --git a/src/drivers/ao_hmc5883.h b/src/drivers/ao_hmc5883.h index 78637b02..b90733df 100644 --- a/src/drivers/ao_hmc5883.h +++ b/src/drivers/ao_hmc5883.h @@ -77,7 +77,7 @@ #define HMC5883_ID_C 12 struct ao_hmc5883_sample { - int16_t x, y, z; + int16_t x, z, y; }; extern struct ao_hmc5883_sample ao_hmc5883_current; diff --git a/src/drivers/ao_mpu6000.c b/src/drivers/ao_mpu6000.c index 650407ad..81d3c16c 100644 --- a/src/drivers/ao_mpu6000.c +++ b/src/drivers/ao_mpu6000.c @@ -192,7 +192,7 @@ _ao_mpu6000_setup(void) _ao_mpu6000_wait_alive(); /* Reset the whole chip */ - + _ao_mpu6000_reg_write(MPU6000_PWR_MGMT_1, (1 << MPU6000_PWR_MGMT_1_DEVICE_RESET)); @@ -292,7 +292,7 @@ _ao_mpu6000_setup(void) ao_delay(AO_MS_TO_TICKS(200)); _ao_mpu6000_sample(&normal_mode); - + errors += ao_mpu6000_accel_check(normal_mode.accel_x, test_mode.accel_x); errors += ao_mpu6000_accel_check(normal_mode.accel_y, test_mode.accel_y); errors += ao_mpu6000_accel_check(normal_mode.accel_z, test_mode.accel_z); @@ -315,7 +315,7 @@ _ao_mpu6000_setup(void) /* Set sample rate divider to sample at 200Hz (v = gyro/rate - 1) */ _ao_mpu6000_reg_write(MPU6000_SMPRT_DIV, 1000 / 200 - 1); - + ao_delay(AO_MS_TO_TICKS(100)); ao_mpu6000_configured = 1; } @@ -325,6 +325,7 @@ struct ao_mpu6000_sample ao_mpu6000_current; static void ao_mpu6000(void) { + struct ao_mpu6000_sample sample; /* ao_mpu6000_init already grabbed the SPI bus and mutex */ _ao_mpu6000_setup(); #if AO_MPU6000_SPI @@ -335,14 +336,15 @@ ao_mpu6000(void) #if AO_MPU6000_SPI ao_mpu6000_spi_get(); #endif - _ao_mpu6000_sample(&ao_mpu6000_current); + _ao_mpu6000_sample(&sample); #if AO_MPU6000_SPI ao_mpu6000_spi_put(); -#endif - ao_arch_critical( - AO_DATA_PRESENT(AO_DATA_MPU6000); - AO_DATA_WAIT(); - ); +#endif + ao_arch_block_interrupts(); + ao_mpu6000_current = sample; + AO_DATA_PRESENT(AO_DATA_MPU6000); + AO_DATA_WAIT(); + ao_arch_release_interrupts(); } } @@ -351,16 +353,13 @@ static struct ao_task ao_mpu6000_task; static void ao_mpu6000_show(void) { - struct ao_data sample; - - ao_data_get(&sample); printf ("Accel: %7d %7d %7d Gyro: %7d %7d %7d\n", - sample.mpu6000.accel_x, - sample.mpu6000.accel_y, - sample.mpu6000.accel_z, - sample.mpu6000.gyro_x, - sample.mpu6000.gyro_y, - sample.mpu6000.gyro_z); + ao_mpu6000_current.accel_x, + ao_mpu6000_current.accel_y, + ao_mpu6000_current.accel_z, + ao_mpu6000_current.gyro_x, + ao_mpu6000_current.gyro_y, + ao_mpu6000_current.gyro_z); } static const struct ao_cmds ao_mpu6000_cmds[] = { @@ -374,7 +373,7 @@ ao_mpu6000_init(void) ao_mpu6000_configured = 0; ao_add_task(&ao_mpu6000_task, ao_mpu6000, "mpu6000"); - + #if AO_MPU6000_SPI ao_spi_init_cs(AO_MPU6000_SPI_CS_PORT, (1 << AO_MPU6000_SPI_CS_PIN)); @@ -386,7 +385,7 @@ ao_mpu6000_init(void) ao_cur_task = &ao_mpu6000_task; ao_spi_get(AO_MPU6000_SPI_BUS, AO_SPI_SPEED_1MHz); ao_cur_task = NULL; -#endif +#endif ao_cmd_register(&ao_mpu6000_cmds[0]); } diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 0afdf012..914e0c1b 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -201,11 +201,13 @@ __xdata struct ao_ms5607_sample ao_ms5607_current; static void ao_ms5607(void) { + struct ao_ms5607_sample sample; ao_ms5607_setup(); for (;;) { - ao_ms5607_sample(&ao_ms5607_current); + ao_ms5607_sample(&sample); ao_arch_block_interrupts(); + ao_ms5607_current = sample; AO_DATA_PRESENT(AO_DATA_MS5607); AO_DATA_WAIT(); ao_arch_release_interrupts(); diff --git a/src/drivers/ao_rn4678.c b/src/drivers/ao_rn4678.c index 4e3d12cb..98dc35b5 100644 --- a/src/drivers/ao_rn4678.c +++ b/src/drivers/ao_rn4678.c @@ -39,7 +39,7 @@ static void ao_rn_log_char(char c, char dir) { if (dir != ao_rn_dir) { - putchar(dir); + putchar(dir); putchar('\n'); ao_rn_dir = dir; } switch (c) { @@ -100,84 +100,81 @@ static const char *status_strings[] = { "RFCOMM_CLOSE", "RFCOMM_OPEN", "CONNECT", + "LCONNECT", "DISCONN", "BONDED", }; #define NUM_STATUS_STRING (sizeof status_strings/sizeof status_strings[0]) +static char ao_rn_buffer[64]; +static int ao_rn_buf_cnt, ao_rn_buf_ptr; +static int ao_rn_draining; +static AO_TICK_TYPE ao_rn_buf_time; + +/* Well, this is annoying. The status strings from the RN4678 can't be + * disabled due to a firmware bug. So, this code finds those in the + * input and strips them out. + */ int _ao_wrap_rn_pollchar(void) { - static char buffer[64]; - static int buf_cnt, buf_ptr; - static int draining; int c = AO_READ_AGAIN; unsigned i; int done = 0; - while (!done && !draining) { + while (!done && !ao_rn_draining) { c = _ao_serial_rn_pollchar(); - if (c == AO_READ_AGAIN) + if (c == AO_READ_AGAIN) { + if (ao_rn_buf_cnt && (ao_time() - ao_rn_buf_time) > AO_MS_TO_TICKS(1000)) { + ao_rn_draining = 1; + continue; + } return AO_READ_AGAIN; + } - if (buf_cnt) { + if (ao_rn_buf_cnt) { /* buffering chars */ if (c == STATUS_CHAR) { /* End of status string, drop it and carry on */ - buffer[buf_cnt] = '\0'; - ao_rn_dbg("discard %s\n", buffer); - buf_cnt = 0; - } else if (buf_cnt == sizeof(buffer)) { + ao_rn_buffer[ao_rn_buf_cnt] = '\0'; +// ao_rn_dbg("discard %s\n", ao_rn_buffer); + ao_rn_buf_cnt = 0; + } else if (ao_rn_buf_cnt == sizeof(ao_rn_buffer)) { /* If we filled the buffer, just give up */ - draining = 1; + ao_rn_draining = 1; } else { - buffer[buf_cnt++] = c; + ao_rn_buffer[ao_rn_buf_cnt++] = c; for (i = 0; i < NUM_STATUS_STRING; i++) { int cmp = strlen(status_strings[i]); - if (cmp >= buf_cnt) - cmp = buf_cnt-1; - if (memcmp(buffer+1, status_strings[i], cmp) == 0) + if (cmp >= ao_rn_buf_cnt) + cmp = ao_rn_buf_cnt-1; + if (memcmp(ao_rn_buffer+1, status_strings[i], cmp) == 0) break; } if (i == NUM_STATUS_STRING) - draining = 1; + ao_rn_draining = 1; } } else if (c == STATUS_CHAR) { - buffer[0] = c; - buf_cnt = 1; - buf_ptr = 0; + ao_rn_buffer[0] = c; + ao_rn_buf_cnt = 1; + ao_rn_buf_ptr = 0; + ao_rn_buf_time = ao_time(); } else done = 1; } - if (draining) { - c = buffer[buf_ptr++] & 0xff; - if (buf_ptr == buf_cnt) { - buf_ptr = buf_cnt = 0; - draining = 0; + if (ao_rn_draining) { + c = ao_rn_buffer[ao_rn_buf_ptr++] & 0xff; + if (ao_rn_buf_ptr == ao_rn_buf_cnt) { + ao_rn_buf_ptr = ao_rn_buf_cnt = 0; + ao_rn_draining = 0; } } -#if AO_RN_DEBUG - ao_arch_release_interrupts(); - ao_usb_putchar(c); ao_usb_flush(); - ao_arch_block_interrupts(); -#endif return c; } -#if AO_RN_DEBUG -static void -ao_wrap_rn_putchar(char c) -{ - ao_usb_putchar(c); ao_usb_flush(); - ao_serial_rn_putchar(c); -} -#else -#define ao_wrap_rn_putchar ao_serial_rn_putchar -#endif - static void ao_rn_puts(char *s) { @@ -192,7 +189,7 @@ ao_rn_drain(void) { int timeout = 0; - ao_rn_dbg("drain...\n"); +// ao_rn_dbg("drain...\n"); ao_serial_rn_drain(); while (!timeout) { ao_arch_block_interrupts(); @@ -204,13 +201,13 @@ ao_rn_drain(void) } ao_arch_release_interrupts(); } - ao_rn_dbg("drain done\n"); +// ao_rn_dbg("drain done\n"); } static void ao_rn_send_cmd(char *cmd, char *param) { - ao_rn_dbg("send_cmd %s%s\n", cmd, param ? param : ""); +// ao_rn_dbg("send_cmd %s%s\n", cmd, param ? param : ""); ao_rn_drain(); ao_rn_puts(cmd); if (param) @@ -244,20 +241,20 @@ ao_rn_wait_for(int timeout, char *match) AO_TICK_TYPE giveup_time = ao_time() + timeout; int c; - ao_rn_dbg("wait for %d, \"%s\"\n", timeout, match); +// ao_rn_dbg("wait for %d, \"%s\"\n", timeout, match); memset(reply, ' ', sizeof(reply)); while (memcmp(reply, match, match_len) != 0) { c = ao_rn_wait_char(giveup_time); if (c == AO_READ_AGAIN) { - ao_rn_dbg("\twait for timeout\n"); +// ao_rn_dbg("\twait for timeout\n"); return AO_RN_TIMEOUT; } reply[match_len] = (char) c; memmove(reply, reply+1, match_len); reply[match_len] = '\0'; - ao_rn_dbg("\tmatch now \"%s\"\n", reply); +// ao_rn_dbg("\tmatch now \"%s\"\n", reply); } - ao_rn_dbg("\twait for ok\n"); +// ao_rn_dbg("\twait for ok\n"); return AO_RN_OK; } @@ -266,20 +263,20 @@ ao_rn_wait_line(AO_TICK_TYPE giveup_time, char *line, int len) { char *l = line; - ao_rn_dbg("wait line\n"); +// ao_rn_dbg("wait line\n"); for (;;) { int c = ao_rn_wait_char(giveup_time); /* timeout */ if (c == AO_READ_AGAIN) { - ao_rn_dbg("\twait line timeout\n"); +// ao_rn_dbg("\twait line timeout\n"); return AO_RN_TIMEOUT; } /* done */ if (c == '\r') { *l = '\0'; - ao_rn_dbg("\twait line \"%s\"\n", line); +// ao_rn_dbg("\twait line \"%s\"\n", line); return AO_RN_OK; } @@ -302,7 +299,7 @@ ao_rn_wait_status(void) AO_TICK_TYPE giveup_time = ao_time() + AO_RN_CMD_TIMEOUT; int status; - ao_rn_dbg("wait status\n"); +// ao_rn_dbg("wait status\n"); status = ao_rn_wait_line(giveup_time, message, sizeof (message)); if (status == AO_RN_OK) if (strncmp(message, "AOK", 3) != 0) @@ -317,7 +314,7 @@ ao_rn_set_name(void) char *s = sn + 8; int n; - ao_rn_dbg("set name...\n"); +// ao_rn_dbg("set name...\n"); *--s = '\0'; n = ao_serial_number; do { @@ -330,7 +327,7 @@ ao_rn_set_name(void) static int ao_rn_get_name(char *name, int len) { - ao_rn_dbg("get name...\n"); +// ao_rn_dbg("get name...\n"); ao_rn_send_cmd(AO_RN_GET_NAME_CMD, NULL); return ao_rn_wait_line(ao_time() + AO_RN_CMD_TIMEOUT, name, len); } @@ -404,12 +401,18 @@ ao_rn(void) continue; } - ao_rn_puts("$$$"); - /* After it reboots, it can take a moment before it responds * to commands */ - (void) ao_rn_wait_for(AO_RN_REBOOT_TIMEOUT, "CMD> "); + status = ao_rn_wait_for(AO_RN_REBOOT_TIMEOUT, "CMD> "); + + if (status == AO_RN_TIMEOUT) { + ao_rn_puts("$$$"); + (void) ao_rn_wait_for(AO_RN_REBOOT_TIMEOUT, "CMD> "); + } + + ao_rn_send_cmd(AO_RN_VERSION_CMD, NULL); + (void) ao_rn_wait_status(); /* Check to see if the name is already set and assume * that the device is ready to go @@ -417,7 +420,9 @@ ao_rn(void) status = ao_rn_get_name(name, sizeof (name)); if (status != AO_RN_OK) { ao_rn_dbg("get name failed\n"); - continue; + status = ao_rn_get_name(name, sizeof (name)); + if (status != AO_RN_OK) + continue; } if (strncmp(name, "TeleBT-", 7) == 0) { @@ -433,6 +438,12 @@ ao_rn(void) continue; } + ao_rn_send_cmd(AO_RN_SET_STATUS_STRING, AO_RN_STATUS_STRING_ENABLE); + if (ao_rn_wait_status() != AO_RN_OK) { + ao_rn_dbg("set status string\n"); + continue; + } + /* Select 'fast' mode to ignore command sequence (more or less) */ ao_rn_send_cmd(AO_RN_SET_FAST_MODE, NULL); if (ao_rn_wait_status() != AO_RN_OK) { @@ -465,17 +476,27 @@ ao_rn(void) ao_exti_enable(AO_RN_CONNECTED_PORT, AO_RN_CONNECTED_PIN); -#if 1 +#if AO_RN_DEBUG + + /* + * Separate debug code when things aren't working. Just dump + * inbound bluetooth characters to stdout + */ + for (;;) { + int c; + + ao_arch_block_interrupts(); + while ((c = _ao_rn_pollchar()) == AO_READ_AGAIN) + ao_sleep(&ao_serial_rn_rx_fifo); + ao_arch_release_interrupts(); + } +#else ao_rn_stdio = ao_add_stdio(_ao_wrap_rn_pollchar, - ao_wrap_rn_putchar, + ao_serial_rn_putchar, NULL); ao_rn_echo(0); - ao_rn_check_link(); - - ao_rn_dbg("RN running\n"); - /* * Now just hang around and flash the blue LED when we've got * a connection @@ -487,27 +508,11 @@ ao_rn(void) ao_arch_release_interrupts(); while (ao_rn_connected) { ao_led_for(AO_BT_LED, AO_MS_TO_TICKS(20)); + if (ao_rn_buf_cnt != 0) + ao_wakeup(&ao_stdin_ready); ao_delay(AO_SEC_TO_TICKS(3)); } } -#else - - /* - * Separate debug code when things aren't working. Just dump - * inbound bluetooth characters to stdout - */ - for (;;) { - int c; - - while (rn_cmd_running) - ao_delay(AO_MS_TO_TICKS(1000)); - - ao_arch_block_interrupts(); - while ((c = _ao_wrap_rn_pollchar()) == AO_READ_AGAIN) - ao_sleep(&ao_serial_rn_rx_fifo); - ao_arch_release_interrupts(); - putchar(c); flush(); - } #endif } @@ -539,19 +544,39 @@ ao_rn_factory(void) /* Right after power on, poke P3_1 five times to force a * factory reset */ - for (i = 0; i < 10; i++) { + for (i = 0; i < 20; i++) { v = 1-v; - ao_delay(AO_MS_TO_TICKS(100)); + ao_delay(AO_MS_TO_TICKS(50)); ao_gpio_set(AO_RN_P3_1_PORT, AO_RN_P3_1_PIN, foo, v); ao_led_toggle(AO_BT_LED); } /* And let P3_1 float again */ ao_enable_input(AO_RN_P3_1_PORT, AO_RN_P3_1_PIN, AO_EXTI_MODE_PULL_NONE); + + printf("Reboot BT\n"); flush(); + ao_delay(AO_MS_TO_TICKS(100)); + ao_gpio_set(AO_RN_RST_N_PORT, AO_RN_RST_N_PIN, foo, 0); + ao_delay(AO_MS_TO_TICKS(100)); + ao_gpio_set(AO_RN_RST_N_PORT, AO_RN_RST_N_PIN, foo, 1); } +#if AO_RN_DEBUG +static void +ao_rn_send(void) +{ + int c; + + while ((c = getchar()) != '~') + ao_rn_putchar(c); +} +#endif + static const struct ao_cmds rn_cmds[] = { { ao_rn_factory, "F\0Factory reset rn4678" }, +#if AO_RN_DEBUG + { ao_rn_send, "B\0Send data to rn4678. End with ~" }, +#endif { 0 }, }; diff --git a/src/drivers/ao_rn4678.h b/src/drivers/ao_rn4678.h index d6fea23a..a4dcea38 100644 --- a/src/drivers/ao_rn4678.h +++ b/src/drivers/ao_rn4678.h @@ -56,7 +56,7 @@ */ -#define AO_RN_REBOOT_MSG "%REBOOT%" +#define AO_RN_REBOOT_MSG "REBOOT" #define AO_RN_CMD_TIMEOUT AO_MS_TO_TICKS(200) @@ -67,11 +67,14 @@ #define AO_RN_SET_NAME_CMD "SN," #define AO_RN_GET_NAME_CMD "GN" -#define AO_RN_SET_STATUS_STRING "SO," +#define AO_RN_SET_STATUS_STRING "so," #define AO_RN_STATUS_STRING_DISABLE " " +#define AO_RN_STATUS_STRING_ENABLE "%,%" #define AO_RN_REBOOT_CMD "R,1" +#define AO_RN_VERSION_CMD "V" + #define AO_RN_TIMEOUT -1 #define AO_RN_ERROR 0 #define AO_RN_OK 1 diff --git a/src/easymini-v1.0/ao_pins.h b/src/easymini-v1.0/ao_pins.h index 5983bb9e..45c6891d 100644 --- a/src/easymini-v1.0/ao_pins.h +++ b/src/easymini-v1.0/ao_pins.h @@ -42,7 +42,7 @@ #define PACKET_HAS_SLAVE 0 -#define AO_LOG_FORMAT AO_LOG_FORMAT_EASYMINI +#define AO_LOG_FORMAT AO_LOG_FORMAT_EASYMINI1 /* USART */ diff --git a/src/easymini-v2.0/ao_pins.h b/src/easymini-v2.0/ao_pins.h index c141d1a6..2ec0e90b 100644 --- a/src/easymini-v2.0/ao_pins.h +++ b/src/easymini-v2.0/ao_pins.h @@ -44,7 +44,7 @@ #define AO_PA11_PA12_RMP 1 #define AO_USB_FORCE_IDLE 1 -#define AO_LOG_FORMAT AO_LOG_FORMAT_EASYMINI +#define AO_LOG_FORMAT AO_LOG_FORMAT_EASYMINI2 #define HAS_BOOT_RADIO 0 diff --git a/src/kernel/ao_log.h b/src/kernel/ao_log.h index 5c568c99..aca669db 100644 --- a/src/kernel/ao_log.h +++ b/src/kernel/ao_log.h @@ -45,7 +45,7 @@ extern __pdata enum ao_flight_state ao_log_state; #define AO_LOG_FORMAT_TELEMETRY 3 /* 32 byte ao_telemetry records */ #define AO_LOG_FORMAT_TELESCIENCE 4 /* 32 byte typed telescience records */ #define AO_LOG_FORMAT_TELEMEGA_OLD 5 /* 32 byte typed telemega records */ -#define AO_LOG_FORMAT_EASYMINI 6 /* 16-byte MS5607 baro only, 3.0V supply */ +#define AO_LOG_FORMAT_EASYMINI1 6 /* 16-byte MS5607 baro only, 3.0V supply */ #define AO_LOG_FORMAT_TELEMETRUM 7 /* 16-byte typed telemetrum records */ #define AO_LOG_FORMAT_TELEMINI2 8 /* 16-byte MS5607 baro only, 3.3V supply, cc1111 SoC */ #define AO_LOG_FORMAT_TELEGPS 9 /* 32 byte telegps records */ @@ -53,6 +53,7 @@ extern __pdata enum ao_flight_state ao_log_state; #define AO_LOG_FORMAT_DETHERM 11 /* 16-byte MS5607 baro only, no ADC */ #define AO_LOG_FORMAT_TELEMINI3 12 /* 16-byte MS5607 baro only, 3.3V supply, stm32f042 SoC */ #define AO_LOG_FORMAT_TELEFIRETWO 13 /* 32-byte test stand data */ +#define AO_LOG_FORMAT_EASYMINI2 14 /* 16-byte MS5607 baro only, 3.3V supply, stm32f042 SoC */ #define AO_LOG_FORMAT_NONE 127 /* No log at all */ extern __code uint8_t ao_log_format; @@ -252,8 +253,8 @@ struct ao_log_mega { int16_t gyro_y; /* 20 */ int16_t gyro_z; /* 22 */ int16_t mag_x; /* 24 */ - int16_t mag_y; /* 26 */ - int16_t mag_z; /* 28 */ + int16_t mag_z; /* 26 */ + int16_t mag_y; /* 28 */ int16_t accel; /* 30 */ } sensor; /* 32 */ /* AO_LOG_TEMP_VOLT */ diff --git a/src/kernel/ao_log_mega.c b/src/kernel/ao_log_mega.c index a0212198..b86abe7a 100644 --- a/src/kernel/ao_log_mega.c +++ b/src/kernel/ao_log_mega.c @@ -135,8 +135,8 @@ ao_log(void) #endif #if HAS_HMC5883 log.u.sensor.mag_x = ao_data_ring[ao_log_data_pos].hmc5883.x; - log.u.sensor.mag_y = ao_data_ring[ao_log_data_pos].hmc5883.y; log.u.sensor.mag_z = ao_data_ring[ao_log_data_pos].hmc5883.z; + log.u.sensor.mag_y = ao_data_ring[ao_log_data_pos].hmc5883.y; #endif log.u.sensor.accel = ao_data_accel(&ao_data_ring[ao_log_data_pos]); ao_log_mega(&log); diff --git a/src/kernel/ao_telemetry.c b/src/kernel/ao_telemetry.c index a4c73a86..2ae1e41b 100644 --- a/src/kernel/ao_telemetry.c +++ b/src/kernel/ao_telemetry.c @@ -160,8 +160,8 @@ ao_send_mega_sensor(void) #if HAS_HMC5883 telemetry.mega_sensor.mag_x = packet->hmc5883.x; - telemetry.mega_sensor.mag_y = packet->hmc5883.y; telemetry.mega_sensor.mag_z = packet->hmc5883.z; + telemetry.mega_sensor.mag_y = packet->hmc5883.y; #endif ao_telemetry_send(); diff --git a/src/kernel/ao_telemetry.h b/src/kernel/ao_telemetry.h index 45aaeb07..23e3ed7d 100644 --- a/src/kernel/ao_telemetry.h +++ b/src/kernel/ao_telemetry.h @@ -198,8 +198,8 @@ struct ao_telemetry_mega_sensor { int16_t gyro_z; /* 24 */ int16_t mag_x; /* 26 */ - int16_t mag_y; /* 28 */ - int16_t mag_z; /* 30 */ + int16_t mag_z; /* 28 */ + int16_t mag_y; /* 30 */ /* 32 */ }; diff --git a/src/micropeak-v2.0/ao_pins.h b/src/micropeak-v2.0/ao_pins.h index 13a4fd10..fa2ed804 100644 --- a/src/micropeak-v2.0/ao_pins.h +++ b/src/micropeak-v2.0/ao_pins.h @@ -53,7 +53,8 @@ extern uint8_t ao_on_battery; #define HAS_SERIAL_1 0 #define HAS_SERIAL_2 1 #define USE_SERIAL_2_STDIN 0 -#define HAS_SERIAL_SW_FLOW 0 +#define USE_SERIAL_2_FLOW 0 +#define USE_SERIAL_2_SW_FLOW 0 #define SERIAL_2_PA2_PA3 1 #define SERIAL_2_PA14_PA15 0 #define USE_SERIAL2_FLOW 0 diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index c625471e..ef562313 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -195,7 +195,7 @@ ao_usart_set_speed(struct ao_stm_usart *usart, uint8_t speed) } static void -ao_usart_init(struct ao_stm_usart *usart) +ao_usart_init(struct ao_stm_usart *usart, int hw_flow) { usart->reg->cr1 = ((0 << STM_USART_CR1_OVER8) | (1 << STM_USART_CR1_UE) | @@ -236,6 +236,10 @@ ao_usart_init(struct ao_stm_usart *usart) (0 << STM_USART_CR3_IREN) | (0 << STM_USART_CR3_EIE)); + if (hw_flow) + usart->reg->cr3 |= ((1 << STM_USART_CR3_CTSE) | + (1 << STM_USART_CR3_RTSE)); + /* Pick a 9600 baud rate */ ao_usart_set_speed(usart, AO_SERIAL_SPEED_9600); } @@ -244,8 +248,6 @@ ao_usart_init(struct ao_stm_usart *usart) static void ao_usart_set_flow(struct ao_stm_usart *usart) { - usart->reg->cr3 |= ((1 << STM_USART_CR3_CTSE) | - (1 << STM_USART_CR3_RTSE)); } #endif @@ -441,7 +443,7 @@ ao_serial_init(void) stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART1EN); ao_stm_usart1.reg = &stm_usart1; - ao_usart_init(&ao_stm_usart1); + ao_usart_init(&ao_stm_usart1, 0); stm_nvic_set_enable(STM_ISR_USART1_POS); stm_nvic_set_priority(STM_ISR_USART1_POS, AO_STM_NVIC_MED_PRIORITY); @@ -494,10 +496,7 @@ ao_serial_init(void) stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USART2EN); ao_stm_usart2.reg = &stm_usart2; - ao_usart_init(&ao_stm_usart2); -#if USE_SERIAL_2_FLOW && !USE_SERIAL_2_SW_FLOW - ao_usart_set_flow(&ao_stm_usart2); -#endif + ao_usart_init(&ao_stm_usart2, USE_SERIAL_2_FLOW && !USE_SERIAL_2_SW_FLOW); stm_nvic_set_enable(STM_ISR_USART2_POS); stm_nvic_set_priority(STM_ISR_USART2_POS, AO_STM_NVIC_MED_PRIORITY); @@ -541,7 +540,7 @@ ao_serial_init(void) stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USART3EN); ao_stm_usart3.reg = &stm_usart3; - ao_usart_init(&ao_stm_usart3); + ao_usart_init(&ao_stm_usart3, 0); stm_nvic_set_enable(STM_ISR_USART3_POS); stm_nvic_set_priority(STM_ISR_USART3_POS, AO_STM_NVIC_MED_PRIORITY); diff --git a/src/stmf0/ao_serial_stm.c b/src/stmf0/ao_serial_stm.c index e20b5755..59cfde2e 100644 --- a/src/stmf0/ao_serial_stm.c +++ b/src/stmf0/ao_serial_stm.c @@ -180,7 +180,7 @@ ao_usart_set_speed(struct ao_stm_usart *usart, uint8_t speed) } static void -ao_usart_init(struct ao_stm_usart *usart) +ao_usart_init(struct ao_stm_usart *usart, int hw_flow) { usart->reg->cr1 = ((0 << STM_USART_CR1_M1) | (0 << STM_USART_CR1_EOBIE) | @@ -223,44 +223,39 @@ ao_usart_init(struct ao_stm_usart *usart) (0 << STM_USART_CR2_LBDL) | (0 << STM_USART_CR2_ADDM7)); - usart->reg->cr3 = ((0 << STM_USART_CR3_WUFIE) | - (0 << STM_USART_CR3_WUS) | - (0 << STM_USART_CR3_SCARCNT) | - (0 << STM_USART_CR3_DEP) | - (0 << STM_USART_CR3_DEM) | - (0 << STM_USART_CR3_DDRE) | - (0 << STM_USART_CR3_OVRDIS) | - (0 << STM_USART_CR3_ONEBIT) | - (0 << STM_USART_CR3_CTIIE) | - (0 << STM_USART_CR3_CTSE) | - (0 << STM_USART_CR3_RTSE) | - (0 << STM_USART_CR3_DMAT) | - (0 << STM_USART_CR3_DMAR) | - (0 << STM_USART_CR3_SCEN) | - (0 << STM_USART_CR3_NACK) | - (0 << STM_USART_CR3_HDSEL) | - (0 << STM_USART_CR3_IRLP) | - (0 << STM_USART_CR3_IREN) | - (0 << STM_USART_CR3_EIE)); - + uint32_t cr3 = ((0 << STM_USART_CR3_WUFIE) | + (0 << STM_USART_CR3_WUS) | + (0 << STM_USART_CR3_SCARCNT) | + (0 << STM_USART_CR3_DEP) | + (0 << STM_USART_CR3_DEM) | + (0 << STM_USART_CR3_DDRE) | + (0 << STM_USART_CR3_OVRDIS) | + (0 << STM_USART_CR3_ONEBIT) | + (0 << STM_USART_CR3_CTIIE) | + (0 << STM_USART_CR3_CTSE) | + (0 << STM_USART_CR3_RTSE) | + (0 << STM_USART_CR3_DMAT) | + (0 << STM_USART_CR3_DMAR) | + (0 << STM_USART_CR3_SCEN) | + (0 << STM_USART_CR3_NACK) | + (0 << STM_USART_CR3_HDSEL) | + (0 << STM_USART_CR3_IRLP) | + (0 << STM_USART_CR3_IREN) | + (0 << STM_USART_CR3_EIE)); + + if (hw_flow) + cr3 |= ((1 << STM_USART_CR3_CTSE) | + (1 << STM_USART_CR3_RTSE)); + + usart->reg->cr3 = cr3; /* Pick a 9600 baud rate */ ao_usart_set_speed(usart, AO_SERIAL_SPEED_9600); /* Enable the usart */ usart->reg->cr1 |= (1 << STM_USART_CR1_UE); - } -#if HAS_SERIAL_HW_FLOW -static void -ao_usart_set_flow(struct ao_stm_usart *usart) -{ - usart->reg->cr3 |= ((1 << STM_USART_CR3_CTSE) | - (1 << STM_USART_CR3_RTSE)); -} -#endif - #if HAS_SERIAL_1 struct ao_stm_usart ao_stm_usart1; @@ -391,13 +386,13 @@ ao_serial_init(void) */ #if SERIAL_1_PA9_PA10 - stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN); + ao_enable_port(&stm_gpioa); stm_afr_set(&stm_gpioa, 9, STM_AFR_AF1); stm_afr_set(&stm_gpioa, 10, STM_AFR_AF1); #else #if SERIAL_1_PB6_PB7 - stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN); + ao_enable_port(&stm_gpiob); stm_afr_set(&stm_gpiob, 6, STM_AFR_AF0); stm_afr_set(&stm_gpiob, 7, STM_AFR_AF0); @@ -409,7 +404,7 @@ ao_serial_init(void) stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART1EN); ao_stm_usart1.reg = &stm_usart1; - ao_usart_init(&ao_stm_usart1); + ao_usart_init(&ao_stm_usart1, 0); stm_nvic_set_enable(STM_ISR_USART1_POS); stm_nvic_set_priority(STM_ISR_USART1_POS, 4); @@ -428,8 +423,7 @@ ao_serial_init(void) */ # if SERIAL_2_PA2_PA3 - stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN); - + ao_enable_port(&stm_gpioa); stm_afr_set(&stm_gpioa, 2, STM_AFR_AF1); stm_afr_set(&stm_gpioa, 3, STM_AFR_AF1); # if USE_SERIAL_2_FLOW @@ -447,8 +441,7 @@ ao_serial_init(void) # endif # else # if SERIAL_2_PA14_PA15 - stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN); - + ao_enable_port(&stm_gpioa); stm_afr_set(&stm_gpioa, 14, STM_AFR_AF1); stm_afr_set(&stm_gpioa, 15, STM_AFR_AF1); # if USE_SERIAL_2_FLOW @@ -472,10 +465,7 @@ ao_serial_init(void) stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USART2EN); ao_stm_usart2.reg = &stm_usart2; - ao_usart_init(&ao_stm_usart2); -# if USE_SERIAL_2_FLOW && !USE_SERIAL_2_SW_FLOW - ao_usart_set_flow(&ao_stm_usart2); -# endif + ao_usart_init(&ao_stm_usart2, USE_SERIAL_2_FLOW && !USE_SERIAL_2_SW_FLOW); stm_nvic_set_enable(STM_ISR_USART2_POS); stm_nvic_set_priority(STM_ISR_USART2_POS, 4); diff --git a/src/telebt-v3.0/Makefile b/src/telebt-v3.0/Makefile index 40d1f6e4..4636c046 100644 --- a/src/telebt-v3.0/Makefile +++ b/src/telebt-v3.0/Makefile @@ -55,6 +55,7 @@ ALTOS_SRC = \ ao_convert_volt.c \ ao_packet_master.c \ ao_packet.c \ + ao_send_packet.c \ ao_monitor.c \ $(PROFILE) \ $(SAMPLE_PROFILE) \ diff --git a/src/telebt-v3.0/ao_telebt.c b/src/telebt-v3.0/ao_telebt.c index 8775d993..63633c90 100644 --- a/src/telebt-v3.0/ao_telebt.c +++ b/src/telebt-v3.0/ao_telebt.c @@ -23,6 +23,7 @@ #include #include #include +#include #if HAS_SAMPLE_PROFILE #include #endif @@ -53,6 +54,7 @@ main(void) ao_radio_init(); ao_packet_master_init(); ao_monitor_init(); + ao_send_packet_init(); ao_config_init(); diff --git a/src/telebt-v4.0/Makefile b/src/telebt-v4.0/Makefile index 31651120..38ac7513 100644 --- a/src/telebt-v4.0/Makefile +++ b/src/telebt-v4.0/Makefile @@ -14,6 +14,7 @@ INC = \ ao_product.h \ ao_cc1200_CC1200.h \ ao_task.h \ + ao_rn4678.h \ stm32f0.h \ Makefile diff --git a/src/telebt-v4.0/ao_pins.h b/src/telebt-v4.0/ao_pins.h index baf3db69..f3d70d1a 100644 --- a/src/telebt-v4.0/ao_pins.h +++ b/src/telebt-v4.0/ao_pins.h @@ -54,7 +54,7 @@ #define USE_SERIAL_2_STDIN 1 #define DELAY_SERIAL_2_STDIN 1 #define USE_SERIAL_2_FLOW 1 -#define USE_SERIAL_2_SW_FLOW 1 +#define USE_SERIAL_2_SW_FLOW 0 #define SERIAL_2_PA2_PA3 1 #define SERIAL_2_PD5_PD6 0 #define SERIAL_2_PORT_RTS (&stm_gpioa) @@ -75,7 +75,6 @@ #define HAS_APRS 0 #define HAS_ACCEL 0 #define HAS_AES 0 -#define HAS_POLLCHAR 1 #define HAS_SPI_1 1 #define SPI_1_PA5_PA6_PA7 1 /* CC1200 */ diff --git a/src/telefireone-v1.0/ao_pins.h b/src/telefireone-v1.0/ao_pins.h index b2f5a5ab..d36d9d82 100644 --- a/src/telefireone-v1.0/ao_pins.h +++ b/src/telefireone-v1.0/ao_pins.h @@ -34,7 +34,7 @@ #define HAS_EEPROM 1 #define HAS_LOG 1 #define HAS_PAD 1 -#define USE_INTERNAL_FLASH 0 +#define USE_INTERNAL_FLASH 1 #define IGNITE_ON_P0 0 #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 0 diff --git a/src/test/Makefile b/src/test/Makefile index a22abe46..a0c2d5fe 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -1,7 +1,7 @@ vpath % ..:../kernel:../drivers:../util:../micropeak:../aes:../product:../lisp PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_flight_test_mm \ - ao_flight_test_metrum \ + ao_flight_test_metrum ao_flight_test_mini \ ao_gps_test ao_gps_test_skytraq ao_gps_test_ublox ao_convert_test ao_convert_pa_test ao_fec_test \ ao_aprs_test ao_micropeak_test ao_fat_test ao_aes_test ao_int64_test \ ao_ms5607_convert_test ao_quaternion_test ao_lisp_test @@ -37,6 +37,9 @@ ao_flight_test_mm: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman. ao_flight_test_metrum: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c ao_pyro.c ao_pyro.h $(INCS) cc -DTELEMETRUM_V2=1 $(CFLAGS) -o $@ $< -lm +ao_flight_test_mini: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c ao_pyro.c ao_pyro.h $(INCS) + cc -DEASYMINI=1 -DHAS_ACCEL=0 $(CFLAGS) -o $@ $< -lm + ao_gps_test: ao_gps_test.c ao_gps_sirf.c ao_gps_print.c ao_host.h cc $(CFLAGS) -o $@ $< diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index 25ddb48f..d3d39f2a 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -46,7 +46,7 @@ int ao_gps_new; -#if !defined(TELEMEGA) && !defined(TELEMETRUM_V2) +#if !defined(TELEMEGA) && !defined(TELEMETRUM_V2) && !defined(EASYMINI) #define TELEMETRUM_V1 1 #endif @@ -84,6 +84,18 @@ struct ao_adc { }; #endif +#if EASYMINI +#define AO_ADC_NUM_SENSE 2 +#define HAS_MS5607 1 +#define HAS_BEEP 1 +#define AO_CONFIG_MAX_SIZE 1024 + +struct ao_adc { + int16_t sense_a; + int16_t sense_m; + int16_t v_batt; +}; +#endif #if TELEMETRUM_V1 /* @@ -323,7 +335,7 @@ struct ao_cmds { #define ao_xmemcmp(d,s,c) memcmp(d,s,c) #define AO_NEED_ALTITUDE_TO_PRES 1 -#if TELEMEGA || TELEMETRUM_V2 +#if TELEMEGA || TELEMETRUM_V2 || EASYMINI #include "ao_convert_pa.c" #include struct ao_ms5607_prom ao_ms5607_prom; @@ -475,7 +487,7 @@ ao_insert(void) #else double accel = 0.0; #endif -#if TELEMEGA || TELEMETRUM_V2 +#if TELEMEGA || TELEMETRUM_V2 || EASYMINI double height; ao_ms5607_convert(&ao_data_static.ms5607_raw, &ao_data_static.ms5607_cooked); @@ -670,6 +682,19 @@ int32(uint8_t *bytes, int off) return (int32_t) uint32(bytes, off); } +uint32_t +uint24(uint8_t *bytes, int off) +{ + return (uint32_t) bytes[off] | (((uint32_t) bytes[off+1]) << 8) | + (((uint32_t) bytes[off+2]) << 16); +} + +int32_t +int24(uint8_t *bytes, int off) +{ + return (int32_t) uint24(bytes, off); +} + static int log_format; void @@ -694,12 +719,14 @@ ao_sleep(void *wchan) for (;;) { if (ao_records_read > 2 && ao_flight_state == ao_flight_startup) { + #if TELEMEGA ao_data_static.mpu6000 = ao_ground_mpu6000; #endif #if TELEMETRUM_V1 ao_data_static.adc.accel = ao_flight_ground_accel; #endif + ao_insert(); return; } @@ -829,6 +856,72 @@ ao_sleep(void *wchan) } } #endif +#if EASYMINI + if ((log_format == AO_LOG_FORMAT_EASYMINI1 || log_format == AO_LOG_FORMAT_EASYMINI2) && nword == 14 && strlen(words[0]) == 1) { + int i; + struct ao_ms5607_value value; + + type = words[0][0]; + tick = strtoul(words[1], NULL, 16); +// printf ("%c %04x", type, tick); + for (i = 2; i < nword; i++) { + bytes[i - 2] = strtoul(words[i], NULL, 16); +// printf(" %02x", bytes[i-2]); + } +// printf ("\n"); + switch (type) { + case 'F': + ao_flight_started = 1; + ao_ground_pres = uint32(bytes, 4); + ao_ground_height = ao_pa_to_altitude(ao_ground_pres); +#if 0 + printf("ground pres %d height %d\n", ao_ground_pres, ao_ground_height); + printf("sens %d off %d tcs %d tco %d tref %d tempsens %d crc %d\n", + ao_ms5607_prom.sens, + ao_ms5607_prom.off, + ao_ms5607_prom.tcs, + ao_ms5607_prom.tco, + ao_ms5607_prom.tref, + ao_ms5607_prom.tempsens, + ao_ms5607_prom.crc); +#endif + break; + case 'A': + ao_data_static.tick = tick; + ao_data_static.ms5607_raw.pres = int24(bytes, 0); + ao_data_static.ms5607_raw.temp = int24(bytes, 3); +#if 0 + printf("raw pres %d temp %d\n", + ao_data_static.ms5607_raw.pres, + ao_data_static.ms5607_raw.temp); +#endif + ao_ms5607_convert(&ao_data_static.ms5607_raw, &value); +// printf("pres %d height %d\n", value.pres, ao_pa_to_altitude(value.pres)); + ao_records_read++; + ao_insert(); + return; + } + continue; + } else if (nword == 3 && strcmp(words[0], "ms5607") == 0) { + if (strcmp(words[1], "reserved:") == 0) + ao_ms5607_prom.reserved = strtoul(words[2], NULL, 10); + else if (strcmp(words[1], "sens:") == 0) + ao_ms5607_prom.sens = strtoul(words[2], NULL, 10); + else if (strcmp(words[1], "off:") == 0) + ao_ms5607_prom.off = strtoul(words[2], NULL, 10); + else if (strcmp(words[1], "tcs:") == 0) + ao_ms5607_prom.tcs = strtoul(words[2], NULL, 10); + else if (strcmp(words[1], "tco:") == 0) + ao_ms5607_prom.tco = strtoul(words[2], NULL, 10); + else if (strcmp(words[1], "tref:") == 0) + ao_ms5607_prom.tref = strtoul(words[2], NULL, 10); + else if (strcmp(words[1], "tempsens:") == 0) + ao_ms5607_prom.tempsens = strtoul(words[2], NULL, 10); + else if (strcmp(words[1], "crc:") == 0) + ao_ms5607_prom.crc = strtoul(words[2], NULL, 10); + continue; + } +#endif #if TELEMETRUM_V2 if (log_format == AO_LOG_FORMAT_TELEMETRUM && nword == 14 && strlen(words[0]) == 1) { int i; @@ -1007,7 +1100,7 @@ ao_sleep(void *wchan) if (type != 'F' && !ao_flight_started) continue; -#if TELEMEGA || TELEMETRUM_V2 +#if TELEMEGA || TELEMETRUM_V2 || EASYMINI (void) a; (void) b; #else diff --git a/telegps/TeleGPS.java b/telegps/TeleGPS.java index cf2cbd4f..3646f000 100644 --- a/telegps/TeleGPS.java +++ b/telegps/TeleGPS.java @@ -25,8 +25,8 @@ import java.io.*; import java.util.concurrent.*; import java.util.*; import java.text.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class TeleGPS extends AltosUIFrame @@ -152,7 +152,7 @@ public class TeleGPS status_update.saved_listener_state = listener_state; if (state == null) - state = new AltosState(); + state = new AltosState(new AltosCalData()); int i = 0; for (AltosFlightDisplay display : displays) { @@ -287,23 +287,30 @@ public class TeleGPS new TeleGPSConfig(this); } + private static AltosFlightSeries make_series(AltosRecordSet set) { + AltosFlightSeries series = new AltosFlightSeries(set.cal_data()); + set.capture_series(series); + series.finish(); + return series; + } + void export() { - AltosDataChooser chooser; - chooser = new AltosDataChooser(this); - AltosStateIterable states = chooser.runDialog(); - if (states == null) + AltosDataChooser chooser = new AltosDataChooser(this); + + AltosRecordSet set = chooser.runDialog(); + if (set == null) return; - new AltosCSVUI(this, states, chooser.file()); + AltosFlightSeries series = make_series(set); + new AltosCSVUI(this, series, chooser.file()); } void graph() { - AltosDataChooser chooser; - chooser = new AltosDataChooser(this); - AltosStateIterable states = chooser.runDialog(); - if (states == null) + AltosDataChooser chooser = new AltosDataChooser(this); + AltosRecordSet set = chooser.runDialog(); + if (set == null) return; try { - new TeleGPSGraphUI(states, chooser.file()); + new TeleGPSGraphUI(set, chooser.file()); } catch (InterruptedException ie) { } catch (IOException ie) { } @@ -612,40 +619,28 @@ public class TeleGPS connect(device); } - static AltosStateIterable record_iterable(File file) { - FileInputStream in; - if (file.getName().endsWith("telem")) { - try { - in = new FileInputStream(file); - return new AltosTelemetryFile(in); - } catch (Exception e) { - System.out.printf("Failed to open file '%s'\n", file); - } - } else { - - try { - AltosEepromFile f = new AltosEepromFile(new FileReader(file)); - return f; - } catch (Exception e) { - System.out.printf("Failed to open file '%s'\n", file); - } + static AltosRecordSet record_set(File file) { + try { + return AltosLib.record_set(file); + } catch (IOException ie) { + System.out.printf("%s\n", ie.getMessage()); } return null; } static AltosReplayReader replay_file(File file) { - AltosStateIterable states = record_iterable(file); - if (states == null) + AltosRecordSet set = record_set(file); + if (set == null) return null; - return new AltosReplayReader(states.iterator(), file); + return new AltosReplayReader(set, file); } static boolean process_graph(File file) { - AltosStateIterable states = record_iterable(file); - if (states == null) + AltosRecordSet set = record_set(file); + if (set == null) return false; try { - new TeleGPSGraphUI(states, file); + new TeleGPSGraphUI(set, file); } catch (Exception e) { return false; } diff --git a/telegps/TeleGPSConfig.java b/telegps/TeleGPSConfig.java index d24e7471..7fc15ba9 100644 --- a/telegps/TeleGPSConfig.java +++ b/telegps/TeleGPSConfig.java @@ -23,8 +23,8 @@ import javax.swing.*; import java.io.*; import java.util.concurrent.*; import java.text.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class TeleGPSConfig implements ActionListener { diff --git a/telegps/TeleGPSConfigUI.java b/telegps/TeleGPSConfigUI.java index dd3965b4..88ced192 100644 --- a/telegps/TeleGPSConfigUI.java +++ b/telegps/TeleGPSConfigUI.java @@ -23,8 +23,8 @@ import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class TeleGPSConfigUI extends AltosUIDialog @@ -131,7 +131,7 @@ public class TeleGPSConfigUI } public double pyro_firing_time() { - return -1; + return AltosLib.MISSING; } boolean is_telemetrum() { @@ -140,46 +140,46 @@ public class TeleGPSConfigUI } void set_radio_enable_tool_tip() { - if (radio_enable_value.isEnabled()) + if (radio_enable_value.isVisible()) radio_enable_value.setToolTipText("Enable/Disable telemetry and RDF transmissions"); else radio_enable_value.setToolTipText("Firmware version does not support disabling radio"); } void set_rate_tool_tip() { - if (rate_value.isEnabled()) + if (rate_value.isVisible()) rate_value.setToolTipText("Select telemetry baud rate"); else rate_value.setToolTipText("Firmware version does not support variable telemetry rates"); } void set_aprs_interval_tool_tip() { - if (aprs_interval_value.isEnabled()) + if (aprs_interval_value.isVisible()) aprs_interval_value.setToolTipText("Enable APRS and set the interval between APRS reports"); else aprs_interval_value.setToolTipText("Hardware doesn't support APRS"); } void set_aprs_ssid_tool_tip() { - if (aprs_ssid_value.isEnabled()) + if (aprs_ssid_value.isVisible()) aprs_ssid_value.setToolTipText("Set the APRS SSID (secondary station identifier)"); - else if (aprs_ssid_value.isEnabled()) + else if (aprs_ssid_value.isVisible()) aprs_ssid_value.setToolTipText("Software version doesn't support setting the APRS SSID"); else aprs_ssid_value.setToolTipText("Hardware doesn't support APRS"); } void set_aprs_format_tool_tip() { - if (aprs_format_value.isEnabled()) + if (aprs_format_value.isVisible()) aprs_format_value.setToolTipText("Set the APRS format (compressed/uncompressed)"); - else if (aprs_format_value.isEnabled()) + else if (aprs_format_value.isVisible()) aprs_format_value.setToolTipText("Software version doesn't support setting the APRS format"); else aprs_format_value.setToolTipText("Hardware doesn't support APRS"); } void set_flight_log_max_tool_tip() { - if (flight_log_max_value.isEnabled()) + if (flight_log_max_value.isVisible()) flight_log_max_value.setToolTipText("Size reserved for each flight log (in kB)"); else flight_log_max_value.setToolTipText("Cannot set max value with flight logs in memory"); @@ -675,7 +675,7 @@ public class TeleGPSConfigUI public void units_changed(boolean imperial_units) { boolean was_dirty = dirty; - if (tracker_motion_value.isEnabled()) { + if (tracker_motion_value.isVisible()) { String motion = tracker_motion_value.getSelectedItem().toString(); tracker_motion_label.setText(get_tracker_motion_label()); set_tracker_motion_values(); @@ -712,21 +712,24 @@ public class TeleGPSConfigUI } public int main_deploy() { - return -1; + return AltosLib.MISSING; } public void set_apogee_delay(int new_apogee_delay) { } public int apogee_delay() { - return -1; + return AltosLib.MISSING; } public void set_apogee_lockout(int new_apogee_lockout) { } - public int apogee_lockout() { return -1; } + public int apogee_lockout() { return AltosLib.MISSING; } public void set_radio_frequency(double new_radio_frequency) { - radio_frequency_value.set_frequency(new_radio_frequency); + if (new_radio_frequency != AltosLib.MISSING) + radio_frequency_value.set_frequency(new_radio_frequency); + radio_frequency_label.setVisible(new_radio_frequency != AltosLib.MISSING); + radio_frequency_value.setVisible(new_radio_frequency != AltosLib.MISSING); } public double radio_frequency() { @@ -734,45 +737,32 @@ public class TeleGPSConfigUI } public void set_radio_calibration(int new_radio_calibration) { - radio_calibration_value.setVisible(new_radio_calibration >= 0); - if (new_radio_calibration < 0) - radio_calibration_value.setText("Disabled"); - else + if (new_radio_calibration != AltosLib.MISSING) radio_calibration_value.setText(String.format("%d", new_radio_calibration)); - } - - private int parse_int(String name, String s, boolean split) throws AltosConfigDataException { - String v = s; - if (split) - v = s.split("\\s+")[0]; - try { - return Integer.parseInt(v); - } catch (NumberFormatException ne) { - throw new AltosConfigDataException("Invalid %s \"%s\"", name, s); - } + radio_calibration_value.setVisible(new_radio_calibration == AltosLib.MISSING); + radio_calibration_label.setVisible(new_radio_calibration == AltosLib.MISSING); } public void set_radio_enable(int new_radio_enable) { - if (new_radio_enable >= 0) { - radio_enable_value.setSelected(new_radio_enable > 0); - radio_enable_value.setEnabled(true); - } else { - radio_enable_value.setSelected(true); - radio_enable_value.setVisible(radio_frequency() > 0); - radio_enable_value.setEnabled(false); - } + if (new_radio_enable != AltosLib.MISSING) + radio_enable_value.setSelected(new_radio_enable != 0); + radio_enable_label.setVisible(new_radio_enable != AltosLib.MISSING); + radio_enable_value.setVisible(new_radio_enable != AltosLib.MISSING); set_radio_enable_tool_tip(); } public int radio_enable() { - if (radio_enable_value.isEnabled()) + if (radio_enable_value.isVisible()) return radio_enable_value.isSelected() ? 1 : 0; else - return -1; + return AltosLib.MISSING; } public void set_telemetry_rate(int new_rate) { - rate_value.set_rate(new_rate); + if (new_rate != AltosLib.MISSING) + rate_value.set_rate(new_rate); + rate_label.setVisible(new_rate != AltosLib.MISSING); + rate_value.setVisible(new_rate != AltosLib.MISSING); } public int telemetry_rate() { @@ -780,12 +770,27 @@ public class TeleGPSConfigUI } public void set_callsign(String new_callsign) { + if (new_callsign != null) + callsign_value.setText(new_callsign); callsign_value.setVisible(new_callsign != null); - callsign_value.setText(new_callsign); + callsign_label.setVisible(new_callsign != null); } public String callsign() { - return callsign_value.getText(); + if (callsign_value.isVisible()) + return callsign_value.getText(); + return null; + } + + private int parse_int(String name, String s, boolean split) throws AltosConfigDataException { + String v = s; + if (split) + v = s.split("\\s+")[0]; + try { + return Integer.parseInt(v); + } catch (NumberFormatException ne) { + throw new AltosConfigDataException("Invalid %s \"%s\"", name, s); + } } int flight_log_max_limit; @@ -828,15 +833,15 @@ public class TeleGPSConfigUI } public void set_ignite_mode(int new_ignite_mode) { } - public int ignite_mode() { return -1; } + public int ignite_mode() { return AltosLib.MISSING; } public void set_pad_orientation(int new_pad_orientation) { } - public int pad_orientation() { return -1; } + public int pad_orientation() { return AltosLib.MISSING; } public void set_beep(int new_beep) { } - public int beep() { return -1; } + public int beep() { return AltosLib.MISSING; } String[] tracker_motion_values() { if (AltosConvert.imperial_units) @@ -859,87 +864,92 @@ public class TeleGPSConfigUI } void set_tracker_tool_tip() { - if (tracker_motion_value.isEnabled()) + if (tracker_motion_value.isVisible()) tracker_motion_value.setToolTipText("How far the device must move before logging"); else tracker_motion_value.setToolTipText("This device doesn't disable logging when stationary"); - if (tracker_interval_value.isEnabled()) + if (tracker_interval_value.isVisible()) tracker_interval_value.setToolTipText("How often to report GPS position"); else tracker_interval_value.setToolTipText("This device can't configure interval"); } public void set_tracker_motion(int tracker_motion) { - if (tracker_motion < 0) { - tracker_motion_value.setEnabled(false); - } else { - tracker_motion_value.setEnabled(true); + if (tracker_motion != AltosLib.MISSING) tracker_motion_value.setSelectedItem(AltosConvert.height.say(tracker_motion)); - } + tracker_motion_label.setVisible(tracker_motion != AltosLib.MISSING); + tracker_motion_value.setVisible(tracker_motion != AltosLib.MISSING); } public int tracker_motion() throws AltosConfigDataException { - String str = tracker_motion_value.getSelectedItem().toString(); - try { - return (int) (AltosConvert.height.parse_locale(str) + 0.5); - } catch (ParseException pe) { - throw new AltosConfigDataException("invalid tracker motion %s", str); + if (tracker_motion_value.isVisible()) { + String str = tracker_motion_value.getSelectedItem().toString(); + try { + return (int) (AltosConvert.height.parse_locale(str) + 0.5); + } catch (ParseException pe) { + throw new AltosConfigDataException("invalid tracker motion %s", str); + } } + return AltosLib.MISSING; } public void set_tracker_interval(int tracker_interval) { - if (tracker_interval< 0) { - tracker_interval_value.setEnabled(false); - } else { - tracker_interval_value.setEnabled(true); + if (tracker_interval != AltosLib.MISSING) tracker_interval_value.setSelectedItem(String.format("%d", tracker_interval)); - } + tracker_interval_label.setVisible(tracker_interval != AltosLib.MISSING); + tracker_interval_value.setVisible(tracker_interval != AltosLib.MISSING); } public int tracker_interval() throws AltosConfigDataException { - return parse_int ("tracker interval", tracker_interval_value.getSelectedItem().toString(), false); + if (tracker_interval_value.isVisible()) + return parse_int ("tracker interval", tracker_interval_value.getSelectedItem().toString(), false); + return AltosLib.MISSING; } public void set_aprs_interval(int new_aprs_interval) { - String s; - - if (new_aprs_interval <= 0) - s = "Disabled"; - else - s = Integer.toString(new_aprs_interval); - aprs_interval_value.setSelectedItem(s); - aprs_interval_value.setVisible(new_aprs_interval >= 0); + if (new_aprs_interval != AltosLib.MISSING) + aprs_interval_value.setSelectedItem(Integer.toString(new_aprs_interval)); + aprs_interval_value.setVisible(new_aprs_interval != AltosLib.MISSING); + aprs_interval_label.setVisible(new_aprs_interval != AltosLib.MISSING); set_aprs_interval_tool_tip(); } public int aprs_interval() throws AltosConfigDataException { - String s = aprs_interval_value.getSelectedItem().toString(); + if (aprs_interval_value.isVisible()) { + String s = aprs_interval_value.getSelectedItem().toString(); - if (s.equals("Disabled")) - return 0; - return parse_int("aprs interval", s, false); + return parse_int("aprs interval", s, false); + } + return AltosLib.MISSING; } public void set_aprs_ssid(int new_aprs_ssid) { - aprs_ssid_value.setSelectedItem(Math.max(0,new_aprs_ssid)); - aprs_ssid_value.setVisible(new_aprs_ssid >= 0); + if (new_aprs_ssid != AltosLib.MISSING) + aprs_ssid_value.setSelectedItem(new_aprs_ssid); + aprs_ssid_value.setVisible(new_aprs_ssid != AltosLib.MISSING); + aprs_ssid_label.setVisible(new_aprs_ssid != AltosLib.MISSING); set_aprs_ssid_tool_tip(); } public int aprs_ssid() throws AltosConfigDataException { - Integer i = (Integer) aprs_ssid_value.getSelectedItem(); - return i; + if (aprs_ssid_value.isVisible()) { + Integer i = (Integer) aprs_ssid_value.getSelectedItem(); + return i; + } + return AltosLib.MISSING; } public void set_aprs_format(int new_aprs_format) { - aprs_format_value.setVisible(new_aprs_format >= 0); - aprs_format_label.setVisible(new_aprs_format >= 0); - - aprs_format_value.setSelectedIndex(Math.max(0,new_aprs_format)); + if (new_aprs_format != AltosLib.MISSING) + aprs_format_value.setSelectedIndex(new_aprs_format); + aprs_format_value.setVisible(new_aprs_format != AltosLib.MISSING); + aprs_format_label.setVisible(new_aprs_format != AltosLib.MISSING); set_aprs_format_tool_tip(); } public int aprs_format() throws AltosConfigDataException { - return aprs_format_value.getSelectedIndex(); + if (aprs_format_value.isVisible()) + return aprs_format_value.getSelectedIndex(); + return AltosLib.MISSING; } } diff --git a/telegps/TeleGPSDisplayThread.java b/telegps/TeleGPSDisplayThread.java index a9c80dc0..fdf0e201 100644 --- a/telegps/TeleGPSDisplayThread.java +++ b/telegps/TeleGPSDisplayThread.java @@ -22,8 +22,8 @@ import java.awt.*; import javax.swing.*; import java.io.*; import java.text.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class TeleGPSDisplayThread extends Thread { @@ -31,7 +31,9 @@ public class TeleGPSDisplayThread extends Thread { IdleThread idle_thread; AltosVoice voice; AltosFlightReader reader; - AltosState old_state, state; + AltosState state; + int old_state = AltosLib.ao_flight_invalid; + boolean old_gps_ready = false; AltosListenerState listener_state; AltosFlightDisplay display; @@ -130,11 +132,12 @@ public class TeleGPSDisplayThread extends Thread { } public synchronized void notice(boolean spoken) { - if (old_state != null && old_state.state() != state.state()) { + if (old_state != state.state()) { report_time = now(); this.notify(); } else if (spoken) set_report_time(); + old_state = state.state(); } public IdleThread() { @@ -144,17 +147,17 @@ public class TeleGPSDisplayThread extends Thread { synchronized boolean tell() { boolean ret = false; - if (old_state == null || old_state.gps_ready != state.gps_ready) { + if (old_gps_ready != state.gps_ready) { if (state.gps_ready) { voice.speak("GPS ready"); ret = true; } - else if (old_state != null) { + else if (old_gps_ready) { voice.speak("GPS lost"); ret = true; } + old_gps_ready = state.gps_ready; } - old_state = state; return ret; } @@ -173,7 +176,6 @@ public class TeleGPSDisplayThread extends Thread { listener_state.running = false; break; } - reader.update(state); show_safely(); told = tell(); idle_thread.notice(told); diff --git a/telegps/TeleGPSGraphUI.java b/telegps/TeleGPSGraphUI.java index 55ee370e..9d8c6bf5 100644 --- a/telegps/TeleGPSGraphUI.java +++ b/telegps/TeleGPSGraphUI.java @@ -27,14 +27,14 @@ import javax.swing.*; import java.io.*; import java.util.concurrent.*; import java.util.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.ui.RefineryUtilities; -public class TeleGPSGraphUI extends AltosUIFrame +public class TeleGPSGraphUI extends AltosUIFrame implements AltosFontListener, AltosUnitsListener { JTabbedPane pane; AltosGraph graph; @@ -42,13 +42,33 @@ public class TeleGPSGraphUI extends AltosUIFrame AltosUIMap map; AltosState state; AltosFlightStats stats; - AltosGraphDataSet graphDataSet; AltosFlightStatsTable statsTable; - - void fill_map(AltosStateIterable states) { - for (AltosState state : states) { - if (state.gps != null && state.gps.locked && state.gps.nsat >= 4) - map.show(state, null); + AltosGPS gps; + boolean has_gps; + + void fill_map(AltosFlightSeries flight_series) { + boolean any_gps = false; + AltosGPSTimeValue gtv_last = null; + + if (flight_series.gps_series != null) { + for (AltosGPSTimeValue gtv : flight_series.gps_series) { + gtv_last = gtv; + AltosGPS gps = gtv.gps; + if (gps != null && + gps.locked && + gps.nsat >= 4) { + if (map == null) + map = new AltosUIMap(); + map.show(gps, (int) flight_series.value_before(AltosFlightSeries.state_name, gtv.time)); + this.gps = gps; + has_gps = true; + } + } + } + if (gtv_last != null) { + int state = (int) flight_series.value_after(AltosFlightSeries.state_name, gtv_last.time); + if (state == AltosLib.ao_flight_landed) + map.show(gtv_last.gps, state); } } @@ -58,16 +78,35 @@ public class TeleGPSGraphUI extends AltosUIFrame TeleGPS.subtract_window(); } - TeleGPSGraphUI(AltosStateIterable states, File file) throws InterruptedException, IOException { + public void font_size_changed(int font_size) { + if (map != null) + map.font_size_changed(font_size); + if (statsTable != null) + statsTable.font_size_changed(font_size); + } + + public void units_changed(boolean imperial_units) { + if (map != null) + map.units_changed(imperial_units); + if (enable != null) + enable.units_changed(imperial_units); + } + + TeleGPSGraphUI(AltosRecordSet set, File file) throws InterruptedException, IOException { super(file.getName()); - state = null; + AltosCalData cal_data = set.cal_data(); + + AltosUIFlightSeries flight_series = new AltosUIFlightSeries(cal_data); + set.capture_series(flight_series); + flight_series.finish(); pane = new JTabbedPane(); enable = new AltosUIEnable(); - stats = new AltosFlightStats(states); - graphDataSet = new AltosGraphDataSet(states); - graph = new AltosGraph(enable, stats, graphDataSet); + stats = new AltosFlightStats(flight_series); + + graph = new AltosGraph(enable, stats, flight_series); + statsTable = new AltosFlightStatsTable(stats); map = new AltosUIMap(); @@ -75,11 +114,14 @@ public class TeleGPSGraphUI extends AltosUIFrame pane.add("Graph", graph.panel); pane.add("Configure Graph", enable); pane.add("Statistics", statsTable); - fill_map(states); + fill_map(flight_series); pane.add("Map", map); setContentPane (pane); + AltosUIPreferences.register_font_listener(this); + AltosPreferences.register_units_listener(this); + addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { diff --git a/telegps/TeleGPSInfo.java b/telegps/TeleGPSInfo.java index f4fa7216..383a0a44 100644 --- a/telegps/TeleGPSInfo.java +++ b/telegps/TeleGPSInfo.java @@ -22,8 +22,8 @@ import java.util.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class TeleGPSInfo extends AltosUIFlightTab { diff --git a/telegps/TeleGPSPreferences.java b/telegps/TeleGPSPreferences.java index 61952326..58b3ae35 100644 --- a/telegps/TeleGPSPreferences.java +++ b/telegps/TeleGPSPreferences.java @@ -23,7 +23,7 @@ import java.awt.event.*; import java.beans.*; import javax.swing.*; import javax.swing.event.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altosuilib_12.*; public class TeleGPSPreferences extends AltosUIConfigure diff --git a/telegps/TeleGPSState.java b/telegps/TeleGPSState.java index 9ba0b7a5..21173394 100644 --- a/telegps/TeleGPSState.java +++ b/telegps/TeleGPSState.java @@ -22,8 +22,8 @@ import java.util.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class TeleGPSState extends AltosUIFlightTab { @@ -124,10 +124,11 @@ public class TeleGPSState extends AltosUIFlightTab { class FirmwareVersion extends AltosUIIndicator { public void show(AltosState state, AltosListenerState listener_state) { - if (state.firmware_version == null) + AltosCalData cal_data = state.cal_data(); + if (cal_data.firmware_version == null) show("Missing"); else - show(state.firmware_version); + show(cal_data.firmware_version); } public FirmwareVersion(Container container, int y) { @@ -137,9 +138,8 @@ public class TeleGPSState extends AltosUIFlightTab { class FlightLogMax extends AltosUIIndicator { public void show(AltosState state, AltosListenerState listener_state) { - int storage = state.flight_log_max; - if (storage == AltosLib.MISSING) - storage = state.log_space >> 10; + AltosCalData cal_data = state.cal_data(); + int storage = cal_data.flight_log_max; if (storage == AltosLib.MISSING) show("Missing"); else diff --git a/telegps/TeleGPSStatus.java b/telegps/TeleGPSStatus.java index 5479f43a..e1be69a4 100644 --- a/telegps/TeleGPSStatus.java +++ b/telegps/TeleGPSStatus.java @@ -20,8 +20,8 @@ package org.altusmetrum.telegps; import java.awt.*; import javax.swing.*; -import org.altusmetrum.altoslib_11.*; -import org.altusmetrum.altosuilib_11.*; +import org.altusmetrum.altoslib_12.*; +import org.altusmetrum.altosuilib_12.*; public class TeleGPSStatus extends JComponent implements AltosFlightDisplay { GridBagLayout layout; @@ -75,11 +75,14 @@ public class TeleGPSStatus extends JComponent implements AltosFlightDisplay { String call; void show(AltosState state, AltosListenerState listener_state) { - if (state.callsign != call) { - value.setText(state.callsign); - call = state.callsign; + AltosCalData cal_data = state.cal_data(); + if (cal_data == null) + System.out.printf("null cal data?\n"); + if (cal_data.callsign != call) { + value.setText(cal_data.callsign); + call = cal_data.callsign; } - if (state.callsign == null) + if (cal_data.callsign == null) setVisible(false); else setVisible(true); @@ -100,12 +103,13 @@ public class TeleGPSStatus extends JComponent implements AltosFlightDisplay { class Serial extends Value { int serial = -1; void show(AltosState state, AltosListenerState listener_state) { - if (state.serial != serial) { - if (state.serial == AltosLib.MISSING) + AltosCalData cal_data = state.cal_data(); + if (cal_data.serial != serial) { + if (cal_data.serial == AltosLib.MISSING) value.setText("none"); else - value.setText(String.format("%d", state.serial)); - serial = state.serial; + value.setText(String.format("%d", cal_data.serial)); + serial = cal_data.serial; } } @@ -126,12 +130,13 @@ public class TeleGPSStatus extends JComponent implements AltosFlightDisplay { int last_flight = -1; void show(AltosState state, AltosListenerState listener_state) { - if (state.flight != last_flight) { - if (state.flight == AltosLib.MISSING) + AltosCalData cal_data = state.cal_data(); + if (cal_data.flight != last_flight) { + if (cal_data.flight == AltosLib.MISSING) value.setText("none"); else - value.setText(String.format("%d", state.flight)); - last_flight = state.flight; + value.setText(String.format("%d", cal_data.flight)); + last_flight = cal_data.flight; } } diff --git a/telegps/TeleGPSStatusUpdate.java b/telegps/TeleGPSStatusUpdate.java index ac37af31..1b66d142 100644 --- a/telegps/TeleGPSStatusUpdate.java +++ b/telegps/TeleGPSStatusUpdate.java @@ -19,7 +19,7 @@ package org.altusmetrum.telegps; import java.awt.event.*; -import org.altusmetrum.altoslib_11.*; +import org.altusmetrum.altoslib_12.*; public class TeleGPSStatusUpdate implements ActionListener {