Search code examples
delphipascallazaruscrc

Calculate CRC-6 GSM using lookup table


I am trying to calculate CRC-6 GSM but the result is wrong ($16). For '123456789' it should return $13 according to https://reveng.sourceforge.io/crc-catalogue/all.htm#crc.cat.crc-6-gsm

var Table: array[0..255] of Byte = (
$3F, $10, $0E, $21, $32, $1D, $03, $2C, 
$25, $0A, $14, $3B, $28, $07, $19, $36, 
$0B, $24, $3A, $15, $06, $29, $37, $18, 
$11, $3E, $20, $0F, $1C, $33, $2D, $02, 
$38, $17, $09, $26, $35, $1A, $04, $2B, 
$22, $0D, $13, $3C, $2F, $00, $1E, $31, 
$0C, $23, $3D, $12, $01, $2E, $30, $1F, 
$16, $39, $27, $08, $1B, $34, $2A, $05, 
$31, $1E, $00, $2F, $3C, $13, $0D, $22, 
$2B, $04, $1A, $35, $26, $09, $17, $38, 
$05, $2A, $34, $1B, $08, $27, $39, $16, 
$1F, $30, $2E, $01, $12, $3D, $23, $0C, 
$36, $19, $07, $28, $3B, $14, $0A, $25, 
$2C, $03, $1D, $32, $21, $0E, $10, $3F, 
$02, $2D, $33, $1C, $0F, $20, $3E, $11, 
$18, $37, $29, $06, $15, $3A, $24, $0B, 
$23, $0C, $12, $3D, $2E, $01, $1F, $30, 
$39, $16, $08, $27, $34, $1B, $05, $2A, 
$17, $38, $26, $09, $1A, $35, $2B, $04, 
$0D, $22, $3C, $13, $00, $2F, $31, $1E, 
$24, $0B, $15, $3A, $29, $06, $18, $37, 
$3E, $11, $0F, $20, $33, $1C, $02, $2D, 
$10, $3F, $21, $0E, $1D, $32, $2C, $03, 
$0A, $25, $3B, $14, $07, $28, $36, $19, 
$2D, $02, $1C, $33, $20, $0F, $11, $3E, 
$37, $18, $06, $29, $3A, $15, $0B, $24, 
$19, $36, $28, $07, $14, $3B, $25, $0A, 
$03, $2C, $32, $1D, $0E, $21, $3F, $10, 
$2A, $05, $1B, $34, $27, $08, $16, $39, 
$30, $1F, $01, $2E, $3D, $12, $0C, $23, 
$1E, $31, $2F, $00, $13, $3C, $22, $0D, 
$04, $2B, $35, $1A, $09, $26, $38, $17
);

function GSM_Update(Msg: PByte; Length: Integer): Byte;
var i: Integer;
    H: Byte;
begin
  H :=  $00;

  for i:=0 to Length-1 do begin

    H := Table[H xor Msg^];  //I believe this line might be wrong but don't know how to change it
    Inc(Msg);
  end;

  Result := H xor $3F;
end;

Invoking is quite simple:

var Msg: AnsiString;
...
GSM_Update(@Msg[1], Length(Msg));

or

var Msg: array of AnsiChar;
Len: Integer;
...
SetLength(Msg, Len); 
GSM_Update(@Msg[0], Len);

Solution

  • I'm not certain about the Pascal operators and syntax, but for the table in your code, that line needs to be:

        H := (not Table[(H shl 2) xor Msg^]) and $3F;
    

    This could be simplified and sped up by using a more appropriate table. I would replace each byte in the table by its one's complement shifted left by two bits. I.e. $00, $bc, $c4, $78, ... Then that line would be what you currently have:

        H := Table[H xor Msg^];
    

    and the last line would need to be changed to:

      Result := (H shr 2) xor $3F;