Я хочу создать таблицу для CRC-6/CDMA2000-A. Я пытался использовать различные CRC-8, и приведенный ниже алгоритм работает нормально, но для CRC-6 я получаю массивы, которые у меня не работают. Либо массив неправильный, либо функция, которую я использую для вычисления CRC-6 с массивом.
const POLYNOMIAL = $27;
BitsCRC = 6;
var Table: array[0..255] of Byte;
i: Integer;
j: Integer;
temp: Byte;
S: String;
Mask: Byte;
begin
mask := (1 shl (BitsCRC - 1));
for i:=0 to 255 do Table[i] := i ;
for i:=0 to 255 do begin
for j:=7 downto 0 do begin
temp := Table[i] and Mask;
if (temp <> 0) then begin
Table[i] := Table[i] shl 1;
Table[i] := Table[i] xor POLYNOMIAL;
end
else begin
Table[i] := Table[i] shl 1;
end;
end;
end;
S := '';
for i:=0 to 255 do begin
S := S + '$' + IntToHex(Table[i], 2) +', ';
if i mod 16 = 15 then begin
Memo1.Lines.Add(s);
S := '';
end;
end;
Я получаю этот массив из кода выше:
$00, $F5, $CD, $38, $9A, $6F, $57, $A2, $34, $C1, $F9, $0C, $AE, $5B, $63, $96,
$4F, $BA, $82, $77, $D5, $20, $18, $ED, $7B, $8E, $B6, $43, $E1, $14, $2C, $D9,
$9E, $6B, $53, $A6, $04, $F1, $C9, $3C, $AA, $5F, $67, $92, $30, $C5, $FD, $08,
$D1, $24, $1C, $E9, $4B, $BE, $86, $73, $E5, $10, $28, $DD, $7F, $8A, $B2, $47,
$00, $F5, $CD, $38, $9A, $6F, $57, $A2, $34, $C1, $F9, $0C, $AE, $5B, $63, $96,
$4F, $BA, $82, $77, $D5, $20, $18, $ED, $7B, $8E, $B6, $43, $E1, $14, $2C, $D9,
$9E, $6B, $53, $A6, $04, $F1, $C9, $3C, $AA, $5F, $67, $92, $30, $C5, $FD, $08,
$D1, $24, $1C, $E9, $4B, $BE, $86, $73, $E5, $10, $28, $DD, $7F, $8A, $B2, $47,
$00, $F5, $CD, $38, $9A, $6F, $57, $A2, $34, $C1, $F9, $0C, $AE, $5B, $63, $96,
$4F, $BA, $82, $77, $D5, $20, $18, $ED, $7B, $8E, $B6, $43, $E1, $14, $2C, $D9,
$9E, $6B, $53, $A6, $04, $F1, $C9, $3C, $AA, $5F, $67, $92, $30, $C5, $FD, $08,
$D1, $24, $1C, $E9, $4B, $BE, $86, $73, $E5, $10, $28, $DD, $7F, $8A, $B2, $47,
$00, $F5, $CD, $38, $9A, $6F, $57, $A2, $34, $C1, $F9, $0C, $AE, $5B, $63, $96,
$4F, $BA, $82, $77, $D5, $20, $18, $ED, $7B, $8E, $B6, $43, $E1, $14, $2C, $D9,
$9E, $6B, $53, $A6, $04, $F1, $C9, $3C, $AA, $5F, $67, $92, $30, $C5, $FD, $08,
$D1, $24, $1C, $E9, $4B, $BE, $86, $73, $E5, $10, $28, $DD, $7F, $8A, $B2, $47
Я пытаюсь сгенерировать CRC-6 следующим образом:
procedure crc6_update(var CRC: Byte; Str: String);
var i: Integer;
begin
for i:=1 to Length(Str) do
CRC := CRC_Table[(CRC shl 2) xor ord(Str[i]) ] ;
end;
CRC := $3f;
crc6_update(CRC, '123456789');
Caption := IntToHex(CRC, 2);
Есть несколько проблем. Вы перемещаете мусор в два верхних бита записей таблицы, но затем не избавляетесь от них с помощью and
. Что еще более важно, вы игнорируете два верхних бита, биты 6 и 7, каждой начальной записи таблицы (i
) с вашей маской, которая смотрит на бит 5.
Чтобы сделать это правильно, вам нужно вычислить CRC в шести старших битах обрабатываемого байта (i
). Вы маскируете бит 7 вместо бита 5 и сдвигаете полином на два бита вверх, чтобы соответствовать этому. Если вы делаете это в байте, то это позаботится о смещении мусора вверх, поскольку он падает с вершины байта.
Вы хотите:
Mask := 1 shl 7;
и:
Table[i] := Table[i] xor (POLYNOMIAL shl 2);
Теперь CRC в вашей таблице на самом деле там, где вы хотели бы, чтобы они были в любом случае, то есть в шести старших битах каждого байта. Тогда вам не нужно делать CRC shl 2
для каждого вычисляемого байта. Вместо этого эта строка в вашем расчете становится:
CRC := CRC_Table[CRC xor ord(Str[i])];
Затем после вашего цикла вам нужно сдвинуть CRC вниз на два, чтобы вернуть CRC в младших шести битах:
CRC := CRC shr 2;
и начальное значение нужно сдвинуть вверх на два:
CRC := $fc;
Это даст правильный ответ для этого тестового вектора, который равен $0D
.
Я не понимаю, почему у вас есть три цикла с массивом для генерации вашей таблицы. Кажется, было бы проще сделать так, с одним циклом и без массива (не тестировалось - я не знаю Pascal/Delphi):
var
i: Integer;
j: Integer;
crc: Byte;
S: String;
begin
S := '';
for i := 0 to 255 do begin
crc := i;
for j := 0 to 7 do
if ((crc and $80) <> 0) then
crc := (crc shl 1) xor $9c
else
crc := crc shl 1;
S := S + '$' + IntToHex(crc, 2) + ', ';
if i mod 16 = 15 then begin
Memo1.Lines.Add(S);
S := '';
end;
end;
end.
Я забыл упомянуть, что начальное значение также нужно сдвинуть вверх на два. Я добавил это к ответу. CRC := $fc;
.
У меня проблема с кодом - он дает мне 33 доллара, а не 0 долларов. Я даже перевела на C, так что, возможно, вам будет проще: pastebin.com/YHwMFQL5