Wednesday, November 02, 2005


Cross platform serial developing

I have heard some people say that any time you need to code for hardware cross platform, you are doomed to fail. Maybe that is true in some circumstances. I'm so inexperienced code wise that I can't say one way or another. I can tell you what I've seen with Perl.

First, the pain level really depends on what you're trying to do with the serial port. If you were, say, trying to communicate with a modem and a remote system or a live user, that is probably going to be relatively easy to create something that will work on the platforms you need it to. Problems will likely arise with things like identifying the serial port (/dev/blah, Com1, or more esoteric depending on the platform).

In a simple exercise, even this isn't a big deal. You can rely on the user to specify their serial port correctly or use a little bit of conditional logic to try to guess at it. Another option is to abstract it via a conditionally loaded object. To someone who had only used procedural programming for so long, this feels like magic.

The idea is this. Class A needs to communicate with the serial port. This involves things like configuring the port (setting baud rates, buffers, etc), writing data, reading data and getting status (for instance, whether the buffer has characters waiting or whether CTS is high or low). Class A conditionally loads a serial class based on the platform. For instance, this probably bug-ridden code:

package a;

my $osname = $^O;

if ($osname eq 'Win32') {
use Win32::SerialPort;
my $serial = new Win32::SerialPort;
} elsif ($osname eq 'Linux') {
use Device::SerialPort;
my $serial = new Device::SerialPort;
} else
die "Oops, not cross-platform enough";

In this case, Win32::SerialPort and Device::SerialPort both have nearly identical interfaces. In a case where they didn't, an object could be created to abstract a native serial port object to a common interface.

Abstraction isn't the exclusive domain of OOP. Much of the same could be implemented with procedural calls. The difference is that once the object is instantiated, a method call is already routed to the correct class library. Without objects you are probably relying on the exporter to export the same interface into your namespace. That's ugly. It gets uglier when you're using a language that doesn't do that magic exporting.

This goes a little beyond theory. I ran into several modules on CPAN that control X10 products and things like the XM PCR which use exactly this technique to port between Windows and Linux. And, although I figured out that I really need to rewrite the serial communication methods in Audio::Radio::Sirius, it limps along there as well. We'll see how it turns out.

Comments: Post a Comment

Links to this post:

Create a Link

<< Home

This page is powered by Blogger. Isn't yours?