CRC計算

符号の乗算が排他的論理和なのは信号処理屋にとっては言ふも更なりだし、ちょっと考えれば当たり前なんだけど、まぁ一見さんは戸惑うかもね。

/**
 * CRCを計算する(バッファされたデータを一気に計算)
 *
 * CRC-16-CCITT計算
 * 生成多項式=x^16+x^12+x^5+1 (除数=0x1021,左送り)
 *
 * @param data データの先頭へのポインタ
 * @param length データの長さ(バイト数)
 * @return CRC値(16ビット)
 */
unsigned short CRC_calc(unsigned char *data, int length)
{
    unsigned short crc16;
    int i,j;
    
    crc16 = 0xFFFF;
    for(i=0;i<length;i++){
        crc16 ^= ( ((unsigned short)data[i]) << 8);
        for(j=0;j<8;j++){
            if(crc16 & 0x8000){
                crc16 = (crc16 << 1) ^ 0x1021; // 生成多項式
            }else{
                crc16 <<= 1;
            }
        }
    }
    return crc16;
}

/** ストリームを1バイトずつCRC計算するための静的変数 */
static unsigned short g_crc16;

/**
 * 1バイトずつCRC計算の初期化
 */
void CRC_init(void)
{
    g_crc16 = 0xFFFF;
}

/**
 * 1バイトずつCRC計算する
 * 
 * CRC-16-CCITT計算
 * 生成多項式=x^16+x^12+x^5+1 (除数=0x1021,左送り)
 * 
 * @param data データ
 */
void CRC_put(unsigned char data)
{
    int j;
    
    g_crc16 ^= ( ((unsigned short)data) << 8);
    for(j=0;j<8;j++){
        if(g_crc16 & 0x8000){
            g_crc16 = (g_crc16 << 1) ^ 0x1021; // 生成多項式
        }else{
            g_crc16 <<= 1;
        }
    }
}

/**
 * 1バイトずつCRC計算した結果を取得する
 *
 * @return CRC値(16ビット)
 */
unsigned short CRC_get(void)
{
    return g_crc16;
}