#include "ucp_cpri.h"
#include "hw_cpri.h"
#include "cpri_timer.h"
#include "ecpri_timer.h"
#include "ucp_param.h"
#include "ucp_csu.h"
#include "ucp_js_ctrl.h"
#include "cpri_csu.h"
#include "mtimer_com.h"
#include "cpri_delay.h"
#include "ucp_utility.h"
#include "ucp_printf.h"
#include "phy_para.h"
#include "ctc_intr.h"
#include "inter_vector.h"
#include "HeaderRam.h"
#include "dw_apb_gpio.h"
#include "log_server.h"
#include "ecs_rfm_dm_mgt.h"
#include "ucp_mtimer.h"
#include "mtimer_drv.h"
#include "mtimer_cal.h"
#include "gtimer_drv.h"
#include "gpio_drv.h"

#include "ape_csu.h"
#include "cpri_driver.h"
#include "cpri_csu_api.h"

#ifdef TEST_ENABLE
#include "cpri_test.h"
#endif

extern stPhyScsPara*		phyPara;
//extern stSfnPara			gCellSfnPara[2];
extern uint32_t				gScsId;

extern stCpriIntStat		gCpriIntStatus;

//stCpriTimerPara 			gCpriTimerPara;

extern stMtimerIntStat 		gMtimerIntCnt[SCS_MAX_NUM];
extern stMtimerPhyPara 		gMtimerSfnNum[SCS_MAX_NUM];
extern stMtimerSfnCal 		gMtimerSfnCalPara[SCS_MAX_NUM];

// 告警标志
//extern uint32_t 			gCpriAlarmFlag;
extern uint32_t 			gCpriCsuDummyFlag;

uint32_t gCpriAlarmSfnCnt = 0;

uint32_t gCpriTestMode = 0;
extern uint32_t* gCpriCsuStopCmd;
extern uint32_t  gCpriDelayOamSetFlag;

extern void rfm1_fapi_callback();


volatile uint32_t reCfgFlag = 0;

void cpri_timer_ecprimode_clk_init()
{
	// bit26: cpri_pma_clk_sel, A: cpri_serdes_tx_clk, B: cpri_div33_tx_clk
	// bit25: cpri_div33_clk_sel, A: jecs_pma_tx0_ropll_div33_clk, B: pet_tx_ropll_div33_clk
	// bit24: cpri_core_clk_sel1, A: tmp_cpri_clk, B: cpri_pma_clk
	// bit23: cpri_core_clk_sel0
	// bit22: cpri_tx_clk_sel
	do_write(&JECS_CRG_PLLSEL, do_read_volatile(&JECS_CRG_PLLSEL) | (BIT26|BIT24));

	// cpri_core_reset
    do_write(&JECS_CRG_CPRI4_RST_CTRL, do_read_volatile(&JECS_CRG_CPRI4_RST_CTRL) | BIT24);

	// cpri core clk div
	do_write(&JECS_CRG_CPRI_CORE_CLK_CTRL, 0x521000);
}

void cpri_mtimer_init(int32_t nScsId, int32_t nTddSlotNum)
{
	stMtimerIntStat* pMtimerInt = &gMtimerIntCnt[MTIMER_CPRI_ID];
	stMtimerPhyPara* pMtimerSfn = &gMtimerSfnNum[MTIMER_CPRI_ID];
	stMtimerSfnCal* pMtimerCalPara = &gMtimerSfnCalPara[MTIMER_CPRI_ID];

	memset(pMtimerInt, 0, sizeof(stMtimerIntStat));
	memset(pMtimerSfn, 0, sizeof(stMtimerPhyPara));
	memset(pMtimerCalPara, 0, sizeof(stMtimerSfnCal));

	mtimer_para_init(MTIMER_CPRI_ID, nScsId, nTddSlotNum);

    cpri_timer_init();
}

void cpri_timer_init()
{
	stMtimerIntStat* pMtimerInt = &gMtimerIntCnt[MTIMER_CPRI_ID];
	
    mtimer_clear_all_event(MTIMER_CPRI_ID);

    set_cpri_tmr_period();                   // set OVF value, every slot int and 10ms int, cevent0/2 for ape0, report link status

    set_cpri_tx_rfp();                       // cpri_tx_rfn 10ms pulse, tevent0 for ape0, int, delay meaurement
    set_cpri_tx_axc_ch_en();                 // axc_ch_en, tevent1 for ape0
	cpri_1pps_src_init(MTIMER_PP1S_SRC_TOD); // select stc tod pp1s as cpri pp1s input
    //set_cpri_1pps_scratch();                 // 1pps scratch, cevent17 for ape0, int, pp1s precision
    set_cpri_timer_int();                    // cpri timer int enable

	pMtimerInt->tmrIntInitFinished = 1;
}

void cpri_timer_reconfig(phy_timer_config_ind_t *my_cpritmr)
{
	int32_t apeId = get_core_id();
	int32_t flag = 0x10;
	debug_write((DBG_DDR_IDX_DRV_BASE+3+(apeId<<2)), flag); // 0xBc

    EcsRfmDmLocalMgt_t* pEcsDmLocalMgt = get_ecs_rfm_dm_local_mgt();
	stMtimerPara* pMtimerPara = pEcsDmLocalMgt->pMtimerPara[MTIMER_CPRI_ID];
	stMtimerPhyPara* pMtimerSfn = &gMtimerSfnNum[MTIMER_CPRI_ID];
	stMtimerIntStat* pMtimerInt = &gMtimerIntCnt[MTIMER_CPRI_ID];
	uint8_t nBsType = get_protocol_sel(); 

	// get cpri delay
	stCpriDelayMeasure* pCpriDelay = pEcsDmLocalMgt->pCpriDelay;
	uint32_t tempOffset;

	if (0 == gCpriDelayOamSetFlag)
	{
		pCpriDelay->cpriTxOffset = do_read_volatile(CSU_TX_ADVANCE_SAMPLE);
		pCpriDelay->cpriRxOffset = do_read_volatile(CSU_RX_TD_SAMPLE);		// ns
		pCpriDelay->cpriUlFrmDataOffset = do_read_volatile(CSU_UL_HEADER_DATA_OFFSET);
		__ucps2_synch(0);
	}

	//debug_write((DBG_DDR_IDX_DRV_BASE+62), pMtimerInt->tmrPP1sCost); // 0xF8

	//tempOffset = (uint32_t)(((float)pCpriDelay->cpriTxOffset/1000)+0.5);	// ns -> us
	//pCpriDelay->cpri10msOffset = (tempOffset < (CPRI_INT_DELAY+FIBER_MIN_DELAY)) ? (CPRI_INT_DELAY+FIBER_MIN_DELAY) : (tempOffset+CPRI_INT_DELAY+FIBER_MIN_DELAY);
	tempOffset = pCpriDelay->cpriTxOffset;
	pCpriDelay->cpri10msOffset = tempOffset + pMtimerInt->tmrPP1sCost*2; // +FIBER_MIN_DELAY;

	//tempOffset = (uint32_t)(((float)pCpriDelay->cpriRxOffset/1000)+0.5);	// ns -> us
	//pCpriDelay->cpri10msRxOffset = (tempOffset < (CPRI_INT_DELAY+FIBER_MIN_DELAY)) ? (CPRI_INT_DELAY+FIBER_MIN_DELAY) : (tempOffset+CPRI_INT_DELAY-FIBER_MIN_DELAY);
	tempOffset = pCpriDelay->cpriRxOffset;
	pCpriDelay->cpri10msRxOffset = (tempOffset < (12000-pMtimerInt->tmrPP1sCost*2)) ? (12000-pMtimerInt->tmrPP1sCost*2) : (tempOffset);

	pCpriDelay->cpriTddOffset = pCpriDelay->cpri10msOffset + EDMA_OFFSET;
	
	do_write(CPRI_DELAY_ADDR, pCpriDelay->cpri10msRxOffset);
    do_write(CPRI_ADVANCE_ADDR, pCpriDelay->cpri10msOffset);
    do_write(CPRI_TDD_ADVANCE_ADDR, pCpriDelay->cpriTddOffset);

	uint32_t addr = (uint32_t)&(phyPara[my_cpritmr->scsId].gpsOffset);
	uint16_t gpsOffset = do_read_volatile_short(addr);
	
	pCpriDelay->cpri10ms2PP1sTxOffset = pCpriDelay->cpri10msOffset + gpsOffset*1000; // advance ns
	pCpriDelay->cpri10ms2PP1sRxOffset = gpsOffset*1000 - pCpriDelay->cpri10msRxOffset; // delay ns
	pCpriDelay->cpriTdd2PP1sOffset = gpsOffset*1000 + pCpriDelay->cpriTddOffset; // advance ns as positive number
	
	reCfgFlag = 1;

	if (PROTOCOL_CPRI == nBsType)
	{
		set_cpri_tx_rfp();
	    if (do_read_volatile(CPRI_TX_ADVANCE_PP1S_ADDR) != pCpriDelay->cpri10ms2PP1sTxOffset)
		{
			while (1 == reCfgFlag);
		}
		else
		{
			gCpriIntStatus.cpriSyncFlag = 1;
		}
	}
#ifdef PALLADIUM_TEST
	flag++;
	debug_write((DBG_DDR_IDX_DRV_BASE+3+(apeId<<2)), flag);
#endif

    do_write(CPRI_TX_ADVANCE_PP1S_ADDR, pCpriDelay->cpri10ms2PP1sTxOffset);
    do_write(CPRI_RX_ADVANCE_PP1S_ADDR, pCpriDelay->cpri10ms2PP1sRxOffset);
    do_write(CPRI_TDD_ADVANCE_PP1S_ADDR, pCpriDelay->cpriTdd2PP1sOffset);

	//enable_mtimer_cevent_int(MTIMER_CPRI_ID, MTMR_CEVENT_CNT14H, MTMR_INT_10ms);	// 10ms int
#ifdef PALLADIUM_TEST
	flag++;
	debug_write((DBG_DDR_IDX_DRV_BASE+3+(apeId<<2)), flag);
#endif
	
	pMtimerPara->scsId = my_cpritmr->scsId;
	pMtimerPara->runCoreId = (uint16_t)my_cpritmr->runCoreId;
	pMtimerPara->tddPeriod = my_cpritmr->t_period; // us
	pMtimerPara->tddSlotNum = my_cpritmr->num_tti;
	pMtimerPara->slotPeriod = my_cpritmr->t_us;
	pMtimerPara->slotMaxNum = my_cpritmr->num_tti_per_sfn;
	pMtimerSfn->slotMaxNum = my_cpritmr->num_tti_per_sfn;
	pMtimerSfn->slotNumPP1s = (pCpriDelay->cpri10ms2PP1sTxOffset / (my_cpritmr->t_us*1000)) % my_cpritmr->num_tti_per_sfn;

	do_write_short((&(phyPara[my_cpritmr->scsId].slotNumOfTdd)), my_cpritmr->num_tti);
	do_write_short((&(phyPara[my_cpritmr->scsId].mtimerId)), MTIMER_CPRI_ID);
	__ucps2_synch(0);

	set_cpri_sfn_offset();
#ifdef PALLADIUM_TEST
		flag++;
		debug_write((DBG_DDR_IDX_DRV_BASE+3+(apeId<<2)), flag);
#endif

	if (PROTOCOL_CPRI == nBsType)
	{
		set_cpri_tdd_offset();					// 5ms int, tevent2 for all ape cores, dma
#ifdef PALLADIUM_TEST
		flag++;
		debug_write((DBG_DDR_IDX_DRV_BASE+3+(apeId<<2)), flag);
#endif
	}

	set_cpri_insert_int();
#ifdef PALLADIUM_TEST
	flag++;
	debug_write((DBG_DDR_IDX_DRV_BASE+3+(apeId<<2)), flag);
#endif

	pMtimerInt->txSlotIntCnt = 0;
	pMtimerInt->rxSlotIntCnt = 0;
	set_rx_slot_offset();
	set_tx_slot_offset();
#ifdef PALLADIUM_TEST
	flag++;
	debug_write((DBG_DDR_IDX_DRV_BASE+3+(apeId<<2)), flag);
#endif

	if (LTE_SCS_ID == my_cpritmr->scsId)
	{
		pMtimerInt->lteFapiIntCnt = 0;
		set_cpri_lte_fapi_offset();
#ifdef PALLADIUM_TEST
		flag++;
		debug_write((DBG_DDR_IDX_DRV_BASE+3+(apeId<<2)), flag);
#endif
	}

	if (PROTOCOL_ECPRI == nBsType)
	{
		for (int32_t i = 0; i < SLOT_SYMBOL_NUM; i++)
		{
			set_cpri_tx_symbol_offset(i);
		}
#ifdef PALLADIUM_TEST
		flag++;
		debug_write((DBG_DDR_IDX_DRV_BASE+3+(apeId<<2)), flag);
#endif
	}

	reCfgFlag = 3;
	pMtimerSfn->cellSetup = 1;
	debug_write((DBG_DDR_IDX_DRV_BASE+912), pMtimerSfn->txSfnNum);	// 0xE40
	debug_write((DBG_DDR_IDX_DRV_BASE+913), GET_STC_CNT());	        // 0xE44
}

void cpri_timer_clear_cell(uint8_t scsId)
{
	stMtimerSfnCal* pSfnCal = &gMtimerSfnCalPara[MTIMER_CPRI_ID];
	stMtimerIntStat* pMtimerInt = &gMtimerIntCnt[MTIMER_CPRI_ID];
	stMtimerPhyPara* pMtimerSfn = &gMtimerSfnNum[MTIMER_CPRI_ID];
	pSfnCal->sfnCalFinished = 0;
	pMtimerInt->csuEnCnt = 0;

	UCP_API_CPRI_CSU_STOP(); // 是否需要等几个ms

	clear_cpri_tdd_offset();
	clear_tx_slot_offset();
	clear_rx_slot_offset();
	if (LTE_SCS_ID == scsId)
	{
		clear_cpri_lte_fapi_offset();
	}
	pMtimerSfn->cellSetup = 0;
}

void cpri_timer_rcfg_act()
{
    EcsRfmDmLocalMgt_t* pEcsDmLocalMgt = get_ecs_rfm_dm_local_mgt();
	stMtimerPara* pMtimerPara = pEcsDmLocalMgt->pMtimerPara[MTIMER_CPRI_ID];
	stMtimerPhyPara* pMtimerSfn = &gMtimerSfnNum[MTIMER_CPRI_ID];
	int32_t nScsId = pMtimerPara->scsId;
	uint16_t runCore = pMtimerPara->runCoreId;
	uint32_t addr = (uint32_t)&(phyPara[nScsId].runCoreId);
	uint16_t cellCore = do_read_volatile_short(addr);

	set_cpri_tmr_period();					// set OVF value, every slot int and 10ms int, cevent0/2 for ape0, report link status

	//pMtimerSfn->txSfnNum = 0;
	pMtimerSfn->txSlotNum = pMtimerSfn->slotNumPP1s; // 0
	//pMtimerSfn->rxSfnNum = 0; // 1023;
	pMtimerSfn->rxSlotNum = pMtimerSfn->slotNumPP1s; // 0 // pMtimerSfn->slotMaxNum - 1;

	if ((0 == pMtimerSfn->slotNumPP1s) && (runCore == cellCore)) // no frame header offset, and the first cell
	{
		pMtimerSfn->txSfnNum++;
		pMtimerSfn->txSfnNum &= 0x3FF;
		pMtimerSfn->rxSfnNum = pMtimerSfn->txSfnNum;
	}
	addr = (uint32_t)&(phyPara[nScsId].txSfnNum);
	do_write(addr, pMtimerSfn->txSfnNum);
	addr = (uint32_t)&(phyPara[nScsId].rxSfnNum);
	do_write(addr, pMtimerSfn->rxSfnNum);
	addr = (uint32_t)&(phyPara[nScsId].txSlotNum);
	do_write(addr, pMtimerSfn->txSlotNum);
	addr = (uint32_t)&(phyPara[nScsId].rxSlotNum);
	do_write(addr, pMtimerSfn->rxSlotNum);
	
	debug_write((DBG_DDR_IDX_DRV_BASE+556), cellCore);	// 0x8b0
	debug_write((DBG_DDR_IDX_DRV_BASE+557), runCore);	// 0x8b4
	debug_write((DBG_DDR_IDX_DRV_BASE+558), pMtimerSfn->txSfnNum);	// 0x8b8
	debug_write((DBG_DDR_IDX_DRV_BASE+559), pMtimerSfn->rxSfnNum);	// 0x8bc
	
	do_write(CTC_INT_TYPE_ADDR, (MTIMER_CPRI_ID+1));
	if (PROTOCOL_ECPRI == get_protocol_sel())
	{
		// ecs rfm0 cal
		set_ctc_cal_int(ECS_RFM_SPU0_CORE_ID);
	}

	// ape tmrpoints
	volatile uint32_t h1Pos = __builtin_clz(runCore); // 从高bit开始，第一个1前面的0的个数
	uint8_t apeId = 0;
	__ucps2_synch(0);
	while (32 > h1Pos)
	{
		apeId = 31 - h1Pos;
		if (8 <= apeId)
		{
			return;
		}

		set_ctc_cal_int(apeId);

		runCore &= (~(1 << apeId));
		h1Pos = __builtin_clz(runCore);
		__ucps2_synch(0);
	}

	reCfgFlag = 5;
	disable_mtimer_cevent_int(MTIMER_CPRI_ID, MTMR_CEVENT_CNT14H, MTMR_INT_10ms);	// disable 10ms int
	debug_write((DBG_DDR_IDX_DRV_BASE+916), pMtimerSfn->txSfnNum);	// 0xE50
	debug_write((DBG_DDR_IDX_DRV_BASE+917), GET_STC_CNT());	        // 0xE54
}

void set_cpri_tmr_period(void)
{
    EcsRfmDmLocalMgt_t* pEcsDmLocalMgt = get_ecs_rfm_dm_local_mgt();
	stMtimerPara* pMtimerPara = pEcsDmLocalMgt->pMtimerPara[MTIMER_CPRI_ID];
	
	// 设置计数器溢出值
	uint32_t tempL = pMtimerPara->tmrMsPeriod * pMtimerPara->slotPeriod / 1000;
	uint32_t tempM = 2; //gCpriTimerPara.tddSlotNum;
	uint32_t tempH = SFN_PERIOD / pMtimerPara->slotPeriod / 2; //gCpriTimerPara.tddSlotNum;

	set_mtimer_period(MTIMER_CPRI_ID, tempL, tempM, tempH);
	
	//enable_mtimer_cevent_int(MTIMER_CPRI_ID, MTMR_CEVENT_CNT14H, MTMR_INT_10ms);	// 10ms int
}

void cpri_1pps_src_init(uint8_t srcId)
{
	JECS_CTRL_CPRI_GMAC_PHY_INT &= ~(0x7 << 10);
	JECS_CTRL_CPRI_GMAC_PHY_INT |= (srcId << 10);
}

void set_cpri_1pps_scratch(void)
{
	set_mtimer_1pps_scratch(MTIMER_CPRI_ID);
}

// 10ms
void set_cpri_sfn_offset(void)
{
	uint32_t offset = 0;
//#ifdef INTEGRATED_BS
//#else
	EcsRfmDmLocalMgt_t* pEcsDmLocalMgt = get_ecs_rfm_dm_local_mgt();
	offset = pEcsDmLocalMgt->pCpriDelay->cpri10ms2PP1sTxOffset; // pEcsDmLocalMgt->pCpriDelay->cpri10msOffset;
//#endif
	uint32_t tmr0Point = SFN_PERIOD*1000 - offset; // pEcsDmLocalMgt->pCpriDelay->cpri10msOffset; // us

	set_mtimer_tmrpoint_ns(MTIMER_CPRI_ID, MTMR_10ms_OFFSET, tmr0Point, MTIMER_MASK_62BIT);
	enable_mtimer_tmrpoint_int(MTIMER_CPRI_ID, MTMR_10ms_OFFSET, MTMR_INT_10ms);
}

void set_cpri_tx_rfp(void)
{
	set_cpri_sfn_offset();
	set_cpri_tmr_ctrl();
}

void set_cpri_tx_axc_ch_en(void)
{
	uint32_t offset = 0;
//#ifdef INTEGRATED_BS
//#else
    EcsRfmDmLocalMgt_t* pEcsDmLocalMgt = get_ecs_rfm_dm_local_mgt();
	offset = pEcsDmLocalMgt->pCpriDelay->cpri10ms2PP1sTxOffset; // pEcsDmLocalMgt->pCpriDelay->cpri10msOffset;
//#endif
	uint32_t tmr1Point = SFN_PERIOD*1000 - offset - 2000; 	// ns

	set_mtimer_tmrpoint_ns(MTIMER_CPRI_ID, MTMR_CSU_CH, tmr1Point, MTIMER_MASK_62BIT);
}

void set_cpri_tdd_offset(void)
{
	//stMtimerPara* pMtimerPara = pEcsDmLocalMgt->pMtimerPara[MTIMER_CPRI_ID];
	uint32_t offset = 0;
//#ifdef INTEGRATED_BS
//#else
    EcsRfmDmLocalMgt_t* pEcsDmLocalMgt = get_ecs_rfm_dm_local_mgt();
	offset = pEcsDmLocalMgt->pCpriDelay->cpriTdd2PP1sOffset; // pEcsDmLocalMgt->pCpriDelay->cpriTddOffset;
//#endif

	uint32_t tmr2Point = 5000*1000 - offset;  // us // 5ms
	set_mtimer_tmrpoint_ns(MTIMER_CPRI_ID, MTMR_TDD_OFFSET, tmr2Point, MTIMER_MASK_62BIT);
	enable_mtimer_tmrpoint_int(MTIMER_CPRI_ID, MTMR_TDD_OFFSET, MTMR_INT_TDD_OFFSET);

	uint32_t tmr25Point = SFN_PERIOD*1000 - offset;  // us // 5ms
	set_mtimer_tmrpoint_ns(MTIMER_CPRI_ID, MTMR_TDD_OFFSET_10000, tmr25Point, MTIMER_MASK_62BIT);
	enable_mtimer_tmrpoint_int(MTIMER_CPRI_ID, MTMR_TDD_OFFSET_10000, MTMR_INT_TDD_OFFSET);

	uint32_t tmr26Point = 2500*1000 - offset; // us
	set_mtimer_tmrpoint_ns(MTIMER_CPRI_ID, MTMR_TDD_OFFSET_2500, tmr26Point, MTIMER_MASK_62BIT);
	enable_mtimer_tmrpoint_int(MTIMER_CPRI_ID, MTMR_TDD_OFFSET_2500, MTMR_INT_TDD_OFFSET);

	uint32_t tmr27Point = 7500*1000 - offset;	// us
	set_mtimer_tmrpoint_ns(MTIMER_CPRI_ID, MTMR_TDD_OFFSET_7500, tmr27Point, MTIMER_MASK_62BIT);
	enable_mtimer_tmrpoint_int(MTIMER_CPRI_ID, MTMR_TDD_OFFSET_7500, MTMR_INT_TDD_OFFSET);

}

void clear_cpri_tdd_offset(void)
{
	disable_mtimer_tmrpoint_int(MTIMER_CPRI_ID, MTMR_TDD_OFFSET, MTMR_INT_TDD_OFFSET);
	disable_mtimer_tmrpoint_int(MTIMER_CPRI_ID, MTMR_TDD_OFFSET_10000, MTMR_INT_TDD_OFFSET);
	disable_mtimer_tmrpoint_int(MTIMER_CPRI_ID, MTMR_TDD_OFFSET_2500, MTMR_INT_TDD_OFFSET);
	disable_mtimer_tmrpoint_int(MTIMER_CPRI_ID, MTMR_TDD_OFFSET_7500, MTMR_INT_TDD_OFFSET);
}

void set_tx_slot_offset()
{
	uint32_t offset = 0;
//#ifdef INTEGRATED_BS
//#else
    EcsRfmDmLocalMgt_t* pEcsDmLocalMgt = get_ecs_rfm_dm_local_mgt();
	offset = pEcsDmLocalMgt->pCpriDelay->cpri10ms2PP1sTxOffset; // pEcsDmLocalMgt->pCpriDelay->cpri10msOffset;
//#endif

	uint32_t tmr3Point = SFN_PERIOD*1000 - offset; // us
	set_mtimer_tmrpoint_ns(MTIMER_CPRI_ID, MTMR_TXSLOT_OFFSET, tmr3Point, MTIMER_MASK_32BIT);
	enable_mtimer_tmrpoint_int(MTIMER_CPRI_ID, MTMR_TXSLOT_OFFSET, MTMR_INT_SLOT_OFFSET);

	//uint32_t tempL = gCpriTimerPara.tmrMsPeriod * (tmr3Point % gCpriTimerPara.slotPeriod) / 1000;
	//uint32_t addr = (uint32_t)&(phyPara[gCpriTimerPara.scsId].txSetVal);
	//do_write(addr, tempL);

#if 0
	// ape tmrpoints
	for (int32_t i = 0; i < APE_NUM; i++)
	{
		int32_t tmrId = MTMR_APE0_TXSLOT + (i<<1);
		set_mtimer_tmrpoint(MTIMER_CPRI_ID, tmrId, tmr3Point, MTIMER_MASK_32BIT);
		enable_mtimer_tmrpoint_int(MTIMER_CPRI_ID, tmrId, (MTMR_INT_APE0_SLOT+i));
	}
	// rfm0 tmrpoints
	int32_t tmrId = MTMR_RFM0_TXSLOT;
	set_mtimer_tmrpoint(MTIMER_CPRI_ID, tmrId, tmr3Point, MTIMER_MASK_32BIT);
	enable_mtimer_tmrpoint_int(MTIMER_CPRI_ID, tmrId, MTMR_INT_RFM0_SLOT);
#endif
}

void clear_tx_slot_offset()
{
	disable_mtimer_tmrpoint_int(MTIMER_CPRI_ID, MTMR_TXSLOT_OFFSET, MTMR_INT_SLOT_OFFSET);
}

void set_rx_slot_offset()
{
	int32_t offset = 0;
//#ifdef INTEGRATED_BS
//#else
    EcsRfmDmLocalMgt_t* pEcsDmLocalMgt = get_ecs_rfm_dm_local_mgt();
	offset = pEcsDmLocalMgt->pCpriDelay->cpri10ms2PP1sRxOffset; // pEcsDmLocalMgt->pCpriDelay->cpri10msRxOffset;
//#endif

	uint32_t tmr4Point = 0; // offset; // us
	if (offset < 0)
	{
		tmr4Point = (~offset) + 1;
	}
	else
	{
		tmr4Point = SFN_PERIOD*1000 - offset; // us
	}
	set_mtimer_tmrpoint_ns(MTIMER_CPRI_ID, MTMR_RXSLOT_OFFSET, tmr4Point, MTIMER_MASK_32BIT);
	enable_mtimer_tmrpoint_int(MTIMER_CPRI_ID, MTMR_RXSLOT_OFFSET, MTMR_INT_SLOT_OFFSET);

	//uint32_t tempL = gCpriTimerPara.tmrMsPeriod * (tmr3Point % gCpriTimerPara.slotPeriod) / 1000;
	//uint32_t addr = (uint32_t)&(phyPara[gCpriTimerPara.scsId].txSetVal);
	//do_write(addr, tempL);

#if 0
	// ape tmrpoints
	for (int32_t i = 0; i < APE_NUM; i++)
	{
		int32_t tmrId = MTMR_APE0_RXSLOT + (i<<1);
		set_mtimer_tmrpoint(MTIMER_CPRI_ID, tmrId, tmr4Point, MTIMER_MASK_32BIT);
		enable_mtimer_tmrpoint_int(MTIMER_CPRI_ID, tmrId, (MTMR_INT_APE0_SLOT+i));
	}
	// rfm0 tmrpoints
	int32_t tmrId = MTMR_RFM0_RXSLOT;
	set_mtimer_tmrpoint(MTIMER_CPRI_ID, tmrId, tmr4Point, MTIMER_MASK_32BIT);
	enable_mtimer_tmrpoint_int(MTIMER_CPRI_ID, tmrId, MTMR_INT_RFM0_SLOT);
#endif
}

void clear_rx_slot_offset()
{
	disable_mtimer_tmrpoint_int(MTIMER_CPRI_ID, MTMR_RXSLOT_OFFSET, MTMR_INT_SLOT_OFFSET);
}


void set_cpri_lte_fapi_offset(void)
{
	uint32_t offset = 0;
//#ifdef INTEGRATED_BS
//#else
	EcsRfmDmLocalMgt_t* pEcsDmLocalMgt = get_ecs_rfm_dm_local_mgt();
	offset = pEcsDmLocalMgt->pCpriDelay->cpri10ms2PP1sTxOffset; // pEcsDmLocalMgt->pCpriDelay->cpri10msOffset;
//#endif
	uint32_t tmr30Point = SFN_PERIOD*1000 - offset - 500000; // ns

	set_mtimer_tmrpoint_ns(MTIMER_CPRI_ID, MTMR_LTE_FAPI, tmr30Point, MTIMER_MASK_32BIT);
	enable_mtimer_tmrpoint_int(MTIMER_CPRI_ID, MTMR_LTE_FAPI, MTMR_INT_SLOT_OFFSET);

}

void clear_cpri_lte_fapi_offset(void)
{
	disable_mtimer_tmrpoint_int(MTIMER_CPRI_ID, MTMR_LTE_FAPI, MTMR_INT_SLOT_OFFSET);
}


int32_t set_cpri_ape_slot_offset(uint32_t apeCoreId)
{
	uint32_t txOffset = 0;
	uint32_t rxOffset = 0;
	uint32_t runCore = apeCoreId;
	volatile uint32_t h1Pos = 0;
	uint8_t apeId = 0;
	int32_t tmrId = 0;

	EcsRfmDmLocalMgt_t* pEcsDmLocalMgt = get_ecs_rfm_dm_local_mgt();
	stMtimerPara* pMtimerPara = pEcsDmLocalMgt->pMtimerPara[MTIMER_CPRI_ID];
	stMtimerPhyPara* pMtimerSfn = &gMtimerSfnNum[MTIMER_CPRI_ID];
	pMtimerPara->runCoreId = apeCoreId;
	txOffset = pEcsDmLocalMgt->pCpriDelay->cpri10ms2PP1sTxOffset; // pEcsDmLocalMgt->pCpriDelay->cpri10msOffset;
	rxOffset = pEcsDmLocalMgt->pCpriDelay->cpri10ms2PP1sRxOffset; // pEcsDmLocalMgt->pCpriDelay->cpri10msRxOffset;

	enable_mtimer_cevent_int(MTIMER_CPRI_ID, MTMR_CEVENT_CNT14H, MTMR_INT_10ms);	// 10ms int

	uint32_t tmr3Point = SFN_PERIOD*1000 - txOffset; // us
	uint32_t tmr4Point = 0; // offset; // us
	if (rxOffset < 0)
	{
		tmr4Point = (~rxOffset) + 1;
	}
	else
	{
		tmr4Point = SFN_PERIOD*1000 - rxOffset; // us
	}
	
	// ape tmrpoints
	h1Pos = __builtin_clz(runCore); // 从高bit开始，第一个1前面的0的个数
	while (32 > h1Pos)
	{
		apeId = 31 - h1Pos;
		if (8 <= apeId)
		{
			return -1;
		}
		// tx slot int
		tmrId = MTMR_APE0_TXSLOT + (apeId<<1);
		set_mtimer_tmrpoint_ns(MTIMER_CPRI_ID, tmrId, tmr3Point, MTIMER_MASK_32BIT);
		enable_mtimer_tmrpoint_int(MTIMER_CPRI_ID, tmrId, (MTMR_INT_APE0_SLOT+apeId));
		// rx slot int
		tmrId = MTMR_APE0_RXSLOT + (apeId<<1);
		set_mtimer_tmrpoint_ns(MTIMER_CPRI_ID, tmrId, tmr4Point, MTIMER_MASK_32BIT);
		enable_mtimer_tmrpoint_int(MTIMER_CPRI_ID, tmrId, (MTMR_INT_APE0_SLOT+apeId));

		runCore &= (~(1 << apeId));
		h1Pos = __builtin_clz(runCore);
	}
	
	reCfgFlag = 4;
	debug_write((DBG_DDR_IDX_DRV_BASE+914), pMtimerSfn->txSfnNum);	// 0xE48
	debug_write((DBG_DDR_IDX_DRV_BASE+915), GET_STC_CNT());	        // 0xE4c

	return 0;
}

int32_t clear_cpri_ape_slot_offset(uint32_t apeCoreId)
{
	uint32_t runCore = apeCoreId;
	volatile uint32_t h1Pos = 0;
	uint8_t apeId = 0;
	int32_t tmrId = 0;

	// ape tmrpoints
	h1Pos = __builtin_clz(runCore); // 从高bit开始，第一个1前面的0的个数
	while (32 > h1Pos)
	{
		apeId = 31 - h1Pos;
		if (8 <= apeId)
		{
			return -1;
		}
		// tx slot int
		tmrId = MTMR_APE0_TXSLOT + (apeId<<1);
		disable_mtimer_tmrpoint_int(MTIMER_CPRI_ID, tmrId, (MTMR_INT_APE0_SLOT+apeId));
		// rx slot int
		tmrId = MTMR_APE0_RXSLOT + (apeId<<1);
		disable_mtimer_tmrpoint_int(MTIMER_CPRI_ID, tmrId, (MTMR_INT_APE0_SLOT+apeId));

		runCore &= (~(1 << apeId));
		h1Pos = __builtin_clz(runCore);
	}

	return 0;
}


int32_t set_cpri_tx_symbol_offset(uint8_t symbolId)
{
	if (SLOT_SYMBOL_NUM <= symbolId)
	{
		return -1;
	}
	
	uint32_t longCp = (uint32_t)4448*500000/(4448+13*4384); // ns
	uint32_t shortCp = (uint32_t)4384*500000/(4448+13*4384); // ns
	
	int32_t tmrPoint = 0 - CPRI_INT_DELAY;
	if (1 >= symbolId)
	{
		tmrPoint += ((longCp*symbolId));
	}
	else
	{
		tmrPoint += ((longCp + shortCp*(symbolId-1)));
	}

	set_mtimer_tmrpoint_ns(MTIMER_CPRI_ID, MTMR_ECPRI_TX_SYMBOL0+symbolId, tmrPoint, MTIMER_MASK_32BIT);
	enable_mtimer_tmrpoint_int(MTIMER_CPRI_ID, MTMR_ECPRI_TX_SYMBOL0+symbolId, MTMR_INT_RFM0_SLOT);

	return 0;
}


void set_cpri_insert_int(void)
{
	uint32_t offset = 0;
//#ifdef DISTRIBUTED_BS
    EcsRfmDmLocalMgt_t* pEcsDmLocalMgt = get_ecs_rfm_dm_local_mgt();
	offset = pEcsDmLocalMgt->pCpriDelay->cpri10ms2PP1sTxOffset; // pEcsDmLocalMgt->pCpriDelay->cpri10msOffset;
//#endif

	UINT32 tmr24Point = 8000000 - offset;  // us
	set_mtimer_tmrpoint_ns(MTIMER_CPRI_ID, MTMR_CSU_INSERT, tmr24Point, MTIMER_MASK_62BIT);
	enable_mtimer_tmrpoint_int(MTIMER_CPRI_ID, MTMR_CSU_INSERT, MTMR_INT_TDD_OFFSET);
}

void set_cpri_timer_int(void)
{
	int32_t apeId = get_core_id(); // Get_ApcId(); //
	uint32_t intNum = 0;

	intNum = APC_CPRI_TMR_INTR0 + MTMR_INT_10ms;
	int32_t ret = smart_irq_request(intNum, isr_cpri_10ms);
	if (0 != ret)
	{
		UCP_PRINT_EMPTY("attach int num: 0x%x error. errno = 0x%x. \r\n", intNum, ret);
		debug_write(DBG_DDR_ERR_IDX(apeId, 1), ret);
	}

	intNum = APC_CPRI_TMR_INTR0 + MTMR_INT_TDD_OFFSET;
	ret = smart_irq_request(intNum, isr_cpri_tdd_offset);
	if (0 != ret)
	{
		UCP_PRINT_EMPTY("attach int num: 0x%x error. errno = 0x%x. \r\n", intNum, ret);
		debug_write(DBG_DDR_ERR_IDX(apeId, 2), ret);
	}

	intNum = APC_CPRI_TMR_INTR0 + MTMR_INT_SLOT_OFFSET;
	ret = smart_irq_request(intNum, isr_cpri_slot_offset);
	if (0 != ret)
	{
		UCP_PRINT_EMPTY("attach int num: 0x%x error. errno = 0x%x. \r\n", intNum, ret);
		debug_write(DBG_DDR_ERR_IDX(apeId, 3), ret);
	}
}

void start_cpri_timer(void)
{
	start_mtimer(MTIMER_CPRI_ID);
}

void stop_cpri_timer(void)
{
	stop_mtimer(MTIMER_CPRI_ID);
}

// temp to be deleted
int32_t gRfm1SlotIntCnt = 0;
//int32_t gPP1sLockCnt = 0;
uint32_t lastTxSlotCnt = 0;
uint32_t nowTxSlotCnt = 0;
uint32_t rfmSlotErrCnt = 0;
uint32_t rfmSlotErrMax = 0;
void isr_cpri_10ms(void)
{
	uint32_t tmrIntcFlag = 0;
	uint32_t cEventFlag = 0;
	uint32_t tEventFlag = 0;
    EcsRfmDmLocalMgt_t* pEcsDmLocalMgt = get_ecs_rfm_dm_local_mgt();
	stMtimerIntStat* pMtimerInt = &gMtimerIntCnt[MTIMER_CPRI_ID];
	stMtimerPhyPara* pMtimerSfn = &gMtimerSfnNum[MTIMER_CPRI_ID];
	stMtimerSfnCal* pMtimerCal = &gMtimerSfnCalPara[MTIMER_CPRI_ID];
	stMtimerPara* pMtimerPara = pEcsDmLocalMgt->pMtimerPara[MTIMER_CPRI_ID];
	uint32_t tmrBaseAddr = mtimer_get_baseaddr(MTIMER_CPRI_ID);
	uint8_t apeId = get_core_id();

	tmrIntcFlag = do_read_volatile(tmrBaseAddr + MTMR_INTC_REG) ;
	//__ucps2_synch(0);
	if ((tmrIntcFlag & (1 << MTMR_INT_10ms)))  /* tmr int */
	{
		uint32_t cFlagAddr = tmrBaseAddr + MTMR_CINTF0_REG + 2*(MTMR_INT_10ms<<2);
		uint32_t tFlagAddr = tmrBaseAddr + MTMR_TINTF00_REG + 6*(MTMR_INT_10ms<<2);
		cEventFlag = do_read_volatile(cFlagAddr);
		tEventFlag = do_read_volatile(tFlagAddr);
		//__ucps2_synch(0);
		if ((cEventFlag & BIT17) || (cEventFlag & BIT2) || (tEventFlag & (1<<MTMR_10ms_OFFSET)))
		{
			if (cEventFlag & BIT17)	// 1pps int
			{
				do_write((tmrBaseAddr+MTMR_CEVENT_REG), BIT17);
				do_write(cFlagAddr, BIT17);	// clear int flag
//uint32_t start = GET_STC_CNT();
				if (0 == pMtimerInt->pp1sIntCnt)
				{
					start_cpri_timer();
					gtimer2_start(0);
					pMtimerSfn->txSfnNum = 0;
					pMtimerInt->tmrPP1sCost = GET_STC_CNT();
				    debug_write((DBG_DDR_IDX_DRV_BASE+61), pMtimerInt->tmrPP1sCost); // 0xF4
				}

#ifdef ENABLE_SFNCAL
				debug_write((DBG_DDR_IDX_DRV_BASE+60), pMtimerSfn->txSfnNum);
				mtimer_1pps_func(MTIMER_CPRI_ID);
#endif
				pMtimerInt->pp1sIntCnt++;
				debug_write((DBG_DDR_IDX_DRV_BASE+64+1), pMtimerInt->pp1sIntCnt); // 0x104
#if 0//def PALLADIUM_TEST
				//debug_write((DBG_DDR_IDX_DRV_BASE+576+(gCpriTimerPara.pp1sIntCnt&0x3f)), get_tx_nr_slot(1)); // 0xB7E06900

				uint32_t val = 0;
				for (int32_t core = 0; core < 12; core++)
				{
					val = do_read_volatile(SLOT_NUM_DEBUG_ADDR+((core<<2)<<2));
					debug_write(((DBG_DDR_IDX_DRV_BASE+832+(core<<2))), val);	// 0xd00

					val = do_read_volatile(SLOT_NUM_DEBUG_ADDR+((1+(core<<2))<<2));
					debug_write(((DBG_DDR_IDX_DRV_BASE+832+(core<<2)) + 1), val);	// 0xd00

					val = do_read_volatile(SLOT_NUM_DEBUG_ADDR+((2+(core<<2))<<2));
					debug_write(((DBG_DDR_IDX_DRV_BASE+832+(core<<2)) + 2), val);	// 0xd00

					val = do_read_volatile(SLOT_NUM_DEBUG_ADDR+((3+(core<<2))<<2));
					debug_write(((DBG_DDR_IDX_DRV_BASE+832+(core<<2)) + 3), val);	// 0xd00
				}
#endif
//debug_write((DBG_DDR_IDX_DRV_BASE+288), (GET_STC_CNT()-start));	// 0x480
			}
			if (tEventFlag & (1<<MTMR_10ms_OFFSET)) 				// 10ms offset int
			{
				do_write((tmrBaseAddr+MTMR_TEVENT0_REG), (1<<MTMR_10ms_OFFSET));
				do_write(tFlagAddr, (1<<MTMR_10ms_OFFSET));	// clear int flag

				pMtimerInt->sfnOffsetIntFlag = 1;
				pMtimerInt->sfnOffsetIntCnt++;
				if (0 == pMtimerSfn->cellSetup)
				{
					pMtimerSfn->txSfnNum++;
					pMtimerSfn->txSfnNum &= 0x3FF;
					do_write(SLOT_NUM_DEBUG_ADDR+((apeId<<2)<<2), pMtimerSfn->txSfnNum);
				}
#ifdef PALLADIUM_TEST
				debug_write((DBG_DDR_IDX_DRV_BASE+64+3), pMtimerInt->sfnOffsetIntCnt);	// 0x10C
				//debug_write((DBG_DDR_IDX_DRV_BASE+672+(pMtimerInt->sfnOffsetIntCnt&0x1f)), pMtimerSfn->txSlotNum); //get_tx_nr_slot(1)); // 0xb7e06a00
#endif
//uint32_t start = GET_STC_CNT();
                if (0 == (pMtimerInt->sfnOffsetIntCnt&0x3))
                {
                    spu_log_server_isr();
                }
//debug_write((DBG_DDR_IDX_DRV_BASE+259), (GET_STC_CNT()-start)); // 0x40c
			}
			if (cEventFlag & (1<<MTMR_CEVENT_CNT14H)) 			// 10ms int
			{
				do_write((tmrBaseAddr+MTMR_CEVENT_REG), (1<<MTMR_CEVENT_CNT14H));
				do_write(cFlagAddr, (1<<MTMR_CEVENT_CNT14H));	// clear int flag
				pMtimerInt->sfnIntCnt++;
#ifdef PALLADIUM_TEST
				debug_write((DBG_DDR_IDX_DRV_BASE+64+2), pMtimerInt->sfnIntCnt);	// 0x108
#endif
				uint16_t runCore = do_read_volatile_short(&(phyPara[gScsId].runCoreId));
				if (((runCore & pMtimerPara->runCoreId) == pMtimerPara->runCoreId) && (4 == reCfgFlag))
				{
					debug_write((DBG_DDR_IDX_DRV_BASE+907), GET_STC_CNT()); // 0xe2c	// timer restart finished
//uint32_t start = GET_STC_CNT();
					cpri_timer_rcfg_act();
//debug_write((DBG_DDR_IDX_DRV_BASE+288), (GET_STC_CNT()-start)); // 0x480
					pMtimerCal->sfnCalFinished = 1;
					debug_write((DBG_DDR_IDX_DRV_BASE+910), cEventFlag); // pMtimerInt->txSlotIntCnt); // 0xe38
					debug_write((DBG_DDR_IDX_DRV_BASE+911), get_mtimer_rt_scr_value(MTIMER_CPRI_ID)); // pMtimerInt->tddOffsetIntCnt); // 0xe3C
				}
				set_trigger_state(GPIO_ON);
			}
			cEventFlag = do_read_volatile(cFlagAddr);
			tEventFlag = do_read_volatile(tFlagAddr);
		}
		do_write((tmrBaseAddr+MTMR_INTC_REG), (1 << MTMR_INT_10ms));			// clear int
	}
}

uint32_t gLast2500usStcCnt = 0;
uint32_t gCpriCsuIntErrCnt = 0;
uint32_t gCpriCsuFifoRxCnt = 0;
uint32_t gCpriCsuFifoTxCnt = 0;
uint32_t gIntervalMax = 0;
uint32_t gIntervalMin = 2500000;
void isr_cpri_tdd_offset(void)
{
	uint32_t tmrIntcFlag = 0;
	uint32_t tEventFlag = 0;
	stMtimerIntStat* pMtimerInt = &gMtimerIntCnt[MTIMER_CPRI_ID];
	stMtimerSfnCal* pMtimerCal = &gMtimerSfnCalPara[MTIMER_CPRI_ID];
	stMtimerPhyPara* pMtimerSfn = &gMtimerSfnNum[MTIMER_CPRI_ID];
	uint32_t tmrBaseAddr = mtimer_get_baseaddr(MTIMER_CPRI_ID);

	tmrIntcFlag = do_read_volatile(tmrBaseAddr + MTMR_INTC_REG); // &CPRI_TMR_INTC_REG);
	//__ucps2_synch(0);
	if ((tmrIntcFlag & (1 << MTMR_INT_TDD_OFFSET)))  /* tmr int */
	{
		uint32_t tFlagAddr = tmrBaseAddr + MTMR_TINTF00_REG + 6*(MTMR_INT_TDD_OFFSET<<2);
		tEventFlag = do_read_volatile(tFlagAddr);
		//__ucps2_synch(0);
		uint32_t tddVal = (1<<MTMR_TDD_OFFSET_2500) | (1<<MTMR_TDD_OFFSET_10000) | (1<<MTMR_TDD_OFFSET) | (1<<MTMR_TDD_OFFSET_7500);
		if (tEventFlag & (tddVal|(1<<MTMR_CSU_INSERT)))
		{
			if (tEventFlag & tddVal)		// tdd offset int
			{
				uint32_t setFlag = tEventFlag & tddVal;
				do_write((tmrBaseAddr+MTMR_TEVENT0_REG), setFlag);
				do_write(tFlagAddr, setFlag);	// clear int flag
//uint32_t start = GET_STC_CNT();
				pMtimerInt->tddOffsetIntCnt++;
			// start_csu_timing
#ifdef PALLADIUM_TEST
				debug_write((DBG_DDR_IDX_DRV_BASE+64+4), pMtimerInt->tddOffsetIntCnt); // 0x110
//				debug_write(((DBG_DDR_IDX_DRV_BASE+576) + (gCpriTimerPara.tddOffsetIntCnt&0x3F)), get_tx_nr_slot(NR_SCS_30K)); 	// 0x900
#endif
#if 0 //def CPRI_TIMING_TEST
				if (tEventFlag & ((1<<MTMR_TDD_OFFSET_10000)|(1<<MTMR_TDD_OFFSET)))
				{
					debug_write((DBG_DDR_IDX_DRV_BASE+896+(pMtimerInt->tddOffsetIntCnt&0x3F)), UCP_API_CPRI_GetTxHfnCnt()); // 0xE00
					debug_write((DBG_DDR_IDX_DRV_BASE+960+(pMtimerInt->tddOffsetIntCnt&0x3F)), UCP_API_CPRI_GetRxHfnCnt()); // 0xF00
					cpri_tdd_start_csu_timing();
				}
#endif
#if 0
				if (32 > pMtimerInt->tddOffsetIntCnt)
				{
					debug_write((DBG_DDR_IDX_DRV_BASE+896+(pMtimerInt->tddOffsetIntCnt<<2)), pMtimerSfn->txSlotNum); // 0xe00
					debug_write((DBG_DDR_IDX_DRV_BASE+897+(pMtimerInt->tddOffsetIntCnt<<2)), pMtimerSfn->rxSlotNum); // 0xe04
					debug_write((DBG_DDR_IDX_DRV_BASE+898+(pMtimerInt->tddOffsetIntCnt<<2)), pMtimerInt->txSlotIntCnt); // 0xe08
					debug_write((DBG_DDR_IDX_DRV_BASE+899+(pMtimerInt->tddOffsetIntCnt<<2)), tEventFlag); // 0xe0c
				}
#endif
				debug_write((DBG_DDR_IDX_DRV_BASE+970), pMtimerCal->sfnCalFinished);	// 0xf28
				debug_write((DBG_DDR_IDX_DRV_BASE+971), gCpriIntStatus.cpriSyncFlag);	// 0xf2c
				if ((1 == pMtimerCal->sfnCalFinished)  && (1 == gCpriIntStatus.cpriSyncFlag))
				{
					// wait fifo num empty
					if ((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)))
					{
						UCP_API_CPRI_CSU_Flush_Latch(CPRI_CSU_TX0_LATCH_FLUSH_ID); // flush csu latch
						UCP_API_CPRI_CSU_Flush_Latch(CPRI_CSU_RX0_LATCH_FLUSH_ID);

						gCpriIntStatus.cpriSyncFlag = 0;
						UCP_API_CPRI_CSU_CH_Disable(UCP_API_CPRI_CSU_Get_AxcIdNum(), UCP_API_CPRI_CSU_Get_LatchNum());
						do_write(CSU_STOP_CMD_ADDR, 0);
						pMtimerInt->csuEnCnt = 0;
						debug_write((DBG_DDR_IDX_DRV_BASE+908), GET_STC_CNT()); // 0xe30
						debug_write((DBG_DDR_IDX_DRV_BASE+909), tEventFlag);	// 0xe34
					}
				}
				if (((0 == do_read_volatile(CSU_STOP_CMD_ADDR)) && (0 == pMtimerInt->csuEnCnt) && (tEventFlag & (1<<MTMR_TDD_OFFSET_10000))) || (0 != pMtimerInt->csuEnCnt))
				{
					//debug_write((DBG_DDR_IDX_DRV_BASE+896+(pMtimerInt->csuEnCnt&0x3F)), UCP_API_CPRI_GetTxHfnCnt()); // 0xE00
					//debug_write((DBG_DDR_IDX_DRV_BASE+960+(pMtimerInt->csuEnCnt&0x3F)), UCP_API_CPRI_GetRxHfnCnt()); // 0xF00

					cpri_tdd_start_csu_7ds2u();
					if ((1 == pMtimerInt->csuEnCnt) && (tEventFlag & (BIT25)))
					{
						UCP_API_CPRI_CSU_CH_Enable(UCP_API_CPRI_CSU_Get_AxcIdNum(), UCP_API_CPRI_CSU_Get_LatchNum());
						debug_write((DBG_DDR_IDX_DRV_BASE+974), GET_STC_CNT()); // 0xf38
						debug_write((DBG_DDR_IDX_DRV_BASE+896), UCP_API_CPRI_GetTxHfnCnt()); // 0xe00
						debug_write((DBG_DDR_IDX_DRV_BASE+897), UCP_API_CPRI_GetRxHfnCnt()); // 0xe04
						debug_write((DBG_DDR_IDX_DRV_BASE+898), pMtimerInt->tddOffsetIntCnt); // 0xe08
						debug_write((DBG_DDR_IDX_DRV_BASE+900), pMtimerSfn->txSlotNum); // 0xe10
						debug_write((DBG_DDR_IDX_DRV_BASE+901), pMtimerSfn->txSfnNum); // 0xe14
						debug_write((DBG_DDR_IDX_DRV_BASE+902), pMtimerSfn->rxSlotNum); // 0xe18
						debug_write((DBG_DDR_IDX_DRV_BASE+903), pMtimerSfn->rxSfnNum); // 0xe1c
					}
				}
#if 1
				uint32_t stcCntTemp = GET_STC_CNT();
				if ((stcCntTemp > gLast2500usStcCnt) && (8 < pMtimerInt->tddOffsetIntCnt))
				{
					uint32_t cost = stcCntTemp - gLast2500usStcCnt;
					if ((2505000 < cost) || (2495000 > cost))
					{
						gCpriCsuIntErrCnt++;
						debug_write((DBG_DDR_IDX_DRV_BASE+72), gCpriCsuIntErrCnt); // 0x120
						debug_write((DBG_DDR_IDX_DRV_BASE+73), cost);			// 0x124
					}
					if (cost > gIntervalMax)
					{
						gIntervalMax = cost;
						debug_write((DBG_DDR_IDX_DRV_BASE+74), gIntervalMax); // 0x128
					}
					if (cost < gIntervalMin)
					{
						gIntervalMin = cost;
						debug_write((DBG_DDR_IDX_DRV_BASE+75), gIntervalMin); // 0x12c
					}
				}
				gLast2500usStcCnt = stcCntTemp;

				if (0 == do_read_volatile(&JECS_CSU_CMDFIFO0_NUM))
				{
					gCpriCsuFifoRxCnt++;
					debug_write((DBG_DDR_IDX_DRV_BASE+76), gCpriCsuFifoRxCnt); // 0x130
				}
				if (0 == do_read_volatile(&JECS_CSU_CMDFIFO1_NUM))
				{
					gCpriCsuFifoTxCnt++;
					debug_write((DBG_DDR_IDX_DRV_BASE+77), gCpriCsuFifoTxCnt); // 0x134
				}
#endif
//debug_write((DBG_DDR_IDX_DRV_BASE+289), (GET_STC_CNT()-start)); // 0x484
			}
			if (tEventFlag & (1<<MTMR_CSU_INSERT))		// 8ms int
			{
				do_write((tmrBaseAddr+MTMR_TEVENT0_REG), (1<<MTMR_CSU_INSERT));
				do_write(tFlagAddr, (1<<MTMR_CSU_INSERT));	// clear int flag
				pMtimerInt->insOffsetIntCnt++;
				// start_csu_timing
#ifdef PALLADIUM_TEST
				debug_write((DBG_DDR_IDX_DRV_BASE+64+5), pMtimerInt->insOffsetIntCnt); // 0x114
#endif
				Cpri_Header_Tx();
//#ifdef TEST_ENABLE
				//Cpri_Header_Rx();
//#endif
			}
			tEventFlag = do_read_volatile(tFlagAddr);
		}
		do_write((tmrBaseAddr+MTMR_INTC_REG), (1 << MTMR_INT_TDD_OFFSET));			// clear int
	}
}

uint32_t gCpriCsuFifoErrCnt = 0;
uint32_t gCpriCsuFifoErrFlag = 0;
void isr_cpri_slot_offset(void)
{
	uint32_t tmrIntcFlag = 0;
	uint32_t tEventFlag = 0;
	int32_t apeId = get_core_id();
	stCoreInt* apeCoreIntInfo = (stCoreInt*)APE_INT_INFO_ADDR + APE_INT_MAXNUM*apeId;
    //EcsRfmDmLocalMgt_t* pEcsDmLocalMgt = get_ecs_rfm_dm_local_mgt();
	//stMtimerPara* pMtimerPara = pEcsDmLocalMgt->pMtimerPara[MTIMER_CPRI_ID];
	stMtimerIntStat* pMtimerInt = &gMtimerIntCnt[MTIMER_CPRI_ID];
	stMtimerPhyPara* pMtimerSfn = &gMtimerSfnNum[MTIMER_CPRI_ID];
	//stMtimerSfnCal* pMtimerCal = &gMtimerSfnCalPara[MTIMER_CPRI_ID];
	uint32_t tmrBaseAddr = mtimer_get_baseaddr(MTIMER_CPRI_ID);

	tmrIntcFlag = do_read_volatile(tmrBaseAddr+MTMR_INTC_REG);
	//__ucps2_synch(0);
	if ((tmrIntcFlag & (1 << MTMR_INT_SLOT_OFFSET)))  /* tmr int */
	{
		uint32_t tFlagAddr = tmrBaseAddr+MTMR_TINTF00_REG + 6*(MTMR_INT_SLOT_OFFSET<<2);
		tEventFlag = do_read_volatile(tFlagAddr);
		//__ucps2_synch(0);
		if (tEventFlag & ((1<<MTMR_TXSLOT_OFFSET)|(1<<MTMR_RXSLOT_OFFSET)|(1<<MTMR_LTE_FAPI)))
		{
			if (tEventFlag & (1<<MTMR_TXSLOT_OFFSET)) // tx slot offset
			{
				do_write((tmrBaseAddr+MTMR_TEVENT0_REG), (1<<MTMR_TXSLOT_OFFSET));
				do_write(tFlagAddr, (1<<MTMR_TXSLOT_OFFSET));	// clear int flag
//uint32_t start = GET_STC_CNT();
				if (5 == reCfgFlag)
				{
					reCfgFlag = 0;
				    //disable_mtimer_cevent_int(MTIMER_CPRI_ID, MTMR_CEVENT_CNT14H, MTMR_INT_10ms);	// 10ms int
				}
				pMtimerSfn->txSlotTiming = GET_STC_CNT();
				pMtimerSfn->txSlotNum++;
				__ucps2_synch(0);
				if (pMtimerSfn->txSlotNum == pMtimerSfn->slotMaxNum)
				{
					pMtimerSfn->txSfnNum++;
					pMtimerSfn->txSfnNum &= 0x3FF;
					pMtimerSfn->txSlotNum = 0;
				}
				// test for trigger
				if ((pMtimerSfn->slotMaxNum >> 1) == pMtimerSfn->txSlotNum)
				{
					set_trigger_state(GPIO_OFF);
				}
				//__ucps2_synch(0);
#if 0
				uint32_t readFlag = do_read_volatile(0x0A4D7248);
				__ucps2_synch(0);
				if ((1 == readFlag) && (pMtimerSfn->txSlotNum & 0x1))
				{
					// 0xB4800000, 0x1EF00
					ape_csu_dma_1D_G2L_ch0ch1_transfer(0xB4800000, 0x60000000, 0x1EF00, 0, 0);
					
					do_write(0x0A4D7248, 0);
				}
#endif

#ifdef PALLADIUM_TEST
				if (8 > pMtimerInt->txSlotIntCnt)
				{
					debug_write((DBG_DDR_IDX_DRV_BASE+576+(5<<3)+pMtimerInt->txSlotIntCnt), (GET_STC_CNT())); // -gRfm0LastTxTiming)); // 0x900
				}
#endif

				pMtimerInt->txSlotIntCnt++;
#ifdef PALLADIUM_TEST
				debug_write((DBG_DDR_IDX_DRV_BASE+80), pMtimerInt->txSlotIntCnt);	// 0x140
#endif

				do_write(SLOT_NUM_DEBUG_ADDR+((apeId<<2)<<2), pMtimerSfn->txSfnNum);
				do_write(SLOT_NUM_DEBUG_ADDR+((1+(apeId<<2))<<2), pMtimerSfn->txSlotNum);
				// write sm
				do_write(&(apeCoreIntInfo[APE_INT_TX_SLOT].intNum), APE_INT_TX_SLOT);
				do_write(&(apeCoreIntInfo[APE_INT_TX_SLOT].intCnt), pMtimerInt->txSlotIntCnt);

				__ucps2_synch(f_SMW);

#if 0 // def DISTRIBUTED_BS
#ifdef TEST_ENABLE
				fh_test_move_data();
#endif
#endif
//debug_write((DBG_DDR_IDX_DRV_BASE+290), (GET_STC_CNT()-start)); // 0x488
#if 0 // def PALLADIUM_TEST
				debug_write(((DBG_DDR_IDX_DRV_BASE+8192) + (gCpriTimerPara.txSlotIntCnt&0x1FF)), gCpriTimerPara.txSlotIntCnt);		// 0x8000
				debug_write(((DBG_DDR_IDX_DRV_BASE+8704) + (gCpriTimerPara.txSlotIntCnt&0x1FF)), get_tx_nr_slot(1)); 		// 0x8800
				nowTxSlotStcCnt = GET_STC_CNT();
				debug_write(((DBG_DDR_IDX_DRV_BASE+9216) + (gCpriTimerPara.txSlotIntCnt&0x1FF)), nowTxSlotStcCnt); 			// 0x9000
				debug_write(((DBG_DDR_IDX_DRV_BASE+9728) + (gCpriTimerPara.txSlotIntCnt&0x1FF)), (nowTxSlotStcCnt-lastTxSlotStcCnt)); 	// 0x9800
				lastTxSlotStcCnt = nowTxSlotStcCnt;
#endif
#if 0
				nowTxSlotCnt = GET_STC_CNT();
				if ((nowTxSlotCnt > lastTxSlotCnt) && (2 < pMtimerInt->txSlotIntCnt))
				{
					uint32_t cost = nowTxSlotCnt - lastTxSlotCnt;
					if ((505000 < cost) || (495000 > cost))
					{
						rfmSlotErrCnt++;
						debug_write((DBG_DDR_IDX_DRV_BASE+108), rfmSlotErrCnt);	// 0x1b0
						debug_write((DBG_DDR_IDX_DRV_BASE+109), cost);			// 0x1b4
					}
					if (cost > rfmSlotErrMax)
					{
						rfmSlotErrMax = cost;
					}
					debug_write((DBG_DDR_IDX_DRV_BASE+110), rfmSlotErrMax); // 0x1b8
				}
				lastTxSlotCnt = nowTxSlotCnt;
#endif
			}
			if (tEventFlag & (1<<MTMR_RXSLOT_OFFSET)) // rx slot offset
			{
				do_write((tmrBaseAddr+MTMR_TEVENT0_REG), (1<<MTMR_RXSLOT_OFFSET));
				do_write(tFlagAddr, (1<<MTMR_RXSLOT_OFFSET));	// clear int flag
//uint32_t start = GET_STC_CNT();
				pMtimerSfn->rxSlotNum++;
				__ucps2_synch(0);
				if (pMtimerSfn->rxSlotNum == pMtimerSfn->slotMaxNum)
				{
					pMtimerSfn->rxSfnNum++;
					pMtimerSfn->rxSfnNum &= 0x3FF;
					pMtimerSfn->rxSlotNum = 0;
				}
				//__ucps2_synch(0);

#ifdef PALLADIUM_TEST
				if (8 > pMtimerInt->rxSlotIntCnt)
				{
					debug_write((DBG_DDR_IDX_DRV_BASE+624+(5<<3)+pMtimerInt->rxSlotIntCnt), (GET_STC_CNT())); // -gRfm0LastTxTiming)); // 0x900
				}
#endif

				pMtimerInt->rxSlotIntCnt++;
#ifdef PALLADIUM_TEST
				debug_write((DBG_DDR_IDX_DRV_BASE+81), pMtimerInt->rxSlotIntCnt);	// 0x144
#endif

				do_write(SLOT_NUM_DEBUG_ADDR+((2+(apeId<<2))<<2), pMtimerSfn->rxSfnNum);
				do_write(SLOT_NUM_DEBUG_ADDR+((3+(apeId<<2))<<2), pMtimerSfn->rxSlotNum);
				// write sm
				do_write(&(apeCoreIntInfo[APE_INT_RX_SLOT].intNum), APE_INT_RX_SLOT);
				do_write(&(apeCoreIntInfo[APE_INT_RX_SLOT].intCnt), pMtimerInt->rxSlotIntCnt);
				__ucps2_synch(f_SMW);
//debug_write((DBG_DDR_IDX_DRV_BASE+291), (GET_STC_CNT()-start)); // 0x48c
			}
			if (tEventFlag & (1<<MTMR_LTE_FAPI))				// LTE FAPI
			{
				do_write((tmrBaseAddr+MTMR_TEVENT0_REG), (1<<MTMR_LTE_FAPI));
				do_write(tFlagAddr, (1<<MTMR_LTE_FAPI)); // clear int flag
				pMtimerInt->lteFapiIntCnt++;
#ifdef PALLADIUM_TEST
				debug_write((DBG_DDR_IDX_DRV_BASE+64+14), pMtimerInt->lteFapiIntCnt);	// 0x138
				debug_write((DBG_DDR_IDX_DRV_BASE+672+(pMtimerInt->lteFapiIntCnt&0x1f)), (GET_STC_CNT()-pMtimerSfn->txSlotTiming)); //get_tx_nr_slot(1)); // 0xb7e06a80
#endif
				rfm1_fapi_callback();
			}
			tEventFlag = do_read_volatile(tFlagAddr);
		}
		do_write((tmrBaseAddr+MTMR_INTC_REG), (1 << MTMR_INT_SLOT_OFFSET));			// clear int
	}
}

int32_t get_sfnoffset_int_flag()
{
	stMtimerIntStat* pMtimerInt = &gMtimerIntCnt[MTIMER_CPRI_ID];
	return pMtimerInt->sfnOffsetIntFlag;
}

void clear_sfnoffset_int_flag()
{
	stMtimerIntStat* pMtimerInt = &gMtimerIntCnt[MTIMER_CPRI_ID];
	pMtimerInt->sfnOffsetIntFlag = 0;
}
#if 0
void cpri_tdd_start_csu_timing()
{
#ifdef DISTRIBUTED_BS
#ifdef TEST_ENABLE
	cpri_test_case();
#endif
#endif
}
#endif
void cpri_tdd_start_csu_7ds2u()
{
	stMtimerIntStat* pMtimerInt = &gMtimerIntCnt[MTIMER_CPRI_ID];
#if 1
	if (CPRI_TEST_MODE == gCpriTestMode)
	{
		// start csu
#ifdef TEST_ENABLE
		fh_test_case();
#endif
		pMtimerInt->csuEnCnt++;
		debug_write((DBG_DDR_IDX_DRV_BASE+64+6), pMtimerInt->csuEnCnt); // 0x118
	}
	else
#endif
	{
		// start csu
		UCP_API_CPRI_CSU_START();
		pMtimerInt->csuEnCnt++;
		debug_write((DBG_DDR_IDX_DRV_BASE+64+6), pMtimerInt->csuEnCnt); // 0x118
	}
}

//#endif

