#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"
#ifdef DISTRIBUTED_BS
#include "ucp_cpri.h"
#include "HeaderRam.h"
#include "cpri_timer.h"

extern stCpriIntStat		gCpriIntStatus;
#endif
#ifdef INTEGRATED_BS
#include "jesd_timer.h"
#endif

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

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];
	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);
#ifdef DISTRIBUTED_BS
	gCpriIntStatus.cpriSyncFlag = 0;
	stop_cpri_timer();
	//set_cpri_tx_rfp();
	set_cpri_tmr_ctrl();
	start_cpri_timer();
	stCpriDelayMeasure* pCpriDelay = pEcsDmLocalMgt->pCpriDelay;
	n10msOffset = pCpriDelay->cpri10msOffset;
#endif
#ifdef INTEGRATED_BS
	stop_jesd_timer(MTIMER_JESD_RX0_ID);
	stop_jesd_timer(MTIMER_JESD_TX0_ID);
	start_jesd_timer(MTIMER_JESD_RX0_ID);
	start_jesd_timer(MTIMER_JESD_TX0_ID);
#endif
	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];
	//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, CTC_INT_TYPE_CAL);
		for (int32_t i = 0; i < APE_NUM; i++)
		{
			set_ctc_cal_int(i);
		}
		//set_ctc_cal_int(10);	// sfn calibration for ecs rfm0
		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];
	
	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;

	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;
}

