/*==================================================================================================
*   Project              : RTD AUTOSAR 4.4
*   Platform             : CORTEXM
*   Peripheral           : SIUL2
*   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 Siul2_Dio_Ip.c
*
*   @addtogroup DIO_IPL
*   @{
*/

#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 "Siul2_Dio_Ip.h"
#if (STD_ON == SIUL2_DIO_IP_DEV_ERROR_DETECT)
    #include "Devassert.h"
#endif /* (STD_ON == SIUL2_DIO_IP_DEV_ERROR_DETECT) */

/*==================================================================================================
*                                 SOURCE FILE VERSION INFORMATION
==================================================================================================*/
/*
* @brief Parameters that shall be published within the driver header file and also in the
* module's description file
*/
#define SIUL2_DIO_IP_VENDOR_ID_C                     43
#define SIUL2_DIO_IP_AR_RELEASE_MAJOR_VERSION_C      4
#define SIUL2_DIO_IP_AR_RELEASE_MINOR_VERSION_C      4
#define SIUL2_DIO_IP_AR_RELEASE_REVISION_VERSION_C   0
#define SIUL2_DIO_IP_SW_MAJOR_VERSION_C              0
#define SIUL2_DIO_IP_SW_MINOR_VERSION_C              9
#define SIUL2_DIO_IP_SW_PATCH_VERSION_C              0

/*==================================================================================================
*                                       FILE VERSION CHECKS
==================================================================================================*/
/* Check if Siul2_Dio_Ip source file and Siul2_Dio_Ip header file are of the same vendor */
#if (SIUL2_DIO_IP_VENDOR_ID_C != SIUL2_DIO_IP_VENDOR_ID_H)
    #error "Siul2_Dio_Ip.c and Siul2_Dio_Ip.h have different vendor ids"
#endif

/* Check if  Siul2_Dio_Ip source file and Siul2_Dio_Ip header file are of the same Autosar version */
#if ((SIUL2_DIO_IP_AR_RELEASE_MAJOR_VERSION_C    != SIUL2_DIO_IP_AR_RELEASE_MAJOR_VERSION_H) || \
     (SIUL2_DIO_IP_AR_RELEASE_MINOR_VERSION_C    != SIUL2_DIO_IP_AR_RELEASE_MINOR_VERSION_H) || \
     (SIUL2_DIO_IP_AR_RELEASE_REVISION_VERSION_C != SIUL2_DIO_IP_AR_RELEASE_REVISION_VERSION_H) \
    )
    #error "AutoSar Version Numbers of Siul2_Dio_Ip.c and Siul2_Dio_Ip.h are different"
#endif

/* Check if Siul2_Dio_Ip source file and Siul2_Dio_Ip header file are of the same Software version */
#if ((SIUL2_DIO_IP_SW_MAJOR_VERSION_C != SIUL2_DIO_IP_SW_MAJOR_VERSION_H) || \
     (SIUL2_DIO_IP_SW_MINOR_VERSION_C != SIUL2_DIO_IP_SW_MINOR_VERSION_H) || \
     (SIUL2_DIO_IP_SW_PATCH_VERSION_C != SIUL2_DIO_IP_SW_PATCH_VERSION_H)    \
    )
    #error "Software Version Numbers of Siul2_Dio_Ip.c and Siul2_Dio_Ip.h are different"
#endif
/*==================================================================================================
*                           LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS)
==================================================================================================*/

/*==================================================================================================
*                                          LOCAL MACROS
==================================================================================================*/
#define SIUL2_NUM_OF_PIN_PORT           16u

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

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

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

/*==================================================================================================
*                                        GLOBAL VARIABLES
==================================================================================================*/
#define DIO_START_SEC_VAR_INIT_32
#include "Dio_MemMap.h"

#if (STD_ON == DIO_VIRTWRAPPER_SUPPORT)
uint32 Siul2BaseAdresses[3] =
{
    DIO_SIUL2_VIRTWRAPPER_PDAC0,
    DIO_SIUL2_VIRTWRAPPER_PDAC1,
    DIO_SIUL2_VIRTWRAPPER_PDAC2
};
#else
uint32 Siul2BaseAdresses[SIUL2_INSTANCE_COUNT] = SIUL2_BASE_ADDRS;
#endif

#define DIO_STOP_SEC_VAR_INIT_32
#include "Dio_MemMap.h"
/*==================================================================================================
*                                    LOCAL FUNCTION PROTOTYPES
==================================================================================================*/
#define DIO_START_SEC_CODE
#include "Dio_MemMap.h"

static inline uint16 Siul2_Dio_Ip_REV_BIT_16(uint16 value);

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

/* Reverse bit order in each halfword independently */
static inline uint16 Siul2_Dio_Ip_REV_BIT_16(uint16 value)
{
    uint8 i;
    uint16 ret = 0U;

    for (i = 0U; i < 8U; i++)
    {
        ret |= (uint16)((((value >> i) & 1U) << (15U - i)) | (((value << i) & 0x8000U) >> (15U - i)));
    }

    return ret;
}

/*==================================================================================================
*                                        GLOBAL FUNCTIONS
==================================================================================================*/

/**
 *Function Name : Siul2_Dio_Ip_WritePin
 * Description   : This function writes the given pin from a port, with the given value
 * ('0' represents LOW, '1' represents HIGH).
 *
 * @implements    Siul2_Dio_Ip_WritePin_Activity
 */
void Siul2_Dio_Ip_WritePin(Siul2_Dio_Ip_GpioType * const base,
                           Siul2_Dio_Ip_PinsChannelType pin,
                           Siul2_Dio_Ip_PinsLevelType value)
{
    SIUL2_DIO_DEV_ASSERT(base != NULL_PTR);
    SIUL2_DIO_DEV_ASSERT((boolean)(pin < SIUL2_NUM_OF_PIN_PORT));
    SIUL2_DIO_DEV_ASSERT((boolean)(value <= 1U));
    Siul2_Dio_Ip_PinsChannelType pinsValues = (Siul2_Dio_Ip_PinsChannelType)base->PGPDO;
    pinsValues &= (Siul2_Dio_Ip_PinsChannelType)(~((Siul2_Dio_Ip_PinsChannelType)1U << (15U - pin)));
    pinsValues |= (Siul2_Dio_Ip_PinsChannelType)(((Siul2_Dio_Ip_PinsChannelType)value & 1U) << (15U - pin));
    base->PGPDO = pinsValues;
}

/**
 * Function Name : Siul2_Dio_Ip_WritePins
 * Description   : This function writes all pins configured as output with the values given in
 * the parameter pins. '0' represents LOW, '1' represents HIGH.
 *
 * @implements    Siul2_Dio_Ip_WritePins_Activity
 */
void Siul2_Dio_Ip_WritePins(Siul2_Dio_Ip_GpioType * const base,
                            Siul2_Dio_Ip_PinsChannelType pins)
{
    SIUL2_DIO_DEV_ASSERT(base != NULL_PTR);
    base->PGPDO = Siul2_Dio_Ip_REV_BIT_16(pins);
}

/**
 * Function Name : Siul2_Dio_Ip_GetPinsOutput
 * Description   : This function returns the current output that is written to a port. Only pins
 * that are configured as output will have meaningful values.
 *
 * @implements    Siul2_Dio_Ip_GetPinsOutput_Activity
 */
Siul2_Dio_Ip_PinsChannelType Siul2_Dio_Ip_GetPinsOutput(const Siul2_Dio_Ip_GpioType * const base)
{
    SIUL2_DIO_DEV_ASSERT(base != NULL_PTR);
    Siul2_Dio_Ip_PinsChannelType returnValue = 0U;
    returnValue = (Siul2_Dio_Ip_PinsChannelType)Siul2_Dio_Ip_REV_BIT_16(base->PGPDO);
    return returnValue;
}

/**
 * Function Name : Siul2_Dio_Ip_SetPins
 * Description   : This function configures output pins listed in parameter pins (bits that are
 * '1') to have a value of 'set' (HIGH). Pins corresponding to '0' will be
 * unaffected.
 *
 * @implements    Siul2_Dio_Ip_SetPins_Activity
 */
void Siul2_Dio_Ip_SetPins(Siul2_Dio_Ip_GpioType * const base,
                          Siul2_Dio_Ip_PinsChannelType pins)
{
    SIUL2_DIO_DEV_ASSERT(base != NULL_PTR);
    base->PGPDO |= Siul2_Dio_Ip_REV_BIT_16(pins);
}

/**
 * Function Name : Siul2_Dio_Ip_ClearPins
 * Description   : This function configures output pins listed in parameter pins (bits that are
 * '1') to have a 'cleared' value (LOW). Pins corresponding to '0' will be
 * unaffected.
 *
 * @implements    Siul2_Dio_Ip_ClearPins_Activity
 */
void Siul2_Dio_Ip_ClearPins(Siul2_Dio_Ip_GpioType * const base,
                            Siul2_Dio_Ip_PinsChannelType pins)
{
    SIUL2_DIO_DEV_ASSERT(base != NULL_PTR);
    base->PGPDO &= (Siul2_Dio_Ip_PinsChannelType)(~Siul2_Dio_Ip_REV_BIT_16(pins));
}

/**
 * Function Name : Siul2_Dio_Ip_TogglePins
 * Description   : This function toggles output pins listed in parameter pins (bits that are
 * '1'). Pins corresponding to '0' will be unaffected.
 *
 * @implements    Siul2_Dio_Ip_TogglePins_Activity
 */
void Siul2_Dio_Ip_TogglePins(Siul2_Dio_Ip_GpioType * const base,
                             Siul2_Dio_Ip_PinsChannelType pins)
{
    SIUL2_DIO_DEV_ASSERT(base != NULL_PTR);
    base->PGPDO ^= Siul2_Dio_Ip_REV_BIT_16(pins);
}

/**
 * Function Name : Siul2_Dio_Ip_ReadPins
 * Description   : This function returns the current input values from a port. Only pins
 * configured as input will have meaningful values.
 *
 * @implements    Siul2_Dio_Ip_ReadPins_Activity
 */
Siul2_Dio_Ip_PinsChannelType Siul2_Dio_Ip_ReadPins(const Siul2_Dio_Ip_GpioType * const base)
{
    SIUL2_DIO_DEV_ASSERT(base != NULL_PTR);
    Siul2_Dio_Ip_PinsChannelType returnValue = 0U;
    returnValue = (Siul2_Dio_Ip_PinsChannelType)Siul2_Dio_Ip_REV_BIT_16(base->PGPDI);
    return returnValue;
}

/**
 * Function Name : Siul2_Dio_Ip_ReadPin
 * Description   : This function returns the current  input value of the given pin from port. Only pin
 * configured as input will have meaningful value.
 *
 * @implements    Siul2_Dio_Ip_ReadPin_Activity
 */
Siul2_Dio_Ip_PinsLevelType Siul2_Dio_Ip_ReadPin(const Siul2_Dio_Ip_GpioType * const base, Siul2_Dio_Ip_PinsChannelType pin)
{
    SIUL2_DIO_DEV_ASSERT(base != NULL_PTR);
    SIUL2_DIO_DEV_ASSERT((boolean)(pin < SIUL2_NUM_OF_PIN_PORT));
    Siul2_Dio_Ip_PinsLevelType returnValue = 0U;

    returnValue = (Siul2_Dio_Ip_PinsLevelType)((Siul2_Dio_Ip_REV_BIT_16(base->PGPDI) & ((Siul2_Dio_Ip_PinsChannelType)1U << pin)) >> pin);
    return returnValue;
}

/**
 * Function Name : Siul2_Dio_Ip_MaskedWritePins
 * Description   : This function writes the masked pins configured as output with the values given
 * in the parameter pins. '0' represents LOW, '1' represents HIGH.
 *
 * @implements    Siul2_Dio_Ip_MaskedWritePins_Activity
 */
void Siul2_Dio_Ip_MaskedWritePins(uint8 u8Siul2Instance, uint8 u8PortId, Siul2_Dio_Ip_PinsChannelType pins, Siul2_Dio_Ip_PinsChannelType mask)
{
    SIUL2_Type * base = (SIUL2_Type *)Siul2BaseAdresses[u8Siul2Instance];
    uint32 maskRev;
    uint32 pinsRev;

    maskRev = (uint32)(Siul2_Dio_Ip_REV_BIT_16(mask));
    pinsRev = (uint32)(Siul2_Dio_Ip_REV_BIT_16(pins));

    base->MPGPDO[u8PortId] = (maskRev << (uint32)16U) | pinsRev;
}

#if (STD_ON == DIO_VIRTWRAPPER_SUPPORT)
/**
 * Function Name : Siul2_Dio_Ip_VirtWrapperMaskedWritePins
 * Description   : This function writes the masked pins configured as output with the values given
 * in the parameter pins. '0' represents LOW, '1' represents HIGH.
 *
 *
 */
void Siul2_Dio_Ip_VirtWrapperMaskedWritePins(uint8 u8PdacIndex, uint8 u8PortId, Siul2_Dio_Ip_PinsChannelType pins, Siul2_Dio_Ip_PinsChannelType mask)
{
    SIUL2_DIO_DEV_ASSERT(u8PdacIndex != 255);
    uint32 maskRev;
    uint32 pinsRev;
    uint32 value;

    /* Store the value of the mask */
    maskRev = (uint32)(Siul2_Dio_Ip_REV_BIT_16(mask));
    /* Store the value of MPPDO */
    pinsRev = (uint32)(Siul2_Dio_Ip_REV_BIT_16(pins));
    /* Place mask and MPPDO into MPGPDO register */
    value   = ((maskRev << (uint32)16U) | pinsRev);
    (*(uint32*)(SIUL2_DIO_MPGPDO_ADDR32(u8PdacIndex,u8PortId))) = value;
}
#endif

/**
 * Function Name : Siul2_Dio_Ip_ReadChannel
 * Description   : This function will returns the current value of a channel, just be used in IPW
 *
 * @implements None
 */
Siul2_Dio_Ip_PinsLevelType Siul2_Dio_Ip_ReadChannel(uint8 u8Siul2Instance, Siul2_Dio_Ip_PinsChannelType pin)
{
    Siul2_Dio_Ip_PinsLevelType returnValue = 0U;
    returnValue = (*(uint8*)(SIUL2_DIO_GPDI_ADDR32(u8Siul2Instance,pin))) & SIUL2_GPDI_MASK_U8;
    return returnValue;

}

/**
 * Function Name : Siul2_Dio_Ip_WriteChannel
 * Description   : This function will writes the logic level for a pin, just be used in IPW
 *
 * @implements None
 */
void Siul2_Dio_Ip_WriteChannel(uint8 u8Siul2Instance, Siul2_Dio_Ip_PinsChannelType pin, Siul2_Dio_Ip_PinsLevelType value)
{
    *(uint8*)(SIUL2_DIO_GPDO_ADDR32(u8Siul2Instance,pin))=value;
}

#if (STD_ON == DIO_VIRTWRAPPER_SUPPORT)
/**
 * Function Name : Siul2_Dio_Ip_VirtWrapperWriteChannel
 * Description   : This function will writes the logic level for a pin, just be used in IPW
 *
 * @implements None
 */
void Siul2_Dio_Ip_VirtWrapperWriteChannel(uint8 u8PdacIndex, Siul2_Dio_Ip_PinsChannelType pin, Siul2_Dio_Ip_PinsLevelType value)
{
    SIUL2_DIO_DEV_ASSERT(u8PdacIndex != 255);
    *(uint8*)(SIUL2_DIO_GPDO_ADDR32(u8PdacIndex,pin))=value;
}
#endif

#define DIO_STOP_SEC_CODE
#include "Dio_MemMap.h"

#ifdef __cplusplus
}
#endif

/** @} */

/******************************************************************************
 * EOF
 *****************************************************************************/
