--- /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();
+
+ }
+
+
+}