www.pudn.com > WCDMA.rar > ReceiverClass.cpp


// ReceiverClass.cpp: implementation of the ReceiverClass class. 
// 
// Copyright 2002 The Mobile and Portable Radio Research Group 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
 
#include "ReceiverClass.h" 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
ReceiverClass::ReceiverClass(SimConfigClass SimConfig,TransmitterConfigClass *TxConfig) 
/************************************************************************************************ 
/ReceiverClass::ReceiverClass(SimConfigClass SimConfig,TransmitterConfigClass *TxConfig) 
/ 
/ Copyright 2002 The Mobile and Portable Radio Research Group 
/ 
/This is the constructor for an object of type receiver class.  The constructor performs the  
/following actions 
/	1.  Generates the pusle shape wavefirn 
/	2.  Stores the desired channel's channelization code and scrambling code 
/	3.  Stores the multipath delays and their associated average amplitudes 
/ 
/Parameters 
/	SimConfig	SimConfigClass				Structure that contains the simulation  
/											configuration parameters 
/	TxConfig	TransmitterConfigClass *	Structure that contains the configuation of the  
/											Transmitter 
*************************************************************************************************/ 
{ 
	unsigned *DelayPtr;		//Stores the multipath delays in chip duration 
	double *UIDelayPtr;		//Stores the multipath delays in seconds 
	double *AmplitudePtr;	//Stores the average amplitude in linear terms 
	double *UIAmplitudePtr;	//Stores the average amplitude in decibels 
	unsigned k;				//Loop counter 
	double TempDelay;		//Contains the delay of the "current" multipath component 
	double fsample;			//sampling frequence 
	double IntegerPortion;	//Used for rounding the multipath delay (when expressed as an integer 
							//number of chips 
		 
	//Get parameters needed to generate pulse shape 
	UpperBoundT = SimConfig.PulseLength >> 1; 
	LowerBoundT = - (int) SimConfig.PulseLength >> 1; 
	SamplesPerChip = SimConfig.SamplesPerChip; 
	SamplesPerFrame = CHIPS_PER_FRAME * SamplesPerChip; 
	Rolloff = 0.22; 
	PulseLength = (UpperBoundT-LowerBoundT)*SamplesPerChip+1; 
	//Generate Pulse shape 
	PulseShape = GeneratePulseShape(); 
 
	/**************************************** 
	//Debug Code 
	FILE *fp; 
	fp = fopen("Pulse.txt","w"); 
	for (k=0; kDesiredDPCHformat; 
	ChannelCode = TxConfig->DesiredChannelCode; 
	ScrambleCode = TxConfig->DesiredScrambleCode; 
	//Determine if STTD is used 
	STTDflag = TxConfig->STTDflag; 
	//Compute the length of the transmitted signal for a given frame 
	TransmittedSignalLength = PulseLength + (SamplesPerChip*(CHIPS_PER_FRAME-1)); 
 
	//**************************************** 
	//Debug Code 
//	fp = fopen("ChannelCode.txt","w"); 
//	for (k=0; kreal,(ScrambleCode+k)->imaginary); 
//	fclose(fp); 
	//**************************************** 
 
		//Allocated arrays for the multipath delays and amplitudes 
	MultiPathComponents = SimConfig.MPathComponents; 
	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; 
	} 
 
	//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 = SimConfig.Delays; 
	AmplitudePtr = Amplitudes; 
	UIAmplitudePtr = SimConfig.Amplitudes; 
	for (k=0; k= 0.5) *DelayPtr++ = (unsigned) IntegerPortion + 1.00; 
		else *DelayPtr++ = (unsigned) IntegerPortion; 
 
		//Compute the amplitude of each multipath component 
		*AmplitudePtr++ = pow(10.000, *UIAmplitudePtr++ / 20.00); 
	} 
 
 
} 
 
ReceiverClass::~ReceiverClass() 
{ 
	//These pointers "point" to arrays that were allocated elsewhere.   
	//Just set to NULL and deallocate later 
	Amplitudes = NULL; 
	Delays = NULL; 
	ChannelCode = NULL; 
	ScrambleCode = NULL; 
 
	if (DataBits != NULL) 
	{ 
		free(DataBits); 
		DataBits = NULL; 
	} 
 
	if (PulseShape != NULL) 
	{ 
		free(PulseShape); 
		PulseShape = NULL; 
	} 
 
 
 
} 
 
 
int * ReceiverClass::Receiver(ComplexNumber *IncomingSignal, unsigned SignalLength) 
/************************************************************************************** 
* int * ReceiverClass::Receiver(ComplexNumber *IncomingSignal, unsigned SignalLength) 
* 
* Copyright 2002 The Mobile and Portable Radio Research Group 
* 
* Function that determines which receiver is to be used.  If STTD coding is employed,  
* then the STTDReceiver (a RAKE receiver with an STTD decoder) is used.  Otherise, a 
* Simple RAKE reciever is employed 
* 
* Returns	An array that contains the decoded bits in the "data fields".  
*			Note that TFCI, TCP, and Pilot bits are not returned 
* 
* Parameters 
*	IncomingSignal	ComplexNumber *		Array that contains the receiver input  
*										(channel output) for the given radio frame 
*	SignalLength	unsigned			Length of the signal sample 
***************************************************************************************/ 
{ 
	if (STTDflag) DataBits = STTDReceiver(IncomingSignal, SignalLength); 
	else DataBits = SimpleReceiver(IncomingSignal, SignalLength); 
 
	return (DataBits); 
} 
 
 
 
int * ReceiverClass::SimpleReceiver(ComplexNumber *IncomingSignal, 
										 unsigned SignalLength) 
/************************************************************************************** 
* int * ReceiverClass::SimpleReceiver(ComplexNumber *IncomingSignal, unsigned SignalLength) 
* 
* Copyright 2002 The Mobile and Portable Radio Research Group 
* 
* The function implements a "simple" RAKE receiver.  The number of fingers on the receiver 
* equals the number of multipath components in the channel, and each finger is exactly  
* tuned to the delay of the multipath components (i.e., the receiver has perfect knowledge 
* of the multipath delays.  Each finger performs the following operations:  matched filter, 
* descramble, despread, channel estimate, and weighting by the complex conjugate of the  
* channel estimate. Then the output of each finger is then summed, thereby implementing 
* maximum ratio diveristy combiner.  The resultant combined signal is then sent to a detector 
* to extract the transmitted symbols 
* 
* Returns	An array that contains the decoded bits in the "data fields".  
*			Note that TFCI, TCP, and Pilot bits are not returned 
* 
* Parameters 
*	IncomingSignal	ComplexNumber *		Array that contains the receiver input  
*										(channel output) for the given radio frame 
*	SignalLength	unsigned			Length of the signal sample 
***************************************************************************************/ 
{ 
	unsigned k,j;	//Loop counters 
	ComplexNumber *IncomingSignalComponent;	//That portion of the incoming signal that contains 
											//the complete transmitted signal record for a givn 
											//multipath component 
	ComplexNumber *RakeFingerOutputPtr,*TempRakeFingerOutputPtr;	//Pointer and temporary pointer 
																	//to the output of one finger 
																	//of the RAKE receiver 
	ComplexNumber *CombinedOutputPtr,*TempCombinedOutputPtr;		//Pointer and temporary pointer 
																	//to the resultant signal when	 
																	//the outputs of each RAKE figner  
																	//is linearly combined 
	unsigned SymbolsPerFrame;		//Number of symbols in a given frame 
	unsigned *DelayPtr;				//Temporary Pointer to the array that contains the multipath delays in chips 
//	FILE *fp;			 
 
	//Determine the number of symbols in a frame 
	SymbolsPerFrame = DPCH_Format.ActualSlotsPerFrame * (DPCH_Format.BitsPerSlot >> 1); 
	//Allocate array for the receiver output 
	CombinedOutputPtr = (ComplexNumber *) calloc(SymbolsPerFrame,sizeof(ComplexNumber)); 
	if (CombinedOutputPtr == NULL) 
	{ 
		printf("\nMemory allocation to CombinedOutputPtr failed--exiting\n"); 
		return(NULL); 
	} 
 
	DelayPtr = Delays; 
	//Process each figner of the RAKE receiver 
	for (k=0; kreal,(IncomingSignalComponent+j)->imaginary); 
		fclose(fp); 
/**********************************************************/ 
 
		//Process one figuer of the RAKE reciever 
		RakeFingerOutputPtr = SimpleRakeFinger(DPCH_Format,IncomingSignalComponent,TransmittedSignalLength); 
 
		//Combine RAKE finger output with the output of all the other RAKE fingers that have been proceed to date 
		TempRakeFingerOutputPtr = RakeFingerOutputPtr; 
		TempCombinedOutputPtr = CombinedOutputPtr; 
		for (j=0; jreal,(FilteredSignal+k)->imaginary); 
	fclose(fp); 
	/*********************************************************************************/ 
 
	//Descramble the Filtered Signal 
	Descramble(FilteredSignal,ScrambleCode); 
 
//	fp=fopen("DescrambledSignal.txt","w"); 
//	for (k=0;kreal,(FilteredSignal+k)->imaginary); 
//	fclose(fp); 
 
 
	//Despread the Descrambled Signal 
	DespreadSignal = DespreadFrame(Format,FilteredSignal); 
	free(FilteredSignal); 
 
	/********************************************************************* 
	fp=fopen("DespreadSignal.txt","w"); 
	unsigned SF,fee; 
	SF = Format.SF; 
	fee=38400/SF; 
	for (k=0;kreal,(DespreadSignal+k)->imaginary); 
	fclose(fp); 
	/***********************************************************************/ 
 
	//Obtain Channel Estimates 
	ChannelEstimates=ChannelEstimator(Format,DespreadSignal); 
 
	/********************************************************************* 
	fp=fopen("ChannelEstimates.txt","w"); 
	for (k=0;k<15;k++)  
		fprintf(fp,"%g %g\n",(ChannelEstimates+k)->real,(ChannelEstimates+k)->imaginary); 
	fclose(fp); 
	/***********************************************************************/ 
 
	//Apply Channel Estimates to Despread Signal 
	ApplyChannelEstimates(Format, DespreadSignal, ChannelEstimates); 
	free (ChannelEstimates); 
 
	/************************************************************************** 
	fp=fopen("ModifiedDespreadSignal.txt","w"); 
	for (k=0;k<150;k++)  
		fprintf(fp,"%g %g\n",(DespreadSignal+k)->real,(DespreadSignal+k)->imaginary); 
	fclose(fp); 
	/***************************************************************************/ 
	return(DespreadSignal); 
} 
 
int * ReceiverClass::STTDReceiver(ComplexNumber *IncomingSignal, 
								  unsigned SignalLength) 
/************************************************************************************** 
* int * ReceiverClass::STTDReceiver(ComplexNumber *IncomingSignal, unsigned SignalLength) 
* 
* Copyright 2002 The Mobile and Portable Radio Research Group 
* 
* The function implements a RAKE receiver for an STTD coded signal.  The number of fingers on the receiver 
* equals the number of multipath components in the channel, and each finger is exactly  
* tuned to the delay of the multipath components (i.e., the receiver has perfect knowledge 
* of the multipath delays.  Each finger performs the following operations:  matched filter, 
* descramble, despread, channel estimate, and soft STTD decoding. The output of each finger  
* is then a soft decoded estimate of the transmitted signal.  These estimates are then  
* summed.  The resultant combined signal is then sent to a detector 
* to extract the transmitted symbols 
* 
* Returns	An array that contains the decoded bits in the "data fields".  
*			Note that TFCI, TCP, and Pilot bits are not returned 
* 
* Parameters 
*	IncomingSignal	ComplexNumber *		Array that contains the receiver input  
*										(channel output) for the given radio frame 
*	SignalLength	unsigned			Length of the signal sample 
***************************************************************************************/ 
{ 
	unsigned k,j;	//Loop counters 
	ComplexNumber *IncomingSignalComponent;	//That portion of the incoming signal that contains 
											//the complete transmitted signal record for a givn 
											//multipath component 
	ComplexNumber *RakeFingerOutputPtr,*TempRakeFingerOutputPtr;	//Pointer and temporary pointer 
																	//to the output of one finger 
																	//of the RAKE receiver 
	ComplexNumber *CombinedOutputPtr,*TempCombinedOutputPtr;		//Pointer and temporary pointer 
																	//to the resultant signal when	 
																	//the outputs of each RAKE figner  
																	//is linearly combined 
	unsigned SymbolsPerFrame;		//Number of symbols in a given frame 
	unsigned *DelayPtr;				//Temporary Pointer to the array that contains the multipath delays in chips 
 
	 
	//Determine the number of symbols in a frame 
	SymbolsPerFrame = DPCH_Format.ActualSlotsPerFrame * (DPCH_Format.BitsPerSlot >> 1); 
	//Allocate array for the receiver output 
	CombinedOutputPtr = (ComplexNumber *) calloc(SymbolsPerFrame,sizeof(ComplexNumber)); 
	if (CombinedOutputPtr == NULL) 
	{ 
		printf("\nMemory allocation to CombinedOutputPtr failed--exiting\n"); 
		return(NULL); 
	} 
	 
	DelayPtr = Delays; 
	//Process each figner of the RAKE receiver 
	for (k=0; kreal,(IncomingSignalComponent+k)->imaginary); 
		fclose(fp); 
		/*************************************************************/ 
 
		//Process one figuer of the RAKE reciever 
		RakeFingerOutputPtr = STTDRakeFinger(DPCH_Format,IncomingSignalComponent,TransmittedSignalLength); 
 
		//Combine RAKE finger output with the output of all the other RAKE fingers that have been proceed to date 
		TempRakeFingerOutputPtr = RakeFingerOutputPtr; 
		TempCombinedOutputPtr = CombinedOutputPtr; 
		for (j=0; jreal,(FilteredSignal+k)->imaginary); 
	fclose(fp); 
	/*********************************************************************************/ 
 
	//Descramble the Filtered Signal 
	Descramble(FilteredSignal,ScrambleCode); 
 
	/****************************************************************** 
	fp=fopen("DescrambledSignal.txt","w"); 
	for (k=0;kreal,(FilteredSignal+k)->imaginary); 
	fclose(fp); 
	/*********************************************************************************/ 
 
 
	//Despread the Descrambled Signal 
	DespreadSignal = DespreadFrame(Format,FilteredSignal); 
	free(FilteredSignal); 
 
	/****************************************************************** 
	fp=fopen("DespreadSignal.txt","w"); 
	for (k=0;k<150;k++)  
		fprintf(fp,"%g %g\n",(DespreadSignal+k)->real,(DespreadSignal+k)->imaginary); 
	fclose(fp); 
	/*********************************************************************************/ 
 
	//Obtain Channel Estimates 
	ChannelEstimates = STTDChannelEstimator(Format,DespreadSignal); 
 
	//Peform STTD Soft Decode 
 
	DecodedSignal = STTDSoftDecode(Format,ChannelEstimates,DespreadSignal); 
	/****************************************************************** 
	fp=fopen("DecodedSignal.txt","w"); 
	for (k=0;k<150;k++)  
		fprintf(fp,"%g %g\n",(DecodedSignal+k)->real,(DecodedSignal+k)->imaginary); 
	fclose(fp); 
	/*********************************************************************************/ 
 
	//free channel estimate array 
	free(ChannelEstimates); 
	//free array containing despreaded signal 
	free(DespreadSignal); 
 
	//free array containing the soft decoded symbols 
	return(DecodedSignal); 
} 
 
 
ComplexNumber * ReceiverClass::Filter(ComplexNumber *SignalPtr,unsigned IncomingSignalLength,unsigned FilteredSignalSamples) 
/************************************************************************************************* 
*ComplexNumber * ReceiverClass::Filter(ComplexNumber *SignalPtr, 
*									   unsigned IncomingSignalLength, 
*									   unsigned FilteredSignalSamples)* 
* 
* Copyright 2002 The Mobile and Portable Radio Research Group 
* 
*This function filters and decimates the incoming complex-valued signal with the FIR impulse  
*reponse stored in PulseShape.  The decimation rate is equal to SamplesPerChip.  Decimation is simply 
*performed by filtering every SamplesPerChip'th output sample.  The "delay" and "tail" due to the  
*filtering is removed 
*This fuction works on matrix of signal data, where each column in the the matrix is a   
*different signal 
* 
*Returns	A poiter to an array of type ComplexNumber that contains the values of the filtered 
*			and decimated signal 
* 
*Parameters 
*   Input 
*      SignalPtr			ComplexNumber	Pointer to array of length NumSamples that stores the  
*										    signal values 
*      IncomingSignalLength	unsigned		Length of incoming signal 
* 
*   Output 
*      FilteredSignalSamples      unsigned     legnth of filtered signal 
* 
**************************************************************************************************/ 
{ 
	ComplexNumber *FilteredSignalPtr;	//Pointer to the array that contains the values fo the  
										//filtered and ecimated signal 
 
	unsigned k1,k2;						//Loop counters 
	unsigned PaddedLength;				//Length of signal array, included the necessary zero padding 
//	double *InphasePaddedPtr,*QuadPaddedPtr; 
	ComplexNumber *SigPtr;				//Temporary pointer to the signal array.  Used to determine the  
										//what elements of the incoming signal are to be included for 
										//the filtering of a particular value 
	ComplexNumber *FilterSigPtr;		//Temporary pointer to the filtered signal array 
	ComplexNumber *FilterTmpPtr;		//Another temporary pointer to the filtered signal array 
	ComplexNumber *TmpPtr;				//Temporary pointer to the signal array.  used to perform the  
										//Actuall filtering (i.e., multiplication with the pulse shape) 
	double *PulseTmpPtr;				//Temporary pointer to the array that contains the pulse shape 
	unsigned loopstart;					//Looping parameter.  Used to determine the start of a given for loop 
 
	PaddedLength = IncomingSignalLength + 2 * PulseLength; 
	//Allocated memory for filtered signal 
	FilteredSignalPtr = (ComplexNumber *) calloc(FilteredSignalSamples,sizeof(ComplexNumber)); 
	if (FilteredSignalPtr == NULL) 
	{ 
		printf("Memory Allocation to FilteredSignalPtr failed!--returning\n"); 
		return(NULL); 
	} 
 
	SigPtr = SignalPtr; 
	FilterSigPtr = FilteredSignalPtr; 
 
	//perform filtering and decimation 
	loopstart=PulseLength-1; 
	FilterTmpPtr = FilterSigPtr; 
	SigPtr += loopstart; 
	for (k1=loopstart;k1> 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> 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; 
	} 
 
	//Initialize the Channel Estimate Vector 
	ChannelEstimatePtr = (ComplexNumber *) calloc(SlotsPerFrame,sizeof(ComplexNumber)); 
	if (ChannelEstimatePtr == NULL) 
	{ 
		printf("Memory allocation for ChannelEstimatePtr failed--exiting\n"); 
		return(NULL); 
	} 
 
	//Now Perform the channel Estimates--One estimate per Slot 
	//The estimates are obtained by dividing the despread symbol by the known pilot symbol 
	//for that particular location.  Then for each slot, these estimates are averaged 
	TempChannelEstimatePtr = ChannelEstimatePtr; 
	TempDespreadSignalPtr = DespreadSignal; 
	TempPilotPtr = PilotPtr; 
	for (k=0; k> 1; 
 
	//Assign temporary pointers 
	TempChannelEstimate = ChannelEstimate; 
	TempDespreadSignal = DespreadSignal; 
	//Apply the channel estimate by multiplying each slot with the conjugate of the channel estimate 
	//for that slot 
	for (k=0; k> 1; 
	//Determine the number of symbols in the data1 field 
	Data1Symbols = Format.Ndata1 >> 1; 
	//Determine the number of symbols in the data2 field 
	Data2Symbols = Format.Ndata2 >> 1; 
	//Determine the number of databits in a given frame 
	DataBitsPerFrame = Format.ActualSlotsPerFrame * (Format.Ndata1 + Format.Ndata2); 
 
	//Allocate memory for an array that will store the detected data bits 
	DetectedDataBits = (int *) calloc(DataBitsPerFrame,sizeof(int)); 
	if (DetectedDataBits == NULL) 
	{ 
		printf("memory Allocation for DetectedDataBits failed--exiting\n"); 
		return(NULL); 
	} 
 
	//Assign temporary pointers 
	TempDetectedDataBits = DetectedDataBits; 
	TempDespreadSignal = DespreadSignal; 
	//Go through the detection process on a slot-by-slot basis 
	for (k=0; kreal) >= 0.0) 
				*TempDetectedDataBits++ = 1; 
			else 
				*TempDetectedDataBits++ = -1; 
 
			if ((TempDespreadSignal->imaginary) >= 0.0) 
				*TempDetectedDataBits++ = 1; 
			else 
				*TempDetectedDataBits++ = -1; 
			TempDespreadSignal++; 
		} 
 
		TempDespreadSignal += SkipLength; 
		//Then do symbols in the data2 field 
		for (j=0; j< Data2Symbols; j++) 
		{ 
			if ((TempDespreadSignal->real) >= 0.0) 
				*TempDetectedDataBits++ = 1; 
			else 
				*TempDetectedDataBits++ = -1; 
 
			if ((TempDespreadSignal->imaginary) >= 0.0) 
				*TempDetectedDataBits++ = 1; 
			else 
				*TempDetectedDataBits++ = -1; 
			TempDespreadSignal++; 
		} 
 
		TempDespreadSignal += (Format.NPilot >> 1); 
	} 
 
	return(DetectedDataBits); 
} 
 
 
ComplexNumber * ReceiverClass::STTDChannelEstimator(DPCH_FormatStructure Format,ComplexNumber *DespreadSignal) 
/******************************************************************************************************************** 
* ComplexNumber * ReceiverClass::STTDChannelEstimator(DPCH_FormatStructure Format,ComplexNumber *DespreadSignal) 
* 
* Copyright 2002 The Mobile and Portable Radio Research Group 
* 
* The function estimates the two complex channel gains associated with a STTD link.  In such a link, two transimtter  
* antennas and only one receive antenna are employed.  Therefore, for each slot, two channel gain estimates are required. 
* this function uses the Pilot symbols in each slot to estimate these gains.  
* 
* It is important to note that specific estimation procedure is a direct funciton of the number of Pilot bits per slot 
* used in the transmission.   Details of the specific estimation procedure are documented in the code 
* 
* Returns	A ComplexNumber type array of length 30 (assuming the frame contains 15 slots) containing the channel gains 
*			from the two antennas to the receiver.  The even numbered elements (note the elements are numbered 0 to 29) 
*			contain the channel estimates from transmit antenna 0 to the receiver.  The odd numbered elements contain  
*			the channel estimates from transmit antenna 1 to the receiver. 
* 
* 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 declared and defined 
	//*************************************************************************************************************** 
 
	const ComplexNumber Sdata[4] =		{{1,1},{1,-1},{-1,1},{-1,-1}};	//Stores the four possible symbol values 
 
	ComplexNumber *PilotPtr,*TempPilotPtr;		//Poiter and temporary pointer to the array that contains  
												//the select pilot symbol 
	unsigned SF;								//Spreading Factor 
	unsigned NumPilotSymbols;					//Number of pilto symbols 
	ComplexNumber *ChannelEstimatePtr,*TempChannelEstimatePtr;	//Poiner and temporary pointer to the array that 
																//contains the channel estimates 
	ComplexNumber *TempDespreadSignalPtr;		//Temporary poiner to the despread signal 
	unsigned PilotPositionInSlot;				//Location of the first pilot symbol in every slot 
	unsigned SlotsPerFrame;						//Number of slots per frame 
	ComplexNumber TempEstimate0,TempEstimate1;	//Temporary storage for the channel estimates 
	ComplexNumber s,s0,s1,r0,r1,r2,r3,r4,r5,r6,r7;	//Varialbes used in channel estimation procedure 
	ComplexNumber fee,foo;						//Temporary storage (general use) 
	unsigned j,k;								//Loop counters 
 
	//Get spreading factor 
	SF = Format.SF; 
	//Determine the number of pilot symbols in a given slot 
	NumPilotSymbols = (Format.NPilot >> 1); 
	//Determine the postion of th efirst pilot symbol in any given slot 
	PilotPositionInSlot = (Format.BitsPerSlot >> 1) - NumPilotSymbols; 
	//Determine the number slots per frame 
	SlotsPerFrame = Format.ActualSlotsPerFrame; 
 
	//Get the correct Pilot Symbols 
	switch (Format.NPilot) 
	{ 
		case 2: 
			PilotPtr = (ComplexNumber *) Npilot2; 
//			Pilot2Ptr = (ComplexNumber *) N2Pilot2; 
			break; 
		case 4: 
			PilotPtr = (ComplexNumber *) Npilot4; 
//			Pilot2Ptr = (ComplexNumber *) N4Pilot2; 
			break; 
		case 8: 
			PilotPtr = (ComplexNumber *) Npilot8; 
//			Pilot2Ptr = (ComplexNumber *) N8Pilot2; 
			break; 
		case 16: 
			PilotPtr = (ComplexNumber *) Npilot16; 
//			Pilot2Ptr = (ComplexNumber *) N16Pilot2; 
			break; 
	} 
 
	//Initialize the Channel Estimate Vector 
	ChannelEstimatePtr = (ComplexNumber *) calloc(2*SlotsPerFrame,sizeof(ComplexNumber)); 
	if (ChannelEstimatePtr == NULL) 
	{ 
		printf("Memory allocation for ChannelEstimatePtr failed--exiting\n"); 
		return(NULL); 
	} 
 
	//Now Perform the channel Estimates--One estimate per Slot 
	//The estimates are obtained by dividing the despread symbol by the known pilot symbol 
	//for that particular location.  Then for each slot, these estimates are averaged 
	TempChannelEstimatePtr = ChannelEstimatePtr; 
	TempDespreadSignalPtr = DespreadSignal; 
	TempPilotPtr = PilotPtr; 
	if (NumPilotSymbols==1) 
	{ 
		for (k=0; k> 1; 
	//Get the number of symples for the entire frame 
	SymbolsPerFrame = SymbolsPerSlot * Format.ActualSlotsPerFrame; 
	//Get the number of slots for the entire frame 
	SlotsPerFrame = Format.ActualSlotsPerFrame; 
	//Compute the number of decoding iterations per slot 
	IterationsPerSlot = SymbolsPerSlot >> 1; 
 
	//Allocate Output Array 
	DecodedSignalPtr = (ComplexNumber *) calloc(SymbolsPerFrame,sizeof(ComplexNumber)); 
	if (DecodedSignalPtr == NULL) 
	{ 
		printf("\nMemory allocation for DecodedSignalPtr failed--exiting\n"); 
		return(NULL); 
	} 
 
	//Assign Temporary Pointers 
	TempChannelEstimates = ChannelEstimates; 
	TempDespreadSignal = DespreadSignal; 
	TempDecodedSignalPtr = DecodedSignalPtr; 
	//Perform the decoding 
	for (k=0; k