/******************************************************************
 * @file  cpri_csu_api.s.c
 * @brief:    CPRI CSU API  
 * @author: bo.liu
 * @Date 2022年12月14日
 * COPYRIGHT NOTICE: (c) smartlogictech. All rights reserved. 
 * Change_date         Owner         Change_content
 * 2022年12月14日        bo.liu       create file

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

/**************************include******************************/
#include <typedef.h>
#include <ucp_utility.h> 

#include "ape_csu.h"
#include "cpri_driver.h"
#include "cpri_csu_api.h"
#include "cpri_csu.h"
#include "phy_para.h"
#include "mtimer_com.h"
#include "ecs_rfm_dm_mgt.h"
 
extern stMtimerPhyPara  gMtimerSfnNum[SCS_MAX_NUM];
extern stMtimerIntStat 	gMtimerIntCnt[SCS_MAX_NUM];
//extern stSfnPara		gCellSfnPara[2];
extern uint32_t*		gCpriCsuStopCmd;

uint32_t CsuStopFlag;
uint32_t gCpriCsuCmdCnt = 0;
uint32_t gCpriAxcIdNum = 0;
uint32_t gCpriLatchNum = 0;
 
/**************************function******************************/
 /*!   
 * @brief:  CPRI_CSU初始化函数
 * @author:  bo.liu
 * @Date:  2022年12月14日
 * @param: Cfg_BusRegNum :      [配置CSU FIFO通道总线寄存器的个数 ]
 * @param: Clr_CpriDmaRegGroup :[初始化时需要清0的CSU寄存器组个数 ]
 * @param: DmaTagMask :         [Dma tag mask，32bit,每个bit索引对应相应的TAG号，0表示屏蔽 ]
 */
uint32_t  UCP_API_CPRI_CSU_Init(uint32_t Cfg_BusRegNum, uint32_t Clr_CpriDmaRegGroup, uint32_t DmaTagMask)
{

	uint32_t  index = 0; 
	volatile uint32_t  *reg_addr = NULL;
//	uint32_t  reg_value = 0; 
	
	
    //step1: 初始化4个FIFO通道
	reg_addr = &(JECS_CSU_EM_BS_SMSEL_PREDATANUM);

	//JECS_CSU_LATCHALFULL = 0x2;
	//JECS_CSU_LATCHALFULL = 0x80000040;
	JECS_CSU_EM_BS_SMSEL_PREDATANUM = (0x1<<14) | (0x5<<5) | 0x8;
	JECS_CSU_EM_BS_SMSEL_PREDATANUM = (0x3<<14) | (0x5<<5) | 0x8;

#if 0
    //配置对应的FIFO通道总线寄存器
	for (index = 0; index < Cfg_BusRegNum; index++)
	{
	    reg_value = (index<<14) + (0xC<<5) + 0xF;
	    do_write(reg_addr, reg_value); 
    }	
#endif
    
    do_write(&JECS_CSU_FINDDMATAG, 0x60); 
    do_write(&JECS_CSU_TAGMASK0,DmaTagMask);  //设置dmatagmask

    //step2:初始化总线相关寄存器，以及UPDATE 寄存器,TAGMASK寄存器
    do_write(&JECS_CSU_ALMOSTFULLSENDTHRED,0x00007fff); 

    //step3:清0 Rx inlatch寄存器和TX outlatch 寄存器
    do_write(&JECS_CSU_CPRIRX0RFPSET, 0);
 
	//step3.1:初始化RX0 inlatch寄存器以及RX0/1 onwork寄存器
	reg_addr = &JECS_CSU_CPRIRX0PORTINFO0; 
	for (index = 0; index < 64; index++)
	{
	    do_write((reg_addr+index), 0); 
	}


	reg_addr = &JECS_CSU_CPRIRX0LATCHINFOL0; 
	for (index = 0; index < 8; index++)
	{
		do_write((reg_addr+index), 0); 
	}

    reg_addr = &JECS_CSU_CPRIRX0LATCHINFOH0; 
	for (index = 0; index < 8; index++)
	{
		do_write((reg_addr+index), 0); 
	}

	reg_addr = &JECS_CSU_CPRIRX0CYCLENUM0; 
	for (index = 0; index < 8; index++)
	{
		do_write((reg_addr+index), 0); 
	}

    do_write(&JECS_CSU_CPRIRX0ONWORK,0); //关闭RX0/1通道
    do_write(&JECS_CSU_CPRIRX1ONWORK,0); 

 

    //step3.3 初始化TX0 outlatch寄存器以及ONWORK寄存器
    do_write(&JECS_CSU_CPRITX0RFPSET,0); 
    // 初始化64个TX0 portinfo寄存器
    reg_addr = &JECS_CSU_CPRITX0PORTINFO0; 
    for (index = 0; index < 64; index++)
	{
	    do_write((reg_addr+index), 0); 
	}

	 //初始化tx outlatch寄存器
    reg_addr = &JECS_CSU_CPRITX0LATCHINFOL0;
    for (index = 0; index < 8; index++)
	{
		do_write((reg_addr+index), 0); 
	}

	reg_addr = &JECS_CSU_CPRITX0LATCHINFOM0; 
	for (index = 0; index < 8; index++)
	{
		do_write((reg_addr+index), 0); 
	}

	reg_addr = &JECS_CSU_CPRITX0LATCHINFOH0; 
	for (index = 0; index < 8; index++)
	{
		do_write((reg_addr+index), 0); 
	}

    //关闭TX0/1通道
	do_write(&JECS_CSU_CPRITX0ONWORK,0);
	do_write(&JECS_CSU_CPRITX1ONWORK,0); 

	
    
   
    
		
    /* step 4: 0x800寄存器开始，清0每组DMA参数里的8个寄存器：
#define JECS_CSU_DMAADDRL0                        (*((volatile uint32_t *)(JECS_CSU_BASE+0x200*4)))
#define JECS_CSU_DMAADDRH0                        (*((volatile uint32_t *)(JECS_CSU_BASE+0x201*4)))
#define JECS_CSU_DMAYSTEPL0                       (*((volatile uint32_t *)(JECS_CSU_BASE+0x202*4)))
#define JECS_CSU_DMAYSTEPH0                       (*((volatile uint32_t *)(JECS_CSU_BASE+0x203*4)))
#define JECS_CSU_DMAZSTEPL0                       (*((volatile uint32_t *)(JECS_CSU_BASE+0x204*4)))
#define JECS_CSU_DMAZSTEPH0                       (*((volatile uint32_t *)(JECS_CSU_BASE+0x205*4)))
#define JECS_CSU_DMAYNUMXNUM0                     (*((volatile uint32_t *)(JECS_CSU_BASE+0x206*4)))
#define JECS_CSU_DMASIZEGRANALLNUM0               (*((volatile uint32_t *)(JECS_CSU_BASE+0x207*4)))

*/
    reg_addr = &JECS_CSU_DMAADDRL0;  
    for(index = 0; index < Clr_CpriDmaRegGroup * 8; index++)
    {
        do_write((reg_addr+index), 0); 
    }

#if 1
    //进行TX0/RX0 TX1/RX1 clear，清空inlatch和outlatch 
  
    do_write(&JECS_CSU_CPRITX0FLUSH, 1); 
    do_write(&JECS_CSU_CPRITX1FLUSH, 1); 
    do_write(&JECS_CSU_CPRIRX0FLUSH, 1); 
    do_write(&JECS_CSU_CPRIRX1FLUSH, 1); 


    do_write(&JECS_CSU_CPRITX0FLUSH, 0); 
    do_write(&JECS_CSU_CPRITX1FLUSH, 0); 
    do_write(&JECS_CSU_CPRIRX0FLUSH, 0); 
    do_write(&JECS_CSU_CPRIRX1FLUSH, 0); 

#endif 
    return 0; 

}



 /*!   
 * @brief:  CPRI CSU Rxinlatch 寄存器配置
 * @author:  bo.liu
 * @Date:  2022年12月14日
 * @param: AxcIdNum :         [AXC ID个数 ]
 * @param: *Rx0Portinfo :     [RX0 PORT info配置参数数组首地址 ]
 * @param: InlatchNum :       [RX0 使用的inlatch 个数 ]
 * @param: *Rx0InLatchinfoL : [RX0 inlath L 寄存器配置参数数组首地址]
 * @param: *Rx0InLatchinfoH : [RX0 inlatch H 寄存器配置参数数组首地址]
 * @param: *Rx0CycleNum :     [RX0 cycle 寄存器配置参数数组首地址]
 */
void  UCP_API_CPRI_CSU_RxInLatch_Cfg(uint32_t AxcIdNum, 
                                        uint32_t *Rx0Portinfo,
                                        uint32_t  InlatchNum,
                                        uint32_t *Rx0InLatchinfoL, 
                                        uint32_t *Rx0InLatchinfoH,
                                        uint32_t *Rx0CycleNum)
                                        
{
    volatile uint32_t  *reg_addr = NULL;
	
	uint32_t  index = 0 ; 




	
	//设置RX0RFOSET寄存器
	do_write(&JECS_CSU_CPRIRX0RFPSET,AxcIdNum-1); 
	

	reg_addr = &JECS_CSU_CPRIRX0PORTINFO0;

    //对RXPORTINFOx寄存器进行赋值 
	for (index = 0; index <AxcIdNum; index++)
	{
        do_write((reg_addr +index), Rx0Portinfo[index]); 
	}


    reg_addr = &JECS_CSU_CPRIRX0LATCHINFOL0; 
    for(index = 0; index < InlatchNum; index++)
    {
        do_write((reg_addr + index), Rx0InLatchinfoL[index]); 
    }

    
	reg_addr = &JECS_CSU_CPRIRX0LATCHINFOH0; 
	for(index = 0; index < InlatchNum; index++)
	{
	   do_write((reg_addr + index), Rx0InLatchinfoH[index]); 
	}


	reg_addr = &JECS_CSU_CPRIRX0CYCLENUM0; 
	for(index = 0; index < InlatchNum; index++)
	{
	   do_write((reg_addr + index), Rx0CycleNum[index]); 
	}
  

   
    

}




 /*!   
 * @brief:  CPRI CSU RX inlatch门限配置
 * @author:  bo.liu
 * @Date:  2022年12月14日
 * @param: Inlatch_index :    [RX inlatch 索引]
 * @param: WriteOrRead :      [读写标志，1为写，0为读]
 * @param: send_threshold :   [send threshold ]
 * @param: almostfull_threshold :[almost full threshold]
 */
uint32_t  UCP_API_CPRI_CSU_RxInLatchThres_Cfg(uint32_t Inlatch_index,
												  uint32_t  WriteOrRead,
												  uint32_t  send_threshold,
												  uint32_t  almostfull_threshold)
{

	volatile uint32_t  *reg_addr = NULL;
	uint32_t  reg_value = 0 ; 


     //根据Inlatch_index 设置RX0 或者RX1 的send_threshold和allmostfull 
	if (1 == WriteOrRead)
	{
		reg_addr = &JECS_CSU_ALMOSTFULLSENDTHRED;
		do_write(reg_addr, ((Inlatch_index<<31)|(send_threshold<<16)|(Inlatch_index<<15)|(almostfull_threshold)));
		return 0; 
	}
	else 
	{
		if (0 == Inlatch_index)  //读取RX0的寄存器值
		{
			reg_addr = &JECS_CSU_ALMOSTFULLSENDTHRED;
            reg_value = do_read(reg_addr); 
            return reg_value; 
        }
        else if (1 == Inlatch_index) //读取RX1的寄存器值
        {
			reg_addr = &JECS_CSU_ALMOSTFULLSENDTHRED1;
            reg_value = do_read(reg_addr); 
            return reg_value; 

        }
        else 
        {
           return -1; 
        }
	}
}




 /*!   
 * @brief:  配置CPRI CSU TX OUTLATCH 寄存器
 * @author:  bo.liu
 * @Date:  2022年12月14日
 * @param: AxcIdNum :         [TX AXC ID总数 ]
 * @param: Tx0RfpBfSet :      [TX0 RFPBFSET寄存器参数]
 * @param: *Tx0Portinfo :     [TX PORT0INFO寄存器参数配置数组首地址]
 * @param: OutlatchNum :      [TX0 outlatch个数]
 * @param: *Tx0LatchinfoL :   [TX0 lathinfo L寄存器配置参数数组首地址]
 * @param: *Tx0LatchinfoM :   [TX0 latchinfo M 寄存器配置参数数组首地址]
 * @param: *Tx0latchinfoH :   [TX0 latchinfo H 寄存器配置参数数组首地址]
 */
void UCP_API_CPRI_CSU_TxOutLatch_Cfg(uint32_t AxcIdNum, 
											uint32_t   Tx0RfpBfSet,
											uint32_t  *Tx0Portinfo,
											uint32_t  OutlatchNum,
											uint32_t  *Tx0LatchinfoL, 
											uint32_t  *Tx0LatchinfoM, 
											uint32_t  *Tx0latchinfoH)
{

    volatile uint32_t  *reg_addr = NULL;

	uint32_t  index = 0 ; 

    //设置TX 预发送寄存器
	reg_addr = &JECS_CSU_CPRITX0RFPSET;
	do_write(reg_addr,Tx0RfpBfSet); //RfpPoint=0x1 can send 4//push 4 basic frame at 1st tx_axc_rfp)

    //设置Tx0PortInfo寄存器
	reg_addr = &JECS_CSU_CPRITX0PORTINFO0; 
	for (index = 0; index < AxcIdNum;index++)
	{
	    do_write((reg_addr+index),Tx0Portinfo[index]);
	}


    reg_addr = &JECS_CSU_CPRITX0LATCHINFOL0; 
    for (index = 0; index < OutlatchNum; index++)
    {
        do_write((reg_addr + index), Tx0LatchinfoL[index]); 
    }

    reg_addr = &JECS_CSU_CPRITX0LATCHINFOM0; 
    for (index = 0; index < OutlatchNum; index++)
    {
        do_write((reg_addr + index), Tx0LatchinfoM[index]); 
    }

    reg_addr = &JECS_CSU_CPRITX0LATCHINFOH0; 
    for (index = 0; index < OutlatchNum; index++)
    {
        do_write((reg_addr + index), Tx0latchinfoH[index]); 
    }


}






 /*!   
 * @brief:  单端多维或者双端多维链表的节点生成函数
 * @author:  bo.liu
 * @Date:  2022年12月15日
 * @param: *LinkDesc :        [链表节点的地址，根据链表节点类型地址对齐 ]
 * @param: LinkType :         [链接类型，0：单端多维，1：双端多维 ]
 * @param: NodeType :         [节点类型：0：源端节点，1：目的端节点 ]
 * @param: CpriEndFlag :      [CPRI 端标志：0：非CPRI端， 1：CPRI端 ]
 * @param: Addr :             [数据接收或者数据发送地址 ]
 * @param: AxcId :            [本节点的AXC ID ]
 * @param: Xnum :             [本节点的Xnum]
 * @param: Allnum :           [本节点的ALLnum ]
 * @param: LatchId :          [本节点的使用的Latch索引 ]
 * @param: RxFirstDmaFlag :   [第一个RXfirst DMA 标志 ]
 * @param: TxLastDmaFlag :    [最后一个TX DMA标志]
 * @param: NextNodeAddr :     [下一个节点的地址，0：表示下一个节点地址在本节点之后，非0：下一个节点的绝对地址]
 */
int32_t  UCP_API_CPRI_CSU_MdDma_LinkNodeGen(
											     stCsuLinkDesc1L3D *LinkDesc,
											     uint32_t LinkType, 
											     uint32_t NodeType,
												 uint32_t CpriEndFlag,
												 uint32_t Addr,
												 uint32_t AxcId,
												 uint32_t Xnum,
												 uint32_t Allnum,
												 uint32_t LatchId, 
												 uint32_t RxFirstDmaFlag,
												 uint32_t TxLastDmaFlag, 
												 uint32_t NextNodeAddr)
{


     // 设置链表节点cmd
	uint32_t ListCmdL = 0;
	uint32_t ListCmdH = 0;
	stCsuLinkDesc1L3D stLinkDesc;
	uint32_t xnum_switch_s = 0; 
	uint32_t xnum_switch_d = 0;

	uint32_t circular_list_d = 0; 
	uint32_t circular_list_s = 0; 


    //参数检查，检查单边多维链表节点地址0x20对齐
//	if ((SINGLE_END_MD_DMA == LinkType) && (((Addr&0xFF) &0x1F) > 0))
	if ((SINGLE_END_MD_DMA == LinkType) && (((((uint32_t)(LinkDesc))&0xFF) &0x1F) > 0))
	{ 
		return -1; 
	}

	//检查双边多维链表节点地址0x40对齐
//	if ((DUAL_END_MD_DMA == LinkType) && (((Addr&0xFF) &0x3F) > 0))
	if ((DUAL_END_MD_DMA == LinkType) && (((((uint32_t)(LinkDesc))&0xFF) &0x1F) > 0))
	{ 
		return -2; 
	}


	memset(&stLinkDesc, 0, sizeof(stCsuLinkDesc1L3D));

	if ((SINGLE_END_MD_DMA == LinkType) && (LINKLIST_NODE_TYPE_SRC == NodeType)) //单边链表模式,源端节点
	{
		xnum_switch_s = 1;
		circular_list_s = 1;
	}

	if ((SINGLE_END_MD_DMA == LinkType) && (LINKLIST_NODE_TYPE_DST == NodeType))
	{
		xnum_switch_d = 1;
		circular_list_s = 1; 
	}

    if(DUAL_END_MD_DMA == LinkType)
    {
        xnum_switch_d  = 1;
        xnum_switch_s = 1; 
        circular_list_d = 1; 
        circular_list_s = 1; 
    }

    //设置节点里的低32bit 
	ListCmdL = (1<<4)+(0<<5)+(3<<6);  //节点里的DAM设置为普通模式，continue模式

    //设置DMA cmd里的高14bit 
	ListCmdH = xnum_switch_s+(xnum_switch_d<<2)+(RxFirstDmaFlag<<4)+(circular_list_d<<11)+(circular_list_s<<13);
  
	stLinkDesc.cmdFifoL = ListCmdL;
	stLinkDesc.cmdFifoH = ListCmdH & 0x3FFF;
	stLinkDesc.dmaAddrL = Addr;
	
	stLinkDesc.dmaXNum = Xnum;
	stLinkDesc.dmaYStep = Xnum;
	stLinkDesc.dmaYNum = 1;
	stLinkDesc.dmaZStep = Xnum;
	stLinkDesc.dmaAllNum = Allnum;	

	stLinkDesc.nAddrMode = NextNodeAddr;	//设置下一个节点的地址
	if (CPRIENDFLAG == CpriEndFlag)
	{
        stLinkDesc.dmaGran = LatchId; 	// CPRI端设置latch id
        stLinkDesc.dmaAddrL = CPRIEND_ADDR; 
        //接收的第一个DMA节点，发送的最后一个DMA节点，gran[3] = 1
        if((1 == RxFirstDmaFlag) || (1 == TxLastDmaFlag))  
        {
            stLinkDesc.dmaCGran = 1;	
        }
	}
	else
	{
       stLinkDesc.dmaSize = 0xF; //memory端设置size =0xF 
	}

    //dummy 地址是固定访问首地址，防止访问越界。
	if ((CSU_TX_DUMMYBUFFER_ADDR == Addr) || (CSU_RX_DUMMYBUFFER_ADDR == Addr))
	{
		stLinkDesc.dmaYStep = 0; //始终在原地址上访问    
        stLinkDesc.dmaZStep = 0; //始终在原地址上访问
	}

	
	memcpy_ext(LinkDesc, &stLinkDesc, sizeof(stCsuLinkDesc1L3D));

	return 0; 


}




 /*!   
 * @brief:  CPRI_CSU DMA 参数寄存器配置
 * @author:  bo.liu
 * @Date:  2022年12月15日
 * @param: DmaRegIdx :        [参数寄存器组的索引，0-31 ]
 * @param: DmaMode :          [DMA 参数寄存器配置模式，0：普通寄存器模式，1：链表模式 ]
 * @param: DmaAddrL :         [数据地址]
 * @param: Xnum :             [Xnum]
 * @param: Ynum :             [Ynum]
 * @param: YstepL :           [YstepL ]
 * @param: ZsetpL :           [ZstepL ]
 * @param: SizeGranAllnum :   [sizegranallnum ]
 */
void UCP_API_CPRI_CSU_DmaParamReg_Cfg(uint32_t           DmaRegIdx, 
												uint32_t  DmaMode,
												uint32_t  DmaAddrL, 
												uint32_t  Xnum,
												uint32_t  Ynum,
												uint32_t  YstepL,
												uint32_t  ZsetpL,
												uint32_t  SizeGranAllnum)

{
    
    volatile uint32_t  *reg_addr = NULL;



    reg_addr = &JECS_CSU_DMAADDRL0; 
    reg_addr = reg_addr + DmaRegIdx * 8;  //设置对应的寄存器参数组

    if (DMA_PARAM_MODE_NORMAL  == DmaMode)
    {
	    do_write((reg_addr+0), DmaAddrL); //ADDRL 
	    do_write((reg_addr+1), 0);        //ADDRH 
	    do_write((reg_addr+2),YstepL);    //YSETPL
	    do_write((reg_addr+3),0);         //YSETPH
	    do_write((reg_addr+4),ZsetpL);    //ZSTEPL
	    do_write((reg_addr+5),0);         //ZSTEPH 
	    do_write((reg_addr+6),((Ynum << 16)|Xnum));   //YNUM_XNUM
	    do_write((reg_addr+7),SizeGranAllnum); 
	}
	else   
	
//链表模式，只需要配置链接第一个节点的地址以及链表节点长度，占用ADDR和ALLNUM寄存器
	{
		do_write((reg_addr+0), DmaAddrL); //ADDRL 
		do_write((reg_addr+1), 0);        //ADDRH 
	   // do_write(reg_addr+2,0);    //YSETPL
	  //  do_write(reg_addr+3,0);         //YSETPH
	  //  do_write(reg_addr+4,0);    //ZSTEPL
	  //  do_write(reg_addr+5,0);         //ZSTEPH 
	  //  do_write(reg_addr+6,0);   //YNUM_XNUM
	    do_write((reg_addr+7),SizeGranAllnum); 

	}

}




 
 /*!   
 * @brief:  CPRI TX CTRL AXC 发送前交织函数
 * @author:  bo.liu
 * @Date:  2023年1月7日
 * @param: cpri_option :      [CPRI optoin, 1-10, 其中option7/7a都对应7]
 * @param: ctrl_axc_bytenum : [要交织的Ctrl_axc的总的Byte数 ]
 * @param: origin_ctrlaxc :   [交织前的数据地址，要求跟交织后的地址不同]
 * @param: interleaver_ctrlaxc :[交织后的数据地址 ]
 */
void UCP_API_CPRI_CSU_TxCtrlAxc_Interleaver (uint32_t cpri_option,
											uint32_t ctrl_axc_bytenum,
											uint32_t origin_ctrlaxc,
											uint32_t interleaver_ctrlaxc)
{



	uint32_t Xs = 4;  //

	uint32_t Y = 0;
	uint32_t Tcw_byte[11] = { 0,1,2,4,5,8,10,16,16,16,16 };//不同option的Tcw对应的Byte数， 7A和7都输入7
	uint32_t total_ctrlaxc_num = (ctrl_axc_bytenum >> 1); //2byte 为一个CTRL_AXC
	uint32_t ctrlaxc_num_eachXs = total_ctrlaxc_num >> 2;
	uint32_t index = 0;

	short *ctrlaxc_in_ptr = (short *)origin_ctrlaxc; 
	short *ctrlaxc_out_ptr = (short *)interleaver_ctrlaxc; 


	Y = Tcw_byte[cpri_option];  //每个CTRLAXC的基本帧上的字节数

    /*
	if (Y * 16 > byte_num) //要发送的byte_num不能占满所有AXC_CTRL BF
	{
	    printf("byte_num  is not enough :Y*16 = %d,bytenum = %d\n", Y * 16, byte_num); 
	}
    */

	/*printf("TX CTRL AXC interleaver: optoin:%d, total_CTRLAXC num = %d, eachXs_ctrlaxc_num = %d\n", cpri_option
	
	total_ctrlaxc_num, ctrlaxc_num_eachXs);
	*/

	for (Xs = 0; Xs < 4; Xs++) //每次处理4个BF的交织，每个BF需要交织的Byte数为Y*4
	{
		for (index = 0; index < ctrlaxc_num_eachXs; index++) 
		{
			ctrlaxc_out_ptr[ctrlaxc_num_eachXs * Xs + index] = ctrlaxc_in_ptr[Xs + index * 4]; 
		}
	}

}


/*!   
 * @brief:	CPRI RX CTRL AXC 接收后解交织函数
 * @author:  bo.liu
 * @Date:  2023年1月7日
 * @param: cpri_option :	  [CPRI optoin, 1-10, 其中option7/7a都对应7]
 * @param: ctrl_axc_bytenum : [要解交织的Ctrl_axc的总的Byte数 ]
 * @param: origin_ctrlaxc :   [解交织前的数据地址，要求跟解交织后的地址不同]
 * @param: interleaver_ctrlaxc :[解交织后的数据地址 ]
 */
void UCP_API_CPRI_CSU_RxCtrkAxc_Deinterleaver(uint32_t cpri_option,
											uint32_t  ctrl_axc_bytenum,
											uint32_t  origin_ctrlaxc,
											uint32_t  deinterleaver_ctrlaxc)
{

    uint32_t Xs = 4;

	uint32_t Y = 0;
	uint32_t Tcw_byte[11] = { 0,1,2,4,5,8,10,16,16,16,16 };   //不同option的Tcw对应的Byte数， 7A和7都输入7
	uint32_t total_ctrlaxc_num = (ctrl_axc_bytenum >> 1);             //2byte 为一个CTRL_AXC
	uint32_t ctrlaxc_num_eachXs = total_ctrlaxc_num >> 2;
	uint32_t index = 0;
	
	short *ctrlaxc_in_ptr = (short *)origin_ctrlaxc;
	short *ctrlaxc_out_ptr = (short *)deinterleaver_ctrlaxc;

	Y = Tcw_byte[cpri_option];  //每个CTRLAXC的基本帧上的字节数

/*
	if (Y * 16 > byte_num) //要发送的byte_num不能占满所有AXC_CTRL BF
	{
		printf("byte_num  is not enough :Y*16 = %d,bytenum = %d\n", Y * 16, byte_num);
	}
*/

	

	for (Xs = 0; Xs < 4; Xs++) //每次处理4个BF的交织，每个BF需要交织的Byte数为Y*4
	{
		for (index = 0; index < ctrlaxc_num_eachXs; index++)
		{
			ctrlaxc_out_ptr[Xs + index * 4] = ctrlaxc_in_ptr[ctrlaxc_num_eachXs * Xs + index];
		}
	}

}



 /*!   
 * @brief:  配置CPRI CSU FIFO通道0命令，用于RX AXC DATA接收。
 * @author:  bo.liu
 * @Date:  2022年12月15日
 * @param: Cmdhigh14bit :     [FIFO 高14bit命令，低14bit有效 ]
 * @param: Cmdlow32bit :      [FIFO 低32bit 命令 ]
 */
void UCP_API_CPRI_CSU_RxAxcData_Fifo0Cmd(uint32_t  Cmdhigh14bit,
										uint32_t  Cmdlow32bit)
{

   
    do_write(&JECS_CSU_CMDHIGHDATA,Cmdhigh14bit);
    do_write(&JECS_CSU_CMDFIFO0,   Cmdlow32bit);
	__ucps2_synch(0);

}



 /*!   
 * @brief: 配置 CPRI_CSU FIFO通道2 命令，用于RX AXC_CTRL 接收
 * @author:  bo.liu
 * @Date:  2022年12月15日
 * @param: Cmdhigh14bit :     [FIFO 高14bit命令，低14bit有效 ]
 * @param: Cmdlow32bit :      [FIFO 低32bit 命令 ]
 */
void UCP_API_CPRI_CSU_RxAxcCtrl_Fifo2Cmd(uint32_t  Cmdhigh14bit,
		                                 uint32_t  Cmdlow32bit)
{


   do_write(&JECS_CSU_CMDHIGHDATA,Cmdhigh14bit);
   do_write(&JECS_CSU_CMDFIFO2,Cmdlow32bit);
	__ucps2_synch(0);
}


 /*!   
 * @brief:  配置CPRI CSU FIFO通道1命令，用于TX AXC Data 发送
 * @author:  bo.liu
 * @Date:  2022年12月15日
 * @param: Cmdhigh14bit :     [FIFO 高14bit命令，低14bit有效 ]
 * @param: Cmdlow32bit :      [FIFO 低32bit 命令 ]
 */
void UCP_API_CPRI_CSU_TxAxcData_Fifo1Cmd(uint32_t  Cmdhigh14bit,
		                                 uint32_t  Cmdlow32bit)
{

   do_write(&JECS_CSU_CMDHIGHDATA,Cmdhigh14bit);
   do_write(&JECS_CSU_CMDFIFO1,Cmdlow32bit);

}



 /*!   
 * @brief:  配置CPRI CSU FIFO 通道3命令，用于TX CTRL AXC 发送
 * @author:  bo.liu
 * @Date:  2022年12月15日
 * @param: Cmdhigh14bit :     [FIFO 高14bit命令，低14bit有效 ]
 * @param: Cmdlow32bit :      [FIFO 低32bit 命令 ]
 */
void UCP_API_CPRI_CSU_TxAxcCtrl_Fifo3Cmd(uint32_t  Cmdhigh14bit,
		                                 uint32_t  Cmdlow32bit)
{

	do_write(&JECS_CSU_CMDHIGHDATA,Cmdhigh14bit);
	do_write(&JECS_CSU_CMDFIFO3,Cmdlow32bit);    
}




 /*!   
 * @brief:  用于TX 0通道控制，使能通道发送，配置AXCID和outlatch 个数
 * @author:  bo.liu
 * @Date:  2023年1月3日
 * @param: Tx0_enable :       [使能/去使能TX 0通道]
 * @param: TxAxcIdNum :       [AXC ID总数 ]
 * @param: OutlatchNum :      [outlatch 总数]
 */
void UCP_API_CPRI_CSU_TXAxcData_ChannelCtrl(uint32_t              Tx0_enable,
                                                      uint32_t  TxAxcIdNum, 
                                                      uint32_t  OutlatchNum)
{
    // 使能或者去使能TX0 通道 
	do_write(&JECS_CSU_CPRITX0ONWORK, (Tx0_enable<<16)| ((TxAxcIdNum-1) << 8) | (OutlatchNum -1)); 
}



 /*!   
 * @brief:  用于RX 0通道控制，使能通道接收，配置latch 个数
 * @author:  bo.liu
 * @Date:  2023年1月3日
 * @param: Rx0_enable :       [使能/去使能RX0 通道 ]
 * @param: InlatchNum :       [RX 0 inlatch个数]
 */
void UCP_API_CPRI_CSU_RXAxcData_ChannelCtrl(uint32_t               Rx0_enable,
													     uint32_t  InlatchNum)
{
  // 使能或者去使能RX0 通道
   do_write(&JECS_CSU_CPRIRX0ONWORK,((Rx0_enable<<16) | (InlatchNum -1))); 
}





 
 /*!   
 * @brief:  TX 1 通道使能、去使能
 * @author:  bo.liu
 * @Date:  2023年1月3日
 * @param: Tx1_enable :       [ TX 1 通道使能、去使能 ]
 * @param: Tx1_capstartnum :  [TX1 capstartnum ]
 */
void UCP_API_CPRI_CSU_TXCtrlAxc_ChannelCtrl(uint32_t  Tx1_enable,
			                                           uint32_t Tx1_capstartnum)
{
	//使能TX1ON WORK 
	do_write(&JECS_CSU_CPRITX1ONWORK, (Tx1_enable<<16) | (Tx1_capstartnum <<8)); 
}



 /*!   
 * @brief:  RX1 通道使能、去使能
 * @author:  bo.liu
 * @Date:  2023年1月3日
 * @param: Rx1_enable :       [RX1 通道使能、去使能]
 * @param: Rx1_capstartnum :  [RX1 capstartnum]
 * @param: Rx1_rfpstartnum :  [RX1 rfpstartnum]
 */
void UCP_API_CPRI_CSU_RXCtrlAxc_ChannelCtrl(uint32_t Rx1_enable,
													    uint32_t Rx1_capstartnum,
													    uint32_t Rx1_rfpstartnum)
{
   //使能RX1通道，
   do_write(&JECS_CSU_CPRIRX1ONWORK,((Rx1_enable<<16) |(Rx1_capstartnum << 8) | Rx1_rfpstartnum)); 

}


 /*!   
 * @brief:  
 * @author:  bo.liu
 * @Date:  2022年12月15日
 * @param: Cmdtag :           [param description ]
 */
uint32_t  UCP_API_CPRI_CSU_TagLookUp(uint32_t Cmdtag)
{
	uint32_t temp = 0;
	temp = do_read(&JECS_CSU_DMASTATUS);
	return temp & (Cmdtag);


}

void UCP_API_CPRI_CSU_Set_AxcIdNum(uint32_t nAxcIdNum)
{
	gCpriAxcIdNum = nAxcIdNum;
}

void UCP_API_CPRI_CSU_Set_LatchNum(uint32_t nLatchNum)
{
	gCpriLatchNum = nLatchNum;
}


uint32_t UCP_API_CPRI_CSU_Get_AxcIdNum()
{
	return gCpriAxcIdNum;
}

uint32_t UCP_API_CPRI_CSU_Get_LatchNum()
{
	return gCpriLatchNum;
}

void UCP_API_CPRI_CSU_Get_CmdFIFO(stCpriCsuCmdFifoInfo* pTxCmdFifo, stCpriCsuCmdFifoInfo* pRxCmdFifo)
{
    EcsRfmDmLocalMgt_t* pEcsDmLocalMgt = get_ecs_rfm_dm_local_mgt();
	stCpriCsuCmdFifoInfo* tx_cmd_fifo_ptr = pEcsDmLocalMgt->tx_cmd_fifo_ptr;
	stCpriCsuCmdFifoInfo* rx_cmd_fifo_ptr = pEcsDmLocalMgt->rx_cmd_fifo_ptr;
	
	memcpy_ucp(tx_cmd_fifo_ptr, pTxCmdFifo, sizeof(stCpriCsuCmdFifoInfo));
	memcpy_ucp(rx_cmd_fifo_ptr, pRxCmdFifo, sizeof(stCpriCsuCmdFifoInfo));
}
 
void UCP_API_CPRI_CSU_START(void)
{
    EcsRfmDmLocalMgt_t* pEcsDmLocalMgt = get_ecs_rfm_dm_local_mgt();
	stCpriCsuCmdFifoInfo* pTxCmdFifo = pEcsDmLocalMgt->tx_cmd_fifo_ptr;
	stCpriCsuCmdFifoInfo* pRxCmdFifo = pEcsDmLocalMgt->rx_cmd_fifo_ptr;
	stMtimerPhyPara* pMtimerSfn = &gMtimerSfnNum[MTIMER_CPRI_ID];
	stMtimerIntStat* pMtimerInt = &gMtimerIntCnt[MTIMER_CPRI_ID];
	uint32_t slotId = pMtimerSfn->txSlotNum; // get_tx_nr_slot(NR_SCS_30K);
	uint32_t cmdId = 0;

	if (1 == *gCpriCsuStopCmd)
	{
		CsuStopFlag = 1;
		return;
	}
	cmdId = pMtimerInt->csuEnCnt & 0x3; //gCpriCsuCmdCnt & 0x3;

	debug_write(((DBG_DDR_IDX_DRV_BASE+704) + ((pMtimerInt->csuEnCnt<<2)&0x7F)), slotId);			// 0xb00
	debug_write(((DBG_DDR_IDX_DRV_BASE+704) + (((pMtimerInt->csuEnCnt<<2)+1)&0x7F)), UCP_API_CPRI_GetTxHfnCnt());		// 0xb00
	debug_write(((DBG_DDR_IDX_DRV_BASE+704) + (((pMtimerInt->csuEnCnt<<2)+2)&0x7F)), pTxCmdFifo->cmdFifo[cmdId].cmd_num);		// 0xb00
	debug_write(((DBG_DDR_IDX_DRV_BASE+704) + (((pMtimerInt->csuEnCnt<<2)+3)&0x7F)), pRxCmdFifo->cmdFifo[cmdId].cmd_num);		// 0xb00
	//debug_write(((DBG_DDR_IDX_DRV_BASE+832) + (gCpriCsuCmdCnt&0x3F)), GET_STC_CNT());		// 0xd00
	gCpriCsuCmdCnt++;
	
	for (uint8_t i = 0; i < pRxCmdFifo->cmdFifo[cmdId].cmd_num; i++)
	{
		UCP_API_CPRI_CSU_RxAxcData_Fifo0Cmd(pRxCmdFifo->cmdFifo[cmdId].cmd[i].cmd14h, pRxCmdFifo->cmdFifo[cmdId].cmd[i].cmd32l);
	}
	for (uint8_t i = 0; i < pTxCmdFifo->cmdFifo[cmdId].cmd_num; i++)
	{
		UCP_API_CPRI_CSU_TxAxcData_Fifo1Cmd(pTxCmdFifo->cmdFifo[cmdId].cmd[i].cmd14h, pTxCmdFifo->cmdFifo[cmdId].cmd[i].cmd32l);
	}
#if 0
	if (1 == gCpriCsuCmdCnt)
	{
		uint32_t axc_id_num = 6; //1个指数因子,4个天线,1个AGC因子
		UCP_API_CPRI_CSU_RXAxcData_ChannelCtrl(1, axc_id_num);
		UCP_API_CPRI_CSU_TXAxcData_ChannelCtrl(1, axc_id_num, axc_id_num);
		
		start_cpri_map();
	}
#endif	

}

void UCP_API_CPRI_CSU_STOP()
{
	do_write(CSU_STOP_CMD_ADDR, 1); 				// csu stop
	//delay_us(5000); 								// delay 5ms, wait fifo empty
	//do_write(&JECS_CSU_CPRITX0FLUSH, 1);			// flush latch
	//do_write(&JECS_CSU_CPRITX1FLUSH, 1);
	//do_write(&JECS_CSU_CPRIRX0FLUSH, 1);
	//do_write(&JECS_CSU_CPRIRX1FLUSH, 1);
	// wait fifo empty
	while ((0 != do_read(&JECS_CSU_CMDFIFO0_NUM)) || (0 != do_read(&JECS_CSU_CMDFIFO1_NUM)) || (0 != do_read(&JECS_CSU_CMDFIFO2_NUM)) || (0 != do_read(&JECS_CSU_CMDFIFO3_NUM)));
}

void UCP_API_CPRI_CSU_Flush_Latch(uint8_t latch_id)
{
	uint32_t addr = (uint32_t)(&JECS_CSU_CPRITX0FLUSH) + 0x200 * latch_id;
	do_write(addr, 1);			// flush latch
	__ucps2_synch(0);
	//ucp_nop(5);
	do_write(addr, 0);			// flush latch
	__ucps2_synch(0);
}

void UCP_API_CPRI_CSU_CH_Enable(uint32_t axc_id_num, uint32_t latch_num)
{
	UCP_API_CPRI_CSU_RXAxcData_ChannelCtrl(1, latch_num);
	UCP_API_CPRI_CSU_TXAxcData_ChannelCtrl(1, axc_id_num, latch_num);
	
	start_cpri_map();
}

void UCP_API_CPRI_CSU_CH_Disable(uint32_t axc_id_num, uint32_t latch_num)
{
	stop_cpri_map();

	UCP_API_CPRI_CSU_TXAxcData_ChannelCtrl(0, axc_id_num, latch_num);
	UCP_API_CPRI_CSU_RXAxcData_ChannelCtrl(0, latch_num);
}


#ifdef   CPRI_API_TEST 


void cpri_csu_axc_linknodegen_timing_apitest( )
{

// 设置链表节点cmd
	uint32_t cycleNum = 32; //8;
	uint32_t rxListCmdL;
	uint32_t rxListCmdH;
	// bit4=1，多维DMA
	// bit5=0，普通模式
	// bit[7:6]=3，该DMA可跟随上一个DMA，下一个DMA可跟随本DMA
	rxListCmdL = (1<<4)+(0<<5)+(3<<6);
	// bit32=1，读操作完成一个xNum换下一个DMA
	// bit34=1，写操作完成一个xNum换下一个DMA
	// bit36=1，读操作为对应AxC的rfp后第一组DMA请求
	// bit43=1，写操作链式循环
	// bit45=1，读操作链式循环
	rxListCmdH = 1+(1<<2)+(1<<4)+(1<<11)+(1<<13);

	
	int idSize = 0;
	int idCGran = 0;
	uint32_t srcAddr = 0;
	uint32_t dstAddr = 0;

	// rx: cpri -> ddr
	// 5ms，第1个链表
	int i = 0;
	for(i = 0; i < ID_NUM; i++)
	{
		idCGran = 1; // 新的无线帧开始
		if(0 == i || 5 == i)
		{
			idSize = 1*2;	// 压缩因子，一个BF 2B
		}
		else
		{
			idSize = 8*8;	// AxC数据，一个BF有4个AxC 64B*4
		}
		

        //调用API生成源节点
		UCP_API_CPRI_CSU_MdDma_LinkNodeGen(
									    (stCsuLinkDesc1L3D*)CSU_RX_DESC_ADDR + 2*i,
									     DUAL_END_MD_DMA, 
									     LINKLIST_NODE_TYPE_SRC,
										 CPRIENDFLAG,
										 CPRIEND_ADDR,
										 i,
										 idSize*cycleNum,
										 idSize*(256*75),
										 i, 
										 idCGran,
										 0, 
										 0); 

										 
        dstAddr = CSU_RX_AXC_ADDR + i*ID_DATA_STEP;
 		//调用API生成目的节点  								 
		UCP_API_CPRI_CSU_MdDma_LinkNodeGen(
									    (stCsuLinkDesc1L3D*)CSU_RX_DESC_ADDR + 2*i+1,
									     DUAL_END_MD_DMA, 
									     LINKLIST_NODE_TYPE_DST,
										 NONCPRIENDFLAG,
										 dstAddr,
										 i,
										 idSize*cycleNum,
										 idSize*(256*75),
										 i, 
										 0,
										 0, 
										 0); 

		
	}

	// 第2个链表
	// bit4=1，多维DMA
	// bit5=0，普通模式
	// bit[7:6]=3，该DMA可跟随上一个DMA，下一个DMA可跟随本DMA
	rxListCmdL = (1<<4)+(0<<5)+(3<<6);
	// bit32=1，读操作完成一个xNum换下一个DMA
	// bit34=1，写操作完成一个xNum换下一个DMA
	// bit36=1，读操作为对应AxC的rfp后第一组DMA请求
	// bit43=1，写操作链式循环
	// bit45=1，读操作链式循环
	rxListCmdH = 1+(1<<2)+(0<<4)+(1<<11)+(1<<13);
	for(i = 0; i < ID_NUM; i++)
	{
		idCGran = 0;
		if(0 == i || 5 == i)
		{
			idSize = 1*2;	// 压缩因子，一个BF 2B
		}
		else
		{
			idSize = 8*8;	// AxC数据，一个BF每个AxC 64B
		}
	
		
		 //调用API生成源节点
		UCP_API_CPRI_CSU_MdDma_LinkNodeGen((stCsuLinkDesc1L3D*)CSU_RX_DESC_ADDR+2*ID_NUM+2*i,
     									     DUAL_END_MD_DMA, 
     									     LINKLIST_NODE_TYPE_SRC,
     										 CPRIENDFLAG,
     										 CPRIEND_ADDR,
     										 i,
     										 idSize*cycleNum,
     										 idSize*(256*75),
     										 i, 
     										 idCGran,
     										 0, 
     										 0); 


         //调用API生成目的节点	
         dstAddr = CSU_RX_AXC_ADDR + ID_NUM*ID_DATA_STEP + i*ID_DATA_STEP;							  
		 UCP_API_CPRI_CSU_MdDma_LinkNodeGen(
										 (stCsuLinkDesc1L3D*)CSU_RX_DESC_ADDR + 2*ID_NUM + 2*i+1,
										  DUAL_END_MD_DMA, 
										  LINKLIST_NODE_TYPE_DST,
										  NONCPRIENDFLAG,
										  dstAddr,
										  i,
										  idSize*cycleNum,
										  idSize*(256*75),
										  i, 
										  0,
										  0, 
										  0); 	
		
	}

	// 设置链表节点CMD
	uint32_t txListCmdL;
	uint32_t txListCmdH;
	// bit4=1，多维DMA
	// bit5=0，普通模式
	// bit[7:6]=3，该DMA可跟随上一个DMA，下一个DMA可跟随本DMA
	txListCmdL = (1<<4)+(0<<5)+(3<<6);
	// bit32=1，读操作完成一个xNum换下一个DMA
	// bit34=1，写操作完成一个xNum换下一个DMA
	// bit43=1，写操作链式循环
	// bit45=1，读操作链式循环
	txListCmdH = 1+(1<<2)+(1<<11)+(1<<13);

	idSize = 0;
	idCGran = 0;

	// tx: ddr -> cpri
	// 偶时隙的前7个符号，第1个链表
	for(i = 0; i < ID_NUM; i++)
	{
		if(0 == i || 5 == i)
		{
			idSize = 1*2; // 压缩因子，一个BF 2B
		}
		else
		{
			idSize = 8*8; // AxC数据，一个BF每个AxC 64B
		}

		
		
        //调用API生成源节点
        srcAddr = CSU_TX_AXC_ADDR + i*ID_DATA_STEP;
		UCP_API_CPRI_CSU_MdDma_LinkNodeGen((stCsuLinkDesc1L3D*)CSU_TX_DESC_ADDR + 2*i,
     									     DUAL_END_MD_DMA, 
     									     LINKLIST_NODE_TYPE_SRC,
     										 NONCPRIENDFLAG,
     										 srcAddr ,
     										 i,
     										 idSize*cycleNum,
     										 idSize*(256*75),
     										 i, 
     										 0,
     										 idCGran, 
     										 0); 



        UCP_API_CPRI_CSU_MdDma_LinkNodeGen((stCsuLinkDesc1L3D*)CSU_TX_DESC_ADDR + 2*i +1,
     									     DUAL_END_MD_DMA, 
     									     LINKLIST_NODE_TYPE_DST,
     										 CPRIENDFLAG,
     										 CPRIEND_ADDR ,
     										 i,
     										 idSize*cycleNum,
     										 idSize*(256*75),
     										 i, 
     										 0,
     										 idCGran, 
     										 0); 
		
		
	}

	// 第2个链表
	for(i = 0; i < ID_NUM; i++)
	{
		if(0 == i)
		{
			idSize = 1*2; // 压缩因子，一个BF 2B
		}
		else if (5 == i)
		{
			idSize = 1*2;
			idCGran = 1; // 该DMA为rfp的最后一个bit所在的DMA，但不一定是该rfp段最后一个DMA
		}
		else
		{
			idSize = 8*8; // AxC数据，一个BF每个AxC 64B
		}
		
//		srcAddr = CSU_TX_AXC_ADDR + i*ID_DATA_STEP;
		srcAddr = CSU_TX_AXC_ADDR + i*ID_DATA_STEP + ID_NUM*ID_DATA_STEP;
		UCP_API_CPRI_CSU_MdDma_LinkNodeGen((stCsuLinkDesc1L3D*)CSU_TX_DESC_ADDR + 2*ID_NUM + 2*i,
													 DUAL_END_MD_DMA, 
													 LINKLIST_NODE_TYPE_SRC,
													 NONCPRIENDFLAG,
													 srcAddr ,
													 i,
													 idSize*cycleNum,
													 idSize*(256*75),
													 i, 
													 0,
													 idCGran, 
													 0); 

		 UCP_API_CPRI_CSU_MdDma_LinkNodeGen((stCsuLinkDesc1L3D*)CSU_TX_DESC_ADDR+2*ID_NUM+2*i +1,
     									     DUAL_END_MD_DMA, 
     									     LINKLIST_NODE_TYPE_DST,
     										 CPRIENDFLAG,
     										 CPRIEND_ADDR ,
     										 i,
     										 idSize*cycleNum,
     										 idSize*(256*75),
     										 i, 
     										 0,
     										 idCGran, 
     										 0); 
		
		
	}


}


void cpri_csu_axc_init_timing_apitest( )
{
	
	uint32_t basic_frame_byte = 0;
	uint32_t cycleNum = 32; //8;
	uint32_t axcidnum = 6; 
	uint32_t inlatchnum = 6; 
	uint32_t outlatchnum = 6; 
	uint32_t index = 0; 

	uint32_t bitperBF[6] = {16,512,512,512,512,16};  //ID0/5 是2byte, 16bit,ID1-4 是64byte,512bit
    uint32_t bitpercycle[6] = {16,0,0,0,0,16}; //0表示64
	
	

	uint32_t Rx0Portinfo[32] = {0}; 
	uint32_t Rx0InlatchinfoL[32] = {0}; 
	uint32_t Rx0InlatchinfoH[32] = {0}; 
	uint32_t Rx0CycleNum[32] = {0}; 

	uint32_t Tx0Portinfo[32] = {0}; 
	uint32_t Tx0LatchinfoL[32] = {0}; 

	uint32_t Tx0LatchinfoM[32] = {0}; 
	uint32_t Tx0latchinfoH[32] = {0}; 

	
	

	
	// 以option8, 4T4R为例
	// ID0，包含1拍，1拍16bit
	// ID1~ID4，包含8拍，1拍64bit
	// 1个基本帧包含1*2+32*8=258B的有效数据
	basic_frame_byte = (ID0_SIZE+ID5_SIZE)*2 + (ID1_SIZE+ID2_SIZE+ID3_SIZE+ID4_SIZE)*8;

    //step2：进行RX inlatch和TX outlacth的设置
    //step2.1 进行RX0 inlatch的配置
    for (index = 0; index < axcidnum; index++)
    {
        Rx0Portinfo[index] =  ((bitperBF[index]<<1)|(bitpercycle[index]<<22));     
    }

    for (index = 0; index < inlatchnum; index++)
    {
        Rx0InlatchinfoL[index] =  bitperBF[index];  
        Rx0InlatchinfoH[index] =  0x38281808; 
        Rx0CycleNum[index] = cycleNum - 1; 
    }
    
  
    
	UCP_API_CPRI_CSU_RxInLatch_Cfg(axcidnum, 
	                               Rx0Portinfo,
	                               inlatchnum ,
	                               Rx0InlatchinfoL, 
	                               Rx0InlatchinfoH,
	                               Rx0CycleNum);
   
	//step2.2：进行RX0 inlatchThreshold 配置
	UCP_API_CPRI_CSU_RxInLatchThres_Cfg(0,
										1,
										0x10,
										0x40);
										  

	//step2.3 

    for (index = 0; index < axcidnum; index++)
    {
        Tx0Portinfo[index] = ((bitperBF[index]<<1) | (bitpercycle[index] <<20) | (index << 26));     
    }

    for (index = 0; index < outlatchnum; index++)
    {
	    Tx0LatchinfoL[index] = 	bitperBF[index]; 
	    Tx0LatchinfoM[index] = 0x180008;
	    Tx0latchinfoH[index] = 0x380028; 
    }
	
	UCP_API_CPRI_CSU_TxOutLatch_Cfg(axcidnum, 
									0x40001,      //RfpPoint=0x1 can send 4//push 4 basic frame at 1st tx_axc_rfp,
									Tx0Portinfo,
									outlatchnum,
									Tx0LatchinfoL, 
									Tx0LatchinfoM, 
									Tx0latchinfoH);



   
	//step3: 进行RX 和TX 的链表节点的配置 
    cpri_csu_axc_linknodegen_timing_apitest(); 


    //step4：进行DMA 参数寄存器的配置 
    /*step4.1 配置RX0的DMA 参数寄存器，RX存在2个链表，用2个寄存器组   */
    UCP_API_CPRI_CSU_DmaParamReg_Cfg(0,  //第0组寄存器
									 DMA_PARAM_MODE_LINKLIST,
									 CSU_RX_DESC_ADDR, 
									 0,
									 0,
								     0,
									 0,
									 axcidnum); 

	UCP_API_CPRI_CSU_DmaParamReg_Cfg(1, //第1组寄存器
									  DMA_PARAM_MODE_LINKLIST,
									  CSU_RX_DESC_ADDR + 64 * axcidnum,  //双边多维节点，64字节
									  0,
									  0,
									  0,
									  0,
									  axcidnum); 

									 
    //setp4.2 配置TX0的DAM 参数寄存器，TX0存在2个链表，用2个寄存器组
	UCP_API_CPRI_CSU_DmaParamReg_Cfg(10, 
								 DMA_PARAM_MODE_LINKLIST,
								 CSU_TX_DESC_ADDR, 
								 0,
								 0,
							     0,
								 0,
								 axcidnum); 


	UCP_API_CPRI_CSU_DmaParamReg_Cfg(11, 
									DMA_PARAM_MODE_LINKLIST,
									CSU_TX_DESC_ADDR + 64 *axcidnum, 
									0,
									0,
									0,
									0,
									axcidnum); 

#if 0
	uint32_t  Cmdhigh14bit = 0; 
	uint32_t  Cmdlow32bit = 0; 

    //发送命令到FIFO0 通道用于接收数据，
    Cmdhigh14bit = 0; //?? 
    Cmdlow32bit = 1 | (1<<2) |(1<<4)|(0 <<5) |(3<<6) |(0<<8) |(0<<13)|(11 <<18); 
    UCP_API_CPRI_CSU_RxAxcData_Fifo0Cmd(Cmdhigh14bit,  Cmdlow32bit); 

    Cmdlow32bit = 1 | (1<<2) |(1<<4)|(0 <<5) |(3<<6) |(1<<8) |(0<<13)|(12 <<18); 
    UCP_API_CPRI_CSU_RxAxcData_Fifo0Cmd(uint32_t  Cmdhigh14bit,uint32_t  Cmdlow32bit); 
    
										
    //发送命令到FIFO1 通道，用于发送数据
    Cmdhigh14bit = 0; //?? 
    Cmdlow32bit = 1 | (1<<2) |(1<<4)|(0 <<5) |(3<<6) |(10<<8) |(0<<13)|(21 <<18); 

    UCP_API_CPRI_CSU_TxAxcData_Fifo1Cmd(Cmdhigh14bit,Cmdlow32bit);

    Cmdlow32bit = 1 | (1<<2) |(1<<4)|(0 <<5) |(3<<6) |(11<<8) |(0<<13)|(22 <<18); 
    UCP_API_CPRI_CSU_TxAxcData_Fifo1Cmd(Cmdhigh14bit,Cmdlow32bit);
    
#endif 

}    

//进行ctrl AXC的配置

#if 0
void cpri_csu_axcctrl_init_timing_apitest()
{
	uint32_t basic_frame_ctrlaxc_byte;
	uint32_t txCapStartNum = 1;
	uint32_t rfpStartNum = 0;
	uint32_t rxCapStartNum = 1;

	basic_frame_ctrlaxc_byte = 16; // option8, 128bit
//	printf("ctrlaxc_byte in bf is %d", basic_frame_ctrlaxc_byte);


    //直接设置寄存器20/21,作为源和目的寄存器组配置，在cmd里指定20/21
	//rx ctrl axc dma config

	UCP_API_CPRI_CSU_DmaParamReg_Cfg(20, 
									 DMA_PARAM_MODE_NORMAL,
								     CPRIEND_ADDR, 
									 0x40,
													uint32_t  Ynum,
													uint32_t  YstepL,
													uint32_t  ZsetpL,
													uint32_t  SizeGranAllnum)


	
	// reg dma
	JECS_CSU_DMAADDRL20 = 0; // addr_s
	JECS_CSU_DMAADDRH20 = 0;
	JECS_CSU_DMAYNUMXNUM20 = 0x10040;        // xnum=0x40,ynum=1,4 basic frames
	JECS_CSU_DMAYSTEPL20 = 0x40;				// ystep=xnum
	JECS_CSU_DMAZSTEPL20 = 0x40;				// zstep = ystep
	JECS_CSU_DMASIZEGRANALLNUM20 = 0x58000000+ basic_frame_ctrlaxc_byte*4*4*75; //allnum=0x57800,gran = 0, size=f, don¡¯t care size,gran


	JECS_CSU_DMAADDRL21 = CSU_RX_CTRL_ADDR;	// addr_d
	JECS_CSU_DMAYNUMXNUM21 = 0x10000 + 0x100;// xnum=0x100,ynum=1,1 hyper frame
	JECS_CSU_DMAYSTEPL21 = 0x100;			// ystep=xnum
	JECS_CSU_DMAZSTEPL21 = 0x100;			// zstep = ystep
	JECS_CSU_DMASIZEGRANALLNUM21 = 0xF0000000 + basic_frame_ctrlaxc_byte*4*4*75; //allnum=0x57800,gran=0x8,size=5, don¡¯t care sizE

    //指定寄存器22/23作为源和目的
	JECS_CSU_DMAADDRL22 = 0; // addr_s
	JECS_CSU_DMAADDRH22 = 0;
	JECS_CSU_DMAYNUMXNUM22 = 0x10040;        // xnum=0x40,ynum=1,4 basic frames
	JECS_CSU_DMAYSTEPL22 = 0x40;				// ystep=xnum
	JECS_CSU_DMAZSTEPL22 = 0x40;				// zstep = ystep
	JECS_CSU_DMASIZEGRANALLNUM22 = 0x58000000+ basic_frame_ctrlaxc_byte*4*4*75; //allnum=0x57800,gran = 0, size=f, don¡¯t care size,gran

	JECS_CSU_DMAADDRL23 = CSU_RX_CTRL_ADDR + basic_frame_ctrlaxc_byte*4*4*75;	// addr_d
	JECS_CSU_DMAYNUMXNUM23 = 0x10000 + 0x100;// xnum=0x100,ynum=1,1 hyper frame
	JECS_CSU_DMAYSTEPL23 = 0x100;			// ystep=xnum
	JECS_CSU_DMAZSTEPL23 = 0x100;			// zstep = ystep
	JECS_CSU_DMASIZEGRANALLNUM23 = 0xF0000000 + basic_frame_ctrlaxc_byte*4*4*75; //allnum=0x57800,gran=0x8,size=5, don¡¯t care sizE

	JECS_CSU_ALMOSTFULLSENDTHRED = 0x80048010; //almostfull1=0x10, sendthred1=0x4， //设置inlatch1 的sendthred和almmost full

	//tx ctrl axc dma config
	JECS_CSU_DMAADDRL24 = CSU_TX_CTRL_ADDR; // addr_s
	JECS_CSU_DMAADDRH24 = 0;
	JECS_CSU_DMAYNUMXNUM24 = 0x10100;        // xnum=0x100,ynum=1,1 hyper frame
	JECS_CSU_DMAYSTEPL24 = 0x100;           // ystep=xnum
	JECS_CSU_DMAZSTEPL24 = 0x100;           // zstep = ystep
	// read global, dma size = 0xF
	JECS_CSU_DMASIZEGRANALLNUM24 = 0xF0000000+ basic_frame_ctrlaxc_byte*4*4*75; //allnum=0x57800,gran = 0, size=f, don¡¯t care size,gran
	JECS_CSU_DMAADDRL25 = 0;				   // addr_d
	JECS_CSU_DMAADDRH25 = 0;
	JECS_CSU_DMAYNUMXNUM25 = 0x10000+ 0x40; // xnum=0x40,ynum=1,4 basic frame
	JECS_CSU_DMAYSTEPL25 = 0x40; 		   // ystep=xnum
	JECS_CSU_DMAZSTEPL25 = 0x40;            // zstep = ystep
	// size = 5, cgran=1, gran=0
	JECS_CSU_DMASIZEGRANALLNUM25 = 0x58000000 + basic_frame_ctrlaxc_byte*4*4*75; //allnum=0x57800,gran=0x8,size=5, don¡¯t care sizE

	JECS_CSU_DMAADDRL26 = CSU_TX_CTRL_ADDR + basic_frame_ctrlaxc_byte*4*4*75; // addr_s
	JECS_CSU_DMAADDRH26 = 0;
	JECS_CSU_DMAYNUMXNUM26 = 0x10100;        // xnum=0x100,ynum=1,1 hyper frame
	JECS_CSU_DMAYSTEPL26 = 0x100;           // ystep=xnum
	JECS_CSU_DMAZSTEPL26 = 0x100;           // zstep = ystep
	// read global, dma size = 0xF
	JECS_CSU_DMASIZEGRANALLNUM26 = 0xF0000000+ basic_frame_ctrlaxc_byte*4*4*75; //allnum=0x57800,gran = 0, size=f, don¡¯t care size,gran
	JECS_CSU_DMAADDRL27 = 0;				   // addr_d
	JECS_CSU_DMAADDRH27 = 0;
	JECS_CSU_DMAYNUMXNUM27 = 0x10000+ 0x40; // xnum=0x40,ynum=1,4 basic frame
	JECS_CSU_DMAYSTEPL27 = 0x40; 		   // ystep=xnum
	JECS_CSU_DMAZSTEPL27 = 0x40;            // zstep = ystep
	// size = 5, cgran=1, gran=0
	JECS_CSU_DMASIZEGRANALLNUM27 = 0x58000000 + basic_frame_ctrlaxc_byte*4*4*75; //allnum=0x57800,gran=0x8,size=5, don¡¯t care sizE

	//tx start and rx capture num config

	// 收到rx_aux_rfp后，等待rx_axc_ctrl_num==RfpStartNum开始工作
	// 满足RfpStartNum之后，再满足rx_axc_ctrl_num==CapStartNum，开始接收数据
	// 满足CapStartNum时，表示一个DMA的开始，必须和DMA中命令Bit36==1的DMA对齐才可执行
	JECS_CSU_CPRIRX1ONWORK = (rxCapStartNum<<8) + rfpStartNum; // NUM0 is RfpStartNum, NUM1 is CapStartNum

	// 收到tx_aux_rfp之后，等待tx_axc_ctrl_num==TxCapStartNum，开始接收数据，只有第一次rfp有效
	JECS_CSU_CPRITX1ONWORK = (txCapStartNum<<8);         // TxCapStartNum
}

#endif 

#endif 


