#include "rfm0_mtimer.h"
#include "typedef.h"
#include "phy_para.h"
#include "ucp_printf.h"
#include "ucp_utility.h"
#include "phy_para.h"
#include "ucp_mtimer.h"
#include "mtimer_com.h"

//#ifdef DISTRIBUTED_BS
#include "rfm0_cpri_timer.h"
#include "rfm0_ecpri_timer.h"
//#endif

#include "ecpri_irq.h"


stPhyCellPara* pPhyCellPara = (stPhyCellPara*)PHY_CELL_ADDR;
extern stPhyScsPara*	phyPara;
//extern uint32_t			gScsId;
//extern uint32_t			gMtimerId;
extern stSfnPara		gCellSfnPara[2];

int32_t rfm0_mtimer_int_init(void)
{
	set_cpri_timer_rfm0_int();
	set_ecpri_timer_rfm0_int();

	return 0;
}

int32_t gRfm0CalFlag = 0;
int32_t gRfm0CalCnt = 0;
int32_t ecs_rfm0_cal_sfn(uint8_t nTmrId)
{
	int32_t apeId = get_core_id();
	int32_t scsId = 0;
	int32_t i = 0;
	if (1 == gCellSfnPara[nTmrId].ctcIntFlag)
	{
		for (i = 0; i < PHY_SCS_MAX_NUM; i++)
		{
			if (nTmrId == do_read_volatile_short(&(phyPara[i].mtimerId))) // 已建了第一个子载波小区
			{
				gCellSfnPara[nTmrId].scsId = i;
				scsId = i;
				break;
			}
		}
		if (PHY_SCS_MAX_NUM == i)
		{
			return -1;
		}
		
		gCellSfnPara[nTmrId].ctcIntFlag = 0;

		gCellSfnPara[nTmrId].slotPeriod = do_read_volatile_short(&(phyPara[scsId].slotPeriod)); 	// 500; // 
		gCellSfnPara[nTmrId].tddSlotNum = do_read_volatile_short(&(phyPara[scsId].slotNumOfTdd));	// 10;	// 
		gCellSfnPara[nTmrId].slotMaxNum = do_read_volatile_short(&(phyPara[scsId].slotNumOfSfn));	// 20;	// 

		gCellSfnPara[nTmrId].txSfnNum = do_read_volatile(&(phyPara[scsId].txSfnNum));
		gCellSfnPara[nTmrId].rxSfnNum = do_read_volatile(&(phyPara[scsId].rxSfnNum));
		gCellSfnPara[nTmrId].txSlotNum = do_read_volatile(&(phyPara[scsId].txSlotNum));
		gCellSfnPara[nTmrId].rxSlotNum = do_read_volatile(&(phyPara[scsId].rxSlotNum));

		gCellSfnPara[nTmrId].txSymbolNum = 0;
		
		gCellSfnPara[nTmrId].txSymbolIntCnt = 0;
		gCellSfnPara[nTmrId].txSlotIntCnt = 0;
		gCellSfnPara[nTmrId].rxSlotIntCnt = 0;

		gRfm0CalFlag = 1;
		gRfm0CalCnt++;
		
#ifdef PALLADIUM_TEST
		debug_write((DBG_DDR_IDX_DRV_BASE+544+apeId), gRfm0CalCnt);	// 0x880
		debug_write((DBG_DDR_IDX_DRV_BASE+556+apeId), GET_STC_CNT());	// 0x8b0
#endif
	}
	return 0;
}

uint32_t lastTxStcCnt = 0;
uint32_t nowTxStcCnt = 0;
uint32_t rfm0SymbolErrCnt = 0;
uint32_t rfm0SymbolInterMax = 0;
int32_t mtimer_rfm0_symbol_callback(uint8_t nTmrId)
{
	uint32_t tmrBaseAddr = 0;

	if (MTIMER_CPRI_ID == nTmrId)
	{
		tmrBaseAddr = CPRI_TMR_BASE;
	}
	else if (MTIMER_ECPRI_ID == nTmrId)
	{
		tmrBaseAddr = ECPRI_TMR_BASE;
	}
	else
	{
		return -1;
	}

	uint32_t tmrIntcFlag = 0;
	uint32_t tEventFlag = 0;
	uint32_t tEventAddr = 0;
	uint32_t tFlagAddr = 0;
	stSfnPara* pSfnPara = &gCellSfnPara[nTmrId];
	int32_t apeId = get_core_id();

	tmrIntcFlag = do_read_volatile(tmrBaseAddr + MTMR_INTC_REG);
	if ((tmrIntcFlag & (1 << MTMR_INT_RFM0_SLOT)))	/* symbol int */
	{
		tFlagAddr = tmrBaseAddr + MTMR_TINTF00_REG + 6*(MTMR_INT_RFM0_SLOT<<2) + 2*((MTMR_ECPRI_TX_SYMBOL0>>5)<<2); // MTMR_TINTF01_REG
		tEventAddr = tmrBaseAddr+MTMR_TEVENT0_REG + ((MTMR_ECPRI_TX_SYMBOL0>>5)<<2);
		tEventFlag = do_read_volatile(tFlagAddr);
		if (tEventFlag & 0x3FFF) // 14symbols // tx symbol offset int
		{
			do_write(tEventAddr, tEventFlag);
			do_write(tFlagAddr, tEventFlag);	// clear int flag
			pSfnPara->txSymbolIntCnt++;
			//uint32_t addr = 0;
#ifdef PALLADIUM_TEST
			debug_write((DBG_DDR_IDX_DRV_BASE+2048+32+nTmrId), pSfnPara->txSymbolIntCnt); // 0xb7e08080
#endif
			ecs_rfm0_cal_sfn(nTmrId);

            if (PROTOCOL_ECPRI == get_protocol_sel())
            {
                /* eCPRI symbol interrupt handle */
                (void)ecpri_sym_irq_handle(pSfnPara->txSlotNum, pSfnPara->txSymbolNum);
            }

			pSfnPara->txSymbolNum++;
			__ucps2_synch(0);
			if (pSfnPara->txSymbolNum == SLOT_SYMBOL_NUM)
			{
				pSfnPara->txSlotNum++;
				if (pSfnPara->txSlotNum == pSfnPara->slotMaxNum)
				{
					pSfnPara->txSfnNum++;
					pSfnPara->txSfnNum &= 0x3FF;
					pSfnPara->txSlotNum = 0;
				}
				pSfnPara->txSymbolNum = 0;
			}
			__ucps2_synch(0);
			
			if (MTIMER_CPRI_ID == nTmrId)
			{
				do_write(SLOT_NUM_DEBUG_ADDR+(((apeId-1)<<2)<<2), pSfnPara->txSymbolNum);
				do_write(SLOT_NUM_DEBUG_ADDR+((apeId<<2)<<2), pSfnPara->txSfnNum);
				do_write(SLOT_NUM_DEBUG_ADDR+((1+(apeId<<2))<<2), pSfnPara->txSlotNum);
				do_write(SLOT_NUM_DEBUG_ADDR+((2+(apeId<<2))<<2), pSfnPara->rxSfnNum);
				do_write(SLOT_NUM_DEBUG_ADDR+((3+(apeId<<2))<<2), pSfnPara->rxSlotNum);
			}
#if 1
			nowTxStcCnt = GET_STC_CNT();
			debug_write(((DBG_DDR_IDX_DRV_BASE+2048+128) + (gCellSfnPara[nTmrId].txSymbolIntCnt&0x3F)), nowTxStcCnt);		// 0xb7e08200
			//debug_write(((DBG_DDR_IDX_DRV_BASE+2048+192) + (gCellSfnPara[nTmrId].txSymbolIntCnt&0x3F)), get_tx_nr_slot(NR_SCS_30K)); 	// 0x800
			if ((nowTxStcCnt > lastTxStcCnt) && (2 < gCellSfnPara[nTmrId].txSlotIntCnt))
			{
				uint32_t cost = nowTxStcCnt - lastTxStcCnt;
				//debug_write(((DBG_DDR_IDX_DRV_BASE+576) + (gCellSfnPara[nTmrId].txSlotIntCnt&0x3F)), nowTxStcCnt);					// 0x900
				//debug_write(((DBG_DDR_IDX_DRV_BASE+640) + (gCellSfnPara[nTmrId].txSlotIntCnt&0x3F)), cost);	// 0xa00
				if (((gCellSfnPara[nTmrId].slotPeriod*1000+5000) < cost) || ((gCellSfnPara[nTmrId].slotPeriod*1000-5000) > cost))
				{
					rfm0SymbolErrCnt++;
					debug_write((DBG_DDR_IDX_DRV_BASE+2048+64+(nTmrId<<2)), rfm0SymbolErrCnt);	// 0xb7e08100
				}
				if (rfm0SymbolInterMax < cost)
				{
					rfm0SymbolInterMax = cost;
					debug_write((DBG_DDR_IDX_DRV_BASE+2048+65+(nTmrId<<2)), rfm0SymbolInterMax); // 0xb7e08104
				}
			}
			lastTxStcCnt = nowTxStcCnt;
#endif
			
			tEventFlag = do_read_volatile(tFlagAddr);
		}
		do_write((tmrBaseAddr+MTMR_INTC_REG), (1 << MTMR_INT_RFM0_SLOT));		// clear int
	}

	return 0;
}

