2

我研究有关 CDROM 原则的信息。在标准http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-130.pdf 在第 35 页(pdf 中的 45)我看到 CIRC 编码器。并且他的有Q码和P码,都是用reed-solomon算法计算出来的。我尝试确认这一点并做一些示例音轨(音轨未使用扰码器作为数据轨道)一个填充 0x01 模式,一个填充 0xA5(数据包中的 CIRC 间隔字节不是位,我在 F3 帧中看到 Q 和 P) . 在我用逻辑分析仪从 CD(直接从激光输出)中读取这个扇区后,并通过脚本解密。我有这个数据用于跟踪模式 0x01

S1 01 01 01 01 01 01 01 01 01 01 01 01 e5 6e 4e c5 01 01 01 01 01 01 01 01 01 01 01 01 ff ff ff ff

S2 01 01 01 01 01 01 01 01 01 01 01 01 e5 6e 4e c5 01 01 01 01 01 01 01 01 01 01 01 01 ff ff ff ff

第一个字节是此示例 SYNC_1 和 SYNC_2 中的子代码 sumbol

对于模式为 0xA5 的轨道

S1 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 6b bc a5 72 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 ff ff ff ff

S1 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 6b bc a5 72 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 ff ff ff ff

如果在 CIRC 上看到 12-15 字节它的倒置 Q 奇偶校验和 28-32 P 奇偶校验(第一个字节它的 sybcode 他在 F3 处添加)。

但我找不到计算这个字节的算法,我的数学技能很差。我尝试了 cdrecord 的计算器,他的 doit 另一个代码,尝试了另一个 Reed-Solomon emplemetation,但我无法从这个示例中获得相同的代码。我可以在哪里得到这个代码的工作实现。

4

1 回答 1

3

我正在根据 edc_ecc.c web github 文件将我在这个答案中找到的内容作为我取得的进展。RSL12 是 GF(2^8),多项式 x^8 + x^4 + x^3 + x^2 + 1 => 十六进制 11d。字段中的所有非零数字都可以视为 hex 02 的幂。

十六进制的 P 生成多项式是:

(x+01)(x+02)(x+04)(x+08) = 01 x^4 + 0f x^3 + 36 x^2 + 78 x + 40

如果您查看 AP[...][31] 的 4 个条目,您会看到值 75、249、78、6,这些是十六进制 0f、36、78、40 的十进制日志。请注意,AP 应该是AP[4][28](不是 [4][32]),修复如下所示。

根据您(现已删除)的评论,我在您在原始问题中给出的示例中“未反转”Q,并使用我自己的 RS 演示程序计算 P 奇偶校验,我现在得到 00 00 00 00:

01 01 01 01 01 01 01 01 01 01 01 01 1a 91 b1 3a 01 01 01 01 01 01 01 01 01 01 01 01 00 00 00 00
a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 94 43 5a 8d a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 00 00 00 00

Q 生成多项式与 P 生成多项式相同。它用于 RS(28,24),但奇偶校验字节位于中间,因此需要修改常规编码,如下所述。

AQ[][] 是错误的,使用 AQ[3][] 得到 Q[3],我得到 69 而不是 3a:

01 01 01 01 01 01 01 01 01 01 01 01 -- -- -- 69 01 01 01 01 01 01 01 01 01 01 01 01

另外,AQ[0] 只定义了 21 个字节,AQ[1] 只定义了 22 个字节,AQ[2] 只定义了 23 个字节,AQ[3] 定义了 24 个字节,但它们显然是错误的。

有一种解决方法,使用 4 擦除解码,将位置 12 到 15 标记为擦除(xx xx xx xx)进行 Q 编码:

01 01 01 01 01 01 01 01 01 01 01 01 xx xx xx xx 01 01 01 01 01 01 01 01 01 01 01 01
a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 xx xx xx xx a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5

经过 4 次擦除校正后,对 Q 奇偶校验字节进行编码:

01 01 01 01 01 01 01 01 01 01 01 01 1a 91 b1 3a 01 01 01 01 01 01 01 01 01 01 01 01
a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 94 43 5a 8d a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5

使用4纠删码方法,我生成了一个固定的AQ[][]:

static const unsigned char AQ[4][24] =
  {{58,152,173,95,88,43,134,205,143,131,163,75,249,66,151,116,125,184,110,16,58,62,137,113},
   {30,214,148,138,112,154,157,96,49,198,189,249,69,47,147,235,156,47,209,183,138,232,205,120},
   {162,244,13,171,213,236,71,177,253,162,59,78,243,180,186,34,78,136,130,85,108,115,178,246},
   {158,179,101,94,49,140,211,149,137,169,81,6,72,157,122,131,190,116,22,64,68,143,119,22}};

但是,如果您打算编写一个解码器(修复擦除和/或错误),那么您可以使用与我使用 4 擦除解码而不是进行编码相同的方法。如果我没记错的话,这就是一些早期的 DAT(数字音频磁带)驱动器实现这一点的方式,因为它们在数据中间也有奇偶校验字节。


AP 应该是 AP[4][28]。P 是 RS(32,28),28 字节的数据用于生成 4 字节的奇偶校验。应删除 AP[...][32] 每一行的前 4 个值,因此它变为 AP[4][28],并且 encode_L1_P() 应编码 28 个字节的数据(如所述的单行修复以下)。

static const unsigned char AP[4][28] =
  {{249,142,180,197,5,155,153,132,143,244,101,76,102,155,203,104,58,152,173,95,88,43,134,205,143,131,163,75},
   {205,252,218,199,202,41,136,106,119,238,193,103,123,242,83,178,30,214,148,138,112,154,157,96,49,198,189,249},
   {67,11,131,40,7,41,80,147,151,17,245,253,208,66,228,116,162,244,13,171,213,236,71,177,253,162,59,78},
   {148,186,203,11,161,159,138,149,250,107,82,108,161,209,110,64,158,179,101,94,49,140,211,149,137,169,81,6}};

encode_L1_P() 需要固定一行:

static int
encode_L1_P(inout)
    unsigned char inout[L1_RAW + L1_Q + L1_P];
{
    unsigned char *P;
    int i;

    P = inout + L1_RAW + L1_Q;

    memset(P, 0, L1_P);
    for (i = 0; i < L1_RAW + L1_Q; i++) {   /* fix (remove + L1_P) */
        unsigned char data;

        data = inout[i];
        if (data != 0) {
            unsigned char base = rs_l12_log[data];

            P[0] ^= rs_l12_alog[(base+AP[0][i]) % (unsigned)((1 << RS_L12_BITS)-1)];
            P[1] ^= rs_l12_alog[(base+AP[1][i]) % (unsigned)((1 << RS_L12_BITS)-1)];
            P[2] ^= rs_l12_alog[(base+AP[2][i]) % (unsigned)((1 << RS_L12_BITS)-1)];
            P[3] ^= rs_l12_alog[(base+AP[3][i]) % (unsigned)((1 << RS_L12_BITS)-1)];
        }
    }
    return (0);
}

回应评论。为了生成 AQ,我使用擦除校正来生成 24 组奇偶校验:

01 00 00 00 00 00 00 00 00 00 00 00 69 60 bf b7 00 00 00 00 00 00 00 00 00 00 00 00
00 01 00 00 00 00 00 00 00 00 00 00 49 f9 fa 4b 00 00 00 00 00 00 00 00 00 00 00 00
...
00 00 00 00 00 00 00 00 00 00 00 00 9e a7 ab 93 00 00 00 00 00 00 00 00 00 00 01 00
00 00 00 00 00 00 00 00 00 00 00 00 1f 3b cf ea 00 00 00 00 00 00 00 00 00 00 00 01

AQ[][ 0] = hex log2{69 60 bf b7} = decimal {058 030 162 158}
AQ[][ 1] = hex log2{49 f9 fa 4b} = decimal {152 214 244 179}
...
AQ[][22] = hex log2{9e a7 ab 93} = decimal {137 205 178 119}
AQ[][23] = hex log2{1f 3b cf ea} = decimal {113 120 246 022}

另一种方法是使用全长 255 字节码字全为零,除了在适当位置模 255 处设置为 01 的一个字节,以标准方式生成奇偶校验,奇偶校验 = msg * x^4 % 生成器。这会生成超出其目标位置 16 个字节的奇偶校验,因此偏移量需要调整 255-16 = +239 模 255 以产生目标奇偶校验:

255_byte_message_offset = 28_byte_message_offset + 239 % 255:

msg[239] = 01 => parities = 69 60 bf b7
msg[240] = 01 => parities = 49 f9 fa 4b
...
msg[010] = 01 => parities = 9e a7 ab 93
msg[011] = 01 => parities = 1f 3b cf ea
于 2019-01-18T11:02:10.390 回答