The V.18 standard gives specifications for the implementation of text telephones, more commonly called TDDs (Telecommunications Devices for the Deaf). The annexes each specify an alternative communications method. This is because the standards brings together existing practice from different regions, each of which developed different types of terminal. Here we consider the implementation of each of these. The initial probing sequence which would automatically detect which one to use is rather more complex and is not considered.
Allocate a full duplex channel, even if the mode you are using is half-duplex. This allows you to configure it once, rather than having to re-configure every time you switch between sending and receiving.
This describes an FSK modem which uses a 5-bit code very similar to Baudot. To implement this on Prosody, configure the channel to use FSK as its protocol as follows:
speed | 50 |
---|---|
mark_frequency | 1400 |
space_frequency | 1800 |
rx_carrier_on_mS | 1 |
rx_carrier_off_mS | 80 |
But note that in the USA a speed of 45.45 bits per second is typical. To specify this, use 45 as the speed.
In principle, the correct value for rx_carrier_on_mS
is
150
, but some existing devices send data with no carrier
before the first data bit, so the receiver must react instantly to a
signal to avoid missing the first character of each transmission.
Configure it to use Async as its encoding as follows:
databits | 5 |
---|
Note that V.18 requires 150mS of carrier to be sent before any data every time the carrier is turned on. To achieve this, set a prefix '11111111' (eight bits of binary 1). This generates carrier for 160 mS. Similarly, a suffix of '111111111111111' (fifteen bits of binary 1) can be used to measure the required 300 mS after transmission in which the receiver is to be disabled.
When sending or receiving data, you will normally need to convert
into and out of the 5-bit code. Some useful functions are provided in
libutil/v18a.h
and libutil/v18a.c
which can
do this for you. They are:
v18astate()
.
os | The address of the first character of the output buffer. |
---|---|
oe | The address of the first character after the end of the output buffer. |
vs | A pointer to a V18ASTATE structure that has been
initialised with v18astate() .
|
*ibuf | The address of the first character of the output buffer. On return, this has been updated to indicate how much data has been successfully processed. |
ie | The address of the first character after the end of the input buffer. |
v18a_fromT50()
.
ofn
is invoked to output each character, with the
parameter p
being passed in each time, along with the
character to be printed. The character ic
is the next in
the sequence of V.18 Annex A characters. Since this is used for
debugging, every invocation generates some output, showing what
character was processed. In addition, the characters
LTRS
and FIGS
modify the state to indicate
the new mode, so that future characters are interpreted correctly.
The V.18 (02/1998) appears to have a few errors which are handled as follows:
NULL
produce no output, except for DEL
which produces only a LTRS
code.
Obviously, since the source code is provided, if you want some variation based on the V.18 specification you can use the source code provided as a starting point for modifications.
Since this uses ordinary DTMF tones, you can use the speech API functions sm_listen_for() and sm_play_digits() to receive and transmit the data. You will also need to translate characters into and out of the sequences of tones used.
This uses standard V.21 FSK modulation (half-duplex, using only channel 1), see the FSK rx and FSK tx documentation for configuration details, but note that the speed used is only 110 bits per second, even though V.21 is capable of 300 bits per second.
You will also need to add even parity bits to the data being sent. This is trivially done with a small array which maps a character into the same character with the correct parity bit. Here is an example:
static char even_parity[256]; void init_parity(void) { unsigned i; even_parity[0] = 0; for (i=0; i<8; i++) { // for each bit unsigned m = 1 << i; unsigned j; for (j=0; j < m; j++) { even_parity[j + m] = even_parity[j] ^ 0x80 ^ m; } } }
After initialisation, even_parity[x]
is the character
x
with bit 7 (the parity bit) set to even parity.
This uses standard Bell 103 FSK modulation, so see the FSK rx and FSK tx documentation for configuration details.
This uses standard V.23 FSK modulation, so see the FSK rx and FSK tx documentation for configuration details.
This uses standard V.21 FSK modulation, see the FSK rx and FSK tx documentation for configuration details.
This is essentially the same as for Annex F.
Document reference: AN 1399