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);
}