/************************************************************************************************/
/**
* @file               adc_bsp.c
* @author             MCU Ecosystem Development Team
* @brief              ADC BSP驱动函数。
*
*
**************************************************************************************************
* @attention
* Copyright (c) CEC Huada Electronic Design Co.,Ltd. All rights reserved.
*
**************************************************************************************************
*/

/*------------------------------------------includes--------------------------------------------*/
#include "adc_bsp.h"

/*--------------------------------------------define--------------------------------------------*/
/* ADC参考电压为VDDA：3300mV。在实际应用中需根据真实的VDD电压值设置该值 */
#define VREF_ADC_VDDA_VOLTAGE               (3300U)

/* ADC采样次数，根据实际需求可调整此值 */
#define ADC_SAMPLE_NUM                      (10U)

/* 校准系数的最值 */
#define CALFACT_MAX                         (31)
#define CALFACT_MIN                         (-31)

/* ADC出厂校准值 */
#define ADC_COMPENSATION_VALUE              (*(int32_t *)(0x1FFF03CC))  

/*------------------------------------------functions-------------------------------------------*/
/**
* @brief  提升ADC校准系数的精度
* @retval 无
*/
void bsp_adc_software_calibrate(void)
{
    int32_t get_calfact = 0;

    /* ADC出厂校准值的相反数作为校准系数 */
    get_calfact = 0 - ADC_COMPENSATION_VALUE;
    
    /* 判断校准系数是否超限 */
    if(get_calfact > CALFACT_MAX)
    {
        get_calfact = CALFACT_MAX;
    }
    else if(get_calfact < CALFACT_MIN)
    {
        get_calfact = CALFACT_MIN;
    }
    std_adc_calibration_factor_config(get_calfact);
}

/**
* @brief  获取转换通道采样值
* @param  conversion_result 通道采样值
* @retval 无
*/
void bsp_adc_get_single_channel_sample_value(uint32_t *conversion_result)
{
    /* 启动转换 */
    std_adc_start_conversion();
    /* 等待channel转换完成 */
    while(std_adc_get_flag(ADC_FLAG_EOC) == 0U);
        
    /* 获取通道采样值 */
    *conversion_result = std_adc_get_conversion_value();
}

/**
* @brief  转换ADC通道采样值为实际电压值
* @retval uint32_t 转换结果
*/
uint32_t bsp_adc_get_channel_voltage(void)
{
    uint32_t get_sample_sum = 0;
    uint32_t get_channel_voltage = 0;
    uint32_t get_single_sample = 0;
    
    /* ADC多次采样取平均，提升采样精度 */
    for(uint8_t i = 0; i < ADC_SAMPLE_NUM; i++)
    {
        bsp_adc_get_single_channel_sample_value(&get_single_sample);
        get_sample_sum += get_single_sample;
    }
    
    /* 计算平均值 */
    get_single_sample = get_sample_sum / ADC_SAMPLE_NUM;
    
    /* 计算采样通道电压 */
    get_channel_voltage = get_single_sample * VREF_ADC_VDDA_VOLTAGE / ADC_CONVER_SCALE;

    return get_channel_voltage;
}

