#include "platform.h"
#include "board.h"
#include "hal_dma.h"
#include "hal_def.h"
#include "hal_audio.h"
#include "hal_audio_adc.h"
#include "hal_pmu.h"
#include "hal_cmu.h"
#include "debug.h"



HAL_StatusTypeDef hal_audio_adc_ch_cfg(audio_adc_handle_typedef *hadc, audio_adc_ch_cfg_typedef ch)
{
    if (hadc == NULL)
    {
        return HAL_ERROR;
    }

    if (ch.hw_pin == AMIC_CH0)
    {
        hadc->ch_cfg[0].sample_rate = ch.sample_rate;
        hadc->ch_cfg[0].digit_volume = ch.digit_volume;
        hadc->ch_cfg[0].hw_pin = ch.hw_pin;
        hadc->ch_cfg[0].amic.mode = ch.amic.mode;
        hadc->ch_cfg[0].amic.mic_gain = ch.amic.mic_gain;
        hadc->ch_cfg[0].amic.mix_gain = ch.amic.mix_gain;
        hadc->ch_cfg[0].amic.vmic = ch.amic.vmic;
    }
    else if (ch.hw_pin == AMIC_CH1)
    {
        hadc->ch_cfg[1].sample_rate = ch.sample_rate;
        hadc->ch_cfg[1].digit_volume = ch.digit_volume;
        hadc->ch_cfg[1].hw_pin = ch.hw_pin;
        hadc->ch_cfg[1].amic.mode = ch.amic.mode;
        hadc->ch_cfg[1].amic.mic_gain = ch.amic.mic_gain;
        hadc->ch_cfg[1].amic.mix_gain = ch.amic.mix_gain;
        hadc->ch_cfg[1].amic.vmic = ch.amic.vmic;
    }
    else if ((ch.hw_pin == DMIC0_GPIO0_GPIO1) || (ch.hw_pin == DMIC0_GPIO18_GPIO19) || (ch.hw_pin == DMIC0_GPIO30_GPIO31))
    {
        hadc->ch_cfg[0].sample_rate = ch.sample_rate;
        hadc->ch_cfg[0].digit_volume = ch.digit_volume;
        hadc->ch_cfg[0].hw_pin = ch.hw_pin;
        hadc->ch_cfg[0].dmic.mode = ch.dmic.mode;
    }
    else if ((ch.hw_pin == DMIC1_GPIO4_GPIO5) || (ch.hw_pin == DIMC1_GPIO20_GPIO21))
    {
        hadc->ch_cfg[1].sample_rate = ch.sample_rate;
        hadc->ch_cfg[1].digit_volume = ch.digit_volume;
        hadc->ch_cfg[1].hw_pin = ch.hw_pin;
        hadc->ch_cfg[1].dmic.mode = ch.dmic.mode;
    }
    else if ((ch.hw_pin == DIMC2_GPIO14_GPIO15) || (ch.hw_pin == DMIC2_GPIO22_GPIO23))
    {
        hadc->ch_cfg[2].sample_rate = ch.sample_rate;
        hadc->ch_cfg[2].digit_volume = ch.digit_volume;
        hadc->ch_cfg[2].hw_pin = ch.hw_pin;
        hadc->ch_cfg[2].dmic.mode = ch.dmic.mode;
    }
    else if (ch.hw_pin == DIMC3_GPIO16_GPIO17)
    {
        hadc->ch_cfg[3].sample_rate = ch.sample_rate;
        hadc->ch_cfg[3].digit_volume = ch.digit_volume;
        hadc->ch_cfg[3].hw_pin = ch.hw_pin;
        hadc->ch_cfg[3].dmic.mode = ch.dmic.mode;
    }

    return HAL_OK;
}

HAL_StatusTypeDef  hal_audio_init(audio_adc_handle_typedef *hadc)
{
    uint32_t data_sel;
    int channel_clock;
    clk_div_typedef clk_div;
    hadc->state = FREE;

    if (hadc == NULL)
    {
        return HAL_ERROR;
    }
    else if ((hadc->state == IDLE) || (hadc->state == WORK))
    {
        return HAL_OK;
    }

    /*开启电源,开启时钟*/
    AON_PMU->PWR_CTL   |= (0x01 << 12);//AVCC ENABLE
    DEV_RMU->RSTEN0    |= DEV_RMU_RSTEN0_AON;
    DEV_CMU->CLKEN0    |= DEV_CMU_CLKEN0_AON;
    AON_OSC->XTAL_CTL  |= 0x01;
    DEV_RMU->RSTEN0    |= DEV_RMU_RSTEN0_ADC;
    DEV_CMU->CLKEN0    |= DEV_CMU_CLKEN0_ADC;
    data_sel = 0;

    /*ch0*/
    if (hadc->ch_cfg[0].hw_pin == AMIC_CH0) /*通道0用模拟麦*/
    {
        if (HAL_ERROR == get_amic_clk_div(hadc->ch_cfg[0].sample_rate, &clk_div)) /*配置滤波器的分频系数*/
        {
            hadc->state = ERR;
            return HAL_ERROR;/*异常返回*/
        }
#ifdef ADC_USE_AUDIO_PLL
        DEV_CMU->ADCCLK = (((clk_div.adc_osc_div + 1)*2-1) << 4) | DEV_CMU_ADCCLK_SEL_PLL_AUDIO | DEV_CMU_ADCCLK_EN_ENABLE; /*audio pll 49.152M as audio clock\r\n*/
#else
        DEV_CMU->ADCCLK = (clk_div.adc_osc_div << 4) | DEV_CMU_ADCCLK_SEL_OSC_XTAL | DEV_CMU_ADCCLK_EN_ENABLE;/*OSC_XTAL as audio clock\r\n*/
#endif
#if 1
        DEV_ADC->CHNn_CFG[0] = DEV_ADC_CHNn_CFG_MIX_SRC_SEL_ENABLE |
                               DEV_ADC_CHNn_CFG_CIC_CLK_DIV_256FS_2_128FS |
                               (hadc->ch_cfg[0].digit_volume << 12) |
                               (clk_div.fir_clk_div << 9) |
                               (clk_div.cic_sel << 2) |
                               DEV_ADC_CHNn_CFG_MODE_SEL_ADC |
                               DEV_ADC_CHNn_CFG_HPF_COEF_1_128 |
                               DEV_ADC_CHNn_CFG_HPF_EN_ENABLE |
                               DEV_ADC_CHNn_CFG_CHN_EN_ENABLE;
#endif
#if 0
        DEV_ADC->CHNn_CFG[0] = (1<<29) |
                               DEV_ADC_CHNn_CFG_CIC_CLK_DIV_256FS_2_128FS |
                               (hadc->ch_cfg[0].digit_volume << 12) |
                               (clk_div.fir_clk_div << 9) |
                               (clk_div.cic_sel << 2) |
                               DEV_ADC_CHNn_CFG_MODE_SEL_ADC |
                               DEV_ADC_CHNn_CFG_HPF_COEF_1_128 |
                               DEV_ADC_CHNn_CFG_HPF_EN_ENABLE |
                               DEV_ADC_CHNn_CFG_CHN_EN_ENABLE;
#endif
        vmic_init(VMIC0, hadc->ch_cfg[0].amic.vmic);
        DEV_ADC->MIC_CTRL0  |= ((hadc->ch_cfg[0].amic.mic_gain << 4) |   //MIC0_GAIN
                                (hadc->ch_cfg[0].amic.mode << 2) |       //MIC0_MODE
                                (0x01 << 0));                            //MIC0_ENABLE
        DEV_ADC->MIX_CTRL0  |= (hadc->ch_cfg[0].amic.mix_gain << 4) |    //MIX0 GAIN
                               (DEV_ADC_MIX_CTRL0_MIX0_MIC0_EN_ENABLE) | //MIX0 MIC0 ENABLE
                               (DEV_ADC_MIX_CTRL0_MIX0_EN_ENABLE);       //MIX0 ENABLE
        data_sel |= (1 << 0);
    }
    else if ((hadc->ch_cfg[0].hw_pin == DMIC0_GPIO0_GPIO1) || (hadc->ch_cfg[0].hw_pin == DMIC0_GPIO18_GPIO19) || (hadc->ch_cfg[0].hw_pin == DMIC0_GPIO30_GPIO31)) /*通道0用数字麦*/
    {
        if (HAL_ERROR == get_dmic_clk_div(hadc->ch_cfg[0].sample_rate, &clk_div)) /*配置滤波器的分频系数*/
        {
            hadc->state = ERR;
            return HAL_ERROR;/*异常返回*/
        }

        set_mic_pin_fun(hadc->ch_cfg[0].hw_pin);

#ifdef ADC_USE_AUDIO_PLL
        DEV_CMU->ADCCLK = (((clk_div.adc_osc_div + 1)*2-1) << 4) | DEV_CMU_ADCCLK_SEL_PLL_AUDIO | DEV_CMU_ADCCLK_EN_ENABLE; /*audio pll 49.152M as audio clock\r\n*/
#else
        DEV_CMU->DLYCLK = DEV_CMU_DLYCLK_SEL_OSC_XTAL | DEV_CMU_DLYCLK_EN_ENABLE;       
        DEV_CMU->ADCCLK = (clk_div.adc_osc_div << 4) | DEV_CMU_ADCCLK_SEL_OSC_XTAL | DEV_CMU_ADCCLK_EN_ENABLE;/*OSC_XTAL as audio clock\r\n*/
#endif
        if (hadc->ch_cfg[0].dmic.mode == DUAL) /*立体声*/
        {
            DEV_ADC->CHNn_CFG[0] = DEV_ADC_CHNn_CFG_MIX_SRC_SEL_ENABLE |
                                   (hadc->ch_cfg[0].digit_volume << 12) |
                                   (clk_div.dmic_clk_div << 24) |
                                   DEV_ADC_CHNn_CFG_DMIC_PIN_SEL_CHN0_1MIXCHN2_3MIX |
                                   DEV_ADC_CHNn_CFG_CIC_CLK_PHASE_POSITIVE |
                                   (clk_div.fir_clk_div << 9) |
                                   DEV_ADC_CHNn_CFG_HPF_COEF_1_128 |
                                   DEV_ADC_CHNn_CFG_HPF_EN_ENABLE |
                                   (clk_div.cic_sel << 2) |
                                   DEV_ADC_CHNn_CFG_MODE_SEL_DMIC |
                                   DEV_ADC_CHNn_CFG_CHN_EN_ENABLE;
            DEV_ADC->CHNn_CFG[1] = DEV_ADC_CHNn_CFG_MIX_SRC_SEL_ENABLE |
                                   (hadc->ch_cfg[0].digit_volume << 12) |
                                   (clk_div.dmic_clk_div << 24) |
                                   DEV_ADC_CHNn_CFG_DMIC_PIN_SEL_CHN0_1MIXCHN2_3MIX |
                                   DEV_ADC_CHNn_CFG_CIC_CLK_PHASE_NEGTIVE |
                                   (clk_div.fir_clk_div << 9) |
                                   DEV_ADC_CHNn_CFG_HPF_COEF_1_128 |
                                   DEV_ADC_CHNn_CFG_HPF_EN_ENABLE |
                                   (clk_div.cic_sel << 2) |
                                   DEV_ADC_CHNn_CFG_MODE_SEL_DMIC |
                                   DEV_ADC_CHNn_CFG_CHN_EN_ENABLE;
            data_sel |= ((1 << 0) + (1 << 1));
        }
        else if (hadc->ch_cfg[0].dmic.mode == SINGLE) /*单声道*/
        {
            DEV_ADC->CHNn_CFG[0] = DEV_ADC_CHNn_CFG_MIX_SRC_SEL_ENABLE |
                                   (hadc->ch_cfg[0].digit_volume << 12) |
                                   (clk_div.dmic_clk_div << 24) |
                                   DEV_ADC_CHNn_CFG_DMIC_PIN_SEL_INDIVIDUAL |
                                   DEV_ADC_CHNn_CFG_CIC_CLK_PHASE_POSITIVE |
                                   (clk_div.fir_clk_div << 9) |
                                   DEV_ADC_CHNn_CFG_HPF_COEF_1_128 |
                                   DEV_ADC_CHNn_CFG_HPF_EN_ENABLE |
                                   (clk_div.cic_sel << 2) |
                                   DEV_ADC_CHNn_CFG_MODE_SEL_DMIC |
                                   DEV_ADC_CHNn_CFG_CHN_EN_ENABLE;
            data_sel |= (1 << 0);
        }
        else
        {
            hadc->state = ERR;
            return HAL_ERROR;/*异常返回*/
        }
    }

    /*ch1*/
    if (hadc->ch_cfg[1].hw_pin == AMIC_CH1) /*通道1用模拟麦*/
    {
        if (HAL_ERROR == get_amic_clk_div(hadc->ch_cfg[1].sample_rate, &clk_div)) /*配置滤波器的分频系数*/
        {
            hadc->state = ERR;
            return HAL_ERROR;/*异常返回*/
        }
#ifdef ADC_USE_AUDIO_PLL
        DEV_CMU->ADCCLK = (((clk_div.adc_osc_div + 1)*2-1) << 4) | DEV_CMU_ADCCLK_SEL_PLL_AUDIO | DEV_CMU_ADCCLK_EN_ENABLE; /*audio pll 49.152M as audio clock\r\n*/
#else  
        DEV_CMU->ADCCLK = (clk_div.adc_osc_div << 4) | DEV_CMU_ADCCLK_SEL_OSC_XTAL | DEV_CMU_ADCCLK_EN_ENABLE;/*OSC_XTAL as audio clock\r\n*/
#endif
#if 1
        DEV_ADC->CHNn_CFG[1] = DEV_ADC_CHNn_CFG_MIX_SRC_SEL_ENABLE |
        						DEV_ADC_CHNn_CFG_CIC_CLK_DIV_256FS_2_128FS|
                               (hadc->ch_cfg[1].digit_volume << 12) |
                               (clk_div.fir_clk_div << 9) |
                               (clk_div.cic_sel << 2) |
                               DEV_ADC_CHNn_CFG_HPF_COEF_1_128 |
                               DEV_ADC_CHNn_CFG_HPF_EN_ENABLE |
                               DEV_ADC_CHNn_CFG_MODE_SEL_ADC |
                               DEV_ADC_CHNn_CFG_CHN_EN_ENABLE;
#endif

#if 0
        DEV_ADC->CHNn_CFG[1] = (1<<29) |
        						DEV_ADC_CHNn_CFG_CIC_CLK_DIV_256FS_2_128FS|
                               (hadc->ch_cfg[1].digit_volume << 12) |
                               (clk_div.fir_clk_div << 9) |
                               (clk_div.cic_sel << 2) |
                               DEV_ADC_CHNn_CFG_HPF_COEF_1_128 |
                               DEV_ADC_CHNn_CFG_HPF_EN_ENABLE |
                               DEV_ADC_CHNn_CFG_MODE_SEL_ADC |
                               DEV_ADC_CHNn_CFG_CHN_EN_ENABLE;
#endif
        vmic_init(VMIC1, hadc->ch_cfg[1].amic.vmic);
        DEV_ADC->MIC_CTRL0  |= (hadc->ch_cfg[1].amic.mic_gain << 12) |   //MIC1_GAIN
                               (hadc->ch_cfg[1].amic.mode << 10) |       //MIC1_MODE
                               (DEV_ADC_MIC_CTRL0_MIC1_EN_ENABLE);       //MIC1_ENABLE
        DEV_ADC->MIX_CTRL0  |= (hadc->ch_cfg[1].amic.mix_gain << 12) |   //MIX1 GAIN
                               (DEV_ADC_MIX_CTRL0_MIX1_MIC1_EN_ENABLE) | //MIX1 MIC1 ENABLE
                               (DEV_ADC_MIX_CTRL0_MIX1_EN_ENABLE);       //MIX1 ENABLE
        data_sel |= (1 << 1);
    }
    else if ((hadc->ch_cfg[1].hw_pin == DMIC1_GPIO4_GPIO5) || (hadc->ch_cfg[1].hw_pin == DIMC1_GPIO20_GPIO21)) /*通道1用数字麦*/
    {
        if (HAL_ERROR == get_dmic_clk_div(hadc->ch_cfg[1].sample_rate, &clk_div)) /*配置滤波器的分频系数*/
        {
            hadc->state = ERR;
            return HAL_ERROR;/*异常返回*/
        }

        set_mic_pin_fun(hadc->ch_cfg[1].hw_pin);
#ifdef ADC_USE_AUDIO_PLL
        DEV_CMU->ADCCLK = (((clk_div.adc_osc_div + 1)*2-1) << 4) | DEV_CMU_ADCCLK_SEL_PLL_AUDIO | DEV_CMU_ADCCLK_EN_ENABLE; /*audio pll 49.152M as audio clock\r\n*/
#else
        DEV_CMU->DLYCLK = DEV_CMU_DLYCLK_SEL_OSC_XTAL | DEV_CMU_DLYCLK_EN_ENABLE;       
        DEV_CMU->ADCCLK = (clk_div.adc_osc_div << 4) | DEV_CMU_ADCCLK_SEL_OSC_XTAL | DEV_CMU_ADCCLK_EN_ENABLE;/*OSC_XTAL as audio clock\r\n*/
#endif
        DEV_ADC->CHNn_CFG[1] = DEV_ADC_CHNn_CFG_MIX_SRC_SEL_ENABLE |
                               (hadc->ch_cfg[1].digit_volume << 12) |
                               (clk_div.dmic_clk_div << 24) |
                               DEV_ADC_CHNn_CFG_DMIC_PIN_SEL_INDIVIDUAL |
                               DEV_ADC_CHNn_CFG_CIC_CLK_PHASE_POSITIVE |
                               (clk_div.fir_clk_div << 9) |
                               DEV_ADC_CHNn_CFG_HPF_COEF_1_128 |
                               DEV_ADC_CHNn_CFG_HPF_EN_ENABLE |
                               (clk_div.cic_sel << 2) |
                               DEV_ADC_CHNn_CFG_MODE_SEL_DMIC |
                               DEV_ADC_CHNn_CFG_CHN_EN_ENABLE;
        data_sel |= (1 << 1);
    }

    /*ch2*/
    if ((hadc->ch_cfg[2].hw_pin == DIMC2_GPIO14_GPIO15) || (hadc->ch_cfg[2].hw_pin == DMIC2_GPIO22_GPIO23)) /*通道2用数字麦*/
    {
        if (HAL_ERROR == get_dmic_clk_div(hadc->ch_cfg[2].sample_rate, &clk_div)) /*配置滤波器的分频系数*/
        {
            hadc->state = ERR;
            return HAL_ERROR;/*异常返回*/
        }

        set_mic_pin_fun(hadc->ch_cfg[2].hw_pin);
#ifdef ADC_USE_AUDIO_PLL
        DEV_CMU->ADCCLK = (((clk_div.adc_osc_div + 1)*2-1) << 4) | DEV_CMU_ADCCLK_SEL_PLL_AUDIO | DEV_CMU_ADCCLK_EN_ENABLE; /*audio pll 49.152M as audio clock\r\n*/
#else
        DEV_CMU->DLYCLK = DEV_CMU_DLYCLK_SEL_OSC_XTAL | DEV_CMU_DLYCLK_EN_ENABLE;       
        DEV_CMU->ADCCLK = (clk_div.adc_osc_div << 4) | DEV_CMU_ADCCLK_SEL_OSC_XTAL | DEV_CMU_ADCCLK_EN_ENABLE;/*OSC_XTAL as audio clock\r\n*/
#endif

        if (hadc->ch_cfg[2].dmic.mode == DUAL) /*立体声*/
        {
            DEV_ADC->CHNn_CFG[2] = DEV_ADC_CHNn_CFG_MIX_SRC_SEL_ENABLE |
                                   (hadc->ch_cfg[2].digit_volume << 12) |
                                   (clk_div.dmic_clk_div << 24) |
                                   DEV_ADC_CHNn_CFG_DMIC_PIN_SEL_CHN0_1MIXCHN2_3MIX |
                                   DEV_ADC_CHNn_CFG_CIC_CLK_PHASE_POSITIVE |
                                   (clk_div.fir_clk_div << 9) |
                                   DEV_ADC_CHNn_CFG_HPF_COEF_1_128 |
                                   DEV_ADC_CHNn_CFG_HPF_EN_ENABLE |
                                   (clk_div.cic_sel << 2) |
                                   DEV_ADC_CHNn_CFG_MODE_SEL_DMIC |
                                   DEV_ADC_CHNn_CFG_CHN_EN_ENABLE;
            DEV_ADC->CHNn_CFG[3] = DEV_ADC_CHNn_CFG_MIX_SRC_SEL_ENABLE |
                                   (hadc->ch_cfg[2].digit_volume << 12) |
                                   (clk_div.dmic_clk_div << 24) |
                                   DEV_ADC_CHNn_CFG_DMIC_PIN_SEL_CHN0_1MIXCHN2_3MIX |
                                   DEV_ADC_CHNn_CFG_CIC_CLK_PHASE_NEGTIVE |
                                   (clk_div.fir_clk_div << 9) |
                                   DEV_ADC_CHNn_CFG_HPF_COEF_1_128 |
                                   DEV_ADC_CHNn_CFG_HPF_EN_ENABLE |
                                   (clk_div.cic_sel << 2) |
                                   DEV_ADC_CHNn_CFG_MODE_SEL_DMIC |
                                   DEV_ADC_CHNn_CFG_CHN_EN_ENABLE;
            data_sel |= ((1 << 2) + (1 << 3));
        }
        else if (hadc->ch_cfg[2].dmic.mode == SINGLE) /*单声道*/
        {
            DEV_ADC->CHNn_CFG[2] = DEV_ADC_CHNn_CFG_MIX_SRC_SEL_ENABLE |
                                   (hadc->ch_cfg[2].digit_volume << 12) |
                                   (clk_div.dmic_clk_div << 24) |
                                   DEV_ADC_CHNn_CFG_DMIC_PIN_SEL_INDIVIDUAL |
                                   DEV_ADC_CHNn_CFG_CIC_CLK_PHASE_POSITIVE |
                                   (clk_div.fir_clk_div << 9) |
                                   DEV_ADC_CHNn_CFG_HPF_COEF_1_128 |
                                   DEV_ADC_CHNn_CFG_HPF_EN_ENABLE |
                                   (clk_div.cic_sel << 2) |
                                   DEV_ADC_CHNn_CFG_MODE_SEL_DMIC |
                                   DEV_ADC_CHNn_CFG_CHN_EN_ENABLE;
            data_sel |= (1 << 2);
        }
    }

    /*ch3*/
    if (hadc->ch_cfg[3].hw_pin == DIMC3_GPIO16_GPIO17) /*通道3用数字麦*/
    {
        if (HAL_ERROR == get_dmic_clk_div(hadc->ch_cfg[3].sample_rate, &clk_div)) /*配置滤波器的分频系数*/
        {
            hadc->state = ERR;
            return HAL_ERROR;/*异常返回*/
        }

        set_mic_pin_fun(hadc->ch_cfg[3].hw_pin);
#ifdef ADC_USE_AUDIO_PLL
        DEV_CMU->ADCCLK = (((clk_div.adc_osc_div + 1)*2-1) << 4) | DEV_CMU_ADCCLK_SEL_PLL_AUDIO | DEV_CMU_ADCCLK_EN_ENABLE; /*audio pll 49.152M as audio clock\r\n*/
#else
        DEV_CMU->DLYCLK = DEV_CMU_DLYCLK_SEL_OSC_XTAL | DEV_CMU_DLYCLK_EN_ENABLE;       
        DEV_CMU->ADCCLK = (clk_div.adc_osc_div << 4) | DEV_CMU_ADCCLK_SEL_OSC_XTAL | DEV_CMU_ADCCLK_EN_ENABLE;/*OSC_XTAL as audio clock\r\n*/
#endif
        DEV_ADC->CHNn_CFG[3] = DEV_ADC_CHNn_CFG_MIX_SRC_SEL_ENABLE |
                               (hadc->ch_cfg[3].digit_volume << 12) |
                               (clk_div.dmic_clk_div << 24) |
                               DEV_ADC_CHNn_CFG_DMIC_PIN_SEL_INDIVIDUAL |
                               DEV_ADC_CHNn_CFG_CIC_CLK_PHASE_POSITIVE |
                               (clk_div.fir_clk_div << 9) |
                               DEV_ADC_CHNn_CFG_HPF_COEF_1_128 |
                               DEV_ADC_CHNn_CFG_HPF_EN_ENABLE |
                               (clk_div.cic_sel << 2) |
                               DEV_ADC_CHNn_CFG_MODE_SEL_DMIC |
                               DEV_ADC_CHNn_CFG_CHN_EN_ENABLE;
        data_sel |= (1 << 3);
    }

    if ((hadc->ch_cfg[0].hw_pin == AMIC_CH0) || (hadc->ch_cfg[1].hw_pin == AMIC_CH1))
    {
        DEV_ADC->MIC_CTRL1  |= DEV_ADC_MIC_CTRL1_MIC_CHOP_EN_ENABLE |             //CHOP ENABLE
                               DEV_ADC_MIC_CTRL1_MIC_VCMI_CHOP_EN_ENABLE |        //VCM CHOP ENABLE
                               //DEV_ADC_MIC_CTRL1_MIC_VCMI_SEL_SELECTVREF_VMIC|  //MIC VCM1 SELECT VREF_VMIC
                               DEV_ADC_MIC_CTRL1_MIC_IBIAS_CTRL_5UA |
                               DEV_ADC_MIC_CTRL1_MIC_CAP_CHG_DISABLE;
        DEV_ADC->SDM_CTRL0 = DEV_ADC_SDM_CTRL0_ADC_START;

        DEV_ADC->SDM_CTRL1 = DEV_ADC_SDM_CTRL1_ADC_VREF_CHG|
        					 DEV_ADC_SDM_CTRL1_ADC_DITHER_EN_ENABLE |
                             DEV_ADC_SDM_CTRL1_ADC_CHOP_DIV_32 |
                             DEV_ADC_SDM_CTRL1_ADC_CHOP_EN_ENABLE;

        if(hadc->ch_cfg[0].hw_pin == AMIC_CH0)
        {
        	DEV_ADC->SDM_CTRL1 |=(DEV_ADC_SDM_CTRL1_ADC0_EN_ENABLE + (clk_div.adc_clkdiv_sel << 24));
        }
        if(hadc->ch_cfg[1].hw_pin == AMIC_CH1)
        {
        	DEV_ADC->SDM_CTRL1 |=(DEV_ADC_SDM_CTRL1_ADC1_EN_ENABLE + (clk_div.adc_clkdiv_sel << 26));
        }
    }



//  DEV_ADC->MIX_CTRL0 = DEV_ADC_MIX_CTRL0_MIX1_GAIN_0DB|           //MIX1 GAIN 0DB
//                       DEV_ADC_MIX_CTRL0_MIX1_MIC1_EN_ENABLE|     //MIX1 MIC1 ENABLE
//                       DEV_ADC_MIX_CTRL0_MIX1_EN_ENABLE|          //MIX1 ENABLE
//                       DEV_ADC_MIX_CTRL0_MIX0_GAIN_0DB|           //MIX0 GAIN 0DB
//                       DEV_ADC_MIX_CTRL0_MIX0_MIC0_EN_ENABLE |    //MIX0 MIC0 ENABLE
//                       DEV_ADC_MIX_CTRL0_MIX0_EN_ENABLE;          //MIX0 ENABLE

    channel_clock = find_first_1bit(data_sel);
    if ((channel_clock >= 0) && (channel_clock <= 3))
    {
        DEV_ADC->CFG = (hadc->init.data_width << 6) |              //ADC_WIDTH
                       (8 << 8) |                                  //HFUL_TH
                       (channel_clock << 20) |                     //FIFO_CLK_SEL
                       ((data_sel & hadc->init.channel_id) << 24); //channel
    }
    else
    {
        hadc->state = ERR;
        return HAL_ERROR;/*异常返回*/
    }

    DEV_ADC->CTL |= DEV_ADC_CTL_RX_FIFO_RST_RXFIFORESET;
    DEV_ADC->CTL = (hadc->init.src_sel << 2);

    if (hadc->dma_handle != NULL)
    {
        DEV_ADC->CTL |= DEV_ADC_CTL_DMA_EN_ENABLE;
    }
    else
    {
        hadc->state = ERR;
        return HAL_ERROR;/*异常返回*/
    }
    mic_fast_charge_cap_disable();//不关闭会导致ADMIC谐波增大
    DEV_ADC->SDM_CTRL1 &= ~DEV_ADC_SDM_CTRL1_ADC_VREF_CHG;
    hadc->state = IDLE;
    return HAL_OK;
}


HAL_StatusTypeDef hal_adc_ctl_en(Options_EnableEnum en)
{
	uint32_t result = HAL_OK;
	DEV_ADC->CTL_f.ADC_EN = en;
	return result;
}


int find_first_1bit(uint32_t data)
{
    int i;

    for (i = 0; i < 32; i++)
    {
        if (data & 0x01)
        {
            return i;
        }
        else
        {
            data >>= 1;
        }
    }

    return -1;
}

HAL_StatusTypeDef set_mic_pin_fun(uint32_t temp)
{
    HAL_StatusTypeDef sta = HAL_OK;

    if (temp & (DMIC0_GPIO0_GPIO1))
    {
        DEV_GPIO->CTL[0] = 5;//dmic0 clk
        DEV_GPIO->CTL[1] = 5;//dmic0 data
    }
    else if (temp & (DMIC0_GPIO18_GPIO19))
    {
        DEV_GPIO->CTL[18] = 5;//dmic0 clk
        DEV_GPIO->CTL[19] = 5;//dmic0 data
    }
    else if (temp & (DMIC0_GPIO30_GPIO31))
    {
        DEV_GPIO->CTL[30] = 5;//dmic0 clk
        DEV_GPIO->CTL[31] = 5;//dmic0 data
    }
    else if (temp & DMIC1_GPIO4_GPIO5)
    {
        DEV_GPIO->CTL[4] = 5;//dmic0 clk
        DEV_GPIO->CTL[5] = 5;//dmic0 data
    }
    else if (temp & DIMC1_GPIO20_GPIO21)
    {
        DEV_GPIO->CTL[20] = 5;//dmic0 clk
        DEV_GPIO->CTL[21] = 5;//dmic0 data
    }
    else if (temp & (DIMC2_GPIO14_GPIO15))
    {
        DEV_GPIO->CTL[14] = 5;//dmic0 clk
        DEV_GPIO->CTL[15] = 5;//dmic0 data
    }
    else if (temp & (DMIC2_GPIO22_GPIO23))
    {
        DEV_GPIO->CTL[22] = 5;//dmic0 clk
        DEV_GPIO->CTL[23] = 5;//dmic0 data
    }
    else if (temp & DIMC3_GPIO16_GPIO17)
    {
        DEV_GPIO->CTL[16] = 5;//dmic0 clk
        DEV_GPIO->CTL[17] = 5;//dmic0 data
    }

    return sta;
}

HAL_StatusTypeDef get_dmic_clk_div(uint32_t sample, clk_div_typedef *addr)
{
    HAL_StatusTypeDef state = HAL_OK;

    switch (sample)
    {
    case SAMPLE_RATE_8K:
        addr->adc_osc_div = 3;
        addr->fir_clk_div = 5;
        addr->dmic_clk_div = 4;
        addr->cic_sel = 1;
        break;

    case SAMPLE_RATE_16K:
        addr->adc_osc_div = 2;
        addr->fir_clk_div = 4;
        addr->dmic_clk_div = 3;
        addr->cic_sel = 1;
        break;

    case SAMPLE_RATE_24K:
        addr->adc_osc_div = 7;
        addr->fir_clk_div = 1;
        addr->dmic_clk_div = 1;
        addr->cic_sel = 2;
        break;

    case SAMPLE_RATE_32K:
        addr->adc_osc_div = 1;
        addr->fir_clk_div = 3;
        addr->dmic_clk_div = 2;
        addr->cic_sel = 1;
        break;

    case SAMPLE_RATE_48K:
        addr->adc_osc_div = 3;
        addr->fir_clk_div = 1;
        addr->dmic_clk_div = 0;
        addr->cic_sel = 1;
        break;

    default:
        state = HAL_ERROR;
        break;
    }

    return state;
}

HAL_StatusTypeDef get_amic_clk_div(uint32_t sample, clk_div_typedef *addr)
{
    HAL_StatusTypeDef state = HAL_OK;

    switch (sample)
    {
    case SAMPLE_RATE_8K:
        addr->adc_osc_div = 11;
        addr->fir_clk_div = 2;
        addr->cic_sel = 0;
        addr->adc_clkdiv_sel = 0;
        addr->dmic_clk_div = 0;
        break;

    case SAMPLE_RATE_16K:
        addr->adc_osc_div = 5;
        addr->fir_clk_div = 2;
        addr->cic_sel = 0;
        addr->adc_clkdiv_sel = 0;
        addr->dmic_clk_div = 0;
        break;

    case SAMPLE_RATE_24K:
        addr->adc_osc_div = 3;
        addr->fir_clk_div = 2;
        addr->cic_sel = 0;
        addr->adc_clkdiv_sel = 0;
        addr->dmic_clk_div = 0;
        break;

    case SAMPLE_RATE_32K:
        addr->adc_osc_div = 2;
        addr->fir_clk_div = 2;
        addr->cic_sel = 0;
        addr->adc_clkdiv_sel = 0;
        addr->dmic_clk_div = 0;
        break;

    case SAMPLE_RATE_48K:
        addr->adc_osc_div = 1;
        addr->fir_clk_div = 2;
        addr->cic_sel = 0;
        addr->adc_clkdiv_sel = 0;
        addr->dmic_clk_div = 0;
        break;

    case SAMPLE_RATE_96K:
        addr->adc_osc_div = 1;
        addr->fir_clk_div = 1;
        addr->cic_sel = 1;
        addr->adc_clkdiv_sel = 0;
        addr->dmic_clk_div = 0;
        break;

    case SAMPLE_RATE_192K:
        addr->adc_osc_div = 1;
        addr->fir_clk_div = 0;
        addr->cic_sel = 2;
        addr->adc_clkdiv_sel = 0;
        addr->dmic_clk_div = 0;
        break;

    default:
        state = HAL_ERROR;
        break;
    }

    return state;
}


HAL_StatusTypeDef audio_adc_cmd(audio_adc_handle_typedef *hadc, Options_EnableEnum cmd)
{
//    if ((hadc == NULL) || (hadc->state == FREE) || (hadc->state == ERR))
//    {
//        return HAL_ERROR;
//    }

    if (cmd == ENABLE)
    {
        DEV_ADC->CTL_f.RX_FIFO_RST = 0;
        hadc->state = WORK;
        DEV_ADC->CTL_f.ADC_EN = 1;
    }
    else
    {
        hadc->state = IDLE;
        DEV_ADC->CTL_f.ADC_EN = 0;
        DEV_ADC->CTL_f.RX_FIFO_RST = 1;
    }

    return HAL_OK;
}




HAL_StatusTypeDef  hal_audio_adc_deinit(audio_adc_handle_typedef *hadc)
{
    if (hadc == NULL)
    {
        return HAL_ERROR;
    }

    DEV_RMU->RSTEN0_f.ADC = 0;
    hadc->state = FREE;
    DEV_RMU->RSTEN0_f.ADC = 1;
    return HAL_OK;
}

/*数字音量设置*/
HAL_StatusTypeDef hal_audio_adc_vol_set(audio_adc_handle_typedef *hadc, adc_channel_type_def ch, volume_type_def vol)
{
    if (hadc == NULL)
    {
        return HAL_ERROR;
    }

    if (ch & CHN0)
    {
        hadc->ch_cfg[0].digit_volume = vol;
        DEV_ADC->CHNn_CFG_f[0].VOL = hadc->ch_cfg[0].digit_volume;
    }

    if (ch & CHN1)
    {
        hadc->ch_cfg[1].digit_volume = vol;
        DEV_ADC->CHNn_CFG_f[1].VOL = hadc->ch_cfg[1].digit_volume;
    }

    if (ch & CHN2)
    {
        hadc->ch_cfg[2].digit_volume = vol;
        DEV_ADC->CHNn_CFG_f[2].VOL = hadc->ch_cfg[2].digit_volume;
    }

    if (ch & CHN3)
    {
        hadc->ch_cfg[3].digit_volume = vol;
        DEV_ADC->CHNn_CFG_f[3].VOL = hadc->ch_cfg[3].digit_volume;
    }

    return HAL_OK;
}

/*amic mic 增益设置*/
HAL_StatusTypeDef hal_audio_adc_mic_gain_set(audio_adc_handle_typedef *hadc, amic_channel_type_def ch, amic_mic_gain_type_def gain)
{
    if (hadc == NULL)
    {
        return HAL_ERROR;
    }

    if (AMIC0 == ch)
    {
        DEV_ADC->MIC_CTRL0_f.MIC0_GAIN = gain;
        hadc->ch_cfg[0].amic.mic_gain = gain;
    }
    else if (AMIC1 == ch)
    {
        DEV_ADC->MIC_CTRL0_f.MIC1_GAIN = gain;
        hadc->ch_cfg[1].amic.mic_gain = gain;
    }

    return HAL_OK;
}

/*amic mic 增益设置*/
HAL_StatusTypeDef hal_audio_adc_mic_gain_get(audio_adc_handle_typedef *hadc, amic_channel_type_def ch, amic_mic_gain_type_def* gain)
{
    if (hadc == NULL)
    {
        return HAL_ERROR;
    }
    if (AMIC0 == ch)
    {
    	*gain = DEV_ADC->MIC_CTRL0_f.MIC0_GAIN;
    }
    else if (AMIC1 == ch)
    {
    	*gain = DEV_ADC->MIC_CTRL0_f.MIC1_GAIN;
    }
    return HAL_OK;
}

/*amic mix 增益设置*/
HAL_StatusTypeDef hal_audio_adc_mix_gain_set(audio_adc_handle_typedef *hadc, amic_channel_type_def ch, amic_mix_gain_type_def gain)
{
    if (hadc == NULL)
    {
        return HAL_ERROR;
    }

    if (AMIC0 == ch)
    {
        DEV_ADC->MIX_CTRL0_f.MIX0_GAIN = gain;
        hadc->ch_cfg[0].amic.mix_gain = gain;
    }
    else if (AMIC1 == ch)
    {
        DEV_ADC->MIX_CTRL0_f.MIX1_GAIN = gain;
        hadc->ch_cfg[1].amic.mix_gain = gain;
    }

    return HAL_OK;
}

void set_mic_gain(input_option_e ch, amic_mic_gain_type_def gain)
{
	uint32_t temp;
    if (MIC_0 == ch)
    {
        //DEV_ADC->MIC_CTRL0_f.MIC0_GAIN = gain;
        temp = DEV_ADC->MIC_CTRL0;
        temp &= ~DEV_ADC_MIC_CTRL0_MIC0_GAIN_MASK;
        temp |= (gain<<4);
        DEV_ADC->MIC_CTRL0 = temp;
    }
    else if (MIC_1 == ch)
    {
        //DEV_ADC->MIC_CTRL0_f.MIC1_GAIN = gain;
        temp = DEV_ADC->MIC_CTRL0;
        temp &= ~DEV_ADC_MIC_CTRL0_MIC1_GAIN_MASK;
        temp |= (gain<<12);
        DEV_ADC->MIC_CTRL0 = temp;
    }
}

void get_mic_gain(input_option_e ch, uint32_t *addr)
{
	uint32_t temp;
    if (MIC_0 == ch)
    {
    	//*addr = DEV_ADC->MIC_CTRL0_f.MIC0_GAIN;
    	temp = (DEV_ADC->MIC_CTRL0 & DEV_ADC_MIC_CTRL0_MIC0_GAIN_MASK)>>4;

    }
    else if (MIC_1 == ch)
    {
    	//*addr = DEV_ADC->MIC_CTRL0_f.MIC1_GAIN;
    	temp = (DEV_ADC->MIC_CTRL0 & DEV_ADC_MIC_CTRL0_MIC1_GAIN_MASK)>>12;
    }
    *addr = temp;
}

void set_mic_mix_gain(input_option_e ch, amic_mix_gain_type_def gain)
{
	uint32_t temp;
    if (MIC_0 == ch)
    {
        //DEV_ADC->MIX_CTRL0_f.MIX0_GAIN = gain;
    	temp = DEV_ADC->MIX_CTRL0;
		temp &= ~DEV_ADC_MIX_CTRL0_MIX0_GAIN_MASK;
		temp |= (gain<<4);
		DEV_ADC->MIX_CTRL0 = temp;

    }
    else if (MIC_1 == ch)
    {
        //DEV_ADC->MIX_CTRL0_f.MIX1_GAIN = gain;
    	temp = DEV_ADC->MIX_CTRL0;
		temp &= ~DEV_ADC_MIX_CTRL0_MIX1_GAIN_MASK;
		temp |= (gain<<12);
		DEV_ADC->MIX_CTRL0 = temp;

    }
}

void get_mic_mix_gain(input_option_e ch, uint32_t *addr)
{
	uint32_t temp;
    if (MIC_0 == ch)
    {
    	//*addr = DEV_ADC->MIX_CTRL0_f.MIX0_GAIN;
    	temp = (DEV_ADC->MIX_CTRL0 & DEV_ADC_MIX_CTRL0_MIX0_GAIN_MASK)>>4;
    }
    else if (MIC_1 == ch)
    {
    	//*addr = DEV_ADC->MIX_CTRL0_f.MIX1_GAIN;
    	temp = (DEV_ADC->MIX_CTRL0 & DEV_ADC_MIX_CTRL0_MIX1_GAIN_MASK)>>12;
    }
    *addr = temp;
}

/*src选择*/
HAL_StatusTypeDef hal_audio_adc_src_sel(audio_adc_handle_typedef *hadc, src_sel_type_def sel)
{
    if (hadc == NULL)
    {
        return HAL_ERROR;
    }

    hadc->init.src_sel = sel;
    DEV_ADC->CTL_f.SRC_SEL = sel;
    return HAL_OK;
}



/*vmic电压设置*/
HAL_StatusTypeDef hal_audio_adc_vmic_volt_sel(audio_adc_handle_typedef *hadc, amic_channel_type_def ch, vmic_vol_type_def volt)
{
    if (hadc == NULL)
    {
        return HAL_ERROR;
    }

    if (ch == AMIC0)
    {
        DEV_ADC->VMIC0_CTRL_f.VMIC0_VOL = volt;
        hadc->ch_cfg[0].amic.vmic = volt;
    }
    else if (ch == AMIC1)
    {
        DEV_ADC->VMIC1_CTRL_f.VMIC1_VOL = volt;
        hadc->ch_cfg[1].amic.vmic = volt;
    }

    return HAL_OK;
}

/*vmic电压开启或关闭*/
HAL_StatusTypeDef hal_audio_adc_vmic_volt_cmd(audio_adc_handle_typedef *hadc, amic_channel_type_def ch, Options_EnableEnum cmd)
{
    if (hadc == NULL)
    {
        return HAL_ERROR;
    }

    if (ch == AMIC0)
    {
        DEV_ADC->VMIC0_CTRL_f.VMIC0_EN = cmd;
    }
    else if (ch == AMIC1)
    {
        DEV_ADC->VMIC1_CTRL_f.VMIC1_EN = cmd;
    }

    return HAL_OK;
}

/*mic channel开启或关闭*/
HAL_StatusTypeDef hal_audio_adc_fifo_sel(audio_adc_handle_typedef *hadc, adc_channel_type_def ch)
{
    if (hadc == NULL)
    {
        return HAL_ERROR;
    }

    if (!(ch & (CHN0 | CHN1 | CHN2 | CHN3)))
    {
        //rt_kprintf("Channel configuration parameters are not available\r\n");
        return HAL_ERROR;
    }

    DEV_ADC->CFG_f.FIFO_DAT_SEL = ch;
    return HAL_OK;
}

/*用于开关某一个MIC声道的模拟部分，节省功耗*/
void hal_audio_adc_option(input_option_e ch,Options_EnableEnum cmd)
{
  if(cmd == ENABLE)//开启
  {
    if(ch == MIC_0)
    {
    	DEV_ADC->VMIC0_CTRL_f.VMIC0_EN = ENABLE;
    	DEV_ADC->MIC_CTRL0_f.MIC0_EN = ENABLE;
    	DEV_ADC->MIX_CTRL0_f.MIX0_EN = ENABLE;
    	DEV_ADC->SDM_CTRL1_f.ADC0_EN = ENABLE;
    }
    else if(ch == MIC_1)
    {
    	DEV_ADC->VMIC1_CTRL_f.VMIC1_EN = ENABLE;
    	DEV_ADC->MIC_CTRL0_f.MIC1_EN = ENABLE;
    	DEV_ADC->MIX_CTRL0_f.MIX1_EN = ENABLE;
    	DEV_ADC->SDM_CTRL1_f.ADC1_EN = ENABLE;
    }
  }
  else//关闭
  {
	if(ch == MIC_0)
	{
		DEV_ADC->VMIC0_CTRL_f.VMIC0_EN = DISABLE;
		DEV_ADC->MIC_CTRL0_f.MIC0_EN = DISABLE;
		DEV_ADC->MIX_CTRL0_f.MIX0_EN = DISABLE;
		DEV_ADC->SDM_CTRL1_f.ADC0_EN = DISABLE;
	}
	else if(ch == MIC_1)
	{
		DEV_ADC->VMIC1_CTRL_f.VMIC1_EN = DISABLE;
		DEV_ADC->MIC_CTRL0_f.MIC1_EN = DISABLE;
		DEV_ADC->MIX_CTRL0_f.MIX1_EN = DISABLE;
		DEV_ADC->SDM_CTRL1_f.ADC1_EN = DISABLE;
	}
  }
}

HAL_StatusTypeDef hal_audio_adc_set_samplerate(audio_adc_handle_typedef *hadc, sample_rate_type_def samplerate)
{
    clk_div_typedef clk_div;

    if (hadc == NULL)
    {
        return HAL_ERROR;
    }

    if (hadc->ch_cfg[0].hw_pin == AMIC_CH0) /*通道0用模拟麦*/
    {
        if (HAL_ERROR == get_amic_clk_div(samplerate, &clk_div)) /*配置滤波器的分频系数*/
        {
            hadc->state = ERR;
            return HAL_ERROR;/*异常返回*/
        }

#ifdef ADC_USE_AUDIO_PLL
        DEV_CMU->ADCCLK = (((clk_div.adc_osc_div + 1)*2-1) << 4) | DEV_CMU_ADCCLK_SEL_PLL_AUDIO | DEV_CMU_ADCCLK_EN_ENABLE; /*audio pll 49.152M as audio clock\r\n*/
#else     
        DEV_CMU->ADCCLK = (clk_div.adc_osc_div << 4) | DEV_CMU_ADCCLK_SEL_OSC_XTAL | DEV_CMU_ADCCLK_EN_ENABLE;/*OSC_XTAL as audio clock\r\n*/
#endif
        DEV_ADC->CHNn_CFG_f[0].FIR_CLK_DIV = clk_div.fir_clk_div;
        DEV_ADC->CHNn_CFG_f[0].CIC_SEL = clk_div.cic_sel;
    }
    else/*通道0用D麦*/
    {
        if (HAL_ERROR == get_dmic_clk_div(samplerate, &clk_div)) /*配置滤波器的分频系数*/
        {
            hadc->state = ERR;
            return HAL_ERROR;/*异常返回*/
        }

#ifdef ADC_USE_AUDIO_PLL
        DEV_CMU->ADCCLK = (((clk_div.adc_osc_div + 1)*2-1) << 4) | DEV_CMU_ADCCLK_SEL_PLL_AUDIO | DEV_CMU_ADCCLK_EN_ENABLE; /*audio pll 49.152M as audio clock\r\n*/
#else
        DEV_CMU->DLYCLK = DEV_CMU_DLYCLK_SEL_OSC_XTAL | DEV_CMU_DLYCLK_EN_ENABLE;       
        DEV_CMU->ADCCLK = (clk_div.adc_osc_div << 4) | DEV_CMU_ADCCLK_SEL_OSC_XTAL | DEV_CMU_ADCCLK_EN_ENABLE;/*OSC_XTAL as audio clock\r\n*/
#endif
        DEV_ADC->CHNn_CFG_f[0].FIR_CLK_DIV = clk_div.fir_clk_div;
        DEV_ADC->CHNn_CFG_f[0].CIC_SEL = clk_div.cic_sel;
        DEV_ADC->CHNn_CFG_f[0].DMIC_CLK_DIV = clk_div.dmic_clk_div;
    }

    if (hadc->ch_cfg[1].hw_pin == AMIC_CH1) /*通道1用模拟麦*/
    {
        if (HAL_ERROR == get_amic_clk_div(samplerate, &clk_div)) /*配置滤波器的分频系数*/
        {
            hadc->state = ERR;
            return HAL_ERROR;/*异常返回*/
        }

#ifdef ADC_USE_AUDIO_PLL
        DEV_CMU->ADCCLK = (((clk_div.adc_osc_div + 1)*2-1) << 4) | DEV_CMU_ADCCLK_SEL_PLL_AUDIO | DEV_CMU_ADCCLK_EN_ENABLE; /*audio pll 49.152M as audio clock\r\n*/
#else
        DEV_CMU->DLYCLK = DEV_CMU_DLYCLK_SEL_OSC_XTAL | DEV_CMU_DLYCLK_EN_ENABLE;       
        DEV_CMU->ADCCLK = (clk_div.adc_osc_div << 4) | DEV_CMU_ADCCLK_SEL_OSC_XTAL | DEV_CMU_ADCCLK_EN_ENABLE;/*OSC_XTAL as audio clock\r\n*/
#endif
        DEV_ADC->CHNn_CFG_f[1].FIR_CLK_DIV = clk_div.fir_clk_div;
        DEV_ADC->CHNn_CFG_f[1].CIC_SEL = clk_div.cic_sel;
    }
    else
    {
        if (HAL_ERROR == get_dmic_clk_div(samplerate, &clk_div)) /*配置滤波器的分频系数*/
        {
            hadc->state = ERR;
            return HAL_ERROR;/*异常返回*/
        }

#ifdef ADC_USE_AUDIO_PLL
        DEV_CMU->ADCCLK = ((clk_div.adc_osc_div + 1) << 4) | DEV_CMU_ADCCLK_SEL_PLL_AUDIO | DEV_CMU_ADCCLK_EN_ENABLE; /*audio pll 49.152M as audio clock\r\n*/
#else
        DEV_CMU->DLYCLK = DEV_CMU_DLYCLK_SEL_OSC_XTAL | DEV_CMU_DLYCLK_EN_ENABLE;       
        DEV_CMU->ADCCLK = (clk_div.adc_osc_div << 4) | DEV_CMU_ADCCLK_SEL_OSC_XTAL | DEV_CMU_ADCCLK_EN_ENABLE;/*OSC_XTAL as audio clock\r\n*/
#endif
        DEV_ADC->CHNn_CFG_f[1].FIR_CLK_DIV = clk_div.fir_clk_div;
        DEV_ADC->CHNn_CFG_f[1].CIC_SEL = clk_div.cic_sel;
        DEV_ADC->CHNn_CFG_f[1].DMIC_CLK_DIV = clk_div.dmic_clk_div;
    }

    if (HAL_ERROR == get_dmic_clk_div(samplerate, &clk_div)) /*配置滤波器的分频系数*/
    {
        hadc->state = ERR;
        return HAL_ERROR;/*异常返回*/
    }
#ifdef ADC_USE_AUDIO_PLL
        DEV_CMU->ADCCLK = (((clk_div.adc_osc_div + 1)*2-1) << 4) | DEV_CMU_ADCCLK_SEL_PLL_AUDIO | DEV_CMU_ADCCLK_EN_ENABLE; /*audio pll 49.152M as audio clock\r\n*/
#else
        DEV_CMU->DLYCLK = DEV_CMU_DLYCLK_SEL_OSC_XTAL | DEV_CMU_DLYCLK_EN_ENABLE;       
        DEV_CMU->ADCCLK = (clk_div.adc_osc_div << 4) | DEV_CMU_ADCCLK_SEL_OSC_XTAL | DEV_CMU_ADCCLK_EN_ENABLE;/*OSC_XTAL as audio clock\r\n*/
#endif
        DEV_ADC->CHNn_CFG_f[2].FIR_CLK_DIV = clk_div.fir_clk_div;
        DEV_ADC->CHNn_CFG_f[2].CIC_SEL = clk_div.cic_sel;
        DEV_ADC->CHNn_CFG_f[2].DMIC_CLK_DIV = clk_div.dmic_clk_div;
        DEV_ADC->CHNn_CFG_f[3].FIR_CLK_DIV = clk_div.fir_clk_div;
        DEV_ADC->CHNn_CFG_f[3].CIC_SEL = clk_div.cic_sel;
        DEV_ADC->CHNn_CFG_f[3].DMIC_CLK_DIV = clk_div.dmic_clk_div;
        DEV_ADC->SDM_CTRL1_f.ADC0_CLKDIV_SEL = clk_div.adc_clkdiv_sel;
        DEV_ADC->SDM_CTRL1_f.ADC1_CLKDIV_SEL = clk_div.adc_clkdiv_sel;
    return HAL_OK;
}


HAL_StatusTypeDef hal_audio_adc_set_samplebits(audio_adc_handle_typedef *hadc, adc_data_width_type_def samplebits)
{
    if (hadc == NULL)
    {
        return HAL_ERROR;
    }

    if ((samplebits != WIDTH_24BIT) && (samplebits != WIDTH_16BIT))
    {
        return HAL_ERROR;
    }

    DEV_ADC->CFG_f.ADC_WIDTH = samplebits;
    return HAL_OK;
}

HAL_StatusTypeDef hal_audio_adc_set_agc(audio_adc_handle_typedef *hadc, adc_AGC_config_typedef_def *agc_config)
{
    DEV_ADC->PEAK_AT = agc_config->Peak_Attack_time;
    DEV_ADC->PEAK_RT = agc_config->Peak_Release_time;
    DEV_ADC->GAIN_AT = agc_config->Gain_Attack_time;
    DEV_ADC->GAIN_RT = agc_config->Gain_Release_time;
    DEV_ADC->GAIN_CFG = (agc_config->Target_level << 24) |
                        (agc_config->noise_level << 16) |
                        (agc_config->Max_gain << 8) |
                        (agc_config->Min_gain << 4) |
                        (agc_config->Hysteresis << 2) |
                        (agc_config->noise_gain_enable << 1) |
                        (agc_config->AGC_enable << 0);
    /***********************************************AGC***************************************************/
// #include"math.h"
// DEV_ADC->GAIN_CFG = (20 << 24) |
//              (60 << 16) |
//              (10 << 8) |
//              (8<<4) |
//              (2<<2) |
//              (1<<1) |
//              (1<<0);
// DEV_ADC->PEAK_AT = (uint32_t)((1-exp(-2.2*(1/16000.0)/0.001))*pow(2,31));
// DEV_ADC->PEAK_RT = (uint32_t)((1-exp(-2.2*(1/16000.0)/0.3))*pow(2,31));
// DEV_ADC->GAIN_AT = (uint32_t)((1-exp(-2.2*(1/16000.0)/0.001))*pow(2,31));
// DEV_ADC->GAIN_RT = (uint32_t)((1-exp(-2.2*(1/16000.0)/0.2))*pow(2,31));
// rt_kprintf("**********************************************\r\n");
    /*****************************************************************************************************/
}

void audio_adc_mic_set(mic_enum mic,amic_mode_type_def option,amic_mic_gain_type_def gain)
{
	if (mic == MIC0)
	{
		DEV_ADC->MIC_CTRL0 &= ~0xFF;
		DEV_ADC->MIC_CTRL0 |= DEV_ADC_MIC_CTRL0_MIC0_EN_ENABLE + (option << 2) + (gain <<4);
	}
	else if(mic == MIC1)
	{
		DEV_ADC->MIC_CTRL0 &= ~(0xFF<<8);
		DEV_ADC->MIC_CTRL0 |= DEV_ADC_MIC_CTRL0_MIC1_EN_ENABLE + (option << 10) + (gain <<12);
	}
}

/*自动增益*/
HAL_StatusTypeDef hal_audio_adc_set_agc_cmd(audio_adc_handle_typedef *hadc, Options_EnableEnum cmd)
{
    if (hadc == NULL)
    {
        return HAL_ERROR;
    }

    if (ENABLE == cmd)
    {
        /*参数设置预留*/
        DEV_ADC->GAIN_CFG |= (DEV_ADC_GAIN_CFG_AGC_EN_ENABLE);
    }
    else
    {
        DEV_ADC->GAIN_CFG &= ~(DEV_ADC_GAIN_CFG_AGC_EN_ENABLE);
    }

    return HAL_OK;
}

void delay_us_nop(uint32_t count)
{
    int i = 100;

    while (count--)
    {
        for (; i > 0; i--);
    }
}

void vmic_init(vmic_enum vmic_sel, uint32_t vmic_voltage)
{
    vmic_config_struct vmic_config;
    vmic_config.bypass_enable = DISABLE;
    vmic_config.ramp_down_enbale = DISABLE;
    vmic_config.ramp_up_enbale = ENABLE;
    vmic_config.ramp_up_down_time_interval = 4999;
    vmic_config.ramp_up_high_num = 20;
    vmic_config.ramp_up_total_num = 244;
    vmic_config.vmic_ref_sel = VCM;
    vmic_config.mic_fast_charge_cap_enable = ENABLE;
    vmic_config.voltage = vmic_voltage;
    pmu_avcc_voltage_config(PMU_AVCC_VOL_3_0V);
    pmu_power_normal_on_config(PMU_POWER_NORMAL_ON_AVCC, ENABLE);

    if (!(DEV_CMU->DACCLK & DEV_CMU_DACCLK_EN_ENABLE)) /*如果DAC时钟没有开启，则开启DAC时钟*/
    {
        //cmu_dac_set_clk(CMU_Clock_PLL_AUDIO, 2);
        cmu_dac_set_clk(CMU_Clock_OSC_XTAL, 1);
    }

    pmu_control_vmic(vmic_sel, ENABLE, vmic_config);
}

void pmu_control_vmic(vmic_enum vmic, Options_EnableEnum option, vmic_config_struct vmic_cfg)
{
    pmu_vmic_ref_sel(vmic, vmic_cfg.vmic_ref_sel);
    pmu_vmic_bypass_control(vmic, vmic_cfg.bypass_enable);
    pmu_vmic_set_voltage(vmic, vmic_cfg);

    if (vmic == VMIC0)
    {
        if (option == ENABLE)
        {
            if (DEV_ADC->VMIC0_CTRL & DEV_ADC_VMIC0_CTRL_VMIC0_EN_ENABLE)
            {
                return;
            }
            else
            {
                pmu_vmic_ramp_up_control(vmic, vmic_cfg);
                delay_us_nop(1000);
                DEV_ADC->MIC_CTRL1 |= vmic_cfg.mic_fast_charge_cap_enable ? (DEV_ADC_MIC_CTRL1_MIC_CAP_CHG_ENABLE) : 0;
                DEV_ADC->VMIC0_CTRL |= DEV_ADC_VMIC0_CTRL_VMIC0_EN_ENABLE;
            }
        }
        else
        {
            pmu_vmic_ramp_up_control(vmic, vmic_cfg);
            delay_us_nop(480000);
            DEV_ADC->VMIC0_CTRL &= ~DEV_ADC_VMIC0_CTRL_VMIC0_EN_ENABLE;
        }
    }
    else
    {
        if (option == ENABLE)
        {
            if (DEV_ADC->VMIC1_CTRL & DEV_ADC_VMIC1_CTRL_VMIC1_EN_ENABLE)
            {
                return;
            }
            else
            {
                pmu_vmic_ramp_up_control(vmic, vmic_cfg);
                delay_us_nop(1000);
                DEV_ADC->MIC_CTRL1 |= vmic_cfg.mic_fast_charge_cap_enable ? (DEV_ADC_MIC_CTRL1_MIC_CAP_CHG_ENABLE) : 0;
                DEV_ADC->VMIC1_CTRL |= DEV_ADC_VMIC1_CTRL_VMIC1_EN_ENABLE;
            }
        }
        else
        {
            pmu_vmic_ramp_up_control(vmic, vmic_cfg);
            delay_us_nop(10000);
            DEV_ADC->VMIC1_CTRL &= ~DEV_ADC_VMIC1_CTRL_VMIC1_EN_ENABLE;
        }
    }
}

void mic_fast_charge_cap_disable(void)
{
    if (DEV_ADC->MIC_CTRL1 | DEV_ADC_MIC_CTRL1_MIC_CAP_CHG_ENABLE)
    {
        delay_us_nop(30000);
        DEV_ADC->MIC_CTRL1 &= ~DEV_ADC_MIC_CTRL1_MIC_CAP_CHG_ENABLE;
    }
}

void pmu_vmic_ref_sel(vmic_enum vmic, vmic_ref_enum ref)
{
    if (vmic == VMIC0)
    {
        if (ref == VREF_VMIC)
        {
            DEV_ADC->VMIC0_CTRL &= ~DEV_ADC_VMIC0_CTRL_VMIC0_REF_SEL_USEVCM;
        }
        else
        {
            DEV_ADC->VMIC0_CTRL |= DEV_ADC_VMIC0_CTRL_VMIC0_REF_SEL_USEVCM;
        }
    }
    else // vmic1
    {
        if (ref == VREF_VMIC)
        {
            DEV_ADC->VMIC1_CTRL &= ~DEV_ADC_VMIC0_CTRL_VMIC0_REF_SEL_USEVCM;
        }
        else
        {
            DEV_ADC->VMIC1_CTRL |= DEV_ADC_VMIC0_CTRL_VMIC0_REF_SEL_USEVCM;
        }
    }
}

void pmu_vmic_bypass_control(vmic_enum vmic, Options_EnableEnum option)
{
    if (vmic == VMIC0)
    {
        if (option == ENABLE)
        {
            DEV_ADC->VMIC0_CTRL |= DEV_ADC_VMIC0_CTRL_VMIC0_BYPASS_ENABLEBYPASS;
        }
        else
        {
            DEV_ADC->VMIC0_CTRL &= ~DEV_ADC_VMIC0_CTRL_VMIC0_BYPASS_ENABLEBYPASS;
        }
    }
    else // vmic1
    {
        if (option == ENABLE)
        {
            DEV_ADC->VMIC1_CTRL |= DEV_ADC_VMIC1_CTRL_VMIC1_BYPASS_ENABLEBYPASS;
        }
        else
        {
            DEV_ADC->VMIC1_CTRL &= ~DEV_ADC_VMIC1_CTRL_VMIC1_BYPASS_ENABLEBYPASS;
        }
    }
}

void pmu_vmic_ramp_up_control(vmic_enum vmic, vmic_config_struct vmic_cfg)
{
    DEV_ADC->VMIC_RAMP0 &= ~(DEV_ADC_VMIC_RAMP0_RAMP_TIME_MASK);
    DEV_ADC->VMIC_RAMP0 |= (vmic_cfg.ramp_up_down_time_interval << 16);
    DEV_ADC->VMIC_RAMP1  = (vmic_cfg.ramp_up_total_num << 16) | vmic_cfg.ramp_up_high_num;

    if (vmic == VMIC0)
    {
        if (vmic_cfg.ramp_up_enbale)
        {
            //DEV_ADC->VMIC_RAMP0 |= DEV_ADC_VMIC_RAMP0_VMIC0_RAMP_UP_EN_ENABLE | DEV_ADC_VMIC_RAMP0_FAST_STUP_VMIC_ENABLE;
            DEV_ADC->VMIC_RAMP0 |= DEV_ADC_VMIC_RAMP0_VMIC0_RAMP_UP_EN_ENABLE;
        }
        else
        {
            //DEV_ADC->VMIC_RAMP0 &= ~(DEV_ADC_VMIC_RAMP0_VMIC0_RAMP_UP_EN_ENABLE | DEV_ADC_VMIC_RAMP0_FAST_STUP_VMIC_ENABLE);
            DEV_ADC->VMIC_RAMP0 &= ~DEV_ADC_VMIC_RAMP0_VMIC0_RAMP_UP_EN_ENABLE;
        }

        if (vmic_cfg.ramp_down_enbale)
        {
            DEV_ADC->VMIC_RAMP0 |= DEV_ADC_VMIC_RAMP0_VMIC0_RAMP_DN_EN_ENABLE;
        }
        else
        {
            DEV_ADC->VMIC_RAMP0 &= ~DEV_ADC_VMIC_RAMP0_VMIC0_RAMP_DN_EN_ENABLE;
        }
    }
    else // vmic1
    {
        if(vmic_cfg.ramp_up_enbale)
        {
            DEV_ADC->VMIC_RAMP0 |= DEV_ADC_VMIC_RAMP0_VMIC1_RAMP_UP_EN_ENABLE;
        }
        else
        {
            DEV_ADC->VMIC_RAMP0 &= ~DEV_ADC_VMIC_RAMP0_VMIC1_RAMP_UP_EN_ENABLE;
        }

        if(vmic_cfg.ramp_down_enbale)
        {
            DEV_ADC->VMIC_RAMP0 |= DEV_ADC_VMIC_RAMP0_VMIC1_RAMP_DN_EN_ENABLE;
        }
        else
        {
            DEV_ADC->VMIC_RAMP0 &= ~DEV_ADC_VMIC_RAMP0_VMIC1_RAMP_DN_EN_ENABLE;
        }
    }
}

void pmu_vmic_set_voltage(vmic_enum vmic, vmic_config_struct vmic_cfg)
{
    if (vmic == VMIC0)
    {
        DEV_ADC->VMIC0_CTRL &= ~DEV_ADC_VMIC0_CTRL_VMIC0_VOL_MASK;
        DEV_ADC->VMIC0_CTRL |= (vmic_cfg.voltage << 4);
    }
    else // vmic1
    {
        DEV_ADC->VMIC1_CTRL &= ~DEV_ADC_VMIC1_CTRL_VMIC1_VOL_MASK;
        DEV_ADC->VMIC1_CTRL |= (vmic_cfg.voltage << 4);
    }
}

void pmu_control_charge_pump(Options_EnableEnum option)
{
    if (option == ENABLE)
    {
        DEV_DAC->CP_CTL |= DEV_DAC_CP_CTL_CP_EN_ENABLE;
    }
    else
    {
        DEV_DAC->CP_CTL &= ~DEV_DAC_CP_CTL_CP_EN_ENABLE;
    }
}

#if 0
void debug_adc_register(void)
{
    rt_kprintf("DEV_ADC->CFG:%x\r\n", DEV_ADC->CFG);
    rt_kprintf("DEV_ADC->MIC_CTRL0:%x\r\n", DEV_ADC->MIC_CTRL0);
    rt_kprintf("DEV_ADC->CHNn_CFG[0]:%x\r\n", DEV_ADC->CHNn_CFG[0]);
    rt_kprintf("DEV_ADC->MIX_CTRL0:%x\r\n", DEV_ADC->MIX_CTRL0);
    rt_kprintf("DEV_ADC->MIC_CTRL1:%x\r\n", DEV_ADC->MIC_CTRL1);
    rt_kprintf("DEV_ADC->MIX_CTRL1:%x\r\n", DEV_ADC->MIX_CTRL1);
    rt_kprintf("DEV_ADC->SDM_CTRL0:%x\r\n", DEV_ADC->SDM_CTRL0);
    rt_kprintf("DEV_ADC->SDM_CTRL1:%x\r\n", DEV_ADC->SDM_CTRL1);
    rt_kprintf("DEV_ADC->CTL:%x", DEV_ADC->CTL);
}
#endif
