Newer
Older
mbed-os / targets / TARGET_TOSHIBA / TARGET_TMPM4NR / Periph_driver / src / txz_adc.c
@Jay Sridharan Jay Sridharan on 31 Dec 2022 35 KB Merge upstream changes into mbed-ce (#117)
/**
 *******************************************************************************
 * @file    txz_adc.c
 * @brief   This file provides API functions for ADC driver.
 * @version V1.0.0
 *
 * DO NOT USE THIS SOFTWARE WITHOUT THE SOFTWARE LICENSE AGREEMENT.
 *
 * Copyright(C) TOSHIBA ELECTRONIC DEVICES & STORAGE CORPORATION 2021
 * 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.
 *******************************************************************************
 */

#ifdef __cplusplus
extern "C" {
#endif

/*------------------------------------------------------------------------------*/
/*  Includes                                                                    */
/*------------------------------------------------------------------------------*/
#include "txz_adc_include.h"
#include "txz_adc_ch.h"
#include "txz_adc.h"

#if defined(__ADC_H)
/**
 *  @addtogroup Periph_Driver Peripheral Driver
 *  @{
 */

/**
 *  @addtogroup ADC
 *  @{
 */

/*------------------------------------------------------------------------------*/
/*  Configuration                                                               */
/*------------------------------------------------------------------------------*/
/**
 *  @defgroup ADC_Private_define ADC Private Define
 *  @{
 */


/**
 *  @}
 */ /* End of group ADC_Private_define */

/*------------------------------------------------------------------------------*/
/*  Macro Definition                                                            */
/*------------------------------------------------------------------------------*/
/**
 *  @defgroup ADC_Private_macro ADC Private Macro
 *  @{
 */

/* no define */

/**
 *  @}
 */ /* End of group ADC_Private_macro */


/*------------------------------------------------------------------------------*/
/*  Enumerated Type Definition                                                  */
/*------------------------------------------------------------------------------*/
/**
 *  @defgroup ADC_Private_Enumeration ADC Private Enumeration
 *  @{
 */

/* no define */

/**
 *  @}
 */ /* End of group ADC_Private_Enumeration */

/*------------------------------------------------------------------------------*/
/*  Structure Definition                                                        */
/*------------------------------------------------------------------------------*/
/**
 *  @defgroup ADC_Private_typedef ADC Private Typedef
 *  @{
 */

/* no define */

/**
 *  @}
 */ /* End of group ADC_Private_typedef */

/*------------------------------------------------------------------------------*/
/*  Variable Definition                                                        */
/*------------------------------------------------------------------------------*/
/**
 *  @defgroup ADC_Private_variable ADC Private Variable Definition
 *  @{
 */
static adc_t *p_AdcObj;
/**
 *  @}
 */ /* End of group ADC_Private_variable */

/*------------------------------------------------------------------------------*/
/*  Private Function                                                            */
/*------------------------------------------------------------------------------*/
/**
 *  @defgroup ADC_Private_fuctions ADC Private Fuctions
 *  @{
 */
static int32_t check_param_sampling_period0(adc_sampling_period0_t param);
static int32_t check_param_sampling_period1(adc_sampling_period1_t param);
static int32_t check_param_prescaler_output(adc_sclk_t param);
static int32_t check_param_interrupt(adc_int_t param);
static int32_t check_param_type(adc_conversion_t param);
static int32_t check_param_ain(adc_ain_range_t ain, adc_ain_range_t min, adc_ain_range_t max);
static void clear_ch_instance_info(adc_ch_t *p_ch);

/*--------------------------------------------------*/
/*!
  * @fn     static int32_t check_param_sampling_period0(adc_sampling_period0_t param)
  * @brief  Check the Sampling Period's parameter.
  * @param[in] param :Sampling Period's parameter
  * @retval    ADC_PARAM_OK :Success.
  * @retval    ADC_PARAM_NG :Failure.
  * @note   Macro definition is ADC_SamplingPeriod"ADC_SAMPLING_PERIOD_xxxx".
  */
/*--------------------------------------------------*/
static int32_t check_param_sampling_period0(adc_sampling_period0_t param)
{
    int32_t result = ADC_PARAM_NG;

    switch (param) {
        case ADC_SAMPLING_PERIOD0_XN:
        case ADC_SAMPLING_PERIOD0_X2N:
        case ADC_SAMPLING_PERIOD0_X3N:
        case ADC_SAMPLING_PERIOD0_X4N:
            result = ADC_PARAM_OK;
            break;
        default:
            /* no process */
            break;
    }

    return (result);
}

/*--------------------------------------------------*/
/*!
  * @fn     static int32_t check_param_sampling_period1(adc_sampling_period1_t param)
  * @brief  Check the Sampling Period's parameter.
  * @param[in] param :Sampling Period's parameter
  * @retval    ADC_PARAM_OK :Success.
  * @retval    ADC_PARAM_NG :Failure.
  * @note   Macro definition is ADC_SamplingPeriod"ADC_SAMPLING_PERIOD_xxxx".
  */
/*--------------------------------------------------*/
static int32_t check_param_sampling_period1(adc_sampling_period1_t param)
{
    int32_t result = ADC_PARAM_NG;

    switch (param) {
        case ADC_SAMPLING_PERIOD1_XN:
        case ADC_SAMPLING_PERIOD1_X2N:
        case ADC_SAMPLING_PERIOD1_X3N:
        case ADC_SAMPLING_PERIOD1_X4N:
            result = ADC_PARAM_OK;
            break;
        default:
            /* no process */
            break;
    }

    return (result);
}

/*--------------------------------------------------*/
/*!
  * @fn     static int32_t check_param_prescaler_output(adc_sclk_t param)
  * @brief  Check the AD Prescaler Output's parameter.
  * @param[in] param :AD Prescaler Output's parameter
  * @retval    ADC_PARAM_OK :Success.
  * @retval    ADC_PARAM_NG :Failure.
  * @note   Macro definition is ADC_SCLK"ADC_SCLK_xxxx".
  */
/*--------------------------------------------------*/
static int32_t check_param_prescaler_output(adc_sclk_t param)
{
    int32_t result = ADC_PARAM_NG;

    switch (param) {
        case ADC_SCLK_2:
        case ADC_SCLK_4:
        case ADC_SCLK_8:
        case ADC_SCLK_16:
        case ADC_SCLK_3:
        case ADC_SCLK_5:
        case ADC_SCLK_6:
        case ADC_SCLK_10:
            result = ADC_PARAM_OK;
            break;
        default:
            /* no process */
            break;
    }

    return (result);
}

/*--------------------------------------------------*/
/*!
  * @fn     static int32_t check_param_interrupt(adc_int_t param)
  * @brief  Check the Interrupt's parameter.
  * @param[in] param :Interrupt's parameter
  * @retval    ADC_PARAM_OK :Success.
  * @retval    ADC_PARAM_NG :Failure.
  * @note   Macro definition is ADC_IntEnable"ADC_INT_xxxx".
  */
/*--------------------------------------------------*/
static int32_t check_param_interrupt(adc_int_t param)
{
    int32_t result = ADC_PARAM_NG;

    switch (param) {
        case ADC_INT_DISABLE:
        case ADC_INT_ENABLE:
            result = ADC_PARAM_OK;
            break;
        default:
            /* no process */
            break;
    }

    return (result);
}

/*--------------------------------------------------*/
/*!
  * @fn     static int32_t check_param_type(adc_conversion_t param)
  * @brief  Check the Conversion Type's parameter.
  * @param[in] param :Conversion Type's parameter
  * @retval    ADC_PARAM_OK :Success.
  * @retval    ADC_PARAM_NG :Failure.
  * @note   Macro definition is ADC_Conversion"ADC_CONVERSION_xxxx".
  */
/*--------------------------------------------------*/
static int32_t check_param_type(adc_conversion_t param)
{
    int32_t result = ADC_PARAM_NG;

    switch (param) {
        case ADC_CONVERSION_DISABLE:
        case ADC_CONVERSION_CNT:
        case ADC_CONVERSION_SGL:
        case ADC_CONVERSION_TRG:
        case ADC_CONVERSION_HPTG:
            result = ADC_PARAM_OK;
            break;
        default:
            /* no process */
            break;
    }

    return (result);
}

/*--------------------------------------------------*/
/*!
  * @fn     static int32_t check_param_ain(adc_ain_range_t ain, adc_ain_range_t min, adc_ain_range_t max)
  * @brief  Check the AIN Range's parameter.
  * @param[in] ain :AIN Range's parameter
  * @param[in] min :Range Min.
  * @param[in] max :Range Max.
  * @retval    ADC_PARAM_OK :Success.
  * @retval    ADC_PARAM_NG :Failure.
  * @note   -
  */
/*--------------------------------------------------*/
static int32_t check_param_ain(adc_ain_range_t ain, adc_ain_range_t min, adc_ain_range_t max)
{
    int32_t result = ADC_PARAM_NG;

    if (min == 0) {
        if (ain <= max) {
            result = ADC_PARAM_OK;
        }
    } else {
        if ((min <= ain) && (ain <= max)) {
            result = ADC_PARAM_OK;
        }
    }

    return (result);
}

/*--------------------------------------------------*/
/*!
  * @fn     static void clear_ch_instance_info(adc_ch_t *p_ch)
  * @brief  Channel Instance Information Clear.
  * @param[in] p_ch :Channel Instance Address.
  * @retval -
  * @note   -
  */
/*--------------------------------------------------*/
static void clear_ch_instance_info(adc_ch_t *p_ch)
{
    p_ch->p_tset     = ADC_NULL;
    p_ch->p_reg      = ADC_NULL;
    p_ch->init.type  = ADC_CONVERSION_DISABLE;
}
/*--------------------------------------------------*/
/*!
  * @fn     static void adc_compa_irq_handler( void )
  * @brief  IRQ Handler for Compare_A done.
  * @param -
  * @retval -
  * @note   Call by Compare_A Done IRQ Handler.
 */
/*--------------------------------------------------*/
void adc_compa_irq_handler(void)
{
    /*------------------------------*/
    /*  Call Handler                */
    /*------------------------------*/
    if ((p_AdcObj != ADC_NULL) &&
            (p_AdcObj->init.CMPxEN[0].handle != ADC_NULL)) {
        p_AdcObj->init.CMPxEN[0].handle(p_AdcObj->init.id, TXZ_SUCCESS);
    }
}

/*--------------------------------------------------*/
/*!
  * @fn     static void adc_compb_irq_handler( void )
  * @brief  IRQ Handler for Compare_B done.
  * @param -
  * @retval -
  * @note   Call by Compare_B Done IRQ Handler.
 */
/*--------------------------------------------------*/
void adc_compb_irq_handler(void)
{
    /*------------------------------*/
    /*  Call Handler                */
    /*------------------------------*/
    if ((p_AdcObj != ADC_NULL) &&
            (p_AdcObj->init.CMPxEN[1].handle != ADC_NULL)) {
        p_AdcObj->init.CMPxEN[1].handle(p_AdcObj->init.id, TXZ_SUCCESS);
    }
}

/*--------------------------------------------------*/
/*!
  * @fn     static void adc_single_irq_handler( void )
  * @brief  IRQ Handler for single conversion done.
  * @param -
  * @retval -
  * @note   Call by Single Conversion Done IRQ Handler.
 */
/*--------------------------------------------------*/
void adc_single_irq_handler(void)
{
    /*------------------------------*/
    /*  Call Handler                */
    /*------------------------------*/
    if ((p_AdcObj != ADC_NULL) &&
            (p_AdcObj->handler.single != ADC_NULL)) {
        p_AdcObj->handler.single(p_AdcObj->init.id, TXZ_SUCCESS);
    }
}

/*--------------------------------------------------*/
/*!
  * @fn     static void adc_continuity_irq_handler( void )
  * @brief  IRQ Handler for continuity conversion done.
  * @param -
  * @retval -
  * @note   Call by Continuity Conversion Done IRQ Handler.
 */
/*--------------------------------------------------*/
void adc_continuity_irq_handler(void)
{
    /*------------------------------*/
    /*  Call Handler                */
    /*------------------------------*/
    if ((p_AdcObj != ADC_NULL) &&
            (p_AdcObj->handler.continuity != ADC_NULL)) {
        p_AdcObj->handler.continuity(p_AdcObj->init.id, TXZ_SUCCESS);
    }
}

/*--------------------------------------------------*/
/*!
  * @fn     static void adc_trigger_irq_handler( void )
  * @brief  IRQ Handler for trigger conversion done.
  * @param -
  * @retval -
  * @note   Call by Trigger Conversion Done IRQ Handler.
 */
/*--------------------------------------------------*/
void adc_trigger_irq_handler(void)
{
    /*------------------------------*/
    /*  Call Handler                */
    /*------------------------------*/
    if ((p_AdcObj != ADC_NULL) &&
            (p_AdcObj->handler.trigger != ADC_NULL)) {
        p_AdcObj->handler.trigger(p_AdcObj->init.id, TXZ_SUCCESS);
    }
}

/*--------------------------------------------------*/
/*!
  * @fn     static void adc_highpriority_irq_handler( void )
  * @brief  IRQ Handler for highpriority conversion done.
  * @param -
  * @retval -
  * @note   Call by HigPriority Conversion Done IRQ Handler.
 */
/*--------------------------------------------------*/
void adc_highpriority_irq_handler(void)
{
    /*------------------------------*/
    /*  Call Handler                */
    /*------------------------------*/
    if ((p_AdcObj != ADC_NULL) &&
            (p_AdcObj->handler.highpriority != ADC_NULL)) {
        p_AdcObj->handler.highpriority(p_AdcObj->init.id, TXZ_SUCCESS);
    }
}

/**
 *  @}
 */ /* End of group ADC_Private_functions */

/*------------------------------------------------------------------------------*/
/*  Public Function                                                             */
/*------------------------------------------------------------------------------*/
/**
 *  @addtogroup ADC_Exported_functions
 *  @{
 */
/*--------------------------------------------------*/
/*!
  * @fn     TXZ_Result adc_init(adc_t *p_obj)
  * @brief     Initialize the ADC object.
  * @param[in] p_obj :ADC object.
  * @retval    TXZ_SUCCESS :Success.
  * @retval    TXZ_ERROR   :Failure.
  * @note      -
  * @attention This function is not available in interrupt. After initialization, 3us of stabilization time is needed.
  */
/*--------------------------------------------------*/
TXZ_Result adc_init(adc_t *p_obj)
{
    TXZ_Result result = TXZ_SUCCESS;
    p_AdcObj = p_obj;

    /*------------------------------*/
    /*  Parameter Check             */
    /*------------------------------*/
    /* Check the parameter.           */
    if ((void *)(p_obj) == (void *)0) {
        result = TXZ_ERROR;
    } else if ((void *)(p_obj->p_instance) == (void *)0) {
        result = TXZ_ERROR;
    }
    if (check_param_sampling_period0(p_obj->init.clk.exaz0) == ADC_PARAM_NG) {
        result = TXZ_ERROR;
    }
    if (check_param_sampling_period1(p_obj->init.clk.exaz1) == ADC_PARAM_NG) {
        result = TXZ_ERROR;
    }
    if (p_obj->init.clk.sampling_select > 0x0100000) {
        result = TXZ_ERROR;
    }
    if (check_param_prescaler_output(p_obj->init.clk.vadcld) == ADC_PARAM_NG) {
        result = TXZ_ERROR;
    }
    if (result == TXZ_SUCCESS) {
        /*------------------------------*/
        /*  Init Variable               */
        /*------------------------------*/
        uint32_t i;

        for (i = 0; i < ADC_NUM_MAX; i++) {
            clear_ch_instance_info(&p_obj->info.ch[i]);
        }
        /*------------------------------*/
        /*  Register Setting            */
        /*------------------------------*/
        /*--- ADxCLK  ---*/
        p_obj->p_instance->CLK  = ((uint32_t)p_obj->init.clk.exaz0 | (uint32_t)p_obj->init.clk.exaz1 | (uint32_t)p_obj->init.clk.vadcld);
        /*--- ADxEXAZSEL  ---*/
        p_obj->p_instance->EXAZSEL = (uint32_t)p_obj->init.clk.sampling_select;
        /*--- ADxMOD0 ---*/
        p_obj->p_instance->MOD0 = (ADxMOD0_RCUT_NORMAL | ADxMOD0_DACON_ON);
        /* wait 3us after set the MOD0 to 1 */
        wait(3);
        /*--- ADxMOD1 ---*/
        p_obj->p_instance->MOD1 = p_obj->init.mod1;
        /*--- ADxMOD2 ---*/
        p_obj->p_instance->MOD2 = p_obj->init.mod2;
    }

    return (result);
}

/*--------------------------------------------------*/
/*!
  * @fn     TXZ_Result adc_deinit(adc_t *p_obj)
  * @brief     Release the ADC object.
  * @param[in] p_obj :ADC object.
  * @retval    TXZ_SUCCESS :Success.
  * @retval    TXZ_ERROR   :Failure.
  * @note      -
  * @attention This function is not available in interrupt.
  */
/*--------------------------------------------------*/
TXZ_Result adc_deinit(adc_t *p_obj)
{
    TXZ_Result result = TXZ_SUCCESS;
    uint32_t i;
    adc_ch_t *p_ch;
    p_AdcObj = p_obj;

    /*------------------------------*/
    /*  Parameter Check             */
    /*------------------------------*/
    if (((void *)(p_obj) == (void *)0) ||
            ((void *)(p_obj->p_instance) == (void *)0)) {
        result = TXZ_ERROR;
    } else {
        /*------------------------------*/
        /*  Register Setting            */
        /*------------------------------*/
        /*--- ADxCR0   ---*/
        p_obj->p_instance->CR0   = (ADxCR0_ADEN_DISABLE | ADxCR0_CNT_DISABLE);
        /*------------------------------*/
        /*  Wait Stop                   */
        /*------------------------------*/
        /*--- ADxST   ---*/
        /* When all convetion stop, ADxST is set "0". */
        while (p_obj->p_instance->ST != 0) {
            /* no processing */
        }
        /*------------------------------*/
        /*  Channel Class Destruct      */
        /*------------------------------*/
        for (i = 0; i < ADC_NUM_MAX; i++) {
            p_ch = &p_obj->info.ch[i];
            if (p_ch->init.type == ADC_CONVERSION_DISABLE) {
                if (adc_ch_deinit(p_ch) == TXZ_SUCCESS) {
                    clear_ch_instance_info(p_ch);
                }
            }
        }
        /*------------------------------*/
        /*  Register Setting            */
        /*------------------------------*/
        /*--- ADxCMPEN ---*/
        p_obj->p_instance->CMPEN = (ADxCMPEN_CMP1EN_DISABLE | ADxCMPEN_CMP0EN_DISABLE);
        /*--- ADxCR1   ---*/
        p_obj->p_instance->CR1   = (ADxCR1_CNTDMEN_DISABLE | ADxCR1_SGLDMEN_DISABLE | ADxCR1_TRGDMEN_DISABLE | ADxCR1_TRGEN_DISABLE);
        /*--- ADxMOD0 ---*/
        p_obj->p_instance->MOD0  = (ADxMOD0_RCUT_IREF_CUT | ADxMOD0_DACON_OFF);
        /*--- ADxMOD1 ---*/
        p_obj->p_instance->MOD1  = ADC_MOD1_SCLK_3;
        /*--- ADxMOD2 ---*/
        p_obj->p_instance->MOD2  = ADC_MOD2_CLEAR;
    }

    return (result);
}

/*--------------------------------------------------*/
/*!
  * @fn     TXZ_Result adc_channel_setting(adc_t *p_obj, uint32_t ch, adc_channel_setting_t *p_setting)
  * @brief     ADC Channel Setting
  * @param[in] p_obj  :ADC object.
  * @param[in] ch          :Channel. Range is (value < ADC_NUM_MAX).
  * @param[in] p_setting   :Channel Setting Source Address.
  * @retval    TXZ_SUCCESS :Success.
  * @retval    TXZ_ERROR   :Failure.
  * @note      -
  * @pre       Conversion has stoped.
  * @attention This function is not available in interrupt.
  */
/*--------------------------------------------------*/
TXZ_Result adc_channel_setting(adc_t *p_obj, uint32_t ch, adc_channel_setting_t *p_setting)
{
    TXZ_Result result = TXZ_SUCCESS;
    p_AdcObj = p_obj;

    /*------------------------------*/
    /*  Parameter Check             */
    /*------------------------------*/
    if (((void *)(p_obj) == (void *)0) ||
            ((void *)(p_obj->p_instance) == (void *)0) ||
            ((void *)(p_setting) == (void *)0) ||
            (ch >= ADC_NUM_MAX)) {
        result = TXZ_ERROR;
    }
    if (check_param_interrupt((adc_int_t)p_setting->interrupt) == ADC_PARAM_NG) {
        result = TXZ_ERROR;
    }
    if (check_param_type((adc_conversion_t)p_setting->type) == ADC_PARAM_NG) {
        result = TXZ_ERROR;
    }
    if (check_param_ain((adc_ain_range_t)p_setting->ain, ADC_AIN_RANGE_MIN, ADC_AIN_RANGE_MAX) == ADC_PARAM_NG) {
        result = TXZ_ERROR;
    }
    if (result == TXZ_SUCCESS) {
        /*------------------------------*/
        /*  Channel Class Construct     */
        /*------------------------------*/
        adc_ch_t *p_ch = &p_obj->info.ch[ch];

        p_ch->p_tset   = (__IO uint32_t *)(&p_obj->p_instance->TSET0 + ch);
        p_ch->p_reg    = (__I uint32_t *)(&p_obj->p_instance->REG0 + ch);
        p_ch->init.interrupt   = p_setting->interrupt;
        p_ch->init.type        = p_setting->type;
        p_ch->init.ain         = p_setting->ain;
        result = adc_ch_init(p_ch);
    }

    return (result);
}

/*--------------------------------------------------*/
/*!
  * @fn     TXZ_Result adc_channel_clear(adc_t *p_obj, uint32_t ch)
  * @brief     ADC Channel Clear
  * @param[in] p_obj  :ADC object.
  * @param[in] ch          :Channel. Range is (value < ADC_NUM_MAX).
  * @retval    TXZ_SUCCESS :Success.
  * @retval    TXZ_ERROR   :Failure.
  * @note      -
  * @pre       Conversion has stoped.
  * @attention This function is not available in interrupt.
  */
/*--------------------------------------------------*/
TXZ_Result adc_channel_clear(adc_t *p_obj, uint32_t ch)
{
    TXZ_Result result = TXZ_SUCCESS;
    p_AdcObj = p_obj;

    /*------------------------------*/
    /*  Parameter Check             */
    /*------------------------------*/
    if (((void *)(p_obj) == (void *)0) ||
            (ch >= ADC_NUM_MAX)) {
        result = TXZ_ERROR;
    } else {
        /*------------------------------*/
        /*  Channel Class Destruct      */
        /*------------------------------*/
        adc_ch_t *p_ch = &p_obj->info.ch[ch];

        result = adc_ch_deinit(p_ch);
        /* Init Variable */
        clear_ch_instance_info(p_ch);
    }

    return (result);
}

/*--------------------------------------------------*/
/*!
  * @fn     TXZ_Result adc_cmp_init(adc_t *p_obj, adc_cmpx_t *p_cmpx_t)
  * @brief     Initialize the ADC Compare register
  * @param[in] p_obj  :ADC object.
  * @param[in] p_cmpx_t    :Clock information structure.
  * @retval    TXZ_SUCCESS :Success.
  * @retval    TXZ_ERROR   :Failure.
  * @note      -
  * @attention This function is not available in interrupt.
  * @attention After initialization, 3us of stabilization time is needed.
  */
/*--------------------------------------------------*/
TXZ_Result adc_cmp_init(adc_t *p_obj, adc_cmpx_t *p_cmpx_t)
{
    TXZ_Result result = TXZ_SUCCESS;
    p_AdcObj = p_obj;
    /*------------------------------*/
    /*  Parameter Check             */
    /*------------------------------*/
    if (((void *)(p_obj) == (void *)0) ||
            ((void *)(p_cmpx_t) == (void *)0)) {
        result = TXZ_ERROR;
    } else {
        /*------------------------------*/
        /*  Init Variable               */
        /*------------------------------*/
        if (p_cmpx_t->CMPEN == ADCMP0EN_DISABLE) {
            p_obj->p_instance->CMPEN &= ~(uint32_t)ADCMP0EN_ENABLE;
        }
        if (p_cmpx_t->CMPEN == ADCMP1EN_DISABLE) {
            p_obj->p_instance->CMPEN &= ~(uint32_t)ADCMP1EN_ENABLE;
        }
        /*------------------------------*/
        /*  Register Setting            */
        /*------------------------------*/
        if (p_cmpx_t->CMPEN == ADCMP0EN_ENABLE) {
            p_obj->init.CMPxEN[0].CMPEN = p_cmpx_t->CMPEN;
            p_obj->init.CMPxEN[0].CMPCNT = p_cmpx_t->CMPCNT;
            p_obj->init.CMPxEN[0].CMPCond = p_cmpx_t->CMPCond;
            p_obj->init.CMPxEN[0].CMPBigSml = p_cmpx_t->CMPBigSml;
            p_obj->init.CMPxEN[0].StrReg = p_cmpx_t->StrReg;
            p_obj->init.CMPxEN[0].ADComp = p_cmpx_t->ADComp;
            p_obj->init.CMPxEN[0].handle = p_cmpx_t->handle;
            p_obj->p_instance->CMPEN |= p_cmpx_t->CMPEN;
            p_obj->p_instance->CMPCR0 = p_cmpx_t->CMPCNT | p_cmpx_t->CMPCond | p_cmpx_t->CMPBigSml | p_cmpx_t->StrReg;
            p_obj->p_instance->CMP0 = p_cmpx_t->ADComp;
        } else if (p_cmpx_t->CMPEN == ADCMP1EN_ENABLE) {
            p_obj->init.CMPxEN[1].CMPEN = p_cmpx_t->CMPEN;
            p_obj->init.CMPxEN[1].CMPCNT = p_cmpx_t->CMPCNT;
            p_obj->init.CMPxEN[1].CMPCond = p_cmpx_t->CMPCond;
            p_obj->init.CMPxEN[1].CMPBigSml = p_cmpx_t->CMPBigSml;
            p_obj->init.CMPxEN[1].StrReg = p_cmpx_t->StrReg;
            p_obj->init.CMPxEN[1].ADComp = p_cmpx_t->ADComp;
            p_obj->init.CMPxEN[1].handle = p_cmpx_t->handle;
            p_obj->p_instance->CMPEN |= p_cmpx_t->CMPEN;
            p_obj->p_instance->CMPCR1 = p_cmpx_t->CMPCNT | p_cmpx_t->CMPCond | p_cmpx_t->CMPBigSml | p_cmpx_t->StrReg;
            p_obj->p_instance->CMP1 = p_cmpx_t->ADComp;
        }
    }

    return (result);
}

/*--------------------------------------------------*/
/*!
  * @fn     TXZ_Result adc_cmp_deinit(adc_t *p_obj, adc_cmpx_t *p_cmpx_t)
  * @brief     Release the ADC Compare register
  * @param[in] p_obj  :ADC object.
  * @param[in] p_cmpx_t    :Clock information structure.
  * @retval    TXZ_SUCCESS :Success.
  * @retval    TXZ_ERROR   :Failure.
  * @note      -
  * @attention This function is not available in interrupt.
  * @attention After initialization, 3us of stabilization time is needed.
  */
/*--------------------------------------------------*/
TXZ_Result adc_cmp_deinit(adc_t *p_obj, adc_cmpx_t *p_cmpx_t)
{
    TXZ_Result result = TXZ_SUCCESS;
    p_AdcObj = p_obj;

    /*------------------------------*/
    /*  Parameter Check             */
    /*------------------------------*/
    if (((void *)(p_obj) == (void *)0) ||
            ((void *)(p_cmpx_t) == (void *)0)) {
        result = TXZ_ERROR;
    } else {
        /*------------------------------*/
        /*  Register Setting            */
        /*------------------------------*/
        if (p_cmpx_t->CMPEN == ADCMP0EN_DISABLE) {
            p_obj->init.CMPxEN[0].CMPEN = 0;
            p_obj->init.CMPxEN[0].CMPCNT = 0;
            p_obj->init.CMPxEN[0].CMPCond = 0;
            p_obj->init.CMPxEN[0].CMPBigSml = 0;
            p_obj->init.CMPxEN[0].StrReg = 0;
            p_obj->init.CMPxEN[0].ADComp = 0;
            p_obj->init.CMPxEN[0].handle = (void *)0;
            p_obj->p_instance->CMPEN &= ~(uint32_t)ADCMP0EN_ENABLE;
            p_obj->p_instance->CMPCR0 = 0;
            p_obj->p_instance->CMP0 = 0;
        } else if (p_cmpx_t->CMPEN == ADCMP1EN_DISABLE) {
            p_obj->init.CMPxEN[1].CMPEN = 0;
            p_obj->init.CMPxEN[1].CMPCNT = 0;
            p_obj->init.CMPxEN[1].CMPCond = 0;
            p_obj->init.CMPxEN[1].CMPBigSml = 0;
            p_obj->init.CMPxEN[1].StrReg = 0;
            p_obj->init.CMPxEN[1].ADComp = 0;
            p_obj->init.CMPxEN[1].handle = (void *)0;
            p_obj->p_instance->CMPEN &= ~(uint32_t)ADCMP1EN_ENABLE;
            p_obj->p_instance->CMPCR1 = 0;
            p_obj->p_instance->CMP1 = 0;
        }
    }

    return (result);
}

/*--------------------------------------------------*/
/*!
  * @fn     TXZ_Result adc_channel_get_value(adc_t *p_obj, uint32_t ch, uint32_t *p_value)
  * @brief  Get AD value
  * @param[in] p_obj  :ADC object.
  * @param[in] ch         :Channel. Range is (value < ADC_NUM_MAX).
  * @param  p_value     :AD value. Destination address.
  * @retval TXZ_SUCCESS :Success.
  * @retval TXZ_ERROR   :Failure.
  * @note   -
  */
/*--------------------------------------------------*/
TXZ_Result adc_channel_get_value(adc_t *p_obj, uint32_t ch, uint32_t *p_value)
{
    TXZ_Result result = TXZ_ERROR;

    /*------------------------------*/
    /*  Parameter Check             */
    /*------------------------------*/
    if (((void *)(p_obj) == (void *)0) ||
            ((void *)(p_obj->p_instance) == (void *)0) ||
            ((void *)(p_value) == (void *)0) ||
            (ch >= ADC_NUM_MAX)) {
        result = TXZ_ERROR;
    } else {
        /*------------------------------*/
        /*  Get Value                   */
        /*------------------------------*/
        adc_ch_t *p_ch = &p_obj->info.ch[ch];

        result = adc_ch_get_value(p_ch, p_value);
    }

    return (result);
}

/*--------------------------------------------------*/
/*!
  * @fn     TXZ_Result adc_start(adc_t *p_obj)
  * @brief  Start Conversion.
  * @param[in] p_obj    :ADC object.
  * @retval TXZ_SUCCESS :Success.
  * @retval TXZ_ERROR   :Failure.
  * @note   -
  * @pre    Conversion has stoped.
  * @attention This function is not available in interrupt.
  */
/*--------------------------------------------------*/
TXZ_Result adc_start(adc_t *p_obj)
{
    TXZ_Result result = TXZ_SUCCESS;

    /*------------------------------*/
    /*  Parameter Check             */
    /*------------------------------*/
    if (((void *)(p_obj) == (void *)0) ||
            ((void *)(p_obj->p_instance) == (void *)0)) {
        result = TXZ_ERROR;
    } else {
        /*------------------------------*/
        /*  Enable Conversion           */
        /*------------------------------*/
        uint32_t i;
        adc_ch_t *p_ch;
        uint32_t cr0 = (ADxCR0_ADEN_ENABLE | ADxCR0_CNT_DISABLE);
        uint32_t cr1 = (ADxCR1_CNTDMEN_DISABLE | ADxCR1_SGLDMEN_DISABLE | ADxCR1_TRGDMEN_DISABLE | ADxCR1_TRGEN_DISABLE);

        for (i = 0; i < ADC_NUM_MAX; i++) {
            p_ch = &p_obj->info.ch[i];
            switch (p_ch->init.type) {
                case ADC_CONVERSION_CNT:
                    cr0 |= ADxCR0_CNT_ENABLE;
                    break;
                case ADC_CONVERSION_SGL:
                    cr0 |= ADxCR0_SGL_ENABLE;
                    break;
                case ADC_CONVERSION_TRG:
                    cr1 |= ADxCR1_TRGEN_ENABLE;
                    break;
                case ADC_CONVERSION_HPTG:
                    cr1 |= ADxCR1_HPTRGEN_ENABLE;
                    break;
                default:
                    /* no processing */
                    break;
            }
        }
        /*--- ADxCR1  ---*/
        p_obj->p_instance->CR1 = cr1;
        /*--- ADxCR0  ---*/
        p_obj->p_instance->CR0 = cr0;
    }

    return (result);
}

/*--------------------------------------------------*/
/*!
  * @fn     TXZ_Result adc_stop(adc_t *p_obj)
  * @brief  Stop Conversion.
  * @param[in] p_obj    :ADC object.
  * @retval TXZ_SUCCESS :Success.
  * @retval TXZ_ERROR   :Failure.
  * @note   -
  * @attention This function is not available in interrupt.
  */
/*--------------------------------------------------*/
TXZ_Result adc_stop(adc_t *p_obj)
{
    TXZ_Result result = TXZ_SUCCESS;
    uint32_t i;
    adc_ch_t *p_ch;
    uint32_t value;
    /*------------------------------*/
    /*  Parameter Check             */
    /*------------------------------*/
    if (((void *)(p_obj) == (void *)0) ||
            ((void *)(p_obj->p_instance) == (void *)0)) {
        result = TXZ_ERROR;
    } else {
        /*------------------------------*/
        /*  Disable Conversion          */
        /*------------------------------*/
        /*--- ADxCR0   ---*/
        p_obj->p_instance->CR0 = (ADxCR0_ADEN_DISABLE | ADxCR0_CNT_DISABLE);
        /*------------------------------*/
        /*  Wait Stop                   */
        /*------------------------------*/
        /*--- ADxST   ---*/
        /* When all convetion stop, ADxST is set "0". */
        while (p_obj->p_instance->ST != 0) {
            /* no processing */
        }
        /*------------------------------*/
        /*  Dummy Read                  */
        /*------------------------------*/
        /* Read is needed before the next convertion. */
        for (i = 0; i < ADC_NUM_MAX; i++) {
            p_ch = &p_obj->info.ch[i];
            if (p_ch->init.type == ADC_CONVERSION_DISABLE) {
                if (adc_ch_get_value(p_ch, &value) != TXZ_SUCCESS) {
                    /* no processing */
                }
            }
        }
    }

    return (result);
}

/*--------------------------------------------------*/
/*!
  * @fn     TXZ_WorkState adc_poll_conversion(adc_t *p_obj, uint32_t timeout)
  * @brief  Wait for single conversion to be completed
  * @param[in] p_obj    :ADC object.
  * @param[in] timeout  :Timeout(tick).
  * @retval TXZ_DONE    :Success.
  * @retval TXZ_BUSY    :Failure.
  * @note   -
  * @attention This function is not available in interrupt.
  */
/*--------------------------------------------------*/
TXZ_WorkState adc_poll_conversion(adc_t *p_obj, uint32_t timeout)
{
    TXZ_WorkState result    = TXZ_BUSY;
    TXZ_WorkState loopBreak = TXZ_BUSY;
    uint32_t base    = hal_get_tick();
    uint32_t current = 0;
    uint32_t status;

    /*------------------------------*/
    /*  Parameter Check             */
    /*------------------------------*/
    if (((void *)(p_obj) == (void *)0) ||
            ((void *)(p_obj->p_instance) == (void *)0)) {
        result = TXZ_DONE;
    } else {
        /*------------------------------*/
        /*  Check Status                */
        /*------------------------------*/
        while (loopBreak == TXZ_BUSY) {
            /*--- Check Status ---*/
            /* Read status.  */
            status = p_obj->p_instance->ST;
            /* Check status. */
            if ((status & ADxST_SNGF_MASK) == ADxST_SNGF_IDLE) {
                result    = TXZ_DONE;
                loopBreak = TXZ_DONE;
            } else {
                /*--- Check Timeout ---*/
                if (timeout == 0) {
                    loopBreak = TXZ_DONE;
                } else {
                    current = hal_get_tick();
                    if (current > base) {
                        if ((current - base) >= timeout) {
                            loopBreak = TXZ_DONE;
                        }
                    } else {
                        base = current;
                    }
                }
            }
        }
    }

    return (result);
}

/*--------------------------------------------------*/
/**
  * @fn     TXZ_Result adc_get_status(adc_t *p_obj, uint32_t *p_status)
  * @brief  Get Conversion Status.
  * @details  Status bits.
  * | Bit   | Bit Symbol | Function                                                           |
  * | :---  | :---       | :---                                                               |
  * | 31-8  | -          | -                                                                  |
  * | 7     | ADBF       | AD Running Flag. Use @ref adc_status_t.                            |
  * | 6-4   | -          | -                                                                  |
  * | 3     | CNTF       | Continuity Conversion Running Flag. Use @ref adc_cnt_status_t.     |
  * | 2     | SNGF       | Single Conversion Running Flag. Use @ref adc_sgl_status_t.         |
  * | 1     | TRGF       | Trigger Conversion Running Flag. Use @ref adc_trg_status_t.        |
  * | 0     | -          | -                                                                  |
  *
  * @param[in] p_obj      :ADC object.
  * @param[out] p_status  :Conversion Status. Destination address.
  * @retval TXZ_SUCCESS :Success.
  * @retval TXZ_ERROR   :Failure.
  * @note   -
  */
/*--------------------------------------------------*/
TXZ_Result adc_get_status(adc_t *p_obj, uint32_t *p_status)
{
    TXZ_Result result = TXZ_SUCCESS;

    /*------------------------------*/
    /*  Parameter Check             */
    /*------------------------------*/
    if (((void *)(p_obj) == (void *)0) ||
            ((void *)(p_obj->p_instance) == (void *)0) ||
            ((void *)(p_status) == (void *)0)) {
        result = TXZ_ERROR;
    } else {
        /*------------------------------*/
        /*  Read Register               */
        /*------------------------------*/
        *p_status = p_obj->p_instance->ST;
    }

    return (result);
}
/**
 *  @}
 */ /* End of group ADC_Exported_functions */

/**
 *  @}
 */ /* End of group ADC */

/**
 *  @}
 */ /* End of group Periph_Driver */

#endif /* defined(__ADC_H)  */

#ifdef __cplusplus
}
#endif /* __cplusplus */