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


// DownlinkSimulator.cpp : Defines the entry point for the console application. 
// 
 
#include "stdafx.h" 
#include "TransmitterClass.h" 
//#include "Sim.h" 
#include "mex.h" 
#include "matrix.h" 
 
ErrorRunClass DownLinkSimulator(SimConfigClass Config); 
 
void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 
/*************************************************************************************** 
* void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 
* 
* 
* Copyright 2002 The Mobile and Portable Radio Research Group 
* 
* Gateway function for the down simulator.  Supports the passing of one arguement,  
* which happens to be a structure, and returns one parameters. 
* 
* The members of the input structure are 
*		S_CCPCHformatID		Integer		Format ID for S_CCPCH 
*		PDSCHformatID		Integer		Format ID for PDSCH 
*		DesiredDPCHformatID	Integer		Format ID for Desired DPCH 
*		Num_DPCH			Integer		Number of remaining DPCHs 
*		NumDPCCHforCPCH		Integer		Number of DPCCHs for CPCH 
*		NumS_CPICH			Integer		Number of S_CPICH 
*		STTD				boolean		STTD flag 
*		OtherDPCHformatID	Int array	Format ID for remaining DPCHs 
*		PulseUpperBound		Integer		Upper bould of pulse length 
*		SamplesPerChip		Integer		Oversampling rate 
*		EbNo_dB				double		EbNo in dB 
*		Velocity			double		Velocity in km/hr 
*		Delays				dbl array	Delay of each multipath component 
*		Amplitudes			dbl array	Amplitude of each multipath component 
* 
* The output parameter is 
*		Error Run Length	int array	Error run lenght for simulation 
***************************************************************************************/ 
{ 
	int NumFields; 
	int Ncolumns,Mrows; 
	char *s1=" "; 
	mxArray *tmpPtr; 
	SimConfigClass SimConfig; 
	double *fee; 
	ErrorRunClass ErrorRun; 
	unsigned k; 
 
 
	/**********************************************/ 
	//Error Checking 
	if (nrhs != 1) 
		mexErrMsgTxt("Exactly one input argument is required\n"); 
	else if (nlhs > 1) 
		mexErrMsgTxt("At least one output argument is required\n"); 
	else if (!mxIsStruct(prhs[0])) 
		mexErrMsgTxt("Input argument must be a structure\n"); 
 
	//Get the number of fields--There should be 15 
	NumFields = mxGetNumberOfFields(prhs[0]); 
	if (NumFields != 15) 
	{ 
		sprintf(s1,"NumFields = %d:  It should equal 15!!  exiting\n",NumFields); 
		mexErrMsgTxt(s1); 
	} 
	/***************************************************/ 
	//Extract Fields 
 
	//S_CCPCH format ID field                            1 
	tmpPtr = mxGetField(prhs[0],0,"S_CCPCHformatID"); 
	if (tmpPtr == NULL) 
		mexErrMsgTxt("Field S_CCPCHformatID could not be found. Verify validity of field name\n"); 
	SimConfig.S_CCPCHformatID = (unsigned) mxGetScalar(tmpPtr); 
 
	//PDSCH format ID field                              2 
	tmpPtr = mxGetField(prhs[0],0,"PDSCHformatID"); 
	if (tmpPtr == NULL) 
		mexErrMsgTxt("Field PDSCHformatID could not be found. Verify validity of field name\n"); 
	SimConfig.PDSCHformatID = (unsigned) mxGetScalar(tmpPtr); 
 
	//Desired DPCH format ID field                       3 
	tmpPtr = mxGetField(prhs[0],0,"DesiredDPCHformatID"); 
	if (tmpPtr == NULL) 
		mexErrMsgTxt("Field DesiredDPCHformatID could not be found. Verify validity of field name\n"); 
	SimConfig.DesiredDPCHformatID = (unsigned) mxGetScalar(tmpPtr); 
 
	//Number of Remaining DPCHs field                    4 
	tmpPtr = mxGetField(prhs[0],0,"Num_DPCH"); 
	if (tmpPtr == NULL) 
		mexErrMsgTxt("Field Num_DPCH could not be found. Verify validity of field name\n"); 
	SimConfig.Num_DPCH = (unsigned) mxGetScalar(tmpPtr); 
 
	//Number of  DPCCH for CPCH field                    5 
	tmpPtr = mxGetField(prhs[0],0,"NumDPCCHforCPCH"); 
	if (tmpPtr == NULL) 
		mexErrMsgTxt("Field NumDPCCHforCPCH could not be found. Verify validity of field name\n"); 
	SimConfig.NumDPCCHforCPCH = (unsigned) mxGetScalar(tmpPtr); 
 
	//Number of S_CPICH field                            6 
	tmpPtr = mxGetField(prhs[0],0,"NumS_CPICH"); 
	if (tmpPtr == NULL) 
		mexErrMsgTxt("Field NumS_CPICH could not be found. Verify validity of field name\n"); 
	SimConfig.NumS_CPICH = (unsigned) mxGetScalar(tmpPtr); 
 
	//STTDflag field                                     7 
	tmpPtr = mxGetField(prhs[0],0,"STTD"); 
	if (tmpPtr == NULL) 
		mexErrMsgTxt("Field STTD could not be found. Verify validity of field name\n"); 
	SimConfig.STTDflag = (bool) mxGetScalar(tmpPtr); 
 
	//Pulse Upper Bound field                            8   
	tmpPtr = mxGetField(prhs[0],0,"PulseLength"); 
	if (tmpPtr == NULL) 
		mexErrMsgTxt("Field PulseUpperBound could not be found. Verify validity of field name\n"); 
	SimConfig.PulseLength = (unsigned) mxGetScalar(tmpPtr); 
 
	//Samples Per Chip field                             9 
	tmpPtr = mxGetField(prhs[0],0,"SamplesPerChip"); 
	if (tmpPtr == NULL) 
		mexErrMsgTxt("Field SamplesPerChip could not be found. Verify validity of field name\n"); 
	SimConfig.SamplesPerChip = (unsigned) mxGetScalar(tmpPtr); 
 
	//EbNo_dB field                                      10  
	tmpPtr = mxGetField(prhs[0],0,"EbNo_dB"); 
	if (tmpPtr == NULL) 
		mexErrMsgTxt("Field EbNo_dB could not be found. Verify validity of field name\n"); 
	SimConfig.EbNo_dB = mxGetScalar(tmpPtr); 
 
	//Velocity field                                     11  
	tmpPtr = mxGetField(prhs[0],0,"Velocity"); 
	if (tmpPtr == NULL) 
		mexErrMsgTxt("Field Velocity could not be found. Verify validity of field name\n"); 
	SimConfig.Velocity = mxGetScalar(tmpPtr); 
 
	//Other DPCH Format ID field                         12 
	tmpPtr = mxGetField(prhs[0],0,"OtherDPCHformatID"); 
	if (tmpPtr == NULL) 
		mexErrMsgTxt("Field OtherDPCHformatID could not be found. Verify validity of field name\n"); 
	fee = mxGetPr(tmpPtr); 
	SimConfig.OtherDPCHformatID = (unsigned *) calloc(SimConfig.Num_DPCH,sizeof(unsigned)); 
	for (k=0; kreal,(Tx.PreviousFrame.Chips+j)->imaginary); 
		fclose(fp); 
 
		fp = fopen("CurrentFrame.txt","w"); 
		for (j=0;j<38400;j++) 
			fprintf(fp,"%g %g\n",(Tx.CurrentFrame.Chips+j)->real,(Tx.CurrentFrame.Chips+j)->imaginary); 
		fclose(fp); 
 
		fp = fopen("NextFrame.txt","w"); 
		for (j=0;j<38400;j++) 
			fprintf(fp,"%g %g\n",(Tx.NextFrame.Chips+j)->real,(Tx.NextFrame.Chips+j)->imaginary); 
		fclose(fp); 
 
		fp = fopen("CurrentSignal.txt","w"); 
		for (j=0; j<192046;j++) 
			fprintf(fp,"%g %g\n",(Modulator.CurSignal1+j)->real,(Modulator.CurSignal1+j)->imaginary); 
		fclose(fp); 
/********************************************************************************************/ 
 
	//Delete the "Previous" frame 
	free(Tx.PreviousFrame.Chips); 
	Tx.PreviousFrame.Chips = NULL; 
	free(Tx.PreviousFrame.DataBits); 
	Tx.PreviousFrame.DataBits = NULL; 
 
	//Update the frames 
	//The "current" frame is now the "previous" frame 
	//The "next" frame is now the "current frame 
	Tx.PreviousFrame = Tx.CurrentFrame; 
	Tx.CurrentFrame = Tx.NextFrame; 
	 
	//Start the Iterations 
	for (k=0; k < Config.Iterations; k++) 
	{ 
 
		//Generate the "next" frame 
		Tx.NextFrame = Tx.GenerateFrame(); 
 
		//Run the frames throgh the Modulator 
		//Generate the "next" signal 
		Modulator.NextSignal1= Modulator.GenerateDownlinkSignal(Tx.CurrentFrame.Chips,Tx.PreviousFrame.Chips,Tx.NextFrame.Chips);  
 
		//Now that we have a "previous" signal, a "current" signal and a "next" signal,  
		//we can process the through the channel. 
		Channel1.MpathProcessor(Modulator.PrevSignal1, 
								Modulator.CurSignal1, 
								Modulator.NextSignal1, 
								Modulator.NumSamples); 
 
		//We no longer need the previous signal, so delete it 
		free(Modulator.PrevSignal1); 
		Modulator.PrevSignal1 = NULL; 
 
		//Update the "current" signal to the "previous" signal 
		//Update the "next" signal to the "current" signal 
		Modulator.PrevSignal1 = Modulator.CurSignal1; 
		Modulator.CurSignal1 = Modulator.NextSignal1; 
		 
		//If STTD was employed, then process the signals from the second antenna 
		if (Tx.TxConfiguration.STTDflag) 
		{ 
			//Geneate the "next" signal 
			Modulator.NextSignal2 = Modulator.GenerateDownlinkSignal(Tx.CurrentFrame.Chips + CHIPS_PER_FRAME, 
																Tx.PreviousFrame.Chips + CHIPS_PER_FRAME, 
																Tx.NextFrame.Chips + CHIPS_PER_FRAME); 
 
			//Send the "previous," "current," and "next" signals through the channel associated  
			//with the 2nd antenna 
			Channel2->MpathProcessor(Modulator.PrevSignal2, 
							 	    Modulator.CurSignal2, 
								    Modulator.NextSignal2, 
									Modulator.NumSamples); 
 
			//Combine (add) the chanel outputs from both antenna 1 and antenna 2. 
			Channel1.Combiner(Channel2->MultipathSignal); 
 
			//We no longer need the "previous" signal, so delete it (deallocate the memory) 
			free(Modulator.PrevSignal2); 
			Modulator.PrevSignal2 = NULL; 
 
			//Update the "current" signal to the "previous" signal 
			//Update the "next" signal to the "current" signal 
			Modulator.PrevSignal2 = Modulator.CurSignal2; 
			Modulator.CurSignal2 = Modulator.NextSignal2; 
		} 
		//Add thermal noise 
		/*************************/ 
		//Temporarily commend out for callibration purposes 
		Channel1.NoiseGenerator(); 
		/*************************/ 
 
		//Extract the received data bits 
		DataBits = Rx.Receiver(Channel1.MultipathSignal,Channel1.MultipathSignalLength); 
 
		//Compute the length 
		DataBitLength = Tx.TxConfiguration.DesiredDPCHformat.MaxSlotsPerFrame * (Tx.TxConfiguration.DesiredDPCHformat.Ndata1 + Tx.TxConfiguration.DesiredDPCHformat.Ndata2);  
/******************************************************************************************** 
		//Debug Code 
		fp = fopen("DataBits.txt","w"); 
		for (j=0; j= ErrorRunBlockSize) 
					{ 
						//Reallocate the array 
						ErrorRunBlockSize += ErrorRunBlockIncrement; 
						ErrorRun.Array = (unsigned *) realloc(ErrorRun.Array, ErrorRunBlockSize * sizeof(unsigned)); 
						//Reset the temporary pointer at the correct location 
						TempErrorArray = ErrorRun.Array + ErrorRunOffset; 
					} 
				} 
			} 
			else 
			{ 
				if(!ErrorState) 
				{ 
					*TempErrorArray++ = RunCount; 
					RunCount = 1; 
					ErrorState = true; 
					//Check to see if the error run array is full.  If it is, then reallocate 
					if ( (ErrorRunOffset = TempErrorArray - ErrorRun.Array) >= ErrorRunBlockSize) 
					{ 
						//Reallocate the array 
						ErrorRunBlockSize += ErrorRunBlockIncrement; 
						ErrorRun.Array = (unsigned *) realloc(ErrorRun.Array, ErrorRunBlockSize * sizeof(unsigned)); 
						//Reset the temporary pointer at the correct location 
						TempErrorArray = ErrorRun.Array + ErrorRunOffset; 
					} 
				} 
				else RunCount++; 
			} 
			ReceivedDataBits += 2; 
			SentDataBits += 2; 
		} 
/***************************************************************************************************/ 
 
/***************************************************************************************************/ 
		//Count the Bit Errors 
		ReceivedDataBits = DataBits; 
		SentDataBits = Tx.PreviousFrame.DataBits; 
		for (j=0; j= ErrorRunBlockSize) 
					{ 
						//Reallocate the array 
						ErrorRunBlockSize += ErrorRunBlockIncrement; 
						ErrorRun.Array = (unsigned *) realloc(ErrorRun.Array, ErrorRunBlockSize * sizeof(unsigned)); 
						//Reset the temporary pointer at the correct location 
						TempErrorArray = ErrorRun.Array + ErrorRunOffset; 
					} 
				} 
			} 
			else 
			{ 
				if(!ErrorState) 
				{ 
					*TempErrorArray++ = RunCount; 
					RunCount = 1; 
					ErrorState = true; 
					//Check to see if the error run array is full.  If it is, then reallocate 
					if ( (ErrorRunOffset = TempErrorArray - ErrorRun.Array) >= ErrorRunBlockSize) 
					{ 
						//Reallocate the array 
						ErrorRunBlockSize += ErrorRunBlockIncrement; 
						ErrorRun.Array = (unsigned *) realloc(ErrorRun.Array, ErrorRunBlockSize * sizeof(unsigned)); 
						//Reset the temporary pointer at the correct location 
						TempErrorArray = ErrorRun.Array + ErrorRunOffset; 
					} 
				} 
				else RunCount++; 
			} 
		} 
/***************************************************************************************************/ 
		//The channel output is no longer required, so remove the signal(s) 
		free(Channel1.MultipathSignal); 
		Channel1.MultipathSignal = NULL; 
		if (Tx.TxConfiguration.STTDflag) 
		{ 
			free(Channel2->MultipathSignal); 
			Channel2->MultipathSignal = NULL; 
		} 
 
		//The "data" and "chipping sequence" associatged with the "previous" frame is no longer 
		//required, so deallocate the memory 
		free(Tx.PreviousFrame.Chips); 
		Tx.PreviousFrame.Chips = NULL; 
		free(Tx.PreviousFrame.DataBits); 
		Tx.PreviousFrame.DataBits = NULL; 
 
		/**************************************************/ 
		//Temporary command 
		//Used to detect memory leaks 
		//Will remove when leaks are plugged 
		free(DataBits); 
		DataBits = NULL; 
		/**************************************************/ 
 
		//Update the frames 
		//The "current" frame is now the "previous" frame 
		//The "next" frame is now the "current frame 
		Tx.PreviousFrame = Tx.CurrentFrame; 
		Tx.CurrentFrame = Tx.NextFrame; 
 
		//Update the wait bar 
 
			//Update up Wait Bar 
		*ZeroPtr = (double) (k+1) / (double) Config.Iterations; //ZeroPtr alread reference to prhs[0] 
		nlhs = 0; //No output arguements required 
		mexStatus = mexCallMATLAB(nlhs,plhs,nrhs,prhs,"waitbar"); 
		if (mexStatus != 0)  
			mexErrMsgTxt("Call to mexCallMATLAB failed!--exiting\n"); 
	} 
 
	//Simulation is complete.  Load the results of the remaining decisions (stored in RunCount) into the Error Run array 
	*TempErrorArray++ = RunCount; 
	ErrorRun.Length = TempErrorArray - ErrorRun.Array; 
 
	//Close the waitbar 
	*ZeroPtr = FigureHandle; 
	mxDestroyArray(prhs[1]); 
	nrhs = 1; 
	mexCallMATLAB(nlhs,plhs,nrhs,prhs,"close"); 
 
 
	return(ErrorRun); 
}