📄 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<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 + -