【问题标题】:Implementing CCSDS BCH(64,56) FEC code by using basic CRC C++ subroutines使用基本 CRC C++ 子例程实现 CCSDS BCH(64,56) FEC 代码
【发布时间】:2019-05-02 18:04:35
【问题描述】:

我使用 C++ 中一个非常基本的 CRC 子例程创建了一个 CCSDS BCH(64,56) 编码器。我打算在 GNU Radio 应用程序中使用它。 BCH(64,56) 代码块的格式如下所示。 。 可以组合一组代码块以形成称为通信链路传输单元 (CLTU) 的数据单元,如下所示。

据我了解,BCH 和 CRC 都使用相同的计算形式在数据末尾附加“余数/奇偶校验”,如 this 线程中所述。

我所要做的就是修改一个标准的 CRC C++ crcFast() subroutine 。该子例程通过遍历由给定多项式 (crcInit()) 预先初始化的数组(表)来计算 CRC。下面的代码显示了两个子例程 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 类型已从 short 更改为 unsigned char(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;
}

我觉得我的方法太天真了。我想知道它是否准确。

问候,

【问题讨论】:

  • 你有什么问题?
  • @RogerLipscombe 我可能有点跑题了,尽管这个问题比代码审查要多得多。我只是想了解如何将 BCH 代码实现为 CRC 的一个特例。
  • @RogerLipscombe 请随意推荐 CR 上的 OP 帖子,但以后请不要以 Code Review 网站的存在作为关闭问题的理由。评估请求并使用太宽泛主要基于意见等原因。然后您可以向 OP 提及它可以在 Code Review 上发布(如果是) on-topic。请参阅this answer to A guide to Code Review for Stack Overflow users 中的你不应该做的事情部分

标签: c++ crc gnuradio gnuradio-companion


【解决方案1】:

如果 BCH 码的距离为 3,仅用于纠正单个位错误或检测(但不纠正)所有两位错误,则 BCH 多项式将与场多项式相同。如果需要更高级别的校正或检测,那么 BCH 多项式就会变得复杂。这在 wiki 文章中有解释:

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

由于消息长度(包括填充位)为 64 位,因此使用 7 位字段(适用于最多 127 位),但显示的表格生成适用于多项式 0x1C5。要解决此问题,请将 POLYNOMIAL 更改为 0x8A,即 ((0xC5

编码循环的内部应该是:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-12-27
    • 2011-06-30
    • 2014-04-21
    • 2013-02-09
    • 1970-01-01
    • 1970-01-01
    • 2011-08-25
    • 2019-01-17
    相关资源
    最近更新 更多