From 63f5d26ae9186419ae65a36bbced33f94a2fdfd9 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 23 Dec 2014 12:47:24 +0100 Subject: [PATCH] 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. --- app/src/processing/app/Serial.java | 57 +++++++---------------- app/src/processing/app/SerialMonitor.java | 21 ++++----- 2 files changed, 26 insertions(+), 52 deletions(-) diff --git a/app/src/processing/app/Serial.java b/app/src/processing/app/Serial.java index 14c0933c0..b9432f904 100755 --- a/app/src/processing/app/Serial.java +++ b/app/src/processing/app/Serial.java @@ -25,9 +25,7 @@ package processing.app; //import processing.core.*; -import processing.app.debug.MessageConsumer; import static processing.app.I18n._; - import gnu.io.*; import java.io.*; @@ -55,15 +53,13 @@ public class Serial implements SerialPortEventListener { // read buffer and streams - InputStream input; + InputStreamReader input; OutputStream output; byte buffer[] = new byte[32768]; int bufferIndex; int bufferLast; - MessageConsumer consumer; - public Serial(boolean monitor) throws SerialException { this(Preferences.get("serial.port"), Preferences.getInteger("serial.debug_rate"), @@ -158,7 +154,7 @@ public class Serial implements SerialPortEventListener { if (portId.getName().equals(iname)) { //System.out.println("looking for "+iname); port = (SerialPort)portId.open("serial madness", 2000); - input = port.getInputStream(); + input = new InputStreamReader(port.getInputStream()); output = port.getOutputStream(); port.setSerialPortParams(rate, databits, stopbits, parity); port.addEventListener(this); @@ -237,62 +233,41 @@ public class Serial implements SerialPortEventListener { port = null; } + char serialBuffer[] = new char[4096]; - public void addListener(MessageConsumer consumer) { - this.consumer = consumer; - } - - 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) { - //System.out.println("data available"); - //System.err.flush(); try { - while (input.available() > 0) { - //if (input.available() > 0) { - //serial = input.read(); - //serialEvent(); - //buffer[bufferCount++] = (byte) serial; + while (input.ready()) { synchronized (buffer) { if (bufferLast == buffer.length) { byte temp[] = new byte[bufferLast << 1]; System.arraycopy(buffer, 0, temp, 0, bufferLast); buffer = temp; } - //buffer[bufferLast++] = (byte) input.read(); - if(monitor == true) - 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])); - */ //} + int n = input.read(serialBuffer); + message(serialBuffer, n); } } - //System.out.println("no more"); - } catch (IOException e) { errorMessage("serialEvent", e); - //e.printStackTrace(); - //System.out.println("angry"); } 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 * and are waiting to be dealt with by the user. diff --git a/app/src/processing/app/SerialMonitor.java b/app/src/processing/app/SerialMonitor.java index 10a23331e..64c8bb399 100644 --- a/app/src/processing/app/SerialMonitor.java +++ b/app/src/processing/app/SerialMonitor.java @@ -18,18 +18,18 @@ package processing.app; -import processing.app.debug.MessageConsumer; import processing.app.debug.TextAreaFIFO; import processing.core.*; import static processing.app.I18n._; import java.awt.*; import java.awt.event.*; + import javax.swing.*; import javax.swing.border.*; import javax.swing.text.*; -public class SerialMonitor extends JFrame implements MessageConsumer,ActionListener { +public class SerialMonitor extends JFrame implements ActionListener { private Serial serial; private String port; private TextAreaFIFO textArea; @@ -210,8 +210,12 @@ public class SerialMonitor extends JFrame implements MessageConsumer,ActionListe public void openSerialPort() throws SerialException { if (serial != null) return; - serial = new Serial(port, serialRate); - serial.addListener(this); + serial = new Serial(port, serialRate) { + @Override + protected void message(char buff[], int n) { + addToUpdateBuffer(buff, n); + } + }; updateTimer.start(); } @@ -226,13 +230,8 @@ public class SerialMonitor extends JFrame implements MessageConsumer,ActionListe } } - public void message(String s) { - // TODO: can we pass a byte array, to avoid overhead of String - addToUpdateBuffer(s); - } - - private synchronized void addToUpdateBuffer(String s) { - updateBuffer.append(s); + private synchronized void addToUpdateBuffer(char buff[], int n) { + updateBuffer.append(buff, 0, n); } private synchronized String consumeUpdateBuffer() {