#include "CANFD_Lib.h"

/**
 * @file        CAN_Signal_Rx.c
 * @brief       CAN接收文件
 * @details     CAN接收文件
 * @author      赵建智
 * @date        2022.04.25
 * @version     V1.0
 * @copyright   赵建智
 */

#if defined(__ICCARM__) /**< IAR ARM Compiler */
const char DataStr [] = {__DATE__};
const char TimeStr [] = {__TIME__};
#elif defined(__ghs__)         /**< Green Hills ARM Compiler */
const char DataStr []               = {__DATE__};
const char TimeStr []               = {__TIME__};
#elif defined(__GNUC__)        /**< GNU Compiler Collection */
const char DataStr []               = {__DATE__};
const char TimeStr []               = {__TIME__};
#elif defined(__DCC__)         /**< Wind River Diab Compiler */
const char DataStr []               = {__DATE__};
const char TimeStr []               = {__TIME__};
#elif defined(__ARMCC_VERSION) /**< ARMC Compiler */
const char DataStr []               = {__DATE__};
const char TimeStr []               = {__TIME__};
#elif defined(__HC12__)        /**< Codewarrior Compiler */
const char DataStr []               = {__DATE__};
const char TimeStr []               = {__TIME__};
#else                          /**< VScode  */
const char DataStr []               = {__DATE__};
const char TimeStr []               = {__TIME__};
#endif

#if defined(__ICCARM__) /**< IAR ARM Compiler */
const char Cur_RX_Module_Version [] = {"RX_VER=V1.0.0"};
#elif defined(__ghs__)         /**< Green Hills ARM Compiler */
const char Cur_RX_Module_Version [] = {"RX_VER=V1.0.0"};
#elif defined(__GNUC__)        /**< GNU Compiler Collection */
const char Cur_RX_Module_Version [] = {"RX_VER=V1.0.0"};
#elif defined(__DCC__)         /**< Wind River Diab Compiler */
const char Cur_RX_Module_Version [] = {"RX_VER=V1.0.0"};
#elif defined(__ARMCC_VERSION) /**< ARMC Compiler */
const char Cur_RX_Module_Version [] = {"RX_VER=V1.0.0"};
#elif defined(__HC12__)        /**< Codewarrior Compiler */
const char Cur_RX_Module_Version [] = {"RX_VER=V1.0.0"};
#else                          /**< VScode  */
const char Cur_RX_Module_Version [] = {"RX_VER=V1.0.0"};
#endif
/**
 * @brief CAN报文接收使能控制
 * @param[in] CanRXMsgOp 报文接收操作对象指针, 每路can都应有独立的结构体指针
 * @param[in] RX_enable  报文接收状态,默认是0x00
 * - CANFD_N_RX_Enable 报文允许接收
 * - CANFD_N_RX_Disable 报文禁止接收
 * @warning
 *
 * 示例
 @code
     CANFD_RX_SetEnable(&CAN_CH0_CanMsgOp,CANFD_N_RX_Enable);
 @endcode
 *
 * @since 1.0.1
 */
void CANFD_RX_SetEnable(st_CanFDMsgOp *CanRXMsgOp, CANFD_RX_Status_t RX_enable)
{
    if ( (CanRXMsgOp->u8CAN_RX_ENABLE & 0x80u) == 0x80u )
    {
    }
    else
    {
        CanRXMsgOp->u8CAN_RX_ENABLE = ( canfdlib_uint8_t )RX_enable;
    }
}
/**
 * @brief CAN报文接收状态读取
 * @param[in] CanRXMsgOp 报文接收操作对象指针, 每路can都应有独立的结构体指针
 * @return  当前CAN通道RX状态
 * - CANFD_N_RX_Enable 报文允许接收
 * - CANFD_N_RX_Disable 报文禁止接收
 * @warning None
 *
 * 示例
 @code
  CANFD_RX_Status_t Rx_Statis = CANFD_RX_ReadEnableSts(&CAN_CH0_CanMsgOp);
 @endcode
 *
 * @since 1.0.1
 */
CANFD_RX_Status_t CANFD_RX_ReadEnableSts(st_CanFDMsgOp *CanRXMsgOp)
{
    return ( CANFD_RX_Status_t )CanRXMsgOp->u8CAN_RX_ENABLE;
}

/**
 * @brief CAN报文接收模块初始化
 * @param[in] CanRXMsgOp 报文接收操作对象指针, 每路can都应有独立的结构体指针
 * @param[in] array 报文接收属性列表,按CAN通道区分,各自独立
 * @param[in] length 接收报文总数量,按CAN通道区分,各自独立
 * @warning None
 *
 * 示例
 @code
    #pragma alignvar(8)
    uint32_t pRXBuff [ CAN_RX_MSG_Block * ID_TOTAL_MAX ];

    void COM_CAN_Init(void)
    {
        memset(pRXBuff, 0, sizeof(pRXBuff));
        CAN_CH0_CanMsgOp.CAN_MSG_Analysis=pRXBuff;
        CanFD_RX_BuffInit(&CAN_CH0_CanMsgOp, CAN_CH0_CAN_MSG_CONST_ARRAY, CAN_CH0_ID_TOTAL_MAX);
    }
 @endcode
 *
 * @since 1.0.0
 */
void CanFD_RX_BuffInit(st_CanFDMsgOp *CanRXMsgOp, const st_CANFDMsgAttribute *array, canfdlib_uint16_t length)
{
    canfdlib_uint16_t i;
    canfdlib_uint8_t  j;

    CanRXMsgOp->pAttrubute = array;
    /*     CanRXMsgOp->CAN_MSG_Analysis = ( st_CANFDMsgStruct * )(( void * )memSpace); */
    CanRXMsgOp->Total_Msg = length;
    for ( i = 0U; i < CanRXMsgOp->Total_Msg; i++ )
    {
        for ( j = 0U; j < 64U; j++ )
        {
            CanRXMsgOp->CAN_MSG_Analysis [ i ].AnalyzeMsg [ j ] = CanRXMsgOp->pAttrubute [ i ].Init_Aarry [ j ];
            CanRXMsgOp->CAN_MSG_Analysis [ i ].ReceiveBuf [ j ] = CanRXMsgOp->pAttrubute [ i ].Init_Aarry [ j ];
        }
        CanRXMsgOp->CAN_MSG_Analysis [ i ].CAN_Busy     = 0U;
        CanRXMsgOp->CAN_MSG_Analysis [ i ].CAN_Received = 0U;
        CanRXMsgOp->CAN_MSG_Analysis [ i ].CAN_Status   = 0U;
        CanRXMsgOp->CAN_MSG_Analysis [ i ].CAN_Reverse  = 0U;
        CanRXMsgOp->CAN_MSG_Analysis [ i ].CAN_Lost     = 0U;
    }
    CanRXMsgOp->u8CAN_RX_ENABLE = 0U;
}
/**
 * @brief CAN报文接收模块逻辑处理
 * @param[in] CanRXMsgOp 报文接收操作对象指针, 每路can都应有独立的结构体指针
 * @param[in] CbkCycle 报文接收模块调用周期,单位是ms
 * @warning None
 *
 * 示例
 @code
     CanFDMSg_XMS_Analysis(&CAN_CH0_CanMsgOp,5u);
 @endcode
 *
 * @since 1.0.0
 */
void CanFDMSg_XMS_Analysis(st_CanFDMsgOp *CanRXMsgOp, canfdlib_uint16_t CbkCycle)
{
    canfdlib_uint16_t i;
    canfdlib_uint8_t  j;
    if ( (CanRXMsgOp->u8CAN_RX_ENABLE & 0x7fu) == 0x00u )
    {
        for ( i = 0U; i < CanRXMsgOp->Total_Msg; i++ )
        {
            if ( CanRXMsgOp->CAN_MSG_Analysis [ i ].CAN_Received == 1u )
            {
                CanRXMsgOp->CAN_MSG_Analysis [ i ].CAN_Busy = 1U;
                for ( j = 0U; j < 64U; j++ )
                {
                    CanRXMsgOp->CAN_MSG_Analysis [ i ].AnalyzeMsg [ j ] = CanRXMsgOp->CAN_MSG_Analysis [ i ].ReceiveBuf [ j ];
                }
                CanRXMsgOp->CAN_MSG_Analysis [ i ].CAN_Busy     = 0U;
                CanRXMsgOp->CAN_MSG_Analysis [ i ].CAN_Received = 0U;
                CanRXMsgOp->CAN_MSG_Analysis [ i ].CAN_Lost     = 0U;
                CanRXMsgOp->CAN_MSG_Analysis [ i ].CAN_Status   = 0U;

                if ( CanRXMsgOp->pAttrubute [ i ].Msg_ProcessCBK != (( void * )0) )
                {
                    CanRXMsgOp->pAttrubute [ i ].Msg_ProcessCBK(CanRXMsgOp->CAN_MSG_Analysis [ i ].AnalyzeMsg);
                }
            }

            if ( (CanRXMsgOp->CAN_MSG_Analysis [ i ].CAN_Lost >= CanRXMsgOp->pAttrubute [ i ].MSG_TimeOut_Val) && (CanRXMsgOp->CAN_MSG_Analysis [ i ].CAN_Status != 0x55U) )
            {
                CanRXMsgOp->CAN_MSG_Analysis [ i ].CAN_Status = 0x55U;
                for ( j = 0U; j < 64U; j++ )
                {
                    CanRXMsgOp->CAN_MSG_Analysis [ i ].AnalyzeMsg [ j ] &= CanRXMsgOp->pAttrubute [ i ].Mask_Array [ j ];
                    CanRXMsgOp->CAN_MSG_Analysis [ i ].AnalyzeMsg [ j ] |= CanRXMsgOp->pAttrubute [ i ].TimeOut_Array [ j ];
                }
                if ( CanRXMsgOp->pAttrubute [ i ].Msg_LostCBK != (( void * )0) )
                {
                    CanRXMsgOp->pAttrubute [ i ].Msg_LostCBK(CanRXMsgOp->CAN_MSG_Analysis [ i ].AnalyzeMsg);
                }
            }
            else
            {
                if ( CanRXMsgOp->CAN_MSG_Analysis [ i ].CAN_Lost < CanRXMsgOp->pAttrubute [ i ].MSG_TimeOut_Val )
                {
                    CanRXMsgOp->CAN_MSG_Analysis [ i ].CAN_Lost += CbkCycle;
                }
            }
        }
    }
}
/**
 * @brief CAN报文接收函数,放在接收中断内
 * @param[in] CanRXMsgOp 报文接收操作对象指针, 每路can都应有独立的结构体指针
 * @param[in] MsgID 报文索引序号,非ID,配合ID转换函数使用.
 * @param[in] m_DLC 报文长度,默认填64
 * @param[in] Msg 报文数据buffer.
 * @warning 不可直接传入ID.
 *
 * 示例
 @code
    Co_CanFD_Buff_Set(&CAN_CH0_CanMsgOp,Co_Can_ConvertSubID_CAN_CH0(m_id), m_dlc, m_Msg);
 @endcode
 *
 * @since 1.0.0
 */
void Co_CanFD_Buff_Set(st_CanFDMsgOp *CanRXMsgOp, canfdlib_uint16_t MsgID, canfdlib_uint8_t m_DLC, canfdlib_uint8_t Msg [])
{
    canfdlib_uint8_t  i;
    canfdlib_uint16_t u16ConverIdx;
    u16ConverIdx = MsgID;
    if ( u16ConverIdx < CanRXMsgOp->Total_Msg )
    {
        if ( CanRXMsgOp->CAN_MSG_Analysis [ u16ConverIdx ].CAN_Busy == 0u )
        {
            for ( i = 0U; i < 64U; i++ )
            {
                CanRXMsgOp->CAN_MSG_Analysis [ u16ConverIdx ].ReceiveBuf [ i ] = Msg [ i ];
            }
            CanRXMsgOp->CAN_MSG_Analysis [ u16ConverIdx ].CAN_Received = 1U;
            if ( CanRXMsgOp->pAttrubute [ u16ConverIdx ].Msg_ReceiveCBK != (( void * )0) )
            {
                CanRXMsgOp->pAttrubute [ u16ConverIdx ].Msg_ReceiveCBK(CanRXMsgOp->CAN_MSG_Analysis [ u16ConverIdx ].ReceiveBuf);
            }
        }
    }
}
/**
 * @brief CAN报文buffer数据读取
 * @param[in] CanRXMsgOp 报文接收操作对象指针, 每路can都应有独立的结构体指针
 * @param[in] MsgIdx 报文索引序号,非ID,使用枚举的内容.
 * @param[in] BuffIdx 报文数组索引0-64
 * @warning 内部使用,外部不使用
 *
 * 示例
 @code
    canfdlib_uint8_t Ret = CANFD_MSG_Read(&CAN_CH0_CanMsgOp , 10u, 5u);
 @endcode
 *
 * @since 1.0.0
 */
canfdlib_uint8_t CANFD_MSG_Read(st_CanFDMsgOp *CanRXMsgOp, canfdlib_uint16_t MsgIdx, canfdlib_uint8_t BuffIdx)
{
    canfdlib_uint8_t ret = 0U;
    if ( MsgIdx < CanRXMsgOp->Total_Msg )
    {
        if ( BuffIdx < 64u )
        {
            ret = CanRXMsgOp->CAN_MSG_Analysis [ MsgIdx ].AnalyzeMsg [ BuffIdx ];
        }
        else
        {
            ret = 0U;
        }
    }
    else
    {
        ret = 0U;
    }
    return ret;
}
/**
 * @brief CAN报文ID当前状态读取
 * @param[in] CanRXMsgOp 报文接收操作对象指针, 每路can都应有独立的结构体指针
 * @param[in] MsgID 报文索引序号,非ID,使用枚举的内容.
 * @return  当前报文状态
 * - 0x00 报文在线
 * - 0x55 报文掉线
 * @warning None
 *
 * 示例
 @code
    canfdlib_uint8_t Ret = CANFD_MSG_Status(&CAN_CH0_CanMsgOp , 3u);
 @endcode
 *
 * @since 1.0.0
 */
canfdlib_uint8_t CANFD_MSG_Status(st_CanFDMsgOp *CanRXMsgOp, canfdlib_uint16_t MsgID)
{
    canfdlib_uint8_t ret;
    if ( MsgID < CanRXMsgOp->Total_Msg )
    {
        ret = ( canfdlib_uint8_t )CanRXMsgOp->CAN_MSG_Analysis [ MsgID ].CAN_Status;
    }
    else
    {
        ret = 0U;
    }
    return ret;
}
/**
 * @brief CAN报文接收模块复位所有掉线时间,重新计时
 * @param[in] CanRXMsgOp 报文接收操作对象指针, 每路can都应有独立的结构体指针
 * @warning None
 *
 * 示例
 @code
    CanFD_RX_ResetAllTimer(&CAN_CH0_CanMsgOp);
 @endcode
 *
 * @since 1.0.0
 */
void CanFD_RX_ResetAllTimer(st_CanFDMsgOp *CanRXMsgOp)
{
    canfdlib_uint16_t i;

    for ( i = 0U; i < CanRXMsgOp->Total_Msg; i++ )
    {
        CanRXMsgOp->CAN_MSG_Analysis [ i ].CAN_Lost = 0U;
    }
}
/**
 * @brief CAN报文接收模块复位所有掉线时间,重新计时
 * @param[in] CanRXMsgOp 报文接收操作对象指针, 每路can都应有独立的结构体指针
 * @param[in] idx  报文索引序号,非ID,使用枚举的内容.
 * @warning None
 *
 * 示例
 @code
    CanFD_RX_ResetTimer(&CAN_CH0_CanMsgOp,9u);
 @endcode
 *
 * @since 1.0.0
 */
void CanFD_RX_ResetTimer(st_CanFDMsgOp *CanRXMsgOp, canfdlib_uint16_t idx)
{
    if ( idx < CanRXMsgOp->Total_Msg )
    {
        CanRXMsgOp->CAN_MSG_Analysis [ idx ].CAN_Lost = 0U;
    }
}
/**
 * @brief CAN报文接收模块,诊断控制
 * @param[in] CanRXMsgOp 报文接收操作对象指针, 每路can都应有独立的结构体指针
 * @param[in] RX_enable  模块控制状态
 * - 0x00 报文接收使能
 * - 0x55 报文接收关闭
 * @warning None
 *
 * 示例
 @code
    CANFD_RX_DiagCtrlEnable(&CAN_CH0_CanMsgOp,0x00u);
 @endcode
 *
 * @since 1.0.0
 */
void CANFD_RX_DiagCtrlEnable(st_CanFDMsgOp *CanRXMsgOp, CANFD_RX_Status_t RX_enable)
{
    CanRXMsgOp->u8CAN_RX_ENABLE = ( canfdlib_uint8_t )RX_enable;
    CanRXMsgOp->u8CAN_RX_ENABLE |= 0x80U;
}
/**
 * @brief CAN报文接收模块,诊断控制释放
 * @param[in] CanRXMsgOp 报文接收操作对象指针, 每路can都应有独立的结构体指针
 * @warning None
 *
 * 示例
 @code
    CANFD_RX_DiagCtrlRelease(&CAN_CH0_CanMsgOp);
 @endcode
 *
 * @since 1.0.0
 */
void CANFD_RX_DiagCtrlRelease(st_CanFDMsgOp *CanRXMsgOp)
{
    CanRXMsgOp->u8CAN_RX_ENABLE &= ~(0x01u << 7);
}
/**
 * @brief CAN报文接收模块版本读取
 * @warning None
 *
 * 示例
 @code
   canfdlib_uint32_t Ver = Read_CANFD_RX_Version();
 @endcode
 *
 * @since 1.0.0
 */
canfdlib_uint32_t Read_CANFD_RX_Version(void)
{
    return 0x0105UL;
}

/**
 * @brief CAN报文接收模块报文掉线时间戳
 * @warning None
 *
 * 示例
 @code
   canfdlib_uint32_t CAN_ID_030 = CANFD_RX_Get_TimeStamp(&CAN_CH0_CanMsgOp,3);
 @endcode
 *
 * @since 1.0.1
 */
canfdlib_uint32_t CANFD_RX_Get_TimeStamp(st_CanFDMsgOp *CanRXMsgOp, canfdlib_uint16_t MsgIdx)
{
    canfdlib_uint32_t Ret = 0UL;
    Ret          = CanRXMsgOp->CAN_MSG_Analysis [ MsgIdx ].CAN_Lost;
    return Ret;
}
