diff options
| author | Bdale Garbee <bdale@gag.com> | 2017-07-21 17:44:03 -0600 | 
|---|---|---|
| committer | Bdale Garbee <bdale@gag.com> | 2017-07-21 17:44:03 -0600 | 
| commit | c8dbcaf69cd538a31ab6e2b568237ae7c8656a9a (patch) | |
| tree | 213ec02db2e80f2e8c39772c0bde95d802900e53 | |
| parent | 0cbfa444a9f9159cb509bb47ca5590fc1d709f64 (diff) | |
| parent | ea3b5815b27005b2f4c3034715f656d28ea8534e (diff) | |
Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos
325 files changed, 6571 insertions, 5560 deletions
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<Integer,AltosState>	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<AltosState>	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<AltosState>();  	}  	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 <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, 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<String> { +public class AltosConfigData {  	/* Version information */  	public String	manufacturer; @@ -33,9 +33,7 @@ public class AltosConfigData implements Iterable<String> {  	public int	log_space;  	public String	version;  	public int	altitude_32; - -	/* Strings returned */ -	public LinkedList<String>	__lines; +	public int	config_major, config_minor;  	/* Config information */  	/* HAS_FLIGHT*/ @@ -96,14 +94,13 @@ public class AltosConfigData implements Iterable<String> {  	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<String> {  		throw new ParseException("mismatch", 0);  	} -	public Iterator<String> 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<String> {  		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<String> {  	}  	public void reset() { -		__lines = new LinkedList<String>(); -  		manufacturer = null;  		product = null;  		serial = AltosLib.MISSING; @@ -242,6 +237,8 @@ public class AltosConfigData implements Iterable<String> {  		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<String> {  		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<String> {  	}  	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<String> {  		/* 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<String> {  			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<String> {  	}  	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<String> {  		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<String> {  	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<String> {  		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<String> {  			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<String> {  		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<String> {  	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<String> {  			}  		} -		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<String> {  			}  		} -		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<String> {  			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 <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, 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/AltosStateUpdate.java b/altoslib/AltosDataProvider.java index e9698cba..9589a8e6 100644 --- a/altoslib/AltosStateUpdate.java +++ b/altoslib/AltosDataProvider.java @@ -16,8 +16,8 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_12; -public interface AltosStateUpdate { -	public void	update_state(AltosState state) throws InterruptedException, AltosUnknownProduct; +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 <keithp@keithp.com> + * Copyright © 2017 Keith Packard <keithp@keithp.com>   *   * This program is free software; you can redistribute it and/or modify   * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; 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<Byte>		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<Byte>(); +		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<Byte>(); +		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<Byte> data) { +		this.config = config; +		this.data = data; +	} + +	public AltosEeprom(AltosConfigData config_data, ArrayList<Byte> 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<AltosState> 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 <keithp@keithp.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, 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<Byte>		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<Byte>(); -		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<Byte>(); -		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<Byte> data) { -		this.config = config; -		this.data = data; -	} - -	public AltosEepromNew(AltosConfigData config_data, ArrayList<Byte> 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<AltosEepromRecord> { -	AltosEepromNew		eeprom; +	AltosEeprom		eeprom;  	int			wide_tick; @@ -65,30 +64,44 @@ public abstract class AltosEepromRecord implements Comparable<AltosEepromRecord>  		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<AltosEepromRecord>  	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<AltosState> { -	AltosEepromNew			eeprom; +public class AltosEepromRecordSet implements AltosRecordSet { +	AltosEeprom			eeprom;  	TreeSet<AltosEepromRecord>	ordered; -	AltosState			start_state; +	AltosCalData			cal_data; -	class RecordIterator implements Iterator<AltosState> { -		Iterator<AltosEepromRecord> 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<AltosState> 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<AltosState> {  			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<AltosState> {  		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<AltosState> {  		}  	} -	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 <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, 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 <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, 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<AltosTimeSeries> series = new ArrayList<AltosTimeSeries>(); + +	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<AltosGPSTimeValue> 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<AltosGPSTimeValue>(); +		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 <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_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 {  		"</Document>\n" +  		"</kml>\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 <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, 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 <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, 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 <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, 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<AltosState>	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<AltosState> 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 <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, 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 <keithp@keithp.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; 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<AltosState> { - -	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 <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, 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/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 <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, 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> { -	AltosState			state; -	Iterator<AltosTelemetry>	telems; -	AltosTelemetry			next; -	boolean				seen; - -	public boolean hasNext() { -		return !seen || telems.hasNext(); -	} - -	public AltosState next() { -		if (seen) { -			AltosState	n = state.clone(); -			AltosTelemetry	t = telems.next(); - -			t.update_state(n); -			state = n; -		} -		seen = true; -		return state; +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<AltosTelemetry> 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<AltosState> iterator() { -		AltosState			state = start.clone(); -		Iterator<AltosTelemetry>  	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<AltosTelemetry> {  	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<AltosTelemetry> {  		return new AltosTelemetryOrderedIterator(telems);  	} -	public AltosTelemetryIterable (FileInputStream input) { +	public AltosTelemetryIterable (FileInputStream input) throws IOException {  		telems = new TreeSet<AltosTelemetryOrdered> ();  		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<AltosLine> 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 <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, 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 <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, 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<AltosTimeValue>, Comparable<AltosTimeSeries> { +	public String			label; +	public AltosUnits		units; +	ArrayList<AltosTimeValue>	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<AltosTimeValue> 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<AltosTimeValue>(); +	} +} 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 <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_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<AltosState> 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> {  	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<AltosBTDevice> {  	LinkedList<AltosBTDevice>	devices = new LinkedList<AltosBTDevice>(); 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<AltosBTDevice> {  	LinkedBlockingQueue<AltosBTDevice> 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<String>	combo_box; -	Iterable<AltosState>	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 <keithp@keithp.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; 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 <keithp@keithp.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; 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 <keithp@keithp.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; 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<AltosUIDataPoint> { -	AltosGraphDataSet	dataSet; -	Iterator<AltosState>	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<AltosState> iterator, AltosGraphDataSet dataSet) { -		this.iterator = iterator; -		this.dataSet = dataSet; -	} - -	public void remove() { -	} -} - -class AltosGraphIterable implements Iterable<AltosUIDataPoint> { -	AltosGraphDataSet	dataSet; - -	public Iterator<AltosUIDataPoint> 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<AltosUIDataPoint> 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<Object> { 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 <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, 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<String,AltosUITimeSeriesAxis> 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<String,AltosUITimeSeriesAxis>(); +	} +} 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<AltosFrequency> { 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<AltosUIGrapher>	graphers; -	AltosUIDataSet			dataSet; +	AltosUITimeSeries[]		series;  	int				axis_index;  	int				series_index; +	Hashtable<Integer,Boolean>	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<AltosUIGrapher>(); -		this.series_index = 0; +		this.series = null;  		this.axis_index = 0; +		axes_added = new Hashtable<Integer,Boolean>(); +  		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<String> { @@ -27,10 +27,9 @@ public class AltosUIRateList extends JComboBox<String> {  	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 <keithp@keithp.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; 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<String> { 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 <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; 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<ValueMarker>	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<ValueMarker>(); +			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 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> + +<svg +       xmlns:dc="http://purl.org/dc/elements/1.1/" +   xmlns:cc="http://creativecommons.org/ns#" +   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" +   xmlns:svg="http://www.w3.org/2000/svg" +   xmlns="http://www.w3.org/2000/svg" +   width="1.75in" +   height="1.25in" +   viewBox="0 0 175 125" +   preserveaspectratio="none" +   id="svg2" +   version="1.1"> +  <g transform="translate(12.5,12.5)" +     style="fill:none;stroke:#000000;stroke-width:1;stroke-linejoin:miter;font-size:20"> +    <!-- outline --> +    <rect width="150" height="100" x="0" y="0"/> +    <!-- holes --> +    <path d="M12.5,12.5 m-6.25,0 a6.25,6.25,0,1,0,12.5,0 a6.25,6.25,0,1,0,-12.5,0 l12.5,0 m-6.25,-6.25 l0,12.5"/> +    <path d="M137.5,12.5 m-6.25,0 a6.25,6.25,0,1,0,12.5,0 a6.25,6.25,0,1,0,-12.5,0 l12.5,0 m-6.25,-6.25 l0,12.5"/> +    <path d="M12.5,87.5 m-6.25,0 a6.25,6.25,0,1,0,12.5,0 a6.25,6.25,0,1,0,-12.5,0 l12.5,0 m-6.25,-6.25 l0,12.5"/> +    <path d="M137.5,87.5 m-6.25,0 a6.25,6.25,0,1,0,12.5,0 a6.25,6.25,0,1,0,-12.5,0 l12.5,0 m-6.25,-6.25 l0,12.5"/> +    <!-- arrow --> +    <path d="M25,50 l100,0"/> +    <path style="fill:#000000;stroke:none" d="M125,45 l10,5 l-10,5 z"/> +    <!-- label --> +    <text x="75" y="35" style="fill:#000000;stroke:none" text-anchor="middle">TeleGPS</text> +    <g transform="rotate(90)"> +      <text x="50" y="-133" style="fill:#000000;stroke:none" text-anchor="middle">UP</text> +    </g> +  </g> +</svg> 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 <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, 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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <termios.h> +#include <errno.h> +#include <unistd.h> +#include <ctype.h> +#include <dirent.h> +#include <bluetooth/bluetooth.h> +#include <bluetooth/hci.h> +#include <bluetooth/hci_lib.h> +#include <bluetooth/rfcomm.h> +#include <bluetooth/sdp.h> +#include <bluetooth/sdp_lib.h> +#include <bluetooth/l2cap.h> +#include <poll.h> + +#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<MicroDataPoint> { -	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<MicroDataPoint> { - -	MicroData	data; - -	public Iterator<MicroDataPoint> iterator() { -		return new MicroIterator(data); -	} - -	public MicroIterable(MicroData data) { -		this.data = data; -	} -} - -class MicroUIIterator implements Iterator<AltosUIDataPoint> { -	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<AltosUIDataPoint> { -	MicroData	data; - -	public Iterator<AltosUIDataPoint> 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<Integer>	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<AltosUIDataPoint> dataPoints() { -		return new MicroUIIterable(this); -	} - -	public Iterable<MicroDataPoint> 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<Integer>(); + +		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 <keithp@keithp.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; 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 <keithp@keithp.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; 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 <keithp@keithp.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; 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 <keithp@keithp.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; 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 <ao_profile.h>  #include <ao_btm.h>  #include <ao_lco_cmd.h> +#include <ao_send_packet.h>  #if HAS_SAMPLE_PROFILE  #include <ao_sample_profile.h>  #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 <ao_ms5607.h>  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 {  | 
