/************************************************************************************************/
/**
* @file               common.c
* @author             MCU Ecosystem Development Team
* @brief              通用函数或本外设相关的配置实现函数。
*
*
**************************************************************************************************
* @attention
* Copyright (c) CEC Huada Electronic Design Co.,Ltd. All rights reserved.
*
**************************************************************************************************
*/

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

/*------------------------------------------define----------------------------------------------*/
/* ADC校准次数，根据实际需求可调整此值 */
#define ADC_CALIBRATION_NUM                 (8U)

/*------------------------------------------functions-------------------------------------------*/
/**
* @brief  系统时钟配置
* @retval 无
*/
void system_clock_config(void)
{
    uint32_t ahbdiv_tmp;
    
    /* 设置Flash读访问等待时间 */
    std_flash_set_latency(FLASH_LATENCY_1CLK);

    /* 使能RCH */
    std_rcc_rch_enable();
    while(!std_rcc_get_rch_ready());
    
    /* 备份AHB分频参数 */
    ahbdiv_tmp = std_rcc_get_ahbdiv();    
    /* 配置AHB最大分频：128分频 */
    std_rcc_set_ahbdiv(RCC_HCLK_DIV128);  
    
    /* 切换RCH4到RCH48 */    
    std_rcc_set_rch_source(RCC_RCH_FREQ_48M);
    
    /* 恢复AHB分频参数 */
    std_rcc_set_ahbdiv(ahbdiv_tmp);  

    /* 设置系统时钟源为RCH */
    std_rcc_set_sysclk_source(RCC_SYSCLK_SRC_RCH);
    while(std_rcc_get_sysclk_source() != RCC_SYSCLK_SRC_STATUS_RCH);

    /* 设置AHB分频因子 */
    std_rcc_set_ahbdiv(RCC_HCLK_DIV1);
    /* 设置APB分频因子 */
    std_rcc_set_apbdiv(RCC_PCLK_DIV1);
    
    SystemCoreClockUpdate();
}


/**
* @brief  ADC初始化配置函数
* @retval 无
*/
void adc_init(void)
{
    std_adc_init_t adc_config = {0};

    /* 使能ADC时钟 */
    std_rcc_apb2_clk_enable(RCC_PERIPH_CLK_ADC);

    /* ADC初始化配置 */
    adc_config.clock_presc    = ADC_CLK_DIV3;                        /* ADC时钟, 3分频 */
    adc_config.conver_mode    = ADC_SINGLE_CONVER_MODE;              /* 单次转换模式 */
    adc_config.overrun_mode   = ADC_OVRN_MODE_OVERWRITTEN;           /* 数据溢出模式: 数据覆盖 */
    adc_config.trigger_edge   = ADC_TRIG_SW;                         /* 软件触发 */
    adc_config.sampt          = ADC_SAMPTIME_119CYCLES;              /* 采样时间设置为119CLK */
    adc_config.scan_dir       = ADC_SCAN_DIR_FORWARD;                /* 正向扫描 */
    std_adc_init(&adc_config);
    
    /* 选择通道6 */
    std_adc_fix_sequence_channel_enable(ADC_CHANNEL_6);
    
    /* 使能DMA */
    std_adc_dma_enable();
    
    /* 配置wait模式，避免数据未及时读取，转换溢出 */
    std_adc_wait_mode_enable();

    /* ADC选择间歇工作模式 */
    std_adc_mode_config(ADC_MODE_INTERVAL);
    
    /* 使能ADC */
    std_adc_enable();

    /* 等待ADC使能状态稳定 */
    std_delayus(ADC_EN_DELAY);

    /* 清除ADC转换状态，确保之前状态不影响转换 */
    std_adc_clear_flag(ADC_FLAG_ALL);
}


/**
* @brief  GPIO初始化
* @retval 无
*/
void gpio_init(void)
{
    std_gpio_init_t adc_gpio_config = {0};

    /* 使能GPIOF时钟 */
    std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOF);
    
    /* ADC_IN6输入通道配置：PF2 */
    adc_gpio_config.pin = GPIO_PIN_2;
    adc_gpio_config.mode = GPIO_MODE_ANALOG;
    std_gpio_init(GPIOF, &adc_gpio_config);
}


/**
* @brief  DMA初始化
* @retval 无
*/
void dma_init(void)
{
    std_dma_init_t dma_init_param = {0};
    
    /* DMA外设时钟使能 */
    std_rcc_ahb_clk_enable(RCC_PERIPH_CLK_DMA);
    
    /* dma_init 结构体初始化 */
    dma_init_param.dma_channel      = DMA_CHANNEL_0;
    dma_init_param.transfer_type    = DMA_BLOCK_TRANSFER;
    dma_init_param.dma_req_id       = DMA_REQUEST_ADC;
    dma_init_param.src_addr_inc     = DMA_SRC_INC_DISABLE;
    dma_init_param.dst_addr_inc     = DMA_DST_INC_ENABLE;
    dma_init_param.data_size        = DMA_DATA_SIZE_HALFWORD;
    dma_init_param.mode             = DMA_MODE_CIRCULAR;
    
    /* DMA初始化 */
    std_dma_init(&dma_init_param);
    
    /* 使能传输完成中断及传输错误中断 */
    std_dma_interrupt_enable(DMA_CHANNEL_0, DMA_INTERRUPT_TF | DMA_INTERRUPT_TE);
}

/**
* @brief  NVIC初始化
* @retval 无
*/
void nvic_init(void)
{
    /* DMA的NVIC中断初始化 */
    NVIC_SetPriority(DMA_Channel0_IRQn, NVIC_PRIO_0);    
    NVIC_EnableIRQ(DMA_Channel0_IRQn);
}

