
#include "receiver_symb_func.h"


void ChannelEqu_Proc(
	uint32_t* param_data_ptr,
    int32_t  *temp_dm0_ptr,
    int32_t  *temp_dm1_ptr,
	int32_t* temp_dm2_ptr,
	int32_t* temp_dm3_ptr

)
{
    //局部变量定义
	uint32_t *ConfigByteSet = receiver_symb_config_dm0_ptr + g_receiver_symb_table_param.ByteSet_CFG15_Offset ;
 
    uint32_t res_ptr = CHANNELEQU_DATA_DDR_PTR;             //Store result of Equ


	// Temporary input for test
	uint32_t * InputNoise = ((((uint32_t)&temp_dm3_ptr[0] + 4095)>>12)<<12);

	ByteSet(ConfigByteSet,0,MPU_ADDR(InputNoise),32768);
	SVRReg[0] = MPU_ADDR(ConfigByteSet);
	ByteSetAsm(SVRReg);
	WAIT_MPU_STOP;
    

	// available address space for channelEqu
	uint32_t * available_ptr_dm0 = temp_dm0_ptr;
	uint32_t * available_ptr_dm1 = temp_dm1_ptr + 0x1000;
	uint32_t * available_ptr_dm2 = temp_dm2_ptr;
	uint32_t * available_ptr_dm3 = InputNoise + 0x1000;


	// Configuration
    uint32_t *CfgFft4096Int32 = receiver_symb_config_dm0_ptr + g_receiver_symb_table_param.Fft4096Int32_CFG5_Offset;
    uint32_t *CfgEQ21Part1 = receiver_symb_config_dm0_ptr + g_receiver_symb_table_param.EQ21Part1_CFG6_Offset;
    uint32_t *CfgEQ1Part2 = receiver_symb_config_dm0_ptr + g_receiver_symb_table_param.EQ1Part2_CFG7_Offset;
    uint32_t *CfgIFFT4096 =  receiver_symb_config_dm0_ptr + g_receiver_symb_table_param.IFFT4096_CFG8_Offset;
    uint32_t *CfgIFFT4096TURN =  receiver_symb_config_dm0_ptr + g_receiver_symb_table_param.IFFTDatTurn_CFG9_Offset;
	uint32_t *CfgAgcShift = receiver_symb_config_dm0_ptr + g_receiver_symb_table_param.Agcshift_CFG10_Offset;
    uint32_t *CfgIFFT4096AddCP = receiver_symb_config_dm0_ptr + g_receiver_symb_table_param.AddCP_CFG11_Offset;

	uint32_t *CfgByteCopy = receiver_symb_config_dm0_ptr + g_receiver_symb_table_param.ByteCopy_CFG16_Offset;
   	uint32_t *CfgAgcMultiSym = receiver_symb_config_dm0_ptr + g_receiver_symb_table_param.AgcMultiSym_CFG17_Offset;
   
	
	// LUT
    uint32_t *Lut_W4096 = receiver_symb_config_dm2_ptr + g_receiver_symb_table_param.EqW4096_LUT2_Offset;
    uint32_t *Lut_EqFactor0 = receiver_symb_config_dm2_ptr + g_receiver_symb_table_param.EqFactor0_LUT3_Offset;
    uint32_t *Lut_EqFactor1 = receiver_symb_config_dm3_ptr + g_receiver_symb_table_param.EqFactor_LUT5_Offset;
    uint32_t *Lut_EqFactor = receiver_symb_config_dm1_ptr + g_receiver_symb_table_param.EqFactor1_LUT4_Offset;
    // uint32_t *Lut_Zero = lut_addr + RECEIVER_SYMB_EqW4096_LUT2_LENGTH + RECEIVER_SYMB_EqFactor0_LUT3_LENGTH + RECEIVER_SYMB_EqFactor1_LUT4_LENGTH;   //useless
    uint32_t *Lut_phase =  receiver_symb_config_dm2_ptr + g_receiver_symb_table_param.EqCpPhase_LUT6_Offset ;
    uint32_t *Lut_agcFactor = receiver_symb_config_dm2_ptr + g_receiver_symb_table_param.AgcShiftFft_LUT7_Offset;
    uint32_t *Lut_agcMultiSymFactor = receiver_symb_config_dm2_ptr + g_receiver_symb_table_param.AgcMultiSymFactor_LUT8_Offset;


    // channelEst and data
    uint32_t *InputCHEst_ddr_ptr = (uint32_t *)CHANNELEST_DATA_DDR_PTR;
    uint32_t *InputData_ddr_ptr = (uint32_t *)(COMPENSATED_DATA_DDR_PTR + 2048*4); //去除导频

	int numSym = 7 ;    ///7;
	int Scale = 13;
	int NRE = 4096;
	int ShiftFactor[] = {7,1,0,0,0,0,0,0,0,0,0,0};
	int NumCB = 2;
	const int16_t dataPilotDiff = 6;

//	int16_t baseScale = -2;


	for(int i=0;i<NumCB;i++)
	{

		int16_t pre_scale = 0;

		int *Scalep = available_ptr_dm0;
		int *Scale0 = available_ptr_dm0 + 0x0040;
		int *Scales = available_ptr_dm0 + 0x0080;

		int *tmp0 = (int*)(((int)available_ptr_dm1 + 0x4000 - 1) & ~(0x4000 - 1));             // LENGTH: 0x2000
		int *Fft_est_dm3_ptr = (int*)(((int)available_ptr_dm3 + 0x4000 - 1) & ~(0x4000 - 1));   // LENGTH: 0x1000
		int *channelEst_dm0_ptr = (int*)(((int)Scales + 0x0100 + 0x4000 - 1) & ~(0x4000 - 1));

		 /*****************************************FFT of channelEst*****************************************/

    	ape_csu_task_lookup(DMA_TAG_G2L, 1);
    	ape_csu_dma_1D_G2L_ch0ch1_transfer(
			(uint64_t)(InputCHEst_ddr_ptr + 4096*i) ,
            (uint64_t)DM_TO_CSU_ADDR(Fft_est_dm3_ptr),
            4096*4,
            DMA_TAG_G2L,
            1);

		for(int ii=0;ii<32;ii++)
		{
			Lut_agcFactor[ii] = 0;
		}

    	AgcShiftForFftInt32(
    		(int)CfgAgcShift,
			MPU_ADDR(Fft_est_dm3_ptr),
			MPU_ADDR(Fft_est_dm3_ptr),
			4096,
			1,
			MPU_ADDR(Lut_agcFactor),
			MPU_ADDR(Lut_agcFactor),
			MPU_ADDR(channelEst_dm0_ptr),
			MPU_ADDR(channelEst_dm0_ptr)
			);
    	SVRReg[0] = MPU_ADDR(CfgAgcShift);
    	AgcShiftForFftInt32Asm(SVRReg);
		WAIT_MPU_STOP;

		Fft4096Int32(
			(int)CfgFft4096Int32,
			1,
			Scale,
			ShiftFactor,
			MPU_ADDR(Lut_W4096),                        //DM2
			MPU_ADDR(channelEst_dm0_ptr),               //DM0
			MPU_ADDR(available_ptr_dm2),                //DM2
			MPU_ADDR(Fft_est_dm3_ptr),                  //DM3
			MPU_ADDR(tmp0),                             //DM1
			MPU_ADDR(Scalep),
			MPU_ADDR(Scale0)
			);
	    SVRReg[0] = MPU_ADDR(CfgFft4096Int32);
		Fft4096Int32Asm(SVRReg);
		WAIT_MPU_STOP;

		int16_t pilotFFtScale = Scalep[0] & (0xFFFF);

		/*ape_csu_dma_1D_L2G_ch0ch1_transfer(
			(uint64_t)DM_TO_CSU_ADDR(Fft_est_dm3_ptr),
			(uint64_t)0x84c00000,
			4096*4 ,
			DMA_TAG_L2G,
			1);
		*/

		ByteCopy((int)CfgByteCopy, MPU_ADDR(Fft_est_dm3_ptr),MPU_ADDR(channelEst_dm0_ptr + 4096),16384);
		SVRReg[0] = MPU_ADDR(CfgByteCopy);
		ByteCopyAsm(SVRReg);
		WAIT_MPU_STOP;

		//构造第二根天线
		ByteCopy((int)CfgByteCopy, MPU_ADDR(channelEst_dm0_ptr),MPU_ADDR(Fft_est_dm3_ptr + 4096),16384);
		SVRReg[0] = MPU_ADDR(CfgByteCopy);
		ByteCopyAsm(SVRReg);
        WAIT_MPU_STOP;
		if(i==1){
			InputData_ddr_ptr = InputData_ddr_ptr + 7*(68+4096) + 1024 + 72;
		}

		 /*****************************************channelEqu*****************************************/
		
		int *Fft_outputdata_dm3_ptr = Fft_est_dm3_ptr + 0x2000;
		int *InData_dm0_ptr = channelEst_dm0_ptr + 0x2000;

		for(int j=0;j<numSym;j++){

			if(j==0){
				ape_csu_task_lookup(DMA_TAG_G2L, 1);
				ape_csu_dma_1D_G2L_ch0ch1_transfer((uint64_t)(InputData_ddr_ptr + (68+4096)*j + 68) ,
	                             (uint64_t)DM_TO_CSU_ADDR(Fft_outputdata_dm3_ptr),
	                             4096*4,
	                             DMA_TAG_G2L,
	                             1);
			}




			AgcShiftForFftInt32(
			    (int)CfgAgcShift,
				MPU_ADDR(Fft_outputdata_dm3_ptr),
				MPU_ADDR(Fft_outputdata_dm3_ptr),
				4096,
				1,
				MPU_ADDR(Lut_agcFactor),
				MPU_ADDR(Lut_agcFactor),
				MPU_ADDR(InData_dm0_ptr),
				MPU_ADDR(InData_dm0_ptr)
			);
			SVRReg[0] = MPU_ADDR(CfgAgcShift);
			AgcShiftForFftInt32Asm(SVRReg);
			WAIT_MPU_STOP;


			TRACE(TRACE_RECEIVER_SYMB_ADDR, 12, *Fft_outputdata_dm3_ptr);
			TRACE(TRACE_RECEIVER_SYMB_ADDR, 13, *(Fft_outputdata_dm3_ptr+1));
			TRACE(TRACE_RECEIVER_SYMB_ADDR, 14, *InData_dm0_ptr);
			TRACE(TRACE_RECEIVER_SYMB_ADDR, 15, *(InData_dm0_ptr+1));


	    	// FFT of Data
			Fft4096Int32(
				(int)CfgFft4096Int32,
				1,
				Scale,
				ShiftFactor,
				MPU_ADDR(Lut_W4096),
				MPU_ADDR(InData_dm0_ptr),          //DM0
				MPU_ADDR(available_ptr_dm2),       //DM2
				MPU_ADDR(Fft_outputdata_dm3_ptr),  //DM3
				MPU_ADDR(tmp0),                    //DM1
				MPU_ADDR(Scalep),
				MPU_ADDR(Scale0)
				);
			SVRReg[0] = MPU_ADDR((int)CfgFft4096Int32);
			Fft4096Int32Asm(SVRReg);
			WAIT_MPU_STOP;

				/* --------------  拉齐信道估计FFT     ------------*/
			int16_t dataFftScale = Scalep[0] & (0xFFFF);
			int16_t shiftScale = -(pilotFFtScale - dataFftScale - dataPilotDiff);

			int cc = i;
			int ccc = j;


			if(shiftScale!=0){
				Lut_agcMultiSymFactor[0] = shiftScale;

				AgcShiftMultiSym((int)CfgAgcMultiSym, MPU_ADDR(channelEst_dm0_ptr), 8192,1, MPU_ADDR(Fft_est_dm3_ptr),MPU_ADDR(Lut_agcMultiSymFactor));
				SVRReg[0] = MPU_ADDR(CfgAgcMultiSym);
				AgcShiftMultiSymAsm(SVRReg);
				WAIT_MPU_STOP;


			}


			// 构造第二根天线数据，与第一根相同
			ByteCopy((int)CfgByteCopy, MPU_ADDR(InData_dm0_ptr),MPU_ADDR(Fft_outputdata_dm3_ptr + 4096),16384);
			SVRReg[0] = MPU_ADDR(CfgByteCopy);
			ByteCopyAsm(SVRReg);

			int *Equ_Output = InData_dm0_ptr + 0x1000;			 	        //LENGTH 0x2000 (the second ant occupied additional space 0x1000)
			int *InOut2_dm1_ptr = tmp0;				                        //LENGTH 0x1000
			int *InOut3_dm0_ptr = InData_dm0_ptr + 0x3000;  				//LENGTH 0x2000
			int *InOut1_dm1_ptr = tmp0 + 0x1000;          	                //LENGTH 0x1000
			WAIT_MPU_STOP;


			EQ21Part1(
				CfgEQ21Part1,
				NRE,
				1,
				MPU_ADDR(Fft_est_dm3_ptr),       	//dm3  信道估计fft
				MPU_ADDR(InputNoise),            	//dm3  噪声全0
				MPU_ADDR(Fft_outputdata_dm3_ptr), 	//dm3  数据fft
				MPU_ADDR(Equ_Output),           	//dm0
				MPU_ADDR(InOut1_dm1_ptr),       	//dm1
				MPU_ADDR(InOut2_dm1_ptr),    		//dm1
				MPU_ADDR(InOut3_dm0_ptr)     		//dm0
				);
			SVRReg[0] = MPU_ADDR(CfgEQ21Part1);
			EQ21Part1Asm(SVRReg);


			int *Equ_Output_2 = available_ptr_dm2;                  //第一根天线均衡输出
			int *Equ_Output_21 = available_ptr_dm2 + 0x2000;        //第二根天线均衡输出
			EQ1Part2(
					CfgEQ1Part2,
					NRE,
					1,
					MPU_ADDR(Equ_Output),
					MPU_ADDR(InOut1_dm1_ptr),
					MPU_ADDR(InOut2_dm1_ptr),
					MPU_ADDR(InOut3_dm0_ptr),
					MPU_ADDR(Equ_Output_2),
					MPU_ADDR(Equ_Output_21)
					);
			WAIT_MPU_STOP;
			SVRReg[0]= MPU_ADDR(CfgEQ1Part2);
			EQ1Part2Asm(SVRReg);
			WAIT_MPU_STOP;
			TRACE(TRACE_RECEIVER_SYMB_ADDR, 16, *Equ_Output_2);
			TRACE(TRACE_RECEIVER_SYMB_ADDR, 17, *(Equ_Output_2+1));
			TRACE(TRACE_RECEIVER_SYMB_ADDR, 18, *(Equ_Output_2+2));
			TRACE(TRACE_RECEIVER_SYMB_ADDR, 19, *(Equ_Output_2+3));

			//ape_csu_task_lookup(DMA_TAG_G2L, 1);
	    	// ape_csu_dma_1D_L2G_ch0ch1_transfer(
	    	// 							(uint64_t)DM_TO_CSU_ADDR((Equ_Output_2)),
	    	//                             (uint64_t)res_ptr,
			// 							4096*4 ,
	    	//                             DMA_TAG_L2G,
	    	//                             1);



			//提前准备下一块数据
			if(j<numSym-1){
				ape_csu_task_lookup(DMA_TAG_G2L, 1);
				ape_csu_dma_1D_G2L_ch0ch1_transfer((uint64_t)(InputData_ddr_ptr + (68+4096)*(j+1) + 68),   //(68+4096)*(j+1) + 68)
				                             (uint64_t)DM_TO_CSU_ADDR(Fft_outputdata_dm3_ptr),
				                             4096*4,
				                             DMA_TAG_G2L,
				                             0);
			}



			/******************************          IFFT       ****************************************8*/
			int *Temp1 = Fft_outputdata_dm3_ptr + 0x1000;           // 缓存
			IFFT4096DataTurn(
					(int)CfgIFFT4096TURN,
					1,
					1,
					MPU_ADDR(Equ_Output_2), //dm2
					MPU_ADDR(tmp0),         //dm1  无效
					MPU_ADDR(Equ_Output),   //dm0
					MPU_ADDR(Temp1)         //dm3  无效
					);
			SVRReg[0]= MPU_ADDR(CfgIFFT4096TURN);
			IFFT4096DataTurnAsm(SVRReg);
			WAIT_MPU_STOP;


			int *Temp0 = available_ptr_dm2;                // buff, Equ_Output_2
			IFFT4096(
				(int)CfgIFFT4096,
				1,
				MPU_ADDR(Temp0),       //DM2
				MPU_ADDR(Temp1),       //DM3
				MPU_ADDR(Equ_Output),  //DM0
				MPU_ADDR(tmp0),        //DM1
				MPU_ADDR(Lut_EqFactor0),    //DM2
				MPU_ADDR(Lut_EqFactor1),    //DM3
				MPU_ADDR(Lut_EqFactor));   //DM1
			SVRReg[0] = MPU_ADDR(CfgIFFT4096);
			IFFT4096Asm(SVRReg);
			WAIT_MPU_STOP;


			int CPLength0 = 352;
			int CPLength1 = 288;
			AddCP(
				(int) CfgIFFT4096AddCP,
				2,
				1,
				CPLength0,
				CPLength1,
				MPU_ADDR(Equ_Output),      //DM0
				MPU_ADDR(tmp0),     		//DM1  invalid
				MPU_ADDR(Equ_Output_2),    //DM2
				MPU_ADDR(Temp1),           //DM3   invalid
				MPU_ADDR(Lut_phase)        //
				);

			SVRReg[0] = MPU_ADDR(CfgIFFT4096AddCP);
			AddCPAsm(SVRReg);
			WAIT_MPU_STOP;

			TRACE(TRACE_RECEIVER_SYMB_ADDR, 20, *(Equ_Output_2));
			TRACE(TRACE_RECEIVER_SYMB_ADDR, 21, *(Equ_Output_2+1));
			TRACE(TRACE_RECEIVER_SYMB_ADDR, 22, *(Equ_Output_2+2));

			ape_csu_task_lookup(DMA_TAG_G2L, 1);
	    	ape_csu_dma_1D_L2G_ch0ch1_transfer(
	    								(uint64_t)DM_TO_CSU_ADDR((Equ_Output_2+CPLength0)),
	    	                            (uint64_t)res_ptr,
										4096*4 ,
	    	                            DMA_TAG_L2G,
	    	                            1);


	    	res_ptr = res_ptr + 16384;

		}

	}

}

