实现 CRC 算法

Implementing a CRC algorithm

我正在尝试实现某些视频接口标准中定义的 CRC 算法:

原始数据是 10 位字,被压缩成 8 位字节,我在 numpy 中提取和使用没有问题。

CRC 有多项式:

CRC(X) = X^18 + X^5 + X^4 + 1

我相信这给了我常数:

POLY = 0x40031

我已经尝试了几种不同的实现方式,但我生成的任何东西都与我的示例数据不匹配。 此实现的灵感来自 this

MASK = 0x3FFFF
class MYCRC:
    crc_table = []
    def __init__(self):
        if not self.crc_table:
            for i in range(1024):
                k = i
                for j in range(10):
                    if k & 1:
                        k ^= POLY
                    k >>= 1
                self.crc_table.append(k)

    def calc(self, crc, data):
        crc ^= MASK
        for d in data:
            crc = (crc >> 10) ^ self.crc_table[(crc & 0x3FF) ^ d]
        return crc ^ MASK

然后是我从某个地方(不确定在哪里)提取的这个实现

def crc_calc(crc, p):
    crc = MASK & ~crc
    for i in range(len(p)):
        crc = (crc ^ p[i]) # & BIG_MASK
        for j in range(10):
            crc = ((crc >> 1) ^ (POLY & -(crc & 1))) # & BIG_MASK
    return MASK & ~crc

我还查看了使用 this library,它支持使用自定义多项式,但它似乎是为使用 8 位数据而构建的,而不是我拥有的 10 位数据。

我不确定如何最好地共享测试数据,因为我只有整个帧,如果导出为 numpy 文件大约 5MB。 我也不清楚我应该提供给 CRC 计算的数据范围。我认为从阅读它来看,它应该是从一行中的第一个活动样本开始,直到之后的行的行数,然后是在该范围内计算的校验和。从硬件的角度来看,这是最有意义的,但标准对我来说并不清楚。

编辑: pastebin 的 10 行测试数据,这包括嵌入式校验和。 在一行数据中,样本 0-7 是 EAV 标记,8-11 是行号,12-16 是两个校验和。数据是两个交错的视频数据流(亮度通道和 CbCr 通道)。 标准规定校验和是 运行 从第一个活动样本到行数据的末尾,我将其解释为从一行的样本 740 到下一行的样本 11 运行s .

根据 SMPTE292M 的第 5 节,数据是 10 位数据,不能低于 0x3 或高于 0x3FC。根据 table 4,CRC 的结果应该是 18 位,它被拆分并作为两个字嵌入到流中(其中一位填充另一位的非)请注意,每个通道都有一个校验和的数据,这两个校验和在每行 12-16

编辑 2 some longer test data 跨越从消隐数据到活动帧数据的跳跃

必须反映CRC计算。 (提示 Table 9 中的注释:“注意 – CRC0 是错误检测代码的 MSB。”)

此 C 例程正确检查示例中的 CRC:

// Update the CRC-18 crc with the low ten bits of word.
// Polynomial = 1000000000000110001
// Reflected (dropping x^18) = 10 0011 0000 0000 0000 = 0x23000
unsigned crc18(unsigned crc, unsigned word) {
    crc ^= word & 0x3ff;
    for (int k = 0; k < 10; k++)
        crc = crc & 1 ? (crc >> 1) ^ 0x23000 : crc >> 1;
    return crc;
}

确实,检查的范围是从活动行的开始到行号,一直到流中的两个 CRC 之前。该计算与这两个 CRC 匹配。每个 CRC 都是根据流中的交替字来计算的。 CRC 初始化为零。