#ifndef CAN_LIB_H_
#define CAN_LIB_H_

/*
#define Platform_16Bit
#define Platform_32Bit
*/

#ifdef Platform_16Bit
    #define canfdlib_uint8_t  unsigned char
    #define canfdlib_uint16_t unsigned int
    #define canfdlib_uint32_t unsigned long
#else
    #define canfdlib_uint8_t  unsigned char
    #define canfdlib_uint16_t unsigned short
    #define canfdlib_uint32_t unsigned int
    #define canfdlib_uint64_t unsigned long long
#endif

#define CAN_RX_MSG_Block (( canfdlib_uint8_t )(136U / 4u))
#define CAN_TX_MSG_Block (( canfdlib_uint8_t )(88U / 4u))

typedef void (*FDMSG_CKB_ON_RECEIVE)(canfdlib_uint8_t CopyData []);
typedef void (*FDMSG_CKB_ON_PROCESS)(canfdlib_uint8_t CopyData []);
typedef void (*FDMSG_CKB_ON_LOST)(canfdlib_uint8_t CopyData []);
typedef void (*FDpfnMsgBufferSet)(canfdlib_uint8_t CopyData []);
typedef void (*FDpfnMsgSuccess)(void);

/**@enum CANFD_FUNC_ERR_t
 * @brief 定义驱动上报应用消息类型 \n
 */
typedef enum
{
    CANFD_ERR_OK,       /**< 模块初始化返回值,参数正常 */
    CANFD_ERR_ParaInit, /**< 模块初始化返回值,初始化错误 */
    CANFD_ERR_OUTRANGE, /**< 模块初始化返回值,参数传入超限制 */
} CANFD_FUNC_ERR_t;

/**@enum CANFD_TX_Status_t
 * @brief 定义CAN模块发送状态 \n
 */
typedef enum
{
    CANFD_N_TX_Disable = 0x00U, /**< CAN模块禁止发送 */
    CANFD_N_TX_Enable  = 0x55U, /**< CAN模块允许发送 */
} CANFD_TX_Status_t;

/**@enum CANFD_RX_Status_t
 * @brief 定义CAN模块接收状态 \n
 */
typedef enum
{
    CANFD_N_RX_Enable  = 0x00U, /**< CAN模块禁止接收 */
    CANFD_N_RX_Disable = 0x55U, /**< CAN模块允许接收 */
} CANFD_RX_Status_t;

/**@struct st_CANFDMsgAttribute
 * @brief 报文接收属性结构体 \n
 * 定义报接收文属性
 */
typedef struct
{
    canfdlib_uint8_t     Init_Aarry [ 64U ];    /**< 报文初始化值.默认加载,未收到报文时,buffer内为该值 */
    canfdlib_uint8_t     TimeOut_Array [ 64U ]; /**< 报文掉线值.掉线后加载 */
    canfdlib_uint8_t     Mask_Array [ 64U ];    /**< 报文掉线掩码.哪一位要是用掉线值就置位 */
    canfdlib_uint32_t    MSG_TimeOut_Val;      /**< 报文掉线时间,单位ms */
    canfdlib_uint32_t    MSG_Identifier;       /**< 报文ID值 */
    FDMSG_CKB_ON_RECEIVE Msg_ReceiveCBK;       /**< 报文中断接收回调函数,默认NULL,该回调函数处于接收中断内. */
    FDMSG_CKB_ON_PROCESS Msg_ProcessCBK;       /**< 报文逻辑接收回调函数,默认NULL,该回调函数处逻辑函数内 */
    FDMSG_CKB_ON_LOST    Msg_LostCBK;          /**< 报文逻辑掉线回调函数,默认NULL,该回调函掉线后会被执行一次 */
} st_CANFDMsgAttribute;

/**@struct st_CANFD_SendAttribute
 * @brief 报文发送属性结构体 \n
 * 定义发送报文属性
 */
typedef struct
{
    canfdlib_uint32_t u32MsgID;          /**< 报文发送ID */
    canfdlib_uint32_t u32MsgCycle;       /**< 报文发送周期,单位是us */
    canfdlib_uint32_t u32MsgCycleOffset; /**< 报文发送周期偏移量,定时器计时初值 */
    canfdlib_uint32_t u32InitSendCnt;    /**< 报文发送初始次数 */
    canfdlib_uint8_t  u8MsgSTD_EXT;      /**< 报文类型是标准帧还是扩展帧  标准帧0 扩展帧1 */
    canfdlib_uint8_t  u8MsgPro;          /**< 报文发送优先级,使用哪个buffer发送 */
    canfdlib_uint8_t  u8MsgDLC;          /**< 报文发送的长度,默认8 */
    canfdlib_uint8_t  u8TXMsgType;       /**< 报文发送的类型,周期帧,事件帧,周期事件帧 */
    FDpfnMsgBufferSet MsgBufferSet;      /**< 报文发送buffer填充函数,报文发送前会调用此函数从外部加载发送值 */
    FDpfnMsgSuccess   MsgSuccess;        /**< 报文发送成功回调函数 */
} st_CANFD_SendAttribute;


typedef struct
{
    union
    {
        canfdlib_uint32_t word_msg [ 2*8 ];
        canfdlib_uint8_t  Msg [ 8*8 ];
    }sig;
} st_CANFD_MsgBuff;

extern st_CANFD_MsgBuff              Load_AttrBuff [ 100 ] ;



/**@struct st_CANFD_Msg
 * @brief 报文发送结构体 \n
 * 定义报文发送结构的信息
 */
typedef struct
{
    canfdlib_uint32_t MsgID;     /**< 报文发送ID */
    canfdlib_uint8_t  MsgStd;    /**< 报文发送标准帧/扩展帧 */
    canfdlib_uint8_t  MsgRTR;    /**< 报文发送数据帧/远程帧 默认0 */
    canfdlib_uint8_t  MsgDLC;    /**< 报文发送长度 */
    canfdlib_uint8_t  MsgPro;    /**< 报文发送优先级,对应使用buffer */
    canfdlib_uint8_t  Msg [ 64U ]; /**< 报文发送数据buffer */
} st_CANFD_Msg;

typedef canfdlib_uint8_t (*HAL_CANFD_Send)(st_CANFD_Msg *Msg);
/**@struct st_CANFDMsgStruct
 * @brief 内部使用 \n
 * 内容不明
 */
typedef struct
{
    canfdlib_uint8_t          AnalyzeMsg [ 64U ];
    canfdlib_uint8_t          ReceiveBuf [ 64U ];
    volatile canfdlib_uint8_t CAN_Busy;
    volatile canfdlib_uint8_t CAN_Received;
    canfdlib_uint8_t          CAN_Status;
    canfdlib_uint8_t          CAN_Reverse;
    canfdlib_uint32_t         CAN_Lost;
} st_CANFDMsgStruct;
/**@struct st_CanFDMsgOp
 * @brief 内部使用,不做讲解 \n
 * 内部使用,不做讲解
 */
typedef struct
{
    st_CANFDMsgStruct          *CAN_MSG_Analysis;
    const st_CANFDMsgAttribute *pAttrubute;
    canfdlib_uint16_t           Total_Msg;
    canfdlib_uint8_t            u8CAN_RX_ENABLE;
} st_CanFDMsgOp;
/**@struct st_CANFD_SendOperation
 * @brief 内部使用,不做讲解 \n
 * 内部使用,不做讲解
 */
typedef struct
{
    canfdlib_uint32_t u32MsgID;
    canfdlib_uint32_t u32Timer;
    canfdlib_uint32_t u32MsgCycle;
    canfdlib_uint32_t u32SendCnt;
    canfdlib_uint8_t  u8MsgSTD_EXT;
    canfdlib_uint8_t  u8MsgPro;
    canfdlib_uint8_t  u8TXMsgType;
    canfdlib_uint8_t  u8MsgRet;
    canfdlib_uint8_t  u8MsgBuff [ 64U ];
    canfdlib_uint16_t u16MsgDLC;
    canfdlib_uint16_t u16TXMsgDIMcounter;
} st_CANFD_SendOperation;
/**@struct st_CanFDMsgTxOp
 * @brief 内部使用,不做讲解 \n
 * 内部使用,不做讲解
 */
typedef struct
{
    const st_CANFD_SendAttribute *pCAN_SendAttribute;
    st_CANFD_SendOperation       *CanMsg;
    canfdlib_uint16_t             Total_Msg;
    HAL_CANFD_Send                Can_Write;
    canfdlib_uint8_t              u8CAN_TX_ENABLE;
} st_CanFDMsgTxOp;

extern void            CANFD_RX_SetEnable(st_CanFDMsgOp *CanRXMsgOp, CANFD_RX_Status_t RX_enable);
extern CANFD_RX_Status_t CANFD_RX_ReadEnableSts(st_CanFDMsgOp *CanRXMsgOp);

extern void            CANFD_TX_SetEnable(st_CanFDMsgTxOp *CanMsgTxOp, CANFD_TX_Status_t TX_enable);
extern CANFD_TX_Status_t CANFD_TX_ReadEnableSts(st_CanFDMsgTxOp *CanMsgTxOp);

extern void           CanFD_Write_Fun(st_CanFDMsgTxOp *CanMsgTxOp, canfdlib_uint32_t u32CbkCycle);
extern CANFD_FUNC_ERR_t CanFD_Msg_Tx_Overwrite(st_CanFDMsgTxOp *CanMsgTxOp, canfdlib_uint32_t u32TxMsgIdx, canfdlib_uint16_t u16TxMSgDIMcounter, canfdlib_uint32_t u32TxMsgCycle);
extern CANFD_FUNC_ERR_t CanFD_TX_BuffInit(st_CanFDMsgTxOp *CanMsgTxOp, const st_CANFD_SendAttribute *Array, canfdlib_uint16_t length, HAL_CANFD_Send pfunc);
extern void           CanFD_Msg_TX_SUCCESS(st_CanFDMsgTxOp *CanMsgTxOp, canfdlib_uint32_t u32TxMsgIdx);
extern CANFD_FUNC_ERR_t CanFD_Msg_TX_FastInitCycle(st_CanFDMsgTxOp *CanMsgTxOp, canfdlib_uint32_t u32TxMsgIdx, canfdlib_uint32_t CurTimerCnt);
extern void CanFD_Msg_TX_SetMsgBuffer(st_CanFDMsgTxOp *CanMsgTxOp, canfdlib_uint32_t u32TxMsgIdx, canfdlib_uint8_t CopyLength, canfdlib_uint8_t Msg []);

extern void           CanFD_RX_BuffInit(st_CanFDMsgOp *CanRXMsgOp, const st_CANFDMsgAttribute *array, canfdlib_uint16_t length);
extern void           CanFDMSg_XMS_Analysis(st_CanFDMsgOp *CanRXMsgOp, canfdlib_uint16_t CbkCycle);
extern void           Co_CanFD_Buff_Set(st_CanFDMsgOp *CanRXMsgOp, canfdlib_uint16_t MsgID, canfdlib_uint8_t m_DLC, canfdlib_uint8_t Msg []);
extern canfdlib_uint8_t CANFD_MSG_Status(st_CanFDMsgOp *CanRXMsgOp, canfdlib_uint16_t MsgID);
extern canfdlib_uint8_t CANFD_MSG_Read(st_CanFDMsgOp *CanRXMsgOp, canfdlib_uint16_t MsgIdx, canfdlib_uint8_t BuffIdx);
extern void           CanFD_RX_ResetAllTimer(st_CanFDMsgOp *CanRXMsgOp);
extern void           CanFD_RX_ResetTimer(st_CanFDMsgOp *CanRXMsgOp, canfdlib_uint16_t idx);
extern canfdlib_uint32_t CAN_RX_Get_TimeStamp(st_CanFDMsgOp *CanRXMsgOp, canfdlib_uint16_t MsgIdx);
extern canfdlib_uint32_t Read_CANFD_RX_Version(void);
extern canfdlib_uint32_t Read_CANFD_TX_Version(void);

extern void CANFD_TX_DiagCtrlEnable(st_CanFDMsgTxOp *CanMsgTxOp, CANFD_TX_Status_t TX_enable);
extern void CANFD_TX_DiagCtrlRelease(st_CanFDMsgTxOp *CanMsgTxOp);

extern void CANFD_RX_DiagCtrlEnable(st_CanFDMsgOp *CanRXMsgOp, CANFD_RX_Status_t RX_enable);
extern void CANFD_RX_DiagCtrlRelease(st_CanFDMsgOp *CanRXMsgOp);

#endif
