/*
* ***********************************
* ASL Eye Tracker Serial Driver in Java
* ***********************************
*
* Written by Patryk Laurent. Copyright (C) 2009 Patryk Laurent.
*
* 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 3 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, see .
*
*
* Dependencies: Uses the RXTX java io library.
* To test it out, just run it from the command line (main will fire things up.)
*
*/
package net.pakl.thesis.drivers;
import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import java.math.BigInteger;
import net.pakl.thesis.util.*;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
/**
* Java-to-Serial-Binary Driver to interface with ASL Eye Tracker and get gaze.
*
* @author patryk
*/
public class EyeTrackerDriver
{
public final MessageQueue data = new MessageQueue();
public int BAUD_RATE = 57600;
public char CHARACTER_INDICATING_MESSAGE_START = '-';
public boolean DEBUG_SEND_BYTES_TOO = false;
/** Connects to serial port and returns message queue that will contain the data. */
public MessageQueue connect(String serialPortName) throws Exception
{
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(serialPortName);
if (portIdentifier.isCurrentlyOwned())
{
System.out.println("Error: Port is currently in use");
throw new RuntimeException("Sorry - selected port is currently in use.");
}
else
{
CommPort commPort = portIdentifier.open(this.getClass().getName(), 2000);
if (commPort instanceof SerialPort)
{
SerialPort serialPort = (SerialPort) commPort;
serialPort.setSerialPortParams(BAUD_RATE, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
//serialPort.setSerialPortParams(9600,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
InputStream in = serialPort.getInputStream();
OutputStream out = serialPort.getOutputStream();
(new Thread(new SerialReader(in))).start();
(new Thread(new SerialWriter(out))).start();
return data;
}
else
{
System.out.println("Error: Only serial ports are handled by this example.");
}
}
throw new RuntimeException("Could not connect to the requested port.");
}
private static boolean getBit(int b, int pos)
{
String s = Integer.toBinaryString(b);
if (pos > s.length()-1) return false;
if (s.charAt(s.length()-pos-1) == '1') return true;
return false;
}
/** */
public class SerialReader implements Runnable
{
InputStream in;
public SerialReader(InputStream in)
{
this.in = in;
}
int byteCounter = 0;
int xMSB, xLSB, yMSB, yLSB, overflow1, overflow2;
public void run()
{
byte[] buffer = new byte[1024];
int withinMessageCounter = 0;
int len = -1;
try
{
while ((len = this.in.read(buffer)) > -1)
{
for (int i = 0; i < len; i++)
{
if (DEBUG_SEND_BYTES_TOO) data.put(buffer[i]);
withinMessageCounter++;
if (withinMessageCounter == 4) xMSB = buffer[i];
if (withinMessageCounter == 5) xLSB = buffer[i];
if (withinMessageCounter == 6) yMSB = buffer[i];
if (withinMessageCounter == 7) overflow1 = buffer[i];
if (withinMessageCounter == 8) yLSB = buffer[i];
if (withinMessageCounter == 9)
{
overflow2 = buffer[i];
// Decode the bytes.
if (getBit(overflow1, 4)) xMSB = xMSB | (1<<7);
if (getBit(overflow1, 5)) xLSB = xLSB | (1<<7);
if (getBit(overflow1, 6)) yMSB = yMSB | (1<<7);
if (getBit(overflow2, 0)) yLSB = yLSB | (1<<7);
ASLData d = new ASLData();
d.gazeX = xMSB * 256 + xLSB;
d.gazeY = yMSB * 256 + yLSB;
d.timestamp = System.currentTimeMillis();
data.put(d);
}
// if (byteToString(buffer[i]).charAt(0) == CHARACTER_INDICATING_MESSAGE_START)
// {
// withinMessageCounter = 0;
// }
if (getBit(buffer[i], 7)) // leftmost bit is 1?
{
withinMessageCounter = 0;
}
}
}
} catch (IOException e)
{
e.printStackTrace();
}
}
}
/** */
public class SerialWriter implements Runnable
{
OutputStream out;
public SerialWriter(OutputStream out)
{
this.out = out;
}
public void run()
{
try
{
int c = 0;
while ((c = System.in.read()) > -1)
{
this.out.write(c);
}
} catch (IOException e)
{
e.printStackTrace();
}
}
}
public static List listCommPorts()
{
ArrayList result = new ArrayList();
try
{
java.util.Enumeration pList = CommPortIdentifier.getPortIdentifiers();
// Process the list.
while (pList.hasMoreElements())
{
CommPortIdentifier cpi = (CommPortIdentifier) pList.nextElement();
System.out.print("Port " + cpi.getName() + " ");
if (cpi.getPortType() == CommPortIdentifier.PORT_SERIAL)
{
System.out.println("is a Serial Port: " + cpi);
result.add(cpi.getName());
}
else
{
if (cpi.getPortType() == CommPortIdentifier.PORT_PARALLEL)
{
System.out.println("is a Parallel Port: " + cpi);
}
else
{
System.out.println("is an Unknown Port: " + cpi);
}
}
}
}
catch (java.lang.UnsatisfiedLinkError ule)
{
ule.printStackTrace();
System.err.println("-------------------------------------------------------");
System.err.println("You must use -Djava.library.path= and specify the");
System.err.println("location of the rxtxSerial libraries (i.e., DLLs in ");
System.err.println("Windows or of librxtxSerial.jnilib in Mac OS X)");
System.err.println("-------------------------------------------------------");
}
if (result.size() == 0)
{
result.add("can't access serial library");
}
return result;
}
public static String byteToString(byte b)
{
byte[] subbuffer = new byte[1];
subbuffer[0] = b;
BigInteger bi = new BigInteger(subbuffer);
String s = bi.toString(2);
switch (s.length())
{
case 1:
s = "0" + s;
case 2:
s = "0" + s;
case 3:
s = "0" + s;
case 4:
s = "0" + s;
case 5:
s = "0" + s;
case 6:
s = "0" + s;
case 7:
s = "0" + s;
}
return s;
}
public static void main(String args[])
{
if (args.length < 1)
{
listCommPorts();
System.err.println("-------------------------------------------------------");
System.err.println("Error: Please pass a serial port on the command line.");
System.err.println("-------------------------------------------------------");
return;
}
String serial = args[0];
try
{
EyeTrackerDriver e = new EyeTrackerDriver();
e.connect(serial);
while (true)
{
if (!e.data.isEmpty())
{
Object o = e.data.get();
if (o instanceof Byte)
{
String s = byteToString((Byte) o);
System.out.print(s + " ");
}
else
{
ASLData data = (ASLData) o;
System.out.println("x = " + data.gazeX + "\ty = " + data.gazeY);
}
}
}
} catch (Exception x)
{
// TODO Auto-generated catch block
x.printStackTrace();
}
}
}