⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ldpc_decode.cpp

📁 模拟cmmb系统中ldpc译码的部分
💻 CPP
字号:

#include <stdlib.h>

#include <stdio.h>

#include <math.h>

#include "time.h"

#define N 9216
#define K 4608
#define M 4608

double gaussrand()
    {
        static double V1, V2, S;
        static int phase = 0;
        double X;

        if(phase == 0) {
        		do {
           		 	double U1 = (double)rand() / RAND_MAX;
           		 	double U2 = (double)rand() / RAND_MAX;

          	  	V1 = 2 * U1 - 1;
            		V2 = 2 * U2 - 1;
            		S = V1 * V1 + V2 * V2;
       	 		} while(S >= 1 || S == 0);

        		X = V1 * sqrt(-2 * log(S) / S);
       	 } else
      	 X = V2 * sqrt(-2 * log(S) / S);

      	 phase = 1 - phase;

      	 return X;
    }



void encode(char *rs_encoded,char **G,char *ldpc_encoded_data)
{
	int j,t;
	for(j=0;j<M;j++)
		for(t=0;t<K;t++)
    		ldpc_encoded_data[j] ^= (rs_encoded[t]&&G[j][t]); //校验位先存  G里面存的是(K*M)的转置				
   
	for(j=0;j<K;j++)
		ldpc_encoded_data[M+j] = rs_encoded[j];		//信息位后存     
}



void ldpc_decode(double *llr,char *ldpc_decoded)
{
	int i,j,k,n;
	double ram_init[36][256]={0};
	double ram_ext[3][36][256]={0};
	char	ram_hard[36][256]={0};
	char decision;
	int sum_decision;
	int neg_num;
	int max_iter = 100;
//	int biterrnum;
	double min[2],temp,alpha = 0.8;	
	double sum1,sum2,sum3,temp_ext0,temp_ext1,temp_ext2;
//	double sum_hardware[9216];
//	FILE* fp; 

	/***水平更新时确定从哪个ram组(cnu单元)的哪个ram中取哪一个数***/
	char ext_i[18][6]={{0,0,0,0,0,0},
	{1,0,0,0,0,2},
	{2,0,0,0,0,1},
	{0,1,0,0,2,2},
	{1,0,0,0,1,2},
	{2,0,0,0,1,1},
	{0,2,0,0,2,2},
	{1,0,0,2,2,2},
	{2,0,0,2,1,1},
	{0,1,2,2,2,1},
	{1,1,2,1,1,1},
	{2,0,2,1,1,1},
	{0,2,0,2,2,2},
	{1,2,2,2,1,1},
	{2,2,1,2,1,1},
	{0,1,2,1,1,1},
	{1,2,2,2,1,1},
	{2,0,2,1,1,1}};


	char vnu_i[18][6]={{0,6,12,18,25,30},
	{0,7,19,26,31,12},
	{0,8,13,20,32,26},
	{1,6,14,21,25,31},
	{1,15,27,33,20,8},
	{1,9,16,34,25,21},
	{2,6,28,35,16,20},
	{2,10,17,27,21,30},
	{2,11,22,22,16,34},
	{3,7,26,13,33,19},
	{3,9,28,17,31,18},
	{3,23,9,12,35,24},
	{4,7,29,17,34,18},
	{4,24,10,23,13,32},
	{4,29,10,32,23,15},
	{5,8,14,22,28,30},
	{5,19,11,15,33,27},
	{5,24,35,11,14,29}};


	unsigned char one_i[18][6]={{0,0,0,0,0,0},
	{0,0,0,0,0,157},
	{0,0,0,0,0,229},
	{0,0,0,0,85,248},
	{0,0,0,0,253,255},									
	{0,0,0,0,235,252},
	{0,0,0,0,115,215},
	{0,0,0,203,209,253},
	{0,0,0,146,242,248},
	{0,0,69,132,239,246},
	{0,129,131,209,254,255},
	{0,0,65,250,252,254},
	{0,0,0,164,215,248},
	{0,200,224,231,242,255},
	{0,115,240,243,250,254},
	{0,0,184,249,251,255},
	{0,58,216,240,253,254},
	{0,0,164,236,247,254}};


	
	/***********存储初始化似然比***************/
	for(i=0;i<256;i++)
		for(j=0;j<36;j++)
			ram_init[j][i] = llr[i*36+j];
			
	for(n=0;;n++)	
	{
//		biterrnum = 0;													//for err test
		sum_decision = 0;

//		printf("ram_init[14][154]=%f,ram_ext0[14][154]=%f,ram_ext1[14][154]=%f,ram_ext2[14][154]=%f\n",ram_init[14][154],ram_ext[0][14][154],ram_ext[1][14][154],ram_ext[2][14][154]);
		
		/************* 垂直更新********************/
		for(i=0;i<256;i++)
			for(j=0;j<36;j++)
			{
				temp_ext0 = ram_ext[0][j][i];
				temp_ext1 = ram_ext[1][j][i];
				temp_ext2 = ram_ext[2][j][i];
				sum1 = ram_init[j][i] + ram_ext[0][j][i];	
				sum2 = ram_ext[1][j][i] + ram_ext[2][j][i];	
				sum3 = sum1 +sum2;
				ram_ext[0][j][i] = ram_init[j][i] + sum2;
				ram_ext[1][j][i] = temp_ext2 + sum1;
				ram_ext[2][j][i] = temp_ext1 + sum1;
			/*	sum3 = ram_init[j][i] + ram_ext[0][j][i] + ram_ext[1][j][i] + ram_ext[2][j][i];
				ram_ext[0][j][i] = sum3 - ram_ext[0][j][i];
				ram_ext[1][j][i] = sum3 - ram_ext[1][j][i];
				ram_ext[2][j][i] = sum3 - ram_ext[2][j][i];*/
				ram_hard[j][i] = sum3 >= 0;	
//				if(ram_hard[j][i] != ldpc_encoded_data1[i*36+j])		//for err test
//					biterrnum++;										//for err test
//				sum_hardware[i*36+j]=sum3;
			}

//		printf("after NO.%d,errornum is %d.\n",n+1,biterrnum);			//for err test
		
//		printf("sum=%f\n",sum_hardware[5558]);

/*		fp = fopen("sum_hardware.txt","wb");
		if(fp == NULL)
		{
			printf("file open error!\n");
			return;
		}
		fwrite(sum_hardware,sizeof(double),9216,fp);
		fclose(fp);*/


		/**************水平更新******************/				
		for(i=0;i<256;i++)
			for(j=0;j<18;j++)
			{
				decision = 0;
				
				/****求最小值和负数的个数**********/
				neg_num = 0;
				if(ram_ext[ext_i[j][0]][vnu_i[j][0]][(one_i[j][0]+i)%256] < 0)
					neg_num++;
				min[1] = fabs(ram_ext[ext_i[j][0]][vnu_i[j][0]][(one_i[j][0]+i)%256]);

				if(ram_ext[ext_i[j][1]][vnu_i[j][1]][(one_i[j][1]+i)%256] < 0)
					neg_num++;
				min[0] = fabs(ram_ext[ext_i[j][1]][vnu_i[j][1]][(one_i[j][1]+i)%256]);

				if(min[0]<min[1])   /*最小值存在min[1],次小值存在min[0]*/
    			{
    				temp=min[0];
    				min[0]=min[1];
    				min[1]=temp;
    			}
				
				for(k=2;k<6;k++)
				{
					if(ram_ext[ext_i[j][k]][vnu_i[j][k]][(one_i[j][k]+i)%256] < 0)
						neg_num++;
					if(fabs(ram_ext[ext_i[j][k]][vnu_i[j][k]][(one_i[j][k]+i)%256])<min[0])
					{
    					min[0]=fabs(ram_ext[ext_i[j][k]][vnu_i[j][k]][(one_i[j][k]+i)%256]);
    					if(min[0]<min[1])   /*最小值存在min[1],次小值存在min[0]*/
    					{
    						temp=min[0];
    						min[0]=min[1];
    						min[1]=temp;
    					}    		
    				}	
				}	
				
				/*******找到最小值后更新每行**********/
				for(k=0;k<6;k++)
				{
					decision ^= ram_hard[vnu_i[j][k]][(one_i[j][k]+i)%256];//对校验式进行验算
					
					if(neg_num%2==0)
					{
						if(fabs(ram_ext[ext_i[j][k]][vnu_i[j][k]][(one_i[j][k]+i)%256])!=min[1])
							ram_ext[ext_i[j][k]][vnu_i[j][k]][(one_i[j][k]+i)%256] = ((ram_ext[ext_i[j][k]][vnu_i[j][k]][(one_i[j][k]+i)%256] > 0) ? min[1]*alpha:((-1)*min[1]*alpha));
						else
							ram_ext[ext_i[j][k]][vnu_i[j][k]][(one_i[j][k]+i)%256] = ((ram_ext[ext_i[j][k]][vnu_i[j][k]][(one_i[j][k]+i)%256] > 0) ? min[0]*alpha:((-1)*min[0]*alpha));				
					}
					
					else
					{
						if(fabs(ram_ext[ext_i[j][k]][vnu_i[j][k]][(one_i[j][k]+i)%256])!=min[1])
							ram_ext[ext_i[j][k]][vnu_i[j][k]][(one_i[j][k]+i)%256] = ((ram_ext[ext_i[j][k]][vnu_i[j][k]][(one_i[j][k]+i)%256] > 0) ? ((-1)*min[1]*alpha):min[1]*alpha);
						else
							ram_ext[ext_i[j][k]][vnu_i[j][k]][(one_i[j][k]+i)%256] = ((ram_ext[ext_i[j][k]][vnu_i[j][k]][(one_i[j][k]+i)%256] > 0) ? ((-1)*min[0]*alpha):min[0]*alpha);
					}					
				}	
				sum_decision += decision;
			}
		
		
		
		if(n < max_iter && sum_decision == 0)
		{
			printf("success at NO.%d iteration!\n ",(n+1));
			for(i=0;i<256;i++)
				for(j=0;j<36;j++)
					ldpc_decoded[i*36+j] = ram_hard[j][i];
			break;			
		}
		if(n == max_iter)
		{
			printf("fail to decode after No.%d iteration!\n",max_iter);
			for(i=0;i<256;i++)
				for(j=0;j<36;j++)
					ldpc_decoded[i*36+j] = ram_hard[j][i];
			break;
		}
	}
	
}



int main(int argc, char* argv[])
//int sc_main(int argc, char* argv[])
{
	char info[K];
	char rs_encoded[N];
	char rs_encoded1[N];
	char ldpc_encoded_data[N];
	char ldpc_encoded_data1[N];
	
	char **G;
	int i,j;
	int errframe,temperr,ErrorTimes = 10;
	long framenum,errbit;
	int alpha = 1,MQAM = 1;
	FILE *fp;
//	sc_fixed<total_bits,integral_bits,SC_RND,SC_SAT> ldpc_ch_info[N];
	double ldpc_ch_info[N];
//	double ldpc_ch_info1[N];  //for err test
	clock_t start, finish; //计算时间用的
	double duration;
	double Per,Ber;
	float LDPC_RATE = 0.5;
	float snr,sigma,noise_var;
	int order[N];			//码字重排
//	int initerrnum;			//for err test
	printf("input the snr:");
    scanf("%f",&snr);
	noise_var = alpha*alpha/(LDPC_RATE*pow(10,snr/10)*MQAM);// %复信号不需要*2 
	sigma = sqrt(noise_var/2);
	errframe = 0;
	errbit = 0;
	framenum=0;	
	

	G = (char **)malloc(M*sizeof(char *));	
	for(i=0 ; i<M ; i++)
	{
		G[i] = (char *)calloc(K,sizeof(char));
	}
    
    		//不同码率的生成矩阵不同,要根据码率分别读入。这里只读入了码率为1/2时的矩阵
	fp = fopen("GG12.txt","rb");		//GG12按列存,读的时候其实读的是(K*M)维矩阵的转置(M*K)   		
    if(fp==NULL)
	{
		printf("can not open the file!\n");					
		return 0;
	}
	for(j=0;j<M;j++)				
					
		fread(G[j],sizeof(char),K,fp);
					 	
	fclose(fp);	
				
		
	fp = fopen("rorder.txt","rb");
    		
    if(fp==NULL)
	{
		printf("can not open the file!\n");					
		return 0;
	}									
	fread(order,sizeof(int),N,fp);					 	
	fclose(fp);

	start = clock();	
			
	while (errframe<ErrorTimes)
   	{
    	temperr=0;
//		initerrnum=0;
    				
		framenum = framenum+1;
		srand( (unsigned)time( NULL ) );
		for(i=0;i<K;i++)
		{
			info[i]=(char)(rand()%2);		
		}

		for(i=0;i<N;i++)						//每次编码前对上一次的码字清零,不然会累积
			ldpc_encoded_data[i]=0;

		encode(info,G,ldpc_encoded_data);		//LDPC编码
	

		/****编码后码字重排****/
		for(i=0;i<N;i++)
		{
			ldpc_encoded_data1[order[i]] = ldpc_encoded_data[i];	
		}

		
		/******加入高斯噪声*******/
		for(i=0;i<N;i++)
		{
//			ldpc_ch_info[i]=(sc_fixed<total_bits,integral_bits,SC_RND,SC_SAT>)(2*ldpc_encoded_data.data[i]-1+sigma*gaussrand());
			ldpc_ch_info[i]=(double)(2*ldpc_encoded_data1[i]-1+sigma*gaussrand());
//			cout<<ldpc_ch_info[i].to_string()<<endl;
		}
		
		
		/****************************************************************/
		/*****************************************************************/
		/***********for test*************/
		
/*			fp=fopen("coded_data.txt","rb");
			if(fp==NULL)
			{
				printf("can not open the file!\n");
			}
			fread(ldpc_encoded_data1,sizeof(char),N,fp);	
			fclose(fp);
		
			fp = fopen("llr.txt","rb");
			if(fp==NULL)
			{
				printf("Can not open the file!\n");
				return 0;
			}
			fread(ldpc_ch_info,sizeof(double),N,fp);
			fclose(fp);
*/
/*			for(i=0;i<N;i++)
			{
				ldpc_encoded_data1[order[i]] = ldpc_encoded_data[i];	
			}
			for(i=0;i<N;i++)
			{
				ldpc_ch_info[order[i]] = ldpc_ch_info1[i];	
			}*/
			/**************************************************************/
			/**************************************************************/
			/***************************************************************/
			/********test over*********/



/*		for(i=0;i<N;i++)
			if((ldpc_ch_info[i]>=0)!=ldpc_encoded_data1[i])
				initerrnum++;
		printf("initerrnum=%d\n",initerrnum);
*/

		ldpc_decode(ldpc_ch_info,rs_encoded);  //ldpc译码
		
		/******译码后码字重排*******/
		
		for(i=0;i<N;i++)
			rs_encoded1[i] = rs_encoded[order[i]];

		
		/*******计算错误bit数,误码率等*********/
		for(i=0;i<N;i++)							
			if(ldpc_encoded_data[i]!=rs_encoded1[i])								
					temperr++;
								
		errframe = errframe + (temperr>0);
								
		errbit = errbit + temperr;
						
		if(temperr!=0)
		{
			printf("total errframe is %d,the current error framenum is %ld\n ",errframe,framenum)	;	
			Ber = errbit/(double)(framenum*9216);
            Per = (double)errframe/framenum;

            fp = fopen("datarecord.txt","w");
            if(fp==NULL)
			{
				printf("Can not open the file!\n");
				return 0;
			}
			fprintf(fp ,"snr=%f ,framenum=%ld ,errframe=%d ,errbit=%ld ,ber=%f ,per=%f \n",snr,framenum,errframe,errbit,Ber,Per);
			fclose(fp);														
		}	
//		if(framenum == 1)
//			break;
    }
    printf("snr=%f ,framenum=%ld ,errframe=%d ,errbit=%ld ,ber=%f ,per=%f\n",snr,framenum,errframe,errbit,Ber,Per);
 
	for( j=0 ; j<M ; j++)
	{
		free(G[j]);
	}
	free(G);

	finish = clock();
	duration = (double)(finish - start) / CLOCKS_PER_SEC; 
	printf( "%f seconds\n", duration );
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -