Skip to content

Commit

Permalink
Add experimental RS-485 support
Browse files Browse the repository at this point in the history
Many modern RS-485 serial devices such as the ones from FTDI already
operate in RS-485 mode by default and will work with tio out of the box.
However, there are some RS-232/485 devices which need to be switched
from e.g. RS-232 to RS-485 mode to operate accordingly on the physical
level.

This commit implements the switching mechanism and interface required to
enable RS-485 mode. It only works on Linux and with serial devices which
use device drivers that support the Linux RS-485 control interface.

The RS-485 feature is detailed via the following options:

 --rs-485                           Enable RS-485 mode
 --rs-485-config <config>           Set RS-485 configuration

Set the RS-485 configuration using the following key or key value pair
format in the configuration field:

 RTS_ON_SEND=value             Set logical level (0 or 1) for RTS pin when sending
 RTS_AFTER_SEND=value          Set logical level (0 or 1) for RTS pin after sending
 RTS_DELAY_BEFORE_SEND=value   Set RTS delay (ms) before sending
 RTS_DELAY_AFTER_SEND=value    Set RTS delay (ms) after sending
 RX_DURING_TX                  Receive data even while sending data

If defining more than one key or key value pair, they must be comma
separated.

Example use:

 $ tio /dev/ttyUSB0 --rs-485 --rs-r485-config=RTS_DELAY_AFTER_SEND=50,RX_DURING_TX
  • Loading branch information
lundmar committed Sep 10, 2022
1 parent a58d406 commit ee46686
Show file tree
Hide file tree
Showing 13 changed files with 351 additions and 11 deletions.
10 changes: 0 additions & 10 deletions TODO
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,3 @@
$ tio --socket ws:1234

Use libwesockets to implement feature.

* RS-485 support

Many modern RS-485 devices such as the ones from FTDI already operate in
RS-485 mode by default and will work with tio out of the box. However, there
are still some RS-232/485 devices which need to be switched from e.g. RS-232 to
RS-485 mode to operate accordingly on the physical level.

To enable RS-485 mode on such serial devices the idea is to add a --rs-485
option.
6 changes: 6 additions & 0 deletions example/tiorc
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,9 @@ color = 11
pattern = usb([0-9]*)
tty = /dev/ttyUSB%s
color = 12

[rs-485-device]
tty = /dev/ttyUSB0
rs-485 = enable
rs-485-config = RTS_ON_SEND=1,RTS_AFTER_SEND=1,RTS_DELAY_BEFORE_SEND=60,RTS_DELAY_AFTER_SEND=80,RX_DURING_TX
color = 13
36 changes: 36 additions & 0 deletions man/tio.1.in
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,33 @@ response mode to make it easy to parse the response.

Set timeout [ms] of line response (default: 100).

.TP
.BR " \-\-rs\-485"

Enable RS-485 mode.

.TP
.BR " \-\-rs\-485\-config " \fI<config>

Set the RS-485 configuration using the following key or key value pair format in
the configuration field:

.RS
.TP 30n
.IP \fBRTS_ON_SEND=value
Set logical level (0 or 1) for RTS pin when sending
.IP \fBRTS_AFTER_SEND=value
Set logical level (0 or 1) for RTS pin after sending
.IP \fBRTS_DELAY_BEFORE_SEND=value
Set RTS delay (ms) before sending
.IP \fBRTS_DELAY_AFTER_SEND=value
Set RTS delay (ms) after sending
.IP \fBRX_DURING_TX
Receive data even while sending data
.P
If defining more than one key or key value pair, they must be comma separated.
.RE

.TP
.BR \-v ", " \-\-version

Expand Down Expand Up @@ -358,6 +385,10 @@ Set prefix ctrl key (a..z, default: t)
Enable wait for line response
.IP "\fBresponse-timeout"
Set line response timeout
.IP "\fBrs-485"
Enable RS-485 mode
.IP "\fBrs-485-config"
Set RS-485 configuration

.SH "CONFIGURATION FILE EXAMPLES"

Expand Down Expand Up @@ -507,6 +538,11 @@ Likewise, to pipe data from file to the serial device:

$ cat data.bin | tio /dev/serial/by\-id/usb\-FTDI_TTL232R-3V3_FTGQVXBL\-if00\-port0

.TP
Enable RS-485 mode:

$ tio --rs-485 --rs-485-config=RTS_ON_SEND=1,RX_DURING_TX /dev/ttyUSB0

.SH "WEBSITE"
.PP
Visit https://tio.github.io
Expand Down
7 changes: 7 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,12 @@ foreach rate : test_baudrates
endif
endforeach

# Test for RS-485 support on Linux
if host_machine.system() == 'linux'
if compiler.check_header('linux/serial.h')
enable_rs485 = compiler.has_header_symbol('sys/ioctl.h', 'TIOCSRS485')
endif
endif

subdir('src')
subdir('man')
10 changes: 10 additions & 0 deletions src/bash-completion/tio.in
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ _tio()
-S --socket \
-r --response-wait \
--response-timeout \
--rs-485 \
--rs-485-config \
-x --hexadecimal \
-v --version \
-h --help"
Expand Down Expand Up @@ -122,6 +124,14 @@ _tio()
COMPREPLY=( $(compgen -W "1 10 100" -- ${cur}) )
return 0
;;
--rs-485)
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
;;
--rs-485-config)
COMPREPLY=( $(compgen -W "RTS_ON_SEND RTS_AFTER_SEND RTS_DELAY_BEFORE_SEND RTS_DELAY_AFTER_SEND RX_DURING_TX" -- ${cur}) )
return 0
;;
-x | --hexadecimal)
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
Expand Down
17 changes: 17 additions & 0 deletions src/configfile.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "options.h"
#include "error.h"
#include "print.h"
#include "rs485.h"

static struct config_t *c;

Expand Down Expand Up @@ -264,6 +265,22 @@ static int data_handler(void *user, const char *section, const char *name,
{
option.response_timeout = atoi(value);
}
else if (!strcmp(name, "rs-485"))
{
if (!strcmp(value, "enable"))
{
option.rs485 = true;
}
else if (!strcmp(value, "disable"))
{
option.rs485 = false;
}
}
else if (!strcmp(name, "rs-485-config"))
{
rs485_parse_config(value);
}

}
return 0;
}
Expand Down
7 changes: 6 additions & 1 deletion src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ tio_sources = [
'configfile.c',
'signals.c',
'socket.c',
'setspeed.c'
'setspeed.c',
'rs485.c'
]

tio_dep = dependency('inih', required: true,
Expand All @@ -31,6 +32,10 @@ if enable_iossiospeed
tio_c_args += '-DHAVE_IOSSIOSPEED'
endif

if enable_rs485
tio_c_args += '-DHAVE_RS485'
endif

executable('tio',
tio_sources,
c_args: tio_c_args,
Expand Down
19 changes: 19 additions & 0 deletions src/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "misc.h"
#include "print.h"
#include "tty.h"
#include "rs485.h"

enum opt_t
{
Expand All @@ -44,6 +45,8 @@ enum opt_t
OPT_LOG_STRIP,
OPT_LINE_PULSE_DURATION,
OPT_RESPONSE_TIMEOUT,
OPT_RS485,
OPT_RS485_CONFIG,
};

/* Default options */
Expand Down Expand Up @@ -78,6 +81,10 @@ struct option_t option =
.response_wait = false,
.response_timeout = 100,
.mute = false,
.rs485 = false,
.rs485_config_flags = 0,
.rs485_delay_rts_before_send = -1,
.rs485_delay_rts_after_send = -1,
};

void print_help(char *argv[])
Expand Down Expand Up @@ -109,6 +116,8 @@ void print_help(char *argv[])
printf(" -x, --hexadecimal Enable hexadecimal mode\n");
printf(" -r, --response-wait Wait for line response then quit\n");
printf(" --response-timeout <ms> Response timeout (default: 100)\n");
printf(" --rs-485 Enable RS-485 mode\n");
printf(" --rs-485-config <config> Set RS-485 configuration\n");
printf(" -v, --version Display version\n");
printf(" -h, --help Display help\n");
printf("\n");
Expand Down Expand Up @@ -295,6 +304,8 @@ void options_parse(int argc, char *argv[])
{"hexadecimal", no_argument, 0, 'x' },
{"response-wait", no_argument, 0, 'r' },
{"response-timeout", required_argument, 0, OPT_RESPONSE_TIMEOUT },
{"rs-485", no_argument, 0, OPT_RS485 },
{"rs-485-config", required_argument, 0, OPT_RS485_CONFIG },
{"version", no_argument, 0, 'v' },
{"help", no_argument, 0, 'h' },
{0, 0, 0, 0 }
Expand Down Expand Up @@ -437,6 +448,14 @@ void options_parse(int argc, char *argv[])
option.response_timeout = string_to_long(optarg);
break;

case OPT_RS485:
option.rs485 = true;
break;

case OPT_RS485_CONFIG:
rs485_parse_config(optarg);
break;

case 'v':
printf("tio v%s\n", VERSION);
exit(EXIT_SUCCESS);
Expand Down
5 changes: 5 additions & 0 deletions src/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#pragma once

#include <stdint.h>
#include <stdbool.h>
#include <limits.h>
#include <termios.h>
Expand Down Expand Up @@ -70,6 +71,10 @@ struct option_t
bool response_wait;
int response_timeout;
bool mute;
bool rs485;
uint32_t rs485_config_flags;
int32_t rs485_delay_rts_before_send;
int32_t rs485_delay_rts_after_send;
};

extern struct option_t option;
Expand Down
1 change: 1 addition & 0 deletions src/print.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#pragma once

#include <stdio.h>
#include <stdbool.h>
#include "misc.h"
#include "error.h"
Expand Down
Loading

0 comments on commit ee46686

Please sign in to comment.