

#ifndef CRC_PRV_IFX_HW_H
#define CRC_PRV_IFX_HW_H

/*
**********************************************************************************************************************
* Includes
**********************************************************************************************************************
*/

#include "Mcu.h"
#include "rba_BswSrv.h"
#include RBA_REG_FCE_H

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

/* mapping of autosar core numbers (logical) to ifx core numbers (physical) */
#define CRC_PRV_IFX_CORE_0        (0U)  /* BSW : phys. 0, log. 0 */
#define CRC_PRV_IFX_CORE_1        (1U) /* ASW + Lockstep Code : phys. 0, log. 1 */
#define CRC_PRV_IFX_CORE_2        (2U) /* ASW : phys. 2 log. 2 */

#define CRC_PRV_IFX_CFG(X)          ((*(X)).CFG)    /* Macro for the configuration register of the FCE engine */
#define CRC_PRV_IFX_INP(X)          ((*(X)).IR)     /* Macro for the input register of the FCE engine */
#define CRC_PRV_IFX_INTRES(X)       ((*(X)).CRC)    /* Macro for the interium result register of the FCE engine */
#define CRC_PRV_IFX_RES(X)          ((*(X)).RES)    /* Macro for the result register of the FCE engine */


typedef rba_Reg_FCE_Input_CRC_tst Crc_HwReg_tst;

/*
 **********************************************************************************************************************
 * Crc_Prv_DetectCrcEngineToUse_Hw
 *
 * \brief checks which of the two Ifx Crc engines shall be used
 *
 * A-periodical: General function can be called by the Start-Function.
 *
 * \return   rba_Reg_FCE_Input_CRC_tst*     address of the crc engine
 **********************************************************************************************************************
 */
CRC_INLINE rba_Reg_FCE_Input_CRC_tst* Crc_Prv_DetectCrcEngineToUse_Hw(void)
{
    rba_Reg_FCE_Input_CRC_tst *Crc_Prv_Engine_u32;

    /* the core to crc hardware assignment is configurable */
    /* default configuration : */
    /* BSW core gets always crc engine 0, ASW core gets always crc engine 1 */

    /* read number of crc engine in CrcHWTable */
    Crc_Prv_Engine_u32 = (&(FCE.CRC[Crc_Core_2_CrcHWTable[rba_BswSrv_GetPhysCore()].Crc32_HW]));

    return (Crc_Prv_Engine_u32);
}

/*
 **********************************************************************************************************************
 * Crc_Prv_GetRegisterValues_Hw
 *
 * \brief stores the the data of the registers of the flexible Crc Engine into registerValues_au32:
 *
 * [0]: data of the configuration register.
 * [1]: data of the input register.
 **********************************************************************************************************************
 */
CRC_INLINE void Crc_Prv_GetRegisterValues_Hw(uint32* registerValues_au32, const rba_Reg_FCE_Input_CRC_tst* const Crc_Address_s_ptr)
{
    /*
     ******************************************************************************************
     * Saving the registers of the crc engine. This is important if a task, currently
     * using the crc calculation is interrupted by another task. If the interrupting task
     * also executes the crc calculation, the data on the registers in manipulated.
     * This is why the registers must be set back to the original state (with original data).
     * Here the original data is loaded from the register.
     ******************************************************************************************
     */
     registerValues_au32[0] = CRC_PRV_IFX_INP(Crc_Address_s_ptr);
     registerValues_au32[1] = CRC_PRV_IFX_INTRES(Crc_Address_s_ptr);
}

/*
 **********************************************************************************************************************
 * Crc_Prv_SetRegisterValues_Hw
 *
 * \brief restores the the data of the registers of the flexible Crc Engine with the data stored in registerValues_au32:
 *
 * [0]: data of the configuration register.
 * [1]: data of the input register.
 **********************************************************************************************************************
 */
CRC_INLINE void Crc_Prv_SetRegisterValues_Hw(const uint32* const registerValues_au32, rba_Reg_FCE_Input_CRC_tst * Crc_Address_s_ptr )
{
    /*
     ******************************************************************************************
     * Restoring the registers of the crc engine. This is important if a task, currently
     * using the crc calculation is interrupted by another task. If the interrupting task
     * also executes the crc calculation, the data on the registers in manipulated.
     * This is why the registers must be set back to the original state (with original data).
     * Here the registers are set back to the original state.
     ******************************************************************************************
     */
    CRC_PRV_IFX_INP(Crc_Address_s_ptr)  = registerValues_au32[0];
    CRC_PRV_IFX_INTRES(Crc_Address_s_ptr) = registerValues_au32[1];
}

/*
 **********************************************************************************************************************
 * Crc_Prv_Config_Hw
 *
 * \brief sets the configuration and the status register of the crc engine for the crc32 calculation.
 * Also the CRC calculation registers on IFX are enabled.
 *
 * A-periodical: General function can be called by the Start-Function.
 *
 * \param    rba_Reg_FCE_Input_CRC_tst* Crc_Address_s_ptr,    address of the crc engine
 **********************************************************************************************************************
 */
CRC_INLINE void Crc_Prv_Config_Hw(rba_Reg_FCE_Input_CRC_tst *Crc_Address_s_ptr)
{
    /*
     *****************************************************************************************************************
     * Enables the CRC calculation-registers on IFX. There is an if-condition before setting the bit.
     * This is because the setting of the bit requires to go into the init-phase and to leave it again after
     * setting the bit. The switching of the phases is more time consuming than one if-condition. In the functions
     * (switching phases) there are if-conditions used as well as additional operations. The following condition,
     * makes the whole procedure (switching phases and setting the bit) just must run once.
     *****************************************************************************************************************
     */
    if(FCE.CLC != 0U)
    {
    	Mcu_Rb_ResetEndInit();
        FCE.CLC = 0U;
        Mcu_Rb_SetEndInit();
    }

    /* Sets the interim result back to zero in the CRC register of IFX */
    CRC_PRV_IFX_INTRES(Crc_Address_s_ptr) = (0U);

    /* The configuration is not set anymore because it already uses the proper configuration by default.
     * This configuration is not allowed to be changed. */
}

/*
 **********************************************************************************************************************
 * Crc_Prv_CalculateCrc_Hw
 *
 * \brief sets the input register of the crc engine to start the crc calculation
 *
 * Periodical: General function can be called by the Update-Function.
 *
 * \param    uint32 const*    Crc_data_u32,        input data for the crc calculation
 * \param    rba_Reg_FCE_Input_CRC_tst* Crc_Address_s_ptr,   address of the crc engine
 **********************************************************************************************************************
 */
CRC_INLINE void Crc_Prv_CalculateCrc_Hw(uint32 const* Crc_data_u32, rba_Reg_FCE_Input_CRC_tst *Crc_Address_s_ptr)
{
    CRC_PRV_IFX_INP(Crc_Address_s_ptr) = ((*Crc_data_u32));
}

/*
 **********************************************************************************************************************
 * Crc_Prv_Result_Hw
 *
 * \brief returns the result of the crc calculation (RES register)
 *
 * A-Peridoical: General function  Result_Prv_Crc_Hw can be called by the finish-function
 *
 * \param    rba_Reg_FCE_Input_CRC_tst const* Crc_Address_s_ptr,   address of the crc engine
 * \return   uint32                                      result of crc calculation
 **********************************************************************************************************************
 */
CRC_INLINE uint32 Crc_Prv_Result_Hw(rba_Reg_FCE_Input_CRC_tst const* Crc_Address_s_ptr)
{
    return CRC_PRV_IFX_RES(Crc_Address_s_ptr);
}

#endif /* CRC_PRV_IFX_HW_H */
