www.pudn.com > WCDMA.rar > hannelClass.cpp


 // hannelClass.cpp: implementation of the ChannelClass class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "hannelClass.h" 
#include "stdio.h" 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
ChannelClass::ChannelClass() 
{ 
 
} 
 
ChannelClass::ChannelClass(SimConfigClass Config, ModulatorClass *Modulator, TransmitterClass *Tx) 
/*********************************************************************************************** 
/ChannelClass::ChannelClass(SimConfigClass Config, ModulatorClass *Modulator, TransmitterClass *Tx) 
/ 
/ Copyright 2002 The Mobile and Portable Radio Research Group 
/ 
/This constructor performs the following tasks 
/ 
/	1.  Determines the noise variance 
/	2.  Sets up the multipath delay vector (vector specifies the delay in terms of  
/	    number of samples) 
/	3.  Sets up the multipath amplitude vector 
/	4.  Generates fading signal for each multipath component 
/ 
/Parameters	 
/	Config		SimConfigClass		Contains simulation configuration e.g., the multipath delay 
/									profile, EbNo (in decibels), and the fading rate 
/	Modulator	ModulatorClass *	Contains the pulse shape length and the oversampling rate 
/	Tx			TransmitterClass *	Contains the spreading factor of the desired channel (needed to 
/									determine the noise variance 
***********************************************************************************************/ 
{ 
	double fsample;		//Sampling Frequence 
	unsigned k,j;		//Loop counters 
	double *UIDelayPtr;	//Points the array of delays stored in the input parameter, Config 
	double TempDelay;	//Computes the value of delay in terms of number of sampeld 
	double IntegerPortion;	//Temporary variable used for rounding 
	unsigned *DelayPtr;		//Temporary pointer to the delays stored in this constructed channel object 
	double *AmplitudePtr;	//Temporary pointer to the delays stored in this constructed channel object 
	double *UIAmplitudePtr;	//Temporary pointer to the amplitude array stored in the input parameter, Config 
	ComplexNumber **TempFadingSignalsPtr;	//Temporary pointer to the collection of arrays that stores the 
											//fading signals 
	ComplexNumber *TempFadePtr;	//Temporary pointer to the fading signals 
	unsigned SF;				//Spreading factor 
	int	InitializationFlag = -1;	//Initialization flag for the random number generator 
 
	//Determine the noise variance 
	EbNo_dB = Config.EbNo_dB; 
	EbNo = pow(10.00,EbNo_dB / 10.00); 
	SF = Tx->TxConfiguration.DesiredDPCHformat.SF; 
	NoiseSTDV = sqrt( (double) SF * 2.0 / (EbNo) ); 
 
	//Store the samples per chip 
	SamplesPerChip = Modulator->SamplesPerChip; 
	//Store the pulse length 
	PulseLength = Modulator->PulseLength; 
 
	// Determine the Doppler Spread 
	fDoppler = (Config.Velocity*5/18)/(SPEED_OF_LIGHT/(FREQUENCY*1e6)); 
	MultiPathComponents = Config.MPathComponents; 
 
	//Allocated arrays for the multipath delays and amplitudes 
	Delays = (unsigned *) calloc(MultiPathComponents,sizeof(unsigned)); 
	if (Delays == NULL) 
	{ 
		printf("Memory allocation for Delays failed--exiting\n"); 
		return; 
	} 
 
	Amplitudes= (double *) calloc(MultiPathComponents,sizeof(double)); 
	if (Delays == NULL) 
	{ 
		printf("Memory allocation for Delays failed--exiting\n"); 
		return; 
	} 
 
	//Allocated an array of points.  The k^th element of this array will point to the  
	//fading signal associated with the k^th multipath component 
	FadingSignals = (ComplexNumber **) calloc(MultiPathComponents,sizeof(ComplexNumber *)); 
	if (FadingSignals == NULL) 
	{ 
		printf("Memory allocation for FadingSignals failed--exiting\n"); 
		return; 
	} 
 
	//Compute the delay of each component in terms of signal samples 
	//Compute the "linear" amplitude of each component 
	//Generate a fading signal for each component 
	fsample = SamplesPerChip*CHIPS_PER_FRAME/FRAME_DURATION; 
	DelayPtr = Delays; 
	UIDelayPtr = Config.Delays; 
	AmplitudePtr = Amplitudes; 
	UIAmplitudePtr = Config.Amplitudes; 
	TempFadingSignalsPtr = FadingSignals; 
	for (k=0; k= 0.5) *DelayPtr++ = (unsigned) IntegerPortion + 1.00; 
		else *DelayPtr++ = (unsigned) IntegerPortion; 
		//Compute the amplitude of each multipath component 
		*AmplitudePtr = pow(10.000, *UIAmplitudePtr++ / 20.000); 
		//Generate the fading signal for each multipath components 
		*TempFadingSignalsPtr = RaylieghFadingGenerator(fDoppler,FADE_SAMPLE_RATE,FADE_SIGNAL_LENGTH); 
		//Scale the fading signal by the amplitude vaule computed in this loop 
		TempFadePtr = *TempFadingSignalsPtr++; 
		for (j=0; j 97 || j < 1)  
	{ 
		printf("\nj = %d.  This should not have happened!\n",j); 
		printf("j should have been between 1 and 97\n"); 
		return(-1); 
	} 
	y=v[j]; 
	v[j]=rand(); 
	return(y/maxran); 
} 
 
 
ComplexNumber ChannelClass::GaussianRandomNumberGenerator(int *InitFlag) 
/******************************************************************************** 
* ComplexNumber GaussianRandomNumberGenerator(int InitFlag) 
* 
* Copyright 2002 The Mobile and Portable Radio Research Group 
* 
* A ranodm number generator that returns a random number that conforms to a  
* complex Gaussian Distribution where both the real and imaginary parts have a  
* mean of 0 and a variance of 1 
* 
* This function makes use of the UniformRandomNumberGenerator() function 
* 
* Returns 
*   A random number of type ComplexNumber 
* 
* Parameters 
*   Input 
*      InitFlag		int		Reinitializes the UniformRandomNumberGenerator if  
*							InitFlag is negative.  Otherwise does nothing 
*********************************************************************************/ 
{ 
	double fac,r,v1,v2; 
	ComplexNumber sam; 
 
	do 
	{ 
		v1 = 2.0 * UniformRandomNumberGenerator(InitFlag) - 1.0; 
		v2 = 2.0 * UniformRandomNumberGenerator(InitFlag) - 1.0; 
		r = v1*v1 + v2*v2; 
	} 
	while (r >= 1.0); 
 
	fac = sqrt( -2.0 * log(r) / r); 
	sam.real = v1 * fac / ROOT2; 
	sam.imaginary = v2 * fac / ROOT2; 
 
	return(sam); 
} 
 
ComplexNumber * ChannelClass::RaylieghFadingGenerator( double FDoppler, double FSample, unsigned long NSamples) 
/****************************************************************************************** 
* ComplexNumber *RaylieghFadingGenerator( double FDoppler, double FSample, unsigned long NSamples) 
* 
* Copyright 2002 The Mobile and Portable Radio Research Group 
* 
* Computes a complex valued, Rayliegh fading signal, which has the classical specturm. 
* The frequence spread of this signal is determiend by the Doppler frequency.  The 
* length of this signal is determined by NSamples 
* 
* Returns a ComplexNumber type array of length NSamples that contains the fading signal 
* 
* Parameters 
*	FDoppler	double			The Doppler frequency (or Doppler Spread) 
*	FSample		double			The sampling rate 
*	NSamples	unsigned long	The desired length of the output array 
******************************************************************************************/ 
{ 
	unsigned PolyFitLength = 4;  //Extrapolate the last point via a polynomial of degree 3  
								// this requires data and abcissa arrays of length 4 
	unsigned N;		//Size of FFT used in computation 
	unsigned kd;	//Doppler spread, normalized to sample rate 
	unsigned k;		//Loop counter 
	int InitFlag = 1;	//Initialization flag used for random number generator 
	double deltaF;		//Frequency spacing for the given sample rate and FFT size 
	double FDopplerAdjusted;	//Adjusted value of the doppler frequency = deltaF*kd 
	double log2 = log(2.0);		//The natural log of 2.0 
	double *DopplerPSDPtr,*TempDopplerPSDPtr;	//Pointer and temporary pointer to the array 
												//Containing the doppler spectrum 
	double abcissa[5],*OrdinatePtr;				//Used for polynomial interpolation 
	double error;								//Stores the error associated withthe polynomial interpolation 
	double Energy;								//Stores teh eneraty of the fading signal 
	double InvAmplitude;						//Reciprocal of the square root of the energy in teh fading signal 
	ComplexNumber *FadingSigPtr,*TempFadingSigPtr;	//Pointer and temporary pointer to the fading signal 
	ComplexNumber *FadingSpectrumPtr,*TempFadingSpectrumPtr;	//Pointer and temporary pointer to the spectrum 
																//of the fading signal (the spectrum is used to  
																//compute the signal) 
	ComplexNumber *IFFToutputPtr,*TempIFFToutputPtr;	//Pointer and temporary pointer to the result of the IFFT 
	ComplexNumber One = {1,0}; 
 
	FadingSigPtr = (ComplexNumber *) calloc(NSamples,sizeof(ComplexNumber)); 
	if (FadingSigPtr == NULL) 
	{ 
		printf("\nMemory allocation failed for FadingSigPtr--exiting\n"); 
		return(NULL); 
	} 
 
	//Create a longer duration of fading envlope than needed in order to have 
	//a spectrum that is a power of two.  This will allow use to take advantage 
	//of FFTs 
	deltaF = ceil( log( (double) NSamples) / log2); 
	N = (unsigned) pow(2.000, deltaF); 
 
	//Set the frequency spacing for the required sampling rate 
	deltaF = FSample / (double) N; 
 
	//Compute the normalized Doppler spread (normalized to the sample rate) 
	//Adjust it so that it is an integer value 
	kd = (unsigned) ceil( FDoppler / deltaF); 
 
	// If the Doppler spread is very small (i.e., if kd < PolyFitLength) then the  
	// fading envelope will be essentially constant.  So return an array of  
	// {1,1}'s 
	if (kd < PolyFitLength) 
	{ 
		TempFadingSigPtr = FadingSigPtr; 
		for (k=0; k> 1; 
	FrameEnd = FrameBegin - 1 + FrameSampleLength ; 
	FadeSamplesPerFrame = CHIPS_PER_FRAME / CHIPS_PER_FADE_SAMPLES; 
 
 
	/****************************************************************** 
	/* Create a combined Signal which contains the previous frame the  
	/* current frame and the future frame 
	*/ 
	NCombinedSig = SignalLength + SignalLength + SignalLength - 2*(PulseLength - SamplesPerChip); 
	CombinedSigPtr = (ComplexNumber*) calloc(NCombinedSig,sizeof(ComplexNumber)); 
	if (CombinedSigPtr  == NULL) 
	{ 
		printf("\nMemory Allocation failed for CombinedSigPtr\n"); 
		return(NULL); 
	} 
 
	TempCombinedSigPtr = CombinedSigPtr; 
	TempSigLastptr = SigLastptr; 
	LoopStop = SignalLength - PulseLength + SamplesPerChip; 
	for (i=0; i MaxDelay) MaxDelay = *TempDelaysPtr++; 
		else TempDelaysPtr++; 
	} 
	//Maximum delay found 
	/******************************************************************/ 
	//Now allocate space for the multipath signal 
	NMpathSignal = SignalLength + MaxDelay; 
	MultipathSignalLength = NMpathSignal; 
	MpathSignalptr = (ComplexNumber *) calloc(NMpathSignal,sizeof(ComplexNumber)); 
	if (MpathSignalptr  == NULL) 
	{ 
		printf("\nMemory Allocation failed for MpathSignalptr\n"); 
		return(NULL); 
	} 
 
	increment = (double) FrameSampleLength / (double) AmplitudeLength; //Abcissa increment between data points 
	Increment = (unsigned long) increment; 
//	RemainingSamples = NMpathSignal % Increment; 
															 
	TempDelaysPtr = Delays; 
	for (i=0;ireal,TempMpathSignalptr->imaginary); 
			TempMpathSignalptr++; 
		} 
		fclose(fp); 
 
		fp = fopen("FadeSig.txt","w"); 
		faa = TempFadeptr - AmpBeginPtr + 1; 
		for (k=0; kreal,(AmpBeginPtr+k)->imaginary); 
		fclose(fp); 
		/*******************************************************/ 
 
	} 
	 
	free(CombinedSigPtr); 
	return(MpathSignalptr); 
} 
 
 
 
double ChannelClass::PolynomialFit(double *Xdata,double *Ydata,unsigned N,double x,double *error) 
/****************************************************************************************** 
* double PolynomialFit(double *Xdata,double *Ydata,unsigned N,double x,double *error) 
* 
* 
* Copyright 2002 The Mobile and Portable Radio Research Group 
* 
* Given the abcissa data Xdata and the ordinate data Ydata (each of length N), PolynomialFit 
* estimates the ordinate associcated with the abcissa "x" by fitting the data to a  
* polynomial of degree N-1 
* 
* Returns a double which is an estimate of the ordinate associated with the abcissa, x. 
* 
* Parameters 
*	Input 
*		Xdata	double *	Pointer to the abcissa data 
*		Ydata	double *	Pointer to the ordinate data 
*		N		unsigned	Length of Xdata and Ydata.  N-1 is also the degree of the polynomial 
*		x		double		abcissa value of interest 
*	Output 
*		dy		double *	Pointer to the variable that stores the error indication 
* 
* NOTE:  Algorithm was found in Numerical Recipies in C 
*******************************************************************************************/ 
{ 
	unsigned i,m,ns=1; 
	double den,dif,dift,ho,hp,w; 
	double *c,*d; 
	double *cTemp,*dTemp; 
	double *TempXdata,*TempXdata1,*TempYdata; 
	double y; 
 
	TempXdata = Xdata; 
	TempYdata = Ydata; 
 
	dif = fabs(x - *TempXdata); 
 
	c = (double *) calloc(N,sizeof(double)); 
	if (c == NULL) 
	{ 
		printf("Memory allocation for pointer c failed--exiting\n"); 
		return(-1); 
	} 
 
	d = (double *) calloc(N,sizeof(double)); 
	if (d == NULL) 
	{ 
		printf("Memory allocation for pointer d failed--exiting\n"); 
		return(-1); 
	} 
 
	cTemp = c; 
	dTemp = d; 
	TempYdata = Ydata; 
	for (i=0; i j )  
		{ 
			SWAP( *(TempResultPtr + j), *(TempResultPtr + i) ); 
		} 
 
		m = n >> 1; 
		while ( m >= 1 && j >= m)  //modification to code--may not be correct 
		{ 
			j -= m; 
			m >>= 1; 
		} 
		j += m; 
	} 
 
	mmax = 1; 
	while (n > mmax) 
	{ 
		istep = 2*mmax; 
		theta = 6.28318530717959 / (isign * 2.0 * mmax); 
		wtemp = sin(0.5*theta); 
		wp.real= -2.0*wtemp*wtemp; 
		wp.imaginary = sin(theta); 
		w.real = 1.0; 
		w.imaginary = 0.0; 
		for (m=0; mreal - w.imaginary * (ResultPtr + j)->imaginary; 
				temp.imaginary = w.real * (ResultPtr+j)->imaginary + w.imaginary * (ResultPtr +j)->real; 
				*(ResultPtr+j) = ComplexSubtract( *(ResultPtr+i), temp); 
				*(ResultPtr + i) = ComplexAdd( *(ResultPtr + i),temp); 
			} 
			w.real = (wtemp=w.real)*wp.real - w.imaginary*wp.imaginary + w.real; 
			w.imaginary = w.imaginary * wp.real + wtemp*wp.imaginary + w.imaginary; 
		} 
		mmax = istep; 
	} 
	return(ResultPtr); 
} 
			 
				 
 
 
void ChannelClass::FadingProcessor() 
/********************************************************************************************* 
	// Copyright 2002 The Mobile and Portable Radio Research Group 
	// 
	//Selects the fading signal.  The fading signal for each multipath component 
	//is identified by a pointer that is stored in an array of pointers.  Each fading  
	//signal covers a large number of frames (over 100), and 96 fading samples corresponds 
	//to one 10ms fade duration.  Each time this function is called 3*96 fade sampels  
	//are needed: one group of 96 for the preveious frame, one group of 96 for the  
	//current frame, and one group of 96 for the next frame. Once the channel is  
	//processed, the previous frame (and the fading associated with that frame) is  
	//no longer needed.   
*********************************************************************************************/ 
{ 
	unsigned k,j;				//Loop coutners 
	ComplexNumber *TempFadePtr;	//Temporary pointer to the fading signal 
	double *AmplitudePtr;		//Temporary pointer to the membor array that contains  
								//the fading amplitudes 
 
	if (FadeInitFlag)  //If this is the first time that the function is called 
	{							 //Then a new fading signal was constrcuted in the constructor 
		FadingSignalOffset = 0;	 //So just set the offset to 0 and return 
		FadeInitFlag = false; 
		return; 
	} 
 
	FadingSignalOffset += FadeSamplesPerFrame; 
 
	if ( (FADE_SIGNAL_LENGTH - FadingSignalOffset) < (3*FadeSamplesPerFrame) ) 
	{ 
		// Free current fading signals 
		for (k=0; kreal,TempMultipathSignal->imaginary); 
//		TempMultipathSignal++; 
//	} 
 
	TempMultipathSignal = MultipathSignal; 
	for (k=0; k