/**
 ******************************************************************************
 * @file    bl702_adc.c
 * @version V1.0
 * @date
 * @brief   This file is the standard driver c file
 ******************************************************************************
 * @attention
 *
 * <h2><center>&copy; COPYRIGHT(c) 2020 Bouffalo Lab</center></h2>
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *   1. Redistributions of source code must retain the above copyright notice,
 *      this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright notice,
 *      this list of conditions and the following disclaimer in the documentation
 *      and/or other materials provided with the distribution.
 *   3. Neither the name of Bouffalo Lab nor the names of its contributors
 *      may be used to endorse or promote products derived from this software
 *      without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 ******************************************************************************
 */

#include "bl702_adc.h"
#include "bl702_ef_ctrl.h"

/** @addtogroup  BL702_Peripheral_Driver
 *  @{
 */

/** @addtogroup  ADC
 *  @{
 */

/** @defgroup  ADC_Private_Macros
 *  @{
 */
#undef MSG
#define MSG(...)
#define AON_CLK_SET_DUMMY_WAIT \
  {                            \
    __NOP();                   \
    __NOP();                   \
    __NOP();                   \
    __NOP();                   \
    __NOP();                   \
    __NOP();                   \
    __NOP();                   \
    __NOP();                   \
  }
#define ADC_RESTART_DUMMY_WAIT BL702_Delay_US(100)

/*@} end of group ADC_Private_Macros */

/** @defgroup  ADC_Private_Types
 *  @{
 */

/*@} end of group ADC_Private_Types */

/** @defgroup  ADC_Private_Variables
 *  @{
 */
static intCallback_Type   *adcIntCbfArra[ADC_INT_ALL] = {NULL};
static ADC_Gain_Coeff_Type adcGainCoeffCal            = {
               .adcGainCoeffEnable = DISABLE,
               .adcgainCoeffVal    = 0,
               .coe                = 1,
};

/*@} end of group ADC_Private_Variables */

/** @defgroup  ADC_Global_Variables
 *  @{
 */

/*@} end of group ADC_Global_Variables */

/** @defgroup  ADC_Private_Fun_Declaration
 *  @{
 */

/*@} end of group ADC_Private_Fun_Declaration */

/** @defgroup  ADC_Private_Functions
 *  @{
 */

/*@} end of group ADC_Private_Functions */

/** @defgroup  ADC_Public_Functions
 *  @{
 */

/****************************************************************************/
/**
 * @brief  Software reset the whole ADC
 *
 * @param  None
 *
 * @return None
 *
 *******************************************************************************/
void ADC_Reset(void) {
  uint32_t regCmd;

  /* reset ADC */
  regCmd = BL_RD_REG(AON_BASE, AON_GPADC_REG_CMD);
  BL_WR_REG(AON_BASE, AON_GPADC_REG_CMD, BL_SET_REG_BIT(regCmd, AON_GPADC_SOFT_RST));
  AON_CLK_SET_DUMMY_WAIT;
  BL_WR_REG(AON_BASE, AON_GPADC_REG_CMD, BL_CLR_REG_BIT(regCmd, AON_GPADC_SOFT_RST));
}

/****************************************************************************/
/**
 * @brief  ADC glable enable
 *
 * @param  None
 *
 * @return None
 *
 *******************************************************************************/
void ADC_Enable(void) {
  uint32_t tmpVal;

  tmpVal = BL_RD_REG(AON_BASE, AON_GPADC_REG_CMD);
  tmpVal = BL_SET_REG_BIT(tmpVal, AON_GPADC_GLOBAL_EN);
  BL_WR_REG(AON_BASE, AON_GPADC_REG_CMD, tmpVal);
}

/****************************************************************************/
/**
 * @brief  ADC glable disable
 *
 * @param  None
 *
 * @return None
 *
 *******************************************************************************/
void ADC_Disable(void) {
  uint32_t tmpVal;

  tmpVal = BL_RD_REG(AON_BASE, AON_GPADC_REG_CMD);
  tmpVal = BL_CLR_REG_BIT(tmpVal, AON_GPADC_GLOBAL_EN);
  BL_WR_REG(AON_BASE, AON_GPADC_REG_CMD, tmpVal);
}

/****************************************************************************/
/**
 * @brief  ADC normal mode init
 *
 * @param  cfg: ADC normal mode configuration
 *
 * @return None
 *
 *******************************************************************************/
void ADC_Init(ADC_CFG_Type *cfg) {
  uint32_t regCfg1;
  uint32_t regCfg2;
  uint32_t regCalib;

  CHECK_PARAM(IS_ADC_V18_SEL_TYPE(cfg->v18Sel));
  CHECK_PARAM(IS_ADC_V11_SEL_TYPE(cfg->v11Sel));
  CHECK_PARAM(IS_ADC_CLK_TYPE(cfg->clkDiv));
  CHECK_PARAM(IS_ADC_PGA_GAIN_TYPE(cfg->gain1));
  CHECK_PARAM(IS_ADC_PGA_GAIN_TYPE(cfg->gain2));
  CHECK_PARAM(IS_ADC_CHOP_MOD_TYPE(cfg->chopMode));
  CHECK_PARAM(IS_ADC_BIAS_SEL_TYPE(cfg->biasSel));
  CHECK_PARAM(IS_ADC_PGA_VCM_TYPE(cfg->vcm));
  CHECK_PARAM(IS_ADC_VREF_TYPE(cfg->vref));
  CHECK_PARAM(IS_ADC_SIG_INPUT_TYPE(cfg->inputMode));
  CHECK_PARAM(IS_ADC_DATA_WIDTH_TYPE(cfg->resWidth));

  /* config 1 */
  regCfg1 = 0; // BL_RD_REG(AON_BASE, AON_GPADC_REG_CONFIG1);
  regCfg1 = BL_SET_REG_BITS_VAL(regCfg1, AON_GPADC_V18_SEL, cfg->v18Sel);
  regCfg1 = BL_SET_REG_BITS_VAL(regCfg1, AON_GPADC_V11_SEL, cfg->v11Sel);
  regCfg1 = BL_CLR_REG_BIT(regCfg1, AON_GPADC_DITHER_EN);
  regCfg1 = BL_CLR_REG_BIT(regCfg1, AON_GPADC_SCAN_EN);
  regCfg1 = BL_SET_REG_BITS_VAL(regCfg1, AON_GPADC_SCAN_LENGTH, 0);
  regCfg1 = BL_SET_REG_BITS_VAL(regCfg1, AON_GPADC_CLK_DIV_RATIO, cfg->clkDiv);
  regCfg1 = BL_CLR_REG_BIT(regCfg1, AON_GPADC_CLK_ANA_INV);
  regCfg1 = BL_SET_REG_BITS_VAL(regCfg1, AON_GPADC_CAL_OS_EN, cfg->offsetCalibEn);
  regCfg1 = BL_SET_REG_BITS_VAL(regCfg1, AON_GPADC_RES_SEL, cfg->resWidth);
  BL_WR_REG(AON_BASE, AON_GPADC_REG_CONFIG1, regCfg1);
  AON_CLK_SET_DUMMY_WAIT;

  /* config 2 */
  regCfg2 = BL_RD_REG(AON_BASE, AON_GPADC_REG_CONFIG2);
  regCfg2 = BL_SET_REG_BITS_VAL(regCfg2, AON_GPADC_DLY_SEL, 0x00);
  regCfg2 = BL_SET_REG_BITS_VAL(regCfg2, AON_GPADC_PGA1_GAIN, cfg->gain1);
  regCfg2 = BL_SET_REG_BITS_VAL(regCfg2, AON_GPADC_PGA2_GAIN, cfg->gain2);
  regCfg2 = BL_SET_REG_BITS_VAL(regCfg2, AON_GPADC_BIAS_SEL, cfg->biasSel);
  regCfg2 = BL_SET_REG_BITS_VAL(regCfg2, AON_GPADC_CHOP_MODE, cfg->chopMode);
  regCfg2 = BL_CLR_REG_BIT(regCfg2, AON_GPADC_VBAT_EN);   // vbat enabled (off)
  regCfg2 = BL_CLR_REG_BIT(regCfg2, AON_GPADC_TSVBE_LOW); // tsen didoe current
  /* pga_vcmi_en is for mic */
  regCfg2 = BL_CLR_REG_BIT(regCfg2, AON_GPADC_PGA_VCMI_EN);

  if ((cfg->gain1 != ADC_PGA_GAIN_NONE) || (cfg->gain2 != ADC_PGA_GAIN_NONE)) {
    regCfg2 = BL_SET_REG_BIT(regCfg2, AON_GPADC_PGA_EN);
  } else {
    regCfg2 = BL_CLR_REG_BIT(regCfg2, AON_GPADC_PGA_EN);
  }

  /* pga_os_cal is for mic */
  regCfg2 = BL_SET_REG_BITS_VAL(regCfg2, AON_GPADC_PGA_OS_CAL, 8);
  regCfg2 = BL_SET_REG_BITS_VAL(regCfg2, AON_GPADC_PGA_VCM, cfg->vcm);
  regCfg2 = BL_SET_REG_BITS_VAL(regCfg2, AON_GPADC_VREF_SEL, cfg->vref);
  regCfg2 = BL_SET_REG_BITS_VAL(regCfg2, AON_GPADC_DIFF_MODE, cfg->inputMode);

  BL_WR_REG(AON_BASE, AON_GPADC_REG_CONFIG2, regCfg2);

  /* calibration offset */
  regCalib = BL_RD_REG(AON_BASE, AON_GPADC_REG_DEFINE);
  regCalib = BL_SET_REG_BITS_VAL(regCalib, AON_GPADC_OS_CAL_DATA, cfg->offsetCalibVal);
  BL_WR_REG(AON_BASE, AON_GPADC_REG_DEFINE, regCalib);

#ifndef BFLB_USE_HAL_DRIVER
  Interrupt_Handler_Register(GPADC_DMA_IRQn, GPADC_DMA_IRQHandler);
#endif

  // ADC_Gain_Trim();
}

/****************************************************************************/
/**
 * @brief  ADC normal mode channel config
 *
 * @param  posCh: ADC pos channel type
 * @param  negCh: ADC neg channel type
 * @param  contEn: ENABLE or DISABLE continuous mode
 *
 * @return None
 *
 *******************************************************************************/
void ADC_Channel_Config(ADC_Chan_Type posCh, ADC_Chan_Type negCh, BL_Fun_Type contEn) {
  uint32_t regCmd;
  uint32_t regCfg1;

  CHECK_PARAM(IS_AON_ADC_CHAN_TYPE(posCh));
  CHECK_PARAM(IS_AON_ADC_CHAN_TYPE(negCh));

  /* set channel */
  regCmd = BL_RD_REG(AON_BASE, AON_GPADC_REG_CMD);
  regCmd = BL_SET_REG_BITS_VAL(regCmd, AON_GPADC_POS_SEL, posCh);
  regCmd = BL_SET_REG_BITS_VAL(regCmd, AON_GPADC_NEG_SEL, negCh);
  BL_WR_REG(AON_BASE, AON_GPADC_REG_CMD, regCmd);

  /* set continuous mode */
  regCfg1 = BL_RD_REG(AON_BASE, AON_GPADC_REG_CONFIG1);
  regCfg1 = BL_SET_REG_BITS_VAL(regCfg1, AON_GPADC_CONT_CONV_EN, contEn);
  regCfg1 = BL_CLR_REG_BIT(regCfg1, AON_GPADC_SCAN_EN);
  BL_WR_REG(AON_BASE, AON_GPADC_REG_CONFIG1, regCfg1);
}

/****************************************************************************/
/**
 * @brief  ADC scan mode channel config
 *
 * @param  posChList[]: ADC pos channel list type
 * @param  negChList[]: ADC neg channel list type
 * @param  scanLength: ADC scan length
 * @param  contEn: ENABLE or DISABLE continuous mode
 *
 * @return None
 *
 *******************************************************************************/
void ADC_Scan_Channel_Config(const ADC_Chan_Type posChList[], const ADC_Chan_Type negChList[], uint8_t scanLength, BL_Fun_Type contEn) {
  uint32_t tmpVal, i;
  uint32_t dealLen;

  CHECK_PARAM((scanLength < 13));

  /* Deal with the first 6 */
  dealLen = 6;

  if (scanLength < dealLen) {
    dealLen = scanLength;
  }

  /* Set first 6 scan channels */
  tmpVal = BL_RD_REG(AON_BASE, AON_GPADC_REG_SCN_POS1);

  for (i = 0; i < dealLen; i++) {
    tmpVal = tmpVal & (~(0x1F << (i * 5)));
    tmpVal |= (posChList[i] << (i * 5));
  }

  BL_WR_REG(AON_BASE, AON_GPADC_REG_SCN_POS1, tmpVal);

  tmpVal = BL_RD_REG(AON_BASE, AON_GPADC_REG_SCN_NEG1);

  for (i = 0; i < dealLen; i++) {
    tmpVal = tmpVal & (~(0x1F << (i * 5)));
    tmpVal |= (negChList[i] << (i * 5));
  }

  BL_WR_REG(AON_BASE, AON_GPADC_REG_SCN_NEG1, tmpVal);

  /* Set the left channels */
  if (scanLength > dealLen) {
    tmpVal = BL_RD_REG(AON_BASE, AON_GPADC_REG_SCN_POS2);

    for (i = 0; i < scanLength - dealLen; i++) {
      tmpVal = tmpVal & (~(0x1F << (i * 5)));
      tmpVal |= (posChList[i + dealLen] << (i * 5));
    }

    BL_WR_REG(AON_BASE, AON_GPADC_REG_SCN_POS2, tmpVal);

    tmpVal = BL_RD_REG(AON_BASE, AON_GPADC_REG_SCN_NEG2);

    for (i = 0; i < scanLength - dealLen; i++) {
      tmpVal = tmpVal & (~(0x1F << (i * 5)));
      tmpVal |= (negChList[i + dealLen] << (i * 5));
    }

    BL_WR_REG(AON_BASE, AON_GPADC_REG_SCN_NEG2, tmpVal);
  }

  /* Scan mode */
  tmpVal = BL_RD_REG(AON_BASE, AON_GPADC_REG_CONFIG1);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, AON_GPADC_SCAN_LENGTH, scanLength - 1);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, AON_GPADC_CONT_CONV_EN, contEn);
  tmpVal = BL_SET_REG_BIT(tmpVal, AON_GPADC_CLK_ANA_INV);
  tmpVal = BL_SET_REG_BIT(tmpVal, AON_GPADC_SCAN_EN);
  BL_WR_REG(AON_BASE, AON_GPADC_REG_CONFIG1, tmpVal);
}

/****************************************************************************/
/**
 * @brief  ADC normal mode convert start
 *
 * @param  None
 *
 * @return None
 *
 *******************************************************************************/
void ADC_Start(void) {
  uint32_t regCmd;

  /* disable convert start */
  regCmd = BL_RD_REG(AON_BASE, AON_GPADC_REG_CMD);
  regCmd = BL_CLR_REG_BIT(regCmd, AON_GPADC_CONV_START);
  BL_WR_REG(AON_BASE, AON_GPADC_REG_CMD, regCmd);

  ADC_RESTART_DUMMY_WAIT;

  /* enable convert start */
  regCmd = BL_RD_REG(AON_BASE, AON_GPADC_REG_CMD);
  regCmd = BL_SET_REG_BIT(regCmd, AON_GPADC_CONV_START);
  BL_WR_REG(AON_BASE, AON_GPADC_REG_CMD, regCmd);
}

/****************************************************************************/
/**
 * @brief  ADC normal mode convert stop
 *
 * @param  None
 *
 * @return None
 *
 *******************************************************************************/
void ADC_Stop(void) {
  uint32_t regCmd;

  /* disable convert start */
  regCmd = BL_RD_REG(AON_BASE, AON_GPADC_REG_CMD);
  regCmd = BL_CLR_REG_BIT(regCmd, AON_GPADC_CONV_START);
  BL_WR_REG(AON_BASE, AON_GPADC_REG_CMD, regCmd);
}

/****************************************************************************/
/**
 * @brief  ADC FIFO configuration
 *
 * @param  fifoCfg: ADC FIFO confifuration pointer
 *
 * @return None
 *
 *******************************************************************************/
void ADC_FIFO_Cfg(ADC_FIFO_Cfg_Type *fifoCfg) {
  uint32_t tmpVal;

  /* Check the parameters */
  CHECK_PARAM(IS_GPIP_ADC_FIFO_THRESHOLD_TYPE(fifoCfg->fifoThreshold));

  /*
   *  DMA enable : ,When the fifo data is exceeded to fifoThreshold DMA request will occur
   *  DMA disable : fifoThreshold determine how many data will raise FIFO ready interrupt
   */

  tmpVal = BL_RD_REG(GPIP_BASE, GPIP_GPADC_CONFIG);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, GPIP_GPADC_FIFO_THL, fifoCfg->fifoThreshold);

  /* Enable DMA */
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, GPIP_GPADC_DMA_EN, fifoCfg->dmaEn);

  BL_WR_REG(GPIP_BASE, GPIP_GPADC_CONFIG, tmpVal);

  /* clear fifo by SET GPIP_GPADC_FIFO_CLR bit*/
  tmpVal = BL_RD_REG(GPIP_BASE, GPIP_GPADC_CONFIG);
  tmpVal = BL_SET_REG_BIT(tmpVal, GPIP_GPADC_FIFO_CLR);
  BL_WR_REG(GPIP_BASE, GPIP_GPADC_CONFIG, tmpVal);
}

/****************************************************************************/
/**
 * @brief  ADC get DMA FIFO data count
 *
 * @param  None
 *
 * @return data count in FIFO
 *
 *******************************************************************************/
uint8_t ADC_Get_FIFO_Count(void) {
  uint32_t tmpVal;

  tmpVal = BL_RD_REG(GPIP_BASE, GPIP_GPADC_CONFIG);

  return BL_GET_REG_BITS_VAL(tmpVal, GPIP_GPADC_FIFO_DATA_COUNT);
}

/****************************************************************************/
/**
 * @brief  ADC get DMA FIFO full status
 *
 * @param  None
 *
 * @return SET or RESET
 *
 *******************************************************************************/
BL_Sts_Type ADC_FIFO_Is_Full(void) {
  uint32_t tmpVal;

  tmpVal = BL_RD_REG(GPIP_BASE, GPIP_GPADC_CONFIG);

  if (BL_IS_REG_BIT_SET(tmpVal, GPIP_GPADC_FIFO_FULL)) {
    return SET;
  } else {
    return RESET;
  }
}

/****************************************************************************/
/**
 * @brief  ADC get DMA FIFO empty status
 *
 * @param  None
 *
 * @return SET or RESET
 *
 *******************************************************************************/
BL_Sts_Type ADC_FIFO_Is_Empty(void) {
  uint32_t tmpVal;

  tmpVal = BL_RD_REG(GPIP_BASE, GPIP_GPADC_CONFIG);

  if (BL_IS_REG_BIT_SET(tmpVal, GPIP_GPADC_FIFO_NE)) {
    return RESET;
  } else {
    return SET;
  }
}

/****************************************************************************/
/**
 * @brief  ADC read DMA FIFO data
 *
 * @param  None
 *
 * @return ADC result if return 0 that means this is error data,user should ignore this data.
 *
 *******************************************************************************/
uint32_t ADC_Read_FIFO(void) {
  uint32_t tmpVal;

  tmpVal = BL_RD_REG(GPIP_BASE, GPIP_GPADC_DMA_RDATA);

  return (tmpVal);
}

/****************************************************************************/
/**
 * @brief  ADC parse result
 *
 * @param  orgVal: Original A to D value
 * @param  len: Original AD vaule count
 * @param  result: Final Result array pointer
 *
 * @return None
 *
 *******************************************************************************/
void ADC_Parse_Result(uint32_t *orgVal, uint32_t len, ADC_Result_Type *result) {
  uint8_t             neg     = 0;
  uint32_t            tmpVal1 = 0, tmpVal2 = 0;
  ADC_Data_Width_Type dataType;
  ADC_SIG_INPUT_Type  sigType;
  float               ref = 2.0;
  uint32_t            i   = 0;

  float coe = 1.0;

  if (adcGainCoeffCal.adcGainCoeffEnable) {
    coe = adcGainCoeffCal.coe;
  }

  tmpVal1  = BL_RD_REG(AON_BASE, AON_GPADC_REG_CONFIG1);
  tmpVal2  = BL_RD_REG(AON_BASE, AON_GPADC_REG_CONFIG2);
  dataType = BL_GET_REG_BITS_VAL(tmpVal1, AON_GPADC_RES_SEL);
  sigType  = BL_GET_REG_BITS_VAL(tmpVal2, AON_GPADC_DIFF_MODE);

  if (BL_GET_REG_BITS_VAL(tmpVal2, AON_GPADC_VREF_SEL) == ADC_VREF_3P2V) {
    ref = 3.2;
  }

  if (sigType == ADC_INPUT_SINGLE_END) {
    for (i = 0; i < len; i++) {
      result[i].posChan = orgVal[i] >> 21;
      result[i].negChan = -1;

      if (dataType == ADC_DATA_WIDTH_12) {
        result[i].value = (unsigned int)(((orgVal[i] & 0xffff) >> 4) / coe);
        result[i].volt  = result[i].value / 4096.0 * ref;
      } else if ((dataType == ADC_DATA_WIDTH_14_WITH_16_AVERAGE) || (dataType == ADC_DATA_WIDTH_14_WITH_64_AVERAGE)) {
        result[i].value = (unsigned int)(((orgVal[i] & 0xffff) >> 2) / coe);
        result[i].volt  = result[i].value / 16384.0 * ref;
      } else if ((dataType == ADC_DATA_WIDTH_16_WITH_128_AVERAGE) || (dataType == ADC_DATA_WIDTH_16_WITH_256_AVERAGE)) {
        result[i].value = (unsigned int)((orgVal[i] & 0xffff) / coe);
        result[i].volt  = result[i].value / 65536.0 * ref;
      }
    }
  } else {
    for (i = 0; i < len; i++) {
      neg               = 0;
      result[i].posChan = orgVal[i] >> 21;
      result[i].negChan = (orgVal[i] >> 16) & 0x1F;

      if (orgVal[i] & 0x8000) {
        orgVal[i] = ~orgVal[i];
        orgVal[i] += 1;
        neg = 1;
      }

      if (dataType == ADC_DATA_WIDTH_12) {
        result[i].value = (unsigned int)(((orgVal[i] & 0xffff) >> 4) / coe);
        result[i].volt  = result[i].value / 2048.0 * ref;
      } else if ((dataType == ADC_DATA_WIDTH_14_WITH_16_AVERAGE) || (dataType == ADC_DATA_WIDTH_14_WITH_64_AVERAGE)) {
        result[i].value = (unsigned int)(((orgVal[i] & 0xffff) >> 2) / coe);
        result[i].volt  = result[i].value / 8192.0 * ref;
      } else if ((dataType == ADC_DATA_WIDTH_16_WITH_128_AVERAGE) || (dataType == ADC_DATA_WIDTH_16_WITH_256_AVERAGE)) {
        result[i].value = (unsigned int)((orgVal[i] & 0xffff) / coe);
        result[i].volt  = result[i].value / 32768.0 * ref;
      }

      if (neg) {
        result[i].volt = -result[i].volt;
      }
    }
  }
}

/****************************************************************************/
/**
 * @brief  ADC mask or unmask certain or all interrupt
 *
 * @param  intType: interrupt type
 * @param  intMask: mask or unmask
 *
 * @return None
 *
 *******************************************************************************/
BL_Mask_Type ADC_IntGetMask(ADC_INT_Type intType) {
  uint32_t tmpVal;

  /* Check the parameters */
  CHECK_PARAM(IS_GPIP_ADC_INT_TYPE(intType));
  CHECK_PARAM(IS_BL_MASK_TYPE(intMask));

  switch (intType) {
  case ADC_INT_POS_SATURATION:
    tmpVal = BL_RD_REG(AON_BASE, AON_GPADC_REG_ISR);
    return BL_IS_REG_BIT_SET(tmpVal, AON_GPADC_POS_SATUR_MASK);
    break;

  case ADC_INT_NEG_SATURATION:
    tmpVal = BL_RD_REG(AON_BASE, AON_GPADC_REG_ISR);
    return BL_IS_REG_BIT_SET(tmpVal, AON_GPADC_NEG_SATUR_MASK);
    break;

  case ADC_INT_FIFO_UNDERRUN:
    tmpVal = BL_RD_REG(AON_BASE, GPIP_GPADC_CONFIG);
    return BL_IS_REG_BIT_SET(tmpVal, GPIP_GPADC_FIFO_UNDERRUN_MASK);
    break;

  case ADC_INT_FIFO_OVERRUN:
    tmpVal = BL_RD_REG(AON_BASE, GPIP_GPADC_CONFIG);
    return BL_IS_REG_BIT_SET(tmpVal, GPIP_GPADC_FIFO_OVERRUN_MASK);
    break;

  case ADC_INT_ADC_READY:
    tmpVal = BL_RD_REG(AON_BASE, GPIP_GPADC_CONFIG);
    return BL_IS_REG_BIT_SET(tmpVal, GPIP_GPADC_RDY_MASK);
    break;

  case ADC_INT_FIFO_READY:
    tmpVal = BL_RD_REG(AON_BASE, GPIP_GPADC_CONFIG);
    return BL_IS_REG_BIT_SET(tmpVal, GPIP_GPADC_FIFO_RDY_MASK);
    break;
  default:
    break;
  }
  return 0;
}

/****************************************************************************/
/**
 * @brief  ADC mask or unmask certain or all interrupt
 *
 * @param  intType: interrupt type
 * @param  intMask: mask or unmask
 *
 * @return None
 *
 *******************************************************************************/
void ADC_IntMask(ADC_INT_Type intType, BL_Mask_Type intMask) {
  uint32_t tmpVal;

  /* Check the parameters */
  CHECK_PARAM(IS_GPIP_ADC_INT_TYPE(intType));
  CHECK_PARAM(IS_BL_MASK_TYPE(intMask));

  switch (intType) {
  case ADC_INT_POS_SATURATION:
    tmpVal = BL_RD_REG(AON_BASE, AON_GPADC_REG_ISR);

    if (intMask == UNMASK) {
      /* Enable this interrupt */
      tmpVal = BL_CLR_REG_BIT(tmpVal, AON_GPADC_POS_SATUR_MASK);
    } else {
      /* Disable this interrupt */
      tmpVal = BL_SET_REG_BIT(tmpVal, AON_GPADC_POS_SATUR_MASK);
    }

    BL_WR_REG(AON_BASE, AON_GPADC_REG_ISR, tmpVal);
    break;

  case ADC_INT_NEG_SATURATION:
    tmpVal = BL_RD_REG(AON_BASE, AON_GPADC_REG_ISR);

    if (intMask == UNMASK) {
      /* Enable this interrupt */
      tmpVal = BL_CLR_REG_BIT(tmpVal, AON_GPADC_NEG_SATUR_MASK);
    } else {
      /* Disable this interrupt */
      tmpVal = BL_SET_REG_BIT(tmpVal, AON_GPADC_NEG_SATUR_MASK);
    }

    BL_WR_REG(AON_BASE, AON_GPADC_REG_ISR, tmpVal);
    break;

  case ADC_INT_FIFO_UNDERRUN:
    tmpVal = BL_RD_REG(GPIP_BASE, GPIP_GPADC_CONFIG);

    if (intMask == UNMASK) {
      /* Enable this interrupt */
      tmpVal = BL_CLR_REG_BIT(tmpVal, GPIP_GPADC_FIFO_UNDERRUN_MASK);
    } else {
      /* Disable this interrupt */
      tmpVal = BL_SET_REG_BIT(tmpVal, GPIP_GPADC_FIFO_UNDERRUN_MASK);
    }

    BL_WR_REG(GPIP_BASE, GPIP_GPADC_CONFIG, tmpVal);
    break;

  case ADC_INT_FIFO_OVERRUN:
    tmpVal = BL_RD_REG(GPIP_BASE, GPIP_GPADC_CONFIG);

    if (intMask == UNMASK) {
      /* Enable this interrupt */
      tmpVal = BL_CLR_REG_BIT(tmpVal, GPIP_GPADC_FIFO_OVERRUN_MASK);
    } else {
      /* Disable this interrupt */
      tmpVal = BL_SET_REG_BIT(tmpVal, GPIP_GPADC_FIFO_OVERRUN_MASK);
    }

    BL_WR_REG(GPIP_BASE, GPIP_GPADC_CONFIG, tmpVal);
    break;

  case ADC_INT_ADC_READY:
    tmpVal = BL_RD_REG(GPIP_BASE, GPIP_GPADC_CONFIG);

    if (intMask == UNMASK) {
      /* Enable this interrupt */
      tmpVal = BL_CLR_REG_BIT(tmpVal, GPIP_GPADC_RDY_MASK);
    } else {
      /* Disable this interrupt */
      tmpVal = BL_SET_REG_BIT(tmpVal, GPIP_GPADC_RDY_MASK);
    }

    BL_WR_REG(GPIP_BASE, GPIP_GPADC_CONFIG, tmpVal);
    break;

  case ADC_INT_FIFO_READY:
    tmpVal = BL_RD_REG(GPIP_BASE, GPIP_GPADC_CONFIG);

    if (intMask == UNMASK) {
      /* Enable this interrupt */
      tmpVal = BL_CLR_REG_BIT(tmpVal, GPIP_GPADC_FIFO_RDY_MASK);
    } else {
      /* Disable this interrupt */
      tmpVal = BL_SET_REG_BIT(tmpVal, GPIP_GPADC_FIFO_RDY_MASK);
    }

    BL_WR_REG(GPIP_BASE, GPIP_GPADC_CONFIG, tmpVal);
    break;

  case ADC_INT_ALL:
    if (intMask == UNMASK) {
      /* Enable this interrupt */
      tmpVal = BL_RD_REG(GPIP_BASE, AON_GPADC_REG_ISR);
      tmpVal = BL_CLR_REG_BIT(tmpVal, AON_GPADC_POS_SATUR_MASK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, AON_GPADC_NEG_SATUR_MASK);
      BL_WR_REG(AON_BASE, AON_GPADC_REG_ISR, tmpVal);

      tmpVal = BL_RD_REG(GPIP_BASE, GPIP_GPADC_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, GPIP_GPADC_FIFO_UNDERRUN_MASK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, GPIP_GPADC_FIFO_OVERRUN_MASK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, GPIP_GPADC_RDY_MASK);
      BL_WR_REG(GPIP_BASE, GPIP_GPADC_CONFIG, tmpVal);
    } else {
      /* Disable this interrupt */
      tmpVal = BL_RD_REG(GPIP_BASE, AON_GPADC_REG_ISR);
      tmpVal = BL_SET_REG_BIT(tmpVal, AON_GPADC_POS_SATUR_MASK);
      tmpVal = BL_SET_REG_BIT(tmpVal, AON_GPADC_NEG_SATUR_MASK);
      BL_WR_REG(AON_BASE, AON_GPADC_REG_ISR, tmpVal);

      tmpVal = BL_RD_REG(GPIP_BASE, GPIP_GPADC_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, GPIP_GPADC_FIFO_OVERRUN_MASK);
      tmpVal = BL_SET_REG_BIT(tmpVal, GPIP_GPADC_FIFO_UNDERRUN_MASK);
      tmpVal = BL_SET_REG_BIT(tmpVal, GPIP_GPADC_RDY_MASK);
      BL_WR_REG(GPIP_BASE, GPIP_GPADC_CONFIG, tmpVal);
    }

    break;

  default:
    break;
  }
}

/****************************************************************************/
/**
 * @brief  ADC clear certain or all interrupt
 *
 * @param  intType: interrupt type
 *
 * @return None
 *
 *******************************************************************************/
void ADC_IntClr(ADC_INT_Type intType) {
  uint32_t tmpVal;

  /* Check the parameters */
  CHECK_PARAM(IS_GPIP_ADC_INT_TYPE(intType));

  switch (intType) {
  case ADC_INT_POS_SATURATION:
    tmpVal = BL_RD_REG(AON_BASE, AON_GPADC_REG_ISR);
    tmpVal = BL_CLR_REG_BIT(tmpVal, AON_GPADC_POS_SATUR_CLR);
    BL_WR_REG(AON_BASE, AON_GPADC_REG_ISR, tmpVal);

    tmpVal = BL_SET_REG_BIT(tmpVal, AON_GPADC_POS_SATUR_CLR);
    BL_WR_REG(AON_BASE, AON_GPADC_REG_ISR, tmpVal);

    /*Manual reset*/
    tmpVal = BL_RD_REG(AON_BASE, AON_GPADC_REG_ISR);
    tmpVal = BL_CLR_REG_BIT(tmpVal, AON_GPADC_POS_SATUR_CLR);
    BL_WR_REG(AON_BASE, AON_GPADC_REG_ISR, tmpVal);

    break;

  case ADC_INT_NEG_SATURATION:
    tmpVal = BL_RD_REG(AON_BASE, AON_GPADC_REG_ISR);
    tmpVal = BL_CLR_REG_BIT(tmpVal, AON_GPADC_NEG_SATUR_CLR);
    BL_WR_REG(AON_BASE, AON_GPADC_REG_ISR, tmpVal);

    tmpVal = BL_SET_REG_BIT(tmpVal, AON_GPADC_NEG_SATUR_CLR);
    BL_WR_REG(AON_BASE, AON_GPADC_REG_ISR, tmpVal);

    /*Manual reset*/
    tmpVal = BL_RD_REG(AON_BASE, AON_GPADC_REG_ISR);
    tmpVal = BL_CLR_REG_BIT(tmpVal, AON_GPADC_NEG_SATUR_CLR);
    BL_WR_REG(AON_BASE, AON_GPADC_REG_ISR, tmpVal);

    break;

  case ADC_INT_FIFO_UNDERRUN:
    tmpVal = BL_RD_REG(GPIP_BASE, GPIP_GPADC_CONFIG);
    tmpVal = BL_CLR_REG_BIT(tmpVal, GPIP_GPADC_FIFO_UNDERRUN_CLR);
    BL_WR_REG(GPIP_BASE, GPIP_GPADC_CONFIG, tmpVal);

    tmpVal = BL_SET_REG_BIT(tmpVal, GPIP_GPADC_FIFO_UNDERRUN_CLR);
    BL_WR_REG(GPIP_BASE, GPIP_GPADC_CONFIG, tmpVal);

    /*Manual reset*/
    tmpVal = BL_RD_REG(GPIP_BASE, GPIP_GPADC_CONFIG);
    tmpVal = BL_CLR_REG_BIT(tmpVal, GPIP_GPADC_FIFO_UNDERRUN_CLR);
    BL_WR_REG(GPIP_BASE, GPIP_GPADC_CONFIG, tmpVal);

    break;

  case ADC_INT_FIFO_OVERRUN:
    tmpVal = BL_RD_REG(GPIP_BASE, GPIP_GPADC_CONFIG);
    tmpVal = BL_CLR_REG_BIT(tmpVal, GPIP_GPADC_FIFO_OVERRUN_CLR);
    BL_WR_REG(GPIP_BASE, GPIP_GPADC_CONFIG, tmpVal);

    tmpVal = BL_SET_REG_BIT(tmpVal, GPIP_GPADC_FIFO_OVERRUN_CLR);
    BL_WR_REG(GPIP_BASE, GPIP_GPADC_CONFIG, tmpVal);

    /*Manual reset*/
    tmpVal = BL_RD_REG(GPIP_BASE, GPIP_GPADC_CONFIG);
    tmpVal = BL_CLR_REG_BIT(tmpVal, GPIP_GPADC_FIFO_OVERRUN_CLR);
    BL_WR_REG(GPIP_BASE, GPIP_GPADC_CONFIG, tmpVal);

    break;

  case ADC_INT_ADC_READY:
    tmpVal = BL_RD_REG(GPIP_BASE, GPIP_GPADC_CONFIG);
    tmpVal = BL_CLR_REG_BIT(tmpVal, GPIP_GPADC_RDY_CLR);
    BL_WR_REG(GPIP_BASE, GPIP_GPADC_CONFIG, tmpVal);

    tmpVal = BL_SET_REG_BIT(tmpVal, GPIP_GPADC_RDY_CLR);
    BL_WR_REG(GPIP_BASE, GPIP_GPADC_CONFIG, tmpVal);

    /*Manual reset*/
    tmpVal = BL_RD_REG(GPIP_BASE, GPIP_GPADC_CONFIG);
    tmpVal = BL_CLR_REG_BIT(tmpVal, GPIP_GPADC_RDY_CLR);
    BL_WR_REG(GPIP_BASE, GPIP_GPADC_CONFIG, tmpVal);

    break;

  case ADC_INT_FIFO_READY:
    tmpVal = BL_RD_REG(GPIP_BASE, GPIP_GPADC_CONFIG);
    tmpVal = BL_CLR_REG_BIT(tmpVal, GPIP_GPADC_FIFO_RDY);
    BL_WR_REG(GPIP_BASE, GPIP_GPADC_CONFIG, tmpVal);

    tmpVal = BL_SET_REG_BIT(tmpVal, GPIP_GPADC_FIFO_RDY);
    BL_WR_REG(GPIP_BASE, GPIP_GPADC_CONFIG, tmpVal);

    /*Manual reset*/
    tmpVal = BL_RD_REG(GPIP_BASE, GPIP_GPADC_CONFIG);
    tmpVal = BL_CLR_REG_BIT(tmpVal, GPIP_GPADC_FIFO_RDY);
    BL_WR_REG(GPIP_BASE, GPIP_GPADC_CONFIG, tmpVal);

    break;

  case ADC_INT_ALL:
    tmpVal = BL_RD_REG(AON_BASE, AON_GPADC_REG_ISR);
    tmpVal = BL_CLR_REG_BIT(tmpVal, AON_GPADC_POS_SATUR_CLR);
    tmpVal = BL_CLR_REG_BIT(tmpVal, AON_GPADC_NEG_SATUR_CLR);
    BL_WR_REG(AON_BASE, AON_GPADC_REG_ISR, tmpVal);

    tmpVal = BL_SET_REG_BIT(tmpVal, AON_GPADC_POS_SATUR_CLR);
    tmpVal = BL_SET_REG_BIT(tmpVal, AON_GPADC_NEG_SATUR_CLR);
    BL_WR_REG(AON_BASE, AON_GPADC_REG_ISR, tmpVal);

    /*Manual reset*/
    tmpVal = BL_RD_REG(AON_BASE, AON_GPADC_REG_ISR);
    tmpVal = BL_CLR_REG_BIT(tmpVal, AON_GPADC_POS_SATUR_CLR);
    tmpVal = BL_CLR_REG_BIT(tmpVal, AON_GPADC_NEG_SATUR_CLR);
    BL_WR_REG(AON_BASE, AON_GPADC_REG_ISR, tmpVal);

    tmpVal = BL_RD_REG(GPIP_BASE, GPIP_GPADC_CONFIG);
    tmpVal = BL_CLR_REG_BIT(tmpVal, GPIP_GPADC_FIFO_UNDERRUN_CLR);
    tmpVal = BL_CLR_REG_BIT(tmpVal, GPIP_GPADC_FIFO_OVERRUN_CLR);
    tmpVal = BL_CLR_REG_BIT(tmpVal, GPIP_GPADC_RDY_CLR);
    BL_WR_REG(GPIP_BASE, GPIP_GPADC_CONFIG, tmpVal);

    tmpVal = BL_SET_REG_BIT(tmpVal, GPIP_GPADC_FIFO_UNDERRUN_CLR);
    tmpVal = BL_SET_REG_BIT(tmpVal, GPIP_GPADC_FIFO_OVERRUN_CLR);
    tmpVal = BL_SET_REG_BIT(tmpVal, GPIP_GPADC_RDY_CLR);
    BL_WR_REG(GPIP_BASE, GPIP_GPADC_CONFIG, tmpVal);

    /*Manual reset*/
    tmpVal = BL_RD_REG(GPIP_BASE, GPIP_GPADC_CONFIG);
    tmpVal = BL_CLR_REG_BIT(tmpVal, GPIP_GPADC_FIFO_UNDERRUN_CLR);
    tmpVal = BL_CLR_REG_BIT(tmpVal, GPIP_GPADC_FIFO_OVERRUN_CLR);
    tmpVal = BL_CLR_REG_BIT(tmpVal, GPIP_GPADC_RDY_CLR);
    BL_WR_REG(GPIP_BASE, GPIP_GPADC_CONFIG, tmpVal);

    break;

  default:
    break;
  }
}

/****************************************************************************/
/**
 * @brief  ADC get interrupt status
 *
 * @param  intType: interrupt type
 *
 * @return SET or RESET
 *
 *******************************************************************************/
BL_Sts_Type ADC_GetIntStatus(ADC_INT_Type intType) {
  uint32_t    tmpVal;
  BL_Sts_Type bitStatus = RESET;

  /* Check the parameters */
  CHECK_PARAM(IS_GPIP_ADC_INT_TYPE(intType));

  switch (intType) {
  case ADC_INT_POS_SATURATION:
    tmpVal    = BL_RD_REG(AON_BASE, AON_GPADC_REG_ISR);
    bitStatus = (BL_IS_REG_BIT_SET(tmpVal, AON_GPADC_POS_SATUR)) ? SET : RESET;
    break;

  case ADC_INT_NEG_SATURATION:
    tmpVal    = BL_RD_REG(AON_BASE, AON_GPADC_REG_ISR);
    bitStatus = (BL_IS_REG_BIT_SET(tmpVal, AON_GPADC_NEG_SATUR)) ? SET : RESET;
    break;

  case ADC_INT_FIFO_UNDERRUN:
    tmpVal    = BL_RD_REG(GPIP_BASE, GPIP_GPADC_CONFIG);
    bitStatus = (BL_IS_REG_BIT_SET(tmpVal, GPIP_GPADC_FIFO_UNDERRUN)) ? SET : RESET;
    break;

  case ADC_INT_FIFO_OVERRUN:
    tmpVal    = BL_RD_REG(GPIP_BASE, GPIP_GPADC_CONFIG);
    bitStatus = (BL_IS_REG_BIT_SET(tmpVal, GPIP_GPADC_FIFO_OVERRUN)) ? SET : RESET;
    break;

  case ADC_INT_ADC_READY:
    tmpVal    = BL_RD_REG(GPIP_BASE, GPIP_GPADC_CONFIG);
    bitStatus = (BL_IS_REG_BIT_SET(tmpVal, GPIP_GPADC_RDY)) ? SET : RESET;
    break;

  case ADC_INT_FIFO_READY:
    tmpVal    = BL_RD_REG(GPIP_BASE, GPIP_GPADC_CONFIG);
    bitStatus = (BL_IS_REG_BIT_SET(tmpVal, GPIP_GPADC_FIFO_RDY)) ? SET : RESET;
    break;

  case ADC_INT_ALL:
    break;

  default:
    break;
  }

  return bitStatus;
}

/****************************************************************************/
/**
 * @brief  ADC install interrupt callback
 *
 * @param  intType: ADC interrupt type
 * @param  cbFun: ADC interrupt callback
 *
 * @return None
 *
 *******************************************************************************/
void ADC_Int_Callback_Install(ADC_INT_Type intType, intCallback_Type *cbFun) {
  /* Check the parameters */
  CHECK_PARAM(IS_GPIP_ADC_INT_TYPE(intType));

  adcIntCbfArra[intType] = cbFun;
}

/****************************************************************************/
/**
 * @brief  ADC DMA interrupt handler
 *
 * @param  None
 *
 * @return None
 *
 *******************************************************************************/
#ifndef BFLB_USE_HAL_DRIVER
void GPADC_DMA_IRQHandler(void) {
  if (ADC_GetIntStatus(ADC_INT_POS_SATURATION) == SET) {
    ADC_IntClr(ADC_INT_POS_SATURATION);

    if (adcIntCbfArra[ADC_INT_POS_SATURATION] != NULL) {
      adcIntCbfArra[ADC_INT_POS_SATURATION]();
    }
  }

  if (ADC_GetIntStatus(ADC_INT_NEG_SATURATION) == SET) {
    ADC_IntClr(ADC_INT_NEG_SATURATION);

    if (adcIntCbfArra[ADC_INT_NEG_SATURATION] != NULL) {
      adcIntCbfArra[ADC_INT_NEG_SATURATION]();
    }
  }

  if (ADC_GetIntStatus(ADC_INT_FIFO_UNDERRUN) == SET) {
    ADC_IntClr(ADC_INT_FIFO_UNDERRUN);

    if (adcIntCbfArra[ADC_INT_FIFO_UNDERRUN] != NULL) {
      adcIntCbfArra[ADC_INT_FIFO_UNDERRUN]();
    }
  }

  if (ADC_GetIntStatus(ADC_INT_FIFO_OVERRUN) == SET) {
    ADC_IntClr(ADC_INT_FIFO_OVERRUN);

    if (adcIntCbfArra[ADC_INT_FIFO_OVERRUN] != NULL) {
      adcIntCbfArra[ADC_INT_FIFO_OVERRUN]();
    }
  }

  if (ADC_GetIntStatus(ADC_INT_FIFO_READY) == SET) {
    ADC_IntClr(ADC_INT_FIFO_READY);

    if (adcIntCbfArra[ADC_INT_FIFO_READY] != NULL) {
      adcIntCbfArra[ADC_INT_FIFO_READY]();
    }
  }

  if (ADC_GetIntStatus(ADC_INT_FIFO_READY) == SET) {
    ADC_IntClr(ADC_INT_FIFO_READY);

    if (adcIntCbfArra[ADC_INT_FIFO_READY] != NULL) {
      adcIntCbfArra[ADC_INT_FIFO_READY]();
    }
  }
}
#endif

/****************************************************************************/
/**
 * @brief  ADC VBAT enable
 *
 * @param  None
 *
 * @return None
 *
 *******************************************************************************/
void ADC_Vbat_Enable(void) {
  uint32_t tmpVal;

  tmpVal = BL_RD_REG(AON_BASE, AON_GPADC_REG_CONFIG2);
  tmpVal = BL_SET_REG_BIT(tmpVal, AON_GPADC_VBAT_EN);
  BL_WR_REG(AON_BASE, AON_GPADC_REG_CONFIG2, tmpVal);
}

/****************************************************************************/
/**
 * @brief  ADC VBAT disable
 *
 * @param  None
 *
 * @return None
 *
 *******************************************************************************/
void ADC_Vbat_Disable(void) {
  uint32_t tmpVal;

  tmpVal = BL_RD_REG(AON_BASE, AON_GPADC_REG_CONFIG2);
  tmpVal = BL_CLR_REG_BIT(tmpVal, AON_GPADC_VBAT_EN);
  BL_WR_REG(AON_BASE, AON_GPADC_REG_CONFIG2, tmpVal);
}

/****************************************************************************/
/**
 * @brief  ADC TSEN Config
 *
 * @param  tsenMod: None
 *
 * @return None
 *
 *******************************************************************************/
void ADC_Tsen_Init(ADC_TSEN_MOD_Type tsenMod) {
  uint32_t tmpVal;

  CHECK_PARAM(IS_AON_ADC_TSEN_MOD_TYPE(type));

  /* config gpadc_reg_cmd */
  tmpVal = BL_RD_REG(AON_BASE, AON_GPADC_REG_CMD);
  /* enable sensor dc test mux*/
  tmpVal = BL_CLR_REG_BIT(tmpVal, AON_GPADC_SEN_TEST_EN);
  /*selected sen output current channel*/
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, AON_GPADC_SEN_SEL, 0);
  /* enable chip sensor*/
  tmpVal = BL_CLR_REG_BIT(tmpVal, AON_GPADC_CHIP_SEN_PU);
  /*dwa_en */
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, AON_GPADC_DWA_EN, 1);
  BL_WR_REG(AON_BASE, AON_GPADC_REG_CMD, tmpVal);

  /* config 2 */
  tmpVal = BL_RD_REG(AON_BASE, AON_GPADC_REG_CONFIG2);
  /*tsvbe low=0*/
  tmpVal = BL_CLR_REG_BIT(tmpVal, AON_GPADC_TSVBE_LOW);
  /*dly_sel=2*/
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, AON_GPADC_DLY_SEL, 2);
  /*test_sel=0*/
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, AON_GPADC_TEST_SEL, 0);
  /*test_en=0*/
  tmpVal = BL_CLR_REG_BIT(tmpVal, AON_GPADC_TEST_EN);
  /*ts_en*/
  tmpVal = BL_SET_REG_BIT(tmpVal, AON_GPADC_TS_EN);
  /*select tsen ext or inner*/
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, AON_GPADC_TSEXT_SEL, tsenMod);

  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, AON_GPADC_PGA_VCM, 2);
  /*pga vcmi enable*/
  tmpVal = BL_CLR_REG_BIT(tmpVal, AON_GPADC_PGA_VCMI_EN);
  /*0:512uS;1:16mS;2:32mS;3:64mS*/
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, AON_GPADC_PGA_OS_CAL, 0);

  BL_WR_REG(AON_BASE, AON_GPADC_REG_CONFIG2, tmpVal);

  /* config 3 */
  tmpVal = BL_RD_REG(AON_BASE, AON_GPADC_REG_CONFIG1);
  /* set gpadc_dither_en */
  tmpVal = BL_SET_REG_BIT(tmpVal, AON_GPADC_DITHER_EN);
  BL_WR_REG(AON_BASE, AON_GPADC_REG_CONFIG1, tmpVal);

  /* set 4000F90C[19](gpadc_mic2_diff) = 1
   * debug advise form Ran
   * 2020.08.26
   */
  tmpVal = BL_RD_REG(AON_BASE, AON_GPADC_REG_CMD);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, AON_GPADC_MIC2_DIFF, 1);
  BL_WR_REG(AON_BASE, AON_GPADC_REG_CMD, tmpVal);
}

/****************************************************************************/
/**
 * @brief  ADC TSEN Enable
 *
 * @return None
 *
 *******************************************************************************/
void ADC_Tsen_Enable(void) {
  uint32_t tmpVal;

  tmpVal = BL_RD_REG(AON_BASE, AON_GPADC_REG_CONFIG2);
  tmpVal = BL_SET_REG_BIT(tmpVal, AON_GPADC_TS_EN);
  BL_WR_REG(AON_BASE, AON_GPADC_REG_CONFIG2, tmpVal);
}

/****************************************************************************/
/**
 * @brief  ADC TSEN Disable
 *
 * @return None
 *
 *******************************************************************************/
void ADC_Tsen_Disable(void) {
  uint32_t tmpVal;

  tmpVal = BL_RD_REG(AON_BASE, AON_GPADC_REG_CONFIG2);
  tmpVal = BL_CLR_REG_BIT(tmpVal, AON_GPADC_TS_EN);
  BL_WR_REG(AON_BASE, AON_GPADC_REG_CONFIG2, tmpVal);
}

/****************************************************************************/
/**
 * @brief  ADC Clear fifo
 *
 * @return None
 *
 *******************************************************************************/
void ADC_FIFO_Clear(void) {
  uint32_t tmpVal;

  /* clear fifo by SET GPIP_GPADC_FIFO_CLR bit*/
  tmpVal = BL_RD_REG(GPIP_BASE, GPIP_GPADC_CONFIG);
  tmpVal = BL_SET_REG_BIT(tmpVal, GPIP_GPADC_FIFO_CLR);
  BL_WR_REG(GPIP_BASE, GPIP_GPADC_CONFIG, tmpVal);
}

/****************************************************************************/
/**
 * @brief  config pga
 *
 * @param  pga_vcmi_enable: enable or not vcmi
 * @param  pga_os_cal: pga os cal value
 * @return None
 *
 *******************************************************************************/
void ADC_PGA_Config(uint8_t pga_vcmi_enable, uint8_t pga_os_cal) {
  uint32_t tmpVal;

  tmpVal = BL_RD_REG(AON_BASE, AON_GPADC_REG_CONFIG2);

  if (pga_vcmi_enable) {
    tmpVal = BL_SET_REG_BIT(tmpVal, AON_GPADC_PGA_VCMI_EN);
  } else {
    tmpVal = BL_CLR_REG_BIT(tmpVal, AON_GPADC_PGA_VCMI_EN);
  }

  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, AON_GPADC_PGA_OS_CAL, pga_os_cal);

  BL_WR_REG(AON_BASE, AON_GPADC_REG_CONFIG2, tmpVal);
}
/****************************************************************************/
/**
 * @brief  TSEN_Get_V_Error
 *
 * @param  None
 *
 * @return None
 *
 *******************************************************************************/
uint32_t TSEN_Get_V_Error(void) {
  uint32_t        v0 = 0, v1 = 0;
  uint32_t        v_error = 0;
  uint32_t        regVal  = 0;
  ADC_Result_Type result;
  uint32_t        tmpVal;
  uint8_t         gainCalEnabled = 0;

  /* clear fifo by SET GPIP_GPADC_FIFO_CLR bit*/
  tmpVal = BL_RD_REG(GPIP_BASE, GPIP_GPADC_CONFIG);
  tmpVal = BL_SET_REG_BIT(tmpVal, GPIP_GPADC_FIFO_CLR);
  BL_WR_REG(GPIP_BASE, GPIP_GPADC_CONFIG, tmpVal);

  ADC_SET_TSVBE_LOW();

  ADC_Start();

  while (ADC_Get_FIFO_Count() == 0)
    ;

  regVal                             = ADC_Read_FIFO();
  gainCalEnabled                     = adcGainCoeffCal.adcGainCoeffEnable;
  adcGainCoeffCal.adcGainCoeffEnable = 0;
  ADC_Parse_Result(&regVal, 1, &result);
  adcGainCoeffCal.adcGainCoeffEnable = gainCalEnabled;
  v0                                 = result.value;

  /* clear fifo by SET GPIP_GPADC_FIFO_CLR bit*/
  tmpVal = BL_RD_REG(GPIP_BASE, GPIP_GPADC_CONFIG);
  tmpVal = BL_SET_REG_BIT(tmpVal, GPIP_GPADC_FIFO_CLR);
  BL_WR_REG(GPIP_BASE, GPIP_GPADC_CONFIG, tmpVal);

  ADC_SET_TSVBE_HIGH();

  ADC_Start();

  while (ADC_Get_FIFO_Count() == 0)
    ;

  regVal                             = ADC_Read_FIFO();
  gainCalEnabled                     = adcGainCoeffCal.adcGainCoeffEnable;
  adcGainCoeffCal.adcGainCoeffEnable = 0;
  ADC_Parse_Result(&regVal, 1, &result);
  adcGainCoeffCal.adcGainCoeffEnable = gainCalEnabled;
  v1                                 = result.value;

  v_error = v0 - v1;

  return v_error;
}

/****************************************************************************/
/**
 * @brief  Trim TSEN
 *
 * @param  tsen_offset: None
 *
 * @return SUCCESS or ERROR
 *
 *******************************************************************************/
BL_Err_Type ATTR_CLOCK_SECTION ADC_Trim_TSEN(uint16_t *tsen_offset) {
  Efuse_TSEN_Refcode_Corner_Type trim;

  EF_Ctrl_Read_TSEN_Trim(&trim);
  if (trim.tsenRefcodeCornerEn) {
    if (trim.tsenRefcodeCornerParity == EF_Ctrl_Get_Trim_Parity(trim.tsenRefcodeCorner, 12)) {
      *tsen_offset = trim.tsenRefcodeCorner;

      return SUCCESS;
    }
  }

  return ERROR;
}

/****************************************************************************/
/**
 * @brief  SET ADC TSEN TSVBE LOW/HIGH
 *
 * @param  None
 *
 * @return None
 *
 *******************************************************************************/
void ADC_SET_TSVBE_LOW(void) {
  uint32_t tmpVal;
  tmpVal = BL_RD_REG(AON_BASE, AON_GPADC_REG_CONFIG2);
  tmpVal = BL_CLR_REG_BIT(tmpVal, AON_GPADC_TSVBE_LOW);
  BL_WR_REG(AON_BASE, AON_GPADC_REG_CONFIG2, tmpVal);
}

/****************************************************************************/
/**
 * @brief  SET ADC TSEN TSVBE LOW/HIGH
 *
 * @param  None
 *
 * @return None
 *
 *******************************************************************************/
void ADC_SET_TSVBE_HIGH(void) {
  uint32_t tmpVal;
  tmpVal = BL_RD_REG(AON_BASE, AON_GPADC_REG_CONFIG2);
  tmpVal = BL_SET_REG_BIT(tmpVal, AON_GPADC_TSVBE_LOW);
  BL_WR_REG(AON_BASE, AON_GPADC_REG_CONFIG2, tmpVal);
}

/****************************************************************************/
/**
 * @brief  SET ADC TSEN TSVBE LOW/HIGH
 *
 * @param  tsen_offset: tsen_offset form efuse trim data
 *
 * @return tempture
 *
 *******************************************************************************/
float TSEN_Get_Temp(uint32_t tsen_offset) {
  uint32_t        v0 = 0, v1 = 0;
  float           temp   = 0;
  uint32_t        regVal = 0;
  ADC_Result_Type result;
  uint32_t        tmpVal;
  uint8_t         gainCalEnabled = 0;

  /* clear fifo by SET GPIP_GPADC_FIFO_CLR bit*/
  tmpVal = BL_RD_REG(GPIP_BASE, GPIP_GPADC_CONFIG);
  tmpVal = BL_SET_REG_BIT(tmpVal, GPIP_GPADC_FIFO_CLR);
  BL_WR_REG(GPIP_BASE, GPIP_GPADC_CONFIG, tmpVal);

  ADC_SET_TSVBE_LOW();

  ADC_Start();

  while (ADC_Get_FIFO_Count() == 0)
    ;

  regVal = ADC_Read_FIFO();

  gainCalEnabled                     = adcGainCoeffCal.adcGainCoeffEnable;
  adcGainCoeffCal.adcGainCoeffEnable = 0;
  ADC_Parse_Result(&regVal, 1, &result);
  adcGainCoeffCal.adcGainCoeffEnable = gainCalEnabled;
  v0                                 = result.value;

  /* clear fifo by SET GPIP_GPADC_FIFO_CLR bit*/
  tmpVal = BL_RD_REG(GPIP_BASE, GPIP_GPADC_CONFIG);
  tmpVal = BL_SET_REG_BIT(tmpVal, GPIP_GPADC_FIFO_CLR);
  BL_WR_REG(GPIP_BASE, GPIP_GPADC_CONFIG, tmpVal);

  ADC_SET_TSVBE_HIGH();

  ADC_Start();

  while (ADC_Get_FIFO_Count() == 0)
    ;

  regVal                             = ADC_Read_FIFO();
  gainCalEnabled                     = adcGainCoeffCal.adcGainCoeffEnable;
  adcGainCoeffCal.adcGainCoeffEnable = 0;
  ADC_Parse_Result(&regVal, 1, &result);
  adcGainCoeffCal.adcGainCoeffEnable = gainCalEnabled;
  v1                                 = result.value;

  if (v0 > v1) {
    temp = (((float)v0 - (float)v1) - (float)tsen_offset) / 7.753;
  } else {
    temp = (((float)v1 - (float)v0) - (float)tsen_offset) / 7.753;
  }

  return temp;
}

/****************************************************************************/
/**
 * @brief  ADC MIC Config
 *
 * @param  adc_mic_config: adc_mic_config
 *
 * @return success or not
 *
 *******************************************************************************/
BL_Err_Type ADC_Mic_Init(ADC_MIC_Type *adc_mic_config) {
  uint32_t tmpVal1 = 0, tmpVal2 = 0;

  CHECK_PARAM(IS_ADC_MICBOOST_DB_Type(adc_mic_config->micboostDb));
  CHECK_PARAM(IS_PGA2_GAIN_Type(adc_mic_config->micPga2Gain));
  CHECK_PARAM(IS_ADC_MIC_MODE_Type(adc_mic_config->mic1Mode));
  CHECK_PARAM(IS_ADC_MIC_MODE_Type(adc_mic_config->mic2Mode));
  CHECK_PARAM(IS_BL_Fun_Type(adc_mic_config->dwaEn));
  CHECK_PARAM(IS_BL_Fun_Type(adc_mic_config->micboostBypassEn));
  CHECK_PARAM(IS_BL_Fun_Type(adc_mic_config->micPgaEn));
  CHECK_PARAM(IS_BL_Fun_Type(adc_mic_config->micBiasEn));

  tmpVal2 = BL_RD_REG(AON_BASE, AON_GPADC_REG_CONFIG2);

  tmpVal1 = BL_RD_REG(AON_BASE, AON_GPADC_REG_CMD);
  tmpVal1 = BL_SET_REG_BITS_VAL(tmpVal1, AON_GPADC_MICBOOST_32DB_EN, adc_mic_config->micboostDb);
  tmpVal1 = BL_SET_REG_BITS_VAL(tmpVal1, AON_GPADC_MIC_PGA2_GAIN, adc_mic_config->micPga2Gain);
  tmpVal1 = BL_SET_REG_BITS_VAL(tmpVal1, AON_GPADC_MIC1_DIFF, adc_mic_config->mic1Mode);
  tmpVal1 = BL_SET_REG_BITS_VAL(tmpVal1, AON_GPADC_MIC2_DIFF, adc_mic_config->mic2Mode);
  tmpVal1 = BL_SET_REG_BITS_VAL(tmpVal1, AON_GPADC_DWA_EN, adc_mic_config->dwaEn);
  tmpVal1 = BL_SET_REG_BITS_VAL(tmpVal1, AON_GPADC_BYP_MICBOOST, adc_mic_config->micboostBypassEn);

  if (BL_IS_REG_BIT_SET(tmpVal2, AON_GPADC_PGA_EN) && adc_mic_config->micPgaEn == ENABLE) {
    /* 0x4000F914[13] and 0x4000F90c[15] Cannot be both Enable*/
    return ERROR;
  } else {
    tmpVal1 = BL_SET_REG_BITS_VAL(tmpVal1, AON_GPADC_MICPGA_EN, adc_mic_config->micPgaEn);
  }

  tmpVal1 = BL_SET_REG_BITS_VAL(tmpVal1, AON_GPADC_MICBIAS_EN, adc_mic_config->micBiasEn);

  BL_WR_REG(AON_BASE, AON_GPADC_REG_CMD, tmpVal1);

  return SUCCESS;
}

/****************************************************************************/
/**
 * @brief  ADC MIC bias control
 *
 * @param  None
 *
 * @return None
 *
 *******************************************************************************/
void ADC_MIC_Bias_Enable(void) {
  uint32_t tmpVal;

  tmpVal = BL_RD_REG(AON_BASE, AON_GPADC_REG_CMD);
  tmpVal = BL_SET_REG_BIT(tmpVal, AON_GPADC_MICBIAS_EN);
  BL_WR_REG(AON_BASE, AON_GPADC_REG_CMD, tmpVal);
}

/****************************************************************************/
/**
 * @brief  ADC MIC bias control
 *
 * @param  None
 *
 * @return None
 *
 *******************************************************************************/
void ADC_MIC_Bias_Disable(void) {
  uint32_t tmpVal;

  tmpVal = BL_RD_REG(AON_BASE, AON_GPADC_REG_CMD);
  tmpVal = BL_CLR_REG_BIT(tmpVal, AON_GPADC_MICBIAS_EN);
  BL_WR_REG(AON_BASE, AON_GPADC_REG_CMD, tmpVal);
}

/****************************************************************************/
/**
 * @brief  Trim ADC Gain
 *
 * @param  None
 *
 * @return SUCCESS or ERROR
 *
 *******************************************************************************/
BL_Err_Type ATTR_CLOCK_SECTION ADC_Gain_Trim(void) {
  Efuse_ADC_Gain_Coeff_Type trim;
  uint32_t                  tmp;

  EF_Ctrl_Read_ADC_Gain_Trim(&trim);

  if (trim.adcGainCoeffEn) {
    if (trim.adcGainCoeffParity == EF_Ctrl_Get_Trim_Parity(trim.adcGainCoeff, 12)) {
      adcGainCoeffCal.adcGainCoeffEnable = ENABLE;
      adcGainCoeffCal.adcgainCoeffVal    = trim.adcGainCoeff;
      tmp                                = adcGainCoeffCal.adcgainCoeffVal;

      if (tmp & 0x800) {
        tmp = ~tmp;
        tmp += 1;
        tmp = tmp & 0xfff;
        // printf("val==%08x\r\n",(unsigned int)tmp);
        adcGainCoeffCal.coe = (1.0 + ((float)tmp / 2048.0));
        // printf("coe==%0f\r\n",adcGainCoeffCal.coe);
      } else {
        adcGainCoeffCal.coe = (1.0 - ((float)tmp / 2048.0));
        // printf("coe==%0f\r\n",adcGainCoeffCal.coe);
      }

      return SUCCESS;
    }
  }

  return ERROR;
}

/*@} end of group ADC_Public_Functions */

/*@} end of group ADC */

/*@} end of group BL702_Peripheral_Driver */
