Serial Port Module?

Started by ryuo, June 25, 2014, 07:56:24 PM

Previous topic - Next topic

ryuo

I have noticed there are no APIs in newLISP for this fairly common piece of hardware. I have written a working prototype of this functionality that works for the newLISP Linux version. Hopefully it will also work with other UNIX platforms. I was wondering if there was anyway to get this module incorporated into newLISP officially. It has two parts. There's the C source code which acts as an intermediate layer that abstracts the platform specific code for opening, closing, reading, writing, and configuring serial ports. And then there's the newLISP interface module which binds the simple public C API of the serial port abstraction library into an easy to use FOOP class. The repo for my prototype can be found here: https://github.com/ryuo/newlisp-serial-port">https://github.com/ryuo/newlisp-serial-port



There is also a short script in the repo that I wrote to test the module with an LCD character display that is controlled through a USB serial port adapter.



However, I have no plans to support serial port features that lack convenient access in the underlying platform API. This likely means no DSR/DTR flow control and no Space or Mark Parity. These features appear to be absent from any high level OS abstraction API for serial ports. It's not part of the termios abstraction (the POSIX API for serial ports and other terminal devices). I've only seen it possible to support these features via platform specific usage of ioctl, which is far less portable than using the higher level termios API. Considering I rarely see any hardware that requires these features, I feel it's a waste of time to try to support it. I envision this module as a lightweight abstraction for serial ports on most platforms that newLISP will run on. For now, I wish to keep the supported features restricted to things that will probably work on most of the platforms. However, there's at least two platform specific details that cannot be avoided: the list of supported baud rates and the list of available serial ports. So, I still need to add an API to get a list of all the supported baud rates and available serial ports for the platform that newLISP is running on.



Anyway, thoughts, commentary? Thanks.

Astrobe

#1
To me, the major split is between Windows and Linux platforms. That's also true for sockets. You have no choice but to write platform specific code and to hide the differences behind the a common API.

As for DSR/DTR, RS is such a mess that one can always stumble upon some hardware that do use that. For instance control lines can be used for "reversing" the line driver in the case of an RS485 bus. But I think the few guys that may be interested in this should be savvy enough to fill in the missing parts and would be happy to find a module that already does most of the job - provided it is well written etc.

ryuo

#2
Indeed. There is no way to avoid at least some platform specific code. There should be less of that for the UNIX family, but Windows is another story. I've finished writing an API for retrieving the baud rates that the platform supports and the list of serial port devices currently known to the system. The main criteria for these two lists is that all elements must be valid input for the SerialPortOpen and SerialPortSetParameters functions. I have also decided on a license for the C and newLISP source code. It's all MIT licensed. It is my hope that it can eventually be included in newLISP as an official module. However, I have yet to hear anything from Lutz. So no idea where this stands.

Lutz

#3
It could be linked too from the http://www.newlisp.org/modules/various/index.html">http://www.newlisp.org/modules/various/index.html section when it has documentation. After reading through the C-code, I wonder if the whole thing could be done just in newLISP, without an intermediary C-lib, or at least only importing existing system C-libraries? Many users are not accustomed to compile.

ryuo

#4
Ideally I think it would be statically linked into the interpreter, as it is a very small library, only requiring standard system libraries. The standard C library is all it requires on UNIX systems, and for windows it can use one of the standard system libraries for that system. Windows has its own API for interfacing with serial ports (called COM in Windows land), so it could probably be interfaced through the Win32 API, thus requiring no new DLLs be shipped with the Windows build.



I chose to build it as an external module and small C library because I felt that it would be easiest to encapsulate platform specific details behind a simple C API. But I would prefer it to be interfaced

directly into the interpreter, to avoid some portability issues such as pointer size.

ryuo

#5
Lutz, you also mention the possibility of loading the C functions I use internally at runtime, but I do not consider this wise.



I use a lot of constants which are actually preprocessor macros that have no guarantees about what their value will be on other implementations. And I can't load these at runtime as the preprocessor macros are not part of the library ABI. I would have to maintain a table of constants for each platform, and it would be more trouble than just using a C abstraction layer.



There is also the fact that I must make use of a number of POSIX structs that are not guaranteed to have the same contents for all POSIX platforms. POSIX only guarantees a few members. Implementations are still free to add more members as they see fit. Specifically, I am speaking about termios. For example, how baud rate is stored is not standardized. Some platforms store it in separate integers while others store it as part of one of the bit flag integers. To do this portably, POSIX specifies functions for setting or getting it.



If this was a library with a constant public interface (like mysql or such), then I would agree with you, but that is not the case here.



I do not consider it wise to try to import constant values from the C standard library for ISO, POSIX, and possibly Win32 APIs. The C compiler can handle these details on behalf of newLISP transparently for the most part as it doesn't effect the usage of the API. Because of how unpredictable the contents of structs, constants, and other details defined by ISO, POSIX, and possibly Win32 can be, I think it is easier to just use a C library to wrap these details into a consistent API.

Lutz

#6
Put something into the https://github.com/ryuo/newlisp-serial-port/blob/master/README.md">https://github.com/ryuo/newlisp-serial- ... /README.md">https://github.com/ryuo/newlisp-serial-port/blob/master/README.md file and a link to your repository could be on the http://www.newlisp.org/modules/various/index.html">http://www.newlisp.org/modules/various/index.html page.



The module file serial-port.lsp could contain the API docs and examples, but in newLISP doc format and mentioning that a small compiled C-lib is necessary. This file then could have a link to your repository. There are no plans currently to make a serial communications API part of the main distributable.