#include "ucp_param.h"
#include "ucp_csu.h"
#include "ucp_js_ctrl.h"
#include "ucp_mtimer.h"
#include "mtimer_com.h"
#include "ucp_utility.h"
#include "ucp_printf.h"
#include "phy_para.h"
#include "ctc_intr.h"
#include "inter_vector.h"
#include "dw_apb_gpio.h"
#include "ecs_rfm_dm_mgt.h"
#include "mtimer_drv.h"
#include "gtimer_drv.h"
#include "ucp_handshake.h"
#include "ucp_cpri.h"
#include "HeaderRam.h"
#include "cpri_timer.h"
#include "ecpri_timer.h"
#include "jesd_timer.h"
#include "jesd_orx_timer.h"
#include "jesd_csu.h"

extern stCpriIntStat		gCpriIntStatus;

extern stMtimerIntStat 		gMtimerIntCnt[SCS_MAX_NUM];
extern stMtimerPhyPara 		gMtimerSfnNum[SCS_MAX_NUM];
extern stMtimerSfnCal 		gMtimerSfnCalPara[SCS_MAX_NUM];
extern stPhyScsPara*		phyPara;

void mtimer_1pps_resync(uint8_t nTmrId)
{
    EcsRfmDmLocalMgt_t* pEcsDmLocalMgt = get_ecs_rfm_dm_local_mgt();
	stMtimerPara* pMtimerPara = pEcsDmLocalMgt->pMtimerPara[nTmrId];
	stMtimerSfnCal* pSfnCal = &gMtimerSfnCalPara[nTmrId];
	stMtimerIntStat* pMtimerInt = &gMtimerIntCnt[nTmrId];
	uint8_t nBsType = get_protocol_sel();
	uint32_t n10msOffset = 0;
	
	debug_write((DBG_DDR_IDX_DRV_BASE+905), GET_STC_CNT()); // 0xe24
	pSfnCal->sfnCalFinished = 0;
	pMtimerInt->csuEnCnt = 0;
	do_write(CSU_STOP_CMD_ADDR, 1);

	gtimer2_stop(0);
	if (PROTOCOL_JESD == nBsType)
	{
		stop_jesd_timer(nTmrId);
		//stop_jesd_timer(nTmrId+1);
		stop_jesd_timer(nTmrId+2);
		stop_jesd_timer(nTmrId+3);
		__ucps2_synch(0);
		start_jesd_timer(nTmrId);
		//start_jesd_timer(nTmrId+1);
		start_jesd_timer(nTmrId+2);
		start_jesd_timer(nTmrId+3);
	}
    else // if (DISTRIBUTED_BS == nBsType)
	{
		gCpriIntStatus.cpriSyncFlag = 0;
		stop_cpri_timer();
		stop_ecpri_timer();
		set_cpri_tmr_ctrl();
		__ucps2_synch(0);
		start_cpri_timer();
		start_ecpri_timer();
		stCpriDelayMeasure* pCpriDelay = pEcsDmLocalMgt->pCpriDelay;
		n10msOffset = pCpriDelay->cpri10msOffset;
	}
	gtimer2_start(0);
	
	uint32_t addr = (uint32_t)&(phyPara[pMtimerPara->scsId].gpsOffset);
	uint16_t gpsOffset = do_read_volatile_short(addr);
	pSfnCal->sfnCalBeta = 0;
	pSfnCal->sfnCalAlpha = (float)(n10msOffset+gpsOffset) * 1228.8; // advance * 1.2288*(10^3)
}

void mtimer_1pps_sfn_cal(uint8_t nTmrId)
{
    EcsRfmDmLocalMgt_t* pEcsDmLocalMgt = get_ecs_rfm_dm_local_mgt();
	stFhAlarmStat* pAlarmStatus = pEcsDmLocalMgt->pAlarmStatus;
	stMtimerPara* pMtimerPara = pEcsDmLocalMgt->pMtimerPara[nTmrId];
	stMtimerSfnCal* pSfnCal = &gMtimerSfnCalPara[nTmrId];
	stMtimerPhyPara* pMtimerSfn = &gMtimerSfnNum[nTmrId];
	uint8_t nBsType = get_protocol_sel(); 
	//stMtimerIntStat* pMtimerInt = &gMtimerIntCnt[nTmrId];
	
	pSfnCal->sfnCalCnt = do_read_volatile(ARM_SFN_NUM_ADDR);
	__ucps2_synch(f_SMR);
	
	debug_write((DBG_DDR_IDX_DRV_BASE+962), pMtimerPara->slotMaxNum);	// 0xf08
	uint32_t sfnCalNum = (uint32_t)((float)pSfnCal->sfnCalCnt - (pSfnCal->sfnCalAlpha/(float)(12288000))); // 空口的帧号
	
	if (pMtimerSfn->txSfnNum != sfnCalNum)	// pp1s发生了跳变
	{
#ifdef PALLADIUM_TEST
		debug_write((DBG_DDR_IDX_DRV_BASE+960), pSfnCal->sfnCalCnt);	// 0xf00
		debug_write((DBG_DDR_IDX_DRV_BASE+961), sfnCalNum);				// 0xf04
		debug_write((DBG_DDR_IDX_DRV_BASE+964), pMtimerSfn->txSfnNum);	// 0xf10
		debug_write((DBG_DDR_IDX_DRV_BASE+965), pMtimerSfn->rxSfnNum);	// 0xf14
		debug_write((DBG_DDR_IDX_DRV_BASE+966), pMtimerSfn->txSlotNum);	// 0xf18
		debug_write((DBG_DDR_IDX_DRV_BASE+967), pMtimerSfn->rxSlotNum);	// 0xf1c
		debug_write((DBG_DDR_IDX_DRV_BASE+524+11), GET_STC_CNT()); 			// 0x830+11*4, 11:apeId
#endif		
		pMtimerSfn->txSfnNum = sfnCalNum;
		//gCpriTimerPara.txSfnNum = gCpriTimerPara.sfnCalCnt; // + 1; //gSfnCalCnt;
		pMtimerSfn->rxSfnNum = pMtimerSfn->txSfnNum; //gSfnCalCnt-1;
		pMtimerSfn->txSlotNum = pMtimerSfn->slotNumPP1s; // 0;
		pMtimerSfn->rxSlotNum = pMtimerSfn->slotNumPP1s; // 0; //gCpriTimerPara.slotMaxNum - 1;

		//pMtimerInt->txSlotIntCnt = 0;
		//pMtimerInt->rxSlotIntCnt = 0;

		int32_t nScsId = pMtimerPara->scsId;
		uint32_t 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);

		__ucps2_synch(f_SMW);
		pMtimerSfn->rxSfnNum = pSfnCal->sfnCalCnt-1;
		pMtimerSfn->rxSlotNum = pMtimerSfn->slotMaxNum - 1;

		do_write(CTC_INT_TYPE_ADDR, (nTmrId+1));
		if (PROTOCOL_ECPRI == nBsType)
		{
			// ecs rfm0 cal
			set_ctc_cal_int(ECS_RFM_SPU0_CORE_ID);	// sfn calibration for ecs rfm0
		}

		for (int32_t i = 0; i < APE_NUM; i++)
		{
			set_ctc_cal_int(i);
		}
		pAlarmStatus->alarmFlag = ALARM_SFN_CAL;
		pAlarmStatus->alarmSfnCalCnt++;
	}
	if (1 != (pMtimerSfn->txSfnNum - pMtimerSfn->rxSfnNum))
	{
		pAlarmStatus->alarmFlag = ALARM_SFN_CAL;
		pAlarmStatus->alarmSfnCalCnt++;
	}
	if ((0 != pMtimerSfn->txSlotNum) || (pMtimerSfn->slotMaxNum != pMtimerSfn->rxSlotNum))
	{
		pAlarmStatus->alarmFlag = ALARM_SLOT_CNT;
		pAlarmStatus->alarmSfnCalCnt++;
	}
}

int32_t gPP1sLockCnt = 0;
int32_t mtimer_1pps_func(uint8_t nTmrId)
{
	stMtimerSfnCal* pMtimerCal = &gMtimerSfnCalPara[nTmrId];
	//stMtimerIntStat* pMtimerInt = &gMtimerIntCnt[nTmrId];

	// gps unlock -> lock, adjust pp1s	
	pMtimerCal->pp1sLockFlag = do_read_volatile(ARM_LOCK_FLAG_ADDR);
	__ucps2_synch(f_SMR);
	if ((0 == pMtimerCal->pp1sLockFlagPre) && (1 == pMtimerCal->pp1sLockFlag))	// pp1s刚锁定
	{
#ifdef PALLADIUM_TEST
		debug_write((DBG_DDR_IDX_DRV_BASE+968), GET_STC_CNT()); // 0xf20
#endif
		mtimer_1pps_resync(nTmrId);
		gPP1sLockCnt++;
#ifdef PALLADIUM_TEST
		debug_write((DBG_DDR_IDX_DRV_BASE+963), gPP1sLockCnt);	// 0xf0c
		//debug_write((DBG_DDR_IDX_DRV_BASE+393), GET_STC_CNT()); // 0x624
#endif
	}
	pMtimerCal->pp1sLockFlagPre = pMtimerCal->pp1sLockFlag;

	// sfn num calibration
	pMtimerCal->sfnValidFlag = do_read_volatile(ARM_SFN_VALID_ADDR);
	pMtimerCal->sfnFlipFlag = do_read_volatile(ARM_SFN_FLIP_ADDR);
	__ucps2_synch(f_SMR);
	if (/*(0 < pMtimerInt->txSlotIntCnt) && */(ARM_SFN_VALID_FLAG == pMtimerCal->sfnValidFlag) && (pMtimerCal->sfnFlipFlag != pMtimerCal->sfnFlipFlagPre))
	{
		do_write(ARM_SFN_VALID_ADDR, ARM_SFN_NOTVALID_FLAG);
		__ucps2_synch(f_SMW);
		mtimer_1pps_sfn_cal(nTmrId);
		
		debug_write((DBG_DDR_IDX_DRV_BASE+906), GET_STC_CNT()); // 0xe28
		pMtimerCal->sfnCalFinished = 1;
	}
	pMtimerCal->sfnFlipFlagPre = pMtimerCal->sfnFlipFlag;
	
	return 0;
}

int32_t mtimer_orx_adjust(void)
{
    EcsRfmDmLocalMgt_t* pEcsDmLocalMgt = get_ecs_rfm_dm_local_mgt();
	JesdOrxPara_t* orx_para_ptr = pEcsDmLocalMgt->jesd_orx_para_ptr;

	if (1 == orx_para_ptr->orx_start_flag)
	{
		debug_write((DBG_DDR_IDX_DRV_BASE+60), GET_STC_CNT()); // 0xF0
		if (0 == orx_para_ptr->orx_start_offset_us)
		{
		    jesd_csu_orx_start(0);
		}
		else
		{
  		    start_jesd_orx_timer();
		}
		orx_para_ptr->orx_start_flag = 0;
	}
#if 0
	if (0 < orx_para_ptr->orx_calldrv_cnt)
	{
		orx_para_ptr->orx_adjust_flag = do_read_volatile(ORX_ADJUST_FLAG_ADDR);
		__ucps2_synch(f_SMR);
		if (1 == orx_para_ptr->orx_adjust_flag)
		{
			orx_para_ptr->orx_adjust_val_lo = do_read_volatile(ORX_ADJUST_VAL_ADDR);
			orx_para_ptr->orx_adjust_val_hi = do_read_volatile(ORX_ADJUST_VAL_ADDR+4);
			__ucps2_synch(f_SMR);
			// adjust stc phase offset
			do_write((uint32_t)(&TOD_REG_NSF_INIT_LO), orx_para_ptr->orx_adjust_val_lo);
			do_write((uint32_t)(&TOD_REG_NSF_INIT_HI), orx_para_ptr->orx_adjust_val_hi);
			
			orx_para_ptr->orx_adjust_flag = 0;
			orx_para_ptr->pp1s_adjust_flag = 1;

			do_write(ORX_ADJUST_FLAG_ADDR, 0);
		}
	}
#endif	
	return 0;
}

