#include "System_Monitor.h"

#define Base_Vol 0u

#define ENTER_LOW_N_RANGE 6500U
#define EXIT_LOW_N_RANGE 7000U

#define ENTER_LOW_Y_RANGE 9000U
#define EXIT_LOW_Y_RANGE 9500U

#define EXIT_HIGH_Y_RANGE  26000U

#define ENTER_HIGH_Y_RANGE 26500U

#define EXIT_HIGH_N_RANGE  28500U

#define ENTER_HIGH_N_RANGE 29000U

#define Top_Vol 0xffffu

MonitorStruct SysFun_KL30Monitor;
MonitorStruct SysFun_KL15Monitor;

MonitorStruct SysNM_KL30Monitor;
MonitorStruct SysNM_KL15Monitor;

uint8_t SysWakeUpMode = 0u;
static uint8_t SetVolFlag = 0u;

static uint16_t t_NM_KL30_Debounce;
static uint16_t t_NM_KL15_Debounce;
static uint16_t t_FUN_KL30_Debounce;
static uint16_t t_FUN_KL15_Debounce;

static uint16_t FUNSysVol_Range[10u] =
{
    Base_Vol,
    ENTER_LOW_N_RANGE,
    EXIT_LOW_N_RANGE,
    ENTER_LOW_Y_RANGE,
    EXIT_LOW_Y_RANGE,
    EXIT_HIGH_Y_RANGE,
    ENTER_HIGH_Y_RANGE,
    EXIT_HIGH_N_RANGE,
    ENTER_HIGH_N_RANGE,
    Top_Vol,
};

static uint16_t NMSysVol_Range[10u] =
{
    Base_Vol,
    ENTER_LOW_N_RANGE,
    EXIT_LOW_N_RANGE,
    ENTER_LOW_Y_RANGE,
    EXIT_LOW_Y_RANGE,
    EXIT_HIGH_Y_RANGE,
    ENTER_HIGH_Y_RANGE,
    EXIT_HIGH_N_RANGE,
    ENTER_HIGH_N_RANGE,
    Top_Vol,
};

uint8_t Read_KL30_ConvertFinish(void)
{
    return SysWakeUpMode;
}

static uint8_t System_Calc_FunRange(uint16_t u16Vol)
{
    uint8_t i;
    for (i = 0u; i < (sizeof(FUNSysVol_Range) / sizeof(FUNSysVol_Range[0])); i++)
    {
        if (u16Vol < FUNSysVol_Range[i])
        {
            break;
        }
    }
    return i;
}

static uint8_t System_Calc_NMRange(uint16_t u16Vol)
{
    uint8_t i;
    for (i = 0u; i < (sizeof(NMSysVol_Range) / sizeof(NMSysVol_Range[0])); i++)
    {
        if (u16Vol < NMSysVol_Range[i])
        {
            break;
        }
    }
    return i;
}

void Sys_Set_VolRange(const uint16_t FUN_Vol[], const uint16_t NM_Vol[])
{
    FUNSysVol_Range[0] = FUN_Vol[0];
    FUNSysVol_Range[1] = FUN_Vol[1];
    FUNSysVol_Range[2] = FUN_Vol[2];
    FUNSysVol_Range[3] = FUN_Vol[3];
    FUNSysVol_Range[4] = FUN_Vol[4];
    FUNSysVol_Range[5] = FUN_Vol[5];
    FUNSysVol_Range[6] = FUN_Vol[6];
    FUNSysVol_Range[7] = FUN_Vol[7];
    FUNSysVol_Range[8] = FUN_Vol[8];
    FUNSysVol_Range[9] = FUN_Vol[9];

    NMSysVol_Range[0] = NM_Vol[0];
    NMSysVol_Range[1] = NM_Vol[1];
    NMSysVol_Range[2] = NM_Vol[2];
    NMSysVol_Range[3] = NM_Vol[3];
    NMSysVol_Range[4] = NM_Vol[4];
    NMSysVol_Range[5] = NM_Vol[5];
    NMSysVol_Range[6] = NM_Vol[6];
    NMSysVol_Range[7] = NM_Vol[7];
    NMSysVol_Range[8] = NM_Vol[8];
    NMSysVol_Range[9] = NM_Vol[9];
    SetVolFlag = 0x55u;
}

void Sys_Set_DebounceTimer(uint16_t u16NMKL30, uint16_t u16NMKL15, uint16_t u16FUNKL30, uint16_t u16FUNKL15)
{
    t_NM_KL30_Debounce = u16NMKL30;
    t_NM_KL15_Debounce = u16NMKL15;
    t_FUN_KL30_Debounce = u16FUNKL30;
    t_FUN_KL15_Debounce = u16FUNKL15;
}

void System_Monitor_KL30Init(void)
{
    SysWakeUpMode = 0u;
    SysFun_KL30Monitor.SumCnt = 0u;
    SysFun_KL30Monitor.DebounceTimer = 0u;
    SysFun_KL30Monitor.ActVoltage = 0u;
    SysFun_KL30Monitor.FinalSts = 0u;
    SysFun_KL30Monitor.ActSts = 0u;

    SysFun_KL15Monitor.SumCnt = 0u;
    SysFun_KL15Monitor.DebounceTimer = 0u;
    SysFun_KL15Monitor.ActVoltage = 0u;
    SysFun_KL15Monitor.FinalSts = 0u;
    SysFun_KL15Monitor.ActSts = 0u;

    SysNM_KL30Monitor.SumCnt = 0u;
    SysNM_KL30Monitor.DebounceTimer = 0u;
    SysNM_KL30Monitor.ActVoltage = 0u;
    SysNM_KL30Monitor.FinalSts = 0u;
    SysNM_KL30Monitor.ActSts = 0u;

    SysNM_KL15Monitor.SumCnt = 0u;
    SysNM_KL15Monitor.DebounceTimer = 0u;
    SysNM_KL15Monitor.ActVoltage = 0u;
    SysNM_KL15Monitor.FinalSts = 0u;
    SysNM_KL15Monitor.ActSts = 0u;

    if (t_NM_KL30_Debounce == 0U)
    {
        t_NM_KL30_Debounce = 1000u;
    }
    if (t_NM_KL15_Debounce == 0U)
    {
        t_NM_KL15_Debounce = 2u;
    }
    if (t_FUN_KL30_Debounce == 0U)
    {
        t_FUN_KL30_Debounce = 1000u;
    }
    if (t_FUN_KL15_Debounce == 0U)
    {
        t_FUN_KL15_Debounce = 2u;
    }

    if (SetVolFlag != 0x55u)
    {
        FUNSysVol_Range[0] = Base_Vol;
        FUNSysVol_Range[1] = ENTER_LOW_N_RANGE;
        FUNSysVol_Range[2] = EXIT_LOW_N_RANGE;
        FUNSysVol_Range[3] = ENTER_LOW_Y_RANGE;
        FUNSysVol_Range[4] = EXIT_LOW_Y_RANGE;
        FUNSysVol_Range[5] = EXIT_HIGH_Y_RANGE;
        FUNSysVol_Range[6] = ENTER_HIGH_Y_RANGE;
        FUNSysVol_Range[7] = EXIT_HIGH_N_RANGE;
        FUNSysVol_Range[8] = ENTER_HIGH_N_RANGE;
        FUNSysVol_Range[9] = Top_Vol;

        NMSysVol_Range[0] = Base_Vol;
        NMSysVol_Range[1] = ENTER_LOW_N_RANGE;
        NMSysVol_Range[2] = EXIT_LOW_N_RANGE;
        NMSysVol_Range[3] = ENTER_LOW_Y_RANGE;
        NMSysVol_Range[4] = EXIT_LOW_Y_RANGE;
        NMSysVol_Range[5] = EXIT_HIGH_Y_RANGE;
        NMSysVol_Range[6] = ENTER_HIGH_Y_RANGE;
        NMSysVol_Range[7] = EXIT_HIGH_N_RANGE;
        NMSysVol_Range[8] = ENTER_HIGH_N_RANGE;
        NMSysVol_Range[9] = Top_Vol;
        SetVolFlag = 0x55u;
    }
}

void System_Monitor_WakeupInit(void)
{
    SysWakeUpMode = 0u;
    SysFun_KL30Monitor.SumCnt = 0u;
    SysFun_KL30Monitor.DebounceTimer = 0u;
    SysFun_KL30Monitor.ActVoltage = 0u;
    SysFun_KL30Monitor.FinalSts = 0u;
    SysFun_KL30Monitor.ActSts = 0u;

    SysFun_KL15Monitor.SumCnt = 0u;
    SysFun_KL15Monitor.DebounceTimer = 0u;
    SysFun_KL15Monitor.ActVoltage = 0u;
    SysFun_KL15Monitor.FinalSts = 0u;
    SysFun_KL15Monitor.ActSts = 0u;

    SysNM_KL30Monitor.SumCnt = 0u;
    SysNM_KL30Monitor.DebounceTimer = 0u;
    SysNM_KL30Monitor.ActVoltage = 0u;
    SysNM_KL30Monitor.FinalSts = 0u;
    SysNM_KL30Monitor.ActSts = 0u;

    SysNM_KL15Monitor.SumCnt = 0u;
    SysNM_KL15Monitor.DebounceTimer = 0u;
    SysNM_KL15Monitor.ActVoltage = 0u;
    SysNM_KL15Monitor.FinalSts = 0u;
    SysNM_KL15Monitor.ActSts = 0u;

    if (t_NM_KL30_Debounce == 0U)
    {
        t_NM_KL30_Debounce = 1000u;
    }
    if (t_NM_KL15_Debounce == 0U)
    {
        t_NM_KL15_Debounce = 2u;
    }
    if (t_FUN_KL30_Debounce == 0U)
    {
        t_FUN_KL30_Debounce = 1000u;
    }
    if (t_FUN_KL15_Debounce == 0U)
    {
        t_FUN_KL15_Debounce = 2u;
    }

    if (SetVolFlag != 0x55u)
    {
        FUNSysVol_Range[0] = Base_Vol;
        FUNSysVol_Range[1] = ENTER_LOW_N_RANGE;
        FUNSysVol_Range[2] = EXIT_LOW_N_RANGE;
        FUNSysVol_Range[3] = ENTER_LOW_Y_RANGE;
        FUNSysVol_Range[4] = EXIT_LOW_Y_RANGE;
        FUNSysVol_Range[5] = EXIT_HIGH_Y_RANGE;
        FUNSysVol_Range[6] = ENTER_HIGH_Y_RANGE;
        FUNSysVol_Range[7] = EXIT_HIGH_N_RANGE;
        FUNSysVol_Range[8] = ENTER_HIGH_N_RANGE;
        FUNSysVol_Range[9] = Top_Vol;

        NMSysVol_Range[0] = Base_Vol;
        NMSysVol_Range[1] = ENTER_LOW_N_RANGE;
        NMSysVol_Range[2] = EXIT_LOW_N_RANGE;
        NMSysVol_Range[3] = ENTER_LOW_Y_RANGE;
        NMSysVol_Range[4] = EXIT_LOW_Y_RANGE;
        NMSysVol_Range[5] = EXIT_HIGH_Y_RANGE;
        NMSysVol_Range[6] = ENTER_HIGH_Y_RANGE;
        NMSysVol_Range[7] = EXIT_HIGH_N_RANGE;
        NMSysVol_Range[8] = ENTER_HIGH_N_RANGE;
        NMSysVol_Range[9] = Top_Vol;
        SetVolFlag = 0x55u;
    }
}

void Sys_Status_Update_Service(void)
{
    System_Fun_Process();
    System_NM_Process();
    Sys_LogicProcess();
}

void System_Fast_WakeUp(void)
{
    uint16_t KL30_Voltage = 0U;
    uint16_t KL15_Voltage = 0U;
    uint8_t KL30_Valid = 0U;
    uint8_t KL15_Valid = 0U;
    uint16_t Voltage = 0U;
    uint8_t NormalKL30Cnt = 0U;
    uint8_t abnormalKL30Cnt = 0U;
    uint8_t AttemptCnt = 0U;

    AttemptCnt = 0u;
    KL30_Voltage = Sys_Force_Read_KL30_Voltage();
    KL15_Voltage = Sys_Force_Read_KL15_Voltage();
    while (SysNM_KL30Monitor.FinalSts == 0u)
    {
        {
            /*KL30 KL15电压采集*/
            KL30_Voltage = Sys_Force_Read_KL30_Voltage();
            KL15_Voltage = Sys_Force_Read_KL15_Voltage();
            if (KL30_Voltage > KL15_Voltage)
            {
                Voltage = KL30_Voltage;
            }
            else
            {
                Voltage = KL15_Voltage;
            }

            if ((Voltage <= FUNSysVol_Range[1]) || (Voltage >= FUNSysVol_Range[8]))
            {
                NormalKL30Cnt = 0U;
                abnormalKL30Cnt++;
            }
            else
            {
                NormalKL30Cnt++;
                abnormalKL30Cnt = 0U;
            }

            /*消抖次数设置*/
            if (NormalKL30Cnt >= 5U)
            {
                SysNM_KL30Monitor.FinalSts = 5u;
            }
            if (abnormalKL30Cnt >= 5U)
            {
                /*设置成HALT模式*/
                SysNM_KL30Monitor.FinalSts = 9u;
            }
        }
        Sys_BlockDelay(20U); /*1*50us*/
        AttemptCnt++;
        if (AttemptCnt >= 100u)
        {
            break;
        }
    }

    /*KL15 KL30采集结束,切换模式*/
    if ((SysNM_KL30Monitor.FinalSts != 0u))
    {
        /*切换模式*/
        SysWakeUpMode = 0x55U;
        SysNM_KL15Monitor.FinalSts = System_LINE_KL15();
        SysNM_KL15Monitor.ActSts = System_LINE_KL15();
        SysFun_KL30Monitor.FinalSts = SysNM_KL30Monitor.FinalSts;
        SysFun_KL15Monitor.FinalSts = SysNM_KL15Monitor.ActSts;
        /*发送唤醒状态*/
        Sys_LogicProcess();
    }
}

static void System_NM_Process(void)
{
    uint8_t m8;
    static uint16_t DebpounceTimer;
    uint16_t Voltage;
    uint8_t VoltageKL30Valid;
    uint8_t VoltageKL15Valid;
    uint16_t Voltage_KL15;
    uint16_t Voltage_KL30;

    if (SysNM_KL15Monitor.ActSts != SysNM_KL15Monitor.FinalSts)
    {
        SysNM_KL15Monitor.DebounceTimer++;
        if (SysNM_KL15Monitor.DebounceTimer >= t_NM_KL15_Debounce)
        {
            SysNM_KL15Monitor.FinalSts = System_LINE_KL15();
            SysNM_KL15Monitor.DebounceTimer = 0u;
        }
    }
    else
    {
        SysNM_KL15Monitor.DebounceTimer = 0u;
        SysNM_KL15Monitor.ActSts = System_LINE_KL15();
    }

    VoltageKL30Valid = Sys_Read_KL30_Valid();
    VoltageKL15Valid = Sys_Read_KL15_Valid();

    if ((VoltageKL30Valid == 1U) && (VoltageKL15Valid == 1U))
    {
        Voltage_KL15 = Sys_Read_KL15_Voltage();
        Voltage_KL30 = Sys_Read_KL30_Voltage();
        if (Voltage_KL30 > Voltage_KL15)
        {
            Voltage = Voltage_KL30;
        }
        else
        {
            Voltage = Voltage_KL15;
        }
        if (SysNM_KL30Monitor.SumCnt < 50u)
        {
            SysNM_KL30Monitor.ActVoltage += Voltage;
            SysNM_KL30Monitor.SumCnt += 1u;
            Voltage = (uint16_t)(SysNM_KL30Monitor.ActVoltage / SysNM_KL30Monitor.SumCnt);
        }
        else
        {
            SysNM_KL30Monitor.SumCnt = 0u;
            SysNM_KL30Monitor.ActVoltage = 0u;
            SysNM_KL30Monitor.ActVoltage += Voltage;
            SysNM_KL30Monitor.SumCnt += 1u;
            Voltage = (uint16_t)(SysNM_KL30Monitor.ActVoltage / SysNM_KL30Monitor.SumCnt);
        }

        m8 = System_Calc_NMRange(Voltage);
        if (SysNM_KL30Monitor.ActSts == m8)
        {
            SysNM_KL30Monitor.DebounceTimer++;

            /*计时累计时间1000*2ms*/
            if (SysNM_KL30Monitor.DebounceTimer >= t_NM_KL30_Debounce)
            {
                SysNM_KL30Monitor.DebounceTimer = 0U;
                DebpounceTimer = 0u;
                if (SysNM_KL30Monitor.FinalSts == 9u) /* 高压 */
                {
                    if ((m8 == 9u) || (m8 == 8u))
                    {
                        SysNM_KL30Monitor.FinalSts = 9u;
                    }
                    else
                    {
                        SysNM_KL30Monitor.FinalSts = m8;
                    }
                }
                if (SysNM_KL30Monitor.FinalSts == 1u) /* 低压 */
                {
                    if ((m8 == 1u) || (m8 == 2u))
                    {
                        SysNM_KL30Monitor.FinalSts = 1u;
                    }
                    else
                    {
                        SysNM_KL30Monitor.FinalSts = m8;
                    }
                }
                /*非高低压*/
                if ((SysNM_KL30Monitor.FinalSts != 1u) && (SysNM_KL30Monitor.FinalSts != 9u))
                {
                    SysNM_KL30Monitor.FinalSts = m8;
                }
            }
        }
        else
        {
            /*计时时间清除*/
            SysNM_KL30Monitor.DebounceTimer = 0U;
            DebpounceTimer++;
            if (DebpounceTimer >= 5u)
            {
                DebpounceTimer = 0u;
                SysNM_KL30Monitor.ActSts = m8;
            }
        }
    }
}

static void System_Fun_Process(void)
{
    uint8_t m8;
    uint8_t VoltageKL30Valid;
    uint8_t VoltageKL15Valid;
    uint16_t Voltage;
    uint16_t Voltage_KL15;
    uint16_t Voltage_KL30;
    static uint16_t DebpounceTimer;

    if (SysFun_KL15Monitor.ActSts != SysFun_KL15Monitor.FinalSts)
    {
        SysFun_KL15Monitor.DebounceTimer++;
        if (SysFun_KL15Monitor.DebounceTimer >= t_FUN_KL15_Debounce)
        {
            SysFun_KL15Monitor.FinalSts = System_LINE_KL15();
            SysFun_KL15Monitor.DebounceTimer = 0u;
        }
    }
    else
    {
        SysFun_KL15Monitor.DebounceTimer = 0u;
        SysFun_KL15Monitor.ActSts = System_LINE_KL15();
    }

    VoltageKL30Valid = Sys_Read_KL30_Valid();
    VoltageKL15Valid = Sys_Read_KL15_Valid();

    if ((VoltageKL30Valid == 1U) && (VoltageKL15Valid == 1U))
    {
        Voltage_KL15 = Sys_Read_KL15_Voltage();
        Voltage_KL30 = Sys_Read_KL30_Voltage();
        if (Voltage_KL30 > Voltage_KL15)
        {
            Voltage = Voltage_KL30;
        }
        else
        {
            Voltage = Voltage_KL15;
        }
        if (SysFun_KL30Monitor.SumCnt < 50u)
        {
            SysFun_KL30Monitor.ActVoltage += Voltage;
            SysFun_KL30Monitor.SumCnt += 1u;
            Voltage = (uint16_t)(SysFun_KL30Monitor.ActVoltage / SysFun_KL30Monitor.SumCnt);
        }
        else
        {
            SysFun_KL30Monitor.SumCnt = 0u;
            SysFun_KL30Monitor.ActVoltage = 0u;
            SysFun_KL30Monitor.ActVoltage += Voltage;
            SysFun_KL30Monitor.SumCnt += 1u;
            Voltage = (uint16_t)(SysFun_KL30Monitor.ActVoltage / SysFun_KL30Monitor.SumCnt);
        }

        m8 = System_Calc_FunRange(Voltage);

        if (SysFun_KL30Monitor.ActSts == m8)
        {
            SysFun_KL30Monitor.DebounceTimer++;
            DebpounceTimer = 0u;
            /*计时累计时间1000*2ms*/
            if (SysFun_KL30Monitor.DebounceTimer >= t_FUN_KL30_Debounce) /*40202-8*/
            {
                SysFun_KL30Monitor.DebounceTimer = 0U;

                if (SysFun_KL30Monitor.FinalSts >= 7u) /* 高压 */
                {
                    if ((m8 == 9u) || (m8 == 8u) || (m8 == 7u))
                    {
                        SysFun_KL30Monitor.FinalSts = 9u;
                        SysFun_KL15Monitor.FinalSts = 0u;
                    }
                    else
                    {
                        SysFun_KL30Monitor.FinalSts = m8;
                    }
                }
                if (SysFun_KL30Monitor.FinalSts == 1u) /* 低压 */
                {
                    if ((m8 == 1u) || (m8 == 2u))
                    {
                        SysFun_KL30Monitor.FinalSts = 1u;
                        SysFun_KL15Monitor.FinalSts = 0u;
                    }
                    else
                    {
                        SysFun_KL30Monitor.FinalSts = m8;
                    }
                }
                /*非高低压*/
                if ((SysFun_KL30Monitor.FinalSts != 1u) && (SysFun_KL30Monitor.FinalSts < 7u))
                {
                    SysFun_KL30Monitor.FinalSts = m8;
                }
            }
        }
        else
        {
            /*计时时间清除*/
            SysFun_KL30Monitor.DebounceTimer = 0U;
            DebpounceTimer++;
            if (DebpounceTimer >= 5u)
            {
                DebpounceTimer = 0u;
                SysFun_KL30Monitor.ActSts = m8;
            }
        }
    }
    /*
    else
    {
        SysFun_KL30Monitor.FinalSts = 1u;
        SysFun_KL15Monitor.FinalSts = 0u;
    }*/
}

uint8_t System_NM_KL30_Status_Get(void)
{
    return SysNM_KL30Monitor.FinalSts;
}
uint8_t System_NM_KL15_Status_Get(void)
{
    return SysNM_KL15Monitor.FinalSts;
}

uint8_t System_FUN_KL30_Status_Get(void)
{
    return SysFun_KL30Monitor.FinalSts;
}
uint8_t System_FUN_KL15_Status_Get(void)
{
    return SysFun_KL15Monitor.FinalSts;
}