/************************************************************
  Copyright (C), 2025, cerlink Tech. Co., Ltd.
  FileName: test.cpp
  Author:   dufresne     Version :  1.0        Date:2025.09.15
  Description:     // 模块描述      
  Version:         // 版本信息
  Function List:   // 主要函数及其功能
    1. -------
  History:         // 历史修改记录
      <author>  <time>   <version >   <desc>
      David    96/10/12     1.0     build this moudle  
***********************************************************/

#include "drv_adc.h"
#include "tmp75.h"
#include "stdlib.h"
#include "string.h"
#include "gd32f4xx.h"
#include "gd32f4xx_adc.h"
#include "gd32f4xx_dma.h"
#include "rtthread.h"


void adc_config(void)
{
    /* 启用GPIOA时钟 */
    rcu_periph_clock_enable(RCU_GPIOC);
    /* 启用ADC0时钟 */
    rcu_periph_clock_enable(RCU_ADC1);


    // 复位ADC配置（可选，但建议初始化时做一次）
    adc_deinit();

    // adc_clock_config(ADC_ADCCK_PCLK2_DIV4);

    // 开启ADC
    adc_enable(ADCX);

    // 等待ADC稳定
    rt_thread_mdelay(100);

    // 执行ADC自校准
    adc_calibration_enable(ADCX);

    adc_clock_config(ADC_ADCCK_PCLK2_DIV4);

    /* 配置ADC引脚为模拟输入模式 */
    gpio_mode_set(ADC_GPIO_PORT, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, VOLTAGE_ADC_PIN);
    gpio_mode_set(ADC_GPIO_PORT, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, CURRENT_ADC_PIN);

    // 配置数据对齐方式为右对齐
    adc_data_alignment_config(ADCX, ADC_DATAALIGN_RIGHT);

    // 配置ADC分辨率：12位
    adc_resolution_config(ADCX, ADC_RESOLUTION_12B);

    // 打开扫描模式
    adc_special_function_config(ADCX, ADC_SCAN_MODE, ENABLE);
    
    // 禁止连续模式 -> 单次转换模式
    adc_special_function_config(ADCX, ADC_CONTINUOUS_MODE, DISABLE);

    /* ########## 设置转换通道序列 ########## */
    // 配置规则序列的长度：1个通道
    adc_channel_length_config(ADCX, ADC_ROUTINE_CHANNEL, ADC_CHANNEL_NUM);

}



// adc电压采集
float ptz_Voltage_collect_adc1_task()
{
    // 配置规则序列：序号0是电压通道，序号1是电流通道
    adc_routine_channel_config(ADCX, 0, VOLTAGE_ADC_CHANNEL, ADC_SAMPLETIME_480);

    // 使能外部触发：这里使用软件触发，所以先禁用硬件触发
    adc_external_trigger_config(ADCX, ADC_ROUTINE_CHANNEL, DISABLE);
    // 软件触发使能
    adc_software_trigger_enable(ADCX, ADC_ROUTINE_CHANNEL);


    static float adc1_v[LB_V_TIMES];
    static float curadc1_out_v;
    static uint8_t adc1_v_num;
    int j,k;
    float tem;
    float curadc1;
    uint16_t value_V = 0;

    while(adc_flag_get(ADCX, ADC_FLAG_EOC) == RESET); // 等待转换结束
    value_V = adc_routine_data_read(ADCX); // 读取规则组数据寄存器



    /* 间接测量，11倍分压/放大 */
    adc1_v[adc1_v_num] = (float)value_V / 4095.0 * 3.3;

    adc1_v_num++;
    if(adc1_v_num >= LB_V_TIMES)
    {
        adc1_v_num = 0;
        for(j = 0; j < LB_V_TIMES-1; j++)//采样值由小到大排列
        {
            for(k = 0; k < LB_V_TIMES-j-1; k++)
            {
                if(adc1_v[k] > adc1_v[k+1])
                {
                    tem         = adc1_v[k];
                    adc1_v[k]   = adc1_v[k+1];
                    adc1_v[k+1] = tem;
                }
            }
        }
        for(uint8_t i = 1; i < LB_V_TIMES - 1; i++)
        {
            curadc1 = curadc1 + adc1_v[i];
        }
        curadc1 = curadc1 /((float)(LB_V_TIMES - 2));//去掉一个最大值和一个最小值求平均值
        // g_ptz.Voltage =  curadc1;
        memset(adc1_v, 0, sizeof(adc1_v));//adc1_v 快速清零
        curadc1_out_v = curadc1;
    }
    return curadc1_out_v;
}


// adc电流采集
float ptz_Current_collect_adc1_task()
{
    // 配置规则序列：序号0是电压通道，序号1是电流通道
    adc_routine_channel_config(ADCX, 0, CURRENT_ADC_CHANNEL, ADC_SAMPLETIME_480);

    // 使能外部触发：这里使用软件触发，所以先禁用硬件触发
    adc_external_trigger_config(ADCX, ADC_ROUTINE_CHANNEL, DISABLE);
    // 软件触发使能
    adc_software_trigger_enable(ADCX, ADC_ROUTINE_CHANNEL);


    static float adc1_i[LB_I_TIMES];
    static float curadc1_out_i;
    static uint8_t adc1_i_num;
    int j,k;
    float tem;
    float curadc1;
    uint16_t value_I = 0;

    while(adc_flag_get(ADCX, ADC_FLAG_EOC) == RESET); // 等待转换结束
    value_I = adc_routine_data_read(ADCX); // 读取规则组数据寄存器

    /* 间接测量，11倍分压/放大 */
    adc1_i[adc1_i_num] = (((float)value_I / 4096.0  * 3.3) - 3.3 / 2) / 0.132;

    adc1_i_num++;
    if(adc1_i_num >= LB_I_TIMES)
    {
        adc1_i_num = 0;
        for(j = 0; j < LB_I_TIMES-1; j++)//采样值由小到大排列
        {
            for(k = 0; k < LB_I_TIMES-j-1; k++)
            {
                if(adc1_i[k] > adc1_i[k+1])
                {
                    tem         = adc1_i[k];
                    adc1_i[k]   = adc1_i[k+1];
                    adc1_i[k+1] = tem;
                }
            }
        }
        for(uint8_t i = 1; i < LB_I_TIMES - 1; i++)
        {
            curadc1 = curadc1 + adc1_i[i];
        }
        curadc1 = curadc1 /((float)(LB_I_TIMES - 2));//去掉一个最大值和一个最小值求平均值
        // g_ptz.Voltage =  curadc1;
        memset(adc1_i, 0, sizeof(adc1_i));//adc1_i 快速清零
        curadc1_out_i = curadc1;
    }

    return curadc1_out_i;
}


//温度采集
float ptz_temperature_collect_tmp75_task()
{
    static float tmp75[5];
    static unsigned char tmp75_num;
    static float curtmp75_out;
    float curtmp75;
    float tem;
    int j,k;
    tmp75[tmp75_num] = tmp75_read_temp();
    tmp75_num ++;

    if(tmp75_num >= LB_T_TIMES)
    {
        tmp75_num = 0;
        for(j = 0; j < LB_T_TIMES-1; j++)//采样值由小到大排列
        {
            for(k = 0; k < LB_T_TIMES-j-1; k++)
            {
                if(tmp75[k] > tmp75[k+1])
                {
                    tem        = tmp75[k];
                    tmp75[k]   = tmp75[k+1];
                    tmp75[k+1] = tem;
                }
            }
        }
        for(uint8_t i = 1; i < LB_T_TIMES - 1; i++)
        {
            curtmp75 = curtmp75 + tmp75[i];//去掉一个最大值和一个最小值
        }
        curtmp75 = curtmp75 / ((float)(LB_T_TIMES - 2));
        curtmp75_out = curtmp75;
        memset(tmp75, 0, sizeof(tmp75));
    }
    return curtmp75_out;
}
