/**************************************************************************//**
  * \file      Analog_Signals.c
  * \brief     Analog signal processing
  * \attention
  *
  * This file is automatically generated by analog signals configuration tool.
  * Date         : 2023/8/12 8:57:02
  * Cfg Tool Ver : 1.1.0
  * Engineer     : 
  * (c) Heilongjiang TYW electronics co., LTD
  *
******************************************************************************/

/* Includes -----------------------------------------------------------------*/
#include "Analog_Signals.h"

/* Private typedef ----------------------------------------------------------*/
typedef struct
{
    uint8_t   u8Ch;
    uint8_t   u8RefType;
    uint8_t   u8CalMode;
    uint16_t  u16Reference;
    uint16_t  u16CalData;
    uint16_t  u16Resolution;
    ADC_Circuit_Calc_Func  pfProcFunc;
}ADC_Ch_Cfg_st_t;

typedef enum ASigConvStat
{
    ADC_STAT_IDLE = 0,
    ADC_STAT_INIT,
    ADC_STAT_WAIT,
    ADC_STAT_CONV,
    ADC_STAT_PROC,
    ADC_STAT_ERR,
}ADC_Stat_en_t;

typedef struct
{
    ADC_Stat_en_t  enStatus;
    uint8_t        u8CurrentCh;
    uint8_t        u8DebounceCnt;
    uint8_t        u8Timer;
}ADC_Ctrl_st_t;

typedef struct
{
    uint8_t  u8Valid;
    uint8_t  u8Rsvd;
    uint16_t u16Value;
}ADC_Data_st_t;

/* Private macro -------------------------------------------------------------*/
#define   ADC_DEFAULT_REF_VOLTAGE           (5000U)
#define   ADC_CONV_CH_NUMBER                (ADC_TOTAL_CH_NUMBER)

#define   ADC_SAMPLE_INTERVAL               (2U)
#define   ADC_MAX_SAMPLE_WAIT               (10U)
#define   ADC_PWR_UP_DEBOUNCE               (10U)
#define   ADC_CONV_WAIT                     (50000U)

#define   ADC_REF_TYPE_V_NONE               (0x00U)
#define   ADC_REF_TYPE_V_VREF               (0x01U)
#define   ADC_REF_TYPE_V_CH                 (0x02U)
#define   ADC_REF_TYPE_V_FIXED              (0x03U)
#define   ADC_REF_TYPE_I_FIXED              (0x13U)

/* Private variables --------------------------------------------------------*/
volatile uint16_t u16ADCRefVoltage;
ADC_Ctrl_st_t     stADCCtrl;
uint16_t          u16ADCSample[ADC_CONV_CH_NUMBER];
ADC_Data_st_t     stADCData[ADC_SIGNAL_CH_NUMBER];

const uint8_t u8ADCChList[ADC_CONV_CH_NUMBER] =
{
     9U, 15U, 
};

const ADC_Ch_Cfg_st_t stADCChCfg[ADC_SIGNAL_CH_NUMBER] =
{
    {  0U,   0U,   0U,     0U,     0U,     1U,  ADC_Voltage_Calc_Circuit101,},
    {  1U,   0U,   0U,     0U,     0U,     1U,  ADC_Voltage_Calc_Circuit101,},
};

const ADC_Res_List_st_t stADCResList[ADC_SIGNAL_CH_NUMBER] =
{
    {          0U,    100000U,         0U,         0U,},
    {          0U,    100000U,         0U,         0U,},
};

/* Private function prototypes ----------------------------------------------*/
/* Private functions --------------------------------------------------------*/

void Analog_Signal_Conv_Init(void)
{
    uint8_t i;

    while(ADC_Get_Conversion_Status())
    {
        ADC_Stop_Conversion();
    }

    ADC_Init(u8ADCChList, ADC_CONV_CH_NUMBER);

    for (i = 0U; i < ADC_SIGNAL_CH_NUMBER; i++)
    {
        stADCData[i].u8Valid  = 0U;
        stADCData[i].u16Value = 0U;
    }

    stADCCtrl.enStatus        = ADC_STAT_INIT;
    stADCCtrl.u8CurrentCh     = 0U;
    stADCCtrl.u8DebounceCnt   = ADC_PWR_UP_DEBOUNCE / ADC_SAMPLE_INTERVAL;
    stADCCtrl.u8Timer         = 0U;
    u16ADCRefVoltage          = ADC_DEFAULT_REF_VOLTAGE;
}

void Analog_Signal_Conv_Stop(void)
{
    uint8_t i;

    ADC_DeInit();

    for (i = 0U; i < ADC_SIGNAL_CH_NUMBER; i++)
    {
        stADCData[i].u8Valid = 0U;
    }

    stADCCtrl.enStatus       = ADC_STAT_IDLE;
    stADCCtrl.u8DebounceCnt  = ADC_PWR_UP_DEBOUNCE / ADC_SAMPLE_INTERVAL;
    u16ADCRefVoltage = ADC_DEFAULT_REF_VOLTAGE;
}

void Analog_Signal_Conv_Service(void)
{
    uint8_t  u8Valid;
    uint16_t u16Voltage;
    uint16_t u16Reference;
    uint16_t u16Result;

    switch (stADCCtrl.enStatus)
    {
        case ADC_STAT_IDLE    : break;

        case ADC_STAT_INIT    : ADC_Start_Conversion();
                                stADCCtrl.u8Timer     = 0U;
                                stADCCtrl.u8CurrentCh = 0U;

                                if (stADCCtrl.u8DebounceCnt == 0U)
                                {
                                    stADCCtrl.enStatus = ADC_STAT_CONV;
                                }
                                else
                                {
                                    stADCCtrl.enStatus = ADC_STAT_WAIT;
                                }
                                break;

        case ADC_STAT_WAIT    : if (stADCCtrl.u8DebounceCnt)
                                {
                                    stADCCtrl.u8DebounceCnt--;
                                }

                                if (ADC_Get_Conversion_Status() == 0U)
                                {
                                    ADC_Start_Conversion();
                                    stADCCtrl.u8Timer = 0U;

                                    if (stADCCtrl.u8DebounceCnt == 0U)
                                    {
                                        stADCCtrl.enStatus = ADC_STAT_CONV;
                                    }
                                }
                                else
                                {
                                    stADCCtrl.u8Timer++;
                                    if (stADCCtrl.u8Timer >= ADC_MAX_SAMPLE_WAIT / ADC_SAMPLE_INTERVAL)
                                    {
                                        stADCCtrl.enStatus = ADC_STAT_ERR;
                                        ADC_Stop_Conversion();
                                    }
                                }
                                break;

        case ADC_STAT_CONV    : if (ADC_Get_Conversion_Status() == 0U)
                                {
                                    ADC_Get_Conversion_Result(u16ADCSample, ADC_CONV_CH_NUMBER);

                                    stADCCtrl.u8Timer      = 0U;
                                    stADCCtrl.u8CurrentCh  = 0U;
                                    u16ADCRefVoltage       = ADC_DEFAULT_REF_VOLTAGE;

                                    stADCCtrl.enStatus     = ADC_STAT_PROC;
                                }
                                else
                                {
                                    stADCCtrl.u8Timer++;
                                    if (stADCCtrl.u8Timer >= ADC_MAX_SAMPLE_WAIT / ADC_SAMPLE_INTERVAL)
                                    {
                                        stADCCtrl.enStatus = ADC_STAT_ERR;
                                        ADC_Stop_Conversion();
                                    }
                                }
                                break;

        case ADC_STAT_PROC    : u16Voltage = ADC_Input_Voltage_Calc(u16ADCSample[stADCChCfg[stADCCtrl.u8CurrentCh].u8Ch], ADC_RESOLUTION, u16ADCRefVoltage);
                                u8Valid    = 1U;

                                if (stADCChCfg[stADCCtrl.u8CurrentCh].u8RefType == ADC_REF_TYPE_V_NONE)
                                {
                                    u16Reference = 0U;
                                }
                                else if (stADCChCfg[stADCCtrl.u8CurrentCh].u8RefType == ADC_REF_TYPE_V_VREF)
                                {
                                    u16Reference = u16ADCRefVoltage;
                                }
                                else if (stADCChCfg[stADCCtrl.u8CurrentCh].u8RefType == ADC_REF_TYPE_V_CH)
                                {
                                    u16Reference = ADC_Read_Signal((uint8_t)stADCChCfg[stADCCtrl.u8CurrentCh].u16Reference);
                                    u8Valid      = ADC_Read_Signal_Valid((uint8_t)stADCChCfg[stADCCtrl.u8CurrentCh].u16Reference);
                                }
                                else if ((stADCChCfg[stADCCtrl.u8CurrentCh].u8RefType == ADC_REF_TYPE_V_FIXED) || \
                                         (stADCChCfg[stADCCtrl.u8CurrentCh].u8RefType == ADC_REF_TYPE_I_FIXED))
                                {
                                    u16Reference = stADCChCfg[stADCCtrl.u8CurrentCh].u16Reference;
                                }
                                else
                                {
                                    u8Valid = 0U;
                                }
                                
                                if (u8Valid)
                                {
                                    u16Result = stADCChCfg[stADCCtrl.u8CurrentCh].pfProcFunc(u16Voltage,
                                                                                             u16Reference,
                                                                                             stADCChCfg[stADCCtrl.u8CurrentCh].u16Resolution,
                                                                                             &stADCResList[stADCCtrl.u8CurrentCh]);

                                    u16Result = ADC_Data_Calibrate(u16Result,
                                                                   stADCChCfg[stADCCtrl.u8CurrentCh].u8CalMode,
                                                                   stADCChCfg[stADCCtrl.u8CurrentCh].u16CalData);

                                    stADCData[stADCCtrl.u8CurrentCh].u16Value = u16Result;
                                    stADCData[stADCCtrl.u8CurrentCh].u8Valid  = 1U;
                                }
                                else
                                {
                                    stADCData[stADCCtrl.u8CurrentCh].u16Value = 0U;
                                    stADCData[stADCCtrl.u8CurrentCh].u8Valid  = 0U;
                                }

                                stADCCtrl.u8CurrentCh++;
                                if (stADCCtrl.u8CurrentCh >= ADC_SIGNAL_CH_NUMBER)
                                {
                                    ADC_Start_Conversion();
                                    stADCCtrl.u8CurrentCh = 0U;
                                    stADCCtrl.enStatus    = ADC_STAT_CONV;
                                }
                                break;

        case ADC_STAT_ERR     : if (ADC_Get_Conversion_Status() == 0U)
                                {
                                    stADCCtrl.enStatus = ADC_STAT_INIT;
                                }
                                else
                                {
                                    ADC_Stop_Conversion();
                                }
                                break;

        default               : Analog_Signal_Conv_Init();
                                break;
    }
}

uint16_t ADC_Read_Signal(uint8_t u8ADCCh)
{
    uint16_t u16Value;

    if (u8ADCCh < ADC_SIGNAL_CH_NUMBER)
    {
        u16Value = stADCData[u8ADCCh].u16Value;
    }
    else
    {
        u16Value = 0U;
    }

    return u16Value;
}

uint8_t  ADC_Read_Signal_Valid(uint8_t u8ADCCh)
{
    uint8_t u8Valid;

    if (u8ADCCh < ADC_SIGNAL_CH_NUMBER)
    {
        u8Valid = stADCData[u8ADCCh].u8Valid;
    }
    else
    {
        u8Valid = 0U;
    }

    return u8Valid;
}

uint16_t ADC_Conv_Single_Channel(uint8_t u8ADCCh)
{
    uint8_t  u8RefCh;
    uint8_t  u8Valid;
    uint8_t  u8ConvResult;
    uint16_t u16Voltage;
    uint16_t u16Reference;
    uint16_t u16Result;
    uint32_t u32Timer;

    u16Result = 0U;
    if (u8ADCCh < ADC_SIGNAL_CH_NUMBER)
    {
        if (ADC_Get_Conversion_Status() == 0U)
        {
            ADC_Start_Conversion();
        }

        u32Timer = 0U;
        do
        {
            u32Timer++;
            u8ConvResult = ADC_Get_Conversion_Status();
        }while ((u8ConvResult != 0U) && (u32Timer < ADC_CONV_WAIT));

        if (u8ConvResult == 0U)
        {
            ADC_Get_Conversion_Result(u16ADCSample, ADC_CONV_CH_NUMBER);
            u16ADCRefVoltage = ADC_DEFAULT_REF_VOLTAGE;

            u16Voltage = ADC_Input_Voltage_Calc(u16ADCSample[stADCChCfg[u8ADCCh].u8Ch], ADC_RESOLUTION, u16ADCRefVoltage);
            u8Valid    = 1U;

            if (stADCChCfg[u8ADCCh].u8RefType == ADC_REF_TYPE_V_NONE)
            {
                u16Reference = 0U;
            }
            else if (stADCChCfg[u8ADCCh].u8RefType == ADC_REF_TYPE_V_VREF)
            {
                u16Reference = u16ADCRefVoltage;
            }
            else if (stADCChCfg[u8ADCCh].u8RefType == ADC_REF_TYPE_V_CH)
            {
                u8RefCh = (uint8_t)stADCChCfg[u8ADCCh].u16Reference;

                u16Reference = ADC_Input_Voltage_Calc(u16ADCSample[stADCChCfg[u8RefCh].u8Ch], ADC_RESOLUTION, u16ADCRefVoltage);

                u16Reference = stADCChCfg[u8RefCh].pfProcFunc(u16Reference,
                                                              0U,
                                                              stADCChCfg[u8RefCh].u16Resolution,
                                                              &stADCResList[u8RefCh]);

                u16Reference = ADC_Data_Calibrate(u16Reference,
                                                  stADCChCfg[u8RefCh].u8CalMode,
                                                  stADCChCfg[u8RefCh].u16CalData);
            }
            else if ((stADCChCfg[u8ADCCh].u8RefType == ADC_REF_TYPE_V_FIXED) || \
                     (stADCChCfg[u8ADCCh].u8RefType == ADC_REF_TYPE_I_FIXED))
            {
                u16Reference = stADCChCfg[u8ADCCh].u16Reference;
            }
            else
            {
                u8Valid = 0U;
            }

            if (u8Valid)
            {
                u16Result = stADCChCfg[u8ADCCh].pfProcFunc(u16Voltage,
                                                           u16Reference,
                                                           stADCChCfg[u8ADCCh].u16Resolution,
                                                           &stADCResList[u8ADCCh]);

                u16Result = ADC_Data_Calibrate(u16Result,
                                               stADCChCfg[u8ADCCh].u8CalMode,
                                               stADCChCfg[u8ADCCh].u16CalData);
            }
        }
    }

    return u16Result;
}
