#include "bsp_adc.h"
#include "string.h"
#include "stdbool.h"

#define CUMULATIVE_NUM 1
#define ADC_CHANNEL_NUM 2

volatile uint16_t adc_value[CUMULATIVE_NUM][ADC_CHANNEL_NUM];
uint16_t  adc_v[ADC_CHANNEL_NUM] = { 0 };

void read_adc_value(void)
{
    uint16_t sum = 0;

    for(uint8_t adc_channel_index = 0; adc_channel_index < ADC_CHANNEL_NUM; ++adc_channel_index)
    {
        sum = 0;
        for(uint8_t cumulative_index = 0; cumulative_index < CUMULATIVE_NUM; ++cumulative_index)
        {
            sum += adc_value[cumulative_index][adc_channel_index];
        }
        adc_v[adc_channel_index] = sum / CUMULATIVE_NUM;
    }
}

uint16_t GetAdcValue(uint8_t index)
{
    if(index < ADC_CHANNEL_NUM)
    {
        return adc_v[index];
    }
    else
    {
        return 0;
    }
}

void adc_init(void)
{
    /* system clocks configuration */
    rcu_config();
    /* GPIO configuration */
    gpio_config();
    /* DMA configuration */
    dma_config();
    /* ADC configuration */
    adc_config();
		adc_ordinary_software_trigger_enable(ADC1, TRUE);
}

/*!
  \brief      configure the different system clocks
  \param[in]  none
  \param[out] none
  \retval     none
  */
void rcu_config(void)
{
    /* enable GPIO clock */
    crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
		crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
    /* enable ADC clock */
    crm_periph_clock_enable(CRM_ADC1_PERIPH_CLOCK, TRUE);
    /* enable DMA0 clock */
		crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
 
}

/*!
  \brief      configure the GPIO peripheral
  \param[in]  none
  \param[out] none
  \retval     none
  */
void gpio_config(void)
{
	gpio_init_type gpio_init_struct;
	
	gpio_default_para_init(&gpio_init_struct);

  /* configure the IN8 pin */
  gpio_init_struct.gpio_mode = GPIO_MODE_ANALOG;
  gpio_init_struct.gpio_pins = GPIO_PINS_0;
  gpio_init(GPIOB, &gpio_init_struct);

  /* configure the IN9 pin */
  gpio_init_struct.gpio_mode = GPIO_MODE_ANALOG;
  gpio_init_struct.gpio_pins = GPIO_PINS_1;
  gpio_init(GPIOB, &gpio_init_struct);
}


/*!
  \brief      configure the DMA peripheral
  \param[in]  none
  \param[out] none
  \retval     none
  */
void dma_config(void)
{
	dma_init_type dma_init_struct;
	nvic_irq_enable(DMA1_Channel1_IRQn, 0, 0);

  dma_reset(DMA1_CHANNEL3);
  dma_default_para_init(&dma_init_struct);
  dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
	dma_init_struct.memory_base_addr = (uint32_t)(&adc_v);
  dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_HALFWORD;
  dma_init_struct.memory_inc_enable = TRUE;
	dma_init_struct.peripheral_base_addr = (uint32_t)&ADC1->odt;
  dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_HALFWORD;
  dma_init_struct.peripheral_inc_enable = FALSE;
	dma_init_struct.buffer_size = CUMULATIVE_NUM * ADC_CHANNEL_NUM;
  dma_init_struct.priority = DMA_PRIORITY_HIGH;
  dma_init_struct.loop_mode_enable = TRUE;
  dma_init(DMA1_CHANNEL3, &dma_init_struct);

  /* dmamux function enable */
  dmamux_enable(DMA1, TRUE);
  dmamux_init(DMA1MUX_CHANNEL3, DMAMUX_DMAREQ_ID_ADC1);
	dma_channel_enable(DMA1_CHANNEL3, TRUE);
}



/*!
  \brief      configure the ADC peripheral
  \param[in]  none
  \param[out] none
  \retval     none
  */
void adc_config(void)
{
		adc_base_config_type adc_base_struct;
		adc_common_config_type adc_common_struct;
		
		//common_settings
		crm_adc_clock_select(CRM_ADC_CLOCK_SOURCE_HCLK);
		
		adc_common_default_para_init(&adc_common_struct);  
		/* config adc clock division */
		adc_common_struct.div = ADC_HCLK_DIV_2;
		/* config inner temperature sensor and vintrv */
		adc_common_struct.tempervintrv_state = FALSE;
		adc_common_config(&adc_common_struct);  
		
			/* adc_settings------------------------------------------------------------------- */
		adc_base_default_para_init(&adc_base_struct);
		adc_base_struct.sequence_mode = TRUE;//序列模式
		adc_base_struct.repeat_mode = TRUE;//反复模式
		adc_base_struct.data_align = ADC_RIGHT_ALIGNMENT;//右对齐
		adc_base_struct.ordinary_channel_length = ADC_CHANNEL_NUM;
		adc_base_config(ADC1, &adc_base_struct);
		adc_resolution_set(ADC1, ADC_RESOLUTION_12B);

		/* adc_ordinary_conversionmode---------------------------------------------------- */
		adc_ordinary_channel_set(ADC1, ADC_CHANNEL_8, 1, ADC_SAMPLETIME_12_5);
		adc_ordinary_channel_set(ADC1, ADC_CHANNEL_9, 2, ADC_SAMPLETIME_12_5);
		
		adc_ordinary_conversion_trigger_set(ADC1, ADC_ORDINARY_TRIG_SOFTWARE, ADC_ORDINARY_TRIG_EDGE_NONE);//软件触发

		adc_dma_mode_enable(ADC1, TRUE);
		adc_dma_request_repeat_enable(ADC1, TRUE);
		

		adc_enable(ADC1, TRUE);
		while(adc_flag_get(ADC1, ADC_RDY_FLAG) == RESET);

		/* adc calibration---------------------------------------------------------------- */
		adc_calibration_init(ADC1);
		while(adc_calibration_init_status_get(ADC1));
		adc_calibration_start(ADC1);
		while(adc_calibration_status_get(ADC1));
}
