#ifndef CPRI_DELAY_H_
#define CPRI_DELAY_H_

#include "ucp_drv_common.h"

#define PCS_SH_TX_DELAY		0x2	// 0x33
#define PCS_SH_RX_DELAY		0x2F
#define PCS_SH_GB_POS_TX	0x2F
#define PCS_SH_GB_POS_RX	0x2
#define PCS_SLIP_CNT		0x0

typedef struct _tagCpriDelayMeasure
{
#if 1
	// T2A
	double delayReT2A;		// us
	// DMA
	double delayDma;		// us
	// round trip delay
	double delayRndTrip; 	// us
	// ip delay
	double delayIpTx; 		// us
	double delayIpRx; 		// us
	// adjust buf delay
	double delayAdjTx; 		// us
	double delayAdjRx; 		// us
	// RE offset,TOffset
	double delayReTOffset;	// us
	// serdes delay
	double delaySerdesTx; 	// us
	double delaySerdesRx; 	// us
	// pcs delay
	double delayPcsTx;
	double delayPcsRx;
    // fiber delay
    double delayCable;
	// round trip delay excluding cable delay
	double delayRndTripExCable;
	// round trip cable delay
	double delayRndCableMax;
	double delayRndCableMin;
#else
	// T2A
	int32_t delayReT2A;		// us
	// DMA
	int32_t delayDma;		// us
	// round trip delay
	int32_t delayRndTrip; 	// us
	// ip delay
	int32_t delayIpTx; 		// us
	int32_t delayIpRx; 		// us
	// adjust buf delay
	int32_t delayAdjTx; 		// us
	int32_t delayAdjRx; 		// us
	// RE offset,TOffset
	int32_t delayReTOffset;	// us
	// serdes delay
	int32_t delaySerdesTx; 	// us
	int32_t delaySerdesRx; 	// us
	// pcs delay
	int32_t delayPcsTx;
	int32_t delayPcsRx;
    // fiber delay
    int32_t delayCable;
	// round trip delay excluding cable delay
	int32_t delayRndTripExCable;
	// round trip cable delay
	int32_t delayRndCableMax;
	int32_t delayRndCableMin;
#endif
	// 10ms offset, ns as unit
	uint32_t cpriTxOffset;
	uint32_t cpriRxOffset;
	uint32_t cpriUlFrmDataOffset;       // offset of ul data to ul frame header 
	// 10ms tx offset
	uint32_t cpri10msOffset;
	uint32_t cpri10msOffsetSam[64]; 	// 采样64次取平均值
	// 10ms rx offset
	uint32_t cpri10msRxOffset;
	uint32_t cpri10msRxOffsetSam[64];	// 采样64次取平均值
	// 10ms tx/rx offset to pp1s
	int32_t cpri10ms2PP1sTxOffset;
	int32_t cpri10ms2PP1sRxOffset;
	int32_t cpriTdd2PP1sOffset;
	// tdd offset
	uint32_t cpriTddOffset;
	// measurement count
	uint32_t delayMeasureCnt;
	// flag
	uint8_t delayMeausreValid;	// valid flag
	uint8_t delayRndTripAlarm;
	uint8_t delayRndCableAlarm;
	uint8_t reserved[5];
}stCpriDelayMeasure;

typedef struct _tagCpriLinkStatus
{
	uint8_t losFlag;
	uint8_t lofFlag;
	uint8_t sdiFlag;
	uint8_t raiFlag;
}stCpriLinkStatus;

typedef struct _tagCpriSetLinkDelay
{
	uint8_t  u8fiber_port;
    uint8_t  u8rsv[3];
	uint32_t u32dl_frame_offset;
	uint32_t u32ul_frame_offset;
	uint32_t u32ul_data_frame_offset;
}stCpriSetLinkDelay;

typedef struct _tagCpriGetLinkDelay 
{
	uint8_t  u8fiber_port;
    uint8_t  u8result;
    uint8_t  u8rsv[2];
	uint32_t u32dl_frame_offset;
	uint32_t u32ul_frame_offset;
	uint32_t u32ul_data_frame_offset;
}stCpriGetLinkDelay;

typedef struct _tagCpriGetRndDelay 
{
	uint8_t  u8fiber_port;
    uint8_t  u8result;
    uint8_t  u8rsv[2];
	uint32_t u32t14_val;
}stCpriGetRndDelay;

typedef struct _tagCpriSetDelayRsp 
{
	uint8_t  u8fiber_port;
    uint8_t  u8result;
    uint8_t  u8rsv[2];
}stCpriSetDelayRsp;

typedef struct _tagCpriFrameHeadOffsetReq {
	uint16_t u16frame_head_offset;
    uint8_t  u8rsv[2];
} stCpriFrameHeadOffsetReq;

typedef struct _tagCpriFrameHeadOffsetRsp {
	uint8_t  u8result;
    uint8_t  u8rsv[3];
} stCpriFrameHeadOffsetRsp;

typedef struct _tagCpriGetFrameHeadOffset {
	uint8_t  u8result;
    uint8_t  u8rsv;
	uint16_t u16frame_head_offset;
}stCpriGetFrameHeadOffset;

typedef struct _tagOamMsgTransferHeader {
	uint8_t numMsg;
	uint8_t cellIndex;
	uint16_t rsv;
	uint32_t msgType;
	uint32_t msgLen;
	uint32_t msgData[0];
} stOamMsgTransferHeader;

void cpri_delay_init();

void cpri_link_status_init();
// cpri时延校准
void cpri_delay_measurement();

// cpri link delay calibration for ck
void cpri_delay_measurement_ck();

void update_cpri_link_status();

// cpri延时设置与获取
stCpriSetDelayRsp* set_cpri_link_delay(stCpriSetLinkDelay* pCpriSetDelay);
void get_cpri_link_delay(uint8_t u8fiber_port, stCpriGetLinkDelay* pCpriGetDelay);
void get_cpri_rndtrip_delay(uint8_t u8fiber_port, stCpriGetRndDelay* pCpriRndDealy);

// cpri帧头偏移设置与获取
stCpriFrameHeadOffsetRsp* set_frame_head_offset(stCpriFrameHeadOffsetReq* pCpriFrameHeadOffset);
void get_cpri_framehead_offset(stCpriGetFrameHeadOffset* pCpriFrameHeadOffset);

/*
    函数名称：get_cpri_delay
    函数入参：
    *delay: cpri的接收延迟量，单位为ns
    函数功能：获取oam或phy脚本设置的cpri的接收延迟量，如果oam或phy脚本配置的延迟量不足6us，
              驱动实际取6us做接收延迟量（考虑到中断处理延迟及最小光纤延迟）
*/
void get_cpri_delay(uint32_t* delay);

/*
    函数名称：get_cpri_advance
    函数入参：
    *advance: cpri的发送提前量，单位为ns
    函数功能：获取oam或phy脚本设置的cpri的发送提前量，如果oam或phy脚本配置的延迟量不足6us，
              驱动实际取6us做发送提前量（考虑到中断处理延迟及最小光纤延迟）
*/
void get_cpri_advance(uint32_t* advance);

/*
    函数名称：get_cpri_frame_data_offset
    函数入参：
    *offset: cpri的上行帧头与上行数据直接的偏移量，单位为ns
    函数功能：获取oam或phy脚本设置的cpri的上行帧头与上行数据直接的偏移量
*/
void get_cpri_frame_data_offset(uint32_t* offset);

#endif /* CPRI_DELAY_H_ */
