/*==================================================================================================
*   Project              : RTD AUTOSAR 4.4
*   Platform             : CORTEXM
*   Peripheral           : LPUART
*   Dependencies         : none
*
*   Autosar Version      : 4.4.0
*   Autosar Revision     : ASR_REL_4_4_REV_0000
*   Autosar Conf.Variant :
*   SW Version           : 0.9.0
*   Build Version        : S32K3_RTD_0_9_0__ASR_REL_4_4_REV_0000_20210326
*
*   (c) Copyright 2020 - 2021 NXP Semiconductors
*   All Rights Reserved.
*
*   NXP Confidential. This software is owned or controlled by NXP and may only be
*   used strictly in accordance with the applicable license terms. By expressly
*   accepting such terms or by downloading, installing, activating and/or otherwise
*   using the software, you are agreeing that you have read, and that you agree to
*   comply with and are bound by, such license terms. If you do not agree to be
*   bound by the applicable license terms, then you may not retain, install,
*   activate or otherwise use the software.
==================================================================================================*/

/**
*   @file   Lpuart_Lin_Ip_Hw_Access.c
*
*   @addtogroup LPUART_LIN_IP
*   @{
*/

#ifdef __cplusplus
extern "C"{
#endif

/*==================================================================================================
*                                          INCLUDE FILES
* 1) system and project includes
* 2) needed interfaces from external units
* 3) internal and external interfaces from this unit
==================================================================================================*/

#include "Lpuart_Lin_Ip_Hw_Access.h"

/*==================================================================================================
*                                 SOURCE FILE VERSION INFORMATION
==================================================================================================*/
#define LPUART_LIN_IP_HW_ACCESS_VENDOR_ID_C                      43
#define LPUART_LIN_IP_HW_ACCESS_AR_RELEASE_MAJOR_VERSION_C       4
#define LPUART_LIN_IP_HW_ACCESS_AR_RELEASE_MINOR_VERSION_C       4
#define LPUART_LIN_IP_HW_ACCESS_AR_RELEASE_REVISION_VERSION_C    0
#define LPUART_LIN_IP_HW_ACCESS_SW_MAJOR_VERSION_C               0
#define LPUART_LIN_IP_HW_ACCESS_SW_MINOR_VERSION_C               9
#define LPUART_LIN_IP_HW_ACCESS_SW_PATCH_VERSION_C               0

/*==================================================================================================
*                                       FILE VERSION CHECKS
==================================================================================================*/
#if (LPUART_LIN_IP_HW_ACCESS_VENDOR_ID_C != LPUART_LIN_IP_HW_ACCESS_VENDOR_ID)
    #error "Lpuart_Lin_Ip_Hw_Access.c and Lpuart_Lin_Ip_Hw_Access.h have different vendor ids"
#endif
/* Check if current file and Lpuart_Lin_Ip_Hw_Access header file are of the same Autosar version */
#if ((LPUART_LIN_IP_HW_ACCESS_AR_RELEASE_MAJOR_VERSION_C != LPUART_LIN_IP_HW_ACCESS_AR_RELEASE_MAJOR_VERSION) || \
     (LPUART_LIN_IP_HW_ACCESS_AR_RELEASE_MINOR_VERSION_C != LPUART_LIN_IP_HW_ACCESS_AR_RELEASE_MINOR_VERSION) || \
     (LPUART_LIN_IP_HW_ACCESS_AR_RELEASE_REVISION_VERSION_C != LPUART_LIN_IP_HW_ACCESS_AR_RELEASE_REVISION_VERSION) )
    #error "Software Version Numbers of Lpuart_Lin_Ip_Hw_Access.c and Lpuart_Lin_Ip_Hw_Access.h are different"
#endif
/* Check if current file and Lpuart_Lin_Ip_Hw_Access header file are of the same Software version */
#if ((LPUART_LIN_IP_HW_ACCESS_SW_MAJOR_VERSION_C != LPUART_LIN_IP_HW_ACCESS_SW_MAJOR_VERSION) || \
     (LPUART_LIN_IP_HW_ACCESS_SW_MINOR_VERSION_C != LPUART_LIN_IP_HW_ACCESS_SW_MINOR_VERSION) || \
     (LPUART_LIN_IP_HW_ACCESS_SW_PATCH_VERSION_C != LPUART_LIN_IP_HW_ACCESS_SW_PATCH_VERSION) )
    #error "Software Version Numbers of Lpuart_Lin_Ip_Hw_Access.c and Lpuart_Lin_Ip_Hw_Access.h are different"
#endif

/*==================================================================================================
*                           LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS)
==================================================================================================*/

/*==================================================================================================
*                                          LOCAL MACROS
==================================================================================================*/

/*==================================================================================================
*                                         LOCAL CONSTANTS
==================================================================================================*/

/*==================================================================================================
*                                         LOCAL VARIABLES
==================================================================================================*/

/*==================================================================================================
*                                        GLOBAL CONSTANTS
==================================================================================================*/

/*==================================================================================================
*                                        GLOBAL VARIABLES
==================================================================================================*/

/*==================================================================================================
*                                    LOCAL FUNCTION PROTOTYPES
==================================================================================================*/

/*==================================================================================================
*                                         LOCAL FUNCTIONS
==================================================================================================*/

/*==================================================================================================
*                                        GLOBAL FUNCTIONS
==================================================================================================*/
#define LIN_START_SEC_CODE
#include "Lin_MemMap.h"

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Lin_Ip_HwInit
 * Description   : Initializes the LPUART controller to known state, using
 *                 register reset values defined in the reference manual.
 *END**************************************************************************/
void Lpuart_Lin_Ip_HwInit(LPUART_Type * base)
{
    /* Set the default oversampling ratio (16) and baud-rate divider (4) */
    base->BAUD = ((uint32)((LPUART_LIN_IP_DEFAULT_OSR << LPUART_BAUD_OSR_SHIFT) | \
                 (LPUART_LIN_IP_DEFAULT_SBR << LPUART_BAUD_SBR_SHIFT)));
    /* Clear the error/interrupt flags */
    base->STAT = LPUART_LIN_IP_STAT_REG_FLAGS_MASK;
    /* Reset all features/interrupts by default */
    base->CTRL = 0x00000000;
    /* Reset match addresses */
    base->MATCH = 0x00000000;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Lin_Ip_HwSetBitCountPerChar
 * Description   : Configures the number of bits per char in LPUART controller.
 * In some LPUART instances, the user should disable the transmitter/receiver
 * before calling this function.
 * Generally, this may be applied to all LPUARTs to ensure safe operation.
 *END**************************************************************************/
void Lpuart_Lin_Ip_HwSetBitCountPerChar(LPUART_Type * base, Lpuart_Lin_Ip_BitCountPerCharType bitCountPerChar, boolean parity)
{
    uint32 tmpBitCountPerChar = (uint32)bitCountPerChar;
    if (parity)
    {
        tmpBitCountPerChar += 1U;
    }

    if (tmpBitCountPerChar == (uint32)LPUART_LIN_IP_10_BITS_PER_CHAR)
    {
        base->BAUD = (base->BAUD & ~LPUART_BAUD_M10_MASK) | ((uint32)1U << LPUART_BAUD_M10_SHIFT);
    }
    else
    {
        /* config 8-bit (M=0) or 9-bits (M=1) */
        base->CTRL = (base->CTRL & ~LPUART_CTRL_M_MASK) | (tmpBitCountPerChar << LPUART_CTRL_M_SHIFT);
        /* clear M10 to make sure not 10-bit mode */
        base->BAUD &= ~LPUART_BAUD_M10_MASK;
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Lin_Ip_HwSetParityMode
 * Description   : Configures parity mode in the LPUART controller.
 * In some LPUART instances, the user should disable the transmitter/receiver
 * before calling this function.
 * Generally, this may be applied to all LPUARTs to ensure safe operation.
 *END**************************************************************************/
void Lpuart_Lin_Ip_HwSetParityMode(LPUART_Type * base, Lpuart_Lin_Ip_ParityModeType parityModeType)
{
    base->CTRL = (base->CTRL & ~LPUART_CTRL_PE_MASK) | (((uint32)parityModeType >> 1U) << LPUART_CTRL_PE_SHIFT);
    base->CTRL = (base->CTRL & ~LPUART_CTRL_PT_MASK) | (((uint32)parityModeType & 1U) << LPUART_CTRL_PT_SHIFT);
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Lin_Ip_HwSetIntMode
 * Description   : Configures the LPUART module interrupts to enable/disable
 * various interrupt sources.
 *END**************************************************************************/
void Lpuart_Lin_Ip_HwSetIntMode(LPUART_Type * base, Lpuart_Lin_Ip_InterruptType intSrc, boolean enable)
{
    uint32 reg = (uint32)(intSrc) >> LPUART_LIN_IP_SHIFT;
    uint32 intRegOffset = (uint16)(intSrc);

    SchM_Enter_Lin_LIN_EXCLUSIVE_AREA_03();
    {
        switch (reg)
        {
            case LPUART_LIN_IP_BAUD_REG_ID:
                base->BAUD = (base->BAUD & ~(1UL << intRegOffset)) | ((enable ? 1U : 0U) << intRegOffset);
                break;
            case LPUART_LIN_IP_CTRL_REG_ID:
                base->CTRL = (base->CTRL & ~(1UL << intRegOffset)) | ((enable ? 1U : 0U) << intRegOffset);
                break;
            default :
                /* Invalid parameter: return */
                break;
        }
    }
    SchM_Exit_Lin_LIN_EXCLUSIVE_AREA_03();
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Lin_Ip_HwGetIntMode
 * Description   : Returns whether LPUART module interrupt is enabled/disabled.
 *END**************************************************************************/
boolean Lpuart_Lin_Ip_HwGetIntMode(const LPUART_Type * base, Lpuart_Lin_Ip_InterruptType intSrc)
{
    uint32 reg = (uint32)(intSrc) >> LPUART_LIN_IP_SHIFT;
    boolean retVal = FALSE;

    switch ( reg )
    {
        case LPUART_LIN_IP_BAUD_REG_ID:
            retVal = (((base->BAUD >> (uint16)(intSrc)) & 1U) > 0U);
            break;
        case LPUART_LIN_IP_CTRL_REG_ID:
            retVal = (((base->CTRL >> (uint16)(intSrc)) & 1U) > 0U);
            break;
        default :
            /* Invalid parameter: return */
            break;
    }

    return retVal;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Lin_Ip_HwGetStatusFlag
 * Description   : LPUART get status flag by passing flag enum.
 *END**************************************************************************/
boolean Lpuart_Lin_Ip_HwGetStatusFlag(const LPUART_Type * base, Lpuart_Lin_Ip_StatusFlagType statusFlag)
{
    uint32 reg = (uint32)(statusFlag) >> LPUART_LIN_IP_SHIFT;
    boolean retVal = FALSE;

    switch ( reg )
    {
        case LPUART_LIN_IP_STAT_REG_ID:
            retVal = (((base->STAT >> (uint16)(statusFlag)) & 1U) > 0U);
            break;
        case LPUART_LIN_IP_DATA_REG_ID:
            retVal = (((base->DATA >> (uint16)(statusFlag)) & 1U) > 0U);
            break;
        default:
            /* Invalid parameter: return */
            break;
    }

    return retVal;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Lin_Ip_HwClearStatusFlag
 * Description   : LPUART clears an individual status flag
 * (see Lpuart_Lin_Ip_StatusFlagType for list of status bits).
 *END**************************************************************************/
Lpuart_Lin_Ip_StatusType Lpuart_Lin_Ip_HwClearStatusFlag(LPUART_Type * base,
                                    Lpuart_Lin_Ip_StatusFlagType statusFlag)
{
    Lpuart_Lin_Ip_StatusType returnCode = LPUART_LIN_IP_STATUS_SUCCESS;

    switch(statusFlag)
    {
        /* These flags are cleared automatically by other lpuart operations
         * and cannot be manually cleared, return error code */
        case LPUART_LIN_IP_TX_DATA_REG_EMPTY:
        case LPUART_LIN_IP_TX_COMPLETE:
        case LPUART_LIN_IP_RX_DATA_REG_FULL:
        case LPUART_LIN_IP_RX_ACTIVE:
#if LPUART_LIN_IP_HAS_EXTENDED_DATA_REGISTER_FLAGS
        case LPUART_LIN_IP_NOISE_IN_CURRENT_WORD:
        case LPUART_LIN_IP_PARITY_ERR_IN_CURRENT_WORD:
#endif
            returnCode = LPUART_LIN_IP_STATUS_ERROR;
            break;

        case LPUART_LIN_IP_IDLE_LINE_DETECT:
            base->STAT = (base->STAT & (~LPUART_LIN_IP_STAT_REG_FLAGS_MASK)) | LPUART_STAT_IDLE_MASK;
            break;

        case LPUART_LIN_IP_RX_OVERRUN:
            base->STAT = (base->STAT & (~LPUART_LIN_IP_STAT_REG_FLAGS_MASK)) | LPUART_STAT_OR_MASK;
            break;

        case LPUART_LIN_IP_NOISE_DETECT:
            base->STAT = (base->STAT & (~LPUART_LIN_IP_STAT_REG_FLAGS_MASK)) | LPUART_STAT_NF_MASK;
            break;

        case LPUART_LIN_IP_FRAME_ERR:
            base->STAT = (base->STAT & (~LPUART_LIN_IP_STAT_REG_FLAGS_MASK)) | LPUART_STAT_FE_MASK;
            break;

        case LPUART_LIN_IP_PARITY_ERR:
            base->STAT = (base->STAT & (~LPUART_LIN_IP_STAT_REG_FLAGS_MASK)) | LPUART_STAT_PF_MASK;
            break;

        case LPUART_LIN_IP_BREAK_DETECT:
            base->STAT = (base->STAT & (~LPUART_LIN_IP_STAT_REG_FLAGS_MASK)) | LPUART_STAT_LBKDIF_MASK;
            break;

        case LPUART_LIN_IP_RX_ACTIVE_EDGE_DETECT:
            base->STAT = (base->STAT & (~LPUART_LIN_IP_STAT_REG_FLAGS_MASK)) | LPUART_STAT_RXEDGIF_MASK;
            break;

        case LPUART_LIN_IP_ALL_INT_FLAGS:
            base->STAT = (base->STAT & (~LPUART_LIN_IP_STAT_REG_FLAGS_MASK)) | LPUART_LIN_IP_STAT_ALL_INT_FLAGS_MASK_U32;
            break;

        default:
            returnCode = LPUART_LIN_IP_STATUS_ERROR;
            break;
    }

    return (returnCode);
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Lin_Ip_StartTimeout
 * Description   : Checks for timeout condition
 *
 *END**************************************************************************/
void Lpuart_Lin_Ip_StartTimeout(uint32 *startTimeOut, uint32 *timeoutTicksOut, uint32 timeoutUs, OsIf_CounterType osifCounter)
{
    *startTimeOut    = OsIf_GetCounter(osifCounter);
    *timeoutTicksOut = OsIf_MicrosToTicks(timeoutUs, osifCounter);
}

/*FUNCTION**********************************************************************
 *
 * Function Name : Lpuart_Lin_Ip_TimeoutExpired
 * Description   : Checks for timeout expiration condition
 *
 *END**************************************************************************/
boolean Lpuart_Lin_Ip_TimeoutExpired(uint32 startTime, uint32 timeoutTicks, OsIf_CounterType osifCounter)
{
    uint32 tempTime = startTime;
    uint32 elapsedTime = OsIf_GetElapsed(&tempTime, osifCounter);

    return ((elapsedTime >= timeoutTicks)? TRUE : FALSE);
}

#define LIN_STOP_SEC_CODE
#include "Lin_MemMap.h"

#ifdef __cplusplus
}
#endif

/** @} */
