CDROM, F2 коды Рида-Соломона P Q в CIRC-кодере - PullRequest
0 голосов
/ 16 января 2019

Я исследую информацию о принципах CDROM. В стандарте http://www.ecma -international.org / публикации / файлы / ECMA-ST / Ecma-130.pdf На странице 35 (45 в формате pdf) я вижу кодировщик CIRC. И у него есть Q-код и P-коды, которые вычисляются по алгоритму Рида-Соломона. Я пытаюсь подтвердить это и делаю некоторые примеры звуковых дорожек (звуковая дорожка не использует скрембер в качестве дорожки данных), одна заполняется шаблоном 0x01, а другая - 0xA5 (байт CIRC в пакете, а не биты, и я вижу Q и P в кадре F3) , После того, как я извлек этот сектор с компакт-диска (непосредственно из Laser out) с помощью логического анализатора и расшифровал его по сценарию. У меня есть эти данные для трека с рисунком 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

Первый байт - это субкод sumbol в этом примере SYNC_1 и SYNC_2

Для дорожки с рисунком 0xA5

S1 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 65 bc a5 72 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 ff ff ff ff ff

S1 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 65 bc a5 72 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 a5 f5 ff ff ff ff

Если вы видите на CIRC все в порядке, то это 12-15 байт, его инвертированная четность Q и 28-32 P четность (первый байт - его код, его добавление в F3).

Но я не могу найти алгоритм для вычисления этого байта, мои математические навыки очень плохие. Я пробую калькулятор из cdrecord, его код и другие коды, попробую еще одно emplemetation Рида-Соломона, но я не могу получить идентичный код из этого примера. Где я могу получить реализацию этого кода.

1 Ответ

0 голосов
/ 18 января 2019

Я выкладываю то, что нахожу в этом ответе, когда делаю успехи, основываясь на файлах edc_ecc.c web github. RSL12 - это GF (2 ^ 8), полином x ^ 8 + x ^ 4 + x ^ 3 + x ^ 2 + 1 => hex 11d. Все ненулевые числа в поле можно считать степенями шестнадцатеричного числа 02.

Полином P-генератора в шестнадцатеричном виде:

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

Если вы посмотрите на 4 записи для AP [...] [31], вы увидите значения 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 байта, но они, по-видимому, ошибочны .

Существует обходной путь, для декодирования Q используйте 4 декодирования стирания с местоположениями с 12 по 15, помеченными как стирания (xx xx xx xx):

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 байтов четностей. Первые 4 значения из каждой строки AP [...] [32] должны быть удалены, поэтому он становится 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);
}
...