Open mbr opened 7 years ago
An alternative that is less flexible would be adding support for the tcsendbreak
syscall, which achieves the above without funky bitrate changing tricks (although the required pause MARK-AFTER-BREAK
must then be done "by hand"). Adding support for this feature would almost be equivalent.
Edit: Unfortunately, the tc_sendbreak
is fairly platform dependant:
The effect of a nonzero duration with tcsendbreak() varies. SunOS specifies a break of duration * N seconds, where N is at least 0.25, and not more than 0.5. Linux, AIX, DU, Tru64 send a break of duration milliseconds. FreeBSD and NetBSD and HP-UX and MacOS ignore the value of duration. Under Solaris and UnixWare, tcsendbreak() with nonzero duration behaves like tcdrain().
A millisecond is a long time, about 10x as much as needed for the usecase described above.
Currently, settings (on Linux) are changed using
tcsetattr
inwrite_settings
, passing inTCSANOW
foroptional_actions
. This causes the new settings to take effect immediately, here's the code in question:WIth the proposed pull request #42 , this (on Linux) changes to:
Instead of
tcsetattr
, theTCSETS2
ioctl is used.The issue here is that TCSANOW is hardcoded, which prevents using some of the useful alternative options (from man
tcsetattr(3)
):TCSANOW
TCSADRAIN
TCSAFLUSH
This parameter cannot be specified with the TCSETS2, instead, different IOCTLS must be used. The old equivalents are documented in
tty_ioctl(4)
:Note the missing
2
. An equivalentTCSETS2
,TCSETSW2
andTCSETSF2
exist (some information about these can be found here); they work pretty much the same, except that they require astruct termios2 *
instead of astruct termios *
.A feature that is currently missing in
serial-rs
is the ability to specifiy when the settings changes should take effect. This API needs to be designed and added to the trait first, I'll happily implemented it on Linux, but I'd like to avoid introducing core API changes that may be rejected.Currently, a workaround exists: Calling
flush()
on theSerialPort
and only then writing new settings. This will cause an additional gap in transmisison for as long as it takes to setup and transfer these settings into the kernel.A usecase for this is implementing DMX512 using an RS485 serial port. The DMX512 has a lenient but weird structure, it basically is just a regular UART serial port at 250,000 baud (hence the other pull request for non-standard bitrates).
However, to begin transmission of a frame a DMX master must send a long
BREAK
by pulling the line low for a fairly long amount of time, then releasing it. This can easily be emulated on any UART by setting the bitrate to 57,000 baud, writing a0x00
byte (7 bit), which will result in a 138 usBREAK
(the minimum is92
us). Directly after (but not during) the port should be switched to 250,000 baud and transmission can begin. In Pseudo-code:BREAK
Step 3. could be improved by preparing the new settings in advanced through
TCSETSW2
, hopefully causing minimal delay when switching bitrates.