?? wcdmaratematching.c
字號:
/* * WCDMA RATE MATCHING performs rate matching algorithm
* as specified by 3GPP TS 25.212 * * Copyright 1996-2001 The MathWorks, Inc. * $Revision: 1.2 $ $Date: 2001/12/13 23:29:31 $ */#define S_FUNCTION_NAME wcdmaratematching#define S_FUNCTION_LEVEL 2#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>#include "simstruc.h" /* List input & output ports*/enum {INPORT=0, NUM_INPORTS};enum {OUTPORT=0, NUM_OUTPORTS};/* List the mask parameters*/enum {DELNIMAX_ARGC=0, NUMBITS_ARGC, ERRORCORR_ARGC, CHECKRM_ARGC, NUM_ARGS}; #define DELNIMAX_ARG ssGetSFcnParam(S, DELNIMAX_ARGC)#define NUMBITS_ARG ssGetSFcnParam(S, NUMBITS_ARGC)#define ERRORCORR_ARG ssGetSFcnParam(S, ERRORCORR_ARGC)#define CHECKRM_ARG ssGetSFcnParam(S, CHECKRM_ARGC)
/* Define pWork Structure */
typedef struct{
int_T *pPattern;
int_T b;
int_T X;
int_T *pEIni;
int_T *pEPlus;
int_T *pEMinus;
int_T deltaNi;
int_T checkRM;
int_T numBitsIn;
}TRmPar;
#define parPattern rmPar->pPattern
#define parB rmPar->b
#define parX rmPar->X
#define parEini rmPar->pEIni
#define parEplus rmPar->pEPlus
#define parEminus rmPar->pEMinus
#define parDeltaNi rmPar->deltaNi
#define parCheckRM rmPar->checkRM
#define parNumBitsIn rmPar->numBitsIn
#define THROW_ERROR(S,MSG) {ssSetErrorStatus(S,MSG); return;}
#define RMATCHING 0
#define RDEMATCHING 1
/* Function to determine the Rate Matching Parameters, X, eini, eplus and eminus ========*/static void getRMParameters(TRmPar *rmPar){ int_T a,k;
int_T B = parB-1;
parX = (int_T) parNumBitsIn/parB; if(parB == 1) /* Conv Encoding or Turbocoding AND repetition */ {
a = 2;
parEini[B] = 1;
parEplus[B] = a*parNumBitsIn;
parEminus[B] = a*(int_T)abs(parDeltaNi); } else {
for(k=1;k<B;k++)
{
a = 4-k; /* a=2 for b=2 and a=1 for b=3 */
parEini[B] = (int_T) parNumBitsIn/parB;
parEplus[B] = a*(int_T) parNumBitsIn/parB;
parEminus[B] = a*(int_T)abs(parDeltaNi/2);
}
}
} /* End of Function rmParams */ /* Function to calculate the Rate Matching Pattern vector ==================*/static void rmPatternDetermination(TRmPar *rmPar){/* This function returns a vector of the same size as that of X with -1s in place of bits that needs to be punctured and numbers in place of bits that needs to be repeated indicating how many times they need to be repeated */
int_T e, m, n, temp =0;
int_T B = parB-1; if (parDeltaNi<0) /* Puncturing */ {
e = parEini[B]; /* Initial error between current and desired puncturing ratio */
for (m=0; m<parX; m++)
{
e = e - parEminus[B]; /* Update error */
if(e<=0)
{
parPattern[m] = -1; /* Mark puncturing */
e = e + parEplus[B]; /* Update error */
temp++;
}
else parPattern[m] = 0; /* Mark bit as no puncturing */
}
} else if (parDeltaNi>0) /* Repetition */ {
e = parEini[B]; /* Initial error between current and desired puncturing ratio */
for (m=0; m<parX; m++)
{
e = e - parEminus[B]; /* Update error */
n = 0;
while(e<=0) {
e = e + parEplus[B]; /* Update error */ n++;
temp++;
}
parPattern[m] = n; /* Mark repetition */
} }} /* End of Function rmPatternDetermination */
/* Function to Split and Combine bits and find the overall puncturing Index==================*//*static void rmTurboIndex(int_T **Pwork, int_T *X,int_T *eini, int_T *eplus, int_T *eminus){/* This function returns a vector of the same size as that of X(2)*3 with -1s in place of bits that needs to be punctured for the special case of Turbo Coded bits */ /* int_T **parityOneIndex, **parityTwoIndex, *combinedTurboIndex; int_T i,sepLength; parityOneIndex = (int_T**) malloc(1 * sizeof(int_T*)); parityTwoIndex = (int_T**) malloc(1 * sizeof(int_T*)); sepLength=X[2]; combinedTurboIndex = (int_T*) malloc(X[2]*3*sizeof(int_T)); /*Compute the punctured Index Vector for each Parity output. Systematic Bits not punctured */ /*Since its always puncturing here, the 4th output to rmPatternDe... is any value greater than 0 */ /* rmPatternDetermination(parityOneIndex, X[2],eini[2],eplus[2],eminus[2],-1); rmPatternDetermination(parityTwoIndex, X[3],eini[3],eplus[3],eminus[3],-1); /* Create the combinedTurboIndex */ /*for (i=0;i<sepLength;i++) { combinedTurboIndex[i*3]=0; combinedTurboIndex[i*3+1]=parityOneIndex[0][i]; combinedTurboIndex[i*3+2]=parityTwoIndex[0][i]; }
Pwork[0]=combinedTurboIndex;
}/* End of Function rmTurboIndex =============================*/ /* Function to find the final output vector given the RM puncturing or repetition pattern ====== */
static void rmComputeOutputVec(real_T *outData, real_T *inData, TRmPar *rmPar, int_T inPortWidth){ int_T k,i,outCount, inCount;
real_T aver;
/* Rate Matching Case */ if (parCheckRM == RMATCHING)
{ for (k=0, outCount=0; k<parNumBitsIn; k++) { if (parPattern[k] == -1) {} /* Puncture */ /* Increment input counter (k) */
else if(parPattern[k]>0) /* Repetition */ {
for(i=0;i<parPattern[k];i++)
{
outData[outCount] = inData[k]; outCount ++;
} }
else /* Do Nothing */
{
outData[outCount] = inData[k];
outCount ++;
}
} }
else /* Rate Dematching case */
{
for (k=0, inCount=0; k<parNumBitsIn; k++)
{
if (parPattern[k] == -1) /* Pad with zeros */
outData[k] = 0;
else if(parPattern[k]>0) /*Derepetition */
{
/* Compute average of repeated symbols */
for(i=0, aver=0; i<parPattern[k]; i++)
{
aver += (real_T) inData[inCount]/parPattern[k];
inCount++;
}
outData[k] = aver;
}
else /* Do Nothing */
{
outData[k] = inData[inCount];
inCount ++;
}
}
}
}/* End of Function rmComputeOutputVec */ /* Function: mdlCheckParameters =============================================*/#ifdef MATLAB_MEX_FILE#define MDL_CHECK_PARAMETERSstatic void mdlCheckParameters(SimStruct *S) { /* The mask checks for the polynomial, initial states and the number of * checksums parameters as entered by the user. */}#endif/* Function: mdlInitializeSizes ============================================*/static void mdlInitializeSizes(SimStruct *S){ int i; ssSetNumSFcnParams(S, NUM_ARGS);#if defined(MATLAB_MEX_FILE) if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) return; mdlCheckParameters(S); if (ssGetErrorStatus(S) != NULL) return;#endif ssSetNumSampleTimes(S, 1); /* Input: */ if (!ssSetNumInputPorts(S, NUM_INPORTS)) return; if (!ssSetInputPortDimensionInfo(S, INPORT, DYNAMIC_DIMENSION)) return; ssSetInputPortFrameData( S, INPORT, FRAME_YES); ssSetInputPortComplexSignal( S, INPORT, COMPLEX_NO); ssSetInputPortDirectFeedThrough( S, INPORT, 1); ssSetInputPortRequiredContiguous(S, INPORT, 1); ssSetInputPortReusable( S, INPORT, 0); /* Output: */ if (!ssSetNumOutputPorts(S, NUM_OUTPORTS)) return; if (!ssSetOutputPortDimensionInfo(S, OUTPORT, DYNAMIC_DIMENSION)) return; ssSetOutputPortFrameData( S, OUTPORT, FRAME_YES); ssSetOutputPortComplexSignal( S, OUTPORT, COMPLEX_NO); ssSetOutputPortReusable( S, OUTPORT, 0); ssSetOptions( S, SS_OPTION_EXCEPTION_FREE_CODE); for (i=0; i<NUM_ARGS; i++) ssSetSFcnParamNotTunable(S, i);
/* Initialize the Work Vector to be used for the index vector*/
ssSetNumPWork(S, 1);
}/* Function: mdlInitializeSampleTimes ======================================*/static void mdlInitializeSampleTimes(SimStruct *S){ ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME); ssSetOffsetTime(S, 0, 0.0); if (ssGetSampleTime(S,0) == CONTINUOUS_SAMPLE_TIME) { THROW_ERROR(S, "Input sample time must be discrete."); }}
/* Function: mdlInitializeConditions ========================================*/#define MDL_INITIALIZE_CONDITIONSstatic void mdlInitializeConditions(SimStruct *S){ int_T numBitsIn = (int_T) mxGetPr(NUMBITS_ARG)[0]; int_T errorCorr = (int_T) mxGetPr(ERRORCORR_ARG)[0];
int_T checkRM = (int_T) mxGetPr(CHECKRM_ARG)[0];
int_T deltaNi = (int_T) mxGetPr(DELNIMAX_ARG)[0];
TRmPar *rmPar = NULL;
/* Check parameters */
{
if(numBitsIn != ssGetInputPortWidth(S, INPORT) || numBitsIn != ssGetOutputPortWidth(S, OUTPORT) - deltaNi )
THROW_ERROR(S, "The parameter Number of Bits in Rate Matching Mask has to be equal \
to actual portwidth of the block.");
}
else
{
if(numBitsIn != ssGetInputPortWidth(S, INPORT) - deltaNi || numBitsIn != ssGetOutputPortWidth(S, OUTPORT))
THROW_ERROR(S, "The parameter Number of Bits in Rate DeMatching Mask has to be equal \
to portwidth of the block prior to puncturing or repetition in the Transmitter.");
}
/* Allocate memory for pWork Structure */ rmPar = (TRmPar *) calloc(1,sizeof(TRmPar));
/* Store input parameters in struct */
parDeltaNi = deltaNi;
parCheckRM = checkRM;
parNumBitsIn = numBitsIn;
/* Allocate memory for Rate Matching Pattern vector */
parPattern = (int_T *) calloc(parNumBitsIn, sizeof(int_T));
/* Compute B number of sequences after Bit Separation */
if((errorCorr<3) || ( (errorCorr==3) && (parDeltaNi>0))) /* Convolutional Encoding or Turbo coding when repetition */
parB = 1;
else /* Turbo encoding when puncturing */
parB = 3;
/* Allocate memory for Work vectors */
parEini = (int_T *) calloc(parB, sizeof(int_T));
parEminus = (int_T *) calloc(parB, sizeof(int_T));
parEplus = (int_T *) calloc(parB, sizeof(int_T));
/* Call the rmParams function to compute Rate Matching Paramters */ getRMParameters(rmPar);
/* Get Rate Matching puncturing or repetition pattern */ if(parB == 1)
rmPatternDetermination(rmPar);
/*else
rmTurboIndex(rmPar);*/
/* Store struct's pointer in Simulink's PWork */
ssGetPWork(S)[0] = rmPar;
}/* Function: mdlOutputs ====================================================*/static void mdlOutputs(SimStruct *S, int_T tid)
{
int_T k, inPortWidth;
TRmPar *rmPar = (TRmPar *) ssGetPWorkValue(S,0);
real_T *u = (real_T *) ssGetInputPortRealSignal(S, INPORT); real_T *y = (real_T *) ssGetOutputPortRealSignal(S, OUTPORT);
inPortWidth = ssGetInputPortWidth(S, INPORT);
rmComputeOutputVec(y, u, rmPar, inPortWidth);
}
/* End of mdlOutputs ========================================================*/
static void mdlTerminate(SimStruct *S){
TRmPar *rmPar = (TRmPar *) ssGetPWorkValue(S,0);
/* Free memory for Work vectors */
free(parPattern);
free(parEini);
free(parEminus);
free(parEplus);
free(rmPar);
}
#ifdef MATLAB_MEX_FILE#define MDL_SET_INPUT_PORT_DIMENSION_INFOstatic void mdlSetInputPortDimensionInfo(SimStruct *S, int_T port, const DimsInfo_T *dimsInfo){ int_T outCols, outRows; int_T numBits = (int_T)mxGetPr(NUMBITS_ARG)[0]; int_T delNimax = (int_T)mxGetPr(DELNIMAX_ARG)[0];
int_T checkRM = (int_T)mxGetPr(CHECKRM_ARG)[0];
int_T numDims = ssGetInputPortNumDimensions(S, INPORT);
int_T inRows = (numDims >= 1) ? dimsInfo->dims[0] : 0;
int_T inCols = (numDims >= 2) ? dimsInfo->dims[1] : 0;
if (!ssSetInputPortDimensionInfo(S, port, dimsInfo)) return;
if (inCols != 1) {
THROW_ERROR(S, "This block does not support multi-channel frame signals.\
Use multiple blocks to process multiple frames"); }
if ((checkRM == RMATCHING) && (inRows != numBits))
THROW_ERROR(S, "The input frame length must be same as the specified number of input bits .");
if ((checkRM == RDEMATCHING) && (inRows != numBits + delNimax))
THROW_ERROR(S, "The input frame length must be same as the specified number of input bits .");
outCols = inCols;
if (checkRM == RMATCHING)
outRows = inRows + delNimax;
else
outRows = inRows - delNimax;
if (ssGetOutputPortWidth(S,OUTPORT) == DYNAMICALLY_SIZED) {
if(!ssSetOutputPortMatrixDimensions(S,OUTPORT, outRows, outCols)) return;
}
else
{
if (ssGetOutputPortWidth(S, OUTPORT) != outRows) { THROW_ERROR(S, "Invalid Dimensions for Rate Matching and Dematching Block."); } }}
#define MDL_SET_OUTPUT_PORT_DIMENSION_INFO
static void mdlSetOutputPortDimensionInfo(SimStruct *S, int_T port, const DimsInfo_T *dimsInfo)
{
int_T inCols, inRows;
int_T numBits = (int_T)mxGetPr(NUMBITS_ARG)[0];
int_T delNimax = (int_T)mxGetPr(DELNIMAX_ARG)[0];
int_T checkRM = (int_T)mxGetPr(CHECKRM_ARG)[0];
int_T numDims = ssGetInputPortNumDimensions(S, INPORT);
int_T outRows = (numDims >= 1) ? dimsInfo->dims[0] : 0;
int_T outCols = (numDims >= 2) ? dimsInfo->dims[1] : 0;
if (!ssSetOutputPortDimensionInfo(S, port, dimsInfo)) return;
if (outCols != 1)
{
THROW_ERROR(S, "This block does not support multi-channel frame signals.\
`Use multiple blocks to process multiple frames");
}
if ((checkRM == RMATCHING) && (outRows != numBits+delNimax ))
THROW_ERROR(S, "Invalid Dimensions for Rate Matching and Dematching Block.");
if ((checkRM == RDEMATCHING) && (outRows != numBits))
THROW_ERROR(S, "Invalid Dimensions for Rate Matching and Dematching Block.");
inCols = outCols;
if (checkRM == RMATCHING)
inRows = outRows - delNimax;
else
inRows = outRows + delNimax;
if (ssGetInputPortWidth(S,INPORT) == DYNAMICALLY_SIZED)
{
if(!ssSetInputPortMatrixDimensions(S,OUTPORT, inRows, inCols)) return;
}
else
{
if (ssGetInputPortWidth(S, INPORT) != inRows)
{
THROW_ERROR(S, "Invalid Dimensions for Rate Matching and Dematching Block.");
}
}
}
#define MDL_SET_DEFAULT_PORT_DIMENSION_INFOstatic void mdlSetDefaultPortDimensionInfo(SimStruct *S){ /* initialize a dynamically-dimensioned DimsInfo_T */ DECL_AND_INIT_DIMSINFO(dInfo); int_T dims[2] = {1, 1}; /* select valid port dimensions */ dInfo.width = 1; dInfo.numDims = 2; dInfo.dims = dims; /* call the output functions */ if (ssGetOutputPortWidth(S,OUTPORT) == DYNAMICALLY_SIZED) { mdlSetOutputPortDimensionInfo(S, OUTPORT, &dInfo); } /* call the input functions */ if (ssGetInputPortWidth(S,INPORT) == DYNAMICALLY_SIZED) { mdlSetInputPortDimensionInfo(S, INPORT, &dInfo); }}#endif #ifdef MATLAB_MEX_FILE #include "simulink.c" #else#include "cg_sfun.h" #endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -