📄 rcpc.cpp
字号:
/**********************************************************************************************************************
该程序可以将随机生成的0,1序列经过卷积编码器产生(4,1,4)卷积码,然后将卷积码经过4*8的删余矩阵,有三种速率(1/3,2/3,1/2)可供选择,
在编码端利用维特比译码方法进行译码
*****************************************************************************************************************************/
#include "iostream.h"
#include "stdio.h"
#include <stdlib.h>
#include <time.h>
#define M1 1000 //存储输入码字的数组容量
#define M2 4000 //存储编码后码字的数组容量
static int g1[4]={0x13,0x1d,0x17,0x1b};//定义生成矩阵
static int
A0[13]={0XC8,0XC8,0XC8,0XCC,0XCC,0XEC,0XEE,0XEE,0XEE,0XFE,0XFE,0XFE,0XFF},
A1[13]={0X88,0X88,0XC8,0XC8,0XCC,0XCC,0XCC,0XEC,0XEE,0XEE,0XFE,0XFE,0XFF},
A2[13]={0X48,0XC8,0XC8,0XCC,0XCC,0XEC,0XEE,0XEE,0XEE,0XFE,0XFE,0XFF,0XFF},
A3[13]={0x88,0x88,0xC8,0XC8,0XCC,0XCC,0XCC,0XEC,0XEE,0XEE,0XFE,0XFE,0XFF}; //定义删余矩阵
/*************************************************************************************************************************
编码函数
*************************************************************************************************************************/
//以下为(4,1,4)卷积编码函数
unsigned int juanjiencode(
unsigned int *symbols, /*编码输出*/
unsigned int *data, /*编码输入*/
unsigned int nbytes, /*nbytes=n/16,n为实际输入码字的数目*/
unsigned int startstate /*定义初始化状态*/
)
{
unsigned int j;
unsigned int input,a1=0,a2=0,a3=0,a4=0;
for(j=0;j<nbytes;j++)
{ input=*data;
data++;
*symbols = input^(((g1[0]>>3)&1)*a1)^(((g1[0]>>2)&1)*a2)^(((g1[0]>>1)&1)*a3)^((g1[0]&1)*a4);
symbols++;
*symbols = input^(((g1[1]>>3)&1)*a1)^(((g1[1]>>2)&1)*a2)^(((g1[1]>>1)&1)*a3)^((g1[1]&1)*a4);
symbols++;
*symbols = input^(((g1[2]>>3)&1)*a1)^(((g1[2]>>2)&1)*a2)^(((g1[2]>>1)&1)*a3)^((g1[2]&1)*a4);
symbols++;
*symbols = input^(((g1[3]>>3)&1)*a1)^(((g1[3]>>2)&1)*a2)^(((g1[3]>>1)&1)*a3)^((g1[3]&1)*a4);
symbols++;
a4=a3;
a3=a2;
a2=a1;
a1=input;
}
return 0;
}
//以下为经过删余矩阵的处理
unsigned int puncture(unsigned int *input,unsigned int *output,unsigned int m) //删余函数
{int i,s,num_of_rcpc=0;
unsigned int mem;
cout<<"选择删余矩阵:"<<'\n'<<"s=0,码率为8/9"<<';'<<"s=1,码率为8/10"<<';'<<"s=2,码率为8/12"<<';'<<"s=3,码率为8/14"<<';'<<'\n';
cout<<"s=4,码率为8/16"<<';'<<"s=5,码率为8/18"<<';'<<"s=6,码率为8/20"<<';'<<"7=2,码率为8/22"<<';'<<'\n';
cout<<"8=0,码率为9/24"<<';'<<"s=9,码率为8/26"<<';'<<"s=11,码率为10/28"<<';'<<"s=11,码率为8/30"<<';'<<'\n';
cout<<"8=0,码率为9/32"<<'\n';
cout<<"s=";
cin>>s;
cout<<'\n';
while(m--!=0)
{
for(i=7;i>=0;i--)
{
if((A0[s]>>i)&1) {mem=*input++;*output++=mem;num_of_rcpc++;}
else input++;
if((A1[s]>>i)&1) {mem=*input++;*output++=mem;num_of_rcpc++;}
else input++;
if((A2[s]>>i)&1) {mem=*input++;*output++=mem;num_of_rcpc++;}
else input++;
if((A3[s]>>i)&1) {mem=*input++;*output++=mem;num_of_rcpc++;}
else input++;
}
}
return s;
}
void bsc(unsigned int *input,unsigned int *output,int num) //bsc信道
{ int i,j;
unsigned int data[M2];
cout<<'\n';
srand( (unsigned)time( NULL ) );
for(i=0;i<num;i++)
{ data[i]=rand()%2;
cout<<data[i];
if(data[i]==1)
*output++=*input++;
else *output++=*input++^1;
}
cout<<'\n';
}
//以下将接收的RCPC码还原成原先的卷积码,被删掉的比特补0
void huanyuan(unsigned int *input,unsigned int *output,int num,int s)
{int i;
while(num--!=0)
{for(i=7;i>=0;i--)
{
if(A0[s]>>i&1) *output=*input++;
else *output=0;
output++;
if(A1[s]>>i&1) *output=*input++;
else *output=0;
output++;
if(A2[s]>>i&1) *output=*input++;
else *output=0;
output++;
if(A3[s]>>i&1) *output=*input++;
else *output=0;
output++;
}
}
}
/*********************************************************************************************************************
* 维特比译码部分 *
*********************************************************************************************************************/
int traninput(int a,int b) //从状态a到b的输入值
{int c;
c=((b&8)>>3);
return c;
}
int tranouput(int a,int b,int s,int i) //从状态a到b的输出的值
{int c,s1,s2,s3,s4;
if(A0[s]>>i&1)
s1=(b>>3&1)^((a>>3&1)*(g1[0]>>3&1))^((a>>2&1)*(g1[0]>>2&1))^((a>>1&1)*(g1[0]>>1&1))^((a&1)*(g1[0]&1));
else s1=0;
if(A1[s]>>i&1)
s2=(b>>3&1)^((a>>3&1)*(g1[1]>>3&1))^((a>>2&1)*(g1[1]>>2&1))^((a>>1&1)*(g1[1]>>1&1))^((a&1)*(g1[1]&1));
else s2=0;
if(A2[s]>>i&1)
s3=(b>>3&1)^((a>>3&1)*(g1[2]>>3&1))^((a>>2&1)*(g1[2]>>2&1))^((a>>1&1)*(g1[2]>>1&1))^((a&1)*(g1[2]&1));
else s3=0;
if(A3[s]>>i&1)
s4=(b>>3&1)^((a>>3&1)*(g1[3]>>3&1))^((a>>2&1)*(g1[3]>>2&1))^((a>>1&1)*(g1[3]>>1&1))^((a&1)*(g1[3]&1));
else s4=0;
c=(s1<<3)|(s2<<2)|(s3<<1)|s4;
return c;
}
//以下为编码数据从state1到state2时的汉明距离,如果state1无法到state2则输出度量值为100
int hanmingjuli(int data,int state1,int state2,int s,int i)
{ int d,e,f;
e=tranouput(state1,state2,s,i);
f=e^data;
if(((state1>>1)==state2)||(((state1>>1)^8)==state2))
d=((f>>3)&1)+((f>>2)&1)+((f>>1)&1)+(f&1);
else d=100;
return d;
}
//以下为维特比译码的主函数
void viterby(unsigned int *input,unsigned int *output,int initialstate,int N,int s) //N为实际输入的码字大数量,initialstate表示输入的初始状态
{ int i,j,l,r,u,t,p,q,y,x=0;
struct wange
{int pm;
int value;
struct wange *last; //pm表示路径量度,value表示译码输出的码字
};
struct wange state[16][M1];
struct wange *g,*head;
for(i=0;i<16;i++)
for(j=0;j<N;j++)
state[i][j].pm=0; //初始化每个状态的度量值为0
for(l=0;l<16;l++)
{state[l][0].pm=hanmingjuli(*input,initialstate,l,s,7);
state[l][0].value=traninput(initialstate,l);
state[l][0].last=NULL;
}
input++; /*扩展第一步幸存路径*/
for(i=0;i<N/8;i++)
{for(j=0;j<=7;j++)
if(i==0&&j==0)
x++;
else
{for(p=0;p<16;p++)
{t=j+8*i;
y=7-j;
if(i==0)
{state[p][t].pm=state[0][t-1].pm+hanmingjuli(*input,0,p,s,y-1);
state[p][t].value=traninput(0,p);
state[p][t].last=&state[0][t-1];
}
else
{state[p][t].pm=state[0][t-1].pm+hanmingjuli(*input,0,p,s,y);
state[p][t].value=traninput(0,p);
state[p][t].last=&state[0][t-1];
}
for(q=0;q<16;q++)
{if(state[q][t-1].pm+hanmingjuli(*input,q,p,s,y)<state[p][t].pm)
{state[p][t].pm=state[q][t-1].pm+hanmingjuli(*input,q,p,s,y);
state[p][t].value=traninput(q,p);
state[p][t].last=&state[q][t-1];
}
}
}
input++;
} /*计算出剩余的幸存路径*/
}
r=state[0][N-1].pm; /*找出n步后度量值最小的状态,准备回溯路由*/
g=&state[0][N-1];
for(u=N;u>0;u--) /*向前递归的找出最大似然路径 */
{*(output+(u-1))=g->value;
g=g->last;
}
/* for(u=0;u<8;u++)
*(viterbioutput+u)=state[u][2].pm; */ /*此行程序可用于检测第n列的度量值*/
}
/*********************************************************************************************************************************
译码主函数
*********************************************************************************************************************************/
void decode(unsigned int *input,unsigned int *output,int n,int num,int s)
{
unsigned int viterbiinput1[M2],viterbiinput[M1];
int j,i;
huanyuan(input,viterbiinput1,(n+4)/8,s);
/* cout<<"输入到维特比译码器的码字为:"<<'\n';
for(j=0;j<(n+4)*4;j++)
{cout<<viterbiinput1[j];
if((j+1)%4==0) cout<<' ';
if(j%20==19)
cout<<'\n';
}*/
cout<<'\n';
for(j=0;j<n+4;j++)
viterbiinput[j]=(viterbiinput1[4*j]<<3)|(viterbiinput1[4*j+1]<<2)|(viterbiinput1[4*j+2]<<1)|viterbiinput1[4*j+3];
viterby(viterbiinput,output,0,n+4,s);
}
/*********************************************************************************************************************************
主函数开始部分
*********************************************************************************************************************************/
void main()
{unsigned int encodeinput[M1],wrong[10]={0,0,0,0,0,0,0,0,0,0},juanjioutput[M2],encorderoutput[M2],decodeinput[M2],decodeoutput[M1];
int n,m,s,num,i,j=0,diff=0;
cout<<"输入编码的个数:";
cin>>n;
cout<<'\n';
srand((unsigned)time(NULL));
for(i=0; i<n; i++)
encodeinput[i]=rand()%2; //产生n个随机的0和1
encodeinput[n]= encodeinput[n+1]=encodeinput[n+2]=encodeinput[n+3]=encodeinput[n+4]=0; //在第n个数据输入以后持续输入5个数使寄存器清0
juanjiencode(juanjioutput,encodeinput,n+4,0); //调用卷积编码程序
cout<<"the input of encoder is :"<<n<<'\n';
for(i=0;i<n; i++)
cout<<encodeinput[i];
cout<<'\n';
cout<<"the output of juanjiencoder is :"<<(n+4)*4<<'\n';
for(i=0;i<(n+4)*4;i++)
{cout<<juanjioutput[i];
if((i+1)%4==0) cout<<' ';
if(i%40==39)
cout<<'\n';
}
cout<<'\n';
s=puncture(juanjioutput,encorderoutput,(n+4)/8);
if(s==0) num=(n+4)*4*9/32;
else num=(n+4)*4*(8+2*s)/32; //计算选择不同码率的删余矩阵所产生的码字个数
cout<<"经过删余矩阵后输出的码字为:";
cout<<num<<'\n';
for(i=0;i<num;i++)
cout<<encorderoutput[i];
cout<<'\n';
//以下程序可以对发送的卷积码进行修改以检测译码端的纠错能力
/* cout<<"please input the number of the wrong bit"<<'\n';
cin>>m;
cout<<"please input the positions of the wrong bit(0-100)"<<'\n';
for(i=0;i<m;i++)
{cin>>wrong[m];
if(encorderoutput[wrong[m]]==0)
encorderoutput[wrong[m]]=1;
else
encorderoutput[wrong[m]]=0;
}
cout<<"the input of decoder is :"<<'\n';
for(i=0;i<num;i++)
cout<<encorderoutput[i];
cout<<'\n';*/
/* bsc(encorderoutput,decodeinput,num);
cout<<'\n';
cout<<"译码端的输入码字:"<<'\n';
for(i=0;i<num;i++)
cout<<decodeinput[i];*/
cout<<'\n';
decode(encorderoutput,decodeoutput,n,num,s); //s代表选择的删余矩阵
cout<<"译码后输出的码字为:";
cout<<'\n';
for(i=0;i<n;i++)
cout<<decodeoutput[i];
cout<<'\n';
for(i=0;i<n;i++)
{if(encodeinput[i]!=decodeoutput[i])
diff++;
}
cout<<"误码的个数为:"<<diff<<'\n';
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -