Calculating FCS(CRC) for HDLC frame

Baz picture Baz · Nov 2, 2011 · Viewed 18.6k times · Source

I have the following frame:

7e  01 00  00  01  00  18  ef  00  00  00   b5   20 c1 05 10 02 71 2e 1a c2 05 10 01 71 00 6e 87 02 00 01 42 71 2e 1a 01 96 27 be 27 54 17 3d b9 93 ac 7e

If I understand correctly, then it is this portion of the frame on which the FCS is calculated:

010000010018ef000000b520c1051002712e1ac205100171006e8702000142712e1a019627be2754173db9

I've tried entering this into a number of online calculators but I cant produce 0x93ac from the above data.

http://www.lammertbies.nl/comm/info/crc-calculation.html with input type hex.

How is 0x93ac arrived at?

Thanks,

Barry

Answer

Pavel picture Pavel · Sep 3, 2015

Answering rather for others who got here while searching for advice.

The key is what several points in the closely related ITU-T recommendations (e.g. Q.921, available online for quite some time already) say:

1. the lowest order bit is transmitted (and thus received) first

This legacy behaviour is in contrary to the daily life conventions where highest order digits are written first in the order of reading, and all the generic online calculators and libraries perform the calculation using the conventional order and provide optional settings to facilitate the reversed one. Therefore, you must ask the online calculator

  • to reverse the order of bits in the message you've input in the "conventional" format before performing the calculation,
  • to reverse the order of bits of the result so that you get them in the same order like in the message itself

Quite reasonably, some calculators offer just a single common setting for both.

This reasons the settings "reverse data bytes" and "reverse CRC result before Final XOR" recommended in the previous answer;

2. the result of the CRC calculation must be bit-inverted before sending

Bit inversion is another name of "xor by 0xffff...". There is a purpose in bit-inverting the CRC calculation result before sending it as the message FCS (the last two bytes of the message, the '93 ac' in your example). See point 4 for details.

This reasons the setting "Final value ffff", whose name is quite misleading as it actually defines the pattern to be for xor'ed with the result of the calculation. As such operation is required by several CRC types, only the xor patterns vary from 0 (no op) through 0xfff... (complete inversion), generic calculators/libraries offer it for simplicity of use.

3. the calculation must include processing of a leading sequence of 0xffff

This reasons the point "initial value ffff".

4. on the receiving (checking) side, it is recommended to push the complete message, i.e. including the FCS, through the CRC calculation, and expect the result to be 0x1d0f

There is some clever thinking behind this:

  • the intrinsic property of the CRC algorithm is that

    CRC( x.CRC(x) )

    is always 0 (x represents the original message and "." represents concatenation).

  • running the complete message through the calculation rather than calculating only the message itself and comparing with the FCS received separately means much simpler algorithm (or even circuitry) at the receiving side.

  • however, it is too easy to make a coding mistake causing a result to become 0. Luckily, thanks to the CRC algorithm intrinsic properties again,

    CRC( x.(CRC(x))' )

    yields a constant value independent of x and different from 0 (at least for CRC-CCITT, which we talk about here). The "'" sign represents the bit inversion as required in point 2.