/******************************************************************************

  Copyright (C), 2001-2013, Texas Instrument.

 ******************************************************************************
  File Name     : Keystone_TCP3D.c
  Version       : Initial Draft
  Author        : Andy Yin
  Created       : 2013/8/29
  Last Modified :
  Description   : TCP3D initialization and driver

  Function List :
              Keystone_TCP3D_Init
              Keystone_TCP3D_TTICfg
              Keystone_TCP3D_Submit
              Keystone_TCP3D_PostProc
              Keystone_TCP3D_ISR
  History       :
  1.Date        : 2013/10/17
    Author      : Andy Yin
    Modification: Created file

* Limitation: The file Keystone_TCP3D.c should be compiled with debug option -g
******************************************************************************/
#include "Keystone_common.h"
#include "Keystone_TCP3D.h"
/*----------------------------------------------*
 * external variables                           *
 *----------------------------------------------*/

/*----------------------------------------------*
 * external routine prototypes                  *
 *----------------------------------------------*/

/*----------------------------------------------*
 * internal routine prototypes                  *
 *----------------------------------------------*/
void TCP3d_ControlRegsInit(Uint8 ucModeSel, CSL_Tcp3d_cfgRegs * ptTCP3dCfgReg);

CSL_Edma3ChannelHandle Tcp3d_EdmaInit
(
    CSL_Edma3ChannelObj   *ptEdmaChnObj,
    Uint8                 ucCcInstId,
    Uint8                 ucTcInstId,
    Uint8                 ucChanIdx,
    Uint16                uwPaRAMSet
);

void Tcp3d_EdmaPaRAMSetup
(
		CSL_TPCC_ParamsetRegs *ptPaRAMRegs,
        T_Tcp3d_EdmaPara *ptEdmaPara
);
/* interleaver table parameter for LTE and Wimax */
inline Int32 LTE_interleaver_index(Int32 K);
inline Int32 WIMAX_interleaver_index(Int32 K);
/* sliding window */
Int32 TCP3D_codeBlkSeg (
            Uint32  blockLengthK,
            Uint8   numMAP,
            Uint8  *sw0NomLen,
            Uint8  *sw0LenSel,
            Uint8  *sw1Len,
            Uint8  *sw2LenSel,
            Uint8  *numsw0);
/* beta state for LTE and WCMDA */
void Tcp3d_betaStates(
                    Int8    * restrict tailBits,
                    Int32   signChange,
                    Int32   Kt,
                    Int8    * restrict beta0Ptr,
                    Int8    * restrict beta1Ptr);
/*----------------------------------------------*
 * project-wide global variables                *
 *----------------------------------------------*/
const Int16 TCP3_WimaxInterleaverTable[17][4];
const Int16 TCP3_LteInterleaverTable[220][7];
/*----------------------------------------------*
 * module-wide global variables                 *
 *----------------------------------------------*/
/*----------------------------------------------*
 * constants                                    *
 *----------------------------------------------*/
const T_TCP3D_InstInfo gtTcp3dInstInfo[NUM_TCP3D] = {
		{
				(Uint32)CSL_PSC_PD_TCP3D_A,
				(Uint32)CSL_PSC_LPSC_TCP3D_A,
				(CSL_Tcp3d_cfgRegs *)CSL_TCP3D_A_CFG_REGS,
				(Uint32)CSL_TCP3D_A_DATA_REGS,

				(Uint8)2,
				{
						(Uint8)CSL_TPCC2_TCP3D_A_REVT0,
						(Uint8)CSL_TPCC2_TCP3D_A_REVT1,
				}
		}, /* TCP3D_0 */
		{
				(Uint32)CSL_PSC_PD_TCP3D_B,
				(Uint32)CSL_PSC_LPSC_TCP3D_B,
				(CSL_Tcp3d_cfgRegs *)CSL_TCP3D_B_CFG_REGS,
				(Uint32)CSL_TCP3D_B_DATA_REGS,

				(Uint8)2,
				{
						(Uint8)CSL_TPCC2_TCP3D_B_REVT0,
						(Uint8)CSL_TPCC2_TCP3D_B_REVT1,
				}
		}, /* TCP3D_1 */
#ifdef DEVICE_TN
		{
				(Uint32)CSL_PSC_PD_BCP_FFTC_C_TCP3D_C,
				(Uint32)CSL_PSC_LPSC_BCP_FFTC_C_TCP3D_C,
				(CSL_Tcp3d_cfgRegs *)CSL_TCP3D_C_CFG_REGS,
				(Uint32)CSL_TCP3D_C_DATA_REGS,

				(Uint8)2,
				{
						(Uint8)CSL_TPCC2_TCP3D_C_REVT0,
						(Uint8)CSL_TPCC2_TCP3D_C_REVT1,
				}
		}, /* TCP3D_2 */
#endif
};

const T_TCP3D_DmaOffset gtTcp3dDmaOffset[2] = {
		{
				(Uint32)CSL_TCP3D_DMA_TCP3D_IC_CFG0_P0_OFFSET,
				(Uint32)CSL_TCP3D_DMA_TCP3D_SYS_P0_OFFSET,
				(Uint32)CSL_TCP3D_DMA_TCP3D_PAR0_P0_OFFSET,
				(Uint32)CSL_TCP3D_DMA_TCP3D_PAR1_P0_OFFSET,
				(Uint32)CSL_TCP3D_DMA_TCP3D_OUT_HD0_OFFSET,
				(Uint32)CSL_TCP3D_DMA_TCP3D_OUT_STS0_P0_OFFSET,
		},
		{
				(Uint32)CSL_TCP3D_DMA_TCP3D_IC_CFG0_P1_OFFSET,
				(Uint32)CSL_TCP3D_DMA_TCP3D_SYS_P1_OFFSET,
				(Uint32)CSL_TCP3D_DMA_TCP3D_PAR0_P1_OFFSET,
				(Uint32)CSL_TCP3D_DMA_TCP3D_PAR1_P1_OFFSET,
				(Uint32)CSL_TCP3D_DMA_TCP3D_OUT_HD1_OFFSET,
				(Uint32)CSL_TCP3D_DMA_TCP3D_OUT_STS0_P1_OFFSET,
		}
};

/*----------------------------------------------*
 * macros                                       *
 *----------------------------------------------*/
/**
 * @brief   Macro for computing Kext value for WCDMA using the formula
 *              Kext=4*Ceil(K/4)
 */
#define COMPUTE_KEXT(a)         (4*((a+3)>>2))

/**
 * @brief   Macro for computing Kout value for WCDMA using the formula
 *              Kout = (2*KEXT-K).
 * @ref     COMPUTE_KEXT macro
 */
#define COMPUTE_KOUT(x)         ((2*COMPUTE_KEXT(x))-(x))

/**
 * @brief   Macro for computing Kt value for WCDMA using the formula
 *              Kt = 3 - (Kext-K)
 * @ref     COMPUTE_KOUT macro
 */
#define COMPUTE_KT(x)           (3 -(COMPUTE_KEXT(x)-(x)))
/*----------------------------------------------*
 * routines' implementations                    *
 *----------------------------------------------*/

/*****************************************************************************
 Prototype    : Keystone_TCP3D_Init
 Description  : Power on the TCP3D, initialize the global TCP3d control registers,
                Initialize the TCP3D in/out EDMA,
                Init the IC config registers for each block
 Input        : pTcp3dHdl: Used to store current resource for TTI config, submit and debug
                ptTcp3dResInfo: input hardware resource info
                ptTcp3dComAppInfo: input common app para
                ptTcp3dICCfgBuf: start address of IC config buffer
                ucMaxSupportBlockNum: maximum block number to be supported
 Output       : None
 Return Value :

  History        :
  1.Date         : 2013/10/17
    Author       : Andy
    Modification : Created function

*****************************************************************************/
Int16 Keystone_TCP3D_Init
(
		void                    * restrict pTcp3dHdl,
		T_TCP3D_ResInfo         * restrict ptTcp3dResInfo,
		T_TCP3D_ComAppInfo      * restrict ptTcp3dComAppInfo,
		T_Tcp3dICCfgParams      * restrict ptTcp3dICCfgBuf,
		Uint8                              ucMaxSupportBlockNum
)
{
	Int32  i, j;

	Uint8  ucTcpId;

	T_TCP3D_Hdl *ptTcp3dHdl;

	/* EDMA variable */
	CSL_Edma3ChannelObj tEdmaInChnObj[2], tEdmaOutChnObj[2]; /* two input channel handle, two output channel handle */
    CSL_Edma3ChannelHandle tHEdmaCh[2];
    T_Tcp3d_EdmaPara tTcp3d_EdmaPara;
    CSL_TPCC_ParamsetRegs *ptPaRAMRegs = NULL;
    CSL_Status tStatus;
    Uint16  uwPaRAMSet, uwPingPongStartSet[2]; /* ping-pong set */
    Uint8   ucPingPongBlockNum[2];  /* number of block for ping-pong channel */

	if((ptTcp3dResInfo == NULL) || (pTcp3dHdl == NULL))
	{
		return -1;  /* input resource handle is invalid */
	}
	ucTcpId = ptTcp3dResInfo->ucTCPId;
	if(ucTcpId > NUM_TCP3D)
	{
		return -2; /* input para is invalid */
	}

	ptTcp3dHdl = (T_TCP3D_Hdl *)pTcp3dHdl;
	ptTcp3dHdl->ucTCPId = ucTcpId;
	ptTcp3dHdl->ucModeSel = ptTcp3dComAppInfo->ucModeSel;

	/* power on TCP3D */
	KeyStone_enable_PSC_module(gtTcp3dInstInfo[ucTcpId].udGlbPscModuleNum, gtTcp3dInstInfo[ucTcpId].udLocalPscModuleNum);

	/* init the global control registers */
	TCP3d_ControlRegsInit(ptTcp3dComAppInfo->ucModeSel, gtTcp3dInstInfo[ucTcpId].ptTCP3dCfgReg);

	ucPingPongBlockNum[0] = ((ucMaxSupportBlockNum + 1) >> 1);
	ucPingPongBlockNum[1] = ucMaxSupportBlockNum >> 1;

    ptTcp3dHdl->ucMaxSupportPingPongBlockNum[0] = ucPingPongBlockNum[0];
    ptTcp3dHdl->ucMaxSupportPingPongBlockNum[1] = ucPingPongBlockNum[1];

	/* EDMA in channel init and setup */
	uwPaRAMSet = ptTcp3dResInfo->uwInPaRAMSetStartIdx;
	uwPingPongStartSet[0] = uwPaRAMSet + 4;   /* 2sets@channel, one for direct map, the other for dummy set */
	uwPingPongStartSet[1] = uwPingPongStartSet[0] + ucPingPongBlockNum[0] * 2; /* each block with 2sets, one for cfg and one for LLR */
    for(j = 0; j < 2; j++) /* input ping-pong channel */
    {
    	if(ucPingPongBlockNum[j] == 0)
    	{
    		continue;
    	}
    	tHEdmaCh[j] = Tcp3d_EdmaInit(&tEdmaInChnObj[j],
    			                     ptTcp3dResInfo->ucInEdmaTpcc,
    			                     ptTcp3dResInfo->ucInEdmaTc[j],
    			                     ptTcp3dResInfo->ucInEdmaCh[j],
    			                     (uwPaRAMSet + j * 2)  /* two dummy set for one channel */
    	                             );
    	/* dummy set init */
    	memset((void *)&tTcp3d_EdmaPara, 0, sizeof(T_Tcp3d_EdmaPara));
    	tTcp3d_EdmaPara.uwAcnt = 4;  /* at least one of the cnt fields is nonzero */
    	/* dummy set is used to link and chain the next block's PaRAM set */
    	tTcp3d_EdmaPara.ucTcchEn = CSL_EDMA3_TCCH_EN;
    	tTcp3d_EdmaPara.ucTCC = ptTcp3dResInfo->ucInEdmaCh[j];
    	tTcp3d_EdmaPara.uwLinkPaRAMSetIdx = uwPingPongStartSet[j]; /* link the ping-pong start set */
        ptPaRAMRegs = (CSL_TPCC_ParamsetRegs *)CSL_edma3GetParamHandle (tHEdmaCh[j], uwPaRAMSet + j * 2, &tStatus);
    	Tcp3d_EdmaPaRAMSetup(ptPaRAMRegs, &tTcp3d_EdmaPara);
        /* the current TTI's last set link the dummy set */
        ptPaRAMRegs = (CSL_TPCC_ParamsetRegs *)CSL_edma3GetParamHandle (tHEdmaCh[j], uwPaRAMSet + j * 2 + 1, &tStatus);
    	Tcp3d_EdmaPaRAMSetup(ptPaRAMRegs, &tTcp3d_EdmaPara);

        /* IC_CFG and DATA SET for each block */
    	memset((void *)&tTcp3d_EdmaPara, 0, sizeof(T_Tcp3d_EdmaPara));
        tTcp3d_EdmaPara.ucTCC = ptTcp3dResInfo->ucInEdmaCh[j];

    	/* IC_CFG set, link the next set and chain itself for input data
    	 * To be updated parameters: udSrcAddr */
    	tTcp3d_EdmaPara.ucSyncDim = CSL_EDMA3_SYNC_A;
    	tTcp3d_EdmaPara.ucTcchEn = CSL_EDMA3_TCCH_EN;     /* chain the LLR input set */
    	tTcp3d_EdmaPara.uwAcnt = TCP3D_IC_CFG_REGS_SIZE;  /* 15*4B */
    	tTcp3d_EdmaPara.uwBcnt = 1;
    	tTcp3d_EdmaPara.uwCcnt = 1;
    	tTcp3d_EdmaPara.udDstAddr = gtTcp3dInstInfo[ucTcpId].udTcp3dDataRegsAddress + gtTcp3dDmaOffset[j].udInICCfg;
        for(i = 0; i < ucPingPongBlockNum[j]; i++)
        {
        	tTcp3d_EdmaPara.uwLinkPaRAMSetIdx = uwPingPongStartSet[j] + i * 2 + 1; /* link the DATA_SET */
        	ptPaRAMRegs = (CSL_TPCC_ParamsetRegs *)CSL_edma3GetParamHandle (tHEdmaCh[j], uwPingPongStartSet[j] + i * 2, &tStatus);
        	Tcp3d_EdmaPaRAMSetup(ptPaRAMRegs, &tTcp3d_EdmaPara);
        }

        /* Data set, LINK the next set, but with chain disabled */
        memset((void *)&tTcp3d_EdmaPara, 0, sizeof(T_Tcp3d_EdmaPara));
        tTcp3d_EdmaPara.ucTCC = ptTcp3dResInfo->ucInEdmaCh[j];
        tTcp3d_EdmaPara.ucSyncDim = CSL_EDMA3_SYNC_AB;
        tTcp3d_EdmaPara.ucItcchEn = CSL_EDMA3_ITCCH_EN;
        tTcp3d_EdmaPara.udDstAddr = gtTcp3dInstInfo[ucTcpId].udTcp3dDataRegsAddress + gtTcp3dDmaOffset[j].udInSys;
        /* input data order is different for WCDMA and LTE&Wimax
         * To be updated parameters: uwAcnt, uwSrcBidx, uwSrcCidx, udSrcAddr */
        if(ptTcp3dComAppInfo->ucModeSel == 3)
        {/* WCDMA */
            tTcp3d_EdmaPara.uwBcnt = 3; /* sys, par0, par1 */
            tTcp3d_EdmaPara.uwCcnt = 1;
            tTcp3d_EdmaPara.uwDstBidx = TCP3D_DMA_SYS_PAR_OFFSET;
            tTcp3d_EdmaPara.uwDstCidx = 0;
        }
        else
        {/* for LTE and Wimax mode */
            tTcp3d_EdmaPara.uwBcnt = 2;  /* two half data */
            tTcp3d_EdmaPara.uwCcnt = 3;  /* sys, par0, par1 */
            tTcp3d_EdmaPara.uwDstBidx = TCP3D_DMA_HALF_SYS_SIZE;
            tTcp3d_EdmaPara.uwDstCidx = TCP3D_DMA_SYS_PAR_OFFSET;
        }
        for(i = 0; i < ucPingPongBlockNum[j]; i++)
        {
            tTcp3d_EdmaPara.uwLinkPaRAMSetIdx = uwPingPongStartSet[j] + (i + 1) * 2; /* link the next block's IC_CFG set */
            ptPaRAMRegs = (CSL_TPCC_ParamsetRegs *)CSL_edma3GetParamHandle (tHEdmaCh[j], uwPingPongStartSet[j] + i * 2 + 1, &tStatus);
            Tcp3d_EdmaPaRAMSetup(ptPaRAMRegs, &tTcp3d_EdmaPara);
        }
    }
    ptTcp3dHdl->atInEdmaObj[0] = tEdmaInChnObj[0];
    ptTcp3dHdl->atInEdmaObj[1] = tEdmaInChnObj[1];
    ptTcp3dHdl->uwInChMapPaRAMSetIdx[0] = uwPaRAMSet;
    ptTcp3dHdl->uwInChMapPaRAMSetIdx[1] = uwPaRAMSet + 2;
    ptTcp3dHdl->uwInUePaRAMSetStartIdx[0] = uwPingPongStartSet[0];
    ptTcp3dHdl->uwInUePaRAMSetStartIdx[1] = uwPingPongStartSet[1];

    ptPaRAMRegs = (CSL_TPCC_ParamsetRegs *)CSL_edma3GetParamHandle (tHEdmaCh[0], uwPingPongStartSet[0], &tStatus);
    ptTcp3dHdl->ptInUeStartPaRAMRegs[0] = ptPaRAMRegs;

    ptPaRAMRegs = (CSL_TPCC_ParamsetRegs *)CSL_edma3GetParamHandle (tHEdmaCh[1], uwPingPongStartSet[1], &tStatus);
    ptTcp3dHdl->ptInUeStartPaRAMRegs[1] = ptPaRAMRegs;

    /* out EDMA channel */
    uwPaRAMSet = ptTcp3dResInfo->uwOutPaRAMSetStartIdx;
	uwPingPongStartSet[0] = uwPaRAMSet + 4;
	uwPingPongStartSet[1] = uwPingPongStartSet[0] + ucPingPongBlockNum[0] * 2; /* each block with 2sets */
    for(j = 0; j < 2; j++)
    {
    	if(ucPingPongBlockNum[j] == 0)
    	{
    		continue;
    	}
    	tHEdmaCh[j] = Tcp3d_EdmaInit(&tEdmaOutChnObj[j],
			                         gtTcp3dInstInfo[ucTcpId].ucEdmaCCInst,
			                         ptTcp3dResInfo->ucOutEdmaTc[j],
			                         gtTcp3dInstInfo[ucTcpId].ucRevtEdmaChannel[j],
			                         (uwPaRAMSet + j * 2)  /* two dummy set for one channel */
	                                 );
    	/* dummy set init */
		memset((void *)&tTcp3d_EdmaPara, 0, sizeof(T_Tcp3d_EdmaPara));
		tTcp3d_EdmaPara.uwAcnt = 4;  /* at least one of the CNT fields is nonzero */
		/* dummy set is used to link and chain the next block's PaRAM set */
		tTcp3d_EdmaPara.ucTcchEn = CSL_EDMA3_TCCH_EN;
		tTcp3d_EdmaPara.ucTCC = gtTcp3dInstInfo[ucTcpId].ucRevtEdmaChannel[j];
		tTcp3d_EdmaPara.uwLinkPaRAMSetIdx = uwPingPongStartSet[j]; /* link the ping-pong start set */
		ptPaRAMRegs = (CSL_TPCC_ParamsetRegs *)CSL_edma3GetParamHandle (tHEdmaCh[j], uwPaRAMSet + j * 2, &tStatus);
		Tcp3d_EdmaPaRAMSetup(ptPaRAMRegs, &tTcp3d_EdmaPara);
        /* DUMMY SET */
		ptPaRAMRegs = (CSL_TPCC_ParamsetRegs *)CSL_edma3GetParamHandle (tHEdmaCh[j], uwPaRAMSet + j * 2 + 1, &tStatus);
		Tcp3d_EdmaPaRAMSetup(ptPaRAMRegs, &tTcp3d_EdmaPara);

		/* Hard bit and decoder status SET for each block */
		memset((void *)&tTcp3d_EdmaPara, 0, sizeof(T_Tcp3d_EdmaPara));
		tTcp3d_EdmaPara.ucTCC = gtTcp3dInstInfo[ucTcpId].ucRevtEdmaChannel[j];

		/* Hard bit set, link the next set and chain itself for decoder status output
		 * To be updated parameters: uwAcnt, udDstAddr */
		tTcp3d_EdmaPara.ucSyncDim = CSL_EDMA3_SYNC_A;
		tTcp3d_EdmaPara.ucTcchEn = CSL_EDMA3_TCCH_EN;
		tTcp3d_EdmaPara.uwBcnt = 1;
		tTcp3d_EdmaPara.uwCcnt = 1;
		tTcp3d_EdmaPara.udSrcAddr = gtTcp3dInstInfo[ucTcpId].udTcp3dDataRegsAddress + gtTcp3dDmaOffset[0].udOutHD;
		if(ptTcp3dComAppInfo->ucModeSel == 3)
		{/* WCDMA Split mode */
		    tTcp3d_EdmaPara.udSrcAddr = gtTcp3dInstInfo[ucTcpId].udTcp3dDataRegsAddress + gtTcp3dDmaOffset[j].udOutHD;
		}
		for(i = 0; i < ucPingPongBlockNum[j]; i++)
		{
			tTcp3d_EdmaPara.uwLinkPaRAMSetIdx = uwPingPongStartSet[j] + i * 2 + 1;
			ptPaRAMRegs = (CSL_TPCC_ParamsetRegs *)CSL_edma3GetParamHandle (tHEdmaCh[j], uwPingPongStartSet[j] + i * 2, &tStatus);
			Tcp3d_EdmaPaRAMSetup(ptPaRAMRegs, &tTcp3d_EdmaPara);
		}

		/* decoder status set, LINK the next set but with chain disabled
		 * To be updated parameters: udDstAddr, ucTcchEn */
		memset((void *)&tTcp3d_EdmaPara, 0, sizeof(T_Tcp3d_EdmaPara));
		tTcp3d_EdmaPara.ucTCC = ptTcp3dResInfo->ucInEdmaCh[j];  /* chain the input channel  */
		tTcp3d_EdmaPara.ucSyncDim = CSL_EDMA3_SYNC_A;
		tTcp3d_EdmaPara.uwAcnt = 12;   /* decoder status */
		tTcp3d_EdmaPara.uwBcnt = 1;
		tTcp3d_EdmaPara.uwCcnt = 1;
		tTcp3d_EdmaPara.udSrcAddr = gtTcp3dInstInfo[ucTcpId].udTcp3dDataRegsAddress + gtTcp3dDmaOffset[0].udOutStatus;
		if(ptTcp3dComAppInfo->ucModeSel == 3)
		{/* WCDMA Split mode */
		    tTcp3d_EdmaPara.udSrcAddr = gtTcp3dInstInfo[ucTcpId].udTcp3dDataRegsAddress + gtTcp3dDmaOffset[j].udOutStatus;
		}
		for(i = 0; i < ucPingPongBlockNum[j]; i++)
		{
			tTcp3d_EdmaPara.uwLinkPaRAMSetIdx = uwPingPongStartSet[j] + (i + 1) * 2;
			ptPaRAMRegs = (CSL_TPCC_ParamsetRegs *)CSL_edma3GetParamHandle (tHEdmaCh[j], uwPingPongStartSet[j] + i * 2 + 1, &tStatus);
			Tcp3d_EdmaPaRAMSetup(ptPaRAMRegs, &tTcp3d_EdmaPara);
		}
    }
    ptTcp3dHdl->atOutEdmaObj[0] = tEdmaOutChnObj[0];
    ptTcp3dHdl->atOutEdmaObj[1] = tEdmaOutChnObj[1];

    ptTcp3dHdl->uwOutChMapPaRAMSetStartIdx[0] = uwPaRAMSet;
    ptTcp3dHdl->uwOutChMapPaRAMSetStartIdx[1] = uwPaRAMSet + 2;
    ptTcp3dHdl->uwOutUePaRAMSetStartIdx[0] = uwPingPongStartSet[0];
    ptTcp3dHdl->uwOutUePaRAMSetStartIdx[1] = uwPingPongStartSet[1];

    ptPaRAMRegs = (CSL_TPCC_ParamsetRegs *)CSL_edma3GetParamHandle (tHEdmaCh[0], uwPingPongStartSet[0], &tStatus);
    ptTcp3dHdl->ptOutUeStartPaRAMRegs[0] = ptPaRAMRegs;

    ptPaRAMRegs = (CSL_TPCC_ParamsetRegs *)CSL_edma3GetParamHandle (tHEdmaCh[1], uwPingPongStartSet[1], &tStatus);
    ptTcp3dHdl->ptOutUeStartPaRAMRegs[1] = ptPaRAMRegs;

	/* IC_CFG_REGS init, here init the static field */
	memset((void *)ptTcp3dICCfgBuf, 0, ucMaxSupportBlockNum * sizeof(T_Tcp3dICCfgParams));
	for(i = 0; i < ucMaxSupportBlockNum; i++)
	{
		ptTcp3dICCfgBuf[i].crcIterSel = CSL_TCP3D_DMA_TCP3D_IC_CFG2_P0_CRC_ITER_PASS_MATCH1; /* valid for LTE */
		ptTcp3dICCfgBuf[i].stopSel = ptTcp3dComAppInfo->ucStopSel;
		ptTcp3dICCfgBuf[i].snrVal = ptTcp3dComAppInfo->ucSNRVal;
		ptTcp3dICCfgBuf[i].maxIter = ptTcp3dComAppInfo->ucMaxItr;
		ptTcp3dICCfgBuf[i].minIter = TCP3D_MIN_ITERATIONS;
		ptTcp3dICCfgBuf[i].extScaleEn = CSL_TCP3D_DMA_TCP3D_IC_CFG2_P0_EXT_SCALE_EN_ENABLED;
#ifdef _BIG_ENDIAN
		ptTcp3dICCfgBuf[i].outOrderSel = CSL_TCP3D_DMA_TCP3D_IC_CFG2_P0_OUT_ORDER_SEL_SWAP;  /* 1-swap for big endian, output with the older bit at MSB32 */
#else
		ptTcp3dICCfgBuf[i].outOrderSel = CSL_TCP3D_DMA_TCP3D_IC_CFG2_P0_OUT_ORDER_SEL_NO_SWAP; /* 0-No swap for little endian, output with the older bit at LSB0 */
#endif
		ptTcp3dICCfgBuf[i].outStsRead = CSL_TCP3D_DMA_TCP3D_IC_CFG2_P0_OUT_FLAG_EN_READ;
		ptTcp3dICCfgBuf[i].maxStar = CSL_TCP3D_DMA_TCP3D_IC_CFG2_P0_MAXST_EN_DISABLED;
		ptTcp3dICCfgBuf[i].intLoadSel = CSL_TCP3D_DMA_TCP3D_IC_CFG2_P0_INTER_LOAD_SEL_SET; /* interleaver generation internal TCP3D */
		ptTcp3dICCfgBuf[i].snrReport = CSL_TCP3D_DMA_TCP3D_IC_CFG2_P0_SNR_REP_ENABLED; //report SNR for WCDMA throughput test

		ptTcp3dICCfgBuf[i].maxStarThres = 0;    /* max star disabled */
		ptTcp3dICCfgBuf[i].maxStarValue = 0;

        /* initialize the extrinisic scale factor */
		ptTcp3dICCfgBuf[i].extrScale0 = 24;
		ptTcp3dICCfgBuf[i].extrScale1 = 24;
		ptTcp3dICCfgBuf[i].extrScale2 = 24;
		ptTcp3dICCfgBuf[i].extrScale3 = 24;
		ptTcp3dICCfgBuf[i].extrScale4 = 24;
		ptTcp3dICCfgBuf[i].extrScale5 = 24;
		ptTcp3dICCfgBuf[i].extrScale6 = 24;
		ptTcp3dICCfgBuf[i].extrScale7 = 24;
		ptTcp3dICCfgBuf[i].extrScale8 = 24;
		ptTcp3dICCfgBuf[i].extrScale9 = 24;
		ptTcp3dICCfgBuf[i].extrScale10 = 24;
		ptTcp3dICCfgBuf[i].extrScale11 = 24;
		ptTcp3dICCfgBuf[i].extrScale12 = 24;
		ptTcp3dICCfgBuf[i].extrScale13 = 24;
		ptTcp3dICCfgBuf[i].extrScale14 = 24;
		ptTcp3dICCfgBuf[i].extrScale15 = 24;
	}

	return 0;
}
/*****************************************************************************
 Prototype    : Keystone_TCP3D_TTICfg
 Description  : Update the IC configuration registers for each block,
                Modify the output channel set's chain field, chain the next ue's input channel,
                and generate interrupt for the last ue set
 Input        : pTcp3dHdl
                ptTcp3dBlockInfoAddr: start address of current CB information
                ucBlockNumPerUe: number of block for each ue, here is the array address for all ue
                ucCurUeNum: to be processed ue number

 Output       : None
 Return Value :

  History        :
  1.Date         : 2013/10/17
    Author       : Andy
    Modification : Created function

Note: This function should be compiled with -g
*****************************************************************************/
Int16 Keystone_TCP3D_TTICfg
(
		void                    * restrict pTcp3dHdl,
		T_TCP3D_BlockInfo       * restrict ptTcp3dBlockInfoAddr,
		Uint8                   * restrict ucBlockNumPerUe,
		Uint8                              ucCurUeNum
)
{
    Int32 i, j, k, ii;
    Uint32  udTmpValue;
    Uint8 ucPingPongBlockNum[2];       /* ping-pong block num for each ue */
    Uint8 ucTotalPingPongBlockNum[2];  /* total block num for all ue */

	CSL_TPCC_ParamsetRegs *ptInPaRAMRegs;
	CSL_TPCC_ParamsetRegs *ptOutPaRAMRegs;
	Uint16 uwInChMapPaRAMSetIdx, uwInUePaRAMSetIdx;
	Uint16 uwOutChMapPaRAMSetIdx, uwOutUePaRAMSetIdx;

	T_TCP3D_Hdl *ptTcp3dHdl;
	Uint16 uwBlockSize;

	T_Tcp3dICCfgParams *ptTcpIcCfg;
	/* temp variable for TCP3D IC generation */
    Uint8 sw0NomLen;
    Uint8 sw0LenSel;
    Uint8 sw1Len;
    Uint8 sw2LenSel;
    Uint8 numsw0;
    Uint8 numMap;

    Int32 signChange;
    Int32 Kt;

    Int32 frameLenInd;

    Uint8  ucChanNum[2];

	ptTcp3dHdl = (T_TCP3D_Hdl *)pTcp3dHdl;

	k = 0;
	ucTotalPingPongBlockNum[0] = 0;
	ucTotalPingPongBlockNum[1] = 0;
    for(i = 0; i < ucCurUeNum; i++)
    {
    	ucPingPongBlockNum[0] = (ucBlockNumPerUe[i] + 1) >> 1;
    	ucPingPongBlockNum[1] = ucBlockNumPerUe[i] >> 1;
        for(ii = 0; ii < 2; ii++)
        {/* for(ping_pong) */
			/* update the ping-pong input set */
			ptInPaRAMRegs = ptTcp3dHdl->ptInUeStartPaRAMRegs[ii] + ucTotalPingPongBlockNum[ii] * 2;
			ptOutPaRAMRegs = ptTcp3dHdl->ptOutUeStartPaRAMRegs[ii] + ucTotalPingPongBlockNum[ii] * 2;
			uwInUePaRAMSetIdx = ptTcp3dHdl->uwInUePaRAMSetStartIdx[ii] + ucTotalPingPongBlockNum[ii] * 2;
			uwOutUePaRAMSetIdx = ptTcp3dHdl->uwOutUePaRAMSetStartIdx[ii] + ucTotalPingPongBlockNum[ii] * 2;

			for(j = 0; j < ucPingPongBlockNum[ii]; j++)
			{
				/* update the IC_CFG PaRAM set field: udSrcAddr */
				ptInPaRAMRegs[j * 2].SRC = GLOBAL_ADDR((Uint32)ptTcp3dBlockInfoAddr[k].pudInICCfg);

				/* update the LLR PaRAM set field: udSrcAddr, uwAcnt, uwSrcBidx, uwSrcCidx */
				ptInPaRAMRegs[j * 2 + 1].SRC = GLOBAL_ADDR((Uint32)ptTcp3dBlockInfoAddr[k].pscInputSysLLR);

				udTmpValue = ptInPaRAMRegs[j * 2 + 1].LINK_BCNTRLD >> 16;
				ptInPaRAMRegs[j * 2 + 1].LINK_BCNTRLD = (udTmpValue << 16) | (32 * (uwInUePaRAMSetIdx + j * 2 + 2)); /* LINK the next UE CFG */
				uwBlockSize = ptTcp3dBlockInfoAddr[k].uwBlockSize;
				if(ptTcp3dHdl->ucModeSel == 3) /* WCDMA mode */
				{
					/* Acnt */
					udTmpValue = ptInPaRAMRegs[j * 2 + 1].A_B_CNT >> 16;
					ptInPaRAMRegs[j * 2 + 1].A_B_CNT = (udTmpValue << 16) | ((((uwBlockSize + 3) >> 2) * 4 - uwBlockSize) * 2 + uwBlockSize); /* 2*(uwBlockSize%4 - uwBlockSize)+uwBlockSize (Table3-2 TCP3D UG) */
					/* SRC_BIDX */
					udTmpValue = ptInPaRAMRegs[j * 2 + 1].SRC_DST_BIDX >> 16;
					ptInPaRAMRegs[j * 2 + 1].SRC_DST_BIDX = (udTmpValue << 16) | ((Uint32)ptTcp3dBlockInfoAddr[k].pscInputP0LLR - (Uint32)ptTcp3dBlockInfoAddr[k].pscInputSysLLR);
				}
				else
				{/* LTE or Wimax mode */
					udTmpValue = ptInPaRAMRegs[j * 2 + 1].A_B_CNT >> 16;
					ptInPaRAMRegs[j * 2 + 1].A_B_CNT = (udTmpValue << 16) | (uwBlockSize >> 1);   /* Acnt */
					udTmpValue = ptInPaRAMRegs[j * 2 + 1].SRC_DST_BIDX >> 16;
					ptInPaRAMRegs[j * 2 + 1].SRC_DST_BIDX = (udTmpValue << 16) | (ptTcp3dBlockInfoAddr[k].uwBlockSize >> 1); /* uwSrcBidx */
					udTmpValue = ptInPaRAMRegs[j * 2 + 1].SRC_DST_CIDX >> 16;
					ptInPaRAMRegs[j * 2 + 1].SRC_DST_CIDX = (udTmpValue << 16) | ((Uint32)ptTcp3dBlockInfoAddr[k].pscInputP0LLR - (Uint32)ptTcp3dBlockInfoAddr[k].pscInputSysLLR); /* uwSrcCidx */
				}

				/* update the set for HD out,  uwAcnt, udDstAddr */
				udTmpValue = ptOutPaRAMRegs[j * 2].A_B_CNT >> 16;
				ptOutPaRAMRegs[j * 2].A_B_CNT = (udTmpValue << 16) | ((uwBlockSize + 7) >> 3);
				ptOutPaRAMRegs[j * 2].DST = GLOBAL_ADDR((Uint32)ptTcp3dBlockInfoAddr[k].pucOutHardBit);

				/* update set for status out, udDstAddr, ucTcchEn, ucTCC */
				ptOutPaRAMRegs[j * 2 + 1].DST = GLOBAL_ADDR((Uint32)ptTcp3dBlockInfoAddr[k].pudOutStatus);
				ptOutPaRAMRegs[j * 2 + 1].OPT &= 0xffefffff; /* TCINTEN, disable the transfer completion interrupt */
				ptOutPaRAMRegs[j * 2 + 1].OPT |= (1 << 22);  /* TCCHEN, chain to input the next block */
				udTmpValue = ptOutPaRAMRegs[j * 2 + 1].LINK_BCNTRLD >> 16;
				ptOutPaRAMRegs[j * 2 + 1].LINK_BCNTRLD = (udTmpValue << 16) | (32 * (uwOutUePaRAMSetIdx + j * 2 + 2)); /* LINK */

				k++; /* update index for next block */
			}/* block for ping-pong */
			if(j > 0) /* ucPingPongBlockNum[ii]>0 */
			{
			    ptOutPaRAMRegs[(j - 1) * 2 + 1].OPT &= 0xffbfffff;  /* disable TCCHEN for the last block of current UE */
			    ptOutPaRAMRegs[(j - 1) * 2 + 1].OPT |= (1 << 20);   /* TCINTEN, enable transfer completion interrupt, TCC=input EDMA channel */
			}
		}/* ping-pong */
        ucTotalPingPongBlockNum[0] += ucPingPongBlockNum[0];
        ucTotalPingPongBlockNum[1] += ucPingPongBlockNum[1];
    }/* total ue */
    /* config the last set link to the dummy set,  */
    for(ii = 0; ii < 2; ii++)
    {
    	if(ucTotalPingPongBlockNum[ii] > 0)
    	{
            uwInChMapPaRAMSetIdx = ptTcp3dHdl->uwInChMapPaRAMSetIdx[ii];
            ptInPaRAMRegs = ptTcp3dHdl->ptInUeStartPaRAMRegs[ii] + ucTotalPingPongBlockNum[ii] * 2 - 1;
	        udTmpValue = ptInPaRAMRegs->LINK_BCNTRLD >> 16;
	        ptInPaRAMRegs->LINK_BCNTRLD = (udTmpValue << 16) | (32 * (uwInChMapPaRAMSetIdx + 1));  /* link the dummy set for next ping submit */

	        uwOutChMapPaRAMSetIdx = ptTcp3dHdl->uwOutChMapPaRAMSetStartIdx[ii];
	        ptOutPaRAMRegs = ptTcp3dHdl->ptOutUeStartPaRAMRegs[ii] + ucTotalPingPongBlockNum[ii] * 2 - 1;
	        udTmpValue = ptOutPaRAMRegs->LINK_BCNTRLD >> 16;
	        ptOutPaRAMRegs->LINK_BCNTRLD = (udTmpValue << 16) | (32 * (uwOutChMapPaRAMSetIdx + 1));  /* link the dummy set for next ping submit */
    	}
    }

    /* update the IC_CFG parameters for each block, the IC CFG address is ptTcp3dBlockInfoAddr[].pudInICCfg */
	numMap = 2; /* 2 for LTE and Wimax mode */
	if(ptTcp3dHdl->ucModeSel == 3)
	{/* WCDMA */
		numMap = 1; /* for WCDMA mode */
	}
	k = 0;
	for(i = 0; i < ucCurUeNum; i++)
	{
		for(j = 0; j < ucBlockNumPerUe[i]; j++)
		{
			uwBlockSize = ptTcp3dBlockInfoAddr[k].uwBlockSize;
			ptTcpIcCfg = (T_Tcp3dICCfgParams *)ptTcp3dBlockInfoAddr[k].pudInICCfg;

			/* crcPolySel, blockLn */
			ptTcpIcCfg->blockLen = uwBlockSize - 1; /* BLK_LN = Block size - 1 */
			ptTcpIcCfg->crcPolySel = ptTcp3dBlockInfoAddr[k].ucCrcSel;      /* LTE CRC polynomial select, only valid for LTE */

            /* sliding window length */
			sw0NomLen = ptTcp3dBlockInfoAddr[k].ucInitSw0Len;
			TCP3D_codeBlkSeg(uwBlockSize, numMap, &sw0NomLen, &sw0LenSel, &sw1Len, &sw2LenSel, &numsw0);
			ptTcpIcCfg->num_sw0 = numsw0;
			ptTcpIcCfg->sw1Len = sw1Len;
			ptTcpIcCfg->sw0LenSel = sw0LenSel;
			ptTcpIcCfg->sw2LenSel = sw2LenSel;

			if(ptTcp3dHdl->ucModeSel != 2)
			{/* beta state, only for LTE and WCDMA mode */
			    signChange = 0;
			    Kt = COMPUTE_KT(uwBlockSize);
			    Tcp3d_betaStates(ptTcp3dBlockInfoAddr[k].pscTailBits,
			                     signChange,
			                     Kt,
			                     (Int8 *)&(ptTcpIcCfg->betaMap0[0]),
			                     (Int8 *)&(ptTcpIcCfg->betaMap1[0]));
#if 0
			    Uint32 betaMap00 = 0x7F5F4060, betaMap01 = 0x7F5F4060;
			    Uint32 betaMap10 = 0x405F7F60, betaMap11 = 0x405F7F60;

			    memcpy((void *)&ptTcpIcCfg->betaMap0[0], (void *)&betaMap00, 4);
			    memcpy((void *)&ptTcpIcCfg->betaMap0[4], (void *)&betaMap01, 4);
			    memcpy((void *)&ptTcpIcCfg->betaMap1[0], (void *)&betaMap10, 4);
			    memcpy((void *)&ptTcpIcCfg->betaMap1[4], (void *)&betaMap11, 4);
#endif
			}

			/* interleaver table parameters */
            if(ptTcp3dHdl->ucModeSel == 1) /* LTE mode */
            {
                frameLenInd = LTE_interleaver_index(uwBlockSize);
                ptTcpIcCfg->itg_param0 = (Uint16)((2*TCP3_LteInterleaverTable[frameLenInd][2]) % TCP3_LteInterleaverTable[frameLenInd][0]);
                ptTcpIcCfg->itg_param1 = TCP3_LteInterleaverTable[frameLenInd][6];
                ptTcpIcCfg->itg_param2 = TCP3_LteInterleaverTable[frameLenInd][3];
                ptTcpIcCfg->itg_param3 = TCP3_LteInterleaverTable[frameLenInd][4];
                ptTcpIcCfg->itg_param4 = TCP3_LteInterleaverTable[frameLenInd][5];
            }
            else if(ptTcp3dHdl->ucModeSel == 2) /* Wimax mode */
            {
            	frameLenInd = WIMAX_interleaver_index(uwBlockSize);
                ptTcpIcCfg->itg_param0 = 0;
                ptTcpIcCfg->itg_param1 = TCP3_WimaxInterleaverTable[frameLenInd][0];
                ptTcpIcCfg->itg_param2 = TCP3_WimaxInterleaverTable[frameLenInd][1];
                ptTcpIcCfg->itg_param3 = TCP3_WimaxInterleaverTable[frameLenInd][2];
                ptTcpIcCfg->itg_param4 = TCP3_WimaxInterleaverTable[frameLenInd][3];
            }
            k++;
		}
	}

	/* clear the input EDMA channel IPR bit at TTI config */
    ucChanNum[0] = ptTcp3dHdl->atInEdmaObj[0].chaNum;
    ucChanNum[1] = ptTcp3dHdl->atInEdmaObj[1].chaNum;
    if(ucChanNum[0] > 31)
    {
    	ptTcp3dHdl->atOutEdmaObj[0].regs->TPCC_ICRH |= (1 << (ucChanNum[0] - 32));
    }
    else
    {
    	ptTcp3dHdl->atOutEdmaObj[0].regs->TPCC_ICR |= (1 << ucChanNum[0]);
    }

    if(ucChanNum[1] > 31)
    {
    	ptTcp3dHdl->atOutEdmaObj[1].regs->TPCC_ICRH |= (1 << (ucChanNum[1] - 32));
    }
    else
    {
    	ptTcp3dHdl->atOutEdmaObj[1].regs->TPCC_ICR |= (1 << ucChanNum[1]);
    }
    return 0;
}
/*****************************************************************************
 Prototype    : Keystone_TCP3D_PollFree
 Description  : Poll the input EDMA channel IPR bit to check whether the TCP3D is free or busy

 Input        : pTcp3dHdl
                ucLastProcBlockNum:
 Output       : None
 Return Value : return the free TcpID

  History        :
  1.Date         : 2013/10/17
    Author       : Andy
    Modification : Created function

*****************************************************************************/
Int16 Keystone_TCP3D_PollFree(void                  * restrict pTcp3dHdl,
		                      Uint8                            ucLastProcBlockNum)
{
	T_TCP3D_Hdl *ptTcp3dHdl;
    Uint8  ucChanNum[2];
    Uint32 udTmpIPR;

	ptTcp3dHdl = (T_TCP3D_Hdl *)pTcp3dHdl;

    if(ucLastProcBlockNum == 0)
    {
    	return (ptTcp3dHdl->ucTCPId);
    }
	/* clear the input EDMA channel IPR bit at TTI config */
    ucChanNum[0] = ptTcp3dHdl->atInEdmaObj[0].chaNum;
    ucChanNum[1] = ptTcp3dHdl->atInEdmaObj[1].chaNum;

    /* ping channel */
    if(ucChanNum[0] > 31)
    {
    	ucChanNum[0] -= 32;
    	do
    	{
    		udTmpIPR = (ptTcp3dHdl->atOutEdmaObj[0].regs->TPCC_IPRH >> ucChanNum[0]) & 0x1;
    	} while(udTmpIPR != 1);

    	ptTcp3dHdl->atOutEdmaObj[0].regs->TPCC_ICRH |= (1 << ucChanNum[0]);
    }
    else
    {
    	do
    	{
    		udTmpIPR = (ptTcp3dHdl->atOutEdmaObj[0].regs->TPCC_IPR >> ucChanNum[0]) & 0x1;
    	} while(udTmpIPR != 1);

    	ptTcp3dHdl->atOutEdmaObj[0].regs->TPCC_ICR |= (1 << ucChanNum[0]);
    }

    if(ucLastProcBlockNum > 2)
    {
        /* pong channel */
        if(ucChanNum[1] > 31)
        {
    	    ucChanNum[1] -= 32;
    	    do
    	    {
    	    	udTmpIPR = (ptTcp3dHdl->atOutEdmaObj[1].regs->TPCC_IPRH >> ucChanNum[1]) & 0x1;
    	    } while(udTmpIPR != 1);
    	    ptTcp3dHdl->atOutEdmaObj[1].regs->TPCC_ICRH |= (1 << ucChanNum[1]);
        }
        else
        {
        	do
        	{
        		udTmpIPR = (ptTcp3dHdl->atOutEdmaObj[1].regs->TPCC_IPR >> ucChanNum[1]) & 0x1;
        	} while(udTmpIPR != 1);
    	    ptTcp3dHdl->atOutEdmaObj[1].regs->TPCC_ICR |= (1 << ucChanNum[1]);
        }
    }

	return (ptTcp3dHdl->ucTCPId);  /* return the free TCP3d */
}
/*****************************************************************************
 Prototype    : Keystone_TCP3D_Submit
 Description  : trigger the decoder process

 Input        : pTcp3dHdl
                ucBlockNum: block number of the current ue to be submit
 Output       : None
 Return Value :

  History        :
  1.Date         : 2013/10/17
    Author       : Andy
    Modification : Created function

*****************************************************************************/
Int16 Keystone_TCP3D_Submit(void                    * restrict pTcp3dHdl,
		                    Uint8                              ucBlockNum)
{
	T_TCP3D_Hdl *ptTcp3dHdl;
    Uint8  ucChanNum;

	ptTcp3dHdl = (T_TCP3D_Hdl *)pTcp3dHdl;

    /* trigger the ping channel */
	ucChanNum = ptTcp3dHdl->atInEdmaObj[0].chaNum;
	if(ucChanNum > 31)
	{
		ucChanNum -= 32;
		ptTcp3dHdl->atInEdmaObj[0].regs->TPCC_ESRH |= (1 << ucChanNum);
	}
	else
	{
		ptTcp3dHdl->atInEdmaObj[0].regs->TPCC_ESR |= (1 << ucChanNum);
	}

	if(ucBlockNum > 1)
	{/* need to trigger the pong channel */
		ucChanNum = ptTcp3dHdl->atInEdmaObj[1].chaNum;
		if(ucChanNum > 31)
		{
			ucChanNum -= 32;
			ptTcp3dHdl->atInEdmaObj[1].regs->TPCC_ESRH |= (1 << ucChanNum);
		}
		else
		{
			ptTcp3dHdl->atInEdmaObj[1].regs->TPCC_ESR |= (1 << ucChanNum);
		}
	}

	return 0;
}
/*****************************************************************************
 Prototype    : Keystone_TCP3D_PostProc
 Description  : check the decoder status, CRC for LTE

 Input        : pTcp3dHdl
 Output       : None
 Return Value :

  History        :
  1.Date         : 2013/10/17
    Author       : Andy
    Modification : Created function

*****************************************************************************/
Int16 Keystone_TCP3D_PostProc(Uint8 ucMode, Uint8 ucBlockNum, Uint32 *pudDecStatus, Uint8 *pucStatus)
{
    Int32 i;

    if(ucMode == 1) /* LTE mode, use CRC stop criterion */
    {
        for(i = 0; i < ucBlockNum; i++)
        {
    	    pucStatus[i] = ((pudDecStatus[i * 3 + 1] >> 29) & 0x1);  /* 0-fail, 1-ok */
    	    if(pucStatus[i] == 0)
    	    {
    	    	printf ("LTE CB%d CRC failed\n", i);
    	    }
    	    else
    	    {/* 1- CRC passed */
    	    	printf ("LTE CB%d CRC passed\n", i);
    	    }
        }
    }

    else
    {/* Wimax and WCDMA mode, SNR threshold stop criterion */
    	for(i = 0; i < ucBlockNum; i++)
    	{
        	pucStatus[i] = ((pudDecStatus[i * 3 + 1] >> 30) & 0x3);  /* 0-MAP0 failed SNR, 1-MAP0 passed SNR */
        	if(pucStatus[i] == 0)
        	{
        		printf ("WCMDA CB%d SNR failed\n", i);
        	}
        	else
        	{/* 1-SNR passed */
        		printf ("WCMDA CB%d SNR passed\n", i);
        	}
    	}
    }

	return 0;
}
/*****************************************************************************
 Prototype    : TCP3d_ControlRegsInit
 Description  : Init the global control registers:
                TCP3D_SOFT_RESET
                TCP3D_MODE
                TCP3D_END
                TCP3D_EXE_P0/P1

 Input        : ucModeSel
 Output       : None
 Return Value :

  History        :
  1.Date         : 2013/10/17
    Author       : Andy
    Modification : Created function

*****************************************************************************/
void TCP3d_ControlRegsInit(Uint8 ucModeSel, CSL_Tcp3d_cfgRegs * ptTCP3dCfgReg)
{
    Uint32  reg = 0;

    /* Soft Reset the TCP3D */
    ptTCP3dCfgReg->TCP3_SOFT_RESET = 1;
    ptTCP3dCfgReg->TCP3_SOFT_RESET = 0;

    if(ucModeSel == 3)
    {/* WCDMA split mode with double_buffer mode disabled */
    	CSL_FINS (reg, TCP3D_CFG_TCP3_MODE_MODE_SEL, 3);
    	CSL_FINS (reg, TCP3D_CFG_TCP3_MODE_IN_MEM_DB_EN, 0);
    }
    else if(ucModeSel == 1)
    {/* LTE double buffer mode */
    	CSL_FINS (reg, TCP3D_CFG_TCP3_MODE_MODE_SEL, 1);
    	CSL_FINS (reg, TCP3D_CFG_TCP3_MODE_IN_MEM_DB_EN, 1);
    }
    else if(ucModeSel == 2)
    {/* Wimax double buffer mode */
    	CSL_FINS (reg, TCP3D_CFG_TCP3_MODE_MODE_SEL, 2);  /* Wimax */
    	CSL_FINS (reg, TCP3D_CFG_TCP3_MODE_IN_MEM_DB_EN, 1);
    }

    /* 1 = Internal Generation of Interleaver table enabled */
    CSL_FINS (reg, TCP3D_CFG_TCP3_MODE_ITG_EN, CSL_TCP3D_CFG_TCP3_MODE_ITG_EN_ENABLE);

    /* Error Ignore bit, 1 = Don't stop TCP3D on enabled errors */
    CSL_FINS (reg, TCP3D_CFG_TCP3_MODE_ERROR_IGNORE_EN, CSL_TCP3D_CFG_TCP3_MODE_ERROR_IGNORE_EN_DONT_STOP);

    /* 1 = Auto trigger enabled */
    CSL_FINS (reg, TCP3D_CFG_TCP3_MODE_AUTO_TRIG_EN, CSL_TCP3D_CFG_TCP3_MODE_AUTO_TRIG_EN_ENABLE);

    /* LTE CRC value selection - 0 for LTE */
    CSL_FINS (reg, TCP3D_CFG_TCP3_MODE_LTE_CRC_ISEL, 0);

    ptTCP3dCfgReg->TCP3_MODE = reg;

    /* Set ENDIAN register parameters, native or packed mode??? */
    reg = 0;
#ifdef _BIG_ENDIAN
    CSL_FINS (reg, TCP3D_CFG_TCP3_END_ENDIAN_INTR, CSL_TCP3D_CFG_TCP3_END_ENDIAN_INTR_32_BIT_PACKED);  /* no need as interleave table is generated internally */

    CSL_FINS (reg, TCP3D_CFG_TCP3_END_ENDIAN_INDATA, CSL_TCP3D_CFG_TCP3_END_ENDIAN_INDATA_8_BIT_NATIVE); //CSL_TCP3D_CFG_TCP3_END_ENDIAN_INDATA_8_BIT_NATIVE  CSL_TCP3D_CFG_TCP3_END_ENDIAN_INDATA_32_BIT_PACKED
#else
    CSL_FINS (reg, TCP3D_CFG_TCP3_END_ENDIAN_INTR, CSL_TCP3D_CFG_TCP3_END_ENDIAN_INTR_32_BIT_PACKED);
    CSL_FINS (reg, TCP3D_CFG_TCP3_END_ENDIAN_INDATA, CSL_TCP3D_CFG_TCP3_END_ENDIAN_INDATA_8_BIT_NATIVE);
#endif

    ptTCP3dCfgReg->TCP3_END = reg;

    /* Set EXECUTE P0 register parameters 1 = Normal mode */
    CSL_FINS (ptTCP3dCfgReg->TCP3_EXE_P0, TCP3D_CFG_TCP3_EXE_P0_EXE_CMD, CSL_TCP3D_CFG_TCP3_EXE_P0_EXE_CMD_ENABLE);

    /* Set EXECUTE P1 register parameters 1 = Normal mode */
    CSL_FINS (ptTCP3dCfgReg->TCP3_EXE_P1, TCP3D_CFG_TCP3_EXE_P1_EXE_CMD, CSL_TCP3D_CFG_TCP3_EXE_P1_EXE_CMD_ENABLE);

    return;

}
/**************************************************************************
* Enable the EDMA channel, map channel to the specific PaRAM set
***************************************************************************/
CSL_Edma3ChannelHandle Tcp3d_EdmaInit
(
    CSL_Edma3ChannelObj   *ptEdmaChnObj,
    Uint8                 ucCcInstId,
    Uint8                 ucTcInstId,
    Uint8                 ucChanIdx,
    Uint16                uwPaRAMSet
)
{
    CSL_Edma3Obj        tEdmaObj;
    CSL_Status          tStatus;
    CSL_Edma3Handle     tHModule;
    CSL_Edma3ChannelAttr    tChAttr;
    CSL_Edma3Context        tContext;
    CSL_Edma3ChannelHandle  tHEdmaCh = NULL;

    if (CSL_edma3Init(&tContext) != CSL_SOK)
    {
        return 0;
    }

    /* Open EDMA3, open the specified EDMA CHANNEL CONTROLLER, get the EDMA channel num, base address  */
    tHModule = CSL_edma3Open (&tEdmaObj, ucCcInstId, NULL, &tStatus);
    if ((tHModule == NULL) || (tStatus != CSL_SOK))
    {
        return 0;
    }

    /* open EDMA channel, enable channel event enable reg, map PaRAM set to channel */
    /* Open EDMA channel, return a channel handle for the specified channel, initialize the specified channel data structure */
    tChAttr.regionNum = CSL_EDMA3_REGION_GLOBAL;
    tChAttr.chaNum    = ucChanIdx;
    tHEdmaCh = CSL_edma3ChannelOpen (ptEdmaChnObj, ucCcInstId, &tChAttr, &tStatus);
    if ((tHEdmaCh == NULL) || (tStatus != CSL_SOK))
    {
        return 0;
    }

    /* Enable EDMA channel, set EER */
    if ((tStatus = CSL_edma3HwChannelControl (tHEdmaCh, CSL_EDMA3_CMD_CHANNEL_ENABLE, NULL)) != CSL_SOK)
    {
        return 0;
    }
    /* Map EDMA channel to PaRAM set for the EDMA channel,
     * map channel to EventQ */
    CSL_edma3MapDMAChannelToParamBlock (tHModule, ucChanIdx, uwPaRAMSet);
    CSL_edma3MapDMAChannelToEventQueue (tHModule, ucChanIdx, ucTcInstId);

    return tHEdmaCh;
}

/**************************************************************************
* EDMA PaRAM set config
* input global src and dst address
***************************************************************************/
void Tcp3d_EdmaPaRAMSetup
(
		CSL_TPCC_ParamsetRegs *ptPaRAMRegs,
        T_Tcp3d_EdmaPara *ptEdmaPara
)
{
    ptPaRAMRegs->OPT =
        CSL_EDMA3_OPT_MAKE(ptEdmaPara->ucItcchEn,
            ptEdmaPara->ucTcchEn,
            ptEdmaPara->ucItcintEn,
            ptEdmaPara->ucTcintEn,
			ptEdmaPara->ucTCC,
			CSL_EDMA3_TCC_NORMAL,
			CSL_EDMA3_FIFOWIDTH_NONE,
			CSL_EDMA3_STATIC_DIS,
			ptEdmaPara->ucSyncDim,
			CSL_EDMA3_ADDRMODE_INCR,
			CSL_EDMA3_ADDRMODE_INCR);

    ptPaRAMRegs->SRC = ptEdmaPara->udSrcAddr;
    ptPaRAMRegs->A_B_CNT = (ptEdmaPara->uwBcnt << 16) | (ptEdmaPara->uwAcnt);
    ptPaRAMRegs->DST = ptEdmaPara->udDstAddr;
    ptPaRAMRegs->SRC_DST_BIDX = (ptEdmaPara->uwDstBidx << 16) | (ptEdmaPara->uwSrcBidx);
    ptPaRAMRegs->LINK_BCNTRLD = (ptEdmaPara->uwBcnt << 16) | (ptEdmaPara->uwLinkPaRAMSetIdx * 32);
    ptPaRAMRegs->SRC_DST_CIDX = (ptEdmaPara->uwDstCidx << 16) | (ptEdmaPara->uwSrcCidx);
    ptPaRAMRegs->CCNT = ptEdmaPara->uwCcnt;
}

/**************************************************************************
* TCP3D sliding window parameters calculations,
* reference TCP3d user guide section 3.3.7&3.5.5
***************************************************************************/
/** TCP3D SW0 nominal values */
Int32 tcp3d_sw0_Tab[] = {16, 32, 48,  64, 96, 128};

/** Used for getting the sw0LenSel index values */
Int32 TAB[] = {0, 1, 2, 3, 3, 4, 4, 5};

/** Table used for division optimization logic */
Int32 shiftValTab [] = {4, 5, 4, 6, 5, 7};

/** Table used for division optimization logic */
Uint32 mulValTab [] = {32768, 32768, 10923, 32768, 10923, 32768};

/** Table used for checking bounds */
Uint32 frameLenTab[2][2] = {40,5114,40,6144};

Int32 TCP3D_codeBlkSeg (
            Uint32  blockLengthK,
            Uint8   numMAP,
            Uint8  *sw0NomLen,
            Uint8  *sw0LenSel,
            Uint8  *sw1Len,
            Uint8  *sw2LenSel,
            Uint8  *numsw0)
{
    Int32  status = 0;
    Int32 K, Kext;
    Int32 numSWrem;
    Int32 subFrameLen;
    Int32 sw0LenSelTmp;
    Int32 sw1LenTmp;
    Int32 sw2LenSelTmp;
    Int32 numsw0Tmp;
    Int32 numSW;
    Int32 shiftVal, mulVal;
    Int32 sw0Len = *sw0NomLen;

    /**
     * Check the bounds based on numMAP value. frameLenTab is for the bound values
     *      numMAP  -   mode    - block length bounds
     *        1     -   3GPP    -   [40,5114]
     *        2     - LTE/WIMAX -   [40,6144]
     */
    if ( (blockLengthK < frameLenTab[numMAP-1][0]) ||
         (blockLengthK > frameLenTab[numMAP-1][1]) )
    {
        status = 1;
        return (status);
    }

    K = blockLengthK;
    Kext = ((K + 0x3)>>2)<<2;

    //Calculate sw0LenSelTmp, SW1Len, SW2LenSel, numsw0Tmp
    subFrameLen = Kext >> numMAP;   //Kext / (2*numMAP);

    sw0LenSelTmp = TAB[((sw0Len>>4)-1)&0x7];

    //Check that this holds: (reg->NumInfoBits <= 128 * sparms->tcp3_SW0_length * numMap)
    while((Kext > 128 * sw0Len * numMAP) && sw0LenSelTmp<6)
    {
        sw0LenSelTmp++;
        sw0Len = tcp3d_sw0_Tab[sw0LenSelTmp];
    }

    //numSW = subFrameLen/sw0Len;  Replaced by:
    shiftVal = shiftValTab[sw0LenSelTmp];
    mulVal   = mulValTab[sw0LenSelTmp];
    numSW = _mpysu((subFrameLen >> shiftVal), mulVal)>>15;

    numSWrem = subFrameLen - numSW*sw0Len;
    if(numSWrem)
    {
        numSW++;
    }

    if(numSW == 1)
    {
        numsw0Tmp = 0;
        sw1LenTmp = subFrameLen-1;             //stored value is (sw1_length -1)
        sw2LenSelTmp = 0;                      //SW2 is Off.
    }
    else if(numSW == 2)
    {
        numsw0Tmp = 0;
        if(subFrameLen & 0x3)
        {
            sw1LenTmp = 2*(subFrameLen>>2) + 1;    //stored value is (sw1_length -1)
            sw2LenSelTmp = 2;                      //sw1LenTmp > SW2Len
        }
        else
        {
            sw1LenTmp = (subFrameLen>>1) - 1;  //stored value is (sw1_length -1)
            sw2LenSelTmp = 1;                  //sw1LenTmp = SW2Len
        }
    }
    else if( numSWrem <= (sw0Len>>1) )
    {
        numsw0Tmp = numSW-2;
        numSWrem = subFrameLen - (numSW-2)*sw0Len;
        if((numSWrem) & 0x3)
        {
            sw1LenTmp = 2*(numSWrem>>2) + 1;   //stored value is (sw1_length -1)
            sw2LenSelTmp = 2;                  //sw1LenTmp > SW2Len
        }
        else
        {
            sw1LenTmp = (numSWrem>>1) - 1;     //stored value is (sw1_length -1)
            sw2LenSelTmp = 1;                  //sw1LenTmp = SW2Len
        }
    }
    else
    {
        numsw0Tmp = numSW-1;
        sw1LenTmp = numSWrem - 1;              //stored value is (sw1_length -1)
        sw2LenSelTmp = 0;                      //SW2 is Off.
    }


    *sw0LenSel  = (Uint8) sw0LenSelTmp;
    *sw1Len     = (Uint8) sw1LenTmp;
    *sw2LenSel  = (Uint8) sw2LenSelTmp;
    *numsw0     = (Uint8) numsw0Tmp;
    *sw0NomLen  = (Uint8) sw0Len;

    return ( status );

}

/**
 *  @b  Description
 *  @n
 *              Calculates initial beta state values using the tail bits that
 *              could be used in preparing the TCP3D input configuration
 *              registers.
 *
 *  \param[in]  tailBits
 *              Tail Bits buffer of size 12. The tail bits are expected to be
 *              in the order Xt1[0],Pt1[0],Xt1[1],Pt1[1],Xt1[2],Pt1[2],Xt2[0],
 *              Pt2[0],Xt2[1],Pt2[1],Xt2[2],Pt2[2].
 *
 *  \param[in]  signChange
 *              For sign inversion information.
 *                  1 - the sign of the outputs changed
 *                  0 - the output sign is unchanged.
 *
 *  \param[out] Kt
 *              Number of trellis stages used to calculate initial beta states.
 *              This values is computed using the formula [3 - (Kext-K)],
 *              where K is the code block length.
 *
 *  \param[out] beta0Ptr
 *              Initial beta state values for the MAP0 decoder computed from
 *              the tail bits. The buffer size is 8.
 *
 *  \param[out] beta1Ptr
 *              Initial beta state values for the MAP1 decoder computed from
 *              the tail bits. The buffer size is 8.
 *
 *  \return
 */
void Tcp3d_betaStates(
                    Int8    * restrict tailBits,
                    Int32   signChange,
                    Int32   Kt,
                    Int8    * restrict beta0Ptr,
                    Int8    * restrict beta1Ptr)
{
    int32_t Tmp0,Tmp1,Tmp2;
    int64_t llRes, llFin;
    int32_t bit10, bit32, bit54, bit76, bit98, bitba;

    int32_t scale;
    int32_t beta0,beta1,beta2,beta3,beta4,beta5,beta6,beta7,betaMax;

    if(signChange)
    {
        scale = 0x00800080;   //+128
    }
    else
    {
        scale = 0xff80ff80;  //-128
    }

    //Load 12 tail samples
    Tmp0   = _mem4(&tailBits[0]);
    Tmp1   = _mem4(&tailBits[4]);
    Tmp2   = _mem4(&tailBits[8]);

#ifdef _BIG_ENDIAN
    Tmp0 = _rotl(_swap4(Tmp0), 16);
    Tmp1 = _rotl(_swap4(Tmp1), 16);
    Tmp2 = _rotl(_swap4(Tmp2), 16);
#endif

    //***************************************************
    //Initial Beta States Calculation for MAP 0 and MAP1
    //***************************************************
    //Process 4 samples
    llRes = _mpysu4ll(Tmp0, 0x01010101);
    llFin = _smpy2ll(_loll(llRes), scale);
    bit10 = _shr2(_spack2(_hill(llFin),_loll(llFin)), 8);
    llFin = _smpy2ll(_hill(llRes), scale);
    bit32 = _shr2(_spack2(_hill(llFin),_loll(llFin)), 8);

    //Process 4 samples
    //llRes = _mpysu4ll(_hill(llTmp), 0x01010101);
    llRes = _mpysu4ll(Tmp1, 0x01010101);
    llFin = _smpy2ll(_loll(llRes), scale);
    bit54 = _shr2(_spack2(_hill(llFin),_loll(llFin)), 8);
    llFin = _smpy2ll(_hill(llRes), scale);
    bit76 = _shr2(_spack2(_hill(llFin),_loll(llFin)), 8);

    //Process 4 samples
    llRes = _mpysu4ll(Tmp2, 0x01010101);
    llFin = _smpy2ll(_loll(llRes), scale);
    bit98 = _shr2(_spack2(_hill(llFin),_loll(llFin)), 8);
    llFin = _smpy2ll(_hill(llRes), scale);
    bitba = _shr2(_spack2(_hill(llFin),_loll(llFin)), 8);

    //Compute beta state values based on the Kt (# of trellis stages)
    if(Kt==3)
    {
        //Beta MAP0
        beta0 = 0;
        beta1 = _ext(bit10,16,16) + _ext(bit10,0,16); //xt0[0] + xt0[1];
        beta2 = _ext(bit10,16,16) + _ext(bit32,16,16) + _ext(bit32,0,16); //xt0[0] + xt0[2] + xt0[3];
        beta3 = _ext(bit10,0,16) + _ext(bit32,16,16) + _ext(bit32,0,16);  //xt0[1] + xt0[2] + xt0[3];
        beta4 = _ext(bit10,0,16) + _ext(bit32,16,16) + _ext(bit54,16,16) + _ext(bit54,0,16); //xt0[1] + xt0[2]+ xt0[4] + xt0[5];
        beta5 = _ext(bit10,16,16) + _ext(bit32,16,16) + _ext(bit54,16,16) + _ext(bit54,0,16);//xt0[0]+ xt0[2]+ xt0[4] + xt0[5];
        beta6 = _ext(bit10,16,16) + _ext(bit10,0,16) + _ext(bit32,0,16) + _ext(bit54,16,16) + _ext(bit54,0,16); //xt0[0] + xt0[1]+ xt0[3] + xt0[4] + xt0[5];
        beta7 = _ext(bit32,0,16) + _ext(bit54,16,16) + _ext(bit54,0,16);// xt0[3] + xt0[4] + xt0[5];

        betaMax = _max2(beta0,beta1);
        betaMax = _max2(betaMax,beta2);
        betaMax = _max2(betaMax,beta3);
        betaMax = _max2(betaMax,beta4);
        betaMax = _max2(betaMax,beta5);
        betaMax = _max2(betaMax,beta6);
        betaMax = _max2(betaMax,beta7);
        betaMax = _ext(betaMax,16,16);
        betaMax = 127 - betaMax;

        beta0 = beta0 + betaMax;
        beta1 = beta1 + betaMax;
        beta2 = beta2 + betaMax;
        beta3 = beta3 + betaMax;
        beta4 = beta4 + betaMax;
        beta5 = beta5 + betaMax;
        beta6 = beta6 + betaMax;
        beta7 = beta7 + betaMax;

        beta0 = _max2(0x8000ff81, beta0);
        beta1 = _max2(0x8000ff81, beta1);
        beta2 = _max2(0x8000ff81, beta2);
        beta3 = _max2(0x8000ff81, beta3);
        beta4 = _max2(0x8000ff81, beta4);
        beta5 = _max2(0x8000ff81, beta5);
        beta6 = _max2(0x8000ff81, beta6);
        beta7 = _max2(0x8000ff81, beta7);

#ifdef _BIG_ENDIAN
        _mem4(&beta0Ptr[0]) = _packl4(_pack2(beta0,beta1),_pack2(beta2,beta3));
        _mem4(&beta0Ptr[4]) = _packl4(_pack2(beta4,beta5),_pack2(beta6,beta7));
        //_mem4(&beta0Ptr[0]) = _packl4(_pack2(beta3,beta2),_pack2(beta1,beta0));
        //_mem4(&beta0Ptr[4]) = _packl4(_pack2(beta7,beta6),_pack2(beta5,beta4));
#else
        //_mem4(&beta0Ptr[0]) = _packl4(_pack2(beta3,beta2),_pack2(beta1,beta0));
        //_mem4(&beta0Ptr[4]) = _packl4(_pack2(beta7,beta6),_pack2(beta5,beta4));
        _mem4(&beta0Ptr[0]) = _packl4(_pack2(beta0,beta1),_pack2(beta2,beta3));
        _mem4(&beta0Ptr[4]) = _packl4(_pack2(beta4,beta5),_pack2(beta6,beta7));
#endif

        //Beta MAP1
        beta0 = 0;
        beta1 = _ext(bit76,16,16) + _ext(bit76,0,16); //xt1[0] + xt1[1];
        beta2 = _ext(bit76,16,16) + _ext(bit98,16,16) + _ext(bit98,0,16); //xt1[0] + xt1[2] + xt1[3];
        beta3 = _ext(bit76,0,16) + _ext(bit98,16,16) + _ext(bit98,0,16);  //xt1[1] + xt1[2] + xt1[3];
        beta4 = _ext(bit76,0,16) + _ext(bit98,16,16) + _ext(bitba,16,16) + _ext(bitba,0,16); //xt1[1] + xt1[2]+ xt1[4] + xt1[5];
        beta5 = _ext(bit76,16,16) + _ext(bit98,16,16) + _ext(bitba,16,16) + _ext(bitba,0,16);//xt1[0]+ xt1[2]+ xt1[4] + xt1[5];
        beta6 = _ext(bit76,16,16) + _ext(bit76,0,16) + _ext(bit98,0,16) + _ext(bitba,16,16) + _ext(bitba,0,16); //xt1[0] + xt1[1]+ xt1[3] + xt1[4] + xt1[5];
        beta7 = _ext(bit98,0,16) + _ext(bitba,16,16) + _ext(bitba,0,16);// xt1[3] + xt1[4] + xt1[5];

        betaMax = _max2(beta0,beta1);
        betaMax = _max2(betaMax,beta2);
        betaMax = _max2(betaMax,beta3);
        betaMax = _max2(betaMax,beta4);
        betaMax = _max2(betaMax,beta5);
        betaMax = _max2(betaMax,beta6);
        betaMax = _max2(betaMax,beta7);
        betaMax = _ext(betaMax,16,16);
        betaMax = 127 - betaMax;

        beta0 = beta0 + betaMax;
        beta1 = beta1 + betaMax;
        beta2 = beta2 + betaMax;
        beta3 = beta3 + betaMax;
        beta4 = beta4 + betaMax;
        beta5 = beta5 + betaMax;
        beta6 = beta6 + betaMax;
        beta7 = beta7 + betaMax;

        beta0 = _max2(0x8000ff81, beta0);
        beta1 = _max2(0x8000ff81, beta1);
        beta2 = _max2(0x8000ff81, beta2);
        beta3 = _max2(0x8000ff81, beta3);
        beta4 = _max2(0x8000ff81, beta4);
        beta5 = _max2(0x8000ff81, beta5);
        beta6 = _max2(0x8000ff81, beta6);
        beta7 = _max2(0x8000ff81, beta7);

#ifdef _BIG_ENDIAN
        _mem4(&beta1Ptr[0]) = _packl4(_pack2(beta0,beta1),_pack2(beta2,beta3));
        _mem4(&beta1Ptr[4]) = _packl4(_pack2(beta4,beta5),_pack2(beta6,beta7));
        //_mem4(&beta1Ptr[0]) = _packl4(_pack2(beta3,beta2),_pack2(beta1,beta0));
        //_mem4(&beta1Ptr[4]) = _packl4(_pack2(beta7,beta6),_pack2(beta5,beta4));
#else
        //_mem4(&beta1Ptr[0]) = _packl4(_pack2(beta3,beta2),_pack2(beta1,beta0));
        //_mem4(&beta1Ptr[4]) = _packl4(_pack2(beta7,beta6),_pack2(beta5,beta4));
        _mem4(&beta1Ptr[0]) = _packl4(_pack2(beta0,beta1),_pack2(beta2,beta3));
        _mem4(&beta1Ptr[4]) = _packl4(_pack2(beta4,beta5),_pack2(beta6,beta7));
#endif
    }
    else if(Kt==2)
    {
        //Beta MAP0
        beta0 = 0;
        beta1 = _ext(bit32,16,16) + _ext(bit32,0,16); //xt0[0] + xt0[1];
        beta2 = _ext(bit32,16,16) + _ext(bit54,16,16) + _ext(bit54,0,16); //xt0[0] + xt0[2] + xt0[3];
        beta3 = _ext(bit32,0,16) + _ext(bit54,16,16) + _ext(bit54,0,16);  //xt0[1] + xt0[2] + xt0[3];

        betaMax = _max2(beta0,beta1);
        betaMax = _max2(betaMax,beta2);
        betaMax = _max2(betaMax,beta3);
        betaMax = _ext(betaMax,16,16);
        betaMax = 127 - betaMax;

        beta0 = beta0 + betaMax;
        beta1 = beta1 + betaMax;
        beta2 = beta2 + betaMax;
        beta3 = beta3 + betaMax;

        beta0 = _max2(0x8000ff81, beta0);
        beta1 = _max2(0x8000ff81, beta1);
        beta2 = _max2(0x8000ff81, beta2);
        beta3 = _max2(0x8000ff81, beta3);

#ifdef _BIG_ENDIAN
        _mem4(&beta0Ptr[0]) = _packl4(_pack2(beta0,beta1),_pack2(beta2,beta3));
        //_mem4(&beta0Ptr[0]) = _packl4(_pack2(beta3,beta2),_pack2(beta1,beta0));
#else
        //_mem4(&beta0Ptr[0]) = _packl4(_pack2(beta3,beta2),_pack2(beta1,beta0));
        _mem4(&beta0Ptr[0]) = _packl4(_pack2(beta0,beta1),_pack2(beta2,beta3));
#endif
        _mem4(&beta0Ptr[4]) = 0x81818181;

        //Beta MAP1
        //temp
        beta0 = _ext(bit98,16,16);
        beta0 = _ext(bit98,0,16);
        beta0 = _ext(bitba,16,16);
        beta0 = _ext(bitba,0,16);

        //temp
        beta0 = 0;
        beta1 = _ext(bit98,16,16) + _ext(bit98,0,16); //xt1[0] + xt1[1];
        beta2 = _ext(bit98,16,16) + _ext(bitba,16,16) + _ext(bitba,0,16); //xt1[0] + xt1[2] + xt1[3];
        beta3 = _ext(bit98,0,16) + _ext(bitba,16,16) + _ext(bitba,0,16);  //xt1[1] + xt1[2] + xt1[3];

        betaMax = _max2(beta0,beta1);
        betaMax = _max2(betaMax,beta2);
        betaMax = _max2(betaMax,beta3);
        betaMax = _ext(betaMax,16,16);
        betaMax = 127 - betaMax;

        beta0 = beta0 + betaMax;
        beta1 = beta1 + betaMax;
        beta2 = beta2 + betaMax;
        beta3 = beta3 + betaMax;

        beta0 = _max2(0x8000ff81, beta0);
        beta1 = _max2(0x8000ff81, beta1);
        beta2 = _max2(0x8000ff81, beta2);
        beta3 = _max2(0x8000ff81, beta3);

#ifdef _BIG_ENDIAN
        _mem4(&beta1Ptr[0]) = _packl4(_pack2(beta0,beta1),_pack2(beta2,beta3));
        //_mem4(&beta1Ptr[0]) = _packl4(_pack2(beta3,beta2),_pack2(beta1,beta0));
#else
        //_mem4(&beta1Ptr[0]) = _packl4(_pack2(beta3,beta2),_pack2(beta1,beta0));
        _mem4(&beta1Ptr[0]) = _packl4(_pack2(beta0,beta1),_pack2(beta2,beta3));
#endif
        _mem4(&beta1Ptr[4]) = 0x81818181;
    }
    else if(Kt==1)
    {
        //Beta MAP0
        beta0 = 0;
        beta1 = _ext(bit54,16,16) + _ext(bit54,0,16); //xt0[0] + xt0[1];

        betaMax = _max2(beta0,beta1);
        betaMax = _ext(betaMax,16,16);
        betaMax = 127 - betaMax;

        beta0 = beta0 + betaMax;
        beta1 = beta1 + betaMax;

        beta0 = _max2(0x8000ff81, beta0);
        beta1 = _max2(0x8000ff81, beta1);

#ifdef _BIG_ENDIAN
        _mem4(&beta0Ptr[0]) = _packl4(_pack2(beta0,beta1),0x81818181);
        //_mem4(&beta0Ptr[0]) = _packl4(0x81818181,_pack2(beta1,beta0));
#else
        //_mem4(&beta0Ptr[0]) = _packl4(0x81818181,_pack2(beta1,beta0));
        _mem4(&beta0Ptr[0]) = _packl4(_pack2(beta0,beta1),0x81818181);
#endif
        _mem4(&beta0Ptr[4]) = 0x81818181;

        //Beta MAP1
        beta0 = 0;
        beta1 = _ext(bitba,16,16) + _ext(bitba,0,16); //xt1[0] + xt1[1];

        betaMax = _max2(beta0,beta1);
        betaMax = _ext(betaMax,16,16);
        betaMax = 127 - betaMax;

        beta0 = beta0 + betaMax;
        beta1 = beta1 + betaMax;

        beta0 = _max2(0x8000ff81, beta0);
        beta1 = _max2(0x8000ff81, beta1);

#ifdef _BIG_ENDIAN
        _mem4(&beta1Ptr[0]) = _packl4(_pack2(beta0,beta1),0x81818181);
        //_mem4(&beta1Ptr[0]) = _packl4(0x81818181,_pack2(beta1,beta0));
#else
        //_mem4(&beta1Ptr[0]) = _packl4(0x81818181,_pack2(beta1,beta0));
        _mem4(&beta1Ptr[0]) = _packl4(_pack2(beta0,beta1),0x81818181);
#endif
        _mem4(&beta1Ptr[4]) = 0x81818181;

    }
    else if(Kt==0)
    {
#ifdef _BIG_ENDIAN
        _mem4(&beta0Ptr[0]) = 0x7f818181;
        _mem4(&beta1Ptr[0]) = 0x7f818181;
        //_mem4(&beta0Ptr[0]) = 0x8181817f;
        //_mem4(&beta1Ptr[0]) = 0x8181817f;
#else
        //_mem4(&beta0Ptr[0]) = 0x8181817f;
        //_mem4(&beta1Ptr[0]) = 0x8181817f;
        _mem4(&beta0Ptr[0]) = 0x7f818181;
        _mem4(&beta1Ptr[0]) = 0x7f818181;
#endif
        _mem4(&beta0Ptr[4]) = 0x81818181;
        _mem4(&beta1Ptr[4]) = 0x81818181;
    }
}
/***************************************************************************/
/* LTE Interelaver table with the coefficients P0,P1,P2 and G0 needed for  */
/* internal LTE coefficient generation.                                    */
/* K     f1    f2   P0    P1    P2    G0                                   */
/***************************************************************************/
const Int16   TCP3_LteInterleaverTable [220][7] = {
      40,    3,   10,   30,   20,   10,   13,  //    0
      48,    7,   12,   36,   24,   12,   19,  //    1
      56,   19,   42,   42,   28,   14,    5,  //    2
      64,    7,   16,   48,   32,   16,   23,  //    3
      72,    7,   18,   54,   36,   18,   25,  //    4
      80,   11,   20,   60,   40,   20,   31,  //    5
      88,    5,   22,   22,   44,   66,   27,  //    6
      96,   11,   24,   72,   48,   24,   35,  //    7
     104,    7,   26,   78,   52,   26,   33,  //    8
     112,   41,   84,   28,   56,   84,   13,  //    9
     120,  103,   90,   90,   60,   30,   73,  //   10
     128,   15,   32,   96,   64,   32,   47,  //   11
     136,    9,   34,   34,   68,  102,   43,  //   12
     144,   17,  108,   36,   72,  108,  125,  //   13
     152,    9,   38,   38,   76,  114,   47,  //   14
     160,   21,  120,   40,   80,  120,  141,  //   15
     168,  101,   84,   42,   84,  126,   17,  //   16
     176,   21,   44,   44,   88,  132,   65,  //   17
     184,   57,   46,   46,   92,  138,  103,  //   18
     192,   23,   48,  144,   96,   48,   71,  //   19
     200,   13,   50,   50,  100,  150,   63,  //   20
     208,   27,   52,  156,  104,   52,   79,  //   21
     216,   11,   36,  162,  108,   54,   47,  //   22
     224,   27,   56,  168,  112,   56,   83,  //   23
     232,   85,   58,   58,  116,  174,  143,  //   24
     240,   29,   60,   60,  120,  180,   89,  //   25
     248,   33,   62,   62,  124,  186,   95,  //   26
     256,   15,   32,  192,  128,   64,   47,  //   27
     264,   17,  198,   66,  132,  198,  215,  //   28
     272,   33,   68,   68,  136,  204,  101,  //   29
     280,  103,  210,  210,  140,   70,   33,  //   30
     288,   19,   36,  216,  144,   72,   55,  //   31
     296,   19,   74,  222,  148,   74,   93,  //   32
     304,   37,   76,   76,  152,  228,  113,  //   33
     312,   19,   78,  234,  156,   78,   97,  //   34
     320,   21,  120,   80,  160,  240,  141,  //   35
     328,   21,   82,   82,  164,  246,  103,  //   36
     336,  115,   84,  252,  168,   84,  199,  //   37
     344,  193,   86,   86,  172,  258,  279,  //   38
     352,   21,   44,   88,  176,  264,   65,  //   39
     360,  133,   90,   90,  180,  270,  223,  //   40
     368,   81,   46,   92,  184,  276,  127,  //   41
     376,   45,   94,   94,  188,  282,  139,  //   42
     384,   23,   48,  288,  192,   96,   71,  //   43
     392,  243,   98,  294,  196,   98,  341,  //   44
     400,  151,   40,  300,  200,  100,  191,  //   45
     408,  155,  102,  306,  204,  102,  257,  //   46
     416,   25,   52,  104,  208,  312,   77,  //   47
     424,   51,  106,  318,  212,  106,  157,  //   48
     432,   47,   72,  324,  216,  108,  119,  //   49
     440,   91,  110,  330,  220,  110,  201,  //   50
     448,   29,  168,  112,  224,  336,  197,  //   51
     456,   29,  114,  114,  228,  342,  143,  //   52
     464,  247,   58,  348,  232,  116,  305,  //   53
     472,   29,  118,  118,  236,  354,  147,  //   54
     480,   89,  180,  120,  240,  360,  269,  //   55
     488,   91,  122,  366,  244,  122,  213,  //   56
     496,  157,   62,  124,  248,  372,  219,  //   57
     504,   55,   84,  378,  252,  126,  139,  //   58
     512,   31,   64,  384,  256,  128,   95,  //   59
     528,   17,   66,  132,  264,  396,   83,  //   60
     544,   35,   68,  408,  272,  136,  103,  //   61
     560,  227,  420,  420,  280,  140,   87,  //   62
     576,   65,   96,  144,  288,  432,  161,  //   63
     592,   19,   74,  444,  296,  148,   93,  //   64
     608,   37,   76,  152,  304,  456,  113,  //   65
     624,   41,  234,  156,  312,  468,  275,  //   66
     640,   39,   80,  480,  320,  160,  119,  //   67
     656,  185,   82,  164,  328,  492,  267,  //   68
     672,   43,  252,  504,  336,  168,  295,  //   69
     688,   21,   86,  172,  344,  516,  107,  //   70
     704,  155,   44,  528,  352,  176,  199,  //   71
     720,   79,  120,  540,  360,  180,  199,  //   72
     736,  139,   92,  552,  368,  184,  231,  //   73
     752,   23,   94,  564,  376,  188,  117,  //   74
     768,  217,   48,  192,  384,  576,  265,  //   75
     784,   25,   98,  196,  392,  588,  123,  //   76
     800,   17,   80,  200,  400,  600,   97,  //   77
     816,  127,  102,  612,  408,  204,  229,  //   78
     832,   25,   52,  208,  416,  624,   77,  //   79
     848,  239,  106,  636,  424,  212,  345,  //   80
     864,   17,   48,  216,  432,  648,   65,  //   81
     880,  137,  110,  220,  440,  660,  247,  //   82
     896,  215,  112,  672,  448,  224,  327,  //   83
     912,   29,  114,  228,  456,  684,  143,  //   84
     928,   15,   58,  696,  464,  232,   73,  //   85
     944,  147,  118,  708,  472,  236,  265,  //   86
     960,   29,   60,  240,  480,  720,   89,  //   87
     976,   59,  122,  732,  488,  244,  181,  //   88
     992,   65,  124,  248,  496,  744,  189,  //   89
    1008,   55,   84,  756,  504,  252,  139,  //   90
    1024,   31,   64,  768,  512,  256,   95,  //   91
    1056,   17,   66,  264,  528,  792,   83,  //   92
    1088,  171,  204,  816,  544,  272,  375,  //   93
    1120,   67,  140,  840,  560,  280,  207,  //   94
    1152,   35,   72,  864,  576,  288,  107,  //   95
    1184,   19,   74,  888,  592,  296,   93,  //   96
    1216,   39,   76,  912,  608,  304,  115,  //   97
    1248,   19,   78,  936,  624,  312,   97,  //   98
    1280,  199,  240,  960,  640,  320,  439,  //   99
    1312,   21,   82,  328,  656,  984,  103,  //  100
    1344,  211,  252, 1008,  672,  336,  463,  //  101
    1376,   21,   86,  344,  688, 1032,  107,  //  102
    1408,   43,   88, 1056,  704,  352,  131,  //  103
    1440,  149,   60,  360,  720, 1080,  209,  //  104
    1472,   45,   92,  368,  736, 1104,  137,  //  105
    1504,   49,  846,  376,  752, 1128,  895,  //  106
    1536,   71,   48, 1152,  768,  384,  119,  //  107
    1568,   13,   28,  392,  784, 1176,   41,  //  108
    1600,   17,   80,  400,  800, 1200,   97,  //  109
    1632,   25,  102,  408,  816, 1224,  127,  //  110
    1664,  183,  104, 1248,  832,  416,  287,  //  111
    1696,   55,  954, 1272,  848,  424, 1009,  //  112
    1728,  127,   96, 1296,  864,  432,  223,  //  113
    1760,   27,  110, 1320,  880,  440,  137,  //  114
    1792,   29,  112,  448,  896, 1344,  141,  //  115
    1824,   29,  114,  456,  912, 1368,  143,  //  116
    1856,   57,  116,  464,  928, 1392,  173,  //  117
    1888,   45,  354,  472,  944, 1416,  399,  //  118
    1920,   31,  120, 1440,  960,  480,  151,  //  119
    1952,   59,  610, 1464,  976,  488,  669,  //  120
    1984,  185,  124,  496,  992, 1488,  309,  //  121
    2016,  113,  420,  504, 1008, 1512,  533,  //  122
    2048,   31,   64, 1536, 1024,  512,   95,  //  123
    2112,   17,   66,  528, 1056, 1584,   83,  //  124
    2176,  171,  136, 1632, 1088,  544,  307,  //  125
    2240,  209,  420,  560, 1120, 1680,  629,  //  126
    2304,  253,  216,  576, 1152, 1728,  469,  //  127
    2368,  367,  444, 1776, 1184,  592,  811,  //  128
    2432,  265,  456,  608, 1216, 1824,  721,  //  129
    2496,  181,  468,  624, 1248, 1872,  649,  //  130
    2560,   39,   80, 1920, 1280,  640,  119,  //  131
    2624,   27,  164, 1968, 1312,  656,  191,  //  132
    2688,  127,  504, 2016, 1344,  672,  631,  //  133
    2752,  143,  172, 2064, 1376,  688,  315,  //  134
    2816,   43,   88, 2112, 1408,  704,  131,  //  135
    2880,   29,  300,  720, 1440, 2160,  329,  //  136
    2944,   45,   92,  736, 1472, 2208,  137,  //  137
    3008,  157,  188,  752, 1504, 2256,  345,  //  138
    3072,   47,   96, 2304, 1536,  768,  143,  //  139
    3136,   13,   28,  784, 1568, 2352,   41,  //  140
    3200,  111,  240, 2400, 1600,  800,  351,  //  141
    3264,  443,  204, 2448, 1632,  816,  647,  //  142
    3328,   51,  104, 2496, 1664,  832,  155,  //  143
    3392,   51,  212, 2544, 1696,  848,  263,  //  144
    3456,  451,  192, 2592, 1728,  864,  643,  //  145
    3520,  257,  220,  880, 1760, 2640,  477,  //  146
    3584,   57,  336,  896, 1792, 2688,  393,  //  147
    3648,  313,  228,  912, 1824, 2736,  541,  //  148
    3712,  271,  232, 2784, 1856,  928,  503,  //  149
    3776,  179,  236, 2832, 1888,  944,  415,  //  150
    3840,  331,  120, 2880, 1920,  960,  451,  //  151
    3904,  363,  244, 2928, 1952,  976,  607,  //  152
    3968,  375,  248, 2976, 1984,  992,  623,  //  153
    4032,  127,  168, 3024, 2016, 1008,  295,  //  154
    4096,   31,   64, 3072, 2048, 1024,   95,  //  155
    4160,   33,  130, 1040, 2080, 3120,  163,  //  156
    4224,   43,  264, 3168, 2112, 1056,  307,  //  157
    4288,   33,  134, 1072, 2144, 3216,  167,  //  158
    4352,  477,  408, 1088, 2176, 3264,  885,  //  159
    4416,   35,  138, 3312, 2208, 1104,  173,  //  160
    4480,  233,  280, 1120, 2240, 3360,  513,  //  161
    4544,  357,  142, 1136, 2272, 3408,  499,  //  162
    4608,  337,  480, 1152, 2304, 3456,  817,  //  163
    4672,   37,  146, 1168, 2336, 3504,  183,  //  164
    4736,   71,  444, 3552, 2368, 1184,  515,  //  165
    4800,   71,  120, 3600, 2400, 1200,  191,  //  166
    4864,   37,  152, 1216, 2432, 3648,  189,  //  167
    4928,   39,  462, 3696, 2464, 1232,  501,  //  168
    4992,  127,  234, 3744, 2496, 1248,  361,  //  169
    5056,   39,  158, 3792, 2528, 1264,  197,  //  170
    5120,   39,   80, 3840, 2560, 1280,  119,  //  171
    5184,   31,   96, 3888, 2592, 1296,  127,  //  172
    5248,  113,  902, 1312, 2624, 3936, 1015,  //  173
    5312,   41,  166, 1328, 2656, 3984,  207,  //  174
    5376,  251,  336, 4032, 2688, 1344,  587,  //  175
    5440,   43,  170, 4080, 2720, 1360,  213,  //  176
    5504,   21,   86, 1376, 2752, 4128,  107,  //  177
    5568,   43,  174, 4176, 2784, 1392,  217,  //  178
    5632,   45,  176, 1408, 2816, 4224,  221,  //  179
    5696,   45,  178, 1424, 2848, 4272,  223,  //  180
    5760,  161,  120, 1440, 2880, 4320,  281,  //  181
    5824,   89,  182, 1456, 2912, 4368,  271,  //  182
    5888,  323,  184, 4416, 2944, 1472,  507,  //  183
    5952,   47,  186, 4464, 2976, 1488,  233,  //  184
    6016,   23,   94, 4512, 3008, 1504,  117,  //  185
    6080,   47,  190, 4560, 3040, 1520,  237,  //  186
    6144,  263,  480, 4608, 3072, 1536,  743,   //  187

/*********FOLLOWING PART IS EXTENTION TO 8192 with step 64 TO TEST TCP3 *************/
     6208,     3,   194,  4656,  3104,  1552,   197,     //     188
     6272,     3,    14,  4704,  3136,  1568,    17,     //     189
     6336,     5,    66,  1584,  3168,  4752,    71,     //     190
     6400,     3,    10,  4800,  3200,  1600,    13,     //     191
     6464,     3,   202,  4848,  3232,  1616,   205,     //     192
     6528,     5,   102,  1632,  3264,  4896,   107,     //     193
     6592,     3,   206,  4944,  3296,  1648,   209,     //     194
     6656,     3,    26,  4992,  3328,  1664,    29,     //     195
     6720,    11,   210,  5040,  3360,  1680,   221,     //     196
     6784,     3,   106,  5088,  3392,  1696,   109,     //     197
     6848,     3,   214,  5136,  3424,  1712,   217,     //     198
     6912,     5,     6,  1728,  3456,  5184,    11,     //     199
     6976,     3,   218,  5232,  3488,  1744,   221,     //     200
     7040,     3,   110,  5280,  3520,  1760,   113,     //     201
     7104,     5,   222,  1776,  3552,  5328,   227,     //     202
     7168,     3,    14,  5376,  3584,  1792,    17,     //     203
     7232,     3,   226,  5424,  3616,  1808,   229,     //     204
     7296,     5,   114,  1824,  3648,  5472,   119,     //     205
     7360,     3,   230,  5520,  3680,  1840,   233,     //     206
     7424,     3,    58,  5568,  3712,  1856,    61,     //     207
     7488,     5,    78,  1872,  3744,  5616,    83,     //     208
     7552,     3,   118,  5664,  3776,  1888,   121,     //     209
     7616,     3,   238,  5712,  3808,  1904,   241,     //     210
     7680,     7,    30,  5760,  3840,  1920,    37,     //     211
     7744,     3,    22,  5808,  3872,  1936,    25,     //     212
     7808,     3,   122,  5856,  3904,  1952,   125,     //     213
     7872,     5,   246,  1968,  3936,  5904,   251,     //     214
     7936,     3,    62,  5952,  3968,  1984,    65,     //     215
     8000,     3,    10,  6000,  4000,  2000,    13,     //     216
     8064,     5,    42,  2016,  4032,  6048,    47,     //     217
     8128,     3,   254,  6096,  4064,  2032,   257,     //     218
     8192,     3,     2,  6144,  4096,  2048,     5,     //     219
};

const Int16 TCP3_WimaxInterleaverTable[17][4] ={
      20,     18,    11,       4,  //  0
       8,     12,    23,      34,  //  1
       4,     14,    27,      40,  //  2
      44,     54,    23,       4,  //  3
      28,      8,    39,      46,  //  4
      44,     12,    79,      90,  //  5
      52,     14,    27,      40,  //  6
      68,     20,   107,     126,  //  7
      44,     12,    23,      34,  //  8
      44,     12,    71,      82,  //  9
      52,     14,    27,      40,  // 10
      52,     14,    87,     100,  // 11
     212,    356,   119,     402,  // 12
     172,    588,   387,     474,  // 13
     172,     44,   447,    1390,  // 14
     124,   1000,    87,    1070,  // 15
     212,   1320,   131,    1362   // 16
};

/*WiMAX frame lengths*/
const Int32 WIMAX_FRAME_LENGTHS[17] = {
          48, /*  0:   6 Bytes */
          72, /*  1:   9 Bytes */
          96, /*  2:  12 Bytes */
         144, /*  3:  18 Bytes */
         192, /*  4:  24 Bytes */
         216, /*  5:  27 Bytes */
         240, /*  6:  30 Bytes */
         288, /*  7:  36 Bytes */
         360, /*  8:  45 Bytes */
         384, /*  9:  48 Bytes */
         432, /* 10:  54 Bytes */
         480, /* 11:  60 Bytes */
         960, /* 12: 120 Bytes */
        1920, /* 13: 240 Bytes */
        2880, /* 14: 360 Bytes */
        3840, /* 15: 480 Bytes */
        4800  /* 16: 600 Bytes */
};

/*
 * Calculates the LTE interleaver table index for given block length K
 */
inline Int32 LTE_interleaver_index(Int32 K)
{
    Int32 ind = K;

    if ( K <= 512u )
    {
        ind = ( K >> 3 ) - 5u;
    }
    else if ( K <= 1024u )
    {
        ind = ( K >> 4 ) + 27u;
    }
    else if ( K <= 2048u )
    {
        ind = ( K >> 5 ) + 59u;
    }
    else if ( K <= 8192u )
    {
        ind = ( K >> 6 ) + 91u;
    }

    return (ind);
}

/*
 * Calculates the WIMAX interleaver table index for given block length K
 */
inline Int32 WIMAX_interleaver_index(Int32 K)
{
    Int32 ind = K, i;

    for (i = 0; i < 17; ++i)
    {
        if ( K == WIMAX_FRAME_LENGTHS[i] )
        {
            ind = i;
        }
    }

    return (ind);
}
/***************************************************************************/
