📄 receiverclass.cpp
字号:
return(NULL);
}
SigPtr = SignalPtr;
FilterSigPtr = FilteredSignalPtr;
//perform filtering and decimation
loopstart=PulseLength-1;
FilterTmpPtr = FilterSigPtr;
SigPtr += loopstart;
for (k1=loopstart;k1<IncomingSignalLength;k1+=SamplesPerChip)
//We decimate by skipping samples of the incoming signal at an interval equal to the Samples Per Chip
{
TmpPtr = SigPtr;
PulseTmpPtr = PulseShape;
//The filtering process is a simple multiply and accumulate
for (k2=0;k2<PulseLength;k2++)
*FilterTmpPtr = ComplexAdd(*FilterTmpPtr,ComplexRealMultiply(*PulseTmpPtr++,*TmpPtr--));
FilterTmpPtr++;
SigPtr += SamplesPerChip;
}
return (FilteredSignalPtr);
}
void ReceiverClass::Descramble(ComplexNumber *FilteredSignalPtr,ComplexNumber *ScrambleCodePtr)
/***********************************************************************************************************
* ComplexNumber ReceiverClass::Descramble(ComplexNumber *FilteredSignalPtr,ComplexNumber *ScrambleCodePtr)
*
* Copyright 2002 The Mobile and Portable Radio Research Group
*
* This function descrambles the matched filtered and sampled received signal (i.e., the signal after
* it goes through the Filter routine in this class). This is accomplished by multplying the signal by
* the complex conjugate of the scrambled signal. The resultant signal is then stored in FilteredSignalPtr
*
* Parameters
* FilteredSignalPtr ComplexNumber * The received signal after it passes through the filter
* routine (Signal is fitered and sampled)
* This array also stores the descrambled signal
* ScrambleCodePtr ComplexNumber * The scramble code associated with the desired channel
************************************************************************************************************/
{
unsigned k; //loop counter
ComplexNumber *TempFilterPtr; //Temporary pointer to the incoming signal and scrambled signal (FilterSignalPtr)
ComplexNumber *TempScramblePtr; //Temporary pointer to the scrambling sequence
ComplexNumber Conj; //Stores the conjugate of the signal value
//Assign temporary pointers
TempFilterPtr = FilteredSignalPtr;
TempScramblePtr = ScrambleCodePtr;
//Perform the descrambling operation
for (k=0; k<CHIPS_PER_FRAME; k++)
{
Conj = *TempScramblePtr++;
Conj.imaginary = -Conj.imaginary;
*TempFilterPtr++ = ComplexMultiply(*TempFilterPtr,Conj);
}
}
double * ReceiverClass::GeneratePulseShape()
/******************************************************************************************
/ void GenRootRaisedCosine(int LowerBoundT, int UpperBoundT,unsigned SamplesPerChip,
/ double RollOff,double SymbolPeriod,double *filter,double *t_index,unsigned PulseLength)
/
/ Copyright 2002 The Mobile and Portable Radio Research Group
/
/ GenRootRaisedCosine produces the impulse response of a root raised cosine filter and
/ stores it in an array. Note that the impulse of a root raised cosine filter ranges
/ from -infinity to infinity. It is therefore necessary to truncated from LowerBoundT to
/ UperBountT.
/
/
/******************************************************************************************/
{
double *filter;
double *t_index;
double *filter_temp,*t_temp; //Temporary pointers for *filter and *t_index
double cos_arg; //Stores arguement to cosine funciton
double sin_arg; //Stores arguement to sine function
double bottom_arg; //Stores non-trivial term in the denominator
double coeff; //Stores the normalizing coefficient
double SampleDuration; //Stores the sample period
double SymbolPeriod=1;
int k; //Counter
//Determine Array length
PulseLength = (UpperBoundT-LowerBoundT)*SamplesPerChip+1;
//Allocate space for filter
filter = (double *) calloc(PulseLength,sizeof(double));
t_index = (double *) calloc(PulseLength,sizeof(double));
//Compute impulse response
SampleDuration = SymbolPeriod/SamplesPerChip;
coeff = (4.0 * Rolloff * sqrt(SampleDuration)) / (PI * sqrt(SymbolPeriod));
t_temp=t_index;
filter_temp=filter;
for (k=0; k< (int) PulseLength;k++)
{
//Compute time index
*t_temp=(LowerBoundT * SymbolPeriod) + (k * SampleDuration);
if (*t_temp == double (0.0)) *t_temp = 1e-20;
cos_arg = (1 + Rolloff) * (PI * *t_temp / SymbolPeriod);
sin_arg = (1 - Rolloff) * (PI * *t_temp / SymbolPeriod);
bottom_arg = (double) 4.0 * Rolloff * *t_temp / SymbolPeriod;
t_temp++;
*filter_temp++ = coeff * (cos(cos_arg) + (sin(sin_arg) / bottom_arg)) / (1 - (bottom_arg * bottom_arg));
}
free(t_index);
return(filter);
}
ComplexNumber * ReceiverClass::DespreadFrame(DPCH_FormatStructure Format,
ComplexNumber *DescrambledSignal)
/************************************************************************************
* ComplexNumber * ReceiverClass::DespreadFrame(DPCH_FormatStructure DPCH_format
* ComplexNumber *DescrambledSignal)
*
* Copyright 2002 The Mobile and Portable Radio Research Group
*
* This function takes the descrambled chips from a particular frame and despreads it
*
* Returns A pointer to a ComplexNumber array that contains the despreaded symbols.
* Note that these symbols will still contains noise, attenuations, and phase
* shifts associated with the channel variations
*
* Parameters
* Format DPCH_FormatStructure Format information of the frame of interest
* DescrambledSignal ComplexNumber * Incoming Signal (Filtered and Descrambled)
*
*************************************************************************************/
{
unsigned SF; //Spreading factor
unsigned SymbolsPerFrame; //Number of symbols in a given frame
unsigned k,j; //Loop counters
ComplexNumber *DespreadSignal,*TempDespreadSignal; //Pointer and temporary pointer to the
//array that contains the despread symbol
ComplexNumber *TempDescrambledSignal; //Temporary pointer to the array that contains the
//scambling sequenc
int *TempChanCodePtr; //Temporary pointer to the array that contains the
//channelization code
//Get the spreading factor
SF = Format.SF;
//Determine the number of symbols in a given frame (for the desired channel)
SymbolsPerFrame = (Format.BitsPerSlot*Format.ActualSlotsPerFrame >> 1);
//Allocated memory for the despread signal array
DespreadSignal = (ComplexNumber *) calloc(SymbolsPerFrame,sizeof(ComplexNumber));
if (DespreadSignal == NULL)
{
printf("\nMemory allocation failed for DespreadSignal--exiting\n");
return(NULL);
}
//Assign temporary pointers
TempDespreadSignal = DespreadSignal;
TempDescrambledSignal = DescrambledSignal;
TempChanCodePtr = ChannelCode;
//Perform despreading operation
for (k=0; k<SymbolsPerFrame; k++)
{
TempChanCodePtr = ChannelCode;
for (j=0; j<SF; j++)
*TempDespreadSignal = ComplexAdd(*TempDespreadSignal,
ComplexRealMultiply((double) *TempChanCodePtr++,*TempDescrambledSignal++));
TempDespreadSignal++;
}
return(DespreadSignal);
}
ComplexNumber * ReceiverClass::ChannelEstimator(DPCH_FormatStructure Format,ComplexNumber *DespreadSignal)
/*****************************************************************************************
ComplexNumber * ReceiverClass::ChannelEstimator(DPCH_FormatStructure Format,ComplexNumber *DespreadSignal)
*
* Copyright 2002 The Mobile and Portable Radio Research Group
*
* This function estimates the complex channel gain on a slot-by-slot basis. Specifically
* the function uses the pilot symbols of each slot to estimate the channel. This is done
* by taking the despread symbols in the Pilot symbol field of each slot and dividing
* those values agains the pilot symbols, which are known a priori. The resulting ratio
* is the channel estimate for that symbol. The channel estimate for a given slot is then
* obtained by computing the average estimate over all of the pilot symbol locations in
* the slot
*
* Returns a ComplexNumber orray with the channel estimates
*
* Parameters
* Format DPCH_FormatStructure Contains the format information of the desired frame
* DespreadSignal ComplexNumber * Contains the despread symbol values
*******************************************************************************************/
{
//**************************************************************************************
//Declare and define pilot symbols
const ComplexNumber Npilot2[15]= {{-1,-1},
{1,1},
{1,-1},
{1,1},
{-1,1},
{-1,-1},
{-1,-1},
{-1,1},
{1,-1},
{-1,-1},
{1,-1},
{-1,1},
{-1,1},
{1,1},
{1,1}};
const ComplexNumber Npilot4[30]= {{-1,-1},{-1,-1},
{-1,-1},{1,1},
{-1,-1},{1,-1},
{-1,-1},{1,1},
{-1,-1},{-1,1},
{-1,-1},{-1,-1},
{-1,-1},{-1,-1},
{-1,-1},{-1,1},
{-1,-1},{1,-1},
{-1,-1},{-1,-1},
{-1,-1},{1,-1},
{-1,-1},{-1,1},
{-1,-1},{-1,1},
{-1,-1},{1,1},
{-1,-1},{1,1}};
const ComplexNumber Npilot8[60]= {{-1,-1},{-1,-1},{-1,-1},{-1,1},
{-1,-1},{1,1},{-1,-1},{-1,1},
{-1,-1},{1,-1},{-1,-1},{1,-1},
{-1,-1},{1,1},{-1,-1},{1,1},
{-1,-1},{-1,1},{-1,-1},{1,-1},
{-1,-1},{-1,-1},{-1,-1},{-1,1},
{-1,-1},{-1,-1},{-1,-1},{1,1},
{-1,-1},{-1,1},{-1,-1},{1,1},
{-1,-1},{1,-1},{-1,-1},{-1,1},
{-1,-1},{-1,-1},{-1,-1},{-1,-1},
{-1,-1},{1,-1},{-1,-1},{1,-1},
{-1,-1},{-1,1},{-1,-1},{-1,-1},
{-1,-1},{-1,1},{-1,-1},{1,1},
{-1,-1},{1,1},{-1,-1},{-1,-1},
{-1,-1},{1,1},{-1,-1},{-1,-1}};
const ComplexNumber Npilot16[120]= {{-1,-1},{-1,-1},{-1,-1},{-1,1},{-1,-1},{-1,-1},{-1,-1},{-1,1},
{-1,-1},{1,1},{-1,-1},{-1,1},{-1,-1},{-1,-1},{-1,-1},{1,1},
{-1,-1},{1,-1},{-1,-1},{1,-1},{-1,-1},{-1,1},{-1,-1},{1,1},
{-1,-1},{1,1},{-1,-1},{1,1},{-1,-1},{1,-1},{-1,-1},{-1,1},
{-1,-1},{-1,1},{-1,-1},{1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},
{-1,-1},{-1,-1},{-1,-1},{-1,1},{-1,-1},{1,-1},{-1,-1},{1,-1},
{-1,-1},{-1,-1},{-1,-1},{1,1},{-1,-1},{-1,1},{-1,-1},{-1,-1},
{-1,-1},{-1,1},{-1,-1},{1,1},{-1,-1},{-1,1},{-1,-1},{1,1},
{-1,-1},{1,-1},{-1,-1},{-1,1},{-1,-1},{1,1},{-1,-1},{-1,-1},
{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{1,1},{-1,-1},{-1,-1},
{-1,-1},{1,-1},{-1,-1},{1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,1},
{-1,-1},{-1,1},{-1,-1},{-1,-1},{-1,-1},{1,1},{-1,-1},{-1,1},
{-1,-1},{-1,1},{-1,-1},{1,1},{-1,-1},{1,-1},{-1,-1},{1,-1},
{-1,-1},{1,1},{-1,-1},{-1,-1},{-1,-1},{1,1},{-1,-1},{1,1},
{-1,-1},{1,1},{-1,-1},{-1,-1},{-1,-1},{-1,1},{-1,-1},{1,-1}};
//Pilot symbols defined and declared
//**************************************************************************************
ComplexNumber *PilotPtr,*TempPilotPtr; //Pointer and temporary pointer to the array
//that contains the selected pilot symbols
unsigned SF; //Spreading factor
unsigned NumPilotSymbols; //Number of pilot symbols
ComplexNumber *ChannelEstimatePtr,*TempChannelEstimatePtr; //Pointer and temporary pointer
//to the array that contains the
//channel estimates
ComplexNumber *TempDespreadSignalPtr; //Temporary pointer to the array that contains the
//Despread symbol sequence
unsigned PilotPositionInSlot; //Tracks the location of the first pilot symbol
//in any given slot
unsigned SlotsPerFrame; //The number of slots in any give frame
ComplexNumber CurrentEstimate; //Stores the current channel estimate
unsigned j,k; //Loop counters
SF = Format.SF;
NumPilotSymbols = (Format.NPilot >> 1);
PilotPositionInSlot = (Format.BitsPerSlot >> 1) - NumPilotSymbols;
SlotsPerFrame = Format.ActualSlotsPerFrame;
//Get the correct Pilot Symbols
switch (Format.NPilot)
{
case 2:
PilotPtr = (ComplexNumber *) Npilot2;
break;
case 4:
PilotPtr = (ComplexNumber *) Npilot4;
break;
case 8:
PilotPtr = (ComplexNumber *) Npilot8;
break;
case 16:
PilotPtr = (ComplexNumber *) Npilot16;
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -