FAQ
Cover
This is the archive Discourse for the Processing (ALPHA) software.
Please visit the new Processing forum for current information.

   Processing 1.0 _ALPHA_
   Suggestions
   Software Suggestions
(Moderator: fry)
   Serial I/O
« Previous topic | Next topic »

Pages: 1 
   Author  Topic: Serial I/O  (Read 502 times)
spacegirl


Serial I/O
« on: Nov 22nd, 2002, 7:41am »

At the risk of sounding greedy, is there any way to enable two serial streams simultaneously, say, off of both com1 and com2?
 
 
fry


WWW
Re: Serial I/O
« Reply #1 on: Nov 25th, 2002, 4:20am »

wuall, not with beginSerial() and the rest. you can use any javax.comm code you'd like, because it's built in and you can count on it being there.
 
this is a specific part of our approach with the api used in p5.. that you get the basics very simply (one serial port, mouse coordinates, mouse down, etc), and for those who want more control (many serial ports, info on whether the alt key was pressed while mouse down) then you have easy access to the 'full' version, in this case being the use of javax.comm.  
 
for what it's worth, i've written a p5 app that uses two serial ports (and no beginSerial()) with no trouble and it works nicely.
 
fry


WWW
Re: Serial I/O
« Reply #2 on: Nov 25th, 2002, 4:26am »

here's the code for the dual serial port thing. this is 3x as much as you need to get the stuff running, but you might be able to figure out what parts to remove (i.e. you don't need all those notifyXxxx things, and only care about DATA_EVENTs..)
 
the program is used to sniff communication on a serial line--it reads from COM1, and echoes it to COM2; meanwhile doing the same in the other direction. the log of the communication is written to a file.  
 
(you might post your simpler example if you get it to work for your own use)
 
Code:
SerialPort port1;
InputStream input1;
OutputStream output1;
 
SerialPort port2;
InputStream input2;
OutputStream output2;
 
PrintWriter writer;
 
 
void setup() {
  String request1 = "COM1";
  String request2 = "COM2";
  int rate = 19200;
 
  Enumeration portList = CommPortIdentifier.getPortIdentifiers();
  while (portList.hasMoreElements()) {
    CommPortIdentifier portId =  
      (CommPortIdentifier) portList.nextElement();
 
    if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
      if (portId.getName().equals(request1)) {
      try {
        port1 = (SerialPort)portId.open("cereal killer 1", 2000);
        input1 = port1.getInputStream();
        output1 = port1.getOutputStream();
        port1.setSerialPortParams(rate,
                            SerialPort.DATABITS_8,
                            SerialPort.STOPBITS_1_5,
                            SerialPort.PARITY_NONE);
        port1.addEventListener(this);
        port1.notifyOnDataAvailable(true);
 
        port1.notifyOnBreakInterrupt(true);
        port1.notifyOnCarrierDetect(true);
        port1.notifyOnCTS(true);
        port1.notifyOnDSR(true);
        port1.notifyOnFramingError(true);
        //port1.notifyOnOutputEmpty(true);
        port1.notifyOnOverrunError(true);
        port1.notifyOnParityError(true);
        port1.notifyOnRingIndicator(true);
 
      } catch (Exception e) {
        System.err.println("error opening port 1");
        e.printStackTrace();
        //System.exit(1);
      }
      } else if (portId.getName().equals(request2)) {
      try {
        port2 = (SerialPort)portId.open("cereal killer 2", 2000);
        input2 = port2.getInputStream();
        output2 = port2.getOutputStream();
        port2.setSerialPortParams(rate,
                            SerialPort.DATABITS_8,
                            SerialPort.STOPBITS_1_5,
                            SerialPort.PARITY_NONE);
        port2.addEventListener(this);
        port2.notifyOnDataAvailable(true);
 
        port2.notifyOnBreakInterrupt(true);
        port2.notifyOnCarrierDetect(true);
        port2.notifyOnCTS(true);
        port2.notifyOnDSR(true);
        port2.notifyOnFramingError(true);
        //port2.notifyOnOutputEmpty(true);
        port2.notifyOnOverrunError(true);
        port2.notifyOnParityError(true);
        port2.notifyOnRingIndicator(true);
 
      } catch (Exception e) {
        System.err.println("error opening port 2");
        e.printStackTrace();
        //System.exit(1);
      }
      }
    }
  }
  if ((port1 == null) || (port2 == null)) {
    System.err.println("could not find the two requested ports");
  }
 
  try {
    writer = new PrintWriter(new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream("passthrough.txt"))));
  } catch (IOException e) {
    e.printStackTrace();
  }
}
 
 
public void serialEvent(SerialPortEvent event) {
  if (event.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
 
    if ((SerialPort)event.getSource() == port1) {
      process(input1, output2, true);
 
    } else {
      process(input2, output1, false);
    }
 
  } else {
    String direction = (((SerialPort)event.getSource() == port1) ?  
                  "--> " : "<-- ");
 
    String eventstr = null;
    switch (event.getEventType()) {
    case SerialPortEvent.CTS: eventstr = "CTS"; break;
    case SerialPortEvent.DSR: eventstr = "DSR"; break;
    case SerialPortEvent.RI:  eventstr = "RI";  break;
    case SerialPortEvent.CD:  eventstr = "CD";  break;
    case SerialPortEvent.OE:  eventstr = "OE";  break;
    case SerialPortEvent.PE:  eventstr = "PE";  break;
    case SerialPortEvent.FE:  eventstr = "FE";  break;
    case SerialPortEvent.BI:  eventstr = "BI";  break;
    default: eventstr = "unknown " + event.getEventType(); break;
    }
    System.out.println(direction + " " + eventstr);
 
    writer.print(direction + " " + eventstr + "\n\n");
  }
}
 
 
static byte buffer[] = new byte[32768];
 
public void process(InputStream input, OutputStream output, boolean one) {
  try {
    int count = input.available();
    if (count > buffer.length) buffer = new byte[count*2];
 
    int stamp = millis();
    String line1 = (one ? "--> " : "<-- ") +
      count + " byte" + ((count != 1) ? "s" : "");
    System.out.println(line1);
    writer.print(line1 + "\n");
 
    int sofar = 0;
    while (sofar < count) {
      sofar += input.read(buffer, sofar, count - sofar);
    }
    output.write(buffer, 0, count);
    output.flush();
 
    String line2 = formatChunk(buffer, 0, count, 0);
    System.out.println(line2);
    writer.print(line2 + "\n");
    writer.flush();
 
  } catch (IOException e) {
    e.printStackTrace();
  }
}

 
 
« Last Edit: Nov 25th, 2002, 4:27am by fry »  
fry


WWW
Re: Serial I/O
« Reply #3 on: Nov 25th, 2002, 4:27am »

the last part of the code (was too long for a single message)
 
Code:
// ...........................................................
 
 
static final byte hexBytes[] = {
  (byte) '0', (byte) '1', (byte) '2', (byte) '3',  
  (byte) '4', (byte) '5', (byte) '6', (byte) '7',
  (byte) '8', (byte) '9', (byte) 'A', (byte) 'B',  
  (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F'  
};
 
static final byte HEX_UNPRINTABLE = (byte) '.';
static final int HEX_LINE_LENGTH = 16*2 + 16/2 + 16 + 1;
static final int HEX_CHUNK_LENGTH = HEX_LINE_LENGTH + 10;
private static byte tempLine[];
private static String whiteSpace;
 
 
static {
  tempLine = new byte[HEX_LINE_LENGTH+1];
  for (int i = 0; i < HEX_LINE_LENGTH; i++) {
    tempLine[i] = (byte) ' ';
  }
  tempLine[HEX_LINE_LENGTH] = (byte) '\n';
  whiteSpace = "   ";
}
 
 
public static String formatChunk(byte source[],  
     int offset, int length, int linenum) {
  StringBuffer buffer = new StringBuffer(length * 4);
  int count = 16;
 
  try {
    for (int i = 0; i < length; i += 16) {
 if (length - i < 16) {
 count = length - i;
 }
 buffer.append(formatLine(source, offset + i, count));
 linenum += 16;
    }
  } catch (IOException e) {
    System.err.println("i/o error: " + e);
  }
  return buffer.toString();
}
 
 
private static String formatLine(byte source[],
     int offset, int charCount)
  throws IOException
{
  // have to clear out if the whole line won't be over-written
  if (charCount < 16) {
    for (int i = 0; i < HEX_LINE_LENGTH; i++) {
 tempLine[i] = (byte) ' ';
    }
  }
  int left = 0;
  int right = 16*2 + 16/2 + 1;
 
  for (int i = 0; i < charCount; i++) {
    int c = source[i + offset] & 0xff;
    tempLine[left+0] = hexBytes[c / 16];
    tempLine[left+1] = hexBytes[c % 16];
    left += 2 + (i % 2);
    if ((c >= 32) && (c <= 126))
 tempLine[right++] = (byte) c;
    else
 tempLine[right++] = HEX_UNPRINTABLE;
  }
  return new String(tempLine);
}
 
tigoe
Guest
Email
Re: Serial I/O
« Reply #4 on: Aug 21st, 2003, 10:26pm »

First off:
 
Congratulations, Ben, on getting serial working on the mac with the latest version of rxtx, and thank you!
 
second:  
I love the simple serial implementation. One of the best I've seen because it is so simple.
 
Third:  
It could be a bit more complex, and still be great, I think.  
 
First, implement serialBuffer(). Make it return the whole serial buffer as a char array.  Let the user dump it into another array if they want to, e.g.
myArray[] = char;
..
on serialEvent() {
   myArray = serialBuffer();
}
 
Second, let the end user peek at the serial buffer's length.  Something like this:
 
on serialEvent() {
   if (serialBuffer.length() > 5) {
   // parse the array
   myArray = serialBuffer();
   }
}
 
The reason for the peek is that it makes it possible to see if you've got a full sentence of serial data (like, perhaps if you're parsing serial GPS data, just as a hypothetical example) and want to know that it's all there and intact before you parse.  
 
Currently, a multiple-byte string coming in doesn't work, because each new byte wipes out the byte before it. I tried a simple call and response example: have P5 send a signal character, and have a microcontroller send a 5-byte string in response.  The first 4 bytes sent get thrown out, and only the fifth makes it through.  Unless I'm doing something wrong, in which case, someone please correct me!
 
 
 
tigoe


Re: Serial I/O
« Reply #5 on: Aug 21st, 2003, 10:36pm »

Augh!  I spoke too soon!  Glen just posted a beautiful GPS serial example, which I now have to try.
 
Pages: 1 

« Previous topic | Next topic »