HDLC is an encoding which runs in conjunction with an underlying protocol. For example, it might decode data received by a modem, or it might run over the datatx/datarx protocol as part of an implementation of V.120.
This should be read in conjunction with the generic data communications documentation.
You must use #include "smdc_hdlc.h"
to get the
appropriate declarations.
The encoding type is kSMDCConfigEncodingHDLC
.
The encoding_config_data pointer must point to one of these structs:
typedef struct smdc_hdlc_format_parms { tSM_INT crcsize; tSM_INT crc; tSM_INT rx_min_initial_flags; tSM_INT rx_min_ones; } SMDC_HDLC_FORMAT_PARMS;
where crcsize is the size of the CRC in bits and crc is the CRC polynomial. This value has bit n set if the polynomial includes the x^n term. Any CRC can be used from 0 to 32 bits. A zero bit CRC is the same as using no CRC.
For example, the CRC-CCITT, x^16 + x^12 + x^5 + x^0
must have bits 16, 12, 5 and 0 set, so the value to use is
0x11021
. Note that all 16-bit CRCs use values in
the form 0x1XXXX
, since their highest term must be
x^16. A 32-bit CRC would use a value in the form
0x1XXXXXXXX
. Since this is larger than can be
represented in 32 bits, the 2^32 term is implicitly assumed to
be present when you specify 32 for the crcsize.
(Actually, the highest term is always implicitly inserted, so
you could also use 0x1021
to specify the CRC-CCITT
crc value).
Note that the x^0
term is usually written as
1
, so don't accidentally treat it as
x^1
. i.e. the CRC-CCITT is often described as
x^16 + x^12 + x^5 + 1
.
Where supported by the firmware, rx_min_initial_flags is the minimum number of consecutive flags that must be received at the start of a series of frames. Currently, firmware supporting this feature is only available for ProsodyX cards.
Where supported by the firmware, rx_min_ones is the minimum number of consecutive one bits that must be received to provoke a report of idle. Such a report will always follow a report of receiving junk. If this parameter is set to zero, the reception of the idle pattern is not reported. Currently, firmware supporting this feature is only available for ProsodyX cards.
The firmware module hdlcrx must have been downloaded to receive HDLC, and hdlctx is required to transmit.
Data in the receive buffer appears in multiples of 32 bits.
With one exception, the data appearing is from HDLC frames.
This exception is that the 32-bit word 0xffffffff
is a special marker. Obviously this pattern might appear in
the data, so if a marker word appears in two consecutive words,
it represents data consisting of just 0xffffffff
(i.e. four octets of 0xff
). Other occurrences of
the marker word are followed by two status words and report
significant points in the received signal. Let us call these
status words S1
and S2
. (Obviously
S1
can never be 0xffffffff
). They are
interpreted as follows.
If the least significant bit (bit 0) of S2
is clear, the
receiver has seen a flag at the end of a frame. In this case,
some frame data may have already been delivered before the
marker word (depending in the length of the frame) and the word
S1
contains any odd bits left over (i.e. up to 31
bits).
Prosody data communications Encodings: HDLC data delivery
explains how you can tell the exact length of data received. Bit
1 of S2
indicates the result of checking the CRC.
It is set if the CRC is incorrect.
If the least significant bit (bit 0) of S2
is set, the
receiver is reporting one of three different status changes.
Bits 2 and 3 of S2
indicate which, as follows:
S2 | Meaning |
---|---|
...0000 | Frame with correct CRC |
...0010 | Frame with bad CRC |
...00x1 | Aborted frame |
...0101 | Receiving flags |
...1001 | Receiving junk |
...1111 | Receiving idle pattern (all ones) |
When a frame is aborted, S1
contains any odd bits
not yet delivered (in exactly the same way as for valid frames).
In the other cases S1
is zero.
To avoid redundant status reports, the receiver does not produce two consecutive reports of receiving flags (or of receiving junk). This means that, for example, if it sees some flags, a few valid frames, an abort, and more flags, it will only report seeing flags once at the beginning and once after the abort. Similarly, once it has reported seeing junk, the next report must be that it is seeing flags (unless, of course, the receiver is disabled first).
Here is an example of data from a receiver:
smdc_rx_data values | Interpretation |
---|---|
0xffffffff | Receiving flags |
0x00000000
| |
0x00000005
| |
0x12345678 | Valid frame 78 56 34 12 ff ff ff ff 21 43 65 87 aa |
0xffffffff
| |
0xffffffff
| |
0x87654321
| |
0xffffffff
| |
0x00003eaa
| |
0x00000000
| |
0x12345678 | Aborted frame 78 56 34 12 21 43 65 87 aa |
0x87654321
| |
0xffffffff
| |
0x00003eaa
| |
0x00000001
| |
0xffffffff | Receiving junk |
0x00000000
| |
0x00000009
|
In general, you can handle received data word W
like this:
if (had_marker) { if (had_S1) { if (W & 3) { // discard data accumulated // handle status change if required } else { // append to remainder of frame from S1 data buffer // handle received frame } had_marker = 0; had_S1 = 0; } else if (W == 0xffffffff) { // append 0xffffffff to data buffer had_marker = 0; } else { S1 = W; // save until we get S2 had_S1 = 1; } } else if (W == 0xffffffff) { had_marker = 1; } else { // append W to data buffer }
Typically an application can ignore any status changes and the only processing done is when a valid frame arrives which passes the CRC check.
When finishing a transmission with kSMDCTxCtlFinish note that the transmitter can only finish while it is sending idle (continuous binary 1), which is arranged as described below. If the transmitter is sending flags, then the transmission will never finish.
When setting the capacity, it is necessary to specify a value one greater than the value required. i.e. to get notified when space is available for at least 32 bytes, set the capacity to 33 or greater.
The transmitter is controlled by a stream of 32-bit words. The stream can contain three different kinds of value. The values are distinguished by the first 32-bit word, which is encoded with the least significant byte first, like this:
data[0] = length & 0xff data[1] = (length >> 8) & 0xff data[2] = (length >> 16) & 0xff data[3] = (length >> 24) & 0xff
If a length is zero, this indicates that the transmitter should send idle (continuous binary 1) from this point until more data becomes available. This permits a modulator to turn off its carrier at this point if a request to turn off the carrier is pending. When more data is supplied, the transmitter sends a flag, the frame data, and reverts to filling with flags.
If a length is a negative value, -N
, this
causes the transmitter to send N
flags. Note that
these are additional flags, so a data stream of <frameA>,
-5
, <frameB> will have six flags between
frames A and B because this is five in addition to the one which
would have been sent anyway.
If a length is a positive value, N
, this
causes a frame of N
bits to be sent. Subsequent
32-bit words contain the data to be sent. The bits in these
words are sent least significant bit first. If the number of
bits to be transmitted is not a multiple of 32, the remaining
bits in the last word are ignored. The appropriate CRC is
automatically calculated and appended to the frame. At least one
flag is sent between frames. If data is not supplied fast
enough, the transmitter aborts the frame, discards the
remainder and reports an underrun.
The transmitter sends flags as necessary between frames if data is not supplied fast enough to start a new frame immediately after the previous one.