/*!
* @file     Dio.c
*
* @version  1.0.0
*
* @brief    AUTOSAR Dio Driver implementations
*
* @attention
*
* Project Name      : AUTOSAR MCAL
*
* Platform          : Arm
*
* Autosar Standard  : Classic Platform 4.4.0
*
* Compiled Version  : G32A10xx_MCAL_1_0_0_01-Otc-25
*
* Copyright (C) 2026 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (Geehy Semiconductor Software License Agreement).
*
* The program is only for reference, which is distributed in the hope
* that it will be usefull and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the Geehy Semiconductor Software License Agreement for the governing permissions
* and limitations under the License.
*/

#ifdef __cplusplus
extern "C"{
#endif

#include "Dio.h"
#include "Dio_Hw.h"
#include "Dio_Cfg.h"
#include "Reg_eSys.h"

#if (DIO_DEV_ERR_DETECT_ENABLE == STD_ON)
#include "Det.h"
#endif

/** @addtogroup G32A10xx_StdPeriphDriver
  @{
*/

/** @defgroup DIO_Driver
  * @brief DIO driver modules
  @{
*/

/** @defgroup DIO_Macros
  @{
*/
/*******************************************************************************
                    VENDOR ID & AUTOSAR VERSION INFO
*******************************************************************************/
/** Vendor ID (vendorId) of the dedicated implementation of this module according to the AUTOSAR vendor list. */
#define DIO_VENDOR_ID                              0x00C1U
/* Module ID of this module, as defined in the BSW Module List. */
#define DIO_MODULE_ID                              0x0065U
/** Major version number of AUTOSAR release on which the appropriate implementation is based on. */
#define DIO_AR_RELEASE_MAJOR_VERSION               0x04U
/** Minor version number of AUTOSAR release on which the appropriate implementation is based on. */
#define DIO_AR_RELEASE_MINOR_VERSION               0x04U
/** Revision version number of AUTOSAR release on which the appropriate implementation is based on. */
#define DIO_AR_RELEASE_REVISION_VERSION            0x00U
/** Major version number of the vendor specific implementation of the module. The numbering is vendor specific. */ 
#define DIO_SW_MAJOR_VERSION                       0x01U
/** Minor version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define DIO_SW_MINOR_VERSION                       0x00U
/** Patch level version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define DIO_SW_PATCH_VERSION                       0x00U

/**@} end of group DIO_Macros */
/*******************************************************************************
                            LOCAL FUNCTIONS
*******************************************************************************/
#define DIO_START_SEC_CODE
#include "Dio_MemMap.h"

/** @defgroup DIO_Fuctions
  @{
*/

#if (DIO_DEV_ERR_DETECT_ENABLE == STD_ON)
/*!
 * @brief       Verifies if a channel ID is valid
 *
 * @param       ChannelId       Channel ID to validate
 *
 * @retval      E_OK            Channel ID is valid
 * @retval      E_NOT_OK        Channel ID is invalid
 *
 * @note        Checks against predefined valid channel array
 */
static FUNC(Std_ReturnType, DIO_CODE) Dio_VerifyChannel(CONST(Dio_ChannelType, AUTOMATIC) ChannelId)
{
    VAR(Std_ReturnType, AUTOMATIC) valid = E_NOT_OK;
    uint8 tempVal = 0;
    
    for (tempVal = 0; tempVal < DIO_CHANNLE_MAX; tempVal++)
    {
        if (ChannelId == g_DioAllPortChannel[tempVal])
        {
            valid = E_OK;
            break;
        }
        else
        {
            /* nothing */
        }
    }

    return valid;
}

/*!
 * @brief       Verifies if a port ID is valid
 *
 * @param       PortId          Port ID to validate
 *
 * @retval      E_OK            Port ID is valid
 * @retval      E_NOT_OK        Port ID is invalid
 *
 * @note        Checks against predefined valid port array
 */
static FUNC(Std_ReturnType, DIO_CODE) Dio_VerifyPort(CONST(Dio_PortType, AUTOMATIC) PortId)
{
    VAR(Std_ReturnType, AUTOMATIC) valid = E_NOT_OK;
    uint8 tempVal = 0;

    for (tempVal = 0; tempVal < DIO_PORT_MAX; tempVal++)
    {
        if (PortId == g_DioAllPort[tempVal])
        {
            valid = E_OK;
            break;
        }
        else
        {
            /* nothing */
        }
    }

    return valid;
}
#endif

/*******************************************************************************
                            GLOBAL FUNCTIONS
*******************************************************************************/
/*!
* @brief          Returns the value of the specified DIO channel.
*
* @param[in]      ChannelId                  ID of DIO channel. 
*
* @retval         Dio_LevelType              Type of a DIO channel levels representation.
*                 STD_HIGH                   channel level is high
*                 STD_LOW                    channel level is low
*
* @note   
*/
FUNC(Dio_LevelType, DIO_CODE) Dio_ReadChannel(CONST(Dio_ChannelType, AUTOMATIC) ChannelId)
{
    VAR(Dio_LevelType, AUTOMATIC) channelLevel = DIO_STD_LOW;
#if (DIO_DEV_ERR_DETECT_ENABLE == STD_ON)
    if (E_NOT_OK == Dio_VerifyChannel(ChannelId))
    {
        (void)Det_ReportError((uint16)DIO_CFG_H_MODULE_ID, DIO_INSTANCE_ID,
                        DIO_READCHANNEL_ID, DIO_E_PARAM_INVALID_CHANNEL_ID);
    }
    else
    {
#endif
        channelLevel = Dio_Hw_ReadChannel(ChannelId);
#if (DIO_DEV_ERR_DETECT_ENABLE == STD_ON)
    }
#endif
    return channelLevel;
}



/*!
* @brief          The function used to write the value of the specified DIO channel.
*
* @param[in]      ChannelId                  channel id that will be write. 
* @param[in]      Level                      STD_HIGH or STD_LOW. 
*
* @retval         void    
*
* @note   
*/
FUNC(void, DIO_CODE) Dio_WriteChannel(CONST(Dio_ChannelType, AUTOMATIC) ChannelId, 
                                      CONST(Dio_LevelType, AUTOMATIC) Level)
{
#if (DIO_DEV_ERR_DETECT_ENABLE == STD_ON)
    if (E_NOT_OK == Dio_VerifyChannel(ChannelId))
    {
        (void)Det_ReportError((uint16)DIO_CFG_H_MODULE_ID, DIO_INSTANCE_ID,
                        DIO_WRITECHANNEL_ID, DIO_E_PARAM_INVALID_CHANNEL_ID);
    }
    else if ((Level != DIO_STD_LOW) && (Level != DIO_STD_HIGH))
    {
        (void)Det_ReportError((uint16)DIO_CFG_H_MODULE_ID, DIO_INSTANCE_ID,
                        DIO_WRITECHANNEL_ID, DIO_E_PARAM_LEVEL);
    }
    else
    {
#endif
        Dio_Hw_WriteChannel(ChannelId,Level);
#if (DIO_DEV_ERR_DETECT_ENABLE == STD_ON)
    }
#endif
}


#if (DIO_FLIP_CHANNEL_API == STD_ON)
/*!
* @brief          The function used to flip the level of the specified DIO channel.
*
* @param[in]      ChannelId                  channel id that will be flip. 
*
* @retval         Dio_LevelType              Type of a DIO channel levels representation.
*                 STD_HIGH                   channel level is high
*                 STD_LOW                    channel level is low
*
* @note   
*/
FUNC(Dio_LevelType, DIO_CODE) Dio_FlipChannel(CONST(Dio_ChannelType, AUTOMATIC) ChannelId)
{
    VAR(Dio_LevelType, AUTOMATIC) channelLevel = DIO_STD_LOW;
#if (DIO_DEV_ERR_DETECT_ENABLE == STD_ON)
    if (E_NOT_OK == Dio_VerifyChannel(ChannelId))
    {
        (void)Det_ReportError((uint16)DIO_CFG_H_MODULE_ID, DIO_INSTANCE_ID,
                        DIO_FLIPCHANNEL_ID, DIO_E_PARAM_INVALID_CHANNEL_ID);
    }
    else
    {
#endif
        channelLevel = Dio_Hw_FlipChannel(ChannelId);
#if (DIO_DEV_ERR_DETECT_ENABLE == STD_ON)
    }
#endif
    return channelLevel;
}
#endif


/*!
* @brief          The function used to read the level of the specified DIO port.
*
* @param[in]      PortId                     port id that will be read. 
*
* @retval         Dio_PortLevelType          Type of a DIO port levels representation.
*                 0~0x3ffff                  level of the port
*
* @note   
*/
FUNC(Dio_PortLevelType, DIO_CODE) Dio_ReadPort(CONST(Dio_PortType, AUTOMATIC) PortId)
{
    VAR(Dio_PortLevelType, AUTOMATIC) portLevel = (Dio_PortLevelType)0;
    
#if (DIO_DEV_ERR_DETECT_ENABLE == STD_ON)
    if (E_NOT_OK == Dio_VerifyPort(PortId))
    {
        (void)Det_ReportError((uint16)DIO_CFG_H_MODULE_ID, DIO_INSTANCE_ID,
                        DIO_READPORT_ID, DIO_E_PARAM_INVALID_PORT_ID);
    }
    else
    {
#endif
        portLevel = Dio_Hw_ReadPort(PortId);
#if (DIO_DEV_ERR_DETECT_ENABLE == STD_ON)
    }
#endif
    return portLevel;
}


/*!
* @brief          The function used to write the level of the specified DIO port.
*
* @param[in]      PortId        port id that will be read. 
* @param[in]      Level         the levels of all dio channel include by dio port. 
*
* @retval         void
*
* @note   
*/
FUNC(void, DIO_CODE) Dio_WritePort(CONST(Dio_PortType, AUTOMATIC) PortId, 
                                      CONST(Dio_PortLevelType, AUTOMATIC) Level)
{
#if (DIO_DEV_ERR_DETECT_ENABLE == STD_ON)
    if (E_NOT_OK == Dio_VerifyPort(PortId))
    {
        (void)Det_ReportError((uint16)DIO_CFG_H_MODULE_ID, DIO_INSTANCE_ID,
                        DIO_WRITEPORT_ID, DIO_E_PARAM_INVALID_PORT_ID);
    }
    else
    {
#endif
        Dio_Hw_WritePort(PortId,Level);
#if (DIO_DEV_ERR_DETECT_ENABLE == STD_ON)
    }
#endif
}


/*!
* @brief          The function used to read the level of the specified DIO channel group.
*
* @param[in]      ChannelGroupIdPtr          DIO channel group pointer that will be read. 
*
* @retval         Dio_PortLevelType          Type of a DIO channel group levels representation.
*                 0~0x3ffff                  level of the DIO channel group
*
* @note   
*/
FUNC(Dio_PortLevelType, DIO_CODE) Dio_ReadChannelGroup(P2CONST(Dio_ChannelGroupType, AUTOMATIC, DIO_APPL_CONST) ChannelGroupIdPtr)
{
    VAR(Dio_PortLevelType, AUTOMATIC) channelGroupLevel = (Dio_PortLevelType)0;

#if (DIO_DEV_ERR_DETECT_ENABLE == STD_ON)
    if ((NULL_PTR == ChannelGroupIdPtr) ||
        (NULL_PTR == g_dioConfig.channelGroupListPtr) ||
        ((Std_PointerSizeType)ChannelGroupIdPtr < (Std_PointerSizeType)g_dioConfig.channelGroupListPtr) ||
        ((Std_PointerSizeType)ChannelGroupIdPtr >= (Std_PointerSizeType)(g_dioConfig.channelGroupListPtr + g_dioConfig.channelGroupsCount)) ||
        (g_dioConfig.channelGroupsCount > DIO_PORT_MAX) ||
        (Dio_VerifyPort(ChannelGroupIdPtr->port) == E_NOT_OK))
    {
        (void)Det_ReportError((uint16)DIO_CFG_H_MODULE_ID, DIO_INSTANCE_ID,
                        DIO_READCHANNELGROUP_ID, DIO_E_PARAM_INVALID_GROUP_ID);
    }
    else
    {
#endif
        channelGroupLevel = Dio_Hw_ReadChannelGroup(ChannelGroupIdPtr);
#if (DIO_DEV_ERR_DETECT_ENABLE == STD_ON)
    }
#endif
    return channelGroupLevel;
}


/*!
* @brief          The function used to write the level of the specified DIO port.
*
* @param[in]      ChannelGroupIdPtr          DIO channel group pointer that will be read.
* @param[in]      Level                      the levels of all dio channel include by DIO channel group. 
*
* @retval         void
*
* @note   
*/
FUNC(void, DIO_CODE) Dio_WriteChannelGroup(P2CONST(Dio_ChannelGroupType, AUTOMATIC, DIO_APPL_CONST) ChannelGroupIdPtr,
                                                        CONST(Dio_PortLevelType, AUTOMATIC) Level)
{
#if (DIO_DEV_ERR_DETECT_ENABLE == STD_ON)
    if ((NULL_PTR == ChannelGroupIdPtr) ||
        (NULL_PTR == g_dioConfig.channelGroupListPtr) ||
        ((Std_PointerSizeType)ChannelGroupIdPtr < (Std_PointerSizeType)g_dioConfig.channelGroupListPtr) ||
        ((Std_PointerSizeType)ChannelGroupIdPtr >= (Std_PointerSizeType)(g_dioConfig.channelGroupListPtr + g_dioConfig.channelGroupsCount)) ||
        (g_dioConfig.channelGroupsCount > DIO_PORT_MAX) ||
        (Dio_VerifyPort(ChannelGroupIdPtr->port) == E_NOT_OK))
    {
        (void)Det_ReportError((uint16)DIO_CFG_H_MODULE_ID, DIO_INSTANCE_ID,
                        DIO_WRITECHANNELGROUP_ID, DIO_E_PARAM_INVALID_GROUP_ID);
    }
    else
    {
#endif
        Dio_Hw_WriteChannelGroup(ChannelGroupIdPtr,Level);
#if (DIO_DEV_ERR_DETECT_ENABLE == STD_ON)
    }
#endif
}


#if (DIO_VERINFO_API == STD_ON)
/*!
* @brief        The function used to get the version information of Dio module.
*
* @param[in]    VersionInfo     Pointer of the memory addr which use to store the version 
*                               information of this module.
* @retval       void
*
* @note   
*/
FUNC(void, MCU_CODE) Dio_GetVersionInfo(P2VAR(Std_VersionInfoType, AUTOMATIC, MCU_APPL_DATA) VersionInfo)
{
    if(NULL_PTR != VersionInfo)
    {
        (VersionInfo)->vendorID = (uint16)DIO_VENDOR_ID;
        (VersionInfo)->moduleID = (uint8)DIO_CFG_H_MODULE_ID;
        (VersionInfo)->sw_major_version = (uint8)DIO_AR_RELEASE_MAJOR_VERSION;
        (VersionInfo)->sw_minor_version = (uint8)DIO_AR_RELEASE_MINOR_VERSION;
        (VersionInfo)->sw_patch_version = (uint8)DIO_AR_RELEASE_REVISION_VERSION;
    }
    else
    {
#if (DIO_DEV_ERR_DETECT_ENABLE == STD_ON)
        (void)Det_ReportError((uint16)DIO_CFG_H_MODULE_ID, DIO_INSTANCE_ID,
                        DIO_GETVERSIONINFO_ID, DIO_E_PARAM_POINTER);
#endif
    }
}
#endif

/**@} end of group DIO_Fuctions */

#define DIO_STOP_SEC_CODE
#include "Dio_MemMap.h"

#ifdef __cplusplus
}
#endif

/**@} end of group DIO_Driver */
/**@} end of group G32A10xx_StdPeriphDriver */
