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

📄 biintpmimo_channel.c

📁 2发2收的MIMO信道模拟程序
💻 C
字号:
/*******************************************************************************************************
2发2收的MIMO信道模拟程序,信道满足瑞利衰落,采用最新的改进的Jakes模型,解决了传统算法中的统计性缺陷。
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#define	PI		4*atan(1)

typedef struct
{
	double real;
	double image;
}COMPLEX;

//Add two complex a and b.
COMPLEX add_cmx(COMPLEX a, COMPLEX b)
{
	COMPLEX result;

	result.real  = a.real  + b.real;
	result.image = a.image + b.image;

	return result;
}

//Multiple complexs a and b.
COMPLEX mul_cmx(COMPLEX a, COMPLEX b)
{
	COMPLEX result;

	result.real  = a.real*b.real  - a.image*b.image;
	result.image = a.real*b.image + a.image*b.real;

	return result;
}
// generate channel data for current time
int GenCurCHData(double * alpha, double * beta, double * p_Time, COMPLEX * p_CHData, int PathNum, double* p_Phase, double* p_CorrMatrix)  //PathNum=TotalPathNum
{
	int n;
	int n_Path;
	int N0 = 25;
	//int N  = 4*N0;
	
    double SQRT_N0 = sqrt(N0);
  
	COMPLEX	 temp;
	COMPLEX  CHtemp;
	double  *p_curCorrMatrix;
	
	COMPLEX *p_IID_CHData;	// i.i.d channel data
	p_IID_CHData = (COMPLEX *)malloc(PathNum*sizeof(COMPLEX));
	
	//Generate i.i.d channel data for current TimeInstant
	for(n_Path=0; n_Path<PathNum; n_Path++)
	{
		CHtemp.real = CHtemp.image = 0;
		for(n=0; n<N0; n++)
		{
			temp.real   = cos( (*(alpha + n*PathNum + n_Path))*(*p_Time) + p_Phase[0]);   // alpha=0-191 192-383 ... 24*192-(25*192-1) 
			temp.image  = sin( (*(beta + n*PathNum + n_Path))*(*p_Time) + p_Phase[1]);    // beta=0-191 192-383 ... 24*192-(25*192-1) 
			
			CHtemp.real  = CHtemp.real+temp.real;
			CHtemp.image = CHtemp.image+temp.image;
		}
		
		p_IID_CHData[n_Path].real  = (CHtemp.real)/SQRT_N0;
		p_IID_CHData[n_Path].image = (CHtemp.image)/SQRT_N0;
	}
	
	//Add correlation for i.i.d channel data
	p_curCorrMatrix = p_CorrMatrix;
	for(n_Path=0; n_Path<PathNum; n_Path++) 
	{
		p_CHData[n_Path].real = 0;
		p_CHData[n_Path].image = 0;		
		for(n=0; n<PathNum; n++)
		{
			//p_CHData[n_Path].real  += p_CorrMatrix[n_Path*PathNum+n] * p_IID_CHData[n].real;
			//p_CHData[n_Path].image += p_CorrMatrix[n_Path*PathNum+n] * p_IID_CHData[n].image;
			p_CHData[n_Path].real  += p_curCorrMatrix[n] * p_IID_CHData[n].real;  // p_curCorrMatrix 是一维
			p_CHData[n_Path].image += p_curCorrMatrix[n] * p_IID_CHData[n].image;
		}
		p_curCorrMatrix += PathNum;         ///
	}
	free(p_IID_CHData);
	
	return n_Path;	
}

// intepolate for real, y = a*x.^2 + b*x + c
void dblBiInterp(double* p_IntpBegin, double* p_IntpMiddle, double* p_IntpEnd, int VecLen, double* p_Out, int n_OutLen, int BiInterpCoef)
{
	int i;
	int j;
	double a;
	double b;
	double c;
	
	for(i=0; i<VecLen; i++)
	{
		a =  2*p_IntpBegin[i] - 4*p_IntpMiddle[i] + 2*p_IntpEnd[i];
		b = -3*p_IntpBegin[i] + 4*p_IntpMiddle[i] -   p_IntpEnd[i];
		c =    p_IntpBegin[i];
		
		//for(j=0; j<BiInterpCoef; j++)
		for(j=0; j<n_OutLen; j++)
		{			
			//pp_Out[j][i] = a*j*j/BiInterpCoef/BiInterpCoef + b*j/BiInterpCoef + c;
			p_Out[j*VecLen+i] = a*j*j/BiInterpCoef/BiInterpCoef + b*j/BiInterpCoef + c;//  0-191 ... 192*255-192*256-1
		}
	}	
}

// intepolate for complex
void cmxBiInterp(COMPLEX* p_IntpBegin, COMPLEX* p_IntpMiddle, COMPLEX* p_IntpEnd, int VecLen, double* p_Out_real, double* p_Out_image, int n_OutLen, int BiInterpCoef)
{
	int i;
	
	double *p_IntpBegin_real;
	double *p_IntpBegin_image;
	double *p_IntpMiddle_real;
	double *p_IntpMiddle_image;
	double *p_IntpEnd_real;
	double *p_IntpEnd_image;
	
	p_IntpBegin_real   =  (double*)malloc(VecLen*sizeof(double));
	p_IntpBegin_image  =  (double*)malloc(VecLen*sizeof(double));
	p_IntpMiddle_real  =  (double*)malloc(VecLen*sizeof(double));
	p_IntpMiddle_image =  (double*)malloc(VecLen*sizeof(double));
	p_IntpEnd_real     =  (double*)malloc(VecLen*sizeof(double));
	p_IntpEnd_image    =  (double*)malloc(VecLen*sizeof(double));
	
	// get real part & image part of input vector
	for(i=0; i<VecLen; i++)
	{
		p_IntpBegin_real[i]		= p_IntpBegin[i].real;
		p_IntpBegin_image[i]	= p_IntpBegin[i].image;
		p_IntpMiddle_real[i]	= p_IntpMiddle[i].real;
		p_IntpMiddle_image[i]	= p_IntpMiddle[i].image;
		p_IntpEnd_real[i]		= p_IntpEnd[i].real;
		p_IntpEnd_image[i]		= p_IntpEnd[i].image;
	}
	
	// interpolation of real part & image part
	dblBiInterp(p_IntpBegin_real, p_IntpMiddle_real, p_IntpEnd_real, VecLen, p_Out_real, n_OutLen, BiInterpCoef);//?? why do so VecLen=TotalPathnum
	dblBiInterp(p_IntpBegin_image, p_IntpMiddle_image, p_IntpEnd_image, VecLen, p_Out_image, n_OutLen, BiInterpCoef);
	
	// free!
	free(p_IntpBegin_real);
	free(p_IntpBegin_image);
	free(p_IntpMiddle_real);
	free(p_IntpMiddle_image);
	free(p_IntpEnd_real);
	free(p_IntpEnd_image);

}

// pass through multiple path Rayleigh fading channel
void MIMO_Channel(double *p_txSignal_r, double *p_txSignal_i, int SigLenPerTx, int TxAntennaNum,
				  int RxAntennaNum, double *p_PathDelay, int maxDelay, int PathNum,
				  double *p_CorrMatrix, double fc, double speed, double Tc, 
				  double *p_Phase, double TimeBegin, double *p_rxSignal_r, double *p_rxSignal_i
				  )
{
	int i = 0;	
	int n_Sample= 0;
	int n_Rx	= 0;
	int n_Path	= 0;
	int n_Tx	= 0;
	int Index	= 0;		// index of transmit signal
	int n_rxSignal= 0;		// index of receive signal	
	int n_Segment = 0;		// index for segment
	
	int n = 0;
	int N0 = 25;
	int N = 4*N0;
	double Fd = speed*fc/(3.0e8)/3.6;	
	double Wd = 2*PI*Fd;
	double tt;
	double *alpha,*beta;
	double gamma;

	int tmpInterpCoef	= (int)(1.0/8.0/Fd/Tc);					// calculational interpolate factor ? 1.645714285714286e+004
	int InterpCoef		= (tmpInterpCoef > 128 ? 128:tmpInterpCoef);	// real interpolate factor
	int BiInterpCoef	= 2*InterpCoef;							// for bi_interpolation	
	int TotalPathNum	= RxAntennaNum*TxAntennaNum*PathNum;	// total path number
	int SegChDataLen	= TotalPathNum*BiInterpCoef;			// channel data number of one segment	 
	int txSigLen		= SigLenPerTx*TxAntennaNum;				// data number of all Txs
	int SampleLen		= SigLenPerTx + maxDelay;				// sample number
	int rxSigLen		= RxAntennaNum*SampleLen;				// data number of all Rxs
	int SegNum			= (SampleLen -1) / BiInterpCoef;					// segment number of interpolation
	int lastSegLen		= (SampleLen -1) % BiInterpCoef;				// last segment length for special process
	int lastSegChDataLen= TotalPathNum*(lastSegLen+1);

	COMPLEX *p_CHData;		// pointer to channel datas of one segment
	double  *p_CHData_r;	// real part of p_CHData
	double  *p_CHData_i;	// image part of p_CHData
	COMPLEX *p_curCHData;	// pointer to channel datas of current sample
	COMPLEX *p_txSignal;	// complex transmit signals
	COMPLEX  tmp;

	COMPLEX *p_IntpBegin;	// 1st sample channel datas of all paths for interpolation
	COMPLEX *p_IntpMiddle;	// 2nd sample channel datas of all paths for interpolation
	COMPLEX *p_IntpEnd;		// 3rd sample channel datas of all paths for interpolation
	COMPLEX *p_Tmp;	

	//for interpolate	
	p_IntpBegin = (COMPLEX*)malloc(TotalPathNum*sizeof(COMPLEX));
	p_IntpMiddle= (COMPLEX*)malloc(TotalPathNum*sizeof(COMPLEX));
	p_IntpEnd   = (COMPLEX*)malloc(TotalPathNum*sizeof(COMPLEX));
	
	p_CHData	= (COMPLEX*)malloc(SegChDataLen*sizeof(COMPLEX));
	p_CHData_r	= (double* )malloc(SegChDataLen*sizeof(double ));	
	p_CHData_i	= (double* )malloc(SegChDataLen*sizeof(double ));													
	p_txSignal	= (COMPLEX*)malloc(txSigLen*sizeof(COMPLEX));
	alpha		= (double* )malloc(N0*TotalPathNum*sizeof(double));
	beta		= (double* )malloc(N0*TotalPathNum*sizeof(double));

	// combine real & image part of transmit signal
	for(i=0; i<txSigLen; i++)
	{
		p_txSignal[i].real	= p_txSignal_r[i];
		p_txSignal[i].image = p_txSignal_i[i];
	}

	// generate alpha,beta for all samples
	for(n_Path=0; n_Path<TotalPathNum; n_Path++)	
	{
		for(n=0; n<N0; n++)
		{
			gamma = PI*( (double)2*n + (double)2*n_Path/TotalPathNum + (double)1/(2*TotalPathNum) )/N;// 0-191 192-383 ... 24*192-(25*192-1)
			alpha[n*TotalPathNum + n_Path] = Wd*cos(gamma);         ///M*N*L*N0=4800?
			beta[n*TotalPathNum + n_Path]  = Wd*sin(gamma);
		}
	}
	
	// tt = (1 + TimeBegin + 1e8)*Tc;
	tt = TimeBegin;
	
	//GenCurCHData(alpha,  beta, &tt, p_IntpBegin, TotalPathNum, p_Phase, p_CorrMatrix);
	GenCurCHData(alpha,  beta, &tt, p_IntpBegin, TotalPathNum, p_Phase, p_CorrMatrix);

	// front segments
	for(n_Segment=0; n_Segment<SegNum; n_Segment++)
	{
		tt += InterpCoef * Tc;		
		GenCurCHData(alpha,  beta, &tt, p_IntpMiddle, TotalPathNum, p_Phase, p_CorrMatrix);
		
		tt += InterpCoef * Tc;		
		GenCurCHData(alpha,  beta, &tt, p_IntpEnd, TotalPathNum, p_Phase, p_CorrMatrix);
			
		// compute channel datas for one segment
		cmxBiInterp(p_IntpBegin, p_IntpMiddle, p_IntpEnd, TotalPathNum, p_CHData_r, p_CHData_i, BiInterpCoef, BiInterpCoef);
		
		// combine real & image part of channel datas
		for(i=0; i<SegChDataLen; i++)
		{
			p_CHData[i].real  = p_CHData_r[i];    //p_CHData(192*256)
			p_CHData[i].image = p_CHData_i[i];
		}
		p_curCHData = p_CHData;

		// calculate receive signals of one segment
		for(n=0; n<BiInterpCoef; n++)
		{
			//n_Sample = n_Segment*BiInterpCoef + n;
			//p_curCHData = p_CHData+n*TotalPathNum;
			
			for(n_Rx=0; n_Rx<RxAntennaNum; n_Rx++)
			{
				tmp.real = 0;
				tmp.image = 0;
				for(n_Path=0; n_Path<PathNum; n_Path++)   // PathNum=6 
				{
					Index = n_Sample-(int)(p_PathDelay[n_Path]);
					
					if( Index>=0 &&	Index<SigLenPerTx)
					{
						for(n_Tx=0; n_Tx<TxAntennaNum; n_Tx++)
						{
							tmp = add_cmx( tmp, mul_cmx( p_txSignal[Index*TxAntennaNum+n_Tx],
								p_curCHData[(n_Path*TxAntennaNum+n_Tx)*RxAntennaNum+n_Rx] ) );    // p_curCHData : [(0 8 16 24) ... (160 168 176 184)] [(1 9 17 25)...]  .... tmp=tmp+s(n_Tx,Index)*cur(n_Rx+(n_Path*M+n_Tx)*RxAntennaNum) ?
						}    	
					}
				}
				p_rxSignal_r[n_rxSignal] = tmp.real;
				p_rxSignal_i[n_rxSignal] = tmp.image;
				
				// index of next receive signal
				n_rxSignal++;
			}
			// index of sample
			n_Sample++;
			// pointer to current sample
			p_curCHData += TotalPathNum;   //     p_curCHData(192*256)
		}	
		
		// replace pointer of p_IntpBegin & p_IntpEnd
		p_Tmp		= p_IntpBegin;
		p_IntpBegin = p_IntpEnd;
		p_IntpEnd	= p_Tmp;
	}

	// last senment
	if(lastSegLen)
	{
		tt += InterpCoef * Tc;
		GenCurCHData(alpha,  beta, &tt, p_IntpMiddle, TotalPathNum, p_Phase, p_CorrMatrix);
		
		tt += InterpCoef * Tc;
		GenCurCHData(alpha,  beta, &tt, p_IntpEnd, TotalPathNum, p_Phase, p_CorrMatrix);
			
		// compute channel datas for the last segment
		cmxBiInterp(p_IntpBegin, p_IntpMiddle, p_IntpEnd, TotalPathNum, p_CHData_r, p_CHData_i, lastSegLen+1, BiInterpCoef);
		
		// combine real & image part of channel datas
		for(i=0; i<lastSegChDataLen; i++)
		{
			p_CHData[i].real  = p_CHData_r[i];
			p_CHData[i].image = p_CHData_i[i];
		}
		p_curCHData = p_CHData;
		
		// calculate receive signals of one segment
		for(n=0; n<lastSegLen+1; n++)
		{
			//n_Sample = n_Segment*BiInterpCoef + n;
			//p_curCHData = n*TotalPathNum;

			for(n_Rx=0; n_Rx<RxAntennaNum; n_Rx++)
			{
				tmp.real = 0;
				tmp.image = 0;
				for(n_Path=0; n_Path<PathNum; n_Path++)     // PathNum=6 
				{
					Index = n_Sample-(int)(p_PathDelay[n_Path]);
					
					if( Index>=0 &&	Index<SigLenPerTx)
					{
						for(n_Tx=0; n_Tx<TxAntennaNum; n_Tx++)
						{
							tmp = add_cmx( tmp, mul_cmx( p_txSignal[Index*TxAntennaNum+n_Tx],
								p_curCHData[(n_Path*TxAntennaNum+n_Tx)*RxAntennaNum+n_Rx] ) );
						}    	
					}
				}
				p_rxSignal_r[n_rxSignal] = tmp.real;
				p_rxSignal_i[n_rxSignal] = tmp.image;

				// index of next receive signal
				n_rxSignal++;
			}
			// index of sample
			n_Sample++;		
			// pointer to current sample
			if(n<lastSegLen)
			{
				p_curCHData += TotalPathNum;
			}
		}
	}

	// for the last sample
	else
	{	
		// n_Sample = rxSigLen - 1;
		//p_curCHData = p_IntpBegin;	
		for(n_Rx=0; n_Rx<RxAntennaNum; n_Rx++)
		{
			tmp.real = tmp.image = 0;
			for(n_Path=0; n_Path<PathNum; n_Path++)
			{
				Index = n_Sample-(int)(p_PathDelay[n_Path]);
				
				if( Index>=0 &&	Index<SigLenPerTx)
				{
					for(n_Tx=0; n_Tx<TxAntennaNum; n_Tx++)
					{
						tmp = add_cmx( tmp, mul_cmx( p_txSignal[Index*TxAntennaNum+n_Tx],
							p_IntpBegin[(n_Path*TxAntennaNum+n_Tx)*RxAntennaNum+n_Rx] ) );
					}    	
				}
			}
			p_rxSignal_r[n_rxSignal] = tmp.real;
			p_rxSignal_i[n_rxSignal] = tmp.image;

			// index of next receive signal
			n_rxSignal++;
		}
	}

	free(p_CHData);
	free(p_CHData_r);
	free(p_CHData_i);
	free(p_txSignal);

	//free( (char *)alpha );
	//free( (char *)beta );
	free(alpha );
	free(beta );
	free(p_IntpBegin);
	free(p_IntpMiddle);
	free(p_IntpEnd);
}



void main()
{
	int i,j;
	int SigLenPerTx  = 1000;
	int TxAntennaNum = 2;
	int RxAntennaNum = 2;
	double PathDelay[2] = {0, 5};
	int maxDelay = 5;
	int SampleLen = SigLenPerTx+maxDelay;
	int PathNum  = 2;
	double fc = 3.5e9;
	double speed = 500;
	double Tc = 1/(1.28e6);
	double Phase[2] = {1.8, 0.8};
	double TimeBegin = Tc*1e8 + 1e5;
	FILE *fp1 = fopen("rx_r.dat", "w");
	FILE *fp2 = fopen("rx_i.dat", "w");
	
	double *p_CorrMatrix = (double*)malloc(64*sizeof(double));
	double *p_txSignal_r = (double*)malloc(TxAntennaNum*SigLenPerTx*sizeof(double));
	double *p_txSignal_i = (double*)malloc(TxAntennaNum*SigLenPerTx*sizeof(double));
	double *p_rxSignal_r = (double*)malloc(RxAntennaNum*SampleLen*sizeof(double));
	double *p_rxSignal_i = (double*)malloc(RxAntennaNum*SampleLen*sizeof(double));

	for(i=0; i<8; i++)
	{
		for(j=0; j<8; j++)
		{
			if(i==j)
				p_CorrMatrix[i*8+j] = 1.0;
			else 
				p_CorrMatrix[i*8+j] = 0.0;
		}
	}

	for(i=0; i<2000; i++)
	{
		p_txSignal_r[i] = 1.0;
		p_txSignal_i[i] = 1.0;
	}

	MIMO_Channel(p_txSignal_r, p_txSignal_i, SigLenPerTx, TxAntennaNum, RxAntennaNum, PathDelay, maxDelay,
					PathNum, p_CorrMatrix, fc, speed, Tc, Phase, TimeBegin, p_rxSignal_r, p_rxSignal_i);
	for(i=0; i<2010; i++)
	{
		fprintf(fp1, "%f\n", p_rxSignal_r[i]);
		fprintf(fp2, "%f\n", p_rxSignal_i[i]);
	}
	fclose(fp1);
	fclose(fp2);
	free(p_CorrMatrix);
	free(p_txSignal_r);
	free(p_txSignal_i);
	free(p_rxSignal_r);
	free(p_rxSignal_i); 
}

⌨️ 快捷键说明

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