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

📄 hannelclass.cpp

📁 用matlab程序实现WCDMA系统的仿真
💻 CPP
📖 第 1 页 / 共 3 页
字号:
 // 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<MultiPathComponents; k++)
	{
		//Compute the delay for the k_th multipath component in terms of samples
		TempDelay = *UIDelayPtr++ * fsample;
		if (modf(TempDelay,&IntegerPortion) >= 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<FADE_SIGNAL_LENGTH; j++) *TempFadePtr++ = ComplexRealMultiply(*AmplitudePtr,*TempFadePtr);
		AmplitudePtr++;
	}
	FadingSignalOffset = 0;  //This is an initialization value
	FadeInitFlag = true;
	FadeSamplesPerFrame = CHIPS_PER_FRAME / CHIPS_PER_FADE_SAMPLES;

	fsample = UniformRandomNumberGenerator(&InitializationFlag); //Initialize the random number generator
}

ChannelClass::~ChannelClass()
/*******************************************************************************************
/ Copyright 2002 The Mobile and Portable Radio Research Group
/
/ Destructor for the objects of type ChannelClass
*******************************************************************************************/
{
	unsigned k;
	for (k=0; k<MultiPathComponents; k++)
	{
		if ( *(FadingSignals + k) != NULL )
		{
			free( *(FadingSignals + k) );
			*(FadingSignals + k) = NULL;
		}
	}
	if (FadingSignals != NULL) 
	{
		free(FadingSignals);
		FadingSignals = NULL;
	}

	if (MultipathSignal != NULL)
	{
		free(MultipathSignal);
		MultipathSignal = NULL;
	}

	//These pointers point to arrays that were allocated elsewhere
	Amplitudes = NULL;
	Delays = NULL;

}

double ChannelClass::UniformRandomNumberGenerator(int *idum)
/*******************************************************************************************
* double UniformRandomNumberGenerator(int *idum)
*
* A random number generator that produces a random number between 0 and 1 
*
* Returns	A double value between 0 and 1
*
*Parameters
*	Input
*		idum int *	Reinitializes the random number sequence if the contents is set 
*					to a negative value
*******************************************************************************************/
{
	static double y,maxran,v[98];
	double dum;
	static int iff=0;
	int j;
	unsigned i;

	if (*idum < 0 || iff == 0)	//If the contents of the arguement is negative
	{							//Then reset the seed
		iff=1;
		i=2;
		maxran = RAND_MAX+1;
//		srand(1);
		srand( (unsigned)time( NULL ) );
		*idum=1;
		for (j=1; j <= 97; j++) dum = rand();
		for (j=1; j <= 97; j++) v[j] = rand();
		y=rand();
	}
	//Otherwise, generate the random number
	j = 1 + 97.0 * y / maxran;
	if (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<NSamples; k++) *TempFadingSigPtr++ = One;
		return (FadingSigPtr);
	}

	// If we are here, then the Doppler is large enough to cause a fade during the sample record

	// Compute the unormalized, adjusted Doppler shift
	FDopplerAdjusted = (double) kd * deltaF;

	//Compute the Doppler Power Spetral Density.
	//This will be stored in the array DopplerPSDPtr
	DopplerPSDPtr = (double *) calloc(kd + 1, sizeof(double));
	if (DopplerPSDPtr == NULL)
	{
		printf("\nMemory allocation failed for DopplerPSDPtr--exiting\n");
		return(NULL);
	}

⌨️ 快捷键说明

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