

#ifndef CRC_PRV_RH850_HW_H
#define CRC_PRV_RH850_HW_H

/*
**********************************************************************************************************************
* Includes
**********************************************************************************************************************
*/
#include "Crc_Cfg.h"

/*
**********************************************************************************************************************
* Defines/Macros
**********************************************************************************************************************
*/

#define CRC_GENFUNC_CCITT16   (1U)  // 16 bit CCITT CRC polynomial is used

#include "Os.h"
#if (OS_NUM_CORES == 1U)
#define Crc_GetCoreId()        (0U)
#else
#define Crc_GetCoreId()       GetCoreID()
#endif
#if(1U == CRC_HW_RH850_R1X)
/* configuration of the CRC generation process */
// Bitmask for CRC variant    : DCRBnPOL = DCRBnCTL[0]
#define CRC_HW_8B_ETHERNET32    (0x04U)    // 8 bit input width, 32-bit Ethernet CRC polynomial
#define CRC_HW_8B_CCITT16       (0x05U)    // 8 bit input width, 16-bit CCITT CRC polynomial
#define CRC_HW_16B_CCITT16      (0x11U)    // 16 bit input width, 16-bit CCITT CRC polynomial
#define CRC_HW_DCRBNPOL_BITMASK (0x01U)
#endif
#if(1U == CRC_HW_RH850_P1X)
/* configuration of the CRC generation process:
 * CRC input width: DCRBnISZ = DCRBnCTL[5:4] => 0x2 (8 bit)
 * CRC variant    : DCRBnPOL = DCRBnCTL[1:0]
 */
#define CRC_HW_8B_ETHERNET32    (0x20U)    // 8 bit input width, 32-bit Ethernet CRC polynomial
#define CRC_HW_8B_CCITT16       (0x21U)    // 8 bit input width, 16-bit CCITT CRC polynomial
#define CRC_HW_16B_CCITT16      (0x11U)    // 16 bit input width, 16-bit CCITT CRC polynomial
#define CRC_HW_8B_SAE8          (0x22U)    // 8 bit input width, 8-bit SAE J1850 CRC polynomial
#define CRC_HW_8B_2F8           (0x23U)    // 8 bit input width, 8-bit 0x2F CRC polynomial
#define CRC_HW_DCRBNPOL_BITMASK (0x03U)
#endif

#if((CRC_HW_RH850_R1X == 1U) || (CRC_HW_RH850_P1X == 1U))
/* macros to channel the hardware information */
#define CRC_CFG(channel)  (CrcRegs[(channel)]->crcctl)
#define CRC_INP(channel)  (CrcRegs[(channel)]->crcin)
#define CRC_OUT(channel)  (CrcRegs[(channel)]->crcout)

typedef struct
{
    const uint8* crc8bitDataPtr;
    const uint16* crc16bitDataPtr;
    uint32 crcLength;
} Crc_DataInfoType;

/**
 **********************************************************************************************************************
 * \brief Calculates a CRC given by the crcConfig using the Data CRC Function of the Renesas microcontroller
 *
 * \param    crcConfig       configuration of the crc channel
 * \param    crcChannel      channel of the crc calculation
 * \param    crcDataPtr      holds a pointer to the start address of the data block to be calculated
 * \param    crcLength       length of data block to be calculated in bytes
 * \param    crcStartValue   start value when the algorithm starts
 *
 * \return   8 bit result of CRC calculation
 **********************************************************************************************************************
*/
CRC_INLINE uint32 Crc_Prv_CalcCRC_RH850_Hw(uint8 crcConfig, uint8 crcChannel, const Crc_DataInfoType *InfoPtr,
                                           uint32 crcStartValue)
{
    uint32 i;
    uint32 save_cout;
    uint32 result;
    uint8  save_ctl;

    /* save register context */
    save_ctl = CRC_CFG(crcChannel);
    save_cout = CRC_OUT(crcChannel);
    //If polynomial of interrupted calculation was not CCITT16 - regardless of DCRBnISZ setting.
    if ((CRC_GENFUNC_CCITT16) != (save_ctl & CRC_HW_DCRBNPOL_BITMASK))
    {
       // XOR operation done by hardware needs to be reversed - but NOT for any CCITT16 computation
       save_cout ^= CRC_XOR_VALUE32;
    }

    /* configure CRC generation process and execute it */
    CRC_CFG(crcChannel) = crcConfig;
    CRC_OUT(crcChannel) = crcStartValue;

    if(crcConfig != CRC_HW_16B_CCITT16)
    {
        for (i = 0; i < InfoPtr->crcLength; i++)
        {
            CRC_INP(crcChannel) = InfoPtr->crc8bitDataPtr[i];
        }
    }
    else
    {
        for (i = 0; i < InfoPtr->crcLength; i++)
        {
            CRC_INP(crcChannel) = InfoPtr->crc16bitDataPtr[i];
        }
    }

    result = CRC_OUT(crcChannel);

    /* restore register context */
    CRC_CFG(crcChannel) = save_ctl;
    CRC_OUT(crcChannel) = save_cout;

    return result;
}

/**
 **********************************************************************************************************************
 * \brief Calculates a 8 bit SAE J1850 CRC using the Data CRC Function of the Renesas microcontroller
 *
 * \param    Crc_DataPtr         holds a pointer to the start address of the data block to be calculated
 * \param    Crc_Length_u32      length of data block to be calculated in bytes
 * \param    Crc_StartValue      start value when the algorithm starts
 *
 * \return   8 bit result of CRC calculation
 **********************************************************************************************************************
*/
CRC_INLINE uint8 Crc_Prv_CalcCRC8H2F_Hw(const uint8* Crc_DataPtr,
                                          uint32 Crc_Length_u32, uint8 Crc_StartValue)
{
    Crc_DataInfoType Info;

    Info.crc8bitDataPtr = Crc_DataPtr;
    Info.crcLength = Crc_Length_u32;
     return (uint8)Crc_Prv_CalcCRC_RH850_Hw(CRC_HW_8B_2F8,Crc_Core_2_CrcHWTable[Crc_GetCoreId()].Crc8H2F_HW,
             &Info, Crc_StartValue);
}

/**
 **********************************************************************************************************************
 * \brief Calculates a 8 bit SAE J1850 CRC using the Data CRC Function of the Renesas microcontroller
 *
 * \param    Crc_DataPtr         holds a pointer to the start address of the data block to be calculated
 * \param    Crc_Length_u32      length of data block to be calculated in bytes
 * \param    Crc_StartValue      start value when the algorithm starts
 *
 * \return   8 bit result of CRC calculation
 **********************************************************************************************************************
*/
CRC_INLINE uint8 Crc_Prv_CalcCRC8_Hw(const uint8* Crc_DataPtr,
                                           uint32 Crc_Length_u32, uint8 Crc_StartValue)
{
    Crc_DataInfoType Info;

    Info.crc8bitDataPtr = Crc_DataPtr;
    Info.crcLength = Crc_Length_u32;
    return (uint8)Crc_Prv_CalcCRC_RH850_Hw(CRC_HW_8B_SAE8, Crc_Core_2_CrcHWTable[Crc_GetCoreId()].Crc8_HW,
                                                &Info, Crc_StartValue);
}

/**
 **********************************************************************************************************************
 * \brief Calculates a 16 bit CCITT CRC using the Data CRC Function of the Renesas microcontroller
 *
 * \param    Crc_DataPtr         holds a pointer to the start address of the data block to be calculated
 * \param    Crc_Length_u32      length of data block to be calculated in bytes
 * \param    Crc_StartValue_u32  start value when the algorithm starts
 *
 * \return   16 bit result of CRC calculation
 **********************************************************************************************************************
*/
CRC_INLINE uint16 Crc_Prv_CalcCRC16_Hw(const uint8* Crc_DataPtr,
                                              uint32 Crc_Length_u32, uint16 Crc_StartValue_u16)
{
    Crc_DataInfoType Info;

    Info.crc8bitDataPtr = Crc_DataPtr;
    Info.crcLength = Crc_Length_u32;
    return (uint16)Crc_Prv_CalcCRC_RH850_Hw(CRC_HW_8B_CCITT16, Crc_Core_2_CrcHWTable[Crc_GetCoreId()].Crc16_HW,
                                                &Info, Crc_StartValue_u16);
}

/**
 **********************************************************************************************************************
 * \brief Calculates a 16 bit CCITT CRC using the Data CRC Function of the Renesas microcontroller
 *
 * \param    Crc_DataPtr         holds a pointer to the start address of the data block to be calculated
 * \param    Crc_Length_u32      length of data block to be calculated in bytes
 * \param    Crc_StartValue_u32  start value when the algorithm starts
 *
 * \return   16 bit result of CRC calculation
 **********************************************************************************************************************
*/
CRC_INLINE uint16 Crc_Prv_CalcCRC16_Hw16(const uint16* Crc_DataPtr,
                                              uint32 Crc_Length_u32, uint16 Crc_StartValue_u16)
{
    Crc_DataInfoType Info;

    Info.crc16bitDataPtr = Crc_DataPtr;
    Info.crcLength = Crc_Length_u32;
    return (uint16)Crc_Prv_CalcCRC_RH850_Hw(CRC_HW_16B_CCITT16, Crc_Core_2_CrcHWTable[Crc_GetCoreId()].Crc16_HW,
                                                &Info, Crc_StartValue_u16);
}

/**
 **********************************************************************************************************************
 * \brief Calculates a 32 bit Ethernet CRC using the Data CRC Function of the Renesas microcontroller
 *
 * \param    Crc_DataPtr         holds a pointer to the start address of the data block to be calculated
 * \param    Crc_Length_u32      length of data block to be calculated in bytes
 * \param    Crc_StartValue_u32  start value when the algorithm starts
 *
 * \return   32 bit result of CRC calculation
 **********************************************************************************************************************
*/
CRC_INLINE uint32 Crc_Prv_CalcCRC32_Hw(const uint8* Crc_DataPtr,
                                                     uint32 Crc_Length_u32, uint32 Crc_StartValue_u32)
{
    Crc_DataInfoType Info;

    Info.crc8bitDataPtr = Crc_DataPtr;
    Info.crcLength = Crc_Length_u32;
    return Crc_Prv_CalcCRC_RH850_Hw(CRC_HW_8B_ETHERNET32, Crc_Core_2_CrcHWTable[Crc_GetCoreId()].Crc32_HW,
	                                    &Info, Crc_StartValue_u32);
}
#endif
#endif/* CRC_PRV_RH850_HW_H */
