--- /dev/null
+import net.sf.openrocket.simulation.SimulationStatus;
+import net.sf.openrocket.simulation.exception.SimulationException;
+import net.sf.openrocket.simulation.listeners.AbstractSimulationListener;
+import net.sf.openrocket.util.Coordinate;
+
+/**
+ * Simulation listener that launches a rocket from a specific altitude.
+ */
+public class AirStart extends AbstractSimulationListener {
+
+ /** Launch altitude */
+ private static final double ALTITUDE = 1000.0;
+
+ @Override
+ public void startSimulation(SimulationStatus status) throws SimulationException {
+ Coordinate position = status.getRocketPosition();
+ position = position.add(0, 0, ALTITUDE);
+ status.setRocketPosition(position);
+ }
+
+}
--- /dev/null
+package altimeter;
+
+import gnu.io.CommPortIdentifier;
+import gnu.io.PortInUseException;
+import gnu.io.SerialPort;
+import gnu.io.UnsupportedCommOperationException;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.nio.charset.Charset;
+import java.text.DateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.TimeZone;
+
+/**
+ * Class to interface the PerfectFlite Alt15K/WD altimeter.
+ *
+ * Also includes a main method that retrieves all flight profiles and saves them to files.
+ *
+ * @author Sampo Niskanen <sampo.niskanen@iki.fi>
+ */
+
+public class Alt15K {
+ public static final int TIMEOUT = 500;
+ public static final int RWDELAY = 5;
+
+ private static final boolean DEBUG = false;
+
+ private static final Charset CHARSET = Charset.forName("ISO-8859-1");
+
+ private final CommPortIdentifier portID;
+ private SerialPort port = null;
+ private InputStream is = null;
+ private OutputStream os = null;
+
+
+
+ @SuppressWarnings("unchecked")
+ public static String[] getNames() {
+ ArrayList<String> list = new ArrayList<String>();;
+
+ Enumeration pids = CommPortIdentifier.getPortIdentifiers();
+
+ while (pids.hasMoreElements()) {
+ CommPortIdentifier pid = (CommPortIdentifier) pids.nextElement();
+
+ if (pid.getPortType() == CommPortIdentifier.PORT_SERIAL)
+ list.add(pid.getName());
+ }
+ return list.toArray(new String[0]);
+ }
+
+
+
+ @SuppressWarnings("unchecked")
+ public Alt15K(String name) throws IOException {
+ CommPortIdentifier pID = null;
+
+ Enumeration portIdentifiers = CommPortIdentifier.getPortIdentifiers();
+ while (portIdentifiers.hasMoreElements()) {
+ CommPortIdentifier pid = (CommPortIdentifier) portIdentifiers.nextElement();
+
+ if(pid.getPortType() == CommPortIdentifier.PORT_SERIAL &&
+ pid.getName().equals(name)) {
+ pID = pid;
+ break;
+ }
+ }
+
+ if (pID==null) {
+ throw new IOException("Port '"+name+"' not found.");
+ }
+ this.portID = pID;
+ }
+
+
+ /**
+ * Get altimeter flight data. The flight profile is chosen by the parameter n,
+ * 0 = latest flight, 1 = second latest, etc.
+ *
+ * @param n Which flight profile to use (0=newest, 1=second newest, etc)
+ * @return The altimeter flight data
+ * @throws IOException in case of IOException
+ * @throws PortInUseException in case of PortInUseException
+ */
+ public AltData getData(int n) throws IOException, PortInUseException {
+ AltData alt = new AltData();
+ ArrayList<Integer> data = new ArrayList<Integer>();
+ byte[] buf;
+ byte[] buf2 = new byte[0];
+ boolean identical = false; // Whether identical lines have been read
+
+ if (DEBUG)
+ System.out.println(" Retrieving altimeter data n="+n);
+
+ try {
+ open();
+
+ // Get version and position data
+ byte[] ver = getVersionData();
+ alt.setVersion(new byte[] { ver[0],ver[1] });
+
+ // Calculate the position requested
+ if (n > 2)
+ n = 2;
+ int position = ver[2] - n;
+ while (position < 0)
+ position += 3;
+
+ if (DEBUG)
+ System.out.println(" Requesting data from position "+position);
+
+ // Request the data
+ write("D");
+ write((byte)position);
+ write("PS");
+
+ sleep();
+
+ // Read preliminary data
+ buf = read(4);
+ int msl_level = combine(buf[0],buf[1]);
+ int datacount = combine(buf[2],buf[3]);
+
+ if (DEBUG)
+ System.out.println(" Preliminary data msl="+msl_level+" count="+datacount);
+
+ alt.setMslLevel(msl_level-6000);
+ alt.setDataSamples(datacount);
+
+ if (DEBUG)
+ System.out.println(" Retrieving "+datacount+" samples");
+
+ long t = System.currentTimeMillis();
+
+ int count = 0;
+ while (count < datacount) {
+ sleep();
+ write("G");
+ sleep();
+ buf = read(17);
+
+ if (buf.length == 17) {
+ // Checksum = sum of all bytes + 1
+ // (signedness does not change the result)
+ byte checksum = 1;
+ for (int i=0; i<16; i++)
+ checksum += buf[i];
+ if (checksum != buf[16]) {
+ printBytes("ERROR: Checksum fail on data (computed="+checksum+
+ " orig="+buf[16]+")",buf);
+ System.out.println("Ignoring error");
+ }
+ } else {
+ System.err.println("ERROR: Only "+buf.length+" bytes read, should be 17");
+ }
+
+ for (int i=0; i<buf.length-1; i+=2) {
+ data.add(combine(buf[i],buf[i+1]));
+ count++;
+ }
+
+ /*
+ * Check whether the data is identical to the previous data batch. If reading
+ * too fast, the data seems to become duplicated in the transfer. We need to check
+ * whether this has happened by attempting to read more data than is normally
+ * available.
+ */
+ int c, l=Math.min(buf.length, buf2.length);
+ for (c=0; c<l; c++) {
+ if (buf[c] != buf2[c])
+ break;
+ }
+ if (c==l && buf.length == buf2.length)
+ identical = true;
+ buf2 = buf.clone();
+ }
+
+ if (DEBUG)
+ System.out.println(" Retrieved "+data.size()+" samples in "+
+ (System.currentTimeMillis()-t)+" ms");
+
+
+ // In case of identical lines, check for more data. This would mean that the
+ // transfer was corrupted.
+ if (identical) {
+ System.err.println("WARNING: Duplicate data detected, possible error");
+ }
+
+ // Test for more data
+ if (DEBUG)
+ System.out.println(" Testing for more data");
+ sleep();
+ write("G");
+ sleep();
+ buf = read(17);
+ if (buf.length > 0) {
+ System.err.println("ERROR: Data available after transfer! (length="+buf.length+")");
+ }
+
+
+
+
+
+
+ // Create an int[] array and set it
+ int[] d = new int[data.size()];
+ for (int i=0; i<d.length; i++)
+ d[i] = data.get(i);
+ alt.setData(d);
+
+ // Catch all exceptions, close the port and re-throw the exception
+ } catch (PortInUseException e) {
+ close();
+ throw e;
+ } catch (IOException e) {
+ close();
+ throw e;
+ } catch (UnsupportedCommOperationException e) {
+ close();
+ throw new RuntimeException("Required function of RxTx library not supported",e);
+ } catch (RuntimeException e) {
+ // Catch-all for all other types of exceptions
+ close();
+ throw e;
+ }
+
+ close();
+ return alt;
+ }
+
+
+
+
+ private byte[] getVersionData() throws PortInUseException, IOException,
+ UnsupportedCommOperationException {
+ byte[] ver = new byte[3];
+ byte[] buf;
+
+ if (DEBUG)
+ System.out.println(" Retrieving altimeter version information");
+
+ // Signal to altimeter we are here
+ write((byte)0);
+ sleep(15); // Sleep for 15ms, data is incoming at 10 samples/sec
+
+ // Get altimeter version, skip zeros
+ write("PV");
+ sleep();
+ buf = readSkipZero(2);
+ sleep();
+ if (buf.length != 2) {
+ close();
+ throw new IOException("Communication with altimeter failed.");
+ }
+ ver[0] = buf[0];
+ ver[1] = buf[1];
+
+ // Get position of newest data
+ write("M");
+ sleep();
+ buf = read(1);
+ if (buf.length != 1) {
+ close();
+ throw new IOException("Communication with altimeter failed.");
+ }
+ ver[2] = buf[0];
+
+ if (DEBUG)
+ System.out.println(" Received version info "+ver[0]+"."+ver[1]+", position "+ver[2]);
+
+ return ver;
+ }
+
+
+ /**
+ * Delay the communication by a small delay (RWDELAY ms).
+ */
+ private void sleep() {
+ sleep(RWDELAY);
+ }
+
+ /**
+ * Sleep for the given amount of milliseconds.
+ */
+ private void sleep(int n) {
+ try {
+ Thread.sleep(n);
+ } catch (InterruptedException ignore) { }
+ }
+
+
+ private void open()
+ throws PortInUseException, IOException, UnsupportedCommOperationException {
+ if (port != null) {
+ System.err.println("ERROR: open() called with port="+port);
+ Thread.dumpStack();
+ close();
+ }
+
+ if (DEBUG) {
+ System.out.println(" Opening port...");
+ }
+
+ port = (SerialPort)portID.open("OpenRocket",1000);
+
+ port.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
+ SerialPort.PARITY_NONE);
+
+ port.setInputBufferSize(1);
+ port.setOutputBufferSize(1);
+
+ port.enableReceiveTimeout(TIMEOUT);
+
+ is = port.getInputStream();
+ os = port.getOutputStream();
+ }
+
+
+ private byte[] readSkipZero(int n) throws IOException, UnsupportedCommOperationException {
+ long t = System.currentTimeMillis() + TIMEOUT*2;
+
+ if (DEBUG) {
+ System.out.println(" readSkipZero "+n+" bytes");
+ }
+
+ while (System.currentTimeMillis() < t) {
+ byte[] buf = read(n);
+ if (DEBUG)
+ printBytes(" Received",buf);
+
+ if (buf.length == 0) // No data available
+ return buf;
+
+ // Skip zeros
+ int i;
+ for (i=0; i<buf.length; i++)
+ if (buf[i] != 0)
+ break;
+
+ if (i==0) // No zeros to skip
+ return buf;
+
+ if (i < buf.length) {
+ // Partially read
+ int count = buf.length-i; // No. of data bytes
+ byte[] array = new byte[n];
+ System.arraycopy(buf, i, array, 0, count);
+ buf = read(n-count);
+ if (DEBUG)
+ printBytes(" Received (partial)",buf);
+ System.arraycopy(buf, 0, array, count, buf.length);
+
+ if (DEBUG)
+ printBytes(" Returning",array);
+ return array;
+ }
+ }
+
+ if (DEBUG)
+ System.out.println(" No data read, returning empty");
+ return new byte[0]; // no data, only zeros
+ }
+
+
+ private byte[] read(int n) throws IOException, UnsupportedCommOperationException {
+ byte[] bytes = new byte[n];
+
+ port.enableReceiveThreshold(n);
+
+ long t = System.currentTimeMillis() + TIMEOUT;
+ int count = 0;
+
+ if (DEBUG)
+ System.out.println(" Reading "+n+" bytes");
+
+ while (count < n && System.currentTimeMillis() < t) {
+ byte[] buf = new byte[n-count];
+ int c = is.read(buf);
+ System.arraycopy(buf, 0, bytes, count, c);
+ count += c;
+ }
+
+ byte[] array = new byte[count];
+ System.arraycopy(bytes, 0, array, 0, count);
+
+ if (DEBUG)
+ printBytes(" Returning",array);
+
+ return array;
+ }
+
+ private void write(String s) throws IOException {
+ write(s.getBytes(CHARSET));
+ }
+
+ private void write(byte ... bytes) throws IOException {
+ if (DEBUG)
+ printBytes(" Writing",bytes);
+ os.write(bytes);
+ }
+
+ private void close() {
+ if (DEBUG)
+ System.out.println(" Closing port");
+
+ SerialPort p = port;
+ port = null;
+ is = null;
+ os = null;
+ if (p != null)
+ p.close();
+ }
+
+
+
+
+
+ public static void main(String[] arg) {
+
+ if (arg.length != 1) {
+ System.err.println("Usage: java Alt15K <basename>");
+ System.err.println("Files will be saved <basename>-old.log, -med and -new");
+ return;
+ }
+
+
+ String device = null;
+ String[] devices = Alt15K.getNames();
+ for (int i=0; i<devices.length; i++) {
+ if (devices[i].matches(".*USB.*")) {
+ device = devices[i];
+ break;
+ }
+ }
+ if (device == null) {
+ System.out.println("Device not found.");
+ return;
+ }
+
+
+ System.out.println("Selected device "+device);
+
+ AltData alt = null;
+ String file;
+ try {
+ Alt15K p = new Alt15K(device);
+
+ System.out.println("Retrieving newest data...");
+ alt = p.getData(0);
+ System.out.println("Apogee at "+alt.getApogee()+" feet");
+
+ file = arg[0]+"-new.log";
+ System.out.println("Saving data to "+file+"...");
+ savefile(file,alt);
+
+
+ System.out.println("Retrieving medium data...");
+ alt = p.getData(1);
+ System.out.println("Apogee at "+alt.getApogee()+" feet");
+
+ file = arg[0]+"-med.log";
+ System.out.println("Saving data to "+file+"...");
+ savefile(file,alt);
+
+
+ System.out.println("Retrieving oldest data...");
+ alt = p.getData(2);
+ System.out.println("Apogee at "+alt.getApogee()+" feet");
+
+ file = arg[0]+"-old.log";
+ System.out.println("Saving data to "+file+"...");
+ savefile(file,alt);
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (PortInUseException e) {
+ e.printStackTrace();
+ }
+
+// System.out.println(alt);
+// alt.printData();
+
+ }
+
+
+ static private void savefile(String file, AltData data) throws FileNotFoundException {
+
+ PrintStream output = new PrintStream(file);
+
+ // WTF is this so difficult?!?
+ DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM);
+ TimeZone tz=TimeZone.getTimeZone("GMT+3");
+ fmt.setTimeZone(tz);
+
+ output.println("# Alt15K data, file "+file);
+ output.println("# Data retrieved at: "+fmt.format(new Date()));
+ output.println("# Values are in feet above launch level");
+ output.println("# ");
+ output.println("# Apogee = "+data.getApogee());
+ output.println("# MSL level = "+data.getMslLevel());
+ output.println("# Data count = "+data.getDataSamples());
+
+ byte[] b = data.getVersion();
+ String s="";
+ for (int i=0; i<b.length; i++) {
+ if (s.equals(""))
+ s = ""+((int)b[i]);
+ else
+ s = s+"."+((int)b[i]);
+ }
+ output.println("# Altimeter version = " + s);
+
+ int[] values = data.getData();
+ for (int i=0; i < values.length; i++) {
+ output.println(""+values[i]);
+ }
+
+ output.close();
+ }
+
+
+ static private void printBytes(String str, byte[] b) {
+ printBytes(str, b,b.length);
+ }
+
+ static private void printBytes(String str, byte[] b, int n) {
+ String s;
+ s = str+" "+n+" bytes:";
+ for (int i=0; i<n; i++) {
+ s += " "+unsign(b[i]);
+ }
+ System.out.println(s);
+ }
+
+ static private int unsign(byte b) {
+ if (b >= 0)
+ return b;
+ else
+ return 256 + b;
+ }
+
+ @SuppressWarnings("unused")
+ static private int combine(int a, int b) {
+ return 256*a + b;
+ }
+
+ static private int combine(byte a, byte b) {
+ int val = 256*unsign(a)+unsign(b);
+ if (val <= 32767)
+ return val;
+ else
+ return val-65536;
+
+ }
+
+}
--- /dev/null
+package altimeter;
+
+public class AltData {
+
+ private int mslLevel = 0;
+ private int samples = 0;
+ private int[] data = null;
+ private byte[] version = null;
+
+
+ public void setMslLevel(int msl) {
+ mslLevel = msl;
+ }
+ public int getMslLevel() {
+ return mslLevel;
+ }
+
+ public void setDataSamples(int s) {
+ samples = s;
+ }
+ public int getDataSamples() {
+ return samples;
+ }
+
+ public void setVersion(byte[] v) {
+ if (v==null)
+ version = null;
+ else
+ version = v.clone();
+ }
+ public byte[] getVersion() {
+ if (version == null)
+ return null;
+ return version.clone();
+ }
+
+ public void setData(int[] data) {
+ if (data==null)
+ this.data = null;
+ else
+ this.data = data.clone();
+ }
+ public int[] getData() {
+ if (data == null)
+ return null;
+ return data.clone();
+ }
+
+ public int getApogee() {
+ if (data == null || data.length==0)
+ return 0;
+ int max = Integer.MIN_VALUE;
+ for (int i=0; i<data.length; i++) {
+ if (data[i] > max)
+ max = data[i];
+ }
+ return max;
+ }
+
+ @Override
+ public String toString() {
+ String s = "AltData(";
+ s += "MSL:"+getMslLevel()+",";
+ s += "Apogee:"+getApogee()+",";
+ s += "Samples:"+getDataSamples();
+ s += ")";
+ return s;
+ }
+
+ public void printData() {
+ System.out.println(toString()+":");
+ for (int i=0; i<data.length; i+=8) {
+ String s = " "+i+":";
+ for (int j=0; j<8 && (i+j)<data.length; j++) {
+ s += " "+data[i+j];
+ }
+ System.out.println(s);
+ }
+ }
+
+}
--- /dev/null
+package altimeter;
+
+import gnu.io.CommPortIdentifier;
+import gnu.io.PortInUseException;
+import gnu.io.SerialPort;
+import gnu.io.UnsupportedCommOperationException;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Enumeration;
+
+/**
+ * Class to interface the PerfectFlite Alt15K/WD altimeter.
+ *
+ * Also includes a main method that retrieves all flight profiles and saves them to files.
+ *
+ * @author Sampo Niskanen <sampo.niskanen@iki.fi>
+ */
+
+public class RotationLogger {
+ private static final boolean DEBUG = false;
+
+ private static final int BYTES = 65536;
+
+
+ private final CommPortIdentifier portID;
+ private SerialPort port = null;
+ private InputStream is = null;
+ private OutputStream os = null;
+
+
+
+ @SuppressWarnings("unchecked")
+ public static String[] getNames() {
+ ArrayList<String> list = new ArrayList<String>();;
+
+ Enumeration pids = CommPortIdentifier.getPortIdentifiers();
+
+ while (pids.hasMoreElements()) {
+ CommPortIdentifier pid = (CommPortIdentifier) pids.nextElement();
+
+ if (pid.getPortType() == CommPortIdentifier.PORT_SERIAL)
+ list.add(pid.getName());
+ }
+ return list.toArray(new String[0]);
+ }
+
+
+
+
+
+ @SuppressWarnings("unchecked")
+ public RotationLogger(String name) throws IOException {
+ CommPortIdentifier portID = null;
+
+ Enumeration portIdentifiers = CommPortIdentifier.getPortIdentifiers();
+ while (portIdentifiers.hasMoreElements()) {
+ CommPortIdentifier pid = (CommPortIdentifier) portIdentifiers.nextElement();
+
+ if(pid.getPortType() == CommPortIdentifier.PORT_SERIAL &&
+ pid.getName().equals(name)) {
+ portID = pid;
+ break;
+ }
+ }
+
+ if (portID==null) {
+ throw new IOException("Port '"+name+"' not found.");
+ }
+ this.portID = portID;
+ }
+
+
+
+
+
+
+ public void readData() throws IOException, PortInUseException {
+ int c;
+
+ int[] data = new int[BYTES];
+
+ FileOutputStream rawdump = null;
+
+
+ try {
+ open();
+
+ System.err.println("Sending dump mode command...");
+
+ for (int i=0; i<16; i++) {
+ os.write('D');
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException ignore) { }
+ }
+
+ System.err.println("Waiting for response...");
+ while (true) {
+ c = is.read();
+ if (c == 'K') {
+ break;
+ } else {
+ System.err.printf("Received spurious c=%d\n",c);
+ }
+ }
+
+ System.err.println("Received response.");
+
+
+
+ System.err.println("Opening 'rawdump'...");
+ rawdump = new FileOutputStream("rawdump");
+
+
+
+ System.err.println("Performing dump...");
+
+ os.write('A');
+
+ byte[] buffer = new byte[1024];
+ int printCount = 0;
+ for (int count=0; count < BYTES; ) {
+ if ((BYTES-count) < buffer.length) {
+ buffer = new byte[BYTES-count];
+ }
+
+ int n = is.read(buffer);
+ if (n < 0) {
+ System.err.println("Error condition, n="+n);
+ return;
+ }
+
+ rawdump.write(buffer, 0, n);
+
+ for (int i=0; i<n; i++) {
+ data[count+i] = unsign(buffer[i]);
+ }
+ count += n;
+ if (count - printCount > 1024) {
+ System.err.println("Read "+count+" bytes...");
+ printCount = count;
+ }
+ }
+
+
+ System.err.println("Verifying checksum...");
+ int reported = is.read();
+
+ byte computed = 0;
+ for (int i=0; i < data.length; i++) {
+ computed += data[i];
+ }
+ if (computed == reported) {
+ System.err.println("Checksum ok ("+computed+")");
+ } else {
+ System.err.println("Error in checksum, computed="+computed+
+ " reported="+reported);
+ }
+
+ System.err.println("Communication done.");
+
+ } catch (UnsupportedCommOperationException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } finally {
+ close();
+ if (rawdump != null)
+ rawdump.close();
+ }
+
+ convertData(data);
+
+ }
+
+
+
+ //////////// Data interpretation //////////////
+
+
+ private static void convertData(int[] data) {
+
+ System.err.println("Converting data...");
+
+ int lastBuffer = data[0xffff];
+ if (lastBuffer < 0 || lastBuffer > 3) {
+ System.err.println("Illegal last accessed buffer: "+lastBuffer);
+ return;
+ }
+ System.err.println("Last used buffer: "+lastBuffer);
+
+ for (int i=4; i>0; i--) {
+ int n = (lastBuffer + i) % 4;
+ int bufNumber = 4-i;
+
+ convertBuffer(data, n * (BYTES/4), bufNumber);
+ }
+
+ }
+
+
+ private static void convertBuffer(int[] data, int position, int bufNumber) {
+ int startPosition;
+
+ startPosition = data[position + 0xfd] << 8 + data[position+0xfe];
+
+ // 50 samples per 128 bytes
+ int startTime = (startPosition -position) * 50 / 128;
+
+ System.err.println(" Buffer "+ bufNumber + " (at position "+position+")...");
+ System.err.println(" Start position "+startPosition+" time "+startTime);
+
+ System.out.println("# Buffer "+bufNumber);
+ System.out.println("# Start position t="+startTime);
+
+
+ int t = 0;
+ for (int page = 0; page < 128; page++) {
+ int pageStart = position + page * 128;
+
+ if (pageStart == startPosition) {
+ System.out.println("# ---clip---");
+ }
+
+ for (int i=0; i<125; i += 5) {
+ int sample1, sample2;
+
+ int start = pageStart + i;
+// System.err.println("page="+page+" i="+i+
+// " position="+position+" pageStart="+pageStart+" start="+start);
+
+ sample1 = (data[start] << 2) + (data[start+1] >> 6);
+ sample2 = ((data[start+1] & 0x3f) << 4) + (data[start+2] >> 4);
+ System.out.printf("%d %4d %4d %4d\n", bufNumber, t, sample1, sample2);
+ t++;
+
+ sample1 = ((data[start+2] & 0x0f) << 6) + (data[start+3] >> 2);
+ sample2 = ((data[start+3] & 3) << 8) + data[start+4];
+ System.out.printf("%d %4d %4d %4d\n", bufNumber, t, sample1, sample2);
+ t++;
+ }
+ }
+ }
+
+
+
+ private void open() throws PortInUseException, IOException,
+ UnsupportedCommOperationException {
+
+ if (port != null) {
+ System.err.println("ERROR: open() called with port="+port);
+ Thread.dumpStack();
+ close();
+ }
+
+ if (DEBUG) {
+ System.err.println(" Opening port...");
+ }
+
+ port = (SerialPort)portID.open("OpenRocket",1000);
+
+ port.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
+ SerialPort.PARITY_NONE);
+
+ port.setInputBufferSize(1);
+ port.setOutputBufferSize(1);
+
+ is = port.getInputStream();
+ os = port.getOutputStream();
+ }
+
+
+ private void close() {
+ if (DEBUG)
+ System.err.println(" Closing port");
+
+ SerialPort p = port;
+ port = null;
+ is = null;
+ if (p != null)
+ p.close();
+ }
+
+
+
+ private static int unsign(byte b) {
+ if (b >= 0)
+ return b;
+ else
+ return 256 + b;
+ }
+
+
+
+
+ public static void main(String[] arg) throws Exception {
+
+ if (arg.length > 2) {
+ System.err.println("Illegal arguments.");
+ return;
+ }
+ if (arg.length == 1) {
+ FileInputStream is = new FileInputStream(arg[0]);
+ byte[] buffer = new byte[BYTES];
+ int n = is.read(buffer);
+ if (n != BYTES) {
+ System.err.println("Could read only "+n+" bytes");
+ return;
+ }
+
+ int[] data = new int[BYTES];
+ for (int i=0; i<BYTES; i++) {
+ data[i] = unsign(buffer[i]);
+ }
+
+ int checksum=0;
+ for (int i=0; i<BYTES; i++) {
+ checksum += data[i];
+ }
+ checksum = checksum%256;
+ System.err.println("Checksum: "+checksum);
+
+ convertData(data);
+ return;
+ }
+
+
+ String device = null;
+ String[] devices = RotationLogger.getNames();
+ for (int i=0; i<devices.length; i++) {
+ if (devices[i].matches(".*USB.*")) {
+ device = devices[i];
+ break;
+ }
+ }
+ if (device == null) {
+ System.err.println("Device not found.");
+ return;
+ }
+
+
+ System.err.println("Selected device "+device);
+
+
+ RotationLogger p = new RotationLogger(device);
+
+ p.readData();
+
+ }
+
+
+}
--- /dev/null
+package altimeter;
+
+import gnu.io.CommPortIdentifier;
+import gnu.io.PortInUseException;
+import gnu.io.SerialPort;
+import gnu.io.UnsupportedCommOperationException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Enumeration;
+
+/**
+ * Class to interface the PerfectFlite Alt15K/WD altimeter.
+ *
+ * Also includes a main method that retrieves all flight profiles and saves them to files.
+ *
+ * @author Sampo Niskanen <sampo.niskanen@iki.fi>
+ */
+
+public class SerialDownload {
+ private static final boolean DEBUG = false;
+
+ private static final int MAGIC = 666;
+
+ private final CommPortIdentifier portID;
+ private SerialPort port = null;
+ private InputStream is = null;
+
+
+
+ @SuppressWarnings("unchecked")
+ public static String[] getNames() {
+ ArrayList<String> list = new ArrayList<String>();;
+
+ Enumeration pids = CommPortIdentifier.getPortIdentifiers();
+
+ while (pids.hasMoreElements()) {
+ CommPortIdentifier pid = (CommPortIdentifier) pids.nextElement();
+
+ if (pid.getPortType() == CommPortIdentifier.PORT_SERIAL)
+ list.add(pid.getName());
+ }
+ return list.toArray(new String[0]);
+ }
+
+
+
+
+
+ @SuppressWarnings("unchecked")
+ public SerialDownload(String name) throws IOException {
+ CommPortIdentifier portID = null;
+
+ Enumeration portIdentifiers = CommPortIdentifier.getPortIdentifiers();
+ while (portIdentifiers.hasMoreElements()) {
+ CommPortIdentifier pid = (CommPortIdentifier) portIdentifiers.nextElement();
+
+ if(pid.getPortType() == CommPortIdentifier.PORT_SERIAL &&
+ pid.getName().equals(name)) {
+ portID = pid;
+ break;
+ }
+ }
+
+ if (portID==null) {
+ throw new IOException("Port '"+name+"' not found.");
+ }
+ this.portID = portID;
+ }
+
+
+
+
+
+
+ public void readData() throws IOException, PortInUseException {
+ long t0 = -1;
+ long t;
+
+ int previous = MAGIC;
+
+
+ try {
+ open();
+
+ System.err.println("Ready to read...");
+ while (true) {
+ int c = is.read();
+ t = System.nanoTime();
+ if (t0 < 0)
+ t0 = t;
+
+ System.out.printf("%10.6f %d\n", ((double)t-t0)/1000000000.0, c);
+
+ if (previous == MAGIC) {
+ previous = c;
+ } else {
+ System.out.printf("# Altitude: %5d\n", previous*256 + c);
+ previous = MAGIC;
+ }
+
+ if (c < 0)
+ break;
+ }
+
+
+ } catch (UnsupportedCommOperationException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } finally {
+ close();
+ }
+ }
+
+
+
+ private void open() throws PortInUseException, IOException,
+ UnsupportedCommOperationException {
+
+ if (port != null) {
+ System.err.println("ERROR: open() called with port="+port);
+ Thread.dumpStack();
+ close();
+ }
+
+ if (DEBUG) {
+ System.err.println(" Opening port...");
+ }
+
+ port = (SerialPort)portID.open("OpenRocket",1000);
+
+ port.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
+ SerialPort.PARITY_NONE);
+
+ port.setInputBufferSize(1);
+ port.setOutputBufferSize(1);
+
+ is = port.getInputStream();
+ }
+
+
+ private void close() {
+ if (DEBUG)
+ System.err.println(" Closing port");
+
+ SerialPort p = port;
+ port = null;
+ is = null;
+ if (p != null)
+ p.close();
+ }
+
+
+
+
+
+ public static void main(String[] arg) throws Exception {
+
+ String device = null;
+ String[] devices = SerialDownload.getNames();
+ for (int i=0; i<devices.length; i++) {
+ if (devices[i].matches(".*USB.*")) {
+ device = devices[i];
+ break;
+ }
+ }
+ if (device == null) {
+ System.err.println("Device not found.");
+ return;
+ }
+
+
+ System.err.println("Selected device "+device);
+
+
+ SerialDownload p = new SerialDownload(device);
+
+ p.readData();
+
+ }
+
+
+}
+++ /dev/null
-import net.sf.openrocket.simulation.SimulationStatus;
-import net.sf.openrocket.simulation.exception.SimulationException;
-import net.sf.openrocket.simulation.listeners.AbstractSimulationListener;
-import net.sf.openrocket.util.Coordinate;
-
-/**
- * Simulation listener that launches a rocket from a specific altitude.
- */
-public class AirStart extends AbstractSimulationListener {
-
- /** Launch altitude */
- private static final double ALTITUDE = 1000.0;
-
- @Override
- public void startSimulation(SimulationStatus status) throws SimulationException {
- Coordinate position = status.getRocketPosition();
- position = position.add(0, 0, ALTITUDE);
- status.setRocketPosition(position);
- }
-
-}
+++ /dev/null
-package altimeter;
-
-import gnu.io.CommPortIdentifier;
-import gnu.io.PortInUseException;
-import gnu.io.SerialPort;
-import gnu.io.UnsupportedCommOperationException;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.nio.charset.Charset;
-import java.text.DateFormat;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.Enumeration;
-import java.util.TimeZone;
-
-/**
- * Class to interface the PerfectFlite Alt15K/WD altimeter.
- *
- * Also includes a main method that retrieves all flight profiles and saves them to files.
- *
- * @author Sampo Niskanen <sampo.niskanen@iki.fi>
- */
-
-public class Alt15K {
- public static final int TIMEOUT = 500;
- public static final int RWDELAY = 5;
-
- private static final boolean DEBUG = false;
-
- private static final Charset CHARSET = Charset.forName("ISO-8859-1");
-
- private final CommPortIdentifier portID;
- private SerialPort port = null;
- private InputStream is = null;
- private OutputStream os = null;
-
-
-
- @SuppressWarnings("unchecked")
- public static String[] getNames() {
- ArrayList<String> list = new ArrayList<String>();;
-
- Enumeration pids = CommPortIdentifier.getPortIdentifiers();
-
- while (pids.hasMoreElements()) {
- CommPortIdentifier pid = (CommPortIdentifier) pids.nextElement();
-
- if (pid.getPortType() == CommPortIdentifier.PORT_SERIAL)
- list.add(pid.getName());
- }
- return list.toArray(new String[0]);
- }
-
-
-
- @SuppressWarnings("unchecked")
- public Alt15K(String name) throws IOException {
- CommPortIdentifier pID = null;
-
- Enumeration portIdentifiers = CommPortIdentifier.getPortIdentifiers();
- while (portIdentifiers.hasMoreElements()) {
- CommPortIdentifier pid = (CommPortIdentifier) portIdentifiers.nextElement();
-
- if(pid.getPortType() == CommPortIdentifier.PORT_SERIAL &&
- pid.getName().equals(name)) {
- pID = pid;
- break;
- }
- }
-
- if (pID==null) {
- throw new IOException("Port '"+name+"' not found.");
- }
- this.portID = pID;
- }
-
-
- /**
- * Get altimeter flight data. The flight profile is chosen by the parameter n,
- * 0 = latest flight, 1 = second latest, etc.
- *
- * @param n Which flight profile to use (0=newest, 1=second newest, etc)
- * @return The altimeter flight data
- * @throws IOException in case of IOException
- * @throws PortInUseException in case of PortInUseException
- */
- public AltData getData(int n) throws IOException, PortInUseException {
- AltData alt = new AltData();
- ArrayList<Integer> data = new ArrayList<Integer>();
- byte[] buf;
- byte[] buf2 = new byte[0];
- boolean identical = false; // Whether identical lines have been read
-
- if (DEBUG)
- System.out.println(" Retrieving altimeter data n="+n);
-
- try {
- open();
-
- // Get version and position data
- byte[] ver = getVersionData();
- alt.setVersion(new byte[] { ver[0],ver[1] });
-
- // Calculate the position requested
- if (n > 2)
- n = 2;
- int position = ver[2] - n;
- while (position < 0)
- position += 3;
-
- if (DEBUG)
- System.out.println(" Requesting data from position "+position);
-
- // Request the data
- write("D");
- write((byte)position);
- write("PS");
-
- sleep();
-
- // Read preliminary data
- buf = read(4);
- int msl_level = combine(buf[0],buf[1]);
- int datacount = combine(buf[2],buf[3]);
-
- if (DEBUG)
- System.out.println(" Preliminary data msl="+msl_level+" count="+datacount);
-
- alt.setMslLevel(msl_level-6000);
- alt.setDataSamples(datacount);
-
- if (DEBUG)
- System.out.println(" Retrieving "+datacount+" samples");
-
- long t = System.currentTimeMillis();
-
- int count = 0;
- while (count < datacount) {
- sleep();
- write("G");
- sleep();
- buf = read(17);
-
- if (buf.length == 17) {
- // Checksum = sum of all bytes + 1
- // (signedness does not change the result)
- byte checksum = 1;
- for (int i=0; i<16; i++)
- checksum += buf[i];
- if (checksum != buf[16]) {
- printBytes("ERROR: Checksum fail on data (computed="+checksum+
- " orig="+buf[16]+")",buf);
- System.out.println("Ignoring error");
- }
- } else {
- System.err.println("ERROR: Only "+buf.length+" bytes read, should be 17");
- }
-
- for (int i=0; i<buf.length-1; i+=2) {
- data.add(combine(buf[i],buf[i+1]));
- count++;
- }
-
- /*
- * Check whether the data is identical to the previous data batch. If reading
- * too fast, the data seems to become duplicated in the transfer. We need to check
- * whether this has happened by attempting to read more data than is normally
- * available.
- */
- int c, l=Math.min(buf.length, buf2.length);
- for (c=0; c<l; c++) {
- if (buf[c] != buf2[c])
- break;
- }
- if (c==l && buf.length == buf2.length)
- identical = true;
- buf2 = buf.clone();
- }
-
- if (DEBUG)
- System.out.println(" Retrieved "+data.size()+" samples in "+
- (System.currentTimeMillis()-t)+" ms");
-
-
- // In case of identical lines, check for more data. This would mean that the
- // transfer was corrupted.
- if (identical) {
- System.err.println("WARNING: Duplicate data detected, possible error");
- }
-
- // Test for more data
- if (DEBUG)
- System.out.println(" Testing for more data");
- sleep();
- write("G");
- sleep();
- buf = read(17);
- if (buf.length > 0) {
- System.err.println("ERROR: Data available after transfer! (length="+buf.length+")");
- }
-
-
-
-
-
-
- // Create an int[] array and set it
- int[] d = new int[data.size()];
- for (int i=0; i<d.length; i++)
- d[i] = data.get(i);
- alt.setData(d);
-
- // Catch all exceptions, close the port and re-throw the exception
- } catch (PortInUseException e) {
- close();
- throw e;
- } catch (IOException e) {
- close();
- throw e;
- } catch (UnsupportedCommOperationException e) {
- close();
- throw new RuntimeException("Required function of RxTx library not supported",e);
- } catch (RuntimeException e) {
- // Catch-all for all other types of exceptions
- close();
- throw e;
- }
-
- close();
- return alt;
- }
-
-
-
-
- private byte[] getVersionData() throws PortInUseException, IOException,
- UnsupportedCommOperationException {
- byte[] ver = new byte[3];
- byte[] buf;
-
- if (DEBUG)
- System.out.println(" Retrieving altimeter version information");
-
- // Signal to altimeter we are here
- write((byte)0);
- sleep(15); // Sleep for 15ms, data is incoming at 10 samples/sec
-
- // Get altimeter version, skip zeros
- write("PV");
- sleep();
- buf = readSkipZero(2);
- sleep();
- if (buf.length != 2) {
- close();
- throw new IOException("Communication with altimeter failed.");
- }
- ver[0] = buf[0];
- ver[1] = buf[1];
-
- // Get position of newest data
- write("M");
- sleep();
- buf = read(1);
- if (buf.length != 1) {
- close();
- throw new IOException("Communication with altimeter failed.");
- }
- ver[2] = buf[0];
-
- if (DEBUG)
- System.out.println(" Received version info "+ver[0]+"."+ver[1]+", position "+ver[2]);
-
- return ver;
- }
-
-
- /**
- * Delay the communication by a small delay (RWDELAY ms).
- */
- private void sleep() {
- sleep(RWDELAY);
- }
-
- /**
- * Sleep for the given amount of milliseconds.
- */
- private void sleep(int n) {
- try {
- Thread.sleep(n);
- } catch (InterruptedException ignore) { }
- }
-
-
- private void open()
- throws PortInUseException, IOException, UnsupportedCommOperationException {
- if (port != null) {
- System.err.println("ERROR: open() called with port="+port);
- Thread.dumpStack();
- close();
- }
-
- if (DEBUG) {
- System.out.println(" Opening port...");
- }
-
- port = (SerialPort)portID.open("OpenRocket",1000);
-
- port.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
- SerialPort.PARITY_NONE);
-
- port.setInputBufferSize(1);
- port.setOutputBufferSize(1);
-
- port.enableReceiveTimeout(TIMEOUT);
-
- is = port.getInputStream();
- os = port.getOutputStream();
- }
-
-
- private byte[] readSkipZero(int n) throws IOException, UnsupportedCommOperationException {
- long t = System.currentTimeMillis() + TIMEOUT*2;
-
- if (DEBUG) {
- System.out.println(" readSkipZero "+n+" bytes");
- }
-
- while (System.currentTimeMillis() < t) {
- byte[] buf = read(n);
- if (DEBUG)
- printBytes(" Received",buf);
-
- if (buf.length == 0) // No data available
- return buf;
-
- // Skip zeros
- int i;
- for (i=0; i<buf.length; i++)
- if (buf[i] != 0)
- break;
-
- if (i==0) // No zeros to skip
- return buf;
-
- if (i < buf.length) {
- // Partially read
- int count = buf.length-i; // No. of data bytes
- byte[] array = new byte[n];
- System.arraycopy(buf, i, array, 0, count);
- buf = read(n-count);
- if (DEBUG)
- printBytes(" Received (partial)",buf);
- System.arraycopy(buf, 0, array, count, buf.length);
-
- if (DEBUG)
- printBytes(" Returning",array);
- return array;
- }
- }
-
- if (DEBUG)
- System.out.println(" No data read, returning empty");
- return new byte[0]; // no data, only zeros
- }
-
-
- private byte[] read(int n) throws IOException, UnsupportedCommOperationException {
- byte[] bytes = new byte[n];
-
- port.enableReceiveThreshold(n);
-
- long t = System.currentTimeMillis() + TIMEOUT;
- int count = 0;
-
- if (DEBUG)
- System.out.println(" Reading "+n+" bytes");
-
- while (count < n && System.currentTimeMillis() < t) {
- byte[] buf = new byte[n-count];
- int c = is.read(buf);
- System.arraycopy(buf, 0, bytes, count, c);
- count += c;
- }
-
- byte[] array = new byte[count];
- System.arraycopy(bytes, 0, array, 0, count);
-
- if (DEBUG)
- printBytes(" Returning",array);
-
- return array;
- }
-
- private void write(String s) throws IOException {
- write(s.getBytes(CHARSET));
- }
-
- private void write(byte ... bytes) throws IOException {
- if (DEBUG)
- printBytes(" Writing",bytes);
- os.write(bytes);
- }
-
- private void close() {
- if (DEBUG)
- System.out.println(" Closing port");
-
- SerialPort p = port;
- port = null;
- is = null;
- os = null;
- if (p != null)
- p.close();
- }
-
-
-
-
-
- public static void main(String[] arg) {
-
- if (arg.length != 1) {
- System.err.println("Usage: java Alt15K <basename>");
- System.err.println("Files will be saved <basename>-old.log, -med and -new");
- return;
- }
-
-
- String device = null;
- String[] devices = Alt15K.getNames();
- for (int i=0; i<devices.length; i++) {
- if (devices[i].matches(".*USB.*")) {
- device = devices[i];
- break;
- }
- }
- if (device == null) {
- System.out.println("Device not found.");
- return;
- }
-
-
- System.out.println("Selected device "+device);
-
- AltData alt = null;
- String file;
- try {
- Alt15K p = new Alt15K(device);
-
- System.out.println("Retrieving newest data...");
- alt = p.getData(0);
- System.out.println("Apogee at "+alt.getApogee()+" feet");
-
- file = arg[0]+"-new.log";
- System.out.println("Saving data to "+file+"...");
- savefile(file,alt);
-
-
- System.out.println("Retrieving medium data...");
- alt = p.getData(1);
- System.out.println("Apogee at "+alt.getApogee()+" feet");
-
- file = arg[0]+"-med.log";
- System.out.println("Saving data to "+file+"...");
- savefile(file,alt);
-
-
- System.out.println("Retrieving oldest data...");
- alt = p.getData(2);
- System.out.println("Apogee at "+alt.getApogee()+" feet");
-
- file = arg[0]+"-old.log";
- System.out.println("Saving data to "+file+"...");
- savefile(file,alt);
-
- } catch (IOException e) {
- e.printStackTrace();
- } catch (PortInUseException e) {
- e.printStackTrace();
- }
-
-// System.out.println(alt);
-// alt.printData();
-
- }
-
-
- static private void savefile(String file, AltData data) throws FileNotFoundException {
-
- PrintStream output = new PrintStream(file);
-
- // WTF is this so difficult?!?
- DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM);
- TimeZone tz=TimeZone.getTimeZone("GMT+3");
- fmt.setTimeZone(tz);
-
- output.println("# Alt15K data, file "+file);
- output.println("# Data retrieved at: "+fmt.format(new Date()));
- output.println("# Values are in feet above launch level");
- output.println("# ");
- output.println("# Apogee = "+data.getApogee());
- output.println("# MSL level = "+data.getMslLevel());
- output.println("# Data count = "+data.getDataSamples());
-
- byte[] b = data.getVersion();
- String s="";
- for (int i=0; i<b.length; i++) {
- if (s.equals(""))
- s = ""+((int)b[i]);
- else
- s = s+"."+((int)b[i]);
- }
- output.println("# Altimeter version = " + s);
-
- int[] values = data.getData();
- for (int i=0; i < values.length; i++) {
- output.println(""+values[i]);
- }
-
- output.close();
- }
-
-
- static private void printBytes(String str, byte[] b) {
- printBytes(str, b,b.length);
- }
-
- static private void printBytes(String str, byte[] b, int n) {
- String s;
- s = str+" "+n+" bytes:";
- for (int i=0; i<n; i++) {
- s += " "+unsign(b[i]);
- }
- System.out.println(s);
- }
-
- static private int unsign(byte b) {
- if (b >= 0)
- return b;
- else
- return 256 + b;
- }
-
- @SuppressWarnings("unused")
- static private int combine(int a, int b) {
- return 256*a + b;
- }
-
- static private int combine(byte a, byte b) {
- int val = 256*unsign(a)+unsign(b);
- if (val <= 32767)
- return val;
- else
- return val-65536;
-
- }
-
-}
+++ /dev/null
-package altimeter;
-
-public class AltData {
-
- private int mslLevel = 0;
- private int samples = 0;
- private int[] data = null;
- private byte[] version = null;
-
-
- public void setMslLevel(int msl) {
- mslLevel = msl;
- }
- public int getMslLevel() {
- return mslLevel;
- }
-
- public void setDataSamples(int s) {
- samples = s;
- }
- public int getDataSamples() {
- return samples;
- }
-
- public void setVersion(byte[] v) {
- if (v==null)
- version = null;
- else
- version = v.clone();
- }
- public byte[] getVersion() {
- if (version == null)
- return null;
- return version.clone();
- }
-
- public void setData(int[] data) {
- if (data==null)
- this.data = null;
- else
- this.data = data.clone();
- }
- public int[] getData() {
- if (data == null)
- return null;
- return data.clone();
- }
-
- public int getApogee() {
- if (data == null || data.length==0)
- return 0;
- int max = Integer.MIN_VALUE;
- for (int i=0; i<data.length; i++) {
- if (data[i] > max)
- max = data[i];
- }
- return max;
- }
-
- @Override
- public String toString() {
- String s = "AltData(";
- s += "MSL:"+getMslLevel()+",";
- s += "Apogee:"+getApogee()+",";
- s += "Samples:"+getDataSamples();
- s += ")";
- return s;
- }
-
- public void printData() {
- System.out.println(toString()+":");
- for (int i=0; i<data.length; i+=8) {
- String s = " "+i+":";
- for (int j=0; j<8 && (i+j)<data.length; j++) {
- s += " "+data[i+j];
- }
- System.out.println(s);
- }
- }
-
-}
+++ /dev/null
-package altimeter;
-
-import gnu.io.CommPortIdentifier;
-import gnu.io.PortInUseException;
-import gnu.io.SerialPort;
-import gnu.io.UnsupportedCommOperationException;
-
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Enumeration;
-
-/**
- * Class to interface the PerfectFlite Alt15K/WD altimeter.
- *
- * Also includes a main method that retrieves all flight profiles and saves them to files.
- *
- * @author Sampo Niskanen <sampo.niskanen@iki.fi>
- */
-
-public class RotationLogger {
- private static final boolean DEBUG = false;
-
- private static final int BYTES = 65536;
-
-
- private final CommPortIdentifier portID;
- private SerialPort port = null;
- private InputStream is = null;
- private OutputStream os = null;
-
-
-
- @SuppressWarnings("unchecked")
- public static String[] getNames() {
- ArrayList<String> list = new ArrayList<String>();;
-
- Enumeration pids = CommPortIdentifier.getPortIdentifiers();
-
- while (pids.hasMoreElements()) {
- CommPortIdentifier pid = (CommPortIdentifier) pids.nextElement();
-
- if (pid.getPortType() == CommPortIdentifier.PORT_SERIAL)
- list.add(pid.getName());
- }
- return list.toArray(new String[0]);
- }
-
-
-
-
-
- @SuppressWarnings("unchecked")
- public RotationLogger(String name) throws IOException {
- CommPortIdentifier portID = null;
-
- Enumeration portIdentifiers = CommPortIdentifier.getPortIdentifiers();
- while (portIdentifiers.hasMoreElements()) {
- CommPortIdentifier pid = (CommPortIdentifier) portIdentifiers.nextElement();
-
- if(pid.getPortType() == CommPortIdentifier.PORT_SERIAL &&
- pid.getName().equals(name)) {
- portID = pid;
- break;
- }
- }
-
- if (portID==null) {
- throw new IOException("Port '"+name+"' not found.");
- }
- this.portID = portID;
- }
-
-
-
-
-
-
- public void readData() throws IOException, PortInUseException {
- int c;
-
- int[] data = new int[BYTES];
-
- FileOutputStream rawdump = null;
-
-
- try {
- open();
-
- System.err.println("Sending dump mode command...");
-
- for (int i=0; i<16; i++) {
- os.write('D');
- try {
- Thread.sleep(10);
- } catch (InterruptedException ignore) { }
- }
-
- System.err.println("Waiting for response...");
- while (true) {
- c = is.read();
- if (c == 'K') {
- break;
- } else {
- System.err.printf("Received spurious c=%d\n",c);
- }
- }
-
- System.err.println("Received response.");
-
-
-
- System.err.println("Opening 'rawdump'...");
- rawdump = new FileOutputStream("rawdump");
-
-
-
- System.err.println("Performing dump...");
-
- os.write('A');
-
- byte[] buffer = new byte[1024];
- int printCount = 0;
- for (int count=0; count < BYTES; ) {
- if ((BYTES-count) < buffer.length) {
- buffer = new byte[BYTES-count];
- }
-
- int n = is.read(buffer);
- if (n < 0) {
- System.err.println("Error condition, n="+n);
- return;
- }
-
- rawdump.write(buffer, 0, n);
-
- for (int i=0; i<n; i++) {
- data[count+i] = unsign(buffer[i]);
- }
- count += n;
- if (count - printCount > 1024) {
- System.err.println("Read "+count+" bytes...");
- printCount = count;
- }
- }
-
-
- System.err.println("Verifying checksum...");
- int reported = is.read();
-
- byte computed = 0;
- for (int i=0; i < data.length; i++) {
- computed += data[i];
- }
- if (computed == reported) {
- System.err.println("Checksum ok ("+computed+")");
- } else {
- System.err.println("Error in checksum, computed="+computed+
- " reported="+reported);
- }
-
- System.err.println("Communication done.");
-
- } catch (UnsupportedCommOperationException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } finally {
- close();
- if (rawdump != null)
- rawdump.close();
- }
-
- convertData(data);
-
- }
-
-
-
- //////////// Data interpretation //////////////
-
-
- private static void convertData(int[] data) {
-
- System.err.println("Converting data...");
-
- int lastBuffer = data[0xffff];
- if (lastBuffer < 0 || lastBuffer > 3) {
- System.err.println("Illegal last accessed buffer: "+lastBuffer);
- return;
- }
- System.err.println("Last used buffer: "+lastBuffer);
-
- for (int i=4; i>0; i--) {
- int n = (lastBuffer + i) % 4;
- int bufNumber = 4-i;
-
- convertBuffer(data, n * (BYTES/4), bufNumber);
- }
-
- }
-
-
- private static void convertBuffer(int[] data, int position, int bufNumber) {
- int startPosition;
-
- startPosition = data[position + 0xfd] << 8 + data[position+0xfe];
-
- // 50 samples per 128 bytes
- int startTime = (startPosition -position) * 50 / 128;
-
- System.err.println(" Buffer "+ bufNumber + " (at position "+position+")...");
- System.err.println(" Start position "+startPosition+" time "+startTime);
-
- System.out.println("# Buffer "+bufNumber);
- System.out.println("# Start position t="+startTime);
-
-
- int t = 0;
- for (int page = 0; page < 128; page++) {
- int pageStart = position + page * 128;
-
- if (pageStart == startPosition) {
- System.out.println("# ---clip---");
- }
-
- for (int i=0; i<125; i += 5) {
- int sample1, sample2;
-
- int start = pageStart + i;
-// System.err.println("page="+page+" i="+i+
-// " position="+position+" pageStart="+pageStart+" start="+start);
-
- sample1 = (data[start] << 2) + (data[start+1] >> 6);
- sample2 = ((data[start+1] & 0x3f) << 4) + (data[start+2] >> 4);
- System.out.printf("%d %4d %4d %4d\n", bufNumber, t, sample1, sample2);
- t++;
-
- sample1 = ((data[start+2] & 0x0f) << 6) + (data[start+3] >> 2);
- sample2 = ((data[start+3] & 3) << 8) + data[start+4];
- System.out.printf("%d %4d %4d %4d\n", bufNumber, t, sample1, sample2);
- t++;
- }
- }
- }
-
-
-
- private void open() throws PortInUseException, IOException,
- UnsupportedCommOperationException {
-
- if (port != null) {
- System.err.println("ERROR: open() called with port="+port);
- Thread.dumpStack();
- close();
- }
-
- if (DEBUG) {
- System.err.println(" Opening port...");
- }
-
- port = (SerialPort)portID.open("OpenRocket",1000);
-
- port.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
- SerialPort.PARITY_NONE);
-
- port.setInputBufferSize(1);
- port.setOutputBufferSize(1);
-
- is = port.getInputStream();
- os = port.getOutputStream();
- }
-
-
- private void close() {
- if (DEBUG)
- System.err.println(" Closing port");
-
- SerialPort p = port;
- port = null;
- is = null;
- if (p != null)
- p.close();
- }
-
-
-
- private static int unsign(byte b) {
- if (b >= 0)
- return b;
- else
- return 256 + b;
- }
-
-
-
-
- public static void main(String[] arg) throws Exception {
-
- if (arg.length > 2) {
- System.err.println("Illegal arguments.");
- return;
- }
- if (arg.length == 1) {
- FileInputStream is = new FileInputStream(arg[0]);
- byte[] buffer = new byte[BYTES];
- int n = is.read(buffer);
- if (n != BYTES) {
- System.err.println("Could read only "+n+" bytes");
- return;
- }
-
- int[] data = new int[BYTES];
- for (int i=0; i<BYTES; i++) {
- data[i] = unsign(buffer[i]);
- }
-
- int checksum=0;
- for (int i=0; i<BYTES; i++) {
- checksum += data[i];
- }
- checksum = checksum%256;
- System.err.println("Checksum: "+checksum);
-
- convertData(data);
- return;
- }
-
-
- String device = null;
- String[] devices = RotationLogger.getNames();
- for (int i=0; i<devices.length; i++) {
- if (devices[i].matches(".*USB.*")) {
- device = devices[i];
- break;
- }
- }
- if (device == null) {
- System.err.println("Device not found.");
- return;
- }
-
-
- System.err.println("Selected device "+device);
-
-
- RotationLogger p = new RotationLogger(device);
-
- p.readData();
-
- }
-
-
-}
+++ /dev/null
-package altimeter;
-
-import gnu.io.CommPortIdentifier;
-import gnu.io.PortInUseException;
-import gnu.io.SerialPort;
-import gnu.io.UnsupportedCommOperationException;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Enumeration;
-
-/**
- * Class to interface the PerfectFlite Alt15K/WD altimeter.
- *
- * Also includes a main method that retrieves all flight profiles and saves them to files.
- *
- * @author Sampo Niskanen <sampo.niskanen@iki.fi>
- */
-
-public class SerialDownload {
- private static final boolean DEBUG = false;
-
- private static final int MAGIC = 666;
-
- private final CommPortIdentifier portID;
- private SerialPort port = null;
- private InputStream is = null;
-
-
-
- @SuppressWarnings("unchecked")
- public static String[] getNames() {
- ArrayList<String> list = new ArrayList<String>();;
-
- Enumeration pids = CommPortIdentifier.getPortIdentifiers();
-
- while (pids.hasMoreElements()) {
- CommPortIdentifier pid = (CommPortIdentifier) pids.nextElement();
-
- if (pid.getPortType() == CommPortIdentifier.PORT_SERIAL)
- list.add(pid.getName());
- }
- return list.toArray(new String[0]);
- }
-
-
-
-
-
- @SuppressWarnings("unchecked")
- public SerialDownload(String name) throws IOException {
- CommPortIdentifier portID = null;
-
- Enumeration portIdentifiers = CommPortIdentifier.getPortIdentifiers();
- while (portIdentifiers.hasMoreElements()) {
- CommPortIdentifier pid = (CommPortIdentifier) portIdentifiers.nextElement();
-
- if(pid.getPortType() == CommPortIdentifier.PORT_SERIAL &&
- pid.getName().equals(name)) {
- portID = pid;
- break;
- }
- }
-
- if (portID==null) {
- throw new IOException("Port '"+name+"' not found.");
- }
- this.portID = portID;
- }
-
-
-
-
-
-
- public void readData() throws IOException, PortInUseException {
- long t0 = -1;
- long t;
-
- int previous = MAGIC;
-
-
- try {
- open();
-
- System.err.println("Ready to read...");
- while (true) {
- int c = is.read();
- t = System.nanoTime();
- if (t0 < 0)
- t0 = t;
-
- System.out.printf("%10.6f %d\n", ((double)t-t0)/1000000000.0, c);
-
- if (previous == MAGIC) {
- previous = c;
- } else {
- System.out.printf("# Altitude: %5d\n", previous*256 + c);
- previous = MAGIC;
- }
-
- if (c < 0)
- break;
- }
-
-
- } catch (UnsupportedCommOperationException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } finally {
- close();
- }
- }
-
-
-
- private void open() throws PortInUseException, IOException,
- UnsupportedCommOperationException {
-
- if (port != null) {
- System.err.println("ERROR: open() called with port="+port);
- Thread.dumpStack();
- close();
- }
-
- if (DEBUG) {
- System.err.println(" Opening port...");
- }
-
- port = (SerialPort)portID.open("OpenRocket",1000);
-
- port.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
- SerialPort.PARITY_NONE);
-
- port.setInputBufferSize(1);
- port.setOutputBufferSize(1);
-
- is = port.getInputStream();
- }
-
-
- private void close() {
- if (DEBUG)
- System.err.println(" Closing port");
-
- SerialPort p = port;
- port = null;
- is = null;
- if (p != null)
- p.close();
- }
-
-
-
-
-
- public static void main(String[] arg) throws Exception {
-
- String device = null;
- String[] devices = SerialDownload.getNames();
- for (int i=0; i<devices.length; i++) {
- if (devices[i].matches(".*USB.*")) {
- device = devices[i];
- break;
- }
- }
- if (device == null) {
- System.err.println("Device not found.");
- return;
- }
-
-
- System.err.println("Selected device "+device);
-
-
- SerialDownload p = new SerialDownload(device);
-
- p.readData();
-
- }
-
-
-}