/*!
* @file     Port_Hw.c
*
* @version  1.0.0
*
* @brief    AUTOSAR Port 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  /* ifdef __cplusplus */

#include "Reg_eSys.h"
#include "Std_Types.h"
#include "Port.h"
#include "Port_Hw.h"
#include "Port_Reg.h"

/** @addtogroup G32A10xx_StdPeriphDriver
  @{
*/

/** @defgroup PORT_Driver
  * @brief PORT driver modules
  @{
*/

/** @defgroup PORT_Macros
  @{
*/
/*******************************************************************************
                    VENDOR ID & AUTOSAR VERSION INFO
*******************************************************************************/
/** Vendor ID (vendorId) of the dedicated implementation of this module according to the AUTOSAR vendor list. */
#define PORT_HW_VENDOR_ID                              0x00C1U
/** Major version number of AUTOSAR release on which the appropriate implementation is based on. */
#define PORT_HW_AR_RELEASE_MAJOR_VERSION               0x04U
/** Minor version number of AUTOSAR release on which the appropriate implementation is based on. */
#define PORT_HW_AR_RELEASE_MINOR_VERSION               0x04U
/** Revision version number of AUTOSAR release on which the appropriate implementation is based on. */
#define PORT_HW_AR_RELEASE_REVISION_VERSION            0x00U
/** Major version number of the vendor specific implementation of the module. The numbering is vendor specific. */ 
#define PORT_HW_SW_MAJOR_VERSION                       0x01U
/** Minor version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define PORT_HW_SW_MINOR_VERSION                       0x00U
/** Patch level version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define PORT_HW_SW_PATCH_VERSION                       0x00U

/**@} end of group PORT_Macros */
/*******************************************************************************
                            GLOBAL VARIABLE
*******************************************************************************/
#define PORT_START_SEC_CONST_32
#include "Port_MemMap.h"

/** @defgroup PORT_Variable
  @{
*/

/** The base address array of the PORT */
CONST(uint32, PORT_CONST) PORT_BASEADDR_ARR[6] = {
    GPIOA_BASEADDR,
    GPIOB_BASEADDR,
    GPIOC_BASEADDR,
    GPIOD_BASEADDR,
    ((uint32)0x48001000),
    GPIOF_BASEADDR
};

/**@} end of group PORT_Variable */

#define PORT_STOP_SEC_CONST_32
#include "Port_MemMap.h"
/*******************************************************************************
                            GLOBAL FUNCTIONS
*******************************************************************************/
#define PORT_START_SEC_CODE
#include "Port_MemMap.h"

/** @defgroup PORT_Fuctions
  @{
*/

/*!
* @brief       Configures pin alternate function mode
*
* @param       portId          Target port ID
* @param       portPinId       Target pin ID within the port
* @param       portPinMode     Alternate function mode to set
*
* @retval      None
*
* @note        Handles low-pin (0-7) and high-pin (8-15) register mapping
* @note        Uses AFRL (pins 0-7) and AFRH (pins 8-15) registers
*/
void Port_Hw_AFConfig(Port_PortIdType portId, 
                      Port_PortPinIdType portPinId,
                      Port_PinModeType portPinMode)
{
    uint32_t temp  = 0x00;
    uint32_t temp1 = 0x00;
    
    if (portPinId <= GPIO_PIN_7)
    {
        temp = (uint32)((uint32)((uint32)portPinMode & (uint32)0xF0) >> 4) << ((uint32)portPinId * (uint32)4);
        REG_BIT_CLEAR32(GPIO_ALFL_REG_ADDR(portId), ((uint32)0xf << ((uint32)portPinId * (uint32)4)));
        REG_BIT_SET32(GPIO_ALFL_REG_ADDR(portId),temp);
    }
    else
    {
        temp1 = (uint32)((uint32)((uint32)portPinMode & (uint32)0xF0) >> 4) << ((uint32)((uint32)portPinId & (uint32)0x07) * (uint32)4);
        REG_BIT_CLEAR32(GPIO_ALFH_REG_ADDR(portId), ((uint32)0xf << ((uint32)((uint32)portPinId & (uint8)0x07) * (uint32)4)));
        REG_BIT_SET32(GPIO_ALFH_REG_ADDR(portId),temp1);
    }
}


/*!
* @brief       Configures pin output speed capability
*
* @param       portId          Target port ID
* @param       portPinId       Target pin ID within the port
* @param       speedSelect     Output speed setting
*
* @retval      None
*
* @note        Directly manipulates OSPEEDR register
* @note        Clears previous setting before applying new value
*/
void Port_Hw_ConfigPinSpeed(Port_PortIdType portId, 
                            Port_PortPinIdType portPinId,
                            Port_PinSpeedAbilityType speedSelect)
{
    REG_BIT_CLEAR32(GPIO_OSSEL_REG_ADDR(portId),((uint32)(0x03) << (uint32)((uint32)portPinId * (uint32)2)));
    REG_BIT_SET32(GPIO_OSSEL_REG_ADDR(portId),(uint32)speedSelect << (uint32)((uint32)portPinId * (uint32)2));
}


/*!
* @brief       Configures pin output drive mode
*
* @param       portId          Target port ID
* @param       portPinId       Target pin ID within the port
* @param       outputMode      Output mode (push-pull/open-drain)
*
* @retval      None
*
* @note        Directly manipulates OTYPER register
* @note        Atomic clear-then-set operation on specific bit
*/
void Port_Hw_ConfigPinOutputMode(Port_PortIdType portId, 
                                 Port_PortPinIdType portPinId,
                                 Port_OutputModeType outputMode)
{
    REG_BIT_CLEAR32(GPIO_OMODE_REG_ADDR(portId),(uint32)outputMode << (uint32)portPinId);
    REG_BIT_SET32(GPIO_OMODE_REG_ADDR(portId),(uint32)outputMode << (uint32)portPinId);
}


/*!
* @brief       Configures pin operational mode
*
* @param       portId          Target port ID
* @param       portPinId       Target pin ID within the port
* @param       portPinMode     Pin mode (input/output/alternate/analog)
*
* @retval      None
*
* @note        Directly manipulates MODER register
* @note        Clears previous mode before setting new mode
*/
void Port_Hw_ConfigPinMode(Port_PortIdType portId, 
                           Port_PortPinIdType portPinId,
                           Port_PinModeType portPinMode)
{
    REG_BIT_CLEAR32(GPIO_MODE_REG_ADDR(portId),((uint32)0x03 << (uint32)((uint32)portPinId * (uint32)2)));
    REG_BIT_SET32(GPIO_MODE_REG_ADDR(portId),(uint32)((uint32)portPinMode & (uint32)0xF)  << (uint32)((uint32)portPinId * (uint8)2));
}


/*!
* @brief       Configures pin pull-up/pull-down resistors
*
* @param       portId          Target port ID
* @param       portPinId       Target pin ID within the port
* @param       pullValue       Pull configuration (no-pull/up/down)
*
* @retval      None
*
* @note        Directly manipulates PUPDR register
* @note        Uses two-bit configuration per pin
*/
void Port_Hw_ConfigPull(Port_PortIdType portId, 
                        Port_PortPinIdType portPinId,
                        Port_PullModeType pullValue)
{
    REG_BIT_CLEAR32(GPIO_PUPD_REG_ADDR(portId),((uint32)(0x03) << (uint32)((uint32)portPinId * (uint8)2)));
    REG_BIT_SET32(GPIO_PUPD_REG_ADDR(portId),(uint32)pullValue << (uint32)((uint32)portPinId * (uint8)2));
}


/*!
* @brief       Configures pin direction (input/output)
*
* @param       portId          Target port ID
* @param       portPinId       Target pin ID within the port
* @param       pinDir          Direction setting (input/output)
*
* @retval      None
*
* @note        Directly manipulates MODER register
* @note        Overrides previous pin mode setting
*/
void Port_Hw_ConfigPinDir(Port_PortIdType portId, 
                          Port_PortPinIdType portPinId,
                          Port_PinDirectionType pinDir)
{
    REG_BIT_CLEAR32(GPIO_MODE_REG_ADDR(portId),((uint32)(0x03) << (uint32)((uint32)portPinId * (uint32)2)));
    REG_BIT_SET32(GPIO_MODE_REG_ADDR(portId),(uint32)((uint32)pinDir & (uint32)0xF)  << (uint32)((uint32)portPinId * (uint32)2));
}


/*!
* @brief       Configures pin output level
*
* @param       portId          Target port ID
* @param       portPinId       Target pin ID within the port
* @param       pinLevel        output level
*
* @retval      None
*/
void Port_Hw_ConfigPinOData(Port_PortIdType portId, 
                            Port_PortPinIdType portPinId,
                            Port_pinLevelType pinLevel)
{
    if (PORT_PIN_LEVEL_LOW == pinLevel)
    {
        REG_BIT_SET32(GPIO_BSC_REG_ADDR(portId),(uint32)1U  << (uint32)((uint32)portPinId + (uint32)16));
    }
    else
    {
        REG_BIT_SET32(GPIO_BSC_REG_ADDR(portId),(uint32)1U  << (uint32)portPinId);
    }
    
}


/*!
* @brief       Enables/disables input noise filter
*
* @param       portId          Target port ID
* @param       portPinId       Target pin ID within the port
* @param       status          Filter enable status (ENABLE/DISABLE)
*
* @retval      None
*
* @note        Directly manipulates input filter enable register
* @note        Affects signal stability in noisy environments
*/
void Port_Hw_ConfigFilter(Port_PortIdType portId, 
                          Port_PortPinIdType portPinId,
                          uint8 status)
{
    if ((uint8)ENABLE == status)
    {
        REG_BIT_SET32(GPIO_FILTER_EN_REG_ADDR(portId),(uint32)GPIO_PIN_FILTER_EN(((uint32)portPinId)));
    }
    else
    {
        REG_BIT_CLEAR32(GPIO_FILTER_EN_REG_ADDR(portId),(uint32)GPIO_PIN_FILTER_EN(((uint32)portPinId)));
    }
}

/**@} end of group PORT_Fuctions */

#define PORT_STOP_SEC_CODE
#include "Port_MemMap.h"

#ifdef __cplusplus
}
#endif  /* ifdef __cplusplus */

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