/*!
* @file     Adc_Hw.c
*
* @version  1.0.0
*
* @brief    AUTOSAR Adc 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 "Adc.h"
#include "Adc_Hw.h"
#include "Adc_Reg.h"

#if (ADC_HARDWARE_TRIG_API == STD_ON)
#include "Pdl_TmrReg.h"
#endif

#if (ADC_DMA_TRANSFER_MODE == STD_ON)
#include "CDD_Pdl.h"
#endif


/** @addtogroup G32A10xx_StdPeriphDriver
  @{
*/

/** @defgroup ADC_Driver
  * @brief ADC driver modules
  @{
*/

/** @defgroup ADC_Macros
  @{
*/
/*******************************************************************************
                    VENDOR ID & AUTOSAR VERSION INFO
*******************************************************************************/
/** Vendor ID (vendorId) of the dedicated implementation of this module according to the AUTOSAR vendor list. */
#define ADC_HW_VENDOR_ID                              0x00C1U
/** Major version number of AUTOSAR release on which the appropriate implementation is based on. */
#define ADC_HW_AR_RELEASE_MAJOR_VERSION               0x04U
/** Minor version number of AUTOSAR release on which the appropriate implementation is based on. */
#define ADC_HW_AR_RELEASE_MINOR_VERSION               0x04U
/** Revision version number of AUTOSAR release on which the appropriate implementation is based on. */
#define ADC_HW_AR_RELEASE_REVISION_VERSION            0x00U
/** Major version number of the vendor specific implementation of the module. The numbering is vendor specific. */ 
#define ADC_HW_SW_MAJOR_VERSION                       0x01U
/** Minor version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define ADC_HW_SW_MINOR_VERSION                       0x00U
/** Patch level version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define ADC_HW_SW_PATCH_VERSION                       0x00U

/**@} end of group ADC_Macros */
/*******************************************************************************
                              GLOBAL VARIABLE
*******************************************************************************/
#define ADC_START_SEC_CONST_32
#include "Adc_MemMap.h"

/** @defgroup ADC_Variable
  @{
*/

/** The ADC hardware units Base address */
CONST(uint32, ADC_CONST) ADC_BASEADDR_ARR[1] ={ADC1_BASEADDR};

/**@} end of group ADC_Variable */

#define ADC_STOP_SEC_CONST_32
#include "Adc_MemMap.h"
/*******************************************************************************
                            GLOBAL FUNCTIONS
*******************************************************************************/
#define ADC_START_SEC_CODE
#include "Adc_MemMap.h"

/** @defgroup ADC_Fuctions
  @{
*/

/*!
* @brief       Configures ADC clock mode
*
* @param       adc         ADC instance ID
* @param       adcClock    Clock mode (ASYNC/SYNC/...)
*
* @retval      None
*
* @note        Sets ADC_CFG2[CLKCFG] bits
* @note        Determines ADC core clock source
*/
void Adc_Hw_ClockModeConfig(uint8 adc,Adc_ClkModeType adcClock)
{
    REG_RMW32(ADC_CFG2_REG_ADDR(adc), ADC_CFG2_CLKCFG_MASK, (uint32)adcClock);
}


/*!
* @brief       Configures ADC resolution
*
* @param       adc         ADC instance ID
* @param       resolution  Conversion resolution (8/10/12 bit)
*
* @retval      None
*
* @note        Sets ADC_CFG1[DATARESCFG] bits
* @note        Affects conversion time and accuracy
*/
void Adc_Hw_CataResolutionConfig(uint8 adc,Adc_ResolutionType resolution)
{
    REG_BIT_SET32(ADC_CFG1_REG_ADDR(adc), (uint32)((uint32)resolution << ADC_CFG1_DATARESCFG_SHIFT));
}


/*!
* @brief       Selects ADC trigger source and polarity
*
* @param       adc         ADC instance ID
* @param       trigger     Trigger source (SW/hardware)
* @param       hwSignal    Trigger polarity (rising/falling)
*
* @retval      None
*
* @note        SW trigger: clears EXTPOLSEL
* @note        HW trigger: sets EXTPOLSEL with specified polarity
* @note        Configures ADC_CFG1[EXTPOLSEL]
*/
void Adc_Hw_TriggerSelect(uint8 adc,Adc_TriggerSourceType trigger,Adc_HwTriggerSignalType hwSignal)
{
    if (ADC_TRIGG_SRC_SW == trigger)
    {
        REG_BIT_CLEAR32(ADC_CFG1_REG_ADDR(adc), ADC_CFG1_EXTPOLSEL_MASK);
    }
    else
    {
        REG_BIT_SET32(ADC_CFG1_REG_ADDR(adc), (uint32)((uint32)hwSignal << ADC_CFG1_EXTPOLSEL_SHIFT));
    }
}


/*!
* @brief       Selects trigger event type
*
* @param       adc         ADC instance ID
* @param       event       Trigger edge type (rising/falling/both)
*
* @retval      None
*
* @note        Sets ADC_CFG1[EXTTRGSEL] bits
* @note        Defines which trigger edge starts conversion
*/
void Adc_Hw_TriggerEvent(uint8 adc,Adc_TriggerEventType event)
{
    REG_BIT_SET32(ADC_CFG1_REG_ADDR(adc), (uint32)((uint32)event << ADC_CFG1_EXTTRGSEL_SHIFT));
}


/*!
* @brief       Enables/disables reverse scan direction
*
* @param       adc         ADC instance ID
* @param       status      State (ENABLE/DISABLE)
*
* @retval      None
*
* @note        ENABLE: Scan sequence from high to low channels
* @note        DISABLE: Scan sequence from low to high channels
* @note        Controls ADC_CFG1[SCANSEQDIR]
*/
void Adc_Hw_EnableBackDirection(uint8 adc,uint8 status)
{
    if ((uint8)ENABLE == status)
    {
        REG_BIT_SET32(ADC_CFG1_REG_ADDR(adc),ADC_CFG1_SCANSEQDIR_MASK);
    }
    else
    {
        REG_BIT_CLEAR32(ADC_CFG1_REG_ADDR(adc),ADC_CFG1_SCANSEQDIR_MASK);
    }
}


/*!
* @brief       Selects conversion mode
*
* @param       adc         ADC instance ID
* @param       mode        Conversion mode (single/continuous)
*
* @retval      None
*
* @note        CONTINUOUS: Sets ADC_CFG1[CMODESEL]
* @note        SINGLE: Clears ADC_CFG1[CMODESEL]
* @note        Continuous mode keeps ADC running after conversion
*/
void Adc_Hw_SelectMode(uint8 adc,Adc_GroupConvModeType mode)
{
    if (ADC_CONV_MODE_CONTINUOUS == mode)
    {
        REG_BIT_SET32(ADC_CFG1_REG_ADDR(adc),ADC_CFG1_CMODESEL_MASK);
    }
    else
    {
        REG_BIT_CLEAR32(ADC_CFG1_REG_ADDR(adc),ADC_CFG1_CMODESEL_MASK);
    }
}


/*!
* @brief       Enables/disables conversion delay
*
* @param       adc         ADC instance ID
* @param       status      State (ENABLE/DISABLE)
*
* @retval      None
*
* @note        ENABLE: Adds delay between conversions
* @note        DISABLE: Immediate conversion start
* @note        Controls ADC_CFG1[WAITCEN]
*/
void Adc_Hw_EnableDelayConversion(uint8 adc,uint8 status)
{
    if ((uint8)ENABLE == status)
    {
        REG_BIT_SET32(ADC_CFG1_REG_ADDR(adc),ADC_CFG1_WAITCEN_MASK);
    }
    else
    {
        REG_BIT_CLEAR32(ADC_CFG1_REG_ADDR(adc),ADC_CFG1_WAITCEN_MASK);
    }
}


/*!
* @brief       Configures data alignment
*
* @param       adc         ADC instance ID
* @param       alignment   Data alignment (left/right)
*
* @retval      None
*
* @note        LEFT: Sets ADC_CFG1[DALIGCFG]
* @note        RIGHT: Clears ADC_CFG1[DALIGCFG]
* @note        Affects result register formatting
*/
void Adc_Hw_SelectDataAlignment(uint8 adc,Adc_ResultAlignmentType alignment)
{
    if (ADC_ALIGN_LEFT == alignment)
    {
        REG_BIT_SET32(ADC_CFG1_REG_ADDR(adc),ADC_CFG1_DALIGCFG_MASK);
    }
    else
    {
        REG_BIT_CLEAR32(ADC_CFG1_REG_ADDR(adc),ADC_CFG1_DALIGCFG_MASK);
    }
}


/*!
* @brief       Sets sampling time
*
* @param       adc         ADC instance ID
* @param       adcTime     Sampling time cycles
*
* @retval      None
*
* @note        Writes directly to ADC_SMPTIM register
* @note        Longer times improve accuracy at high impedance
* @note        Shorter times allow faster conversions
*/
void Adc_Hw_SelectSamplingTime(uint8 adc,Adc_SamplingTimeType adcTime)
{
    REG_RMW32(ADC_SMPTIM_REG_ADDR(adc), ADC_SMPTIM_SMPCYCSEL_MASK, (uint32)adcTime);
}


/*!
* @brief       Enables/disables ADC channel
*
* @param       adc         ADC instance ID
* @param       channel     Channel number
* @param       status      Channel state (ENABLE/DISABLE)
*
* @retval      None
*
* @note        ENABLE: Sets channel bit in CHSEL register
* @note        DISABLE: Clears channel bit in CHSEL register
* @note        Channel numbers are bit-mapped (1<<channel)
*/
void Adc_Hw_SelectChannel(uint8 adc,Adc_ChannelType channel,uint8 status)
{
    if ((uint8)ENABLE == status)
    {
        REG_BIT_SET32(ADC_CHSEL_REG_ADDR(adc),(uint32)channel);
    }
    else
    {
        REG_BIT_CLEAR32(ADC_CHSEL_REG_ADDR(adc),(uint32)channel);
    }
}


/*!
* @brief       Clears ADC control register
*
* @param       adc         ADC instance ID
*
* @retval      None
*
* @note        Resets ADC_CTRL register to 0x00
* @note        Typically used during initialization
*/
void Adc_Hw_clearCtrlReg(uint8 adc)
{
    REG_WRITE32(ADC_CTRL_REG_ADDR(adc),0x00);
}


/*!
* @brief       Enables/disables ADC peripheral
*
* @param       adc         ADC instance ID
* @param       status      ADC state (ENABLE/DISABLE)
*
* @retval      None
*
* @note        ENABLE: Sets ADC_CTRL[ADCEN]
* @note        DISABLE: Clears ADC_CTRL[ADCEN]
* @note        Powers up ADC analog circuitry
*/
void Adc_Hw_EnableADC(uint8 adc,uint8 status)
{
    if ((uint8)ENABLE == status)
    {
        REG_BIT_SET32(ADC_CTRL_REG_ADDR(adc),ADC_CTRL_ADCEN_MASK);
    }
    else
    {
        REG_BIT_CLEAR32(ADC_CTRL_REG_ADDR(adc),ADC_CTRL_ADCEN_MASK);
    }
}


/*!
* @brief       Controls ADC disable mode
*
* @param       adc         ADC instance ID
* @param       status      Disable mode (ENABLE/DISABLE)
*
* @retval      None
*
* @note        ENABLE: Sets ADC_CTRL[ADCD]
* @note        DISABLE: Clears ADC_CTRL[ADCD]
* @note        When enabled, prevents accidental ADC wakeup
*/
void Adc_Hw_DisableADC(uint8 adc,uint8 status)
{
    if ((uint8)ENABLE == status)
    {
        REG_BIT_SET32(ADC_CTRL_REG_ADDR(adc),ADC_CTRL_ADCD_MASK);
    }
    else
    {
        REG_BIT_CLEAR32(ADC_CTRL_REG_ADDR(adc),ADC_CTRL_ADCD_MASK);
    }
}


/*!
* @brief       adc delay function
*
* @param       us      delay value
*
* @retval      None
*/
static void Adc_Hw_delay(volatile uint32 us)
{
    volatile uint32 count = 0;
    uint32 loopCount = 8U * us;
    
    while(count < loopCount)
    {
        __asm("nop");
        count = count + (uint32)1;
    }
}


/*!
* @brief       Reads ADC calibration factor
*
* @param       adc         ADC instance ID
*
* @retval      Calibration value (0 if timeout)
*
* @note        Performs full calibration sequence:
*              1. Clear CAL bit
*              2. Set CAL bit to start calibration
*              3. Wait for CAL bit clear (timeout protected)
*              4. Read calibration value from data register
* @warning     Blocking wait with delay - consider RTOS implications
*/
uint32_t Adc_Hw_ReadCalibrationFactor(uint8 adc)
{
    uint32_t temp = 0U;
    uint32_t counter = 0U;
    uint32_t status = 0U;

    REG_BIT_CLEAR32(ADC_CTRL_REG_ADDR(adc), ADC_CTRL_CAL_MASK);

    REG_BIT_SET32(ADC_CTRL_REG_ADDR(adc), ADC_CTRL_CAL_MASK);

    while (counter < ADC_CALIBRATION_TIMEOUT)
    {
        status = REG_BIT_GET32(ADC_CTRL_REG_ADDR(adc), ADC_CTRL_CAL_MASK);
        if (status == 0U)
        {
            break;
        }
        else
        {
            /* nothing */
        }
        counter++;
        Adc_Hw_delay(10U);  
    }

    if (status == 0U)
    {
        temp = REG_READ32(ADC_DATA_REG_ADDR(adc));
    }
    else
    {
        temp = 0U;
    }

    return temp;
}

#if (STD_ON == ADC_ENABLE_INTERRUPT)
/*!
* @brief       Controls ADC interrupt enable state
*
* @param       adc         ADC instance ID
* @param       interrupt   Interrupt type mask
* @param       status      State (ENABLE/DISABLE)
*
* @retval      None
*
* @note        Manages ADC_IEN register bits
* @note        Interrupt parameter is bitmask (multiple interrupts)
* @note        Must configure NVIC separately for full interrupt handling
*/
void Adc_Hw_OperationInterrupt(uint8 adc,Adc_IntType interrupt, uint8 status)
{
    if ((uint8)ENABLE == status)
    {
        REG_BIT_SET32(ADC_IEN_REG_ADDR(adc),(uint32)interrupt);
    }
    else
    {
        REG_BIT_CLEAR32(ADC_IEN_REG_ADDR(adc),(uint32)interrupt);
    }
}
#endif

/*!
* @brief       Checks if interrupt is both enabled and pending
*
* @param       adc         ADC instance ID
* @param       flag        Interrupt flag type mask
*
* @retval      SET (1) if both enabled and pending, else RESET (0)
*
* @note        Dual-check mechanism:
*              1. Verifies interrupt is enabled (IEN register)
*              2. Checks status flag is set (STS register)
* @note        Returns logical AND of enable and status flags
*/
uint8_t Adc_Hw_GetInterruptFlag(uint8 adc,Adc_IntFlgType flag)
{
    uint32_t intEnable = 0;
    uint32_t intStatus = 0;
    uint8_t tempVal = RESET;

    intEnable = REG_READ32(ADC_IEN_REG_ADDR(adc))&(uint32_t)flag;
    intStatus = REG_READ32(ADC_STS_REG_ADDR(adc))&(uint32_t)((uint32)flag & (uint32_t)0xff);

    if ((uint32)0 != (intEnable & intStatus))
    {
        tempVal = SET;
    }
    else
    {
        tempVal = RESET;
    }
    return tempVal;
}


/*!
* @brief       Writes to interrupt status register
*
* @param       adc         ADC instance ID
* @param       flag        Interrupt flags to set
*
* @retval      None
*
* @note        Directly writes to ADC_STS register
* @note        Typically used to clear flags by writing 1 to bit positions
* @warning     Overwrites entire register - use with caution
*/
void Adc_Hw_WriteInterruptFlag(uint8 adc,Adc_IntFlgType flag)
{
    REG_BIT_SET32(ADC_STS_REG_ADDR(adc),(uint32)flag);
}


/*!
* @brief       Starts/stops ADC conversion
*
* @param       adc         ADC instance ID
* @param       status      Conversion state (ENABLE: start, DISABLE: stop)
*
* @retval      None
*
* @note        Controls ADC_CTRL[STARTCEN] bit
* @note        ENABLE: Initiates conversion sequence
* @note        DISABLE: Halts current conversion
*/
void Adc_Hw_EnableConversion(uint8 adc,uint32 status)
{
    if ((uint8)ENABLE == status)
    {
        REG_BIT_SET32(ADC_CTRL_REG_ADDR(adc),ADC_CTRL_STARTCEN_MASK);
    }
    else
    {
        REG_BIT_SET32(ADC_CTRL_REG_ADDR(adc),ADC_CTRL_STOPCEN_MASK);
    }
}


/*!
* @brief       Checks if any channel is enabled
*
* @param       adc         ADC instance ID
*
* @retval      SET (1) if any channel selected, else RESET (0)
*
* @note        Reads ADC_CHSEL register value
* @note        Returns boolean state (non-zero = enabled)
*/
uint8_t Adc_Hw_GetChannelNum(uint8 adc)
{
    uint8_t tempVal = RESET;
    if ((uint32)0 != REG_READ32(ADC_CHSEL_REG_ADDR(adc)))
    {
        tempVal = SET;
    }
    else
    {
        tempVal = RESET;
    }
    return tempVal;
}

/*!
* @brief       Enables/disables ADC DMA transfer
*
* @param       adc         ADC instance ID
* @param       status      DMA state (ENABLE/DISABLE)
*
* @retval      None
*
* @note        Controls ADC_CFG1[DMAEN] bit
* @note        ENABLE: Triggers DMA request after each conversion
* @note        DISABLE: Disables DMA interface
* @note        Requires DMA controller configuration
*/
void Adc_Hw_OperationDma(uint8 adc, uint8 status)
{
    if ((uint8)ENABLE == status)
    {
        REG_BIT_SET32(ADC_CFG1_REG_ADDR(adc),ADC_CFG1_DMAEN_MASK);
    }
    else
    {
        REG_BIT_CLEAR32(ADC_CFG1_REG_ADDR(adc),ADC_CFG1_DMAEN_MASK);
    }
}

/*!
* @brief       Enables/disables DMA circular mode
*
* @param       adc         ADC instance ID
* @param       status      Circular mode state (ENABLE/DISABLE)
*
* @retval      None
*
* @note        Controls ADC_CFG1[DMACFG] bit
* @note        ENABLE: Continuous circular buffer mode
* @note        DISABLE: Single transfer mode
* @note        Requires OperationDma(ENABLE) to take effect
 */
void Adc_Hw_EnableDmaLoopMode(uint8 adc, uint8 status)
{
    if ((uint8)ENABLE == status)
    {
        REG_BIT_SET32(ADC_CFG1_REG_ADDR(adc),ADC_CFG1_DMACFG_MASK);
    }
    else
    {
        REG_BIT_CLEAR32(ADC_CFG1_REG_ADDR(adc),ADC_CFG1_DMACFG_MASK);
    }
}


#if (ADC_HARDWARE_TRIG_API == STD_ON)
/*!
* @brief       Configures timer TRGO signal output
*
* @param       hwUnitId    Timer hardware ID
* @param       TrgoSel     Trigger output selection
*
* @retval      None
*
* @note        Sets TMR_CTRL2[MMSEL] bits
* @note        Connects timer to ADC trigger system
*/
void Adc_Hw_SelectTRGOSignal(Adc_TimerHwIdType hwUnitId,Adc_TRGOSignalType TrgoSel)
{
    REG_BIT_SET32(TMR_CTRL2_REG_ADDR(hwUnitId),(uint32)((uint32)TrgoSel << TMR_CTRL2_MMSEL_SHIFT));
}

#endif



#if (STD_ON == ADC_LIMIT_VALUE_DETECTION_ENABLE)
/*!
* @brief       Enables/disables analog watchdog
*
* @param       adc         ADC instance ID
* @param       status      AWD state (ENABLE/DISABLE)
*
* @retval      None
*
* @note        Manages ADC_CFG1[AWDEN] bit
* @note        Must configure thresholds and channel separately
*/
void ADC_Hw_OperationAnalogWatchdog(uint8 adc, uint8 status)
{
    if (ENABLE == status)
    {
        REG_BIT_SET32(ADC_CFG1_REG_ADDR(adc),ADC_CFG1_AWDEN_MASK);
    }
    else
    {
        REG_BIT_CLEAR32(ADC_CFG1_REG_ADDR(adc),ADC_CFG1_AWDEN_MASK);
    }
}


/*!
* @brief       Sets analog watchdog lower threshold
*
* @param       adc           ADC instance ID
* @param       lowThreshold  Lower limit value (raw ADC units)
*
* @retval      None
*
* @note        Sets ADC_AWDT[AWDLT] field
* @note        Value should be left-aligned if using left alignment
*/
void ADC_Hw_AnalogWatchdogLowThreshold(uint8 adc, uint16 lowThreshold)
{
    REG_BIT_SET32(ADC_AWDT_REG_ADDR(adc),lowThreshold << ADC_AWDT_AWDLT_SHIFT);
}


/*!
* @brief       Sets analog watchdog lower threshold
*
* @param       adc           ADC instance ID
* @param       lowThreshold  Lower limit value (raw ADC units)
*
* @retval      None
*
* @note        Sets ADC_AWDT[AWDLT] field
* @note        Value should be left-aligned if using left alignment
*/
void ADC_Hw_AnalogWatchdogHighThreshold(uint8 adc, uint16 highThreshold)
{
    REG_BIT_SET32(ADC_AWDT_REG_ADDR(adc),highThreshold << ADC_AWDT_AWDHT_SHIFT);
}


/*!
* @brief       Enables/disables single-channel watchdog mode
*
* @param       adc         ADC instance ID
* @param       status      Channel mode state (ENABLE/DISABLE)
*
* @retval      None
*
* @note        Controls ADC_CFG1[AWDCHEN] bit
* @note        ENABLE: Watchdog monitors single channel
* @note        DISABLE: Watchdog monitors all channels
*/
void ADC_Hw_OperationAnalogWatchdogSingleChannel(uint8 adc, uint8 status)
{
    if (ENABLE == status)
    {
        REG_BIT_SET32(ADC_CFG1_REG_ADDR(adc),ADC_CFG1_AWDCHEN_MASK);
    }
    else
    {
        REG_BIT_CLEAR32(ADC_CFG1_REG_ADDR(adc),ADC_CFG1_AWDCHEN_MASK);
    }   
}


/*!
* @brief       Selects analog watchdog channel
*
* @param       adc         ADC instance ID
* @param       channel     Channel number (0-18)
*
* @retval      None
*
* @note        Sets ADC_CFG1[AWDCHSEL] field
* @note        Only effective in single-channel mode
* @note        Channels 0-15: regular, 16-18: internal sensors
*/
void ADC_Hw_AnalogWatchdogSingleChannel(uint8 adc, uint32 channel)
{
    switch (channel)
    {
        case ADC_CHANNEL_0:
            REG_BIT_SET32(ADC_CFG1_REG_ADDR(adc),0 << ADC_CFG1_AWDCHSEL_SHIFT);
            break;
        case ADC_CHANNEL_1:
            REG_BIT_SET32(ADC_CFG1_REG_ADDR(adc),1 << ADC_CFG1_AWDCHSEL_SHIFT);
            break;
        case ADC_CHANNEL_2:
            REG_BIT_SET32(ADC_CFG1_REG_ADDR(adc),2 << ADC_CFG1_AWDCHSEL_SHIFT);
            break;
        case ADC_CHANNEL_3:
            REG_BIT_SET32(ADC_CFG1_REG_ADDR(adc),3 << ADC_CFG1_AWDCHSEL_SHIFT);
            break;
        case ADC_CHANNEL_4:
            REG_BIT_SET32(ADC_CFG1_REG_ADDR(adc),4 << ADC_CFG1_AWDCHSEL_SHIFT);
            break;
        case ADC_CHANNEL_5:
            REG_BIT_SET32(ADC_CFG1_REG_ADDR(adc),5 << ADC_CFG1_AWDCHSEL_SHIFT);
            break;
        case ADC_CHANNEL_6:
            REG_BIT_SET32(ADC_CFG1_REG_ADDR(adc),6 << ADC_CFG1_AWDCHSEL_SHIFT);
            break;
        case ADC_CHANNEL_7:
            REG_BIT_SET32(ADC_CFG1_REG_ADDR(adc),7 << ADC_CFG1_AWDCHSEL_SHIFT);
            break;
        case ADC_CHANNEL_8:
            REG_BIT_SET32(ADC_CFG1_REG_ADDR(adc),8 << ADC_CFG1_AWDCHSEL_SHIFT);
            break;
        case ADC_CHANNEL_9:
            REG_BIT_SET32(ADC_CFG1_REG_ADDR(adc),9 << ADC_CFG1_AWDCHSEL_SHIFT);
            break;
        case ADC_CHANNEL_10:
            REG_BIT_SET32(ADC_CFG1_REG_ADDR(adc),10 << ADC_CFG1_AWDCHSEL_SHIFT);
            break;
        case ADC_CHANNEL_11:
            REG_BIT_SET32(ADC_CFG1_REG_ADDR(adc),11 << ADC_CFG1_AWDCHSEL_SHIFT);
            break;
        case ADC_CHANNEL_12:
            REG_BIT_SET32(ADC_CFG1_REG_ADDR(adc),12 << ADC_CFG1_AWDCHSEL_SHIFT);
            break;
        case ADC_CHANNEL_13:
            REG_BIT_SET32(ADC_CFG1_REG_ADDR(adc),13 << ADC_CFG1_AWDCHSEL_SHIFT);
            break;
        case ADC_CHANNEL_14:
            REG_BIT_SET32(ADC_CFG1_REG_ADDR(adc),14 << ADC_CFG1_AWDCHSEL_SHIFT);
            break;
        case ADC_CHANNEL_15:
            REG_BIT_SET32(ADC_CFG1_REG_ADDR(adc),15 << ADC_CFG1_AWDCHSEL_SHIFT);
            break;
        case ADC_CHANNEL_16:
            REG_BIT_SET32(ADC_CFG1_REG_ADDR(adc),16 << ADC_CFG1_AWDCHSEL_SHIFT);
            break;
        case ADC_CHANNEL_17:
            REG_BIT_SET32(ADC_CFG1_REG_ADDR(adc),17 << ADC_CFG1_AWDCHSEL_SHIFT);
            break;
        case ADC_CHANNEL_18:
            REG_BIT_SET32(ADC_CFG1_REG_ADDR(adc),18 << ADC_CFG1_AWDCHSEL_SHIFT);
            break;
        default:
            /* nothing */
            break;
    }
}
#endif

/*!
* @brief          This function is used to start the channel conversion whose trigger source is software.
*
* @param[in]      Group    Group ID.
*
*/
void Adc_Hw_StartGroupConversion(Adc_GroupType Group)
{
    uint8 tempAdc = g_adcConfigPtr->adcSelect;
    const Adc_GroupConfigType* group = &g_adcConfigPtr->addGroupCfg[Group];
    uint8 tempNum = 0;
    
    Adc_Hw_TriggerSelect(tempAdc,ADC_TRIGG_SRC_SW,ADC_HW_TRIG_INVALID);
    Adc_Hw_EnableBackDirection(tempAdc,group->enableBack);
    
#if (STD_ON == ADC_LIMIT_VALUE_DETECTION_ENABLE)
    if (group->AnalogWatchdog == TRUE)
    {
        ADC_Hw_OperationAnalogWatchdog(tempAdc,ENABLE);
        ADC_Hw_AnalogWatchdogLowThreshold(tempAdc,group->lowThreshold);
        ADC_Hw_AnalogWatchdogHighThreshold(tempAdc,group->highThreshold);
        ADC_Hw_OperationAnalogWatchdogSingleChannel(tempAdc,ENABLE);
        ADC_Hw_AnalogWatchdogSingleChannel(tempAdc,group->channelCfg[0].adcHwChannel);
    }
#endif
    
    if (ADC_CONV_MODE_ONESHOT == group->converMode)
    {
        Adc_Hw_SelectMode(tempAdc,ADC_CONV_MODE_ONESHOT);
    }
    else if ((ADC_CONV_MODE_CONTINUOUS == group->converMode) &&
             (ADC_ACCESS_MODE_STREAMING == group->accessModeCfg.accessMode) &&
             (ADC_STREAM_BUFFER_LINEAR == group->accessModeCfg.streamMode))
    {
        Adc_Hw_SelectMode(tempAdc,ADC_CONV_MODE_ONESHOT);
    }
    else if ((ADC_CONV_MODE_CONTINUOUS == group->converMode) &&
             (ADC_ACCESS_MODE_SINGLE == group->accessModeCfg.accessMode))
    {
        Adc_Hw_SelectMode(tempAdc,ADC_CONV_MODE_ONESHOT);
    }
    else
    {
        Adc_Hw_SelectMode(tempAdc,ADC_CONV_MODE_CONTINUOUS);
    }
    Adc_Hw_EnableDelayConversion(tempAdc,ENABLE);
    Adc_Hw_SelectSamplingTime(tempAdc,group->channelCfg[0].sampleTime);
    
    for (tempNum = 0; tempNum < group->channelCount; tempNum++)
    {
        Adc_Hw_SelectChannel(tempAdc,group->channelCfg[tempNum].adcHwChannel,ENABLE);
    }
    
    g_adcActiveGroup = Group;
    
#if (ADC_ENABLE_INTERRUPT == STD_OFF)
#if (ADC_DMA_TRANSFER_MODE == STD_ON)
    if (g_adcConfigPtr->selectTranMode == ADC_TRANS_MODE_DMA)
    {
        Pdl_TopDmaChDis(DMA_HW_CH1);
        
        Adc_Hw_DmaConfig(Group);
        Pdl_TopDmaChDataNumSet(DMA_HW_CH1, group->channelCount);
        Pdl_TopDmaMAddrRefresh(DMA_HW_CH1, (uint32_t)group->adcGroupResultBuffer[Group]);
        
        Pdl_TopDmaChEn(DMA_HW_CH1);
    }
#endif
#endif    
    
    Adc_Hw_EnableConversion(tempAdc,ENABLE);
#if (STD_ON == ADC_ENABLE_INTERRUPT)
    Adc_Hw_OperationInterrupt(tempAdc,ADC_INT_EOC,ENABLE);
#endif
    Adc_Hw_EnableADC(tempAdc,ENABLE);
}

/*!
* @brief          This function is used to stop the channel conversion whose trigger source is software.
* 
* @param[in]      Group    Group ID.
*
*/
void Adc_Hw_StopGroupConversion(Adc_GroupType Group)
{
    uint8 tempAdc = g_adcConfigPtr->adcSelect;
    const Adc_GroupConfigType* group = &g_adcConfigPtr->addGroupCfg[Group];
    uint8 tempNum = 0;
    
    Adc_Hw_EnableBackDirection(tempAdc,DISABLE);
    Adc_Hw_SelectMode(tempAdc,ADC_CONV_MODE_ONESHOT);
    Adc_Hw_SelectSamplingTime(tempAdc,ADC_SAMPLE_TIME_1_5);
    
    for (tempNum = 0; tempNum < group->channelCount; tempNum++)
    {
        Adc_Hw_SelectChannel(tempAdc,group->channelCfg[tempNum].adcHwChannel,DISABLE);
    }
    
#if (STD_ON == ADC_LIMIT_VALUE_DETECTION_ENABLE)
    ADC_Hw_OperationAnalogWatchdog(tempAdc,DISABLE);
    ADC_Hw_OperationAnalogWatchdogSingleChannel(tempAdc,DISABLE);
    ADC_Hw_AnalogWatchdogSingleChannel(tempAdc,ADC_CHANNEL_0);
#endif
    Adc_Hw_EnableConversion(tempAdc,DISABLE);
    Adc_Hw_WriteInterruptFlag(tempAdc,ADC_INT_FLAG_EOC);
#if (STD_ON == ADC_ENABLE_INTERRUPT)
    Adc_Hw_OperationInterrupt(tempAdc,ADC_INT_EOC,DISABLE);
#endif
    Adc_Hw_EnableDelayConversion(tempAdc,DISABLE);
    Adc_Hw_DisableADC(tempAdc,ENABLE);
}

#if (ADC_DMA_TRANSFER_MODE == STD_ON)

void Adc_Hw_TopDmaPAddrRefresh(uint8 adc)
{
    Pdl_TopDmaPAddrRefresh(DMA_HW_CH1, ADC_DATA_REG_ADDR(adc));
}

FUNC(void, USART_CODE) Adc_Hw_DmaConfig(Adc_GroupType Group)
{
    Pdl_DmaChHwConfigType tempDmaConfig;
    const Adc_GroupConfigType* group = &g_adcConfigPtr->addGroupCfg[Group];
    
    tempDmaConfig.memAddr = 0;
    tempDmaConfig.periphAddr = 0;
    tempDmaConfig.dir = (Pdl_DmaDirType)DMA_DIR_PERIPHERAL;
    tempDmaConfig.bufSize = 0;
    tempDmaConfig.memDataWidth = (Pdl_DmaMemDataSizeType)DMA_MEMORY_DATASIZE_HALFWORD;
    tempDmaConfig.periphDataWidth = (Pdl_DmaPeriDataSizeType)DMA_PERIPHERAL_DATASIZE_HALFWORD;
    tempDmaConfig.memInc = (Pdl_DmaMemIncType)DMA_MEMORY_INC_ENABLE;
    tempDmaConfig.periphInc = (Pdl_DmaPeripheralIncType)DMA_PERIPHERAL_INC_DISABLE;
    
    if (group->converMode == ADC_CONV_MODE_CONTINUOUS)
    {
        tempDmaConfig.circularMode = (Pdl_DmaCircEnStsType)DMA_CIRCULAR_ENABLE;
    }
    else
    {
        tempDmaConfig.circularMode = (Pdl_DmaCircEnStsType)DMA_CIRCULAR_DISABLE;
    }
    
    tempDmaConfig.priority = (Pdl_DmaProLevType)DMA_PRIORITY_LEVEL_HIGHT;
    tempDmaConfig.mem2Mem = (Pdl_DmaM2mEnStsType)DMA_M2M_DISABLE;
    
    /** configure the DMA */
    Pdl_TopDmaChConfig(DMA_HW_CH1, &tempDmaConfig);
    
    /** Disable Request of RxDma */
    Pdl_Dma_ClrStsFlag(DMA1_INT_FLAG_TF1);
    
    Adc_Hw_TopDmaPAddrRefresh(0);
}
#endif
/**@} end of group ADC_Fuctions */

#define ADC_STOP_SEC_CODE
#include "Adc_MemMap.h"

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

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