各バイトのビットを MSB から LSB まで処理するように定義された CRC もあれば、LSB から MSB までビットを処理するように定義された CRC もあります (後者は一般に、「反射」と呼ばれ、逆多項式を使用する順序です)。コードは、CRC の LSB エンドに新しいビットを配置し、右にシフトします。これは反映された CRC に適していますが、CRC-16-DECT は反映されていないものの 1 つに見えます。
「10100011」の入力はバイナリを示唆していますが、8 バイトの ASCII 文字列として処理されています。
代わりに 10100011 を 2 進数として扱い、MSB から処理するとどうなるかを確認するために、次の手計算を行います (入力の 8 ビットはそれほど労力を必要としないため)。
polynomial coefficients
|
| 10100010 <--- quotient (irrelevant)
v __________
10000010110001001 ) 10100011 <-------- input
^ 10000010110001001
-----------------
= 100001110001001
^ 10000010110001001
-----------------
= 101110101101
^ 10000010110001001
-----------------
remainder (CRC) -----> = 111000000101001
= 0x7029 = 28713
したがって、入力をバイナリとして扱い、MSB を最初に動作させるのが正しいことです。
これは、仕事をするためのCコードです(私はPHPにあまり興味がなく、最終的にはCコードが必要なので):
#include <stdio.h>
#include <stdint.h>
static uint16_t crc16(const uint8_t *data, size_t len)
{
size_t i, j;
uint16_t crc = 0;
for (i = 0; i < len; i++) {
crc ^= (data[i] << 8); /* data at top end, not bottom */
for (j = 0; j < 8; j++) {
if ((crc & 0x8000) == 0x8000) /* top bit, not bottom */
crc = (crc << 1) ^ 0x0589; /* shift left, not right */
else
crc <<= 1; /* shift left, not right */
}
}
return crc;
}
int main(void)
{
const uint8_t in[] = { 0xa3 }; /* = 10100011 in binary */
uint16_t crc = crc16(in, sizeof(in));
printf("%u (0x%x)\n", crc, crc);
return 0;
}
結果:
$ gcc -Wall -o crc16 crc16.c
$ ./crc16
28713 (0x7029)
$