Improved Serial input processing.

Before this patch every byte received from Serial
invokes a String allocation, not really efficient.

Moreover a InputStreamReader is chained on the serial
InputStream to correctly convert bytes into UTF-8
characters.
This commit is contained in:
Cristian Maglie 2014-12-23 12:47:24 +01:00
parent 391d3380ee
commit 63f5d26ae9
2 changed files with 26 additions and 52 deletions

View File

@ -25,9 +25,7 @@
package processing.app; package processing.app;
//import processing.core.*; //import processing.core.*;
import processing.app.debug.MessageConsumer;
import static processing.app.I18n._; import static processing.app.I18n._;
import gnu.io.*; import gnu.io.*;
import java.io.*; import java.io.*;
@ -55,15 +53,13 @@ public class Serial implements SerialPortEventListener {
// read buffer and streams // read buffer and streams
InputStream input; InputStreamReader input;
OutputStream output; OutputStream output;
byte buffer[] = new byte[32768]; byte buffer[] = new byte[32768];
int bufferIndex; int bufferIndex;
int bufferLast; int bufferLast;
MessageConsumer consumer;
public Serial(boolean monitor) throws SerialException { public Serial(boolean monitor) throws SerialException {
this(Preferences.get("serial.port"), this(Preferences.get("serial.port"),
Preferences.getInteger("serial.debug_rate"), Preferences.getInteger("serial.debug_rate"),
@ -158,7 +154,7 @@ public class Serial implements SerialPortEventListener {
if (portId.getName().equals(iname)) { if (portId.getName().equals(iname)) {
//System.out.println("looking for "+iname); //System.out.println("looking for "+iname);
port = (SerialPort)portId.open("serial madness", 2000); port = (SerialPort)portId.open("serial madness", 2000);
input = port.getInputStream(); input = new InputStreamReader(port.getInputStream());
output = port.getOutputStream(); output = port.getOutputStream();
port.setSerialPortParams(rate, databits, stopbits, parity); port.setSerialPortParams(rate, databits, stopbits, parity);
port.addEventListener(this); port.addEventListener(this);
@ -237,62 +233,41 @@ public class Serial implements SerialPortEventListener {
port = null; port = null;
} }
char serialBuffer[] = new char[4096];
public void addListener(MessageConsumer consumer) {
this.consumer = consumer;
}
synchronized public void serialEvent(SerialPortEvent serialEvent) { synchronized public void serialEvent(SerialPortEvent serialEvent) {
//System.out.println("serial port event"); // " + serialEvent);
//System.out.flush();
//System.out.println("into");
//System.out.flush();
//System.err.println("type " + serialEvent.getEventType());
//System.err.println("ahoooyey");
//System.err.println("ahoooyeysdfsdfsdf");
if (serialEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) { if (serialEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
//System.out.println("data available");
//System.err.flush();
try { try {
while (input.available() > 0) { while (input.ready()) {
//if (input.available() > 0) {
//serial = input.read();
//serialEvent();
//buffer[bufferCount++] = (byte) serial;
synchronized (buffer) { synchronized (buffer) {
if (bufferLast == buffer.length) { if (bufferLast == buffer.length) {
byte temp[] = new byte[bufferLast << 1]; byte temp[] = new byte[bufferLast << 1];
System.arraycopy(buffer, 0, temp, 0, bufferLast); System.arraycopy(buffer, 0, temp, 0, bufferLast);
buffer = temp; buffer = temp;
} }
//buffer[bufferLast++] = (byte) input.read(); int n = input.read(serialBuffer);
if(monitor == true) message(serialBuffer, n);
System.out.print((char) input.read());
if (this.consumer != null)
this.consumer.message("" + (char) input.read());
/*
System.err.println(input.available() + " " +
((char) buffer[bufferLast-1]));
*/ //}
} }
} }
//System.out.println("no more");
} catch (IOException e) { } catch (IOException e) {
errorMessage("serialEvent", e); errorMessage("serialEvent", e);
//e.printStackTrace();
//System.out.println("angry");
} }
catch (Exception e) { catch (Exception e) {
} }
} }
//System.out.println("out of");
//System.err.println("out of event " + serialEvent.getEventType());
} }
/**
* This method is intended to be redefined by users of Serial class
*
* @param buff
* @param n
*/
protected void message(char buff[], int n) {
// Empty
}
/** /**
* Returns the number of bytes that have been read from serial * Returns the number of bytes that have been read from serial
* and are waiting to be dealt with by the user. * and are waiting to be dealt with by the user.

View File

@ -18,18 +18,18 @@
package processing.app; package processing.app;
import processing.app.debug.MessageConsumer;
import processing.app.debug.TextAreaFIFO; import processing.app.debug.TextAreaFIFO;
import processing.core.*; import processing.core.*;
import static processing.app.I18n._; import static processing.app.I18n._;
import java.awt.*; import java.awt.*;
import java.awt.event.*; import java.awt.event.*;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.*; import javax.swing.border.*;
import javax.swing.text.*; import javax.swing.text.*;
public class SerialMonitor extends JFrame implements MessageConsumer,ActionListener { public class SerialMonitor extends JFrame implements ActionListener {
private Serial serial; private Serial serial;
private String port; private String port;
private TextAreaFIFO textArea; private TextAreaFIFO textArea;
@ -210,8 +210,12 @@ public class SerialMonitor extends JFrame implements MessageConsumer,ActionListe
public void openSerialPort() throws SerialException { public void openSerialPort() throws SerialException {
if (serial != null) return; if (serial != null) return;
serial = new Serial(port, serialRate); serial = new Serial(port, serialRate) {
serial.addListener(this); @Override
protected void message(char buff[], int n) {
addToUpdateBuffer(buff, n);
}
};
updateTimer.start(); updateTimer.start();
} }
@ -226,13 +230,8 @@ public class SerialMonitor extends JFrame implements MessageConsumer,ActionListe
} }
} }
public void message(String s) { private synchronized void addToUpdateBuffer(char buff[], int n) {
// TODO: can we pass a byte array, to avoid overhead of String updateBuffer.append(buff, 0, n);
addToUpdateBuffer(s);
}
private synchronized void addToUpdateBuffer(String s) {
updateBuffer.append(s);
} }
private synchronized String consumeUpdateBuffer() { private synchronized String consumeUpdateBuffer() {