#include "Backlight.h"
#include "Components.h"

typedef void (*SetPwm)(Light_uint16_t Pwm);
typedef Light_uint8_t (*SetPwmEnable)(void);
typedef Light_uint8_t (*SetPwmLevel)(void);
typedef Light_uint16_t (*NtcRes)(void);

typedef struct
{
    SetPwm SetPwmCbk;           /* 设置PWM回调函数 */
    SetPwmEnable SetPwmEnCbk;   /* 设置PWM使能回调函数 */
    SetPwmLevel SetPwmLevelCbk; /* 背光等级回调函数 */
    NtcRes NtcResCbk;           /* 获取电阻值回调函数 */
} BackLightExtPara;

typedef struct
{
    SetPwm SetPwmCbk;           /* 设置PWM回调函数 */
    SetPwmEnable SetPwmEnCbk;   /* 设置PWM使能回调函数 */
    SetPwmLevel SetPwmLevelCbk; /* 背光等级回调函数 */
    NtcRes NtcResCbk;
    Light_uint8_t BacklightEn;     /* 背光使能 */
    Light_uint16_t BacklightPwm;   /* 背光PWM */
    Light_uint16_t BacklightLevel; /* 背光等级 */
} _Backlight_Op;

_Backlight_Op Backlight_Operate;

#define BACK_LIGHT_Val_1 (( 100 * Backlight_Operate.BacklightPwm ) / 100 )
#define BACK_LIGHT_Val_2 (( 200 * Backlight_Operate.BacklightPwm ) / 100 )
#define BACK_LIGHT_Val_3 (( 400 * Backlight_Operate.BacklightPwm ) / 100 )
#define BACK_LIGHT_Val_4 (( 600 * Backlight_Operate.BacklightPwm ) / 100 )
#define BACK_LIGHT_Val_5 (( 800 * Backlight_Operate.BacklightPwm ) / 100 )

#define LIGHT_DATA_TIME 10u /*这里填写多长时间采集一个数据,单位ms*/
#define LIGHT_DATA_NUM 20u  /*燃油电阻采集数据总数 最大255*/
#define LIGHT_CAL_START 5u  /*数据排序后取中间部分计算平均:起始*/
#define LIGHT_CAL_END 15u   /*数据排序后取中间部分计算平均:结束*/
Light_uint8_t LightADCompleteFlg = 0u;
Light_uint16_t LightR = 0u;
Light_uint16_t LightR_Status = 0;
Light_uint16_t LightR_Status_Count = 0u;
Light_uint16_t NtcDataCount;
Light_uint16_t NtcData[LIGHT_DATA_NUM];
typedef struct
{
    Light_uint16_t Temperature; /* 温度 */
    Light_uint16_t Resistance;  /* 阻值 */
} _st_Backlight;

typedef struct
{
    Light_uint16_t BacklightLevel; /* 背光等级 */
    Light_uint16_t BacklightDuty;  /* 背光占空比 */
} _st_BacklightLevel;

#define Backlight_Max 10
#define BacklightLevel_Max 5
_st_Backlight BacklightTable[Backlight_Max] =
    {
        /*温度   阻值 */
        {550,  2708},
        {600,  2602},
        {650,  2500},
        {700,  2043},
        {750,  2310},
        {800,  2221},
        {850,  2136},
        {900,  2055},
        {950,  1977},
        {1000, 1902},
};
_st_BacklightLevel BacklightLevelTable[BacklightLevel_Max] =
    {
        /*背光等级   背光占空比 */
        {1, 100},
        {2, 200},
        {3, 400},
        {4, 600},
        {5, 800},


};

void Data_Light_Res_service(Light_uint8_t deltaTime)//获取光感阻值,并做平均
{
    uint16_t LightRes = 0;
    uint8_t i, j;
    uint32_t temp32;
    static uint16_t timeCount = 0;
    if (timeCount >= LIGHT_DATA_TIME)
    {
        timeCount = 0;
        if (NtcDataCount < LIGHT_DATA_NUM)
        {
            /*获取光敏电阻*/
            LightRes = ADC_Read_Signal(ADC_CH_LIGHT_SENSITIVE); // ADC_Read_Signal(ADC_CH_FUEL1);
            /*四舍五入*/
            if (LightRes < 32000)
            {
                if (LightRes % 10 >= 5)
                {
                    LightRes += 5;
                }
            }
            else
            {
                LightRes = 32000;
            }

            /*由小到大插入数据*/
            for (i = 0; i < NtcDataCount; i++)
            {
                if (LightRes < NtcData[i])
                {
                    break;
                }
            }
            for (j = NtcDataCount; j > i; j--)
            {
                NtcData[j] = NtcData[j - 1];
            }
            NtcData[i] = LightRes;
            NtcDataCount++;
        }
        else
        {
            /*一组数据采集完毕,取中间部分计算平均值*/
            temp32 = 0;
            for (i = LIGHT_CAL_START; i < LIGHT_CAL_END; i++)
            {
                temp32 += NtcData[i];
            }
            LightR = (uint16_t) (temp32 / (LIGHT_CAL_END - LIGHT_CAL_START));
            NtcDataCount = 0;
            LightADCompleteFlg = 1;
        }
    }
    timeCount += deltaTime;
    if(SYS_OPR_STAT_IGN_ON)
    {
        if(Menu_Item_Select_Get(MENU_ITEM_SELECT_AUTO))
        {
            if(LightADCompleteFlg)
            {
                if(LightR <= 800)
                {
                    LightR_Status_Count++;
                    if(LightR_Status_Count>=150)
                    {
                        LightR_Status_Count = 0;
                        LightR_Status = 0;
                    }          
                }
                else if(LightR > 800)
                {
                    LightR_Status_Count++;
                    if(LightR_Status_Count>=150)
                    {
                        LightR_Status_Count = 0;
                        LightR_Status = 1;
                    }            
                }
                if(LightR_Status == 0)
                {
                    TimerM_PWM_set_duty(TIMERM_COUNTER1, TIMERM_CHB, BACK_LIGHT_Val_2);                            
                }
                else
                {
                    TimerM_PWM_set_duty(TIMERM_COUNTER1, TIMERM_CHB, BACK_LIGHT_Val_5); 
                }
            }
        }
        else if(Menu_Item_Select_Get(MENU_ITEM_BACKLIGHT_AUTO))
        {
            if(Backlight_SetPwmLevel() == 1U)
            {
                TimerM_PWM_set_duty(TIMERM_COUNTER1, TIMERM_CHB, BACK_LIGHT_Val_1);
            }
            else if(Backlight_SetPwmLevel() == 2U)
            {
                TimerM_PWM_set_duty(TIMERM_COUNTER1, TIMERM_CHB, BACK_LIGHT_Val_2);
            }
            else if(Backlight_SetPwmLevel() == 3U)
            {
                TimerM_PWM_set_duty(TIMERM_COUNTER1, TIMERM_CHB, BACK_LIGHT_Val_3);
            }
            else if(Backlight_SetPwmLevel() == 4U)
            {
                TimerM_PWM_set_duty(TIMERM_COUNTER1, TIMERM_CHB, BACK_LIGHT_Val_4);
            }
            else if(Backlight_SetPwmLevel() == 5U)
            {
                TimerM_PWM_set_duty(TIMERM_COUNTER1, TIMERM_CHB, BACK_LIGHT_Val_5);
            }
        }
        else
        {
            BackLight_Process();
        }
    }
    else
    {
        TimerM_PWM_set_duty(TIMERM_COUNTER1, TIMERM_CHB, 0);
    }
}



Light_uint16_t GetBacklightDutyByLevel(Light_uint16_t level)
{
    for (Light_uint8_t i = 0; i < BacklightLevel_Max; ++i)
    {
        if (BacklightLevelTable[i].BacklightLevel == level)
        {
            return BacklightLevelTable[i].BacklightDuty;
        }
    }
    return 0;
}





/* 设置PWM回调函数 */
void Backlight_SetPwm(Light_uint16_t Pwm)
{
    TimerM_PWM_set_duty(TIMERM_COUNTER1, TIMERM_CHB, Pwm);
}

/* 设置PWM使能回调函数 */
Light_uint8_t Backlight_SetPwmEn(void)
{
    
    return 1;
}

/* 背光等级回调函数 */
Light_uint8_t Backlight_SetPwmLevel(void)
{
    Light_uint8_t Backlight_PwmLevel;

    if(LightR > 0 && LightR <= 400)
    {
        Backlight_PwmLevel = 1U;
    }
    else if(LightR > 400 && LightR <= 800)
    {
        Backlight_PwmLevel = 2U;
    }
    else if(LightR > 800 && LightR <= 1400)
    {
        Backlight_PwmLevel = 3U;
    }
    else if(LightR > 1400 && LightR <= 2000)
    {
        Backlight_PwmLevel = 4U;
    }
    else if(LightR > 2000 && LightR <= 2600)
    {
        Backlight_PwmLevel = 5U;
    }
    return Backlight_PwmLevel;
}

/* 获取电阻值回调函数 */
Light_uint16_t Backlight_NtcRes(void)
{
    Light_uint16_t u8NtcRes = ADC_Read_Signal(ADC_CH_NTC_TEMP);
    return u8NtcRes;
}

void Backlight_Init(BackLightExtPara *backlightInit)
{
    Backlight_Operate.SetPwmCbk = backlightInit->SetPwmCbk;
    Backlight_Operate.SetPwmEnCbk = backlightInit->SetPwmEnCbk;
    Backlight_Operate.SetPwmLevelCbk = backlightInit->SetPwmLevelCbk;
    Backlight_Operate.NtcResCbk = backlightInit->NtcResCbk;
}

void Backlight_KL30_Wakeup_Init(void)
{
    BackLightExtPara pFunc;

    pFunc.SetPwmCbk        = Backlight_SetPwm;
    pFunc.SetPwmEnCbk      = Backlight_SetPwmEn;
    pFunc.SetPwmLevelCbk   = Backlight_SetPwmLevel;
    pFunc.NtcResCbk        = Backlight_NtcRes;

    Backlight_Init(&pFunc);
}



/**
 * 根据给定的背光表和输入电阻值,获取对应的温度值。
 * 这个函数通过线性插值方法在背光表中查找与输入电阻最接近的温度值。
 * @param backlightTable 背光表,包含电阻和对应温度的数组。
 * @param size 背光表的大小,即数组的元素个数。
 * @param input 输入的电阻值。
 * @return 返回对应的温度值。
 */
Light_uint16_t Get_Ntc_Temp(_st_Backlight *backlightTable, Light_uint8_t size, Light_uint16_t input)
{
    Light_uint16_t result = 0;
    Light_uint32_t temp = 0;
    Light_uint8_t i = 0;

    if (input >= backlightTable[0].Resistance)
    {
        result = backlightTable[0].Temperature;
    }
    else if (input <= backlightTable[size - 1].Resistance)
    {
        result = backlightTable[size - 1].Temperature;
    }
    else
    {
        for (i = 0; i < size - 1; i++)
        {
            if ((input < backlightTable[i].Resistance) && (input >= backlightTable[i + 1].Resistance))
            {
                temp = backlightTable[i + 1].Temperature - backlightTable[i].Temperature;
                temp *= (backlightTable[i].Resistance - input);
                temp /= (backlightTable[i].Resistance - backlightTable[i + 1].Resistance);
                temp += backlightTable[i].Temperature;
                result = (Light_uint16_t)temp;
                break;
            }
        }
    }

    return result;
}

Light_uint16_t Get_Pwm_Factor_Optimized(Light_uint16_t CurrentTemp)
{
    if (CurrentTemp >= 900)
    {
        return 10;
    }
    if (CurrentTemp >= 880 && CurrentTemp <= 890)
    {
        return 20;
    }
    if (CurrentTemp >= 850 && CurrentTemp <= 860)
    {
        return 70;
    }
    if (CurrentTemp >= 800 && CurrentTemp <= 830)
    {
        return 75;
    }
    if (CurrentTemp >= 750 && CurrentTemp <= 780)
    {
        return 80;
    }
    if (CurrentTemp >= 700 && CurrentTemp <= 730)
    {
        return 85;
    }
    if (CurrentTemp >= 650 && CurrentTemp <= 680)
    {
        return 90;
    }
    if (CurrentTemp >= 600 && CurrentTemp <= 630)
    {
        return 95;
    }
    if (CurrentTemp < 580)
    {
        return 100;
    }

    return 100;
}

typedef struct
{
    Light_uint8_t destFactor;
    Light_uint8_t curFactor;
    Light_uint16_t NtcDelayTimer;
    Light_uint16_t u16DialcurDuty;
    Light_uint16_t u16DialdestDuty;
    Light_uint16_t u16DialDampingTimer;
} _st_BacklightFactor_Ctrl;

_st_BacklightFactor_Ctrl BacklightFactorCtrl;

/**
 * @brief 实现数据的渐变效果
 * 该函数用于更新当前值,使其逐渐接近目标值,渐变的步长由step参数控制。同时,通过timer参数来实现一定的延迟效果,
 * 仅当计时器达到或超过预设的timedelay时,才会进行一次渐变操作。这有助于平滑数据的变化,避免突变。
 * @param cur 当前值的指针,函数将更新这个值
 * @param dest 目标值,当前值将逐渐变化到这个值
 * @param step 每次变化的步长
 * @param timer 计时器的指针,用于实现变化的延迟
 * @param timedelay 延迟的时间阈值,当计时器达到或超过这个值时,才会进行变化
 */
void U16_Data_Gradient(Light_uint16_t *cur, Light_uint16_t dest, Light_uint16_t step, Light_uint16_t *timer, const Light_uint16_t timedelay)
{
    if (*cur > dest)
    {
        if ((*cur - dest) > step)
        {
            if (*timer >= timedelay)
            {
                (*cur) -= step;
                (*timer) = 0;
            }
            else
            {
                (*timer)++;
            }
        }
        else
        {
            *cur = dest;
            *timer = 0;
        }
    }
    else
    {
        if ((dest - *cur) > step)
        {
            if (*timer >= timedelay)
            {
                (*cur) += step;
                (*timer) = 0;
            }
            else
            {
                (*timer)++;
            }
        }
        else
        {
            *cur = dest;
            *timer = 0;
        }
    }
}

void BackLight_Service(void)
{

    Light_uint16_t CurrentTemp = 0;
    Light_uint16_t Factor = 0;

    if (Backlight_Operate.NtcResCbk != Backlight_NULL)
    {
        CurrentTemp = Get_Ntc_Temp(BacklightTable, sizeof(BacklightTable) / sizeof(Light_uint16_t), Backlight_Operate.NtcResCbk());
    }
    else
    {
        CurrentTemp = 0XFFFF; /* 无效不执行NTC策略 */
    }

    /* 根据外部传入背光等级获取对应占空比 */
    if (Backlight_Operate.SetPwmLevelCbk != Backlight_NULL)
    {
        Backlight_Operate.BacklightPwm = GetBacklightDutyByLevel(Backlight_Operate.SetPwmLevelCbk());
    }

    if (Backlight_Operate.SetPwmEnCbk != Backlight_NULL)
    {
        Backlight_Operate.BacklightEn = Backlight_Operate.SetPwmEnCbk();
    }

    if (Backlight_Operate.BacklightEn == 1)
    {

        if (CurrentTemp != 0XFFFF)
        {

            BacklightFactorCtrl.destFactor = Get_Pwm_Factor_Optimized(CurrentTemp);

            if ((BacklightFactorCtrl.curFactor < BacklightFactorCtrl.destFactor) && (CurrentTemp <= BacklightTable[0].Temperature))
            {
                if (BacklightFactorCtrl.NtcDelayTimer <= 400)
                    BacklightFactorCtrl.NtcDelayTimer++;
                else
                {
                    BacklightFactorCtrl.NtcDelayTimer = 0;
                    BacklightFactorCtrl.curFactor++;
                }

                if (BacklightFactorCtrl.curFactor >= BacklightFactorCtrl.destFactor)
                    BacklightFactorCtrl.curFactor = BacklightFactorCtrl.destFactor;
            }
            else if (BacklightFactorCtrl.curFactor > BacklightFactorCtrl.destFactor)
            {
                if (BacklightFactorCtrl.NtcDelayTimer <= 200)
                    BacklightFactorCtrl.NtcDelayTimer++;
                else
                {
                    BacklightFactorCtrl.NtcDelayTimer = 0;
                    BacklightFactorCtrl.curFactor--;
                }

                if (BacklightFactorCtrl.curFactor <= BacklightFactorCtrl.destFactor)
                    BacklightFactorCtrl.curFactor = BacklightFactorCtrl.destFactor;
            }

            BacklightFactorCtrl.u16DialdestDuty = Backlight_Operate.BacklightPwm * BacklightFactorCtrl.curFactor / 100;

            if (BacklightFactorCtrl.u16DialdestDuty < 50)
            {
                BacklightFactorCtrl.u16DialdestDuty = 50;
            }

            if (CurrentTemp <= BacklightTable[0].Temperature)
            {
                BacklightFactorCtrl.u16DialcurDuty = BacklightFactorCtrl.u16DialdestDuty;
            }
            else
            {
                if (BacklightFactorCtrl.u16DialcurDuty < 100)
                {
                    BacklightFactorCtrl.u16DialcurDuty = BacklightFactorCtrl.u16DialdestDuty;
                }
                else
                {
                    U16_Data_Gradient((Light_uint16_t *)&BacklightFactorCtrl.u16DialcurDuty, BacklightFactorCtrl.u16DialdestDuty, 1u, (Light_uint16_t *)&BacklightFactorCtrl.u16DialDampingTimer, 1u);
                }
            }
            Backlight_Operate.BacklightPwm = BacklightFactorCtrl.u16DialcurDuty;

            // Backlight_Operate.SetPwmCbk(Backlight_Operate.BacklightPwm);
        }
        else
        {
            /* 无NTC策略 直接根据当前背光等级调整PWM */
            Backlight_Operate.BacklightPwm = 100U;
            // Backlight_Operate.SetPwmCbk(Backlight_Operate.BacklightPwm);
        }
    }
    else
    {
        Backlight_Operate.BacklightPwm = 100U;
        // Backlight_Operate.SetPwmCbk(0);
    }
}

void BackLight_Process(void)
{
    if(SYS_OPR_STAT_IGN_ON)
    {
        if(Menu_Item_Select_Get(MENU_ITEM_BACKLIGHT_5) == 1)
        {
            TimerM_PWM_set_duty(TIMERM_COUNTER1, TIMERM_CHB, (BACK_LIGHT_Val_5));
        }
        else if(Menu_Item_Select_Get(MENU_ITEM_BACKLIGHT_4) == 1)
        {
            TimerM_PWM_set_duty(TIMERM_COUNTER1, TIMERM_CHB, BACK_LIGHT_Val_4);
        }
        else if(Menu_Item_Select_Get(MENU_ITEM_BACKLIGHT_3) == 1)
        {
            TimerM_PWM_set_duty(TIMERM_COUNTER1, TIMERM_CHB, BACK_LIGHT_Val_3);
        }
        else if(Menu_Item_Select_Get(MENU_ITEM_BACKLIGHT_2) == 1)
        {
            TimerM_PWM_set_duty(TIMERM_COUNTER1, TIMERM_CHB, BACK_LIGHT_Val_2);
        }
        else if(Menu_Item_Select_Get(MENU_ITEM_BACKLIGHT_1) == 1)
        {
            TimerM_PWM_set_duty(TIMERM_COUNTER1, TIMERM_CHB, BACK_LIGHT_Val_1);
        }
        else
        {
            TimerM_PWM_set_duty(TIMERM_COUNTER1, TIMERM_CHB, BACK_LIGHT_Val_4);
        }
    }
    else
    {
        TimerM_PWM_set_duty(TIMERM_COUNTER1, TIMERM_CHB, 0);
    }
}