Я создал кодировщик CCSDS BCH (64,56), используя очень простую подпрограмму CRC в C ++. Я намерен использовать его в приложении GNU Radio. Формат кодового блока BCH (64,56) показан ниже.
.
Группа кодовых блоков может быть объединена для формирования блока данных, называемого блоком передачи линии связи (CLTU), показанным ниже.
Насколько я понимаю, как BCH, так и CRC добавляют «остаток / четность» к концу данных, используя ту же форму расчетов, как объяснено в этот нить.
Все, что мне нужно было сделать, это изменить стандарт 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;
}
Я как-то чувствую, что мой подход слишком наивен. Я хотел бы знать, если это точно.
С Уважением,
Если код BCH имеет расстояние 3, предназначенное только для исправления одной битовой ошибки или обнаружения (но не исправления) всех двух битовых ошибок, то полином BCH будет таким же, как полином полевой. Если требуется более высокий уровень коррекции или обнаружения, то многочлен МПБ усложняется. Это объясняется в статье вики:
https://en.wikipedia.org/wiki/BCH_code
Поскольку длина сообщения (включая бит-заполнитель) составляет 64 бита, используется 7-битное поле (подходит для до 127 бит), но показанная генерация таблицы для полинома 0x1C5. Чтобы это исправить, измените POLYNOMIAL на 0x8A, то есть ((0xC5 << 1) & 0xFE)). Это должно привести к 7-битной четности, которая заканчивается в старших 7 битах байта.
Внутренняя часть цикла кодирования должна быть:
remainder = crcTable[message.at(byte) ^ remainder];
Других решений пока нет …