2014年9月3日水曜日

CRC-16-CCITT をテーブルを使わないで計算するソースコード

ついでに、テーブルを使わないでCRCを計算する関数も作成しました。どうしても使用するプログラムメモリを削減したい場合向け。

テーブルを使って高速に計算する関数はこちら

/*
CRC-16-CCITT を計算する
// wikipediaにある実装例の通り(wikipediaの例は多項式が反転、シフトの向きが右)
// http://ja.wikipedia.org/wiki/%E5%B7%A1%E5%9B%9E%E5%86%97%E9%95%B7%E6%A4%9C%E6%9F%BB

MB8877のデータシートに
X^0+X^5+X^12+X^16 と書いてあったので、フロッピーのCRCは CRC-16-CCITT

2014年9月2日作成
*/


unsigned short crc_1byte(unsigned char in, unsigned short crc)
{
/* 1byteづつCRCを計算する
wikipediaにある実装例を、テーブルを使わないように書き換えただけ。

unsigned short crc;
crc = 0xffff; // 初期値
crc = crc_1byte(0xA1, crc);
crc = crc_1byte(0xA1, crc);
crc = crc_1byte(0xA1, crc);
crc = crc_1byte(0xFE, crc); // A1 A1 A1 FE : ID ADDRESS MARK
crc = crc_1byte(0x02, crc); // C
crc = crc_1byte(0x00, crc); // H
crc = crc_1byte(0x03, crc); // R
crc = crc_1byte(0x02, crc); // N

これで crc に計算結果が入る (0x4165)
*/

#define polynomial 0x1021 // 多項式 CRC-16-CCITT X^16+X^12+X^5+X^0 (1 0001 0000 0010 0001)
// 0x8005 //        CRC-16-IBM X^16+X^15+X^2+X^0 (1 1000 0000 0000 0101)
unsigned char bit;
unsigned short a;

a = ((in << 8) ^ crc) & 0xFF00;
for (bit = 8; bit != 0; bit--)
{
if (0 == (a & 0x8000)) a = (a << 1); // 最上位ビットが0ならシフトのみ
else a = polynomial ^ (a << 1); // 最上位ビットが1ならシフトして多項式でXOR
}
crc = a ^ (crc << 8);

return crc;
}

unsigned short crc_block(unsigned char buff[], unsigned short size, unsigned crc)
{
/*
ブロックのCRCを計算する

unsigned short crc;
unsigned char buff[]=
{
0xA1,0xA1,0xA1,0xFE // ID ADDRESS MARK
,0x02 // C
,0x00 // H
,0x03 // R
,0x02 // N
,0x41 // CRC H
,0x65 // CRC L
};
crc = crc_block(buff, 8, 0xFFFF);
これで crc に IDAM から N までの計算結果が入る (0x4165)

crc = crc_block(buff,10, 0xFFFF);
CRCを含めて計算すると、CRCが正しければ計算結果がゼロになる
*/

unsigned short pos;

for(pos=0; pos!=size; pos++)
{
crc = crc_1byte(buff[pos], crc);
}

return crc;
}