// +FHDR------------------------------------------------------------
//                 Copyright (c) 2022 SmartLogic.
//                       ALL RIGHTS RESERVED
// -----------------------------------------------------------------
// Filename      : cpri_test_case39.c
// Author        : xinxin.li
// Created On    : 2023-05-06s
// Last Modified :
// -----------------------------------------------------------------
// Description:
//
//
// -FHDR------------------------------------------------------------

#include "typedef.h"
#include "ucp_utility.h"
#include "cpri_csu_nr_7ds2u.h"
#include "cpri_test_case39.h"
#include "cpri_timer.h"
#include "ape_csu.h"
#include "cpri_test.h"
#include "ucp_printf.h"
#include "HeaderRam.h"
#include "cpri_driver.h"
#include "phy_para.h"
#include "hw_cpri.h"

extern uint32_t compressData[1920];
extern uint32_t antData0[61440];
extern uint32_t antData1[61440];
extern uint32_t antData2[61440];
extern uint32_t antData3[61440];

extern uint32_t 		gCpriTestMode;
//extern stCpriTimerPara	gCpriTimerPara;
extern stMtimerIntStat 		gMtimerIntCnt[SCS_MAX_NUM];

extern uint32_t gCpriTestMode;
//extern uint32_t           CPRI_OPTION;
extern uint32_t			gCpriCsuDummyFlag;
extern volatile uint32_t gVendorFlag;

#define HeaderTestCnt   10

int32_t fh_data_init(void)
{
	gCpriTestMode = CPRI_TEST_MODE;
	gCpriCsuDummyFlag = 0;
	debug_write((DBG_DDR_IDX_DRV_BASE+192), gCpriTestMode); // 0x300

	//Get_Cpri_OptionId();//get cpri option value
	//debug_write((DBG_DDR_IDX_DRV_BASE+193), CPRI_OPTION); // 0x304
		
	Axc_data_init();//init axc data
	UCP_PRINT_LOG("Axc data init.\r\n");
	HeaderTxRam_data_init();
	//HeaderTxRam_init();
	return 0;
}

int32_t fh_drv_init(void)
{
	cpri_init(CPRI_OPTION_8, OTIC_MAP_FIGURE12);

	return 0;
}

int32_t fh_csu_test_init(void)
{
	stCpriCsuCmdFifoInfo		txTestCmdFifo;
	stCpriCsuCmdFifoInfo		rxTestCmdFifo;
	
	cpri_csu_axc_init_nr_7ds2u(CPRI_DUMMY_USE_DDR_ADDR, &txTestCmdFifo, &rxTestCmdFifo);
	cpri_csu_axcctrl_init_timing();
	UCP_API_CPRI_CSU_Get_CmdFIFO(&txTestCmdFifo, &rxTestCmdFifo);

	return 0;
}

void fh_test_case()
{
	UCP_API_CPRI_CSU_START();
}


void HeaderTxRam_data_init()
{
#if 0
	for(int i=0;i<16*HeaderTestCnt;i++)//NS=3,each BF only bit[127:0]
	{
		do_write(((uint32_t *)HeaderTxDataAddr0 +i),0x12345678+i);
	}
#endif
	for(int i=0;i<48*2;i++)//NS=8~19,each BF only bit[31:0]
	{
		do_write(((uint32_t *)HeaderTxDataAddr0 +i),0x12345678+i);
	}
#if 0
	for(int i=0;i<16*HeaderTestCnt;i++)
	{
		do_write(((uint32_t *)HeaderTxDataAddr1 +i),0x87654321+i);
	}
#endif
}

void Axc_data_init()
{
	uint8_t idID = 0;
	uint8_t idSlot = 0;			// even slot, odd slot
	uint8_t idSymbolBlock = 0;	// symbol0~6, symbol7~13
	uint32_t  srcAddr = 0;
	uint32_t  dstAddr = 0;
	uint32_t  dataLen = 0;
	uint16_t  bfByteCnt = 0;
	uint32_t  slotBfCnt = LONGCP_BF_CNT+SHORTCP_BF_CNT*13;
	uint32_t  f7BfCnt = LONGCP_BF_CNT+SHORTCP_BF_CNT*6;
	uint32_t  b7BfCnt = SHORTCP_BF_CNT*7;

	uint32_t cpyCnt = 0;
	// valid data
	// compress factor
	for (idSlot = 0; idSlot <= 1; idSlot++)
	{
		bfByteCnt = 2;
		
		if (0 == idSlot)	// even slot
		{
			srcAddr = (uint32_t)(&compressData[0]);
			dstAddr = CPRI_NR7DS2U_TX_SLOT_EVEN_COMPRESS_ADDR;
		}
		else				// odd slot
		{
			srcAddr = (uint32_t)(&compressData[1920>>1]);
			dstAddr = CPRI_NR7DS2U_TX_SLOT_ODD_COMPRESS_ADDR;
		}
		dataLen = (bfByteCnt*slotBfCnt); 
		debug_write((DBG_DDR_IDX_DRV_BASE+196+(cpyCnt<<2)), (uint32_t)srcAddr); // 0x310
		debug_write((DBG_DDR_IDX_DRV_BASE+196+((cpyCnt<<2)+1)), (uint32_t)dstAddr);
		debug_write((DBG_DDR_IDX_DRV_BASE+196+((cpyCnt<<2)+2)), (uint32_t)dataLen);
		cpyCnt++;
		memcpy_ucp((void*)dstAddr,(void*)srcAddr, dataLen);
	}

	// IQ data	
	for (idID = 1; idID < 5; idID++)
//	for (idID = 1; idID < 2; idID++)
	{
		bfByteCnt = 64;
		for (idSlot = 0; idSlot <= 1; idSlot++)
		{
			for (idSymbolBlock = 0; idSymbolBlock <= 1; idSymbolBlock++)
			{
				if ((0 == idSlot) && (0 == idSymbolBlock))	// even slot, symbol0~6
				{
					dataLen = bfByteCnt * f7BfCnt;
					switch(idID)
					{
						case 1:
							srcAddr = (uint32_t)(&antData0[0]);break;
						case 2:
							srcAddr = (uint32_t)(&antData1[0]);break;	
						case 3:
							srcAddr = (uint32_t)(&antData2[0]);break;
						case 4:
							srcAddr = (uint32_t)(&antData3[0]);break;
					}
					//srcAddr = (uint32_t)(&antData[0]);	
					dstAddr = CPRI_NR7DS2U_TX_SLOT_EVEN_F7SYMBOL_ADDR + (idID-1)*dataLen;
				}
				else if ((0 == idSlot) && (1 == idSymbolBlock))	// even slot, symbol7~13
				{
					dataLen = bfByteCnt * b7BfCnt;
					switch(idID)
					{
						case 1:
							srcAddr = (uint32_t)(&antData0[15376]);break;
						case 2:
							srcAddr = (uint32_t)(&antData1[15376]);break;	
						case 3:
							srcAddr = (uint32_t)(&antData2[15376]);break;
						case 4:
							srcAddr = (uint32_t)(&antData3[15376]);break;
					}
					//srcAddr = (uint32_t)(&antData[15376]);
					dstAddr = CPRI_NR7DS2U_TX_SLOT_EVEN_B7SYMBOL_ADDR + (idID-1)*dataLen;
				}
				else if ((1 == idSlot) && (0 == idSymbolBlock))	// odd slot, symbol0~6
				{
					dataLen = bfByteCnt * f7BfCnt;
					switch(idID)
					{
						case 1:
							srcAddr = (uint32_t)(&antData0[30720]);break;
						case 2:
							srcAddr = (uint32_t)(&antData1[30720]);break;	
						case 3:
							srcAddr = (uint32_t)(&antData2[30720]);break;
						case 4:
							srcAddr = (uint32_t)(&antData3[30720]);break;
					}
					//srcAddr = (uint32_t)(&antData[30720]);
					dstAddr = CPRI_NR7DS2U_TX_SLOT_ODD_F7SYMBOL_ADDR + (idID-1)*dataLen;
				}
				else if ((1 == idSlot) && (1 == idSymbolBlock))	// odd slot, symbol7~13
				{
					dataLen = bfByteCnt * b7BfCnt;
					switch(idID)
					{
						case 1:
							srcAddr = (uint32_t)(&antData0[30720+15376]);break;
						case 2:
							srcAddr = (uint32_t)(&antData1[30720+15376]);break;	
						case 3:
							srcAddr = (uint32_t)(&antData2[30720+15376]);break;
						case 4:
							srcAddr = (uint32_t)(&antData3[30720+15376]);break;
					}
					//srcAddr = (uint32_t)(&antData[30720+15376]);
					dstAddr = CPRI_NR7DS2U_TX_SLOT_ODD_B7SYMBOL_ADDR + (idID-1)*dataLen;
				}
				
				debug_write((DBG_DDR_IDX_DRV_BASE+196+(cpyCnt<<2)), (uint32_t)srcAddr); // 0x310
				debug_write((DBG_DDR_IDX_DRV_BASE+196+((cpyCnt<<2)+1)), (uint32_t)dstAddr);
				debug_write((DBG_DDR_IDX_DRV_BASE+196+((cpyCnt<<2)+2)), (uint32_t)dataLen);
				cpyCnt++;
				memcpy_ucp((void*)dstAddr,(void*)srcAddr, dataLen);
			}
		}
	}
}


uint32_t gCompWordCnt = 0;
uint32_t gErrSlotIdCnt = 0;
uint32_t gCompSlotIdCnt = 0;
void cpri_check_slot_data(uint32_t slotNum)
{
	uint32_t slotId = 0;
	uint32_t srcAddr = 0;
	uint32_t dstAddr = 0;
	uint32_t dataLen = 0;
	uint8_t bitOffset = 0;
	uint32_t totalSlotBfCnt = LONGCP_BF_CNT+SHORTCP_BF_CNT*13;
	uint32_t  slotBfCnt = LONGCP_BF_CNT+SHORTCP_BF_CNT*13;
	uint8_t	bfWordCnt = 0;

	uint8_t slotVal = 0;
	uint8_t idVal = 0;
	uint32_t bfStart = 0;

	uint32_t compVal = 0;
	uint32_t recvVal = 0;
	uint32_t recvAddr = 0;
	uint32_t *pAntData = antData0;
	for (uint32_t i = 0; i < 5; i++)
	{
		gCompSlotIdCnt++;
		slotId = slotNum;	// get_tx_nr_slot(NR_SCS_30K);
		idVal = i;
		bfStart = 0;

		switch(i)
		{
			case 1:
				pAntData = antData0;break;
			case 2:
				pAntData = antData1;break;	
			case 3:
				pAntData = antData2;break;
			case 4:
				pAntData = antData3;break;
		}

		
		if ((slotId >=0) && (slotId <= 6))
		{
			slotBfCnt = LONGCP_BF_CNT+SHORTCP_BF_CNT*13;
			slotVal = slotId & 0x1;
			
			if (0 == i)
			{
				bitOffset = 1;	// one BF, 2B
				bfWordCnt = 1;
				srcAddr = CPRI_NR7DS2U_RX_DUMMY_COMPRESS_ADDR+slotId*(totalSlotBfCnt<<bitOffset); //CPRI_CASE33_RX_SLOT_EVEN_COMPRESS_ADDR;
			}
			else
			{
				bitOffset = 6;	// one BF, 64B
				bfWordCnt = 64>>2;
				srcAddr = CPRI_NR7DS2U_RX_DUMMY_AXC1DATA_ADDR+((i-1)*CPRI_NR7DS2U_RX_DUMMY_AXCDATA_LEN)+slotId*(totalSlotBfCnt<<bitOffset); //CPRI_CASE33_RX_SLOT_EVEN_AXCDATA_ADDR + ((i-1)<<bitOffset);
			}
			dataLen = slotBfCnt << bitOffset;
		}
		else if (7 == slotId)		// compare S slot, odd slot
		{
			bfStart = 0;
			slotBfCnt = LONGCP_BF_CNT + 5 * SHORTCP_BF_CNT;
			slotVal = 1;
			if (0 == i)
			{
				bitOffset = 1;	// one BF, 2B
				bfWordCnt = 1;
				srcAddr = CPRI_NR7DS2U_RX_DUMMY_COMPRESS_ADDR+slotId*(totalSlotBfCnt<<bitOffset);
			}
			else
			{
				bitOffset = 6;	// one BF, 64B
				bfWordCnt = (64>>2);
				srcAddr = CPRI_NR7DS2U_RX_DUMMY_AXC1DATA_ADDR+((i-1)*CPRI_NR7DS2U_RX_DUMMY_AXCDATA_LEN)+slotId*(totalSlotBfCnt<<bitOffset);
			}
			dataLen = slotBfCnt << bitOffset;
		}

		if (0 == i)	// compress factor
		{
			for (uint32_t idBf = 0; idBf < (slotBfCnt>>1); idBf++)
			{
				for (uint32_t idWord = 0; idWord < bfWordCnt; idWord++)
				{
					if (7 == slotId)
					{
						dstAddr = 960 + idBf*bfWordCnt + idWord;
					}
					else
					{
						dstAddr = slotVal*(1920>>1) + idBf*bfWordCnt + idWord;
					}
					recvAddr = (uint32_t)((uint32_t*)srcAddr + idBf*bfWordCnt + idWord);
					recvVal = *((uint32_t*)recvAddr);
					compVal = compressData[dstAddr];
					if ((recvVal != compVal) || (recvVal != compVal))
					{
//						debug_write((DBG_DDR_IDX_DRV_BASE+200+((gErrSlotIdCnt<<2)&0x3F)), dstAddr);		// 0x320
//						debug_write((DBG_DDR_IDX_DRV_BASE+201+((gErrSlotIdCnt<<2)&0x3F)), recvAddr);		// 0x324
//						debug_write((DBG_DDR_IDX_DRV_BASE+202+((gErrSlotIdCnt<<2)&0x3F)), (slotId+(i<<4)+(idBf<<8)));		// 0x328
//						debug_write((DBG_DDR_IDX_DRV_BASE+203+((gErrSlotIdCnt<<2)&0x3F)), recvVal);		// 0x32c
//						gErrSlotIdCnt++;
//						break;
//						break;
					}
			//		do_write(a, gCompSlotIdCnt); // addr 
			//		do_write(a, gErrSlotIdCnt);
				}
			}
		}
		else		// axc data
		{
			for (uint32_t idBf = 0; idBf < slotBfCnt; idBf++)
			{
				for (uint32_t idWord = 0; idWord < bfWordCnt; idWord++)
				{
					if (7 == slotId)
					{
						dstAddr = 30720 +idBf*bfWordCnt + idWord;
					}
					else
					{
						dstAddr = slotVal*30720 + idBf*bfWordCnt + idWord;
					}
//					recvAddr = (uint32_t)((uint32_t*)srcAddr + idBf*bfWordCnt + idWord);
					recvAddr = (uint32_t)((uint32_t*)srcAddr + idBf*bfWordCnt + idWord + 0x10);
					//recvVal = *((uint32_t*)recvAddr);
					recvVal = do_read_volatile(recvAddr);
					//compVal = pAntData[dstAddr];
					compVal = do_read_volatile(pAntData+dstAddr);

					
					if (recvVal != compVal)
					{
						//debug_write((DBG_DDR_IDX_DRV_BASE+200+((gErrSlotIdCnt<<2)&0x3F)), dstAddr);		// 0x320
						//debug_write((DBG_DDR_IDX_DRV_BASE+201+((gErrSlotIdCnt<<2)&0x3F)), recvAddr);		// 0x324
						//debug_write((DBG_DDR_IDX_DRV_BASE+202+((gErrSlotIdCnt<<2)&0x3F)), (slotId+(i<<4)+(idBf<<8)));		// 0x328
						//debug_write((DBG_DDR_IDX_DRV_BASE+203+((gErrSlotIdCnt<<2)&0x3F)), recvVal);		// 0x32c

						if (gErrSlotIdCnt < 0x100)
						{
							debug_write((DBG_DDR_IDX_DRV_BASE+1028+((gErrSlotIdCnt<<3)&0x7FF)), compVal);		// 0x320
							debug_write((DBG_DDR_IDX_DRV_BASE+1029+((gErrSlotIdCnt<<3)&0x7FF)), recvVal);		// 0x324
							debug_write((DBG_DDR_IDX_DRV_BASE+1030+((gErrSlotIdCnt<<3)&0x7FF)), recvAddr);		// 0x32c
							debug_write((DBG_DDR_IDX_DRV_BASE+1031+((gErrSlotIdCnt<<3)&0x7FF)), srcAddr);		// 0x32c
							debug_write((DBG_DDR_IDX_DRV_BASE+1032+((gErrSlotIdCnt<<3)&0x7FF)), (slotId+(i<<4)+(idBf<<8))); 	// 0x328
							debug_write((DBG_DDR_IDX_DRV_BASE+1033+((gErrSlotIdCnt<<3)&0x7FF)), dstAddr);		// 0x328
							debug_write((DBG_DDR_IDX_DRV_BASE+1034+((gErrSlotIdCnt<<3)&0x7FF)), slotBfCnt); 	// 0x328
						}

						gErrSlotIdCnt++;
//						break;
//						break;
					}
				}
			}
		}
		debug_write((DBG_DDR_IDX_DRV_BASE+1024), gCompSlotIdCnt); // 0x310
		debug_write((DBG_DDR_IDX_DRV_BASE+1025), gErrSlotIdCnt); // 0x314
	}
}


void Cpri_Header_Rx(void)
{
	
}

void fh_data_check(uint32_t times)
{
	stMtimerIntStat* pMtimerInt = &gMtimerIntCnt[MTIMER_CPRI_ID];
	if (40 <= pMtimerInt->csuEnCnt)
	{
	#if 0
		if (64 == gCpriTimerPara.csuEnCnt)
		{
			AUX_Rx_init(0x50000000,0x60000000,0x10000,0x10000);
			//AUX_Rx_enable(0x2);
		}
	#endif		
		gCompWordCnt = 0;
		for (int i = 0; i < 7; i++)
		{
			cpri_check_slot_data(i);
		}
		Cpri_Header_Rx();
	}
	
}
