/******************************************************************************
 * file    Core/Src/ADC_collect.c 
 * author  YuLiang
 * version 1.0.0
 * date    20-Jun-2022
 * brief   This file provides all the ADC collect related operation functions.
 ******************************************************************************
 * Attention
 *
 * <h2><center>&copy; COPYRIGHT(c) 2022 LandPower</center></h2>
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *   1. Redistributions of source code must retain the above copyright notice,
 *      this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright notice,
 *      this list of conditions and the following disclaimer in the documentation
 *      and/or other materials provided with the distribution.
 *   3. Neither the name of WTOE nor the names of its contributors may be used to 
 *      endorse or promote products derived from this software without specific
 *      prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 ******************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "math.h"

#include "spi.h"
#include "adc.h"
#include "tim.h"

#include "common.h"
#include "dev_config.h"
#include "RS485_sensor.h"
#include "ADC_collect.h"
#include "flash_log.h"
#include "position.h"

/* Private define ------------------------------------------------------------*/
#define ADC_COMP_TIMEOUT 5              // ADC 采样超时时间.
#define ADC_ERR_MAX 3                   // ADC 采样错误最大计数.

#define ADC_ST_START 0x01               // ADC 采样开始.
#define ADC_ST_END 0x02                 // ADC 采样结束.
#define ADC_ST_ERROR 0x04               // ADC 采样错误.

#define ADCi_COMP_TIMEOUT 1000          // ADCi 采样超时时间.
#define ADCi_ERR_MAX 3                  // ADCi 采样错误最大计数.
#define ADCi_VREF 2560                  // ADCi 采样参考电压, 单位: mv.
#define ADCi_RESOLUTION 4096            // ADCi 采样分辨率.
#define ADCi_VBAT_MUL 2                 // ADCi 采样 VBAT 的倍数..

#define ADCi_ST_START 0x01              // ADCi 采样开始.
#define ADCi_ST_END 0x02                // ADCi 采样结束.
#define ADCi_ST_ERROR 0x04              // ADCi 采样错误.

/* Private typedef -----------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* ADC 任务参数. */
const osThreadAttr_t ADC_attributes =
{
    .name = "ADC",
    .stack_size = 160 * 4,
    .priority = (osPriority_t) osPriorityRealtime,
};

/* ADCi 表示单片机内部 ADC, 不带 'i' 的表示外部 ADC 芯片. */
ADC_ctrl_t ADC_ctrl;
static fd_date_t ADC_data;

/* Private function prototypes -----------------------------------------------*/
/* Internal functions --------------------------------------------------------*/
/* 初始化 ADCi 温度传感器校准数据. */
static void _ADCi_temp_sensor_init(void)
{
    uint16_t t30_value = *(uint16_t*)0x1FFF75A8;
    uint16_t t130_value = *(uint16_t*)0x1FFF75CA;

    /* 计算温度传感器计算参数. */
    ADC_ctrl.ADCi_param1 = 600 * t30_value;
    ADC_ctrl.ADCi_param2 = 6 * (t130_value - t30_value);
}

/* 计算 ADCi 的采样值. */
static void _ADCi_calculate(void)
{
    ADC_ctrl_t *ADC = &ADC_ctrl;
    uint8_t ch = 0;
    uint8_t i = 0;
    uint8_t index = 0;
    uint16_t min = 0xffff;
    uint16_t max = 0;
    uint16_t avg = 0;

    /* 遍历通道. */
    for(ch = 0; ch < ADCi_CH_CNT; ch++)
    {
        min = 0xffff;
        max = 0;
        avg = 0;
        /* 遍历通道所有值, 求和, 并计算出最大值和最小值. */
        for(i = 0; i < ADCi_COLLECT_CNT; i++)
        {
            index = i * ADCi_CH_CNT + ch;
            if (ADC->ADCi_value[index] > max)
            {
                max = ADC->ADCi_value[index];
            }
            if (ADC->ADCi_value[index] < min)
            {
                min = ADC->ADCi_value[index];
            }
            avg += ADC->ADCi_value[index];
        }

        /* 计算平均值, 去掉最小值和最大值. */
        ADC->ADCi_value[ch] = (avg - max - min) / (ADCi_COLLECT_CNT - 2);
    }

    /* 根据 ADC 采样值计算真正的温度和电池电压值. */
    ADC->ADCi_temp = (int32_t)(500 * ADC->ADCi_value[ADCi_CH_TEMP] - ADC->ADCi_param1) * 10 / ADC->ADCi_param2 + 300;
    ADC->ADCi_vbat = (uint32_t)ADC->ADCi_value[ADCi_CH_VBAT] * dev_config.vin_adj / ADCi_RESOLUTION;
    ADC->ADCi_vin = (uint32_t)ADC->ADCi_value[ADCi_CH_VIN] * dev_config.vin_adj / ADCi_RESOLUTION;
    ADC->ADCi_vsc = (uint32_t)ADC->ADCi_value[ADCi_CH_VSC] * dev_config.vin_adj / ADCi_RESOLUTION;
}

/* 关闭 ADCi 采样模块. */
static void _ADCi_stop(uint8_t state)
{
    /* 关闭 ADCi 模块 */
    ADC_ctrl.ADCi_state |= state;

    /* 工厂模式不关闭外设. */
    if (!ADC_ctrl.continue_mode)
    {
        HAL_ADC_Stop_IT(ADC_ctrl.ADCi_adc);
        HAL_ADC_DeInit(ADC_ctrl.ADCi_adc);
    }
    ADC_ctrl.ADCi_cnt = 0;

    /* 错误时, 设置采样值为无效值. */
    if (ADCi_ST_ERROR == state)
    {
        ADC_ctrl.ADCi_temp = INVALID_DATE_16;
        ADC_ctrl.ADCi_vbat = INVALID_DATA_U16;
        ADC_ctrl.ADCi_vin = INVALID_DATA_U16;
        ADC_ctrl.ADCi_vsc = INVALID_DATA_U16;
    }
}

/* 关闭 ADCi 采样. */
static void _ADCi_collect_stop(void)
{
    /* 关闭 ADC 中断. */
    HAL_ADC_Stop_IT(ADC_ctrl.ADCi_adc);
    /* 还原变量. */
    ADC_ctrl.ADCi_err_cnt++;
    ADC_ctrl.ADCi_cnt = 0;  
}

/* 内部 ADC 采集温度和电池电压. */
static int32_t _ADCi_collect(void)
{
    uint32_t notify_value = 0;
    uint32_t tick = 0;

    /* 采集完成后, 再次进入函数后会直接退出. */
    if (ADC_ctrl.ADCi_state & (ADCi_ST_ERROR | ADCi_ST_END))
    {
        return HAL_OK;
    }

    /* 多次错误直接关闭采样. */
    if (ADCi_ERR_MAX == ADC_ctrl.ADCi_err_cnt)
    {
        vty_print("ADCi error!\r\n");
        _ADCi_stop(ADCi_ST_ERROR);
        return HAL_ERROR;
    }

    /* 开始 ADC 采样. */
    HAL_ADC_Start_IT(ADC_ctrl.ADCi_adc);

    tick = HAL_GetTick();
    while(1)
    {
        /* 等待采样完成. */
        notify_value = ulTaskNotifyTake(pdTRUE, ADCi_COMP_TIMEOUT);
        /* 采样超时, 重新开始采样. */
        if (MONITOR_ADCi_NOTIFY_OK == notify_value)
        {
            break;
        }

        if (HAL_GetTick() - tick > ADCi_COMP_TIMEOUT)
        {
            vty_print("ADCi timeout!\r\n");
            _ADCi_collect_stop();
            return HAL_TIMEOUT;
        }
    }
    
    /* 关闭 ADCi 模块. */
    _ADCi_stop(ADCi_ST_END);
    /* 计算 ADCi 的采样值. */
    _ADCi_calculate();

    /* 超级电容电压小于 3.3V 设备不启动. */
    //if (ADC_ctrl.ADCi_vsc < 3300 && DEV_TYPE_CT == dev_info.type_s)
    //{
    //    system_shtudown(600);
    //}
    //else if(ADC_ctrl.ADCi_vbat < 3000 && DEV_TYPE_BAT == dev_info.type_s)
    //{
    //   system_shtudown(7200);
    //}

    return HAL_OK;
}

/* 内部 ADC 采样初始化. */
static void _ADCi_init(void)
{
    /* 已开始不用再初始化. */
    if (ADC_ctrl.ADCi_state & ADCi_ST_START)
    {
        return;
    }

    ADC_ctrl.ADCi_adc = &hadc1;
    /* 初始化 ADCi 温度传感器的内部校准系数. */
    _ADCi_temp_sensor_init();
    /* 校准 ADCi, 提高 ADCi 精度. */    
    HAL_ADCEx_Calibration_Start(ADC_ctrl.ADCi_adc, ADC_SINGLE_ENDED);

    ADC_ctrl.ADCi_state |= ADCi_ST_START;
    osDelay(1000);
}

/* CT 取电下判断电源工作模式. */
static void _ADC_energy_calculate_ct(void)
{
    ADC_ctrl_t *ADC = &ADC_ctrl;
    uint32_t sleep_time = 600;
    uint8_t is_save = FALSE;
    uint8_t main_cable = 0;

    main_cable = dev_config.main_cable;
    if (main_cable > 6)
    {
        main_cable = 4;
    }
    else if (main_cable != 0)
    {
        /* main_cable 范围是 0-5, 而 dev_config.main_cable 为 1-6*/
        main_cable--;
    }

    if (ADC->ADCi_temp < -150 && st_data.is_bat_charge)
    {
        st_data.is_bat_charge = FALSE;
        is_save = TRUE;
    }
    else if(ADC->ADCi_temp >= -130 && !st_data.is_bat_charge)
    {
        st_data.is_bat_charge = TRUE;
        is_save = TRUE;
    }

    if (st_data.is_bat_charge
        && GPIO_PIN_SET == HAL_GPIO_ReadPin(BAT_CHECK_GPIO_Port, BAT_CHECK_Pin))
    {
        /* 开始充电. */
        HAL_GPIO_WritePin(BAT_CHARGE_GPIO_Port, BAT_CHARGE_Pin, GPIO_PIN_RESET);
        HAL_GPIO_WritePin(BAT_CLK_GPIO_Port, BAT_CLK_Pin, GPIO_PIN_SET);
        osDelay(10);
        HAL_GPIO_WritePin(BAT_CLK_GPIO_Port, BAT_CLK_Pin, GPIO_PIN_RESET);
    }
    else if((!st_data.is_bat_charge)
        && GPIO_PIN_RESET == HAL_GPIO_ReadPin(BAT_CHECK_GPIO_Port, BAT_CHECK_Pin))
    {
        /* 停止充电. */
        HAL_GPIO_WritePin(BAT_CHARGE_GPIO_Port, BAT_CHARGE_Pin, GPIO_PIN_SET);
        HAL_GPIO_WritePin(BAT_CLK_GPIO_Port, BAT_CLK_Pin, GPIO_PIN_SET);
        osDelay(10);
        HAL_GPIO_WritePin(BAT_CLK_GPIO_Port, BAT_CLK_Pin, GPIO_PIN_RESET);
    }

    /* 确定工作模式. */
    if (dev_config.energy_mode != ADC_ENERGY_AUTO)
    {
        ADC->energy_mode = dev_config.energy_mode;
    }
    else if (ADC->ADC_elec[main_cable] >= 20000
        && dev_config.main_cable != 0
        && dev_config.is_voltage_col
        && ADC->ADCi_vbat > 2800)
    {
        ADC->energy_mode = ADC_ENERGY_NORMAL;
    }
    else if((ADC->ADCi_vbat >= 3600)
        || (ADC->ADCi_vbat >= 3400 && ADC_ENERGY_NORMAL == st_data.energy_mode))
    {
        ADC->energy_mode = ADC_ENERGY_NORMAL;
    }
    else if (ADC->ADCi_vbat > 2800)
    {
        ADC->energy_mode = ADC_ENERGY_SLEEP;
    }
    else
    {
        flash_log_write(FLASH_LOG_TYPE_WARNING, "CT to force sleep %ds!\r\n", sleep_time);
        common_sys_set(COM_SYS_SHUTDOWN, (void*)&sleep_time);
        osDelay(10000);
    }
    
    if (is_save)
    {
        st_write(&st_data);
    }
}

/* 电池供电下判断电源工作模式. */
static void _ADC_energy_calculate_bat(void)
{
    ADC_ctrl_t *ADC = &ADC_ctrl;
    uint8_t is_save = FALSE;

    if (ADC->ADCi_temp < -150 && st_data.is_bat_charge)
    {
        st_data.is_bat_charge = FALSE;
        is_save = TRUE;
    }
    else if(ADC->ADCi_temp >= -130 && !st_data.is_bat_charge)
    {
        st_data.is_bat_charge = TRUE;
        is_save = TRUE;
    }

    if (st_data.is_bat_charge
        && GPIO_PIN_SET == HAL_GPIO_ReadPin(BAT_CHECK_GPIO_Port, BAT_CHECK_Pin))
    {
        /* 开始充电. */
        HAL_GPIO_WritePin(BAT_CHARGE_GPIO_Port, BAT_CHARGE_Pin, GPIO_PIN_RESET);
        HAL_GPIO_WritePin(BAT_CLK_GPIO_Port, BAT_CLK_Pin, GPIO_PIN_SET);
        osDelay(10);
        HAL_GPIO_WritePin(BAT_CLK_GPIO_Port, BAT_CLK_Pin, GPIO_PIN_RESET);
    }
    else if((!st_data.is_bat_charge)
        && GPIO_PIN_RESET == HAL_GPIO_ReadPin(BAT_CHECK_GPIO_Port, BAT_CHECK_Pin))
    {
        /* 停止充电. */
        HAL_GPIO_WritePin(BAT_CHARGE_GPIO_Port, BAT_CHARGE_Pin, GPIO_PIN_SET);
        HAL_GPIO_WritePin(BAT_CLK_GPIO_Port, BAT_CLK_Pin, GPIO_PIN_SET);
        osDelay(10);
        HAL_GPIO_WritePin(BAT_CLK_GPIO_Port, BAT_CLK_Pin, GPIO_PIN_RESET);
    }

    /* 确定工作模式. */
    if (dev_config.energy_mode != ADC_ENERGY_AUTO)
    {
        ADC->energy_mode = dev_config.energy_mode;
    }
    else if((ADC->ADCi_vbat >= 3600)
        || (ADC->ADCi_vbat >= 3400 && ADC_ENERGY_NORMAL == st_data.energy_mode))
    {
        ADC->energy_mode = ADC_ENERGY_NORMAL;
    }
    else
    {
        ADC->energy_mode = ADC_ENERGY_SLEEP;
    }
    
    if (is_save)
    {
        st_write(&st_data);
    }
}

/* 电池供电下判断电源工作模式. */
static void _ADC_energy_calculate_csg(void)
{
    ADC_ctrl_t *ADC = &ADC_ctrl;
    uint32_t sleep_time = 600;
    uint8_t is_save = FALSE;

    if (ADC->ADCi_temp < -150 && st_data.is_bat_charge)
    {
        st_data.is_bat_charge = FALSE;
        is_save = TRUE;
    }
    else if(ADC->ADCi_temp >= -130 && !st_data.is_bat_charge)
    {
        st_data.is_bat_charge = TRUE;
        is_save = TRUE;
    }

    if (st_data.is_bat_charge
        && GPIO_PIN_SET == HAL_GPIO_ReadPin(BAT_CHECK_GPIO_Port, BAT_CHECK_Pin))
    {
        /* 开始充电. */
        HAL_GPIO_WritePin(BAT_CHARGE_GPIO_Port, BAT_CHARGE_Pin, GPIO_PIN_RESET);
        HAL_GPIO_WritePin(BAT_CLK_GPIO_Port, BAT_CLK_Pin, GPIO_PIN_SET);
        osDelay(10);
        HAL_GPIO_WritePin(BAT_CLK_GPIO_Port, BAT_CLK_Pin, GPIO_PIN_RESET);
    }
    else if((!st_data.is_bat_charge)
        && GPIO_PIN_RESET == HAL_GPIO_ReadPin(BAT_CHECK_GPIO_Port, BAT_CHECK_Pin))
    {
        /* 停止充电. */
        HAL_GPIO_WritePin(BAT_CHARGE_GPIO_Port, BAT_CHARGE_Pin, GPIO_PIN_SET);
        HAL_GPIO_WritePin(BAT_CLK_GPIO_Port, BAT_CLK_Pin, GPIO_PIN_SET);
        osDelay(10);
        HAL_GPIO_WritePin(BAT_CLK_GPIO_Port, BAT_CLK_Pin, GPIO_PIN_RESET);
    }

    /* 确定工作模式. 默认第 4 路数据是主缆电流 */
    if (dev_config.energy_mode != ADC_ENERGY_AUTO)
    {
        ADC->energy_mode = dev_config.energy_mode;
    }
    else if (ADC->ADCi_vbat <= 2800)
    {
        flash_log_write(FLASH_LOG_TYPE_WARNING, "V to force sleep %ds!\r\n", sleep_time);
        common_sys_set(COM_SYS_SHUTDOWN, (void*)&sleep_time);
        osDelay(10000);
    }
    else
    {
        ADC->energy_mode = ADC_ENERGY_NORMAL;
    }
    
    if (is_save)
    {
        st_write(&st_data);
    }
}

/* 稳定电源供电下判断电源工作模式. */
static void _ADC_energy_calculate_acdc(void)
{
    ADC_ctrl_t *ADC = &ADC_ctrl;

    /* 确定工作模式. 默认第 4 路数据是主缆电流 */
    if (dev_config.energy_mode != ADC_ENERGY_AUTO)
    {
        ADC->energy_mode = dev_config.energy_mode;
    }
    else
    {
        ADC->energy_mode = ADC_ENERGY_NORMAL;
    }
}

/* CT 取电下判断电源工作模式. */
static void _ADC_energy_calculate_scap(void)
{
    ADC_ctrl_t *ADC = &ADC_ctrl;
    uint32_t sleep_time = 600;
    uint8_t main_cable = 0;

    main_cable = dev_config.main_cable;
    if (main_cable > 6)
    {
        main_cable = 4;
    }
    else if (main_cable != 0)
    {
        /* main_cable 范围是 0-5, 而 dev_config.main_cable 为 1-6*/
        main_cable--;
    }

    //if (ADC->ADCi_vbat > 4100 && st_data.is_bat_charge)
    //{
    //    st_data.is_bat_charge = FALSE;
    //}
    //else if(ADC->ADCi_vbat < 3900 && !st_data.is_bat_charge)
    {
        st_data.is_bat_charge = TRUE;
    }

    if (st_data.is_bat_charge
        && GPIO_PIN_SET == HAL_GPIO_ReadPin(BAT_CHECK_GPIO_Port, BAT_CHECK_Pin))
    {
        /* 开始充电. */
        HAL_GPIO_WritePin(BAT_CHARGE_GPIO_Port, BAT_CHARGE_Pin, GPIO_PIN_RESET);
        HAL_GPIO_WritePin(BAT_CLK_GPIO_Port, BAT_CLK_Pin, GPIO_PIN_SET);
        osDelay(10);
        HAL_GPIO_WritePin(BAT_CLK_GPIO_Port, BAT_CLK_Pin, GPIO_PIN_RESET);
    }
    else if((!st_data.is_bat_charge)
        && GPIO_PIN_RESET == HAL_GPIO_ReadPin(BAT_CHECK_GPIO_Port, BAT_CHECK_Pin))
    {
        /* 停止充电. */
        HAL_GPIO_WritePin(BAT_CHARGE_GPIO_Port, BAT_CHARGE_Pin, GPIO_PIN_SET);
        HAL_GPIO_WritePin(BAT_CLK_GPIO_Port, BAT_CLK_Pin, GPIO_PIN_SET);
        osDelay(10);
        HAL_GPIO_WritePin(BAT_CLK_GPIO_Port, BAT_CLK_Pin, GPIO_PIN_RESET);
    }

    /* 确定工作模式. */
    if (dev_config.energy_mode != ADC_ENERGY_AUTO)
    {
        ADC->energy_mode = dev_config.energy_mode;
    }
    else if (ADC->ADC_elec[main_cable] >= 20000
        && dev_config.main_cable != 0
        && dev_config.is_voltage_col
        && ADC->ADCi_vbat > 2800)
    {
        ADC->energy_mode = ADC_ENERGY_NORMAL;
    }
    else if((ADC->ADCi_vbat >= 3600)
        || (ADC->ADCi_vbat >= 3400 && ADC_ENERGY_NORMAL == st_data.energy_mode))
    {
        ADC->energy_mode = ADC_ENERGY_NORMAL;
    }
    else if (ADC->ADCi_vbat > 2800)
    {
        ADC->energy_mode = ADC_ENERGY_SLEEP;
    }
    else
    {
        flash_log_write(FLASH_LOG_TYPE_WARNING, "SCAP to force sleep %ds!\r\n", sleep_time);
        common_sys_set(COM_SYS_SHUTDOWN, (void*)&sleep_time);
        osDelay(10000);
    }
}

/* 故障定位模式判断电源工作模式. */
static void _ADC_energy_calculate_ct_p(void)
{
    ADC_ctrl_t *ADC = &ADC_ctrl;
    uint32_t sleep_time = 0;
    uint8_t is_save = FALSE;

    /* 电压小于等于 2.8V 时，休眠 10 分钟 */
    if (ADC->ADCi_vbat <= 2800)
    {
        sleep_time = 600;
    }

    if (ADC->ADCi_temp < -150 && st_data.is_bat_charge)
    {
        st_data.is_bat_charge = FALSE;
        is_save = TRUE;
    }
    else if(ADC->ADCi_temp >= -130 && !st_data.is_bat_charge)
    {
        st_data.is_bat_charge = TRUE;
        is_save = TRUE;
    }

    if (st_data.is_bat_charge
        && GPIO_PIN_SET == HAL_GPIO_ReadPin(BAT_CHECK_GPIO_Port, BAT_CHECK_Pin))
    {
        /* 开始充电. */
        HAL_GPIO_WritePin(BAT_CHARGE_GPIO_Port, BAT_CHARGE_Pin, GPIO_PIN_RESET);
        HAL_GPIO_WritePin(BAT_CLK_GPIO_Port, BAT_CLK_Pin, GPIO_PIN_SET);
        osDelay(10);
        HAL_GPIO_WritePin(BAT_CLK_GPIO_Port, BAT_CLK_Pin, GPIO_PIN_RESET);
    }
    else if((!st_data.is_bat_charge)
        && GPIO_PIN_RESET == HAL_GPIO_ReadPin(BAT_CHECK_GPIO_Port, BAT_CHECK_Pin))
    {
        /* 停止充电. */
        HAL_GPIO_WritePin(BAT_CHARGE_GPIO_Port, BAT_CHARGE_Pin, GPIO_PIN_SET);
        HAL_GPIO_WritePin(BAT_CLK_GPIO_Port, BAT_CLK_Pin, GPIO_PIN_SET);
        osDelay(10);
        HAL_GPIO_WritePin(BAT_CLK_GPIO_Port, BAT_CLK_Pin, GPIO_PIN_RESET);
    }

    /* 故障定位只有正常模式 */
    ADC->energy_mode = ADC_ENERGY_NORMAL;

    if (is_save)
    {
        st_write(&st_data);
    }

    if (sleep_time)
    {
        flash_log_write(FLASH_LOG_TYPE_WARNING, "POSITION to force sleep %ds!\r\n", sleep_time);
        common_sys_set(COM_SYS_SHUTDOWN, (void*)&sleep_time);
        osDelay(10000);
    }
}

/* 判断电源工作模式. */
static void _ADC_energy_calculate(void)
{
    if (DEV_TYPE_CT == dev_info.type_s)
    {
        _ADC_energy_calculate_ct();
    }
    else if(DEV_TYPE_BAT == dev_info.type_s)
    {
        _ADC_energy_calculate_bat();
    }
    else if(DEV_TYPE_CSG == dev_info.type_s)
    {
        _ADC_energy_calculate_csg();
    }
    else if(DEV_TYPE_SCAP == dev_info.type_s)
    {
        _ADC_energy_calculate_scap();
    }
    else if (DEV_TYPE_CT_P == dev_info.type_s)
    {
        _ADC_energy_calculate_ct_p();
    }
    else
    {
        _ADC_energy_calculate_acdc();
    }

    if (st_data.energy_mode != ADC_ctrl.energy_mode)
    {
        st_data.energy_mode = ADC_ctrl.energy_mode;
        st_write(&st_data);
        flash_log_write(FLASH_LOG_TYPE_NOTIFY, "Energy is change to %s!\r\n", energy_str[st_data.energy_mode]);
    }
}

/* 工频 buffer 赋值, 5 次采样取一次最大值. */
static void _ADC_buffer_set(void)
{
    uint8_t ch = 0;

    /* 将值赋值给buf. */
    for(ch = 0; ch < CFG_ADC_CH_CNT; ch++)
    {
        /* 对 buf 赋值. */
        ADC_ctrl.ADC_value[ch][ADC_ctrl.ADC_index] = ADC_ctrl.ADC_buf[ch];
    }

    /* 重置变量. */
    ADC_ctrl.ADC_index++;
}

/* 计算 ADC 的采样值. */
static void _ADC_calculate(void)
{
    ADC_ctrl_t *ADC = &ADC_ctrl;
    uint8_t ch = 0;
    uint8_t adj = 0;
    uint16_t i = 0;
    uint64_t square_sum = 0;
    int32_t mean_sum = 0;
    float temp = 0;
    uint8_t main_cable = 0;
    uint8_t first_col = TRUE;

    /*  */
    main_cable = dev_config.main_cable;
    if (main_cable > 8)
    {
        main_cable = 4;
    }
    else if (main_cable != 0)
    {
        /* main_cable 范围是 0-7, 而 dev_config.main_cable 为 1-8*/
        main_cable--;
    }

    /* 遍历通道. */
    for(ch = 0; ch < CFG_ADC_CH_CNT; ch++)
    {
        square_sum = 0;
        mean_sum = 0;
        /* 遍历通道所有值, 求和, 并计算出最大值和最小值. */
        for(i = 0; i < ADC_COLLECT_CNT; i++)
        {
            square_sum += ADC->ADC_value[ch][i] * ADC->ADC_value[ch][i];
            mean_sum += ADC->ADC_value[ch][i];
        }

        /* 根据数据查找数据落在哪个分段点上. */
        temp = (double)sqrt(square_sum / 2000) - abs(mean_sum / 2000);
        for(adj = 0; adj < CFG_ADC_ADJ_CNT - 1; adj++)
        {
            if (temp <= dev_config.ADC_base[ch][adj])
            {
                break;
            }
        }

        /* 根据分段点计算有效值. */
        if (0 == adj)
        {
            ADC->ADC_elec[ch] = (uint32_t)(temp * dev_config.ADC_adj[ch][adj] * dev_config.ADC_ratio[ch] * 1.414/ 32768);
        }
        else
        {
            ADC->ADC_elec[ch] = (uint32_t)((temp - dev_config.ADC_base[ch][adj - 1]) * dev_config.ADC_adj[ch][adj] * dev_config.ADC_ratio[ch] * 1.414 / 32768 + dev_config.ADC_base_elec[ch][adj - 1]);
        }

        /* 计算工频录波每个点的电流值, 每次要上传工频录波才进行计算, 这里还要判断前 4 路采样是否超过阈值. */
        if (!ADC->collect_finish && ADC->up_finish)
        {
            if (first_col)
            {
                first_col = FALSE;
                ADC->is_ADC_thr = FALSE;
            }
        
            for(i = 0; i < ADC_COLLECT_CNT; i++)
            {
                ADC->ADC_value_elec[ch][i] = (int64_t)ADC->ADC_value[ch][i] * 7257 * dev_config.ADC_ratio[ch] / 3276800;
            }

            /* 判断工频录波上传阈值. */
            if ((ch != main_cable || 0 == dev_config.main_cable) 
                && (abs_cal_u(ADC->ADC_elec[ch], ADC_data.elec[ch]) >= (uint32_t)dev_config.threshold * 1000))
            {
                ADC->is_ADC_thr = TRUE;
            }
        }
    }
}

/* 关闭 ADC 采样. */
static void _ADC_collect_stop(void)
{
    HAL_TIM_Base_Stop_IT(ADC_ctrl.ADC_tim);
    ADC_ctrl.ADC_err_cnt++;
    ADC_ctrl.ADC_index = 0;
    ADC_ctrl.ADC_cnt = 0;
}

/* 关闭 ADC 采样模块. */
static void _ADC_stop(uint8_t state)
{
    ADC_ctrl.ADC_state |= state;
    _ADC_collect_stop();
    ADC_ctrl.ADC_err_cnt = 0;

    /* 工厂模式不关闭外设. */
    if (!ADC_ctrl.continue_mode)
    {
        /* 关闭 ADC 模块 */
        HAL_GPIO_WritePin(POWER_EN_ADC_GPIO_Port, POWER_EN_ADC_Pin, GPIO_PIN_RESET);
        HAL_GPIO_WritePin(ADC_CS_GPIO_Port, ADC_CS_Pin, GPIO_PIN_RESET);
        HAL_GPIO_WritePin(ADC_OS1_GPIO_Port, ADC_OS1_Pin, GPIO_PIN_RESET);
        HAL_GPIO_WritePin(ADC_OS2_GPIO_Port, ADC_OS2_Pin, GPIO_PIN_RESET);
        HAL_SPI_Abort(ADC_ctrl.ADC_spi);
        HAL_SPI_DeInit(ADC_ctrl.ADC_spi);
        HAL_TIM_Base_Stop(ADC_ctrl.ADC_tim);
        HAL_TIM_Base_DeInit(ADC_ctrl.ADC_tim);
    }
}

/* 重新启动 ADC 采样模块. */
static void _ADC_restart(void)
{    
    MX_ADC1_Init();
    MX_SPI2_Init();
    MX_TIM6_Init();
    osDelay(100);
    
    ADC_ctrl.ADCi_state = 0;
    ADC_ctrl.ADC_state = 0;
}

/* 外部 ADC 采集工频电流数据, 每路采集1000点/s. */
static int32_t _ADC_collect(void)
{
    uint32_t notify_value = 0;
    uint32_t tick = 0;

    /* 采集失败后, 再次进入函数后会直接退出. */
    if (ADC_ctrl.ADC_state & (ADC_ST_END | ADC_ST_ERROR))
    {
        return HAL_OK;
    }

    /* 多次错误直接关闭采样. */
    if (ADC_ERR_MAX == ADC_ctrl.ADC_err_cnt)
    {
        vty_print("ADC error!\r\n");
        _ADC_stop(ADC_ST_ERROR);
        return HAL_ERROR;
    }

    /* 开始采样. */
    HAL_TIM_Base_Start_IT(ADC_ctrl.ADC_tim);

    while((ADC_CNT_SUM + ADC_PER_CNT) != ADC_ctrl.ADC_cnt)
    {
        tick = HAL_GetTick();
        while(1)
        {
            /* 等待采样完成. */
            notify_value = ulTaskNotifyTake(pdTRUE, ADC_COMP_TIMEOUT);
            /* 采样超时, 重新开始采样. */
            if (MONITOR_ADC_NOTIFY_OK == notify_value)
            {
                break;
            }

            if (HAL_GetTick() - tick > ADC_COMP_TIMEOUT)
            {
                vty_print("ADC timeout!\r\n");
                _ADC_collect_stop();
                return HAL_TIMEOUT;
            }
        }

        /* 读取 ADC 采样原始值. */
        HAL_GPIO_WritePin(ADC_CS_GPIO_Port, ADC_CS_Pin, GPIO_PIN_RESET);
        HAL_SPI_Receive(ADC_ctrl.ADC_spi, (uint8_t*)ADC_ctrl.ADC_buf, CFG_ADC_CH_CNT, ADC_SPI_TIMEOUT);
        HAL_GPIO_WritePin(ADC_CS_GPIO_Port, ADC_CS_Pin, GPIO_PIN_SET);

        /* 根据算法, 给工频 buffer 赋值. */
        if (ADC_ctrl.ADC_cnt > ADC_PER_CNT)
        {
            _ADC_buffer_set();
        }
    }

    /* 结束采样并计算采样值. */
    _ADC_stop(ADC_ST_END);
    _ADC_calculate();
    
    return HAL_OK;
}

/* . */
static void _ADC_collect_free(void)
{
    ADC_ctrl_t *ADC = &ADC_ctrl;
    uint8_t ch = 0;

    /* 结束采样并计算采样值. */
    HAL_GPIO_WritePin(POWER_EN_5V_GPIO_Port, POWER_EN_5V_Pin, GPIO_PIN_SET);
    osDelay(1000);
    _ADC_stop(ADC_ST_END);

    /* 遍历通道. */
    for(ch = 0; ch < CFG_ADC_CH_CNT; ch++)
    {
        ADC->ADC_elec[ch] = 0;
    }
    ADC->is_ADC_thr = FALSE;
}

/* . */
static void _ADC_data_save(void)
{
    uint8_t i = 0;

    /* 装填数据. */
    ADC_data.temperature = ADC_ctrl.ADCi_temp;
    ADC_data.vbat = ADC_ctrl.ADCi_vbat;
    ADC_data.vin = ADC_ctrl.ADCi_vin;
    ADC_data.vsc = ADC_ctrl.ADCi_vsc;
    for(i = 0; i < CFG_ADC_CH_CNT; i++)
    {
        ADC_data.elec[i] = ADC_ctrl.ADC_elec[i];
    }
    for(i = 0; i < SENSOR_SUM; i++)
    {
        ADC_data.sen_temp[i] = sensor_value[i].temp;
        ADC_data.sen_x[i] = sensor_value[i].joint_attitude_x;
        ADC_data.sen_y[i] = sensor_value[i].joint_attitude_y;
        ADC_data.sen_z[i] = sensor_value[i].joint_attitude_z;
        ADC_data.sen_valid[i] = sensor_value[i].is_valid;
    }
    ADC_data.energy_mode = ADC_ctrl.energy_mode;
    ADC_data.sen_short = sensor_short;
    ADC_data.is_not_updata = TRUE;

    fd_write(&ADC_data);
}

/* 外部 ADC 采样初始化. */
static void _ADC_init(void)
{
    /* 已开始不用再初始化. */
    if (ADC_ctrl.ADC_state & ADC_ST_START)
    {
        return;
    }
    
    /* 这里等待 8s 因为硬件供电后, ADC采样引脚电压稳定需要时间. */
    /* ADC 采样供电初始化. */
    HAL_GPIO_WritePin(ADC_CS_GPIO_Port, ADC_CS_Pin, GPIO_PIN_SET);
    HAL_GPIO_WritePin(ADC_OS1_GPIO_Port, ADC_OS1_Pin, GPIO_PIN_SET);
    HAL_GPIO_WritePin(ADC_OS2_GPIO_Port, ADC_OS2_Pin, GPIO_PIN_SET);
    osDelay(1);
    HAL_GPIO_WritePin(POWER_EN_5V_GPIO_Port, POWER_EN_5V_Pin, GPIO_PIN_SET);
    HAL_GPIO_WritePin(POWER_EN_ADC_GPIO_Port, POWER_EN_ADC_Pin, GPIO_PIN_SET);
    osDelay(3000);
    /* ADC RESET. */
    HAL_GPIO_WritePin(ADC_RST_GPIO_Port, ADC_RST_Pin, GPIO_PIN_SET);
    osDelay(100);
    HAL_GPIO_WritePin(ADC_RST_GPIO_Port, ADC_RST_Pin, GPIO_PIN_RESET);
    osDelay(1000);

    ADC_ctrl.ADC_state |= ADC_ST_START;
}

/* ADC 采集主任务循环. */
static void _ADC_start(void *argument)
{
    uint8_t cnt = 0;

    ADC_ctrl.ADC_tim = &htim6;
    ADC_ctrl.ADC_spi = &hspi2;
    ADC_ctrl.collect_finish = FALSE;
    ADC_ctrl.up_finish = TRUE;
    ADC_ctrl.collect_time = HAL_GetTick();

    for (;;)
    {
        _ADCi_init();
        /* 进行内部 ADC 采样, 如果超时就继续, 3次超时会返回错误, 进行下一步操作. */
        if (HAL_TIMEOUT == _ADCi_collect())
        {
            continue;
        }

        if (dev_config.is_voltage_col)
        {
            _ADC_init();
            /* 进行外部 ADC 采样, 如果超时就继续, 3次超时会返回错误, 进行下一步操作. */
            if (HAL_TIMEOUT == _ADC_collect())
            {
                continue;
            }
        }
        else
        {
            _ADC_collect_free();
        }

        /* 确定节能模式. */
        _ADC_energy_calculate();

        /* 故障定位版本装置不接温度振动传感器 */
        if (DEV_TYPE_CT_P != dev_info.type_s)
        {
            /* 校准模式不开启传感器采样, 传感器 485 口用于接校准设备. */
            if (!IS_MONITOR_BIT_SET(dev_config.flag, DEV_FLAG_ADJ)
                && dev_config.is_temp_col)
            {
                if (!ADC_ctrl.collect_finish && ADC_ctrl.up_finish)
                {
                    sensor_start();
                }
            }
            else
            {
                sensor_start_free();
            }
        }
        
        /* 此处需要在传感器采样完成后才能关闭, 因为 5V 要给 ADC 和传感器供电. */
        if (!IS_MONITOR_BIT_SET(dev_config.flag, DEV_FLAG_ADJ) && (DEV_TYPE_CT_P != dev_info.type_s))
        {
            /* 校准模式与故障定位版本不要关 5V 供电, 485 芯片需要供电. */
            HAL_GPIO_WritePin(POWER_EN_5V_GPIO_Port, POWER_EN_5V_Pin, GPIO_PIN_RESET);
        }
        
        if (!ADC_ctrl.collect_finish && ADC_ctrl.up_finish)
        {
            ADC_ctrl.collect_finish = TRUE;
            ADC_ctrl.up_finish = FALSE;
            _ADC_data_save();
        }

        /* 标志 ADC 内部电压采样完成. */
        MONITOR_BITMAP_SET(system_init_flag, SYS_INIT_ADC);
        
        osDelay(5000);
        common_watchdog_set(COM_WDG_ADC);

        /* 校准模式不自动循环采样. */
        if (!IS_MONITOR_BIT_SET(dev_config.flag, DEV_FLAG_ADJ))
        {
            /* 超过上传间隔, 需要重新上传数据. */
            if ((HAL_GetTick() - ADC_ctrl.collect_time) > (dev_config.collect_interval * 60000))
            {
                cnt = 0;
                _ADC_restart();
                
                ADC_ctrl.collect_finish = FALSE;
                ADC_ctrl.collect_time = HAL_GetTick();
            }
            else
            {
                cnt++;
                if (cnt >= 8)
                {
                    _ADC_restart();
                    cnt = 0;
                }
            }
        }
    }
}

/* ADC 采集主任务循环. */
static void _ADC_start_csg(void *argument)
{
    ADC_ctrl.ADC_tim = &htim6;
    ADC_ctrl.ADC_spi = &hspi2;
    ADC_ctrl.collect_finish = FALSE;
    ADC_ctrl.up_finish = TRUE;

    for (;;)
    {
        _ADCi_init();
        /* 进行内部 ADC 采样, 如果超时就继续, 3次超时会返回错误, 进行下一步操作. */
        if (HAL_TIMEOUT == _ADCi_collect())
        {
            continue;
        }

        _ADC_init();
        /* 进行外部 ADC 采样, 如果超时就继续, 3次超时会返回错误, 进行下一步操作. */
        if (HAL_TIMEOUT == _ADC_collect())
        {
            continue;
        }

        /* 确定节能模式. */
        _ADC_energy_calculate();
                
        /* 校准模式不要关 5V 供电, 485 芯片需要供电. */
        HAL_GPIO_WritePin(POWER_EN_5V_GPIO_Port, POWER_EN_5V_Pin, GPIO_PIN_RESET);
        
        if (!ADC_ctrl.collect_finish)
        {
            ADC_ctrl.collect_finish = TRUE;
            ADC_ctrl.up_finish = FALSE;
            if (ADC_ctrl.is_force_col)
            {
                ADC_ctrl.is_force_col = FALSE;
            }
            else
            {
                ADC_ctrl.collect_time = HAL_GetTick();
            }
            _ADC_data_save();
        }

        /* 标志 ADC 内部电压采样完成. */
        MONITOR_BITMAP_SET(system_init_flag, SYS_INIT_ADC);
        
        osDelay(5000);
        common_watchdog_set(COM_WDG_ADC);
        restart_ontime();

        /* 超过上传间隔, 需要重新上传数据. */
        if ((HAL_GetTick() - ADC_ctrl.collect_time) > (dev_config.collect_interval * 60000))
        {
            _ADC_restart();
            ADC_ctrl.collect_finish = FALSE;
        }
    }
}

/* ADC 采集主任务循环. */
static void _ADC_start_continue(void *argument)
{
    /* 初始化. */
    ADC_ctrl.ADC_tim = &htim6;
    ADC_ctrl.ADC_spi = &hspi2;
    _ADCi_init();
    _ADC_init();
    ADC_ctrl.continue_mode = TRUE;
    ADC_ctrl.collect_finish = FALSE;
    ADC_ctrl.up_finish = TRUE;
    ADC_ctrl.collect_time = HAL_GetTick();

    for (;;)
    {
        /* 进行内部 ADC 采样, 如果超时就继续, 3次超时会返回错误, 进行下一步操作. */
        if (HAL_TIMEOUT == _ADCi_collect())
        {
            continue;
        }

        if (dev_config.is_voltage_col)
        {
            /* 进行外部 ADC 采样, 如果超时就继续, 3次超时会返回错误, 进行下一步操作. */
            if (HAL_TIMEOUT == _ADC_collect())
            {
                continue;
            }
        }
        else
        {
            _ADC_collect_free();
        }

        /* 确定节能模式. */
        _ADC_energy_calculate();

        if (DEV_TYPE_CT_P != dev_info.type_s)
        {
            /* 传感器数据采集. */
            if (dev_config.is_temp_col)
            {
                sensor_start();
            }
            else
            {
                sensor_start_free();
            }
        }
        else
        {
            position_start();
        }

        if (!ADC_ctrl.collect_finish && ADC_ctrl.up_finish)
        {
            ADC_ctrl.collect_finish = TRUE;
            ADC_ctrl.up_finish = FALSE;
            _ADC_data_save();
        }

        /* 标志 ADC 内部电压采样完成. */
        MONITOR_BITMAP_SET(system_init_flag, SYS_INIT_ADC);
        
        osDelay(1000);
        common_watchdog_set(COM_WDG_ADC);

        /* 重新采样一次 */
        ADC_ctrl.ADCi_state = 0;
        ADC_ctrl.ADC_state = 0;
        
        /* 超过上传间隔, 需要重新上传数据. */
        if ((HAL_GetTick() - ADC_ctrl.collect_time) > dev_config.collect_interval * 60000)
        {
            ADC_ctrl.collect_time = HAL_GetTick();
            ADC_ctrl.collect_finish = FALSE;
        }
    }
}

/* Interface functions -------------------------------------------------------*/
/* ADC 采集任务初始化. */
void ADC_init_os(void)
{
    fd_read(fd_id, &ADC_data);

    /* 故障定位版本装置且非校准模式时进行初始化 */
    if (DEV_TYPE_CT_P == dev_info.type_s && !IS_MONITOR_BIT_SET(dev_config.flag, DEV_FLAG_ADJ))
    {
        position_init();
    }

    if (IS_MONITOR_BIT_SET(dev_config.flag, DEV_FLAG_FACTORY)
        || (DEV_TYPE_ACDC == dev_info.type_s && !IS_MONITOR_BIT_SET(dev_config.flag, DEV_FLAG_ADJ)))
    {
        ADC_ctrl.ADCHandle = osThreadNew(_ADC_start_continue, NULL, &ADC_attributes);
    }
    else if (DEV_TYPE_CSG == dev_info.type_s && !IS_MONITOR_BIT_SET(dev_config.flag, DEV_FLAG_ADJ))
    {
        ADC_ctrl.ADCHandle = osThreadNew(_ADC_start_csg, NULL, &ADC_attributes);
    }
    else
    {
        ADC_ctrl.ADCHandle = osThreadNew(_ADC_start, NULL, &ADC_attributes);
    }
}

/* ADCi 电池电压自动校准. */
int32_t ADCi_vbat_auto(uint32_t base)
{
    ADC_ctrl_t *ADC = &ADC_ctrl;

    dev_config.vin_adj = base * ADCi_RESOLUTION / ADC->ADCi_value[ADCi_CH_VIN];

    return HAL_OK;
}

/* ADC base 自动计算. */
HAL_StatusTypeDef ADC_base_auto(uint8_t ch_bitmap, uint8_t index)
{
    ADC_ctrl_t *ADC = &ADC_ctrl;
    uint8_t ch = 0;
    uint16_t i = 0;
    uint64_t square_sum = 0;
    int32_t mean_sum = 0;

    if (!ch_bitmap)
    {
        return HAL_OK;
    }

    /* 重新启动 ADC 采样. */
    _ADC_restart();
    for(i = 0; i < 64; i++)
    {
        if (ADC_ctrl.ADC_state & ADC_ST_END)
        {
            break;
        }
        else if(ADC_ctrl.ADC_state & ADC_ST_ERROR)
        {
            vty_print("ADC base auto calculate is ERROR.\r\n");
            return HAL_ERROR;
        }
        osDelay(500);
    }
    if (i >= 64)
    {
        vty_print("ADC base auto calculate is TIMEOUT.\r\n");
        return HAL_ERROR;
    }

    /* 遍历通道. */
    index--;
    for(ch = 0; ch < CFG_ADC_CH_CNT; ch++)
    {
        /* 过滤通道. */
        if (!IS_MONITOR_BIT_SET(ch_bitmap, ch))
        {
            continue;
        }
        
        square_sum = 0;
        mean_sum = 0;
        /* 遍历通道所有值, 求和, 并计算出最大值和最小值. */
        for(i = 0; i < ADC_COLLECT_CNT; i++)
        {
            square_sum += ADC->ADC_value[ch][i] * ADC->ADC_value[ch][i];
            mean_sum += ADC->ADC_value[ch][i];
        }

        /* 计算校准参数. */
        dev_config.ADC_base[ch][index] = (double)sqrt(square_sum / 2000) - abs(mean_sum / 2000);
        if (0 == index)
        {
            dev_config.ADC_adj[ch][index] = (uint16_t)(dev_config.ADC_base_elec[ch][index] * 32768 / (dev_config.ADC_base[ch][index] * dev_config.ADC_ratio[ch] * 1.414));
        }
        else
        {
            square_sum = (uint64_t)(dev_config.ADC_base_elec[ch][index] - dev_config.ADC_base_elec[ch][index - 1]) * 32768;
            dev_config.ADC_adj[ch][index] =  (uint16_t)(square_sum / ((dev_config.ADC_base[ch][index] -  dev_config.ADC_base[ch][index - 1]) * dev_config.ADC_ratio[ch] * 1.414));
        }

        /* 调试打印. */
        if (dbg_stat_get(DBG_M_ADC))
        {
            DBG(DBG_M_ADC, "%d %f %d %d\r\n", ch, dev_config.ADC_base[ch][index], dev_config.ADC_base_elec[ch][index], dev_config.ADC_adj[ch][index]);
            ADC_value_show(ch + 1);
        }
    }

    return HAL_OK;
}

/* 马上重新开始一次数据采集. */
void ADC_restart_force(void)
{
    if (ADC_ctrl.collect_finish)
    {
        _ADC_restart();
        ADC_ctrl.collect_finish = FALSE;
        ADC_ctrl.is_force_col = TRUE;
    }
}

/* ADCi 采集显示接口. */
void ADCi_show(void)
{
    ADC_ctrl_t *ADC = &ADC_ctrl;

    vty_print("TE   VB   VI   VS   ATE  AVB  AVI  AVS  EC ST\r\n");
    vty_print("%-04d %-04d %-04d %-04d %-04d %-04d %-04d %-04d %-02d %-02x", ADC->ADCi_temp, ADC->ADCi_vbat,
        ADC->ADCi_vin, ADC->ADCi_vsc, ADC->ADCi_value[ADCi_CH_TEMP], ADC->ADCi_value[ADCi_CH_VBAT],
        ADC->ADCi_value[ADCi_CH_VIN], ADC->ADCi_value[ADCi_CH_VSC], ADC->ADCi_err_cnt, ADC->ADCi_state);
    vty_print("\r\n");
}

/* ADC 采集显示接口. */
void ADC_show(void)
{
    ADC_ctrl_t *ADC = &ADC_ctrl;
    uint8_t i = 0;

    for(i = 1; i <= CFG_ADC_CH_CNT; i++)
    {
        vty_print("E%d     ", i);
    }
    vty_print("CF UF TH EC ST \r\n");
    for(i = 0; i < CFG_ADC_CH_CNT; i++)
    {
        vty_print("%-06d ", ADC->ADC_elec[i]);
    }
    vty_print("%-02d %-02d %-02d %-02d %-02x\r\n", ADC->collect_finish, ADC->up_finish, ADC->is_ADC_thr, ADC->ADC_err_cnt,
        ADC->ADC_state);
}

/* ADC 工频采样显示接口. */
void ADC_value_show(uint32_t ch)
{
    ADC_ctrl_t *ADC = &ADC_ctrl;
    uint8_t i = 0;
    uint8_t j = 0;

    if (ch > CFG_ADC_CH_CNT || 0 == ch)
    {
        return;
    }

    ch--;
    for(i = 0; i < 1; i++)
    {
        vty_print("%-02d ", i + 1);
        for(j = 0; j < 40; j++)
        {
           vty_print("%-06d ", ADC->ADC_value[ch][i * 20 + j]);
        }
        vty_print("\r\n");
        osDelay(40);
    }

    vty_print("\r\n");
    for(i = 0; i < 1; i++)
    {
        vty_print("%-02d ", i + 1);
        for(j = 0; j < 40; j++)
        {
            vty_print("%-06d ", ADC->ADC_value_elec[ch][i * 20 + j]);
        }
        vty_print("\r\n");
        osDelay(40);
    }
}

/* ADC 校准显示. */
void ADC_adj_show_ch(uint8_t ch)
{
    uint8_t i = 0;

    if (ch > CFG_ADC_CH_CNT || 0 == ch)
    {
        return;
    }

    ch--;
    vty_print("ch%d(%d):\r\n", ch + 1, dev_config.ADC_ratio[ch]);
    for(i = 0; i < CFG_ADC_ADJ_CNT; i++)
    {
        vty_print("%d %-06d %-04d %f\r\n", i + 1, dev_config.ADC_base_elec[ch][i], dev_config.ADC_adj[ch][i], dev_config.ADC_base[ch][i]);
    }
    vty_print("\r\n");
}

/* ADC 校准显示. */
void ADC_adj_show(void)
{
    uint8_t i = 0;

    for(i = 0; i < CFG_ADC_CH_CNT; i++)
    {
        ADC_adj_show_ch(i + 1);
    }


    vty_print("Vin: %d\r\n", dev_config.vin);
    vty_print("Vin adjust: %d\r\n\n", dev_config.vin_adj);
}
/******************* (C) COPYRIGHT LandPower ***** END OF FILE ****************/
