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