Реализация кода FEC CCSDS BCH (64,56) с использованием базовых функций CRC C ++ - PullRequest
0 голосов
/ 30 ноября 2018

Я создал кодировщик CCSDS BCH (64,56), используя очень простую подпрограмму CRC в C ++.Я намерен использовать его в приложении GNU Radio.Формат кодового блока BCH (64,56) показан ниже.BCH codeblock.Группа кодовых блоков может быть объединена для формирования блока данных, называемого блоком передачи линии связи (CLTU), показанным ниже.cltu

Насколько я понимаю, и МПБ, и КРК добавляют "остаток / паритет" к концу данных, используя ту же форму вычислений, как объяснено в эта нить.

Все, что мне нужно было сделать, - это изменить стандартную подпрограмму CRC C ++ crcFast () .Подпрограмма вычисляет CRC путем перебора массива (таблицы), который предварительно инициализируется заданным полиномом (crcInit ()).Две подпрограммы, crcInit () и crcFast (), показаны в коде ниже.

typedef unsigned char uint8_t;
typedef unsigned short crc;
#define WIDTH (8 * sizeof(crc))
#define TOPBIT (1 << (WIDTH - 1))
crc crcTable[256];
#define POLYNOMIAL 0xD8  /* 11011 followed by 0's */
void
crcInit(void)
{
    crc remainder;


    /*
* Compute the remainder of each possible dividend.
*/
    for (int dividend = 0; dividend < 256; ++dividend)
    {
        /*
* Start with the dividend followed by zeros.
*/
        remainder = dividend << (WIDTH - 8);

        /*
* Perform modulo-2 division, a bit at a time.
*/
        for (uint8_t bit = 8; bit > 0; --bit)
        {
            /*
* Try to divide the current data bit.
*/
            if (remainder & TOPBIT)
            {
                remainder = (remainder << 1) ^ POLYNOMIAL;
            }
            else
            {
                remainder = (remainder << 1);
            }
        }

        /*
* Store the result into the table.
*/
        crcTable[dividend] = remainder;
    }

} /* crcInit() */


crc
crcFast(uint8_t const message[], int nBytes)
{
    uint8_t data;
    crc remainder = 0;


    /*
     * Divide the message by the polynomial, a byte at a time.
     */
    for (int byte = 0; byte < nBytes; ++byte)
    {
        data = message[byte] ^ (remainder >> (WIDTH - 8));
        remainder = crcTable[data] ^ (remainder << 8);
    }

    /*
     * The final remainder is the CRC.
     */
    return (remainder);

}   /* crcFast() */

Измененный код показан ниже.Функция генерирования таблицы crcInit () не изменяется.Алгоритм crcFast был немного изменен, чтобы включить изменения в байте четности (бит комплимента и заполнителя), как указано форматом.Тип CRC был изменен с короткого на беззнаковый символ (1 байт).BCH (64,56) в чистом коде Хемминга с полиномом-генератором, заданным как g (x) = x ^ 7 + x ^ 6 + x ^ 2 + 1, что, по моему мнению, эквивалентно 0xC5.

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <vector>
#include <iostream>
#include "debug.h"
typedef unsigned char uint8_t;
typedef unsigned char crc;
#define WIDTH  (8 * sizeof(crc))
#define TOPBIT (1 << (WIDTH - 1))
crc  crcTable[256];
#define POLYNOMIAL 0xC5  // x^7 + x^6 + x^2 + 1
#define INITIAL_REMAINDER 0x00
#define BCH_INFORMATION_BLOCK 7
void
crcInit(void)
{
    crc  remainder;


    /*
     * Compute the remainder of each possible dividend.
     */
    for (int dividend = 0; dividend < 256; ++dividend)
    {
        /*
         * Start with the dividend followed by zeros.
         */
        remainder = dividend << (WIDTH - 8);

        /*
         * Perform modulo-2 division, a bit at a time.
         */
        for (uint8_t bit = 8; bit > 0; --bit)
        {
            /*
             * Try to divide the current data bit.
             */         
            if (remainder & TOPBIT)
            {
                remainder = (remainder << 1) ^ POLYNOMIAL;
            }
            else
            {
                remainder = (remainder << 1);
            }
        }

        /*
         * Store the result into the table.
         */
        crcTable[dividend] = remainder;
    //std::cout << "Remainder from table : " << int (remainder&0xffff) << std::endl;
    }

}   /* crcInit() */

void
crcEncoder(std::vector<unsigned char> &message, const crc initial_remainder)
{
    uint8_t data;
    crc remainder = initial_remainder;

    /*
     * Divide the message by the polynomial, a byte at a time.
     */
    for (int byte = 0; byte < message.size(); ++byte)
    {
        data = message.at(byte) ^ (remainder >> (WIDTH - 8));
        remainder = crcTable[data] ^ (remainder << 8);
    }

    //Flip the remainder and move by 1 bit
    remainder ^= 0xFF;
    remainder <<= 1;

    //Set filler bit to 0 (anding with 1111 1110)
    remainder &= 0xFE;

    /*
     * The final remainder is the CRC.
     */
    message.push_back(remainder);
    //return message;
}


void bchEncoder(std::vector<unsigned char> &message)
{
    std::vector<unsigned char> information; // 7 bytes
    std::vector<unsigned char> codewords; // Encoded message

    //Ensure integral information symbols
    while(!(message.size() % BCH_INFORMATION_BLOCK) == 0)
      {
        message.push_back(0x55);
      }

    for(int i = 0; i < message.size(); i += BCH_INFORMATION_BLOCK)
    {
        //Copy 7 information bytes
        std::copy(message.begin() + i, message.begin() + i + BCH_INFORMATION_BLOCK,
                      std::back_inserter(information));
        //BCH encoding
        crcEncoder(information,INITIAL_REMAINDER);

        //Copy encoded information bits
        codewords.insert(codewords.end(), information.begin(), information.end());

        //Clear information bytes
        information.clear();
    }
    message = codewords;
}


int main()
{
  crcInit();
  //hexdump(crcTable,256);
  unsigned char message[] = {0xaa, 0xbb, 0xcd, 0xdd, 0xee, 0xff, 0x11,0x00};
  //unsigned char tail[] = {0xC5,0xC5,0xC5,0xC5,0xC5,0xC5,0xC5,0x79};
  std::vector<unsigned char> info(message, message + sizeof(message)/sizeof(unsigned char));

  bchEncoder(info);
  hexdump(info.data(),info.size());

  //Vector hex dump

  return 0;
}

Мне почему-то кажется, что мой подход слишком наивен.Я хотел бы знать, если это точно.

С уважением,

1 Ответ

0 голосов
/ 30 ноября 2018

Если код BCH имеет расстояние 3, предназначенное только для исправления одной битовой ошибки или обнаружения (но не исправления) всех двухбитовых ошибок, то полином BCH будет таким же, как полином полевой.Если требуется более высокий уровень коррекции или обнаружения, то многочлен МПБ усложняется.Это объясняется в статье в вики:

https://en.wikipedia.org/wiki/BCH_code

Поскольку длина сообщения (включая бит-заполнитель) составляет 64 бита, используется 7-битное поле (подходит для до 127биты), но показанная генерация таблицы для полинома 0x1C5.Чтобы это исправить, измените POLYNOMIAL на 0x8A, то есть ((0xC5 << 1) & 0xFE)).Это должно привести к 7-битной четности, которая заканчивается в старших 7 битах байта. </p>

Внутренняя часть цикла кодирования должна быть:

    remainder = crcTable[message.at(byte) ^ remainder];
...