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

📄 modulatorclass.cpp

📁 用matlab程序实现WCDMA系统的仿真
💻 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 + -