/*!
* @file     Gpt_Hw.c
*
* @version  1.0.0
*
* @brief    AUTOSAR Gpt 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 "Gpt.h"
#include "Gpt_Hw.h"
#include "Pdl_TmrReg.h"

/** @addtogroup G32A10xx_StdPeriphDriver
  @{
*/

/** @defgroup GPT_Driver
  * @brief GPT driver modules
  @{
*/

/** @defgroup GPT_Macros
  @{
*/
/*******************************************************************************
                    VENDOR ID & AUTOSAR VERSION INFO
*******************************************************************************/
/** Vendor ID (vendorId) of the dedicated implementation of this module according to the AUTOSAR vendor list. */
#define GPT_HW_VENDOR_ID                              0x00C1U
/** Major version number of AUTOSAR release on which the appropriate implementation is based on. */
#define GPT_HW_AR_RELEASE_MAJOR_VERSION               0x04U
/** Minor version number of AUTOSAR release on which the appropriate implementation is based on. */
#define GPT_HW_AR_RELEASE_MINOR_VERSION               0x04U
/** Revision version number of AUTOSAR release on which the appropriate implementation is based on. */
#define GPT_HW_AR_RELEASE_REVISION_VERSION            0x00U
/** Major version number of the vendor specific implementation of the module. The numbering is vendor specific. */ 
#define GPT_HW_SW_MAJOR_VERSION                       0x01U
/** Minor version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define GPT_HW_SW_MINOR_VERSION                       0x00U
/** Patch level version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define GPT_HW_SW_PATCH_VERSION                       0x00U

/**@} end of group GPT_Macros */
/*******************************************************************************
                            GLOBAL FUNCTIONS
*******************************************************************************/
#define GPT_START_SEC_CODE
#include "Gpt_MemMap.h"

/** @defgroup GPT_Fuctions
  @{
*/

/*!
* @brief       Configures timer prescaler value
*
* @param       hwUnitId            Target timer hardware ID
* @param       channelPrescaler    Prescaler division factor
*
* @retval      None
*
* @note        Sets TMRx_PSC register value
* @note        Divides timer input clock: t_clk = f_ck_psc / (channelPrescaler + 1)
* @warning     Actual frequency reduction: (PSC+1)
*/
void Gpt_Hw_ConfigFreqDivw(Gpt_TimerHwIdType hwUnitId,uint16_t channelPrescaler)
{
    REG_WRITE32(TMR_PSC_REG_ADDR(hwUnitId),channelPrescaler);
}


/*!
* @brief       Controls update event generation
*
* @param       hwUnitId        Target timer hardware ID
* @param       status          Update event state (ENABLE/DISABLE)
*
* @retval      None
*
* @note        Manages TMRx_CEG[UEG] bit
* @note        ENABLE: Generate update events on overflow
* @note        DISABLE: Suppress update events
* @note        Critical for synchronization with slave timers
*/
void Gpt_Hw_UpdataEventGenerate(Gpt_TimerHwIdType hwUnitId,uint32 status)
{
    if ((uint32)ENABLE == status)
    {
        REG_BIT_SET32(TMR_CEG_REG_ADDR(hwUnitId),TMR_CEG_UEG_MASK);
    }
    else
    {
        REG_BIT_CLEAR32(TMR_CEG_REG_ADDR(hwUnitId),TMR_CEG_UEG_MASK);
    }
}


/*!
* @brief       Configures single-pulse mode operation
*
* @param       hwUnitId        Target timer hardware ID
* @param       status          Mode state (ENABLE/DISABLE)
*
* @retval      None
*
* @note        Controls TMRx_CTRL1[SPMEN] bit
* @note        ENABLE: Timer stops after next overflow event
* @note        DISABLE: Continuous counting mode
* @note        Useful for generating precise single-shot pulses
*/
void Gpt_Hw_OperationSinglePulseMode(Gpt_TimerHwIdType hwUnitId,uint32 status)
{
    if ((uint32)ENABLE == status)
    {
        REG_BIT_SET32(TMR_CTRL1_REG_ADDR(hwUnitId),TMR_CTRL1_SPMEN_MASK);
    }
    else
    {
        REG_BIT_CLEAR32(TMR_CTRL1_REG_ADDR(hwUnitId),TMR_CTRL1_SPMEN_MASK);
    }
}


/*!
* @brief       Controls auto-reload preload feature
*
* @param       hwUnitId        Target timer hardware ID
* @param       status          Preload state (ENABLE/DISABLE)
*
* @retval      None
*
* @note        Manages TMRx_CTRL1[ARPEN] bit
* @note        ENABLE: Auto-reload value buffered (updated at next overflow)
* @note        DISABLE: Immediate auto-reload value update
* @note        Prevents glitches during period changes
*/
void Gpt_Hw_OperationAutoreloadPre(Gpt_TimerHwIdType hwUnitId,uint32 status)
{
    if ((uint32)ENABLE == status)
    {
        REG_BIT_SET32(TMR_CTRL1_REG_ADDR(hwUnitId),TMR_CTRL1_ARPEN_MASK);
    }
    else
    {
        REG_BIT_CLEAR32(TMR_CTRL1_REG_ADDR(hwUnitId),TMR_CTRL1_ARPEN_MASK);
    }
}


/*!
* @brief       Sets timer period value
*
* @param       hwUnitId        Target timer hardware ID
* @param       period          Auto-reload register value (period-1)
*
* @retval      None
*
* @note        Writes to TMRx_AUTORLD register
* @note        Actual period = (period + 1) * timer_clock_period
* @note        Defines timer overflow point
*/
void Gpt_Hw_ConfigAutoReloadValue(Gpt_TimerHwIdType hwUnitId,uint32_t period)
{
    REG_WRITE32(TMR_AUTORLD_REG_ADDR(hwUnitId),period);
}


/*!
* @brief       Reads current auto-reload register value
*
* @param       hwUnitId        Target timer hardware ID
*
* @retval      Current period setting value
*
* @note        Reads TMRx_AUTORLD register
* @note        Returns configured period value (not actual clock cycles)
* @note        Actual overflow period = (return_value + 1) * timer_clock_period
*/
Gpt_ValueType Gpt_Hw_GetAutoReloadValue(Gpt_TimerHwIdType hwUnitId)
{
    Gpt_ValueType tempRetVal = 0;
    
    tempRetVal = REG_READ32(TMR_AUTORLD_REG_ADDR(hwUnitId));
    
    return tempRetVal;
}


/*!
* @brief       Disables and resets specified compare channel
*
* @param       hwUnitId        Target timer hardware ID
* @param       HwChannel       Channel number (1-4)
*
* @retval      None
*
* @note        Performs dual operation on compare channel:
*              1. Disables channel (clears CCxEN bit)
*              2. Resets mode selection (clears CCxSEL bits)
* @note        Register usage:
*              - Channels 1-2: TMR_CCM1
*              - Channels 3-4: TMR_CCM2
* @warning     Does NOT support advanced channel configurations
*/
void Gpt_Hw_OperationCompareChannel(uint8 hwUnitId,uint8 HwChannel)
{
    if (hwUnitId <= (uint8)GPT_TMR4)
    {
        if ((uint8)1 == HwChannel)
        {
            REG_BIT_CLEAR32(TMR_CCEN_REG_ADDR(hwUnitId),TMR_CCEN_CC1EN_MASK);
            REG_BIT_CLEAR32(TMR_CCM1_REG_ADDR(hwUnitId),TMR_CCM1_CC1SEL_MASK);
        }
        else if ((uint8)2 == HwChannel)
        {
            REG_BIT_CLEAR32(TMR_CCEN_REG_ADDR(hwUnitId),TMR_CCEN_CC2EN_MASK);
            REG_BIT_CLEAR32(TMR_CCM1_REG_ADDR(hwUnitId),TMR_CCM1_CC2SEL_MASK);
        }
        else if ((uint8)3 == HwChannel)
        {
            REG_BIT_CLEAR32(TMR_CCEN_REG_ADDR(hwUnitId),TMR_CCEN_CC3EN_MASK);
            REG_BIT_CLEAR32(TMR_CCM2_REG_ADDR(hwUnitId),TMR_CCM2_CC3SEL_MASK);
        }
        else if ((uint8)4 == HwChannel)
        {
            REG_BIT_CLEAR32(TMR_CCEN_REG_ADDR(hwUnitId),TMR_CCEN_CC4EN_MASK);
            REG_BIT_CLEAR32(TMR_CCM2_REG_ADDR(hwUnitId),TMR_CCM2_CC4SEL_MASK);
        }
        else
        {
            /* nothing */
        }
    }
    else
    {
        
    }

}


/*!
* @brief       Sets timer counter value
*
* @param       hwUnitId        Target timer hardware ID
* @param       CountValue      Initial counter value
*
* @retval      None
*
* @note        Directly writes to TMRx_CNT register
* @note        Allows precise timer position control
* @warning     May cause glitches if set during operation
*/
void Gpt_Hw_ConfigCounterValue(Gpt_TimerHwIdType hwUnitId,uint32_t CountValue)
{
    REG_WRITE32(TMR_CNT_REG_ADDR(hwUnitId),CountValue);
}


/*!
* @brief       Sets compare register value
*
* @param       hwUnitId        Target timer hardware ID
* @param       HwChannel       Channel number (1-4)
* @param       value           Compare threshold value
*
* @retval      None
*
* @note        Writes to channel-specific compare register (TMR_CCx)
* @note        Determines PWM duty cycle or capture trigger point
* @warning     Uses BIT_SET operation - may not clear previous value
* @note        Actual comparison: CNT == CCx
*/
void Gpt_Hw_ConfigCompareValue(Gpt_TimerHwIdType hwUnitId,uint8 HwChannel,Gpt_ValueType value)
{
    if (hwUnitId <= GPT_TMR4)
    {
        if ((uint8)1 == HwChannel)
        {
            REG_BIT_SET32(TMR_CC1_REG_ADDR(hwUnitId),value);
        }
        else if ((uint8)2 == HwChannel)
        {
            REG_BIT_SET32(TMR_CC2_REG_ADDR(hwUnitId),value);
        }
        else if ((uint8)3 == HwChannel)
        {
            REG_BIT_SET32(TMR_CC3_REG_ADDR(hwUnitId),value);
        }
        else if ((uint8)4 == HwChannel)
        {
            REG_BIT_SET32(TMR_CC4_REG_ADDR(hwUnitId),value);
        }
        else
        {
            /* nothing */
        }
    }
    else
    {
        
    }
}


/*!
* @brief       Controls compare match interrupt
*
* @param       hwUnitId        Target timer hardware ID
* @param       HwChannel       Channel number (1-4)
* @param       status          Interrupt state (ENABLE/DISABLE)
*
* @retval      None
*
* @note        Manages TMRx_DIEN[CCxIEN] bits
* @note        ENABLE: Generate interrupt on CNT==CCx match
* @note        DISABLE: Suppress compare match interrupts
* @note        Requires NVIC configuration for full interrupt handling
*/
void Gpt_Hw_ConfigCompareInterrupt(Gpt_TimerHwIdType hwUnitId,uint8 HwChannel,uint32 status)
{
    if (hwUnitId <= GPT_TMR4)
    {
        if ((uint32)ENABLE == status)
        {
            if ((uint8)1 == HwChannel)
            {
                REG_BIT_SET32(TMR_DIEN_REG_ADDR(hwUnitId),TMR_DIEN_CC1IEN_MASK);
            }
            else if ((uint8)2 == HwChannel)
            {
                REG_BIT_SET32(TMR_DIEN_REG_ADDR(hwUnitId),TMR_DIEN_CC2IEN_MASK);
            }
            else if ((uint8)3 == HwChannel)
            {
                REG_BIT_SET32(TMR_DIEN_REG_ADDR(hwUnitId),TMR_DIEN_CC3IEN_MASK);
            }
            else if ((uint8)4 == HwChannel)
            {
                REG_BIT_SET32(TMR_DIEN_REG_ADDR(hwUnitId),TMR_DIEN_CC4IEN_MASK);
            }
            else
            {
                /* nothing */
            }
        }
        else
        {
            if ((uint8)1 == HwChannel)
            {
                REG_BIT_CLEAR32(TMR_DIEN_REG_ADDR(hwUnitId),TMR_DIEN_CC1IEN_MASK);
            }
            else if ((uint8)2 == HwChannel)
            {
                REG_BIT_CLEAR32(TMR_DIEN_REG_ADDR(hwUnitId),TMR_DIEN_CC2IEN_MASK);
            }
            else if ((uint8)3 == HwChannel)
            {
                REG_BIT_CLEAR32(TMR_DIEN_REG_ADDR(hwUnitId),TMR_DIEN_CC3IEN_MASK);
            }
            else if ((uint8)4 == HwChannel)
            {
                REG_BIT_CLEAR32(TMR_DIEN_REG_ADDR(hwUnitId),TMR_DIEN_CC4IEN_MASK);
            }
            else
            {
                /* nothing */
            }
        }
    }
    else
    {
        if ((uint32)ENABLE == status)
        {
            REG_BIT_SET32(TMR_DIEN_REG_ADDR(hwUnitId),TMR_STS_UIFLG_MASK);
        }
        else
        {
            REG_BIT_CLEAR32(TMR_DIEN_REG_ADDR(hwUnitId),TMR_STS_UIFLG_MASK);
        }
    }


}


/*!
* @brief       Reads compare channel interrupt enable state
*
* @param       hwUnitId        Target timer hardware ID
* @param       HwChannel       Channel number (1-4)
*
* @retval      Current interrupt enable state (0: disabled, 1: enabled)
*
* @note        Queries TMRx_DIEN[CCxIEN] bit
* @note        Returns raw register value (not NVIC state)
* @note        Indicates if interrupt is enabled at timer peripheral level
*/
uint32 Gpt_Hw_GetCompareInterrupt(Gpt_TimerHwIdType hwUnitId,uint8 HwChannel)
{
    uint32 tempRetVal = 0;
    
    if (hwUnitId <= GPT_TMR4)
    {
        if ((uint8)1 == HwChannel)
        {
            tempRetVal = REG_BIT_GET32(TMR_DIEN_REG_ADDR(hwUnitId),TMR_DIEN_CC1IEN_MASK) >> TMR_DIEN_CC1IEN_SHIFT;
        }
        else if ((uint8)2 == HwChannel)
        {
            tempRetVal = REG_BIT_GET32(TMR_DIEN_REG_ADDR(hwUnitId),TMR_DIEN_CC2IEN_MASK) >> TMR_DIEN_CC2IEN_SHIFT;
        }
        else if ((uint8)3 == HwChannel)
        {
            tempRetVal = REG_BIT_GET32(TMR_DIEN_REG_ADDR(hwUnitId),TMR_DIEN_CC3IEN_MASK) >> TMR_DIEN_CC3IEN_SHIFT;
        }
        else if ((uint8)4 == HwChannel)
        {
            tempRetVal = REG_BIT_GET32(TMR_DIEN_REG_ADDR(hwUnitId),TMR_DIEN_CC4IEN_MASK) >> TMR_DIEN_CC4IEN_SHIFT;
        }
        else
        {
            /* nothing */
        }
    }
    else
    {
        tempRetVal = REG_BIT_GET32(TMR_DIEN_REG_ADDR(hwUnitId),TMR_DIEN_UIEN_MASK) >> TMR_DIEN_UIEN_SHIFT;
    }
    
    return tempRetVal;
}


/*!
* @brief       Reads compare channel interrupt flag status
*
* @param       hwUnitId        Target timer hardware ID
* @param       HwChannel       Channel number (1-4)
*
* @retval      Current interrupt flag state (0: not set, 1: pending)
*
* @note        Checks TMRx_STS[CCxIFLG] bit
* @note        Flag is set on counter match (CNT == CCx)
* @note        Flag must be manually cleared in ISR
* @note        Indicates pending interrupt at peripheral level
*/
uint32 Gpt_Hw_GetCompartChannelFlag(Gpt_TimerHwIdType hwUnitId,uint8 HwChannel)
{
    uint32 tempRetVal = 0;
    
    if (hwUnitId <= GPT_TMR4)
    {
        if ((uint8)1 == HwChannel)
        {
            tempRetVal = REG_BIT_GET32(TMR_STS_REG_ADDR(hwUnitId),TMR_STS_CC1IFLG_MASK) >> TMR_STS_CC1IFLG_SHIFT;
        }
        else if ((uint8)2 == HwChannel)
        {
            tempRetVal = REG_BIT_GET32(TMR_STS_REG_ADDR(hwUnitId),TMR_STS_CC2IFLG_MASK) >> TMR_STS_CC2IFLG_SHIFT;
        }
        else if ((uint8)3 == HwChannel)
        {
            tempRetVal = REG_BIT_GET32(TMR_STS_REG_ADDR(hwUnitId),TMR_STS_CC3IFLG_MASK) >> TMR_STS_CC3IFLG_SHIFT;
        }
        else if ((uint8)4 == HwChannel)
        {
            tempRetVal = REG_BIT_GET32(TMR_STS_REG_ADDR(hwUnitId),TMR_STS_CC4IFLG_MASK) >> TMR_STS_CC4IFLG_SHIFT;
        }
        else
        {
            /* nothing */
        }
    }
    else
    {
        tempRetVal = REG_BIT_GET32(TMR_STS_REG_ADDR(hwUnitId),TMR_STS_UIFLG_MASK) >> TMR_STS_UIFLG_SHIFT;
    }
    
    return tempRetVal;
}


/*!
* @brief       Reads current compare register value
*
* @param       hwUnitId        Target timer hardware ID
* @param       HwChannel       Channel number (1-4)
*
* @retval      Current compare threshold value
*
* @note        Reads from TMR_CCx register
* @note        Returned value may differ from set value in buffered modes
* @note        Represents active comparison threshold
*/
uint32 Gpt_Hw_GetCCRegValue(Gpt_TimerHwIdType hwUnitId,uint8 HwChannel)
{
    uint32 tempRetVal = 0;
    
    if (hwUnitId <= GPT_TMR4)
    {
        if ((uint8)1 == HwChannel)
        {
            tempRetVal = REG_READ32(TMR_CC1_REG_ADDR(hwUnitId));
        }
        else if ((uint8)2 == HwChannel)
        {
            tempRetVal = REG_READ32(TMR_CC2_REG_ADDR(hwUnitId));
        }
        else if ((uint8)3 == HwChannel)
        {
            tempRetVal = REG_READ32(TMR_CC3_REG_ADDR(hwUnitId));
        }
        else if ((uint8)4 == HwChannel)
        {
            tempRetVal = REG_READ32(TMR_CC4_REG_ADDR(hwUnitId));
        }
        else
        {
            /* nothing */
        }
    }
    else
    {

    }
    return tempRetVal;
}


/*!
* @brief       Controls timer counter operation
*
* @param       hwUnitId        Target timer hardware ID
* @param       status          Counter state (ENABLE: start, DISABLE: stop)
*
* @retval      None
*
* @note        Manages TMR_CTRL1[CNTEN] bit
* @note        ENABLE: Starts counting from current CNT value
* @note        DISABLE: Freezes counter at current position
* @note        Affects all timer functions (counting, PWM, capture)
*/
void Gpt_Hw_OperationCounter(Gpt_TimerHwIdType hwUnitId,uint32 status)
{
    if ((uint32)ENABLE == status)
    {
        REG_BIT_SET32(TMR_CTRL1_REG_ADDR(hwUnitId),TMR_CTRL1_CNTEN_MASK);
    }
    else
    {
        REG_BIT_CLEAR32(TMR_CTRL1_REG_ADDR(hwUnitId),TMR_CTRL1_CNTEN_MASK);
    }
}


/*!
* @brief       Reads current timer counter value
*
* @param       hwUnitId        Target timer hardware ID
*
* @retval      Current counter value
*
* @note        Reads from TMRx_CNT register
* @note        Value increments/decrements in real-time when counter is running
* @note        Reading during write operations may return unstable values
*/
Gpt_ValueType Gpt_Hw_NowCounterValue(Gpt_TimerHwIdType hwUnitId)
{
    Gpt_ValueType tempRetVal = 0;
    
    tempRetVal = REG_READ32(TMR_CNT_REG_ADDR(hwUnitId));
    
    return tempRetVal;
}

/**@} end of group GPT_Fuctions */

#define GPT_STOP_SEC_CODE
#include "Gpt_MemMap.h"

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

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