📄 modulatorclass.cpp
字号:
// ModulatorClass.cpp: implementation of the ModulatorClass class.
//
//Copyright 2002 The Mobile and Portable Radio Research Group
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ModulatorClass.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
ModulatorClass::ModulatorClass()
{
}
ModulatorClass::ModulatorClass(SimConfigClass Config)
/****************************************************************************************
/ModulatorClass::ModulatorClass(SimConfigClass Config)
/
/ Copyright 2002 The Mobile and Portable Radio Research Group
/
/Constructs an object of type ModulatorClass. This function initalizes and sets member
/variables that are necessary for configuring the object. These include UpperBoundT and
/LowerBoundT, which is used to determine the duration fo the pulse shape; SamplesPerChip,
/which determines the oversampling rate; and SamplesPerFrame. The function also computes
/and stores the pulse shape
*****************************************************************************************/
{
UpperBoundT = Config.PulseLength >> 1; //Store the upper extent of the pulse
LowerBoundT = - (int) Config.PulseLength >> 1; //Store the lower extent of the pulse
SamplesPerChip = Config.SamplesPerChip; //Store the oversampling rate
SamplesPerFrame = CHIPS_PER_FRAME * SamplesPerChip; //The number of samples that makes up a radio frame
RollOff = 0.22; //The Rolloff factor is fixed at 0.22
PulseLength = (UpperBoundT-LowerBoundT)*SamplesPerChip+1; //Determine and store the pulse length
PulseShape = GeneratePulseShape(); //Compute and store the pulse shape
CurSignal1 = NULL;
CurSignal2 = NULL;
NextSignal1 = NULL;
NextSignal2 = NULL;
PrevSignal1 = NULL;
PrevSignal2 = NULL;
}
ModulatorClass::~ModulatorClass()
/****************************************************************************************
/ModulatorClass::~ModulatorClass()
/
/ Copyright 2002 The Mobile and Portable Radio Research Group
/
/This function deystroys an object of type ModulatorClass. This function simply frees
/the memory that was allocated to store the pulse shape
*****************************************************************************************/
{
free(PulseShape);
PulseShape = NULL;
if (CurSignal1 != NULL)
{
free(CurSignal1);
CurSignal1 = NULL;
}
if (PrevSignal1 != NULL)
{
free(PrevSignal1);
PrevSignal1 = NULL;
}
if (NextSignal1 != NULL)
{
free(NextSignal1);
NextSignal1 = NULL;
}
if (CurSignal2 != NULL)
{
free(CurSignal2);
CurSignal2 = NULL;
}
if (PrevSignal2 != NULL)
{
free(PrevSignal2);
PrevSignal2 = NULL;
}
if (NextSignal2 != NULL)
{
free(NextSignal2);
NextSignal2 = NULL;
}
}
double * ModulatorClass::GeneratePulseShape()
/******************************************************************************************
/ void GenRootRaisedCosine()
/
/ 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
/ UperBoundT.
/
/Returns a pointer ot an array that contains the filter impulse response
/******************************************************************************************/
{
double *filter; //Pointer ot an array that contains the filter impulse response
double *t_index; //Pointer ot an array that contains the associated time indicies
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));
//coeff = (4.0 * RollOff ) / PI;
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; //If the time index is 0,
//slightly offset it so that a 0/0
//condition does not occur
//Now compute put pulse shape value for that time index
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); //Free the array that contains the time index
return(filter); //Return the pointer to the array that contains the pulse shape
}
ComplexNumber * ModulatorClass::GenerateDownlinkSignal(ComplexNumber *CurrentChips,
ComplexNumber *PreviousChips,
ComplexNumber *FutureChips)
/*************************************************************************************************
/ComplexNumber * ModulatorClass::GenerateDownlinkSignal(ComplexNumber *CurrentChips,
/ ComplexNumber *PreviousChips,
/ ComplexNumber *FutureChips)
/
/ Copyright 2002 The Mobile and Portable Radio Research Group
/
/Takes the Inphase and Quadrature Data Stream along with the pulse shape and generates
/the baseband representation of the transmitted signal
/
/Parameters
/ Input
/ CurrentChips ComplexNumber * Pointer to the array that contains the chips associated with
/ the current frame
/ PreviousChips ComplexNumber * Pointer to the array that contains the chips associated with
/ the previous frame
/ FutureChips ComplexNumber * Pointer to the array that contains the chips associated with
/ the next frame
/
/Returns a pointer to an array of type ComplexNumber that stores the pulse shaped signal values
/
/*************************************************************************************************/
{
unsigned k0,k1; //Loop Counters
unsigned TempChipArrayLength; //number of chips used in the singal computation
//Equals the length of the frame plus the length of the pulse -1
unsigned PulseLengthInChips; //Length of Tx Pulse in terms of chip duration
unsigned Overlap; //Number of signal samples required from previous and next frame
unsigned Start,Finish; //used to determine the start and finish of certain loops
ComplexNumber *TempChipsTemp; //Temporary pointer to one of the chip arrays corresponding to either
//the previous, current, or next frame
ComplexNumber *ChipArray,*TempChipArray; //Pointer and temporary pointer to an array that contains
//the chips that must go through pulse shape filtering.
//Note that this will include some of the chips from the
//"previous" frame and some of the chips from the "next" frame
//as well as (obviously) all of the chips from the current frame
ComplexNumber *Signal,*SignalTemp; //Pointer and temporary pointer to the array that contains the filtered
//and interpolated signal
double *PulseShapeTemp,*TempPulseTemp; //Pointer and temporary pointer to the array that contains the pulse shape
//Determine the length of the pulse in terms of chips
PulseLengthInChips = (unsigned) (PulseLength / SamplesPerChip);
//Determine size of output array
NumSamples = PulseLength + (SamplesPerChip*(CHIPS_PER_FRAME-1));
//Determine the size of temporary chip array
TempChipArrayLength = CHIPS_PER_FRAME + PulseLengthInChips;
//Allocate temporary chip array
ChipArray = (ComplexNumber *) calloc(TempChipArrayLength,sizeof(ComplexNumber));
if (ChipArray == NULL)
{
printf("\nChipArray could not be allocated--exiting\n");
return(NULL);
}
//Load temporary chip array
TempChipArray = ChipArray;
// InphaseChipsTemp = InphaseChipArray;
// QuadratureChipsTemp = QuadChipArray;
//Load contribution from previous frame
Overlap = PulseLengthInChips/2;
TempChipsTemp = PreviousChips + CHIPS_PER_FRAME - Overlap;
for (k0=0; k0<Overlap; k0++) *TempChipArray++ = *TempChipsTemp++;
//Load contribution from current frame
TempChipsTemp = CurrentChips;
for (k0=0; k0<CHIPS_PER_FRAME; k0++) *TempChipArray++ = *TempChipsTemp++;
//Load contribution from next frame
TempChipsTemp = FutureChips;
for (k0=0; k0<Overlap; k0++) *TempChipArray++ = *TempChipsTemp++;
//TemporaryChipArrayLoaded
//Allocate Memory for Signal array
Signal = (ComplexNumber *) calloc(NumSamples,sizeof(ComplexNumber));
if (Signal == NULL)
{
printf("\nSignal not allocated--exiting\n");
return(NULL);
}
//Perform filtering
SignalTemp = Signal;
TempChipArray = ChipArray;
PulseShapeTemp = PulseShape + Overlap*SamplesPerChip;
Start = (Overlap + 1) * SamplesPerChip;
//Filter the necessary chips from the previous frame.
for (k0=0; k0<Overlap;k0++)
{
TempChipsTemp = SignalTemp;
TempPulseTemp=PulseShapeTemp;
Start -= SamplesPerChip;
for (k1=Start; k1<PulseLength;k1++) *TempChipsTemp++ = ComplexAdd( *TempChipsTemp , ComplexRealMultiply(*TempPulseTemp++,*TempChipArray));
TempChipArray++;
PulseShapeTemp -= SamplesPerChip;
}
//Filter all of the chips from the current frame
for (k0=0;k0<CHIPS_PER_FRAME;k0++)
{
TempChipsTemp = SignalTemp;
PulseShapeTemp = PulseShape;
for (k1=0;k1<PulseLength;k1++) *TempChipsTemp++ = ComplexAdd( *TempChipsTemp, ComplexRealMultiply(*PulseShapeTemp++,*TempChipArray));
SignalTemp += SamplesPerChip;
TempChipArray++;
}
//Filter the necessary chips from the next frame
Finish=PulseLength;
for (k0=0; k0<Overlap; k0++)
{
TempChipsTemp = SignalTemp;
PulseShapeTemp = PulseShape;
Finish -= SamplesPerChip;
for (k1=0;k1<Finish;k1++) *TempChipsTemp++ = ComplexAdd (*TempChipsTemp , ComplexRealMultiply(*PulseShapeTemp++,*TempChipArray));
SignalTemp += SamplesPerChip;
TempChipArray++;
}
free(ChipArray);
/*****************************************************
FILE *fp;
ComplexNumber *t1,*t2,*t3;
unsigned k;
fp = fopen("Signal.txt","w");
SignalTemp = Signal;
for (k=0; k<NumSamples; k++)
{
fprintf(fp,"%g %g\n",SignalTemp->real,SignalTemp->imaginary);
SignalTemp++;
}
fclose(fp);
fp=fopen("Pulse.txt","w");
for (k=0;k<PulseLength;k++) fprintf(fp,"%g\n",*(PulseShape+k));
fclose(fp);
/*fp = fopen("Chips.txt","w");
t1=PreviousChips;
t2=CurrentChips;
t3=FutureChips;
for (k=0; k<CHIPS_PER_FRAME; k++)
{
fprintf(fp,"%d %d\t",(int) t1->real,(int) t1->imaginary);
fprintf(fp,"%d %d\t",(int) t2->real,(int) t2->imaginary);
fprintf(fp,"%d %d\n",(int) t3->real,(int) t3->imaginary);
t1++;
t2++;
t3++;
}
fclose(fp);
/*********************************************************/
return(Signal);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -