Prosody data communications Encodings: HDLC

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.

API function behaviour

This should be read in conjunction with the generic data communications documentation.

smdc_channel_config()

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.

smdc_rx_data()

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:

S2Meaning
...0000Frame with correct CRC
...0010Frame with bad CRC
...00x1Aborted frame
...0101Receiving flags
...1001Receiving junk
...1111Receiving 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 valuesInterpretation
0xffffffffReceiving flags
0x00000000
0x00000005
0x12345678Valid frame 78 56 34 12 ff ff ff ff 21 43 65 87 aa
0xffffffff
0xffffffff
0x87654321
0xffffffff
0x00003eaa
0x00000000
0x12345678Aborted frame 78 56 34 12 21 43 65 87 aa
0x87654321
0xffffffff
0x00003eaa
0x00000001
0xffffffffReceiving 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.

smdc_tx_control()

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.

smdc_tx_data()

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.