Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

Serial Comms for Windows

Posted: 03/16/09 16:33:50 Modified: 03/16/09 18:36:21

I have written and tested a threaded serial port class for D + Tango. It is similar to the SerialPort? class in System.IO.Ports in .NET. It is only for DOS/Windows. Is it worth including in the tango/io/device subdir - the present SerialPort?.d appears to unfinished for Linux and not started for DOS.

If not for inclusion into Tango is there a suitable library it could be?

I tried e-mailing Tim Burrell regarding inclusion into tango.scrapple many moons ago and received no reply.

Regards, Mike.

Author Message

Posted: 03/16/09 19:13:24

Well, it depends a bit on what you want your class to do.

Deficiencies in the SerialPort device should be addressed as tickets to that one. If you feel your functionality goes beyond that, then that would have to be discussed on its own merits. Considering that a threaded communication device sounds like something that shouldn't necessarily be serial port specific, maybe it could be generalized? Is it similar to the concepts sketched in #1470 for instance?

Posted: 03/16/09 21:23:40 -- Modified: 03/16/09 21:27:32 by
Mike James

Hi larsivi,

The serial port class is a fairly standard open(), close(), read() write() driver. The thread is required for the serial event handler to wait for receive, error, tx empty, breaks and status change events without blocking.

A short program that gives a flavour of the class in action...

int main() {

Comms comms = new Comms("COM3", 4800, 8, Comms.StopBits?.One, Comms.Parity.None);

void textIn() {

char ch; while (comms.bytesToRead > 0) {

switch (ch = cast(char)comms.readChar()) {

case '\r':

Stdout.newline; break;

default:

Stdout.format("{0}", ch).flush; break;

}

}

}

void txEmptyDetected() {

Stdout.formatln("TX EMPTY");

}

void breakDetected() {

Stdout.formatln("BREAK");

}

void statusChange(ModemStatus? mask, ModemStatus? status) {

Stdout.formatln("CTS : {0}, {1}", mask.cts, status.cts);

Stdout.formatln("DSR : {0}, {1}", mask.dsr, status.dsr);

Stdout.formatln("RLSD : {0}, {1}", mask.rlsd, status.rlsd);

Stdout.formatln("RI : {0}, {1}", mask.ri, status.ri); Stdout.formatln("");

}

comms.handshake = Comms.Handshake.None;

comms.onData = &textIn; // receive data event

comms.onTxEmpty = &txEmptyDetected; // transmit buffer empty

comms.onBreak = &breakDetected; // break event

comms.onStatusChange = &statusChange; // RS-232 handshake

comms.open();

char[] str = new char[10];

comms.writeln("Hello World");

comms.writeln("the quick brown fox jumped over the lazy dog");

comms.writeImmediate('!');

while ((str = Cin.get) != "q") {

comms.write(str);

}

comms.close();

return 0;

}

The functionality is fairly close to the .NET SerialPort? class - http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.aspx

Regards, Mike.

Posted: 03/16/09 22:36:03

The SerialPort implementation in Tango supports non-blocking operation via the Selector functionality, something that is common for all selectable device types. The only question would be whether all the serial signals can be handled by this mechanism, since if it is , that is a much better solution than having something that is specific for serial port handling.

Posted: 03/18/09 13:22:09

On windows, selector is only usable on network sockets. A stupid limitation, but what are you going to do?

Way back when, I wrote a C++ OS abstraction library for my company, which happened to abstract IO to both sockets and serial ports. Basically, I built simple selection functions into each IO element, such as wait(Enum ReadOrWrite?, int milliseconds = -1). Mostly this was a design decision based on the fact that select only works on sockets on Windows. Not sure it's worth putting this functionality into all conduits of Tango, but it's something to consider. The functions would be braindead simple for unix-like OSes, since they would just call select in the same way. Windows has various methods of waiting for input, but they are all different per device type (a horrible design if you ask me). They focused on overlapped i/o which is a terrible design if you are trying to wait for input on multiple devices.

Also note that there is precedent -- Socket supports a member select call. Maybe it's worth while to separate SerialPort? into a low level device class which has various serial-only functions, and a class that implements the conduit interface, similar to Socket and SocketConduit?.

Posted: 03/18/09 15:55:40

There's a number of ways to improve non-blocking I/O in Tango, and one of them is to leverage LibEvent?. That aside, Steve's idea of a high/low split seems like a good one (Note: I'm not so sure that explicit support for DOS is such a great idea these days)

Posted: 03/18/09 16:08:33

Considering we're not really supporting 90's Windows, I also have some doubts over DOS support.

As for making non-blocking IO more flexible, that is something I'm for. The selectable interface should be such that alternative selction mechanisms could be implemented if necessary.

For laughs; lately I've had the joy of working with a serial comms interface on a unix like OS where only polling is supported, making "fast" serial communication such as 115200 almost impossible. Apperently an interrupt driven interface is under development.

Posted: 03/18/09 16:51:05 -- Modified: 03/18/09 16:54:50 by
Mike James

Hi All,

Sorry if I caused confusion with my DOS/Windows comment - the serial port class works on Windows 2000, XP and Vista.

The class uses the standard WaitForMultipleObjects?() to block for a serial event.

Regards, Mike.