// +FHDR------------------------------------------------------------
//                 Copyright (c) 2022 SmartLogic.
//                       ALL RIGHTS RESERVED
// -----------------------------------------------------------------
// Filename      : main.c
// Author        : xianfeng.du
// Created On    : 2022-06-25
// Last Modified :
// -----------------------------------------------------------------
// Description:
//
//
// -FHDR------------------------------------------------------------


#include "typedef.h"
#include "osp_task.h"
#include "osp_timer.h"
#include "ucp_printf.h"

#include "ucp_drv_common.h"
// #include "pet_rfm_spu0_top.h"
// #include "msg_transfer_host.h"
#include "msg_transfer_layer.h"
// #include "ucp_pcie_traffic.h"
#include "ucp_printf.h"
#include "msg_transfer_mem.h"
#include "msg_transfer_mbuffer.h"

#include "mem_sections.h"
#include "drv_ape.h"
#include "trace.h"
#include "interface_rec_sync2_pcie.h"
#include "Fucp_Ape7_pcie_testcase.h"
#include "mem_def.h"
#include "interface_rec_sync2_rec_sync_first.h"
#include "log_interface.h" 
#include "transform_para_func.h"

uint32_t g_thita1=0;
uint32_t g_thita2=0;
uint32_t g_thita34=0;
static int g_msg_count=0;
static int g_send_msg_flag=1;//0-停止给3588发送数据；1-启动给3588发数据

uint32_t pcie_rx_callback_data(const char* buf,uint32_t payloadSize)
{
	uint32_t ret = -1;
	TRACE(TRACE_PCIE_ADDR, 15, g_msg_count);
    char tmplogbuf[1024] = {0};
    debug_write(DBG_DDR_COMMON_IDX(get_core_id(),19), 0x70701090);
    if(payloadSize < 1024)
    {
        memcpy_ucp(tmplogbuf, buf, payloadSize);
    }
    else
    {
        memcpy_ucp(tmplogbuf, buf, 1024);
    }

	uint32_t *data_tmp=(uint32_t *)tmplogbuf;
    g_thita1=data_tmp[0];
	g_thita2=data_tmp[1];
	g_thita34=data_tmp[2];
    //UCP_PRINT_LOG("received buf : %s\n", tmplogbuf);
	LOG_INFO_S("received buf : [0x%08x][0x%08x][0x%08x]\n", g_thita1,g_thita2,g_thita34);

	
	transform_decode_para(g_thita1, g_thita2, g_thita34);
	uint32_t temp1 = g_thita1_val;
	uint32_t temp2 = g_thita2_val;
	uint32_t temp3 = g_thita34_val;


	ret = transform_decode_para_check(g_thita1, g_thita2, g_thita34);

	if(0 == ret)
	{
		receiver_pcie2sync_t* pcie2sync = (receiver_pcie2sync_t*)TRANSFORM_REF_PARA_PCIE2SYNC_ADDR;//存储在DDR
		STORE_EX_W(&(pcie2sync->thita1_val) , temp1);
		STORE_EX_W(&(pcie2sync->thita2_val) , temp2);
		STORE_EX_W(&(pcie2sync->thita34_val) , temp3);
		STORE_EX_W(&(pcie2sync->status) , 1); // 0: not ready  1: wait APE4 read  2:APE4 read & done
	}
	g_msg_count=0;//为下一次向3588送数初始化
   
    return payloadSize;
}

uint32_t pcie_rx_callback_ctrl(const char* buf,uint32_t payloadSize)
{
    char tmplogbuf[1024] = {0};

    if(payloadSize < 1024)
    {
        memcpy_ucp(tmplogbuf, buf, payloadSize);
    }
    else
    {
        memcpy_ucp(tmplogbuf, buf, 1024);
    }

    //UCP_PRINT_LOG("received buf : %s\n", tmplogbuf);

    return payloadSize;
}

uint32_t pcie_rx_callback_oam(const char* buf,uint32_t payloadSize)
{
    char tmplogbuf[1024] = {0};

    if(payloadSize < 1024)
    {
        memcpy_ucp(tmplogbuf, buf, payloadSize);
    }
    else
    {
        memcpy_ucp(tmplogbuf, buf, 1024);
    }

    //UCP_PRINT_LOG("received buf : %s\n", tmplogbuf);

    return payloadSize;
}

void test_case_cfgpar_pcie()
{
    int i = 0;

#ifdef PCIE_WITH_JESD
    for (i = (MAX_INSTANCE_NUM / 2); i < MAX_INSTANCE_NUM; i++)
#else
    for (i = 0; i < MAX_INSTANCE_NUM; i++)
#endif
    {
        msg_transfer_callback_register(CU_SPLIT, i, C_PLANE, pcie_rx_callback_ctrl);
        msg_transfer_callback_register(CU_SPLIT, i, U_PLANE, pcie_rx_callback_data);
        msg_transfer_callback_register(OAM, i, C_PLANE, pcie_rx_callback_oam);
    }
}

int8_t get_id(uint16_t type_id, uint16_t cu_flag)
{
	int8_t que_id = -1;

	switch (type_id) {
		case CU_SPLIT:
			if (cu_flag == U_PLANE) {
				que_id = UCP4008_TRAFFIC_NR_eMBB_DATA;
			} else {
				que_id = UCP4008_TRAFFIC_NR_eMBB_CTRL;
			}
			break;
		case OAM:
			que_id = UCP4008_TRAFFIC_OAM;
			break;
		default:
			UCP_PRINT_LOG("get_queue_id doesn't support transfer_type[%d] .",type_id);
			break;
	}

	return que_id;
}

//static uint32_t count = 0;

void test_case_sendmsg_pcie(uint32_t sfn ,uint32_t slot ,uint32_t data_addr ,uint32_t data_len )
{
    uint32_t size = 512-16;
    char* buf = NULL;
    uint32_t availableSize;

	uint16_t cu_flag = C_PLANE;
	HandleId_t handler;
	handler.port_id = 0;
	handler.inst_id = 0;
	handler.type_id = CU_SPLIT;
	uint32_t slot_ind_flag = 1;
	int ret = 0;
	
	uint32_t offset = 0;
	uint32_t i = 0;
	char templogbuf[256] = {0};
	
	int8_t que_id = 0;
	MsgQueueLocalMgt_t* pMsgQueueLocalMgt = get_msg_queue_local_mgt();
	MsgQueueLocalInfo_t* ch;	
	//uint32_t core_id = get_core_id();
	//uint32_t bufsize =  ch->bufSize - MSG_MBUF_HEAD_SIZE;


	/****************************test code************************************************/
#ifdef PCIE_WITH_JESD
debug_write(DBG_DDR_COMMON_IDX(get_core_id(),18), 0x70701051);
    for (i = (MAX_INSTANCE_NUM / 2); i < MAX_INSTANCE_NUM; i++)
#else
    for (i = 0; i < MAX_INSTANCE_NUM; i++)
#endif
	{
		//debug_write(DBG_DDR_COMMON_IDX(core_id, 2), ++count);
		handler.port_id = 0;
		handler.inst_id = i;
		handler.type_id = CU_SPLIT; 	
		if(1 == slot_ind_flag)
		{
		   // slot_ind_flag = 0;
			ret = msg_transfer_send_start(handler.value);

			/************C_PLANE***************/
			#if 0
			cu_flag = C_PLANE;
			que_id = get_id(handler.type_id, cu_flag);
			ch = (MsgQueueLocalInfo_t *)&pMsgQueueLocalMgt->localUlQueue[i][que_id];
			size =  ch->bufSize-MSG_MBUF_HEAD_SIZE;				
			ret = msg_transfer_alloc_msg(handler.value, cu_flag, size, &buf, &availableSize, &offset);
			//com_debug_log("alloc ctrl msg ulque[%d][%d] ch=0x%llx ch->bufSize=0x%x\n", i, que_id, (uint64_t)ch, ch->bufSize);			
			if ( SUCCESS != ret) {
				//com_debug_log("alloc ctrl msg failed! ulque[%d][%d] ch=0x%llx ch->bufSize=0x%x\n", i, que_id, (uint64_t)ch, ch->bufSize);
				continue;
			}
			//size = availableSize;
			//buf = *bufAddr;
			UCP_PRINT_LOG("msg transfer alloced ul msg C_PLANE buf = 0x%x!\n", buf);
			memset(templogbuf, 0x00, sizeof(templogbuf));				
			sprintf(templogbuf, "%s", "this is test for ul CU_SPLIT ctrl transfer!\n");
			memcpy_ucp(buf, templogbuf, strlen(templogbuf)+1);
			/*
			*(uint32_t*)(ptr + 0) = 0x12345678;
			*(uint32_t*)(ptr + 4) = 0x5a5a5a5a;
			*(uint32_t*)(ptr + 8) = 0x12345678;
			*(uint32_t*)(ptr + 12) = 0xa5a5a5a5;
			*/
			//PCIE_DEBUG_LOG("start enter msg_transfer_send_msg\n");
			ret = msg_transfer_send_msg(handler.value, cu_flag, (uint8_t *)buf, offset, size);

			if(ret != SUCCESS)
			{
				//com_debug_log("ul msg_transfer_send_msg CU_SPLIT ctrl  failed! ret = %d inst_id=%d\n", ret, handler.inst_id);
			}	
			#endif
			/************U_PLANE***************/
			cu_flag = U_PLANE;
			que_id = get_id(handler.type_id, cu_flag);
			ch = (MsgQueueLocalInfo_t *)&pMsgQueueLocalMgt->localUlQueue[i][que_id];
			size =  ch->bufSize-MSG_MBUF_HEAD_SIZE;	
			debug_write(DBG_DDR_COMMON_IDX(get_core_id(),4), size);						
			ret = msg_transfer_alloc_msg(handler.value, cu_flag, size, &buf, &availableSize, &offset);
			//com_debug_log("alloc data msg ulque[%d][%d] ch=0x%llx ch->bufSize=0x%x\n", i, que_id, (uint64_t)ch, ch->bufSize);			
			
			if ( SUCCESS != ret) {
				//com_debug_log("alloc data msg failed! ulque[%d][%d]  ch=0x%llx  ch->bufSize=0x%x\n", i, que_id, ch, ch->bufSize);
				continue;
			}
			//size = availableSize;
			//buf = *bufAddr;
			UCP_PRINT_LOG("msg transfer alloced ul U_PLANE msg buf = 0x%x!\n", buf);

#if 0	//用于测试		
			sprintf(templogbuf, "%s", "this is test for ul CU_SPLIT data transfer!\n");
			memcpy_ucp(buf, templogbuf, strlen(templogbuf)+1);
#endif

/* 			ptr = (uint8_t *)buf;
			*(uint32_t*)(buf + 0) = 0x12345678;
			*(uint32_t*)(buf + 4) = 0x5a5a5a5a;
			*(uint32_t*)(buf + 8) = 0x12345678;
			*(uint32_t*)(buf + 12) = 0xa5a5a5a5; */
#if 1  //testNPU
			
			*(uint32_t*)(buf + 0) = sfn;
			*(uint32_t*)(buf + 4) = slot;
			memcpy_ucp(buf + 8, data_addr, data_len);

/* 			debug_write(DBG_DDR_COMMON_IDX(get_core_id(),5), 0x70701010);
			debug_write(DBG_DDR_COMMON_IDX(get_core_id(),6), sfn); 
			debug_write(DBG_DDR_COMMON_IDX(get_core_id(),7), slot); 
			debug_write(DBG_DDR_COMMON_IDX(get_core_id(),8), *(uint32_t *)(buf+0));
			debug_write(DBG_DDR_COMMON_IDX(get_core_id(),9), *(uint32_t *)(buf+4));
			debug_write(DBG_DDR_COMMON_IDX(get_core_id(),10), *(uint32_t *)(buf+0));
			debug_write(DBG_DDR_COMMON_IDX(get_core_id(),11), *(uint32_t *)(buf+4));
			debug_write(DBG_DDR_COMMON_IDX(get_core_id(),12), *(uint32_t *)(data_addr+0));
			debug_write(DBG_DDR_COMMON_IDX(get_core_id(),13), *(uint32_t *)(data_addr+4));
 */

#endif
			ret = msg_transfer_send_msg(handler.value, cu_flag, (uint8_t *)buf, offset, size);
			if(ret != SUCCESS)
			{
				//com_debug_log("ul msg_transfer_send_msg CU_SPLIT data failed! ret = %d inst_id = %d\n", ret, handler.inst_id);
			}
	        debug_write(DBG_DDR_COMMON_IDX(get_core_id(),15), 0x70701020);
			ret = msg_transfer_send_end(handler.value);
			if(ret != SUCCESS)
			{
				//com_debug_log("ul msg_transfer_send_end CU_SPLIT data failed! ret = %d inst_id = %d\n", ret, handler.inst_id);
			}
			debug_write(DBG_DDR_COMMON_IDX(get_core_id(),16), 0x70701030);
		}
		#if 0
		handler.type_id = OAM;	
		if(1 == slot_ind_flag)
		{
		   // slot_ind_flag = 0;
		
			ret = msg_transfer_send_start(handler.value);
		
			/************C_PLANE***************/
			cu_flag = C_PLANE;
			que_id = get_id(handler.type_id, cu_flag);
			ch = (MsgQueueLocalInfo_t *)&pMsgQueueLocalMgt->localUlQueue[i][que_id];
			size =  ch->bufSize-MSG_MBUF_HEAD_SIZE;				
			ret = msg_transfer_alloc_msg(handler.value, cu_flag, size, &buf, &availableSize, &offset);
			//com_debug_log("alloc oam msg ulque[%d][%d] ch=0x%llx ch->bufSize=0x%x\n", i, que_id, (uint64_t)ch, ch->bufSize);			
			
			if ( SUCCESS != ret) {
				//com_debug_log("oam alloc msg failed! ulque[%d][%d] ch=0x%llx ch->bufSize = 0x%x\n", i, que_id, ch, ch->bufSize);
				continue;
			}
			//size = availableSize;
			//buf = *bufAddr;
			UCP_PRINT_LOG("msg transfer alloced msg OAM buf = 0x%x!\n", buf);
			memset(templogbuf, 0x00, sizeof(templogbuf));				
			sprintf(templogbuf, "%s", "this is test for ul OAM ctrl transfer!\n");
			memcpy_ucp(buf, templogbuf, strlen(templogbuf)+1);
			
			/*
			*(uint32_t*)(ptr + 0) = 0x12345678;
			*(uint32_t*)(ptr + 4) = 0x5a5a5a5a;
			*(uint32_t*)(ptr + 8) = 0x12345678;
			*(uint32_t*)(ptr + 12) = 0xa5a5a5a5;
			*/
			ret = msg_transfer_send_msg(handler.value, cu_flag, (uint8_t *)buf, offset, size);
			if(ret != SUCCESS)
			{
				//com_debug_log("ul msg_transfer_send_msg failed! CU_SPLIT oam !	ret = %d inst_id = %d\n", ret, handler.inst_id);
				continue;
			}
			
			UCP_PRINT_LOG("msg_transfer_send_msg end!\n");
			ret = msg_transfer_send_end(handler.value);
			if(ret != SUCCESS)
			{
				//com_debug_log("ul msg_transfer_send_end CU_SPLIT oam failed! ret = %d inst_id = %d\n", ret, handler.inst_id);
			}			
		}	
		#endif		
	}
	/*********************************************************************************/

}

void test_case_recv_msg_pcie()
{
	uint16_t cu_flag = C_PLANE;
	HandleId_t handler;
	handler.port_id = 0;
	handler.inst_id = 0;
	handler.type_id = CU_SPLIT;
	
	uint8_t port_id = 0;
	uint32_t offset = 0;
	uint32_t len = 0;
	uint8_t* msg_ptr;	
	uint32_t i = 0;	
	
	/****************************test code************************************************/
#ifdef PCIE_WITH_JESD
    for (i = (MAX_INSTANCE_NUM / 2); i < MAX_INSTANCE_NUM; i++)
#else
    for (i = 0; i < MAX_INSTANCE_NUM; i++)
#endif
    {
		handler.port_id = port_id;
		handler.inst_id = i;
		handler.type_id = CU_SPLIT;
		cu_flag = C_PLANE;
		msg_transfer_receive(handler.value, cu_flag, offset, len, &msg_ptr);
	
		cu_flag = U_PLANE;
		msg_transfer_receive(handler.value, cu_flag, offset, len, &msg_ptr);
	
		handler.type_id = OAM;
		msg_transfer_receive(handler.value, cu_flag, offset, len, &msg_ptr);		
	}
	/*********************************************************************************/ 	
}

#if 0

void test_speed_sendmsg_pcie()
{
    uint32_t size = 0;
    char* buf = NULL;
    uint32_t availableSize;

	uint16_t cu_flag = C_PLANE;
	HandleId_t handler;
	handler.port_id = 0;
	handler.inst_id = 0;
	handler.type_id = CU_SPLIT;
	uint32_t slot_ind_flag = 1;
	int ret = 0;
	
	uint32_t offset = 0;
	uint32_t i = 0;
	char templogbuf[1024] = {0};
	
    MsgQueueLocalMgt_t* pMsgQueueLocalMgt = get_msg_queue_local_mgt();
	MsgQueueLocalInfo_t* ch = (MsgQueueLocalInfo_t*)&pMsgQueueLocalMgt->localUlQueue[0][1];	
	size = ch->bufSize - MSG_MBUF_HEAD_SIZE;
	/****************************test code************************************************/
	for(i = 0; i < 2; i++)
	{
		handler.port_id = 0;
		handler.inst_id = i;
		handler.type_id = CU_SPLIT; 	
		if(1 == slot_ind_flag)
		{
		   // slot_ind_flag = 0;
			ret = msg_transfer_send_start(handler.value);
	
			/************C_PLANE***************/
			cu_flag = C_PLANE;
			ret = msg_transfer_alloc_msg(handler.value, cu_flag, size, &buf, &availableSize, &offset);
			if ( SUCCESS != ret) {
				UCP_PRINT_LOG("alloc msg failed!\n");
				continue;
			}
			//size = availableSize;
			//buf = *bufAddr;
			UCP_PRINT_LOG("msg transfer alloced ul msg C_PLANE buf = 0x%x!\n", buf);
			memset(templogbuf, 0x00, sizeof(templogbuf));				
			sprintf(templogbuf, "%s", "this is test for ul CU_SPLIT ctrl transfer!\n");
			memcpy_ucp(buf, templogbuf, strlen(templogbuf)+1);
			/*
			*(uint32_t*)(ptr + 0) = 0x12345678;
			*(uint32_t*)(ptr + 4) = 0x5a5a5a5a;
			*(uint32_t*)(ptr + 8) = 0x12345678;
			*(uint32_t*)(ptr + 12) = 0xa5a5a5a5;
			*/
			//PCIE_DEBUG_LOG("start enter msg_transfer_send_msg\n");
			ret = msg_transfer_send_msg(handler.value, cu_flag, (uint8_t *)buf, offset, size);
			if(ret != SUCCESS)
			{
				UCP_PRINT_LOG("ul msg_transfer_send_msg CU_SPLIT ctrl  failed! ret = %d\n", ret);
			}
			
			ret = msg_transfer_send_end(handler.value);
		}

	}
	/*********************************************************************************/

}
#endif

void test_speed_recv_msg_pcie()
{
    uint16_t cu_flag = C_PLANE;
    HandleId_t handler;
    handler.port_id = 0;
    handler.inst_id = 0;
    handler.type_id = CU_SPLIT;

    uint8_t port_id = 0;
    uint32_t offset = 0;
    uint32_t len = 0;
    uint8_t* msg_ptr;	
    uint32_t i = 0;	

    /****************************test code************************************************/
#ifdef PCIE_WITH_JESD
    for (i = (MAX_INSTANCE_NUM / 2); i < MAX_INSTANCE_NUM; i++)
#else
    for (i = 0; i < MAX_INSTANCE_NUM; i++)
#endif
    {
        handler.port_id = port_id;
        handler.inst_id = i;
        handler.type_id = CU_SPLIT;
        cu_flag = C_PLANE;
		TRACE(TRACE_PCIE_ADDR, 3, 3);
        msg_transfer_receive(handler.value, cu_flag, offset, len, &msg_ptr);
		TRACE(TRACE_PCIE_ADDR, 3, 4);
        cu_flag = U_PLANE;
        msg_transfer_receive(handler.value, cu_flag, offset, len, &msg_ptr);
		TRACE(TRACE_PCIE_ADDR, 3, 5);
        handler.type_id = OAM;
        msg_transfer_receive(handler.value, cu_flag, offset, len, &msg_ptr);	
		TRACE(TRACE_PCIE_ADDR, 3, 6);
    }
    /*********************************************************************************/ 	
}

void pcie_test_task_init()
{
	transform_para_init(0, 0, 0);
	return;
}

void pcie_test_task_func(receiver_sync2pcie_t* msg_ptr, uint32_t msg_len)
{

	RUN_CNT(TRACE_PCIE_ADDR, 0);
	TRACE(TRACE_PCIE_ADDR, 3, 1);
	g_time_start[1] = TIME_NS();
	//获取状态机状态
	receiver_sync_status_t* status_SM_addr= (uint32_t)RECEIVER_SYNC2SYNC_FIRST_INF_ADDR;
	volatile uint32_t sync_status = LOAD_EX_W(&(status_SM_addr->sync_status));
	TRACE(TRACE_PCIE_ADDR, 4, status_SM_addr);
	TRACE(TRACE_PCIE_ADDR, 5, sync_status);
	
	/*typedef enum
	{
		SYNC_IDLE=0,
		SYNC_FIRST_RUNING,
		SYNC_AI_PROCECING,
		SYNC_TRACKING
	}receiver_sync_status_e;*/
	if(2 !=  sync_status){
		return ;
	} 

   
	//提供的数据地址(DDR)和本次数据的SFN SLOT号
	uint32_t sfn = LOAD_EX_S(&msg_ptr->sfn) ;
	uint32_t slot = LOAD_EX_S(&msg_ptr->slot);
	uint32_t data_addr = LOAD_EX_W(&msg_ptr->data_section0_ptr);
	uint32_t data_len = 1024*4;
	TRACE(TRACE_PCIE_ADDR, 6, sfn);
	TRACE(TRACE_PCIE_ADDR, 7, slot);
	TRACE(TRACE_PCIE_ADDR, 8, data_addr);
	TRACE(TRACE_PCIE_ADDR, 9, *(uint32_t *)data_addr);
	//return ;

   
    //uint32_t clockTick   = 0;
   // uint32_t clockOffset = 0;	
   
    if(g_msg_count==0)
	{ //状态机中存储第一组数据发送时的sfn和slot用于后面计算
		receiver_pcie2sync_t* pcie2sync = (receiver_pcie2sync_t*)TRANSFORM_REF_PARA_PCIE2SYNC_ADDR;//存储在DDR
		STORE_EX_W(&(pcie2sync->ref_sfn) , sfn);
		STORE_EX_W(&(pcie2sync->ref_slot) , slot);
	}

	//一次处理只送8组数据
	// if(g_msg_count < 8)
	// {
		test_case_sendmsg_pcie(sfn,slot,data_addr,data_len);
	// }
	g_msg_count++;
	TRACE(TRACE_PCIE_ADDR, 13, g_msg_count);

	TRACE(TRACE_PCIE_ADDR, 3, 2);

	test_speed_recv_msg_pcie();
    //delay_us(50);

 	TRACE(TRACE_PCIE_ADDR, 3, 0xffff);
    RUN_CNT(TRACE_PCIE_ADDR, 1);

    TRACE_MAX(TRACE_PCIE_ADDR, 2, Time_offset(1) );

	return;
}



