Newer
Older
mbed-os / targets / TARGET_Cypress / TARGET_PSOC6 / mtb-pdl-cat1 / drivers / source / cy_sar.c
@Dustin Crossman Dustin Crossman on 4 Jun 2021 56 KB Fix file modes.
/***************************************************************************//**
* \file cy_sar.c
* \version 2.0.1
*
* Provides the public functions for the API for the SAR driver.
*
********************************************************************************
* \copyright
* Copyright 2017-2021 Cypress Semiconductor Corporation
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
#include "cy_sar.h"

#ifdef CY_IP_MXS40PASS_SAR

#if defined(__cplusplus)
extern "C" {
#endif

CY_MISRA_DEVIATE_BLOCK_START('MISRA C-2012 Rule 11.3', 81, \
'SAR_Type will typecast to either SAR_V1_Type or SAR_V2_Type but not both on PDL initialization based on the target device at compile time.');

#define CHAN_NUM(chan)           ((chan) < CY_SAR_NUM_CHANNELS)
#define IS_RIGHT_ALIGN           (!_FLD2BOOL(SAR_SAMPLE_CTRL_LEFT_ALIGN, SAR_SAMPLE_CTRL(base)))

#define CY_SAR_MASK                 (CY_SAR_SAR0 | \
                                     CY_SAR_SAR1 | \
                                     CY_SAR_SAR2 | \
                                     CY_SAR_SAR3)

#define IS_SAR_MASK_VALID(sarMask)  (0UL == ((sarMask) & ((uint32_t) ~CY_SAR_MASK)))
#define SCAN_CNT_MIN (1UL)
#define SCAN_CNT_MAX (256UL)
#define IS_SCAN_CNT_VALID(scanCnt) ((SCAN_CNT_MIN <= (scanCnt)) && ((scanCnt) <= SCAN_CNT_MAX))

#define CY_SAR_TR_IN_0          (0UL)
#define CY_SAR_TR_IN_1          (1UL)
#define CY_SAR_TR_IN_2          (2UL)
#define CY_SAR_TR_IN_3          (3UL)

static cy_stc_sar_state_backup_t enabledBeforeSleep[CY_SAR_INSTANCES] =
{
    {0UL,0UL},{0UL,0UL}
};

/* This array is used to calibrate the offset for each channel.
* At initialization, channels that are single-ended, signed, and with Vneg = Vref
* have an offset of -(2^12)/2 = -2048. All other channels have an offset of 0.
* The offset can be overridden using Cy_SAR_SetChannelOffset.
* The channel offsets are used by the Cy_SAR_CountsTo_Volts, Cy_SAR_CountsTo_mVolts, and
* Cy_SAR_CountsTo_uVolts functions to convert counts to voltage.
*/
volatile int16_t Cy_SAR_offset[CY_SAR_NUM_CHANNELS][CY_SAR_INSTANCES];

/* This array is used to calibrate the gain for each channel.
* It is set at initialization and the value depends on the SARADC resolution
* and voltage reference, 10*(2^12)/(2*Vref).
* The gain can be overridden using Cy_SAR_SetChannelGain.
* The channel gains are used by the Cy_SAR_CountsTo_Volts, Cy_SAR_CountsTo_mVolts and
* Cy_SAR_CountsTo_uVolts functions to convert counts to voltage.
*/
volatile int32_t Cy_SAR_countsPer10Volt[CY_SAR_NUM_CHANNELS][CY_SAR_INSTANCES];

/* Global variable to save internal states
 * bit 0 - fifo enable for SAR0 instance
 * bit 1 - fifo enable for SAR1 instance
 * */
static uint32_t Cy_SAR_flags = 0UL;


/*******************************************************************************
* Function Name: Cy_SAR_CommonInit
****************************************************************************//**
*
* Initialize common SAR configuration registers.
*
* \param base
* Pointer to structure describing PASS registers.
*
* \param trigConfig
* Pointer to structure containing configuration data.
* See \ref cy_stc_sar_common_config_t.
*
* \return
* - \ref CY_SAR_SUCCESS : initialization complete
* - \ref CY_SAR_BAD_PARAM : input pointers are null, initialization incomplete
*
* \funcusage
*
* \snippet sar/snippet/main.c SNIPPET_SAR_COMMON_INIT
*
*******************************************************************************/
cy_en_sar_status_t Cy_SAR_CommonInit(PASS_Type * base, const cy_stc_sar_common_config_t  * trigConfig)
{
    cy_en_sar_status_t result = CY_SAR_SUCCESS;

    if((!CY_PASS_V1) && (NULL != base) && (NULL != trigConfig))
    {
        uint32_t simultTrigSourceVal = CY_SAR_TR_IN_0;
        bool simultTrigTimer = false;
        uint32_t interruptState;

        CY_ASSERT_L3(IS_SAR_MASK_VALID(trigConfig->simultControl));
        CY_ASSERT_L3(IS_SCAN_CNT_VALID(trigConfig->scanCount));

        /* Convert and check simultTrigSource value */
        switch(trigConfig->simultTrigSource)
        {
        case CY_SAR_SAR0:
            simultTrigSourceVal = CY_SAR_TR_IN_0;
            break;

        case CY_SAR_SAR1:
            simultTrigSourceVal = CY_SAR_TR_IN_1;
            break;

        case CY_SAR_SAR2:
            simultTrigSourceVal = CY_SAR_TR_IN_2;
            break;

        case CY_SAR_SAR3:
            simultTrigSourceVal = CY_SAR_TR_IN_3;
            break;

        case CY_SAR_TIMER:
            simultTrigTimer = true;
            break;

        default:
            /* Incorrect trigger source */
            result = CY_SAR_BAD_PARAM;
            break;
        }

        if(CY_SAR_SUCCESS == result)
        {
            PASS_SAR_SIMULT_CTRL(base) = _VAL2FLD(PASS_V2_SAR_SIMULT_CTRL_SIMULT_HW_TR_EN, trigConfig->simultControl)                              |
                                         _VAL2FLD(PASS_V2_SAR_SIMULT_CTRL_SIMULT_HW_TR_SRC, simultTrigSourceVal)                                   |
                                        _BOOL2FLD(PASS_V2_SAR_SIMULT_CTRL_SIMULT_HW_TR_TIMER_SEL, simultTrigTimer)                                 |
                                         _VAL2FLD(PASS_V2_SAR_SIMULT_CTRL_SIMULT_HW_TR_LEVEL, (uint32_t)(trigConfig->simultTrigEvent))             |
                                         _VAL2FLD(PASS_V2_SAR_SIMULT_CTRL_SIMULT_HW_SYNC_TR, (uint32_t)(trigConfig->simultTrigSync))               |
                                         _VAL2FLD(PASS_V2_SAR_SIMULT_CTRL_SIMULT_TR_SCAN_CNT_SEL, (uint32_t)(trigConfig->simultSamplesPerTrigger)) |
                                         _VAL2FLD(PASS_V2_SAR_SIMULT_CTRL_SIMULT_EOS_INTR_SCAN_CNT_SEL, (uint32_t)(trigConfig->simultEOSIntrSelect));
            PASS_SAR_TR_SCAN_CNT(base) = _VAL2FLD(PASS_V2_SAR_TR_SCAN_CNT_SCAN_CNT, trigConfig->scanCount - 1UL);

            interruptState = Cy_SysLib_EnterCriticalSection();
            CY_REG32_CLR_SET(PASS_ANA_PWR_CFG(base), PASS_V2_ANA_PWR_CFG_PWR_UP_DELAY, trigConfig->pwrUpDelay);
            Cy_SysLib_ExitCriticalSection(interruptState);
        }
    }
    else
    {
        result = CY_SAR_BAD_PARAM;
    }

    return result;
}

/*******************************************************************************
* Function Name: Cy_SAR_Init
****************************************************************************//**
*
* Initialize all SAR configuration registers.
* If routing is to be configured, all switches will be cleared before
* being initialized.
*
* \note If interleaved averaging mode is used, the Differential Result Format
*       should be the same as the Single-Ended Result Format. Otherwise, this
*       function will return CY_SAR_BAD_PARAM.
*
* \param base
* Pointer to structure describing SAR instance registers
*
* \param config
* Pointer to structure containing configuration data. See \ref cy_stc_sar_config_t
* and guidance in the \ref group_sar_initialization section.
*
* \return
* - \ref CY_SAR_SUCCESS : initialization complete successfylly
* - \ref CY_SAR_BAD_PARAM : input pointers are null or some configuration
                            setting is invalid, initialization incomplete.
*
* \funcusage \snippet sar/snippet/main.c SNIPPET_SAR_INIT_CUSTOM
*
*******************************************************************************/
cy_en_sar_status_t Cy_SAR_Init(SAR_Type * base, const cy_stc_sar_config_t * config)
{
    cy_en_sar_status_t result = CY_SAR_BAD_PARAM;

    CY_ASSERT_L1(NULL != base);
    CY_ASSERT_L1(NULL != config);

    if ((NULL != base) && (NULL != config))
    {
        /* If interleaved averaging mode is used, the Differential Result Format should be the same as the Single-Ended Result Format. */
        if (((0UL != (config->sampleCtrl & SAR_V2_SAMPLE_CTRL_AVG_MODE_Msk)) ?
           !((0UL != (config->sampleCtrl & SAR_V2_SAMPLE_CTRL_SINGLE_ENDED_SIGNED_Msk)) !=
             (0UL != (config->sampleCtrl & SAR_V2_SAMPLE_CTRL_DIFFERENTIAL_SIGNED_Msk))) : true) &&
        /* The FIFO is supported by PASS_ver2 only */
            ((NULL != config->fifoCfgPtr) ? !CY_PASS_V1 : true) &&
        /* The Clock selection CY_SAR_CLK_DEEPSLEEP is allowed for PASS_V2 only */
            ((CY_SAR_CLK_DEEPSLEEP == config->clock) ? !CY_PASS_V1 : true))
        {
            uint32_t interruptState;
            uint8_t chan;
            bool vrefNegSelect;
            bool singleEndedSigned;
            bool chanSingleEnded;
            int32_t defaultGain;

            CY_ASSERT_L2(CY_SAR_CTRL(config->ctrl));
            CY_ASSERT_L2(CY_SAR_SAMPLE_CTRL(config->sampleCtrl));
            CY_ASSERT_L2(CY_SAR_SAMPLE_TIME(config->sampleTime01));
            CY_ASSERT_L2(CY_SAR_SAMPLE_TIME(config->sampleTime23));
            CY_ASSERT_L3(CY_SAR_RANGECOND(config->rangeCond));
            CY_ASSERT_L2(CY_SAR_INJMASK(config->chanEn));
            CY_ASSERT_L2(CY_SAR_INTRMASK(config->intrMask));
            CY_ASSERT_L2(CY_SAR_CHANMASK(config->satIntrMask));
            CY_ASSERT_L2(CY_SAR_CHANMASK(config->rangeIntrMask));

            /* Set the REFBUF_EN bit as this is required for proper operation. */
            SAR_CTRL(base) = (config->ctrl | SAR_CTRL_REFBUF_EN_Msk) & ~SAR_CTRL_ENABLED_Msk;
            SAR_SAMPLE_CTRL(base) = config->sampleCtrl | SAR_SAMPLE_CTRL_EOS_DSI_OUT_EN_Msk; /* Set the EOS_DSI_OUT_EN bit so the EOS signal can be routed */
            SAR_SAMPLE_TIME01(base) = config->sampleTime01;
            SAR_SAMPLE_TIME23(base) = config->sampleTime23;
            SAR_RANGE_THRES(base) = config->rangeThres;
            SAR_RANGE_COND(base) = (uint32_t)config->rangeCond << SAR_RANGE_COND_RANGE_COND_Pos;
            SAR_CHAN_EN(base) = _VAL2FLD(SAR_CHAN_EN_CHAN_EN, config->chanEn);

            /* Check whether NEG_SEL is set for VREF */
            vrefNegSelect = ((uint32_t)CY_SAR_NEG_SEL_VREF == (config->ctrl & SAR_CTRL_NEG_SEL_Msk))? true : false;
            /* Check whether single ended channels are set to signed */
            singleEndedSigned = (SAR_SAMPLE_CTRL_SINGLE_ENDED_SIGNED_Msk == (config->sampleCtrl & SAR_SAMPLE_CTRL_SINGLE_ENDED_SIGNED_Msk)) ? true : false;
            /* Calculate the default gain for all the channels in counts per 10 volts with rounding */
            defaultGain = (int32_t)(uint16_t)CY_SYSLIB_DIV_ROUND((uint32_t)CY_SAR_WRK_MAX_12BIT * (uint32_t)CY_SAR_10MV_COUNTS, config->vrefMvValue * 2UL);

            for (chan = 0u; chan < CY_SAR_SEQ_NUM_CHANNELS; chan++)
            {
                CY_ASSERT_L2(CY_SAR_CHAN_CONFIG(config->chanConfig[chan]));

                SAR_CHAN_CONFIG(base, chan) = config->chanConfig[chan];

                /* For signed single ended channels with NEG_SEL set to VREF,
                 * set the offset to minus half scale to convert results to unsigned format */
                chanSingleEnded = (0UL == (config->chanConfig[chan] & (SAR_CHAN_CONFIG_DIFFERENTIAL_EN_Msk | SAR_CHAN_CONFIG_NEG_ADDR_EN_Msk))) ? true : false;
                if (chanSingleEnded && vrefNegSelect && singleEndedSigned)
                {
                    Cy_SAR_offset[chan][CY_SAR_INSTANCE(base)] = (int16_t) (CY_SAR_WRK_MAX_12BIT / -2);
                }
                else
                {
                    Cy_SAR_offset[chan][CY_SAR_INSTANCE(base)] = 0;
                }

                Cy_SAR_countsPer10Volt[chan][CY_SAR_INSTANCE(base)] = defaultGain;
            }

            SAR_INTR_MASK(base) = config->intrMask;
            SAR_INTR(base) = config->intrMask;
            SAR_SATURATE_INTR_MASK(base) = config->satIntrMask;
            SAR_SATURATE_INTR(base) = config->satIntrMask;
            SAR_RANGE_INTR_MASK(base) = config->rangeIntrMask;
            SAR_RANGE_INTR(base) = config->rangeIntrMask;

            /* Set routing related registers if enabled */
            if (true == config->configRouting)
            {
                CY_ASSERT_L2(CY_SAR_SWITCHMASK(config->muxSwitch));
                CY_ASSERT_L2(CY_SAR_SQMASK(config->muxSwitchSqCtrl));

                /* Clear out all the switches so that only the desired switches in the config structure are set. */
                SAR_MUX_SWITCH_CLEAR0(base) = CY_SAR_CLEAR_ALL_SWITCHES;

                SAR_MUX_SWITCH0(base) = config->muxSwitch;
                SAR_MUX_SWITCH_SQ_CTRL(base) = config->muxSwitchSqCtrl;
            }

            /* Set the Cap trim if it was trimmed out of range from sflash */
            if ((CY_SAR_CAP_TRIM_MAX == SAR_ANA_TRIM0(base)) || (CY_SAR_CAP_TRIM_MIN == SAR_ANA_TRIM0(base)))
            {
                SAR_ANA_TRIM0(base) = CY_SAR_CAP_TRIM;
            }

            if (0UL != (CY_SAR_INJ_CHAN_MASK & config->chanEn))
            {
                SAR_INJ_CHAN_CONFIG(base) = config->chanConfig[CY_SAR_INJ_CHANNEL];
                Cy_SAR_countsPer10Volt[CY_SAR_INJ_CHANNEL][CY_SAR_INSTANCE(base)] = defaultGain;
            }

            if (NULL != config->fifoCfgPtr)
            {
                uint32_t locLevel = config->fifoCfgPtr->level - 1UL; /* Convert the user value into the machine value */

                Cy_SAR_flags |= CY_SAR_INSTANCE_MASK(base);

                PASS_FIFO_CONFIG(base) = _BOOL2FLD(PASS_FIFO_V2_CONFIG_CHAN_ID_EN,        config->fifoCfgPtr->chanId) |
                                         _BOOL2FLD(PASS_FIFO_V2_CONFIG_CHAIN_TO_NXT,      config->fifoCfgPtr->chainToNext) |
                                         _BOOL2FLD(PASS_FIFO_V2_CONFIG_TR_INTR_CLR_RD_EN, config->fifoCfgPtr->clrTrIntrOnRead);

                CY_ASSERT_L2(CY_SAR_IS_FIFO_LEVEL_VALID(locLevel));
                PASS_FIFO_LEVEL(base) = _VAL2FLD(PASS_FIFO_V2_LEVEL_LEVEL, locLevel);

                interruptState = Cy_SysLib_EnterCriticalSection();

                if (config->fifoCfgPtr->trOut)
                {
                    PASS_SAR_TR_OUT_CTRL(CY_PASS_V2_ADDR) |= CY_SAR_INSTANCE_MASK(base);
                }
                else
                {
                    PASS_SAR_TR_OUT_CTRL(CY_PASS_V2_ADDR) &= ~CY_SAR_INSTANCE_MASK(base);
                }

                Cy_SysLib_ExitCriticalSection(interruptState);
            }
            else
            {
                Cy_SAR_flags &= ~CY_SAR_INSTANCE_MASK(base);
            }

            if (!CY_PASS_V1)
            {
                uint32_t locReg;
                uint32_t locAndMask = ~(CY_SAR_INSTANCE_MASK(base) |
                                       (CY_SAR_INSTANCE_MASK(base) << PASS_V2_SAR_OVR_CTRL_TR_SCAN_CNT_SEL_Pos) |
                                       (CY_SAR_INSTANCE_MASK(base) << PASS_V2_SAR_OVR_CTRL_EOS_INTR_SCAN_CNT_SEL_Pos));
                uint32_t locOrMask = (config->trTimer ? CY_SAR_INSTANCE_MASK(base) : 0UL) |
                                     (config->scanCnt ? (CY_SAR_INSTANCE_MASK(base) << PASS_V2_SAR_OVR_CTRL_TR_SCAN_CNT_SEL_Pos) : 0UL) |
                                     (config->scanCntIntr ? (CY_SAR_INSTANCE_MASK(base) << PASS_V2_SAR_OVR_CTRL_EOS_INTR_SCAN_CNT_SEL_Pos) : 0UL);

                interruptState = Cy_SysLib_EnterCriticalSection();

                locReg = PASS_SAR_OVR_CTRL(CY_PASS_V2_ADDR);
                locReg &= locAndMask;
                locReg |= locOrMask;
                PASS_SAR_OVR_CTRL(CY_PASS_V2_ADDR) = locReg;

                Cy_SysLib_ExitCriticalSection(interruptState);

                CY_ASSERT_L3(CY_SAR_IS_CLK_VALID(config->clock));
                PASS_SAR_CLOCK_SEL(base) = _VAL2FLD(PASS_V2_SAR_CLOCK_SEL_CLOCK_SEL, config->clock);
                PASS_SAR_DPSLP_CTRL(base) = _BOOL2FLD(PASS_V2_SAR_DPSLP_CTRL_ENABLED, (CY_SAR_CLK_DEEPSLEEP == config->clock));
            }

            result = CY_SAR_SUCCESS;
        }
    }

    return result;
}


/*******************************************************************************
* Function Name: Cy_SAR_DeInit
****************************************************************************//**
*
* Reset SAR registers back to power on reset defaults.
*
* \if Cy_SAR_offset and Cy_SAR_countsPer10Volt arrays are NOT reset. \endif
*
* \param base
* Pointer to structure describing registers
*
* \param deInitRouting
* If true, all SARMUX switches are opened and switch control registers are reset
* to zero. If false, switch registers are untouched.
*
* \return
* - \ref CY_SAR_SUCCESS : de-initialization complete
* - \ref CY_SAR_BAD_PARAM : input pointers are null, de-initialization incomplete
*
* \funcusage
*
* \snippet sar/snippet/main.c SNIPPET_SAR_DEINIT
*
*******************************************************************************/
cy_en_sar_status_t Cy_SAR_DeInit(SAR_Type * base, bool deInitRouting)
{
    cy_en_sar_status_t result = CY_SAR_BAD_PARAM;

    CY_ASSERT_L1(NULL != base);

    if (NULL != base)
    {
        uint8_t chan;

        SAR_CTRL(base) = CY_SAR_DEINIT;
        SAR_SAMPLE_CTRL(base) = CY_SAR_DEINIT;
        SAR_SAMPLE_TIME01(base) = CY_SAR_SAMPLE_TIME_DEINIT;
        SAR_SAMPLE_TIME23(base) = CY_SAR_SAMPLE_TIME_DEINIT;
        SAR_RANGE_THRES(base) = CY_SAR_DEINIT;
        SAR_RANGE_COND(base) = CY_SAR_DEINIT;
        SAR_CHAN_EN(base) = CY_SAR_DEINIT;
        for (chan = 0u; chan < CY_SAR_SEQ_NUM_CHANNELS; chan++)
        {
            SAR_CHAN_CONFIG(base, chan) = CY_SAR_DEINIT;
        }
        SAR_INJ_CHAN_CONFIG(base) = CY_SAR_DEINIT;
        SAR_INTR_MASK(base) = CY_SAR_DEINIT;
        SAR_SATURATE_INTR_MASK(base) = CY_SAR_DEINIT;
        SAR_RANGE_INTR_MASK(base) = CY_SAR_DEINIT;
        if (true == deInitRouting)
        {
            SAR_MUX_SWITCH_CLEAR0(base) = CY_SAR_CLEAR_ALL_SWITCHES;
            SAR_MUX_SWITCH_DS_CTRL(base) = CY_SAR_DEINIT;
            SAR_MUX_SWITCH_SQ_CTRL(base) = CY_SAR_DEINIT;
        }

        if (!CY_PASS_V1)
        {
            uint32_t locAndMask = ~(CY_SAR_INSTANCE_MASK(base) |
                                    (CY_SAR_INSTANCE_MASK(base) << PASS_V2_SAR_OVR_CTRL_TR_SCAN_CNT_SEL_Pos) |
                                    (CY_SAR_INSTANCE_MASK(base) << PASS_V2_SAR_OVR_CTRL_EOS_INTR_SCAN_CNT_SEL_Pos));

            uint32_t interruptState = Cy_SysLib_EnterCriticalSection();

            PASS_SAR_OVR_CTRL(CY_PASS_V2_ADDR) &= locAndMask;
            PASS_SAR_TR_OUT_CTRL(CY_PASS_V2_ADDR) &= ~CY_SAR_INSTANCE_MASK(base);

            Cy_SysLib_ExitCriticalSection(interruptState);

            if (0UL != (Cy_SAR_flags & CY_SAR_INSTANCE_MASK(base)))
            {
                PASS_FIFO_CTRL(base) = CY_SAR_DEINIT; /* Disable first */
                PASS_FIFO_CONFIG(base) = CY_SAR_DEINIT;
                PASS_FIFO_LEVEL(base) = CY_SAR_DEINIT;
                Cy_SAR_flags &= ~CY_SAR_INSTANCE_MASK(base);
            }

            PASS_SAR_DPSLP_CTRL(base) = CY_SAR_DEINIT;
            PASS_SAR_CLOCK_SEL(base) = CY_SAR_DEINIT;
        }

        result = CY_SAR_SUCCESS;
    }

    return result;
}


/*******************************************************************************
* Function Name: Cy_SAR_Enable
****************************************************************************//**
*
* Power up the SAR ADC subsystem block. The hardware is ready to use
* after 2 us, which is included in this function.
*
* \param base
* Pointer to structure describing registers
*
* \return None
*
*******************************************************************************/
void Cy_SAR_Enable(SAR_Type *base)
{
    if (!_FLD2BOOL(SAR_CTRL_ENABLED, SAR_CTRL(base)))
    {
        SAR_CTRL(base) |= SAR_CTRL_ENABLED_Msk;

        /* The block is ready to use 2 us after the enable signal is set high. */
        Cy_SysLib_DelayUs(CY_SAR_2US_DELAY);

        if ((!CY_PASS_V1) && (0UL != (Cy_SAR_flags & CY_SAR_INSTANCE_MASK(base))))
        {
            PASS_FIFO_CTRL(base) = PASS_FIFO_V2_CTRL_ENABLED_Msk;
        }
    }
}


/*******************************************************************************
* Function Name: Cy_SAR_Disable
****************************************************************************//**
*
* Turn off the hardware block.
*
* \param base
* Pointer to structure describing registers
*
* \return None
*
*******************************************************************************/
void Cy_SAR_Disable(SAR_Type *base)
{
    if (_FLD2BOOL(SAR_CTRL_ENABLED, SAR_CTRL(base)))
    {
        while (_FLD2BOOL(SAR_STATUS_BUSY, SAR_STATUS(base)))
        {
            /* Wait for SAR to go idle */
        }

        SAR_CTRL(base) &= ~SAR_CTRL_ENABLED_Msk;

        if ((!CY_PASS_V1) && (0UL != (Cy_SAR_flags & CY_SAR_INSTANCE_MASK(base))))
        {
            PASS_FIFO_CTRL(base) = 0UL;
        }
    }
}


/*******************************************************************************
* Function Name: Cy_SAR_DeepSleep
****************************************************************************//**
*
* This is the preferred routine to prepare the hardware for Deep Sleep.
*
* It will call \ref Cy_SAR_StopConvert to disable continuous conversions
* and wait for SAR conversions to stop before entering Deep Sleep.
* If the SARMUX is not configured for Deep Sleep operation, the entire SAR hardware
* block will be turned off.
*
* \param base
* Pointer to structure describing registers
*
* \return None
*
* \funcusage
*
* This function is used in the \ref Cy_SAR_DeepSleepCallback. There is no
* need to call this function directly.
*
*******************************************************************************/
void Cy_SAR_DeepSleep(SAR_Type *base)
{
    uint32_t ctrlReg = SAR_CTRL(base);

    enabledBeforeSleep[CY_SAR_INSTANCE(base)].hwEnabled = ctrlReg & SAR_CTRL_ENABLED_Msk;

    /* Turn off the reference buffer */
    ctrlReg &= ~SAR_CTRL_REFBUF_EN_Msk;

    if (SAR_CTRL_ENABLED_Msk == enabledBeforeSleep[CY_SAR_INSTANCE(base)].hwEnabled)
    {

        /* Save state of CONTINUOUS bit so that conversions can be re-started upon wake-up */
        enabledBeforeSleep[CY_SAR_INSTANCE(base)].continuous = SAR_SAMPLE_CTRL(base) & SAR_SAMPLE_CTRL_CONTINUOUS_Msk;

        Cy_SAR_StopConvert(base);

        while (_FLD2BOOL(SAR_STATUS_BUSY, SAR_STATUS(base)))
        {
            /* Wait for SAR to stop conversions before entering low power */
        }

        /* Turn off the entire hardware block only if the SARMUX is not
         * enabled for Deep Sleep operation. */
        if (SAR_CTRL_DEEPSLEEP_ON_Msk != (ctrlReg & SAR_CTRL_DEEPSLEEP_ON_Msk))
        {
            SAR_CTRL(base) &= ~SAR_CTRL_ENABLED_Msk;
        }
    }

    SAR_CTRL(base) = ctrlReg;
}


/*******************************************************************************
* Function Name: Cy_SAR_Wakeup
****************************************************************************//**
*
* This is the preferred routine to restore the hardware to the state after calling
* \ref Cy_SAR_DeepSleep. Restoring the hardware involves re-enabling the hardware,
* the reference buffer, and continuous scanning if it was previously
* enabled before entering sleep.
*
* \param base
* Pointer to structure describing registers
*
* \sideeffect
* Calling this function without previously calling \ref Cy_SAR_DeepSleep can lead to
* unpredictable results.
*
* \return None
*
* \funcusage
*
* This function is used in the \ref Cy_SAR_DeepSleepCallback. There is no
* need to call this function directly.
*
*******************************************************************************/
void Cy_SAR_Wakeup(SAR_Type *base)
{
    /* Turn on the reference buffer */
    SAR_CTRL(base) |= SAR_CTRL_REFBUF_EN_Msk;

    if (SAR_CTRL_ENABLED_Msk == enabledBeforeSleep[CY_SAR_INSTANCE(base)].hwEnabled)
    {
        Cy_SAR_Enable(base);

        if (SAR_SAMPLE_CTRL_CONTINUOUS_Msk == enabledBeforeSleep[CY_SAR_INSTANCE(base)].continuous)
        {
            Cy_SAR_StartConvert(base, CY_SAR_START_CONVERT_CONTINUOUS);
        }
    }
}


/*******************************************************************************
* Function Name: Cy_SAR_StartConvert
****************************************************************************//**
*
* Start a single scan (one shot) of all enabled channels or start scanning
* continuously. When in continuous mode, all firmware and hardware triggers
* are ignored. To stop continuous scanning, call \ref Cy_SAR_StopConvert.
*
* \param base
* Pointer to structure describing registers
*
* \param startSelect
* A value of the enum \ref cy_en_sar_start_convert_sel_t
*
* \return None
*
* \funcusage
*
* \snippet sar/snippet/main.c SNIPPET_SAR_START_CONVERT
*
*******************************************************************************/
void Cy_SAR_StartConvert(SAR_Type *base, cy_en_sar_start_convert_sel_t startSelect)
{
    CY_ASSERT_L3(CY_SAR_STARTCONVERT(startSelect));

    switch(startSelect)
    {
    case CY_SAR_START_CONVERT_CONTINUOUS:
        SAR_SAMPLE_CTRL(base) |= SAR_SAMPLE_CTRL_CONTINUOUS_Msk;
        break;
    case CY_SAR_START_CONVERT_SINGLE_SHOT:
    default:
        SAR_START_CTRL(base) = SAR_START_CTRL_FW_TRIGGER_Msk;
        break;
    }
}


/*******************************************************************************
* Function Name: Cy_SAR_StopConvert
****************************************************************************//**
*
* Stop continuous scanning of enabled channels.
* If a conversion is currently executing, that conversion will complete,
* but no further conversions will occur until the next call to
* \ref Cy_SAR_StartConvert or the next hardware trigger, if enabled.
*
* \param base
* Pointer to structure describing registers
*
* \return None
*
* \funcusage
*
* \snippet sar/snippet/main.c SNIPPET_SAR_STOP_CONVERT
*
*******************************************************************************/
void Cy_SAR_StopConvert(SAR_Type *base)
{
    if (SAR_SAMPLE_CTRL_CONTINUOUS_Msk == (SAR_SAMPLE_CTRL(base) & SAR_SAMPLE_CTRL_CONTINUOUS_Msk))
    {
        SAR_SAMPLE_CTRL(base) &= ~SAR_SAMPLE_CTRL_CONTINUOUS_Msk;
    }
}


/*******************************************************************************
* Function Name: Cy_SAR_SetConvertMode
****************************************************************************//**
*
* Set the mode in which conversions are triggered. This function does
* not start any conversions; it only configures the mode for subsequent conversions.
*
* There are three modes:
*   - firmware only; hardware triggering is disabled
*   - firmware and edge sensitive hardware triggering
*   - firmware and level sensitive hardware triggering
*
* Note that firmware triggering is always enabled.
*
* \param base
* Pointer to structure describing registers
*
* \param mode
* A value of the enum \ref cy_en_sar_sample_ctrl_trigger_mode_t
*
* \return None
*
* \funcusage
*
* \snippet sar/snippet/main.c SAR_SNIPPET_SET_CONVERT_MODE
*
*******************************************************************************/
void Cy_SAR_SetConvertMode(SAR_Type *base, cy_en_sar_sample_ctrl_trigger_mode_t mode)
{
    CY_ASSERT_L3(CY_SAR_TRIGGER(mode));

    /* Clear the TRIGGER_EN and TRIGGER_LEVEL bits */
    uint32_t sampleCtrlReg = SAR_SAMPLE_CTRL(base) & ~(SAR_SAMPLE_CTRL_DSI_TRIGGER_EN_Msk | SAR_SAMPLE_CTRL_DSI_TRIGGER_LEVEL_Msk);

    SAR_SAMPLE_CTRL(base) = sampleCtrlReg | (uint32_t)mode;
}


/*******************************************************************************
* Function Name: Cy_SAR_IsEndConversion
****************************************************************************//**
*
* Immediately return the status of the conversion or does not return (blocking)
* until the conversion completes, depending on the retMode parameter.
* In blocking mode, there is a time out of about 10 seconds for a CPU speed of
* 100 MHz.
*
* \param base
* Pointer to structure describing registers
*
* \param retMode
* A value of the enum \ref cy_en_sar_return_mode_t
*
* \return
* - \ref CY_SAR_SUCCESS : the last conversion is complete
* - \ref CY_SAR_CONVERSION_NOT_COMPLETE : the conversion has not completed
* - \ref CY_SAR_TIMEOUT : the watchdog timer has expired in blocking mode
*
* \sideeffect
* This function reads the end of conversion status and clears it after.
*
* \note
* \ref CY_SAR_WAIT_FOR_RESULT and \ref CY_SAR_WAIT_FOR_RESULT_INJ return modes are not recommended 
* for use in RTOS environment.
*
* \funcusage
*
* \snippet sar/snippet/main.c SNIPPET_SAR_IS_END_CONVERSION
*
*******************************************************************************/
cy_en_sar_status_t Cy_SAR_IsEndConversion(SAR_Type *base, cy_en_sar_return_mode_t retMode)
{
    CY_ASSERT_L3(CY_SAR_RETURN(retMode));

    cy_en_sar_status_t result;

    uint32_t wdt = 0x1555555UL; /* Watchdog timer for blocking while loop */
    uint32_t mask = ((CY_SAR_RETURN_STATUS_INJ == retMode) || (CY_SAR_WAIT_FOR_RESULT_INJ == retMode)) ? CY_SAR_INTR_INJ_EOC : CY_SAR_INTR_EOS;
    uint32_t intr = mask & Cy_SAR_GetInterruptStatus(base);

    if ((CY_SAR_WAIT_FOR_RESULT == retMode) || (CY_SAR_WAIT_FOR_RESULT_INJ == retMode))
    {
        while ((0UL == intr) && (0UL != wdt))
        {
            intr = mask & Cy_SAR_GetInterruptStatus(base);
            wdt--;
        }
    }

    /* Clear the EOS bit */
    if (mask == intr)
    {
        result = CY_SAR_SUCCESS;
        Cy_SAR_ClearInterrupt(base, mask);
    }
    else if (0UL == wdt)
    {
        result = CY_SAR_TIMEOUT;
    }
    else
    {
        result = CY_SAR_CONVERSION_NOT_COMPLETE;
    }

    return result;
}


/*******************************************************************************
* Function Name: Cy_SAR_IsChannelSigned
****************************************************************************//**
*
* Return true if channel result is configured for signed format, else false.
* The formats for single-ended and differential channels are independent.
* This function will first check whether the channel is single-ended or differential.
*
* \param base
* Pointer to structure describing registers
*
* \param chan
* The channel to check, between 0 and \ref CY_SAR_INJ_CHANNEL
*
* \return
* If channel number is invalid, false is returned
*
* \funcusage
*
* \snippet sar/snippet/main.c SNIPPET_SAR_IS_CHANNEL_SIGNED
*
*******************************************************************************/
bool Cy_SAR_IsChannelSigned(const SAR_Type *base, uint32_t chan)
{
    CY_ASSERT_L2(CHAN_NUM(chan));

    bool isSigned = false;

    if (chan < CY_SAR_NUM_CHANNELS)
    {
        /* Sign bits are stored separately for differential and single ended channels. */
        if (true == Cy_SAR_IsChannelDifferential(base, chan))
        { /* Differential channel */
            if (SAR_SAMPLE_CTRL_DIFFERENTIAL_SIGNED_Msk == (SAR_SAMPLE_CTRL(base) & SAR_SAMPLE_CTRL_DIFFERENTIAL_SIGNED_Msk))
            {
                isSigned = true;
            }
        }
        else
        { /* Single ended channel */
            if (SAR_SAMPLE_CTRL_SINGLE_ENDED_SIGNED_Msk == (SAR_SAMPLE_CTRL(base) & SAR_SAMPLE_CTRL_SINGLE_ENDED_SIGNED_Msk))
            {
                isSigned = true;
            }
        }
    }

    return isSigned;
}


/*******************************************************************************
* Function Name: Cy_SAR_IsChannelSingleEnded
****************************************************************************//**
*
* Return true if channel is single ended, else false
*
* \param base
* Pointer to structure describing registers
*
* \param chan
* The channel to check, between 0 and \ref CY_SAR_INJ_CHANNEL
*
* \return
* If channel number is invalid, false is returned
*
* \funcusage
*
* \snippet sar/snippet/main.c SNIPPET_SAR_IS_CHANNEL_SE
*
*******************************************************************************/
bool Cy_SAR_IsChannelSingleEnded(const SAR_Type *base, uint32_t chan)
{
    CY_ASSERT_L2(CHAN_NUM(chan));

    bool isSingleEnded = false;

    if (chan < CY_SAR_SEQ_NUM_CHANNELS)
    {
        if (0UL == (SAR_CHAN_CONFIG(base, chan) & (SAR_CHAN_CONFIG_DIFFERENTIAL_EN_Msk | SAR_CHAN_CONFIG_NEG_ADDR_EN_Msk)))
        {
            isSingleEnded = true;
        }
    }
    else if (CY_SAR_INJ_CHANNEL == chan)
    {
        isSingleEnded = !_FLD2BOOL(SAR_INJ_CHAN_CONFIG_INJ_DIFFERENTIAL_EN, SAR_INJ_CHAN_CONFIG(base));
    }
    else
    {
        /* Return false */
    }

    return isSingleEnded;
}


/*******************************************************************************
* Function Name: Cy_SAR_GetResult16
****************************************************************************//**
*
* Return the data available in the channel result data register as a signed
* 16-bit integer.
*
* \param base
* Pointer to structure describing registers
*
* \param chan
* The channel to read the result from, between 0 and \ref CY_SAR_INJ_CHANNEL
*
* \return
* Data is returned as a signed 16-bit integer.
* If channel number is invalid, 0 is returned.
*
* \funcusage
*
* \snippet sar/snippet/main.c SNIPPET_SAR_GET_RESULT16
*
*******************************************************************************/
int16_t Cy_SAR_GetResult16(const SAR_Type *base, uint32_t chan)
{
    CY_ASSERT_L2(CHAN_NUM(chan));

    uint32_t adcResult = 0UL;

    if (chan < CY_SAR_SEQ_NUM_CHANNELS)
    {
        adcResult = _FLD2VAL(SAR_CHAN_RESULT_RESULT, SAR_CHAN_RESULT(base, chan));
    }
    else if (CY_SAR_INJ_CHANNEL == chan)
    {
        adcResult = _FLD2VAL(SAR_INJ_RESULT_INJ_RESULT, SAR_INJ_RESULT(base));
    }
    else
    {
        /* Return zero */
    }

    return (int16_t) adcResult;
}


/*******************************************************************************
* Function Name: Cy_SAR_GetResult32
****************************************************************************//**
*
* Return the data available in the channel result data register as a signed
* 32-bit integer.
*
* \param base
* Pointer to structure describing registers
*
* \param chan
* The channel to read the result from, between 0 and \ref CY_SAR_INJ_CHANNEL
*
* \return
* Data is returned as a signed 32-bit integer.
* If channel number is invalid, 0 is returned.
*
* \funcusage
*
* \snippet sar/snippet/main.c SNIPPET_SAR_GET_RESULT32
*
*******************************************************************************/
int32_t Cy_SAR_GetResult32(const SAR_Type *base, uint32_t chan)
{
    return ((int32_t)Cy_SAR_GetResult16(base, chan));
}


/*******************************************************************************
* Function Name: Cy_SAR_SetLowLimit
****************************************************************************//**
*
* Set the low threshold for range detection. The values are interpreted
* as signed or unsigned according to the channel configuration. Range
* detection is done on the value stored in the result register. That is, after
* averaging, shifting sign extension, and left/right alignment.
*
* \param base
* Pointer to structure describing registers
*
* \param lowLimit
* The low threshold for range detection
*
* \return None
*
* \funcusage
*
* \snippet sar/snippet/main.c SNIPPET_SAR_SET_LOWHIGH_LIMIT
*
*******************************************************************************/
void Cy_SAR_SetLowLimit(SAR_Type *base, uint32_t lowLimit)
{
    CY_ASSERT_L2(CY_SAR_RANGE_LIMIT(lowLimit));

    CY_REG32_CLR_SET(SAR_RANGE_THRES(base), SAR_RANGE_THRES_RANGE_LOW, lowLimit);
}


/*******************************************************************************
* Function Name: Cy_SAR_SetHighLimit
****************************************************************************//**
*
* Set the high threshold for range detection. The values are interpreted
* as signed or unsigned according to the channel configuration. Range
* detection is done on the value stored in the result register. That is, after
* averaging, shifting sign extension, and left/right alignment.
*
* \param base
* Pointer to structure describing registers
*
* \param highLimit
* The high threshold for range detection
*
* \return None
*
* \funcusage
*
* \snippet sar/snippet/main.c SNIPPET_SAR_SET_LOWHIGH_LIMIT
*
*******************************************************************************/
void Cy_SAR_SetHighLimit(SAR_Type *base, uint32_t highLimit)
{
    CY_ASSERT_L2(CY_SAR_RANGE_LIMIT(highLimit));

    CY_REG32_CLR_SET(SAR_RANGE_THRES(base), SAR_RANGE_THRES_RANGE_HIGH, highLimit);
}


/*******************************************************************************
* Function Name: Cy_SAR_SetChannelOffset
****************************************************************************//**
*
* Store the channel offset for the voltage conversion functions.
*
* Offset is applied to counts before unit scaling and gain.
* See \ref Cy_SAR_CountsTo_Volts for more about this formula.
*
* To change channel 0's offset based on a known V_offset_mV, use:
*
*     Cy_SAR_SetOffset(0UL, -1 * V_offset_mV * (1UL << Resolution) / (2 * V_ref_mV));
*
* \param base
* Pointer to structure describing registers
*
* \param chan
* The channel number, between 0 and \ref CY_SAR_INJ_CHANNEL.
*
* \param offset
* The count value measured when the inputs are shorted or
* connected to the same input voltage.
*
* \return
* - \ref CY_SAR_SUCCESS : offset was set successfully
* - \ref CY_SAR_BAD_PARAM : channel number is equal to or greater than \ref CY_SAR_NUM_CHANNELS
*
*******************************************************************************/
cy_en_sar_status_t Cy_SAR_SetChannelOffset(const SAR_Type *base, uint32_t chan, int16_t offset)
{
    CY_ASSERT_L2(CHAN_NUM(chan));

    cy_en_sar_status_t result = CY_SAR_BAD_PARAM;

    if (chan < CY_SAR_NUM_CHANNELS)
    {
        Cy_SAR_offset[chan][CY_SAR_INSTANCE(base)] = offset;
        result = CY_SAR_SUCCESS;
    }

    return result;
}


/*******************************************************************************
* Function Name: Cy_SAR_SetChannelGain
****************************************************************************//**
*
* Store the gain value for the voltage conversion functions.
* The gain is configured at initialization in \ref Cy_SAR_Init
* based on the SARADC resolution and voltage reference.
*
* Gain is applied after offset and unit scaling.
* See \ref Cy_SAR_CountsTo_Volts for more about this formula.
*
* To change channel 0's gain based on a known V_ref_mV, use:
*
*     Cy_SAR_SetGain(0UL, 10000 * (1UL << Resolution) / (2 * V_ref_mV));
*
* \param base
* Pointer to structure describing registers
*
* \param chan
* The channel number, between 0 and \ref CY_SAR_INJ_CHANNEL.
*
* \param adcGain
* The gain in counts per 10 volt.
*
* \return
* - \ref CY_SAR_SUCCESS : gain was set successfully
* - \ref CY_SAR_BAD_PARAM : channel number is equal to or greater than \ref CY_SAR_NUM_CHANNELS
*
*******************************************************************************/
cy_en_sar_status_t Cy_SAR_SetChannelGain(const SAR_Type *base, uint32_t chan, int32_t adcGain)
{
    CY_ASSERT_L2(CHAN_NUM(chan));

    cy_en_sar_status_t result = CY_SAR_BAD_PARAM;

    if (chan < CY_SAR_NUM_CHANNELS)
    {
        Cy_SAR_countsPer10Volt[chan][CY_SAR_INSTANCE(base)] = adcGain;
        result = CY_SAR_SUCCESS;
    }

    return result;
}


/*******************************************************************************
* Function Name: Cy_SAR_RawCounts2Counts
****************************************************************************//**
*
* Convert the channel result to a consistent result after accounting for
* averaging and subtracting the offset.
* The equation used is:
*
*     Counts = (RawCounts/AvgDivider - Offset)
*
* where,
* - RawCounts: Raw counts from SAR 16-bit CHAN_RESULT register
* - AvgDivider: divider based on averaging mode (\ref cy_en_sar_sample_ctrl_avg_mode_t) and number of samples averaged
*   (\ref cy_en_sar_sample_ctrl_avg_cnt_t)
*   - \ref CY_SAR_AVG_MODE_SEQUENTIAL_ACCUM : AvgDivider is the number of samples averaged or 16, whichever is smaller
*   - \ref CY_SAR_AVG_MODE_SEQUENTIAL_FIXED : AvgDivider is 1
*   - \ref CY_SAR_AVG_MODE_INTERLEAVED : AvgDivider is the number of samples averaged
* - Offset: Value stored by the \ref Cy_SAR_SetChannelOffset function.
*
* \param base
* Pointer to structure describing registers
*
* \param chan
* The channel number, between 0 and \ref CY_SAR_INJ_CHANNEL
*
* \param adcCounts
* Conversion result from \ref Cy_SAR_GetResult16
*
* \return
* adcCounts after averaging and offset adjustments.
* If channel number is invalid, adcCounts is returned unmodified.
*
* \funcusage
*
* This function is used by \ref Cy_SAR_CountsTo_Volts, \ref Cy_SAR_CountsTo_mVolts,
* and \ref Cy_SAR_CountsTo_uVolts. Calling this function directly is usually
* not needed.
*
*******************************************************************************/
int16_t Cy_SAR_RawCounts2Counts(const SAR_Type *base, uint32_t chan, int16_t adcCounts)
{
    int16_t retVal = adcCounts;

    CY_ASSERT_L2(CHAN_NUM(chan));

    if (chan < CY_SAR_NUM_CHANNELS)
    {
        /* Divide the adcCount when accumulate averaging mode selected */
        if (!_FLD2BOOL(SAR_SAMPLE_CTRL_AVG_SHIFT, SAR_SAMPLE_CTRL(base)))
        { /* If Average mode != fixed */
            if (((chan < CY_SAR_SEQ_NUM_CHANNELS) && _FLD2BOOL(SAR_CHAN_CONFIG_AVG_EN,         SAR_CHAN_CONFIG(base, chan))) ||
                ((chan == CY_SAR_INJ_CHANNEL)     && _FLD2BOOL(SAR_INJ_CHAN_CONFIG_INJ_AVG_EN, SAR_INJ_CHAN_CONFIG(base))))
            { /* If channel uses averaging */
                uint32_t averageAdcSamplesDiv;

                /* Divide by 2^(AVG_CNT + 1) */
                averageAdcSamplesDiv = (SAR_SAMPLE_CTRL(base) & SAR_SAMPLE_CTRL_AVG_CNT_Msk) >> SAR_SAMPLE_CTRL_AVG_CNT_Pos;
                averageAdcSamplesDiv = (1UL << (averageAdcSamplesDiv + 1UL));

                /* If averaging mode is ACCUNDUMP (channel will be sampled back to back and averaged)
                * divider limit is 16 */
                if (SAR_SAMPLE_CTRL_AVG_MODE_Msk != (SAR_SAMPLE_CTRL(base) & SAR_SAMPLE_CTRL_AVG_MODE_Msk))
                {
                    if (averageAdcSamplesDiv > 16UL)
                    {
                        averageAdcSamplesDiv = 16UL;
                    }
                }

                /* If unsigned format, prevent sign extension */
                if (false == Cy_SAR_IsChannelSigned(base, chan))
                {
                    retVal = (int16_t)(uint32_t)((uint16_t) retVal / averageAdcSamplesDiv);
                }
                else
                {
                    retVal /= (int16_t) averageAdcSamplesDiv;
                }
            }
        }

        /* Subtract ADC offset */
        retVal -= Cy_SAR_offset[chan][CY_SAR_INSTANCE(base)];
    }

    return (retVal);
}


/*******************************************************************************
* Function Name: Cy_SAR_CountsTo_Volts
****************************************************************************//**
*
* Convert the ADC output to Volts as a float32. For example, if the ADC
* measured 0.534 volts, the return value would be 0.534.
* The calculation of voltage depends on the channel offset, gain and other parameters.
* The equation used is:
*
*     V = (RawCounts/AvgDivider - Offset)*TEN_VOLT/Gain
*
* where,
* - RawCounts: Raw counts from SAR 16-bit CHAN_RESULT register
* - AvgDivider: divider based on averaging mode (\ref cy_en_sar_sample_ctrl_avg_mode_t) and number of samples averaged
*   (\ref cy_en_sar_sample_ctrl_avg_cnt_t)
*   - \ref CY_SAR_AVG_MODE_SEQUENTIAL_ACCUM : AvgDivider is the number of samples averaged or 16, whichever is smaller
*   - \ref CY_SAR_AVG_MODE_SEQUENTIAL_FIXED : AvgDivider is 1
*   - \ref CY_SAR_AVG_MODE_INTERLEAVED : AvgDivider is the number of samples averaged
* - Offset: Value stored by the \ref Cy_SAR_SetChannelOffset function.
* - TEN_VOLT: 10 V constant since the gain is in counts per 10 volts.
* - Gain: Value stored by the \ref Cy_SAR_SetChannelGain function.
*
* \note
* This funtion is only valid when result alignment is right aligned.
*
* \param base
* Pointer to structure describing registers
*
* \param chan
* The channel number, between 0 and \ref CY_SAR_INJ_CHANNEL
*
* \param adcCounts
* Conversion result from \ref Cy_SAR_GetResult16
*
* \return
* Result in Volts.
* - If channel number is invalid, 0 is returned.
* - If channel is left aligned, 0 is returned.
*
* \funcusage
*
* \snippet sar/snippet/main.c SNIPPET_SAR_COUNTSTO_VOLTS
*
*******************************************************************************/
float32_t Cy_SAR_CountsTo_Volts(const SAR_Type *base, uint32_t chan, int16_t adcCounts)
{
    CY_ASSERT_L2(CHAN_NUM(chan));

    float32_t result_Volts = 0.0f;

    if (chan < CY_SAR_NUM_CHANNELS)
    {
        if (IS_RIGHT_ALIGN)
        {
            result_Volts = (float32_t)Cy_SAR_RawCounts2Counts(base, chan, adcCounts) * CY_SAR_10V_COUNTS;
            result_Volts /= (float32_t)Cy_SAR_countsPer10Volt[chan][CY_SAR_INSTANCE(base)];
        }
    }

    return result_Volts;
}


/*******************************************************************************
* Function Name: Cy_SAR_CountsTo_mVolts
****************************************************************************//**
*
* Convert the ADC output to millivolts as an int16. For example, if the ADC
* measured 0.534 volts, the return value would be 534.
* The calculation of voltage depends on the channel offset, gain and other parameters.
* The equation used is:
*
*     V = (RawCounts/AvgDivider - Offset)*TEN_VOLT/Gain
*     mV = V * 1000
*
* where,
* - RawCounts: Raw counts from SAR 16-bit CHAN_RESULT register
* - AvgDivider: divider based on averaging mode (\ref cy_en_sar_sample_ctrl_avg_mode_t) and number of samples averaged
*   (\ref cy_en_sar_sample_ctrl_avg_cnt_t)
*   - \ref CY_SAR_AVG_MODE_SEQUENTIAL_ACCUM : AvgDivider is the number of samples averaged or 16, whichever is smaller
*   - \ref CY_SAR_AVG_MODE_SEQUENTIAL_FIXED : AvgDivider is 1
*   - \ref CY_SAR_AVG_MODE_INTERLEAVED : AvgDivider is the number of samples averaged
* - Offset: Value stored by the \ref Cy_SAR_SetChannelOffset function.
* - TEN_VOLT: 10 V constant since the gain is in counts per 10 volts.
* - Gain: Value stored by the \ref Cy_SAR_SetChannelGain function.
*
* \note
* This funtion is only valid when result alignment is right aligned.
*
* \param base
* Pointer to structure describing registers
*
* \param chan
* The channel number, between 0 and \ref CY_SAR_INJ_CHANNEL
*
* \param adcCounts
* Conversion result from \ref Cy_SAR_GetResult16
*
* \return
* Result in millivolts.
* - If channel number is invalid, 0 is returned.
* - If channel is left aligned, 0 is returned.
*
* \funcusage
*
* \snippet sar/snippet/main.c SNIPPET_SAR_COUNTSTO_MVOLTS
*
*******************************************************************************/
int16_t Cy_SAR_CountsTo_mVolts(const SAR_Type *base, uint32_t chan, int16_t adcCounts)
{
    CY_ASSERT_L2(CHAN_NUM(chan));

    int32_t result_mVolts = 0;

    if (chan < CY_SAR_NUM_CHANNELS)
    {
        if (IS_RIGHT_ALIGN)
        {
            int16_t locCounts = Cy_SAR_RawCounts2Counts(base, chan, adcCounts);

            result_mVolts = ((int32_t)locCounts * CY_SAR_10MV_COUNTS);
            if (locCounts > 0)
            {
                result_mVolts += Cy_SAR_countsPer10Volt[chan][CY_SAR_INSTANCE(base)] / 2;
            }
            else
            {
                result_mVolts -= Cy_SAR_countsPer10Volt[chan][CY_SAR_INSTANCE(base)] / 2;
            }
            result_mVolts /= Cy_SAR_countsPer10Volt[chan][CY_SAR_INSTANCE(base)];
        }
    }

    return (int16_t) result_mVolts;
}


/*******************************************************************************
* Function Name: Cy_SAR_CountsTo_uVolts
****************************************************************************//**
*
* Convert the ADC output to microvolts as a int32. For example, if the ADC
* measured 0.534 volts, the return value would be 534000.
* The calculation of voltage depends on the channel offset, gain and other parameters.
* The equation used is:
*
*     V = (RawCounts/AvgDivider - Offset)*TEN_VOLT/Gain
*     uV = V * 1000000
*
* where,
* - RawCounts: Raw counts from SAR 16-bit CHAN_RESULT register
* - AvgDivider: divider based on averaging mode (\ref cy_en_sar_sample_ctrl_avg_mode_t) and number of samples averaged
*   (\ref cy_en_sar_sample_ctrl_avg_cnt_t)
*   - \ref CY_SAR_AVG_MODE_SEQUENTIAL_ACCUM : AvgDivider is the number of samples averaged or 16, whichever is smaller
*   - \ref CY_SAR_AVG_MODE_SEQUENTIAL_FIXED : AvgDivider is 1
*   - \ref CY_SAR_AVG_MODE_INTERLEAVED : AvgDivider is the number of samples averaged
* - Offset: Value stored by the \ref Cy_SAR_SetChannelOffset function.
* - TEN_VOLT: 10 V constant since the gain is in counts per 10 volts.
* - Gain: Value stored by the \ref Cy_SAR_SetChannelGain function.
*
* \note
* This funtion is only valid when result alignment is right aligned.
*
* \param base
* Pointer to structure describing registers
*
* \param chan
* The channel number, between 0 and \ref CY_SAR_INJ_CHANNEL
*
* \param adcCounts
* Conversion result from \ref Cy_SAR_GetResult16
*
* \return
* Result in microvolts.
* - If channel number is valid, 0 is returned.
* - If channel is left aligned, 0 is returned.
*
* \funcusage
*
* \snippet sar/snippet/main.c SNIPPET_SAR_COUNTSTO_UVOLTS
*
*******************************************************************************/
int32_t Cy_SAR_CountsTo_uVolts(const SAR_Type *base, uint32_t chan, int16_t adcCounts)
{
    CY_ASSERT_L2(CHAN_NUM(chan));

    int64_t result_uVolts = 0;

    if (chan < CY_SAR_NUM_CHANNELS)
    {
        if (IS_RIGHT_ALIGN)
        {
            result_uVolts = (int64_t)Cy_SAR_RawCounts2Counts(base, chan, adcCounts) * CY_SAR_10UV_COUNTS;
            result_uVolts /= Cy_SAR_countsPer10Volt[chan][CY_SAR_INSTANCE(base)];
        }
    }

    return ((int32_t)result_uVolts);
}


/*******************************************************************************
* Function Name: Cy_SAR_SetAnalogSwitch
****************************************************************************//**
*
* Provide firmware control of the SARMUX switches for firmware sequencing.
* Each call to this function can open or close a set of switches.
* Previously configured switches are untouched.
*
* If the SARSEQ is enabled, there is no need to use this function.
*
* \param base
* Pointer to structure describing registers
*
* \param switchSelect
* The switch register that contains the desired switches. Select a value
* from \ref cy_en_sar_switch_register_sel_t.
*
* \param switchMask
* The mask of the switches to either open or close.
* Select one or more values from the \ref cy_en_sar_mux_switch_fw_ctrl_t enum
* and "OR" them together.
*
* \param state
* Open or close the desired swithces. Select a value from \ref cy_en_sar_switch_state_t.
*
* \return None
*
* \funcusage
*
* \snippet sar/snippet/main.c SAR_SNIPPET_SET_ANALOG_SWITCH
*
*******************************************************************************/
void Cy_SAR_SetAnalogSwitch(SAR_Type *base, cy_en_sar_switch_register_sel_t switchSelect, uint32_t switchMask, cy_en_sar_switch_state_t state)
{
    CY_ASSERT_L3(CY_SAR_SWITCHSELECT(switchSelect));
    CY_ASSERT_L2(CY_SAR_SWITCHMASK(switchMask));
    CY_ASSERT_L3(CY_SAR_SWITCHSTATE(state));
    (void)switchSelect; /* Suppress warning */

    __IOM uint32_t *switchReg;
    __IOM uint32_t *switchClearReg;

    switchReg = &SAR_MUX_SWITCH0(base);
    switchClearReg = &SAR_MUX_SWITCH_CLEAR0(base);

    switch(state)
    {
    case CY_SAR_SWITCH_CLOSE:
        *switchReg |= switchMask;
        break;
    case CY_SAR_SWITCH_OPEN:
    default:

        /* Unlike the close case, we are not OR'ing the register. Set 1 to clear.*/
        *switchClearReg = switchMask;
        break;
    }
}


/*******************************************************************************
* Function Name: Cy_SAR_GetAnalogSwitch
****************************************************************************//**
*
* Return the state (open or close) of SARMUX switches.
*
* \param base
* Pointer to structure describing registers
*
* \param switchSelect
* The switch register that contains the desired switches. Select a value
* from \ref cy_en_sar_switch_register_sel_t.
*
* \return
* Each bit corresponds to a single switch, where a bit value of 0 is open
* and 1 is closed.
* Compare this value to the switch masks in \ref cy_en_sar_mux_switch_fw_ctrl_t.
*
*******************************************************************************/
uint32_t Cy_SAR_GetAnalogSwitch(const SAR_Type *base, cy_en_sar_switch_register_sel_t switchSelect)
{
    CY_ASSERT_L3(CY_SAR_SWITCHSELECT(switchSelect));
    (void)switchSelect; /* Suppress warning */
    return SAR_MUX_SWITCH0(base);
}


/*******************************************************************************
* Function Name: Cy_SAR_SetSwitchSarSeqCtrl
****************************************************************************//**
*
* Enable or disable SARSEQ control of one or more switches.
* Previously configured switches are untouched.
*
* \param base
* Pointer to structure describing registers
*
* \param switchMask
* The mask of the switches.
* Select one or more values from the \ref cy_en_sar_mux_switch_sq_ctrl_t enum
* and "OR" them together.
*
* \param ctrl
* Enable or disable SARSEQ control. Select a value from \ref cy_en_sar_switch_sar_seq_ctrl_t.
*
* \return None
*
* \funcusage
*
* \snippet sar/snippet/main.c SAR_SNIPPET_SET_SWITCH_SAR_SEQ_CTRL
*
*******************************************************************************/
void Cy_SAR_SetSwitchSarSeqCtrl(SAR_Type *base, uint32_t switchMask, cy_en_sar_switch_sar_seq_ctrl_t ctrl)
{
    CY_ASSERT_L2(CY_SAR_SQMASK(switchMask));
    CY_ASSERT_L3(CY_SAR_SQCTRL(ctrl));

    switch(ctrl)
    {
    case CY_SAR_SWITCH_SEQ_CTRL_ENABLE:
        SAR_MUX_SWITCH_SQ_CTRL(base) |= switchMask;
        break;
    case CY_SAR_SWITCH_SEQ_CTRL_DISABLE:
    default:
        SAR_MUX_SWITCH_SQ_CTRL(base) &= ~switchMask;
        break;
    }
}


/*******************************************************************************
* Function Name: Cy_SAR_DeepSleepCallback
****************************************************************************//**
*
* Callback to prepare the SAR before entering Deep Sleep
* and to re-enable the SAR after exiting Deep Sleep.
*
* \param callbackParams
* Pointer to structure of type \ref cy_stc_syspm_callback_params_t
*
* \param mode
* Callback mode, see \ref cy_en_syspm_callback_mode_t
*
* \return
* See \ref cy_en_syspm_status_t
*
* \funcusage
*
* \snippet sar/snippet/main.c SNIPPET_SAR_DEEPSLEEP_CALLBACK
*
*******************************************************************************/
cy_en_syspm_status_t Cy_SAR_DeepSleepCallback(const cy_stc_syspm_callback_params_t *callbackParams, cy_en_syspm_callback_mode_t mode)
{
    cy_en_syspm_status_t returnValue = CY_SYSPM_SUCCESS;

    if (CY_PASS_V1)
    {
        if (CY_SYSPM_BEFORE_TRANSITION == mode)
        { /* Actions that should be done before entering the Deep Sleep mode */
            Cy_SAR_DeepSleep((SAR_Type *)callbackParams->base);
        }
        else if (CY_SYSPM_AFTER_TRANSITION == mode)
        { /* Actions that should be done after exiting the Deep Sleep mode */
            Cy_SAR_Wakeup((SAR_Type *)callbackParams->base);
        }
        else
        { /* Does nothing in other modes */
        }
    }

    return returnValue;
}


/*******************************************************************************
* Function Name: Cy_SAR_ScanCountEnable
****************************************************************************//**
*
* Enables the Scanning Counter.
* Suitable for PASS_V2.
*
* \param base
* Pointer to the structure of SAR instance registers.
*
* \return The status:
* - CY_SAR_BAD_PARAM - either the feature is not supported by this IP version or
*                      the injection channel is triggered and not tailgating.
* - CY_SAR_SUCCESS - the SAR Scanning Counter feature is successfully enabled.
*
* \funcusage \snippet sar/snippet/main.c SNIPPET_SAR_DS
*
*******************************************************************************/
cy_en_sar_status_t Cy_SAR_ScanCountEnable(const SAR_Type * base)
{
    cy_en_sar_status_t retVal = CY_SAR_BAD_PARAM;

    if (!CY_PASS_V1)
    {
        uint32_t interruptState = Cy_SysLib_EnterCriticalSection();
        uint32_t locInjChanCfg = SAR_INJ_CHAN_CONFIG(base);
        /* If the injection channel is triggered the Scan Counter could be enabled only if the injection channel configured as tailgating  */
        if ((0UL != (locInjChanCfg & SAR_V2_INJ_CHAN_CONFIG_INJ_START_EN_Msk)) ? (0UL == (locInjChanCfg & SAR_V2_INJ_CHAN_CONFIG_INJ_TAILGATING_Msk)) : true)
        {
            PASS_SAR_OVR_CTRL(CY_PASS_V2_ADDR) |= CY_SAR_INSTANCE_MASK(base) << PASS_V2_SAR_OVR_CTRL_TR_SCAN_CNT_SEL_Pos;
            Cy_SysLib_ExitCriticalSection(interruptState);
            retVal = CY_SAR_SUCCESS;
        }
    }

    return (retVal);
}
CY_MISRA_BLOCK_END('MISRA C-2012 Rule 11.3');


#if defined(__cplusplus)
}
#endif

#endif /* CY_IP_MXS40PASS_SAR */

/* [] END OF FILE */