Please can anyone help with some nice Delphi code that will calculate the X.25 Frame Check Sequence?

I am trying to receive and send X.25 packets from Windows 2000 via an ISDN line, without a PAD. I am trying to create the X.25 packets myself. I can get the SABM and DISC packets into a memo box, using APRO component TApdcom. However, next I need to send a UA (unnumbered acknowledgement), and an RR (ready to receive), and one day hopefully, a Call Request, and later, some data.

To do this, I need to calculate the 16-bit checksum to put into the outgoing X.25 packet. I have followed various web links and tried various available programs to (a) construct a table (b) use the table with complex XOR instructions that I don't really understand, but have slavishly copied. I can't get the same answers as the incoming SABM and DISC packets.

I should really appreciate any clues, pointers, and best of all some really nice working code!

I am trying to receive and send X.25 packets from Windows 2000 via an ISDN line, without a PAD. I am trying to create the X.25 packets myself. I can get the SABM and DISC packets into a memo box, using APRO component TApdcom. However, next I need to send a UA (unnumbered acknowledgement), and an RR (ready to receive), and one day hopefully, a Call Request, and later, some data.

To do this, I need to calculate the 16-bit checksum to put into the outgoing X.25 packet. I have followed various web links and tried various available programs to (a) construct a table (b) use the table with complex XOR instructions that I don't really understand, but have slavishly copied. I can't get the same answers as the incoming SABM and DISC packets.

I should really appreciate any clues, pointers, and best of all some really nice working code!

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.

http://www.delphi-jedi.org/Jedi:CODELIBJCL:25500

//========================

// CRC

//========================

const

CRCPolynom = $04C11DB7;

Crc32Table: array [0..255] of Cardinal = (

$00000000, $04C11DB7, $09823B6E, $0D4326D9, $130476DC, $17C56B6B, $1A864DB2, $1E475005,

$2608EDB8, $22C9F00F, $2F8AD6D6, $2B4BCB61, $350C9B64, $31CD86D3, $3C8EA00A, $384FBDBD,

$4C11DB70, $48D0C6C7, $4593E01E, $4152FDA9, $5F15ADAC, $5BD4B01B, $569796C2, $52568B75,

$6A1936C8, $6ED82B7F, $639B0DA6, $675A1011, $791D4014, $7DDC5DA3, $709F7B7A, $745E66CD,

$9823B6E0, $9CE2AB57, $91A18D8E, $95609039, $8B27C03C, $8FE6DD8B, $82A5FB52, $8664E6E5,

$BE2B5B58, $BAEA46EF, $B7A96036, $B3687D81, $AD2F2D84, $A9EE3033, $A4AD16EA, $A06C0B5D,

$D4326D90, $D0F37027, $DDB056FE, $D9714B49, $C7361B4C, $C3F706FB, $CEB42022, $CA753D95,

$F23A8028, $F6FB9D9F, $FBB8BB46, $FF79A6F1, $E13EF6F4, $E5FFEB43, $E8BCCD9A, $EC7DD02D,

$34867077, $30476DC0, $3D044B19, $39C556AE, $278206AB, $23431B1C, $2E003DC5, $2AC12072,

$128E9DCF, $164F8078, $1B0CA6A1, $1FCDBB16, $018AEB13, $054BF6A4, $0808D07D, $0CC9CDCA,

$7897AB07, $7C56B6B0, $71159069, $75D48DDE, $6B93DDDB, $6F52C06C, $6211E6B5, $66D0FB02,

$5E9F46BF, $5A5E5B08, $571D7DD1, $53DC6066, $4D9B3063, $495A2DD4, $44190B0D, $40D816BA,

$ACA5C697, $A864DB20, $A527FDF9, $A1E6E04E, $BFA1B04B, $BB60ADFC, $B6238B25, $B2E29692,

$8AAD2B2F, $8E6C3698, $832F1041, $87EE0DF6, $99A95DF3, $9D684044, $902B669D, $94EA7B2A,

$E0B41DE7, $E4750050, $E9362689, $EDF73B3E, $F3B06B3B, $F771768C, $FA325055, $FEF34DE2,

$C6BCF05F, $C27DEDE8, $CF3ECB31, $CBFFD686, $D5B88683, $D1799B34, $DC3ABDED, $D8FBA05A,

$690CE0EE, $6DCDFD59, $608EDB80, $644FC637, $7A089632, $7EC98B85, $738AAD5C, $774BB0EB,

$4F040D56, $4BC510E1, $46863638, $42472B8F, $5C007B8A, $58C1663D, $558240E4, $51435D53,

$251D3B9E, $21DC2629, $2C9F00F0, $285E1D47, $36194D42, $32D850F5, $3F9B762C, $3B5A6B9B,

$0315D626, $07D4CB91, $0A97ED48, $0E56F0FF, $1011A0FA, $14D0BD4D, $19939B94, $1D528623,

$F12F560E, $F5EE4BB9, $F8AD6D60, $FC6C70D7, $E22B20D2, $E6EA3D65, $EBA91BBC, $EF68060B,

$D727BBB6, $D3E6A601, $DEA580D8, $DA649D6F, $C423CD6A, $C0E2D0DD, $CDA1F604, $C960EBB3,

$BD3E8D7E, $B9FF90C9, $B4BCB610, $B07DABA7, $AE3AFBA2, $AAFBE615, $A7B8C0CC, $A379DD7B,

$9B3660C6, $9FF77D71, $92B45BA8, $9675461F, $8832161A, $8CF30BAD, $81B02D74, $857130C3,

$5D8A9099, $594B8D2E, $5408ABF7, $50C9B640, $4E8EE645, $4A4FFBF2, $470CDD2B, $43CDC09C,

$7B827D21, $7F436096, $7200464F, $76C15BF8, $68860BFD, $6C47164A, $61043093, $65C52D24,

$119B4BE9, $155A565E, $18197087, $1CD86D30, $029F3D35, $065E2082, $0B1D065B, $0FDC1BEC,

$3793A651, $3352BBE6, $3E119D3F, $3AD08088, $2497D08D, $2056CD3A, $2D15EBE3, $29D4F654,

$C5A92679, $C1683BCE, $CC2B1D17, $C8EA00A0, $D6AD50A5, $D26C4D12, $DF2F6BCB, $DBEE767C,

$E3A1CBC1, $E760D676, $EA23F0AF, $EEE2ED18, $F0A5BD1D, $F464A0AA, $F9278673, $FDE69BC4,

$89B8FD09, $8D79E0BE, $803AC667, $84FBDBD0, $9ABC8BD5, $9E7D9662, $933EB0BB, $97FFAD0C,

$AFB010B1, $AB710D06, $A6322BDF, $A2F33668, $BCB4666D, $B8757BDA, $B5365D03, $B1F740B4

);

CrcStart = $FFFFFFFF;

CrcBytes = 4;

CrcHighBit = $80000000;

NotCrcHighBit = $7FFFFFFF;

//------------------------

function Crc32Corr(Crc: Cardinal; N: Integer): Integer;

var

I: Integer;

begin

// calculate Syndrome

for I := 1 to CrcBytes do

Crc := Crc32Table[Crc shr 24] xor (Crc shl 8);

I := -1;

repeat

Inc(I);

if (Crc and 1) <> 0 then

Crc := ((Crc xor CrcPolynom) shr 1) or CrcHighBit

else

Crc := (Crc shr 1) and NotCrcHighBit;

until (Crc = CrcHighBit) or (I = (N + CrcBytes) * 8);

if Crc <> CrcHighBit then

Result := -1000 // not correctable

else

// I = No. of single faulty bit

// (high bit first,

// starting from lowest with CRC bits)

Result := I - (CrcBytes * 8);

// Result < 0 faulty CRC-bit

// Result >= 0 No. of faulty data bit

end;

//------------------------

function Crc32_P(X: PByteArray; N: Integer; Crc: Cardinal = 0): Cardinal;

var

I: Integer;

begin

Result := CrcStart;

for I := 0 to N - 1 do // The CRC Bytes are located at the end of the information

begin

// a 32 bit value shr 24 is a Byte, explictit type conversion to Byte adds an ASM instruction

Result := Crc32Table[Result shr 24] xor (Result shl 8) xor X[I];

end;

for i := 0 to CrcBytes - 1 do

begin

// a 32 bit value shr 24 is a Byte, explictit type conversion to Byte adds an ASM instruction

Result := Crc32Table[Result shr 24] xor (Result shl 8) xor (Crc shr 24);

Crc := Crc shl 8;

end;

end;

//------------------------

function CheckCrc32_P(X: PByteArray; N: Integer; Crc: Cardinal): Integer;

var

I, J: Integer;

C: Byte;

begin

Crc := Crc32_P(X, N, Crc);

if Crc = 0 then

Result := 0 // No CRC-error

else

begin

J := Crc32Corr(Crc, N);

if J < -(CrcBytes * 8 + 1) then

Result := -1 // non-correctable error (more than one wrong bit)

else

begin

if J < 0 then

Result := 1 // one faulty Bit in CRC itself

else

begin // Bit j is faulty

I := J and 7; // I <= 7 (faulty Bit in Byte)

C := 1 shl I; // C <= 128

I := J shr 3; // I: Index of faulty Byte

X[N - 1 - I] := X[N - 1 - I] xor C; // correct faulty bit

Result := 1; // Correctable error

end;

end;

end;

end;

//------------------------

function Crc32(const X: array of Byte; N: Integer; Crc: Cardinal = 0): Cardinal;

begin

Result := Crc32_P(@X, N, Crc);

end;

//------------------------

function CheckCrc32(var X: array of Byte; N: Integer; Crc: Cardinal): Integer;

begin

Result := CheckCRC32_P(@X, N, CRC);

end;

//------------------------

function Crc32_A(const X: array of Byte; Crc: Cardinal = 0): Cardinal;

begin

Result := Crc32_P(@X, Length(X), Crc);

end;

//------------------------

function CheckCrc32_A(var X: array of Byte; Crc: Cardinal): Integer;

begin

Result := CheckCrc32_P(@X, Length(X), Crc);

end;