1.BCH(26,16)的基本简介
BCH(26,16)是一种缩短循环校验码,它的数据位为16位,校验位是10位,码字的长度为26位。BCH(26,16)码取(31,21)循环码中的前5位信息位为0的码字作为码字,构成(21-5)维的线性子空间,它最多能够纠正t=2位错误(,其中m是GF(p^m)中的m,这里的m=5,n=31,k=21)。对于铁路在800M频段上的数据业务,它采用的生成多项式为G(X)=X^10+X^8+X^7+X^5+X^4+X^3+1。
2.BCH(26,16)的编码原理
我们假设C(X)是需要发送的数字,,在这里C15C14....C1C0你是我们需要发送的二进制数据。假设R(X)是校验位,。那么我们需要通过C(X)和生成多项式G(X)产生R(X),R(X)是C(X)X10除以G(X)的余数,这里的除法是模2除法。模2除法与算术除法类似,但每一位除的结果不影响其它位,即不向上一位借位,所以实际上就是异或。例如,发送的数据C(x)=1000,校验位数是3,其选择生成多项式为G(x)=x^3+x+1。G(x)=x^3+x+1对应的二进制数为1011,C(X)X^3=1000<<3=1000 000B;1000 000B(被除数)对1011(除数)做模2除法,得到的余数R(X)便是101B。为了得到BCH(26,16)的校验位,一种很方便的模2除法的算法源代码如下。
unsigned int CX = 0x5555,RX;//16位的数据位
CX = CX<<10;//相当于C(X)X10
unsigned int gx = 0x05B9<<(26-11);
for(int i=0;i<16;i++){//迭代循环16次,进行16次除法操作,最后剩下10位的余数
if((CX&0x2000000)!=0){//对CX的最高位是否为1,如果是1,做减法操作(异或)
CX ^=gx ;//扩展gx到与CX同样是26位,为了方便除法运算
}
CX = CX<<1;
}
RX = CX>>16;
printf("CX为校验位是 %2x",RX);
3. BCH(26,16)的解码原理
3.1用BCH的生成多项式校验数据是否正确,即使用接收到的26位码M(X)= C(X)X^10+R(X)除以生成多项式G(X)。如果余数为0,那么校验正确,否则校验错误,需要纠错。
unsigned int code = 0;
unsigned int gx = 0x05B9<<(26-11);
code = 0x3fffccd;
unsigned int res = 0;
for(int i=0;i<16;i++){//求余数的算法中,只需要除以最高位的16位,余数一定是10位。
if((code&0x2000000)!=0){
code ^=gx;
}
code = code <<1;
}
Res = code>>(26-10);
printf("余数 %2x\n",res);
3.2如果只错了1位或者2位。假设发送方发送的码为,由于只错了一位,那么假设错的这位是Cx,则接收到的码为。我们的问题是如何知道错误的位置x,以及所对应的Cx?上面的关系实际上表明R(X)=C(X)+E(X),其中。我们已经知道R(X),生成多项式G(X)和R(X)%G(X)的余数r(X),现在需要求出C(X)。,如果我们前期计算了一个表,这个表中表明唯一的一个E(X)对应唯一的一个r(X),唯一的r(x)不一定代表唯一的E(X),但是我们假设了只存在一个错误,那么通过查表我们就可以知道E(X)。当求解出E(X)后,C(X)=R(X)-E(X)=R(X)+E(X),这样R(X)和E(X)进行异或运算就可以得到C(X)。这种方式能够解决一位出错的情况,但是当2位出错的时候,可以改写表达式为,因此只要检测到错误的这两位,然后把它修正了就可以了。具体的解码程序如下。
unsigned int CheckMatrix[26][2];
#define gx 0x05B9<<(26-11)
//create check metric
void CreateCheckMatrix(){
unsigned int RX,CX;
CX = 1<<15;
for(int i=0;i<16;i++){
if(i<16){
RX = GetFEC(CX);
CheckMatrix[i][0] = RX;
CheckMatrix[i][1] = CX<<10;
}
CX = CX>>1;
}
CX = 1<<9;
for(int i=0;i<10;i++){
CheckMatrix[i+16][0] = CX;
CheckMatrix[i+16][1] = CX;
printf("%2x 为校验位是 %2x\n",CX,CX);
CX = CX>>1;
}
}
//correct data error
unsigned int CorrectError(unsigned int code,unsigned int *value){
unsigned int encode = 0;
unsigned int decode = 0;
unsigned int res;
decode = code;
printf("decode %2x\n",code);
//2.1 calculate remainder
for(int i=0;i<16;i++){//求余数的算法中,只需要除以最高位的16位,余数一定是10位。
if((code&0x2000000)!=0){
code ^=gx;
}
code = code <<1;
}
res = code>>(26-10);
printf("余数 %2x\n",res);
if(res == 0){
*value = decode;
return 0;
}
//2.2 correct one bit error
for(int i=0;i<26;i++){
if(res == CheckMatrix[i][0]){
decode = decode^CheckMatrix[i][1];
*value = decode;
return 1;
}
}
//2.3 correct two bit error
for(int i=0;i<26;i++){
for(int j=i+1;j<26;j++){
if(res == (CheckMatrix[i][0]^CheckMatrix[j][0])){
decode = decode^CheckMatrix[i][1]^CheckMatrix[j][1];
*value = decode;
return 2;
}
}
}
return 3;
}
3.3最后BCH(26,16)编码和解码源程序如下
#include
#include
#include
#include
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
unsigned int CheckMatrix[26][2];
#define gx 0x05B9<<(26-11)
//get correct remainder
unsigned int GetFEC(unsigned int CX){
unsigned int RX;//16位的数据位
unsigned int tmp;
CX = CX<<10;
tmp = CX;
for(int i=0;i<16;i++){//迭代循环16次,进行16次除法操作,最后剩下10位的余数
if((CX&0x2000000)!=0){//对CX的最高位是否为1,如果是1,做减法操作(异或)
CX ^=gx ;//扩展gx到与CX同样是26位,为了方便除法运算
}
CX = CX<<1;
}
RX = CX>>16;
printf("%2x 为校验位是 %2x\n",tmp,RX);
return RX;
}
//create check metric
void CreateCheckMatrix(){
unsigned int RX,CX;
CX = 1<<15;
for(int i=0;i<16;i++){
if(i<16){
RX = GetFEC(CX);
CheckMatrix[i][0] = RX;
CheckMatrix[i][1] = CX<<10;
}
CX = CX>>1;
}
CX = 1<<9;
for(int i=0;i<10;i++){
CheckMatrix[i+16][0] = CX;
CheckMatrix[i+16][1] = CX;
printf("%2x 为校验位是 %2x\n",CX,CX);
CX = CX>>1;
}
}
//correct data error
unsigned int CorrectError(unsigned int code,unsigned int *value){
unsigned int encode = 0;
unsigned int decode = 0;
unsigned int res;
decode = code;
printf("decode %2x\n",code);
//2.1 calculate remainder
for(int i=0;i<16;i++){//求余数的算法中,只需要除以最高位的16位,余数一定是10位。
if((code&0x2000000)!=0){
code ^=gx;
}
code = code <<1;
}
res = code>>(26-10);
printf("余数 %2x\n",res);
if(res == 0){
*value = decode;
return 0;
}
//2.2 correct one bit error
for(int i=0;i<26;i++){
if(res == CheckMatrix[i][0]){
decode = decode^CheckMatrix[i][1];
*value = decode;
return 1;
}
}
//2.3 correct two bit error
for(int i=0;i<26;i++){
for(int j=i+1;j<26;j++){
if(res == (CheckMatrix[i][0]^CheckMatrix[j][0])){
decode = decode^CheckMatrix[i][1]^CheckMatrix[j][1];
*value = decode;
return 2;
}
}
}
return 3;
}
int main(int argc, char** argv) {
unsigned int code = 0,RX,CX;
unsigned int encode = 0,decode;
unsigned int res = 0;
unsigned int pos1=0,pos2=0,pos3=0;
//produce check metric
CreateCheckMatrix();
//encode
res = 0xffff;
encode = (res<<10)^GetFEC(res);
printf("encode %2x\n",encode);
//decode
// pos1 = 0x8;
pos2 = 0x2000000;
pos3 = 0x800000;
code = encode^pos1^pos2^pos3;
res = CorrectError(code,&decode);
printf("result %2x decode %2x\n",res,decode);
return 0;
}