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; 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]); } public RotationLogger(String name) throws IOException { CommPortIdentifier myPortID = null; Enumeration<?> portIdentifiers = CommPortIdentifier.getPortIdentifiers(); while (portIdentifiers.hasMoreElements()) { CommPortIdentifier pid = (CommPortIdentifier) portIdentifiers.nextElement(); if(pid.getPortType() == CommPortIdentifier.PORT_SERIAL && pid.getName().equals(name)) { myPortID = pid; break; } } if (myPortID == null) { throw new IOException("Port '"+name+"' not found."); } this.portID = myPortID ; } 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(); } }