www.pudn.com > WCDMA.rar > 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; k0real,SignalTemp->imaginary); 
		SignalTemp++; 
	} 
 
	fclose(fp); 
 
	fp=fopen("Pulse.txt","w"); 
	for (k=0;kreal,(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); 
}