/*************************************************************************************
 * @File Name: app_led.c
 * @brief    LED使用的app程序
 * @Version : 1.0
 * @Create Date : 2024-12-02
 * @Author : TianyunV1 email : 3026007337@qq.com
 * 
 * @copyright Copyright (c) 2024 Tianyun Mountain
 * 
 * modification history :
 * Date:   Version:  Author:  Description:   
 *************************************************************************************/
#include "app_led.h"
#include "mw_led.h"
#include "mw_soft_timer.h"
#include "mw_debug_log.h"
#include "app_global.h"
#include "stdint.h"
// #include "mw_soft_timer.h"

// #include "bsp.h"


#include "mw_dehy_test.h"

#define LED_INDICATOR                   (LED1)
#define LED_RGB_RED                     (RGB_RED)
#define LED_RGB_GREEN                   (RGB_GREEN)
#define LED_RGB_BLUE                    (RGB_BLUE)



#define LED_RGB_CHANGE_PERIOD           (5u)

/* led的灯状态 */
typedef enum
{
    led_mode_idle = 0,
    led_mode_running,
    led_mode_fault,

    led_mode_num
}app_led_mode_enum;





static app_led_mode_enum led_indicator_mode;

static mw_led_t led_runMode_indicator;

static uint8_t tmp_indicator_single_mode_state = 0;
// 运行指示器 局部状态机
static uint8_t indicator_local_machState = 0;
static uint8_t rgb_local_machState = 0;

//static uint8_t xqqDebug_indicator_mode = 0;
// 故障码
uint8_t error_code_val = 5;
// 运行状态
uint8_t run_state = 0;

uint16_t current_speed = 0;

uint16_t acc_value = 3;

// uint16_t target_speed = 800;

uint16_t init_cmd = 0;

uint16_t dehy_enable = 0;

uint16_t dehy_init_enable = 0;

uint16_t speed_limit_val = 0;
/*************************************************************************************
 * @brief    idle 状态 指示灯的状态
 * @param[in/out] led  【参数注释】led对象
 * @param[in/out] timer【参数注释】timer对象
 * 
 * @warning  【不可重入,阻塞等警告】
 * @note     【重大修改】
  *************************************************************************************/
void led_indicator_idle_process(mw_led_t led, mw_led_timer_t timer)
{
    
    switch(indicator_local_machState)
    {
        case 0:
            // 灯亮
            led.on();
            // 开始计时
            timer.start_timer(1000);
            // 进入下个状态
            indicator_local_machState = 1;
            break;
        case 1:
            // 时间到？
            if(timer.get_over_time_flag() > 0)
            {
                // 灯灭
                led.off();
                // 开始计时
                timer.start_timer(1000);
                // 进入下个状态
                indicator_local_machState = 2;
            }
            break;
        case 2:
            // 时间到？
            if(timer.get_over_time_flag() > 0)
            {
                
                // 进入下个状态
                indicator_local_machState = 0;
            }
            break;
        default:
            indicator_local_machState = 0;
            break;
    }
}

/*************************************************************************************
 * @brief    run 状态 指示灯的状态
 * @param[in/out] led  【参数注释】led对象
 * @param[in/out] timer【参数注释】timer对象
 * 
 * @warning  【不可重入,阻塞等警告】
 * @note     【重大修改】
  *************************************************************************************/
void led_indicator_run_process(mw_led_t led, mw_led_timer_t timer)
{
    
    switch(indicator_local_machState)
    {
        case 0:
            // 灯亮
            led.on();
            // 开始计时
            timer.start_timer(500);
            // 进入下个状态
            indicator_local_machState = 1;
            break;
        case 1:
            // 时间到？
            if(timer.get_over_time_flag() > 0)
            {
                // 灯灭
                led.off();
                // 开始计时
                timer.start_timer(500);
                // 进入下个状态
                indicator_local_machState = 2;
            }
            break;
        case 2:
            // 时间到？
            if(timer.get_over_time_flag() > 0)
            {
                
                // 进入下个状态
                indicator_local_machState = 0;
            }
            break;
        default:
            indicator_local_machState = 0;
            break;
    }
}

/*************************************************************************************
 * @brief    fault 状态 指示灯的状态
 * @param[in/out] led  【参数注释】led对象
 * @param[in/out] timer【参数注释】timer对象
 * 
 * @warning  【不可重入,阻塞等警告】
 * @note     【重大修改】
  *************************************************************************************/
void led_indicator_fault_process(mw_led_t led, mw_led_timer_t timer)
{
    static uint8_t fault_loop_times = 0;

    switch(indicator_local_machState)
    {
        case 0:
            // 初始化后面要闪的次数
            fault_loop_times = 0;
            // 灯先关1000ms 然后开始闪灯
            led.off();
            // 开始计时
            timer.start_timer(2000);
            // 进入下个状态
            indicator_local_machState = 1;
            break;
        case 1:
            if(timer.get_over_time_flag() > 0)
            {
                // 进入下个状态
                indicator_local_machState = 2;
            }
            break;
        case 2:
            // 灯亮
            led.on();
            // 开始计时
            timer.start_timer(300);
            // 进入下个状态
            indicator_local_machState = 3;
            break;
        case 3:
            // 时间到？
            if(timer.get_over_time_flag() > 0)
            {
                // 灯灭
                led.off();
                // 开始计时
                timer.start_timer(300);
                // 进入下个状态
                indicator_local_machState = 4;
            }
            break;
        case 4:
            if(timer.get_over_time_flag() > 0)
            {
                // 已经闪的次数自增
                fault_loop_times++;
                // 达到了故障码要闪的次数
                if(fault_loop_times >= error_code_val)
                {
                    // 闪的次数够了，不闪了
                    indicator_local_machState = 5;
                }
                else
                {
                    // 闪的次数不够， 继续闪
                    indicator_local_machState = 2;
                }
            }
            break;
        default:
            indicator_local_machState = 0;
            break;
    }
}

/*************************************************************************************
 * @brief    led指示器 
 * 
 * @warning  【不可重入,阻塞等警告】
 * @note     【重大修改】
  *************************************************************************************/
void app_led_indicator_process(void)
{
    // led 控件 作为形参 塞进去 使用
    mw_led_t led = mw_get_led_obj(LED_INDICATOR);
    mw_led_timer_t timer = mw_get_led1_timer_obj();
    
    switch(led_indicator_mode)
    {
        // 空闲模式 亮灯逻辑
        case led_mode_idle:
            led_indicator_idle_process(led, timer);
            break;
        // 运行模式 亮灯逻辑
        case led_mode_running:
            led_indicator_run_process(led, timer);
            break;
        // 故障模式 亮灯逻辑
        case led_mode_fault:
            led_indicator_fault_process(led, timer);
            break;
        default:
            break;
    }
}


/*************************************************************************************
 * @brief    indicator状态管理
 * 
 * @warning  【不可重入,阻塞等警告】
 * @note     【重大修改】
  *************************************************************************************/
void app_led_indicator_state_manage(void)
{
    static uint8_t pre_state = 0;

    if(run_state != pre_state)
    {
        if(run_state == 0)
        {
            led_indicator_mode = led_mode_idle;
        }
        else if(run_state == 1)
        {
            led_indicator_mode = led_mode_running;
        }
        else if(run_state == 2)
        {
            led_indicator_mode = led_mode_fault;
        }
        else
        {
            ;
        }

        indicator_local_machState = 0;
    }
    // 更新pre_state
    pre_state = run_state;
}

/*************************************************************************************
 * @brief    led状态指示器 任务
 * 
 * @warning  【不可重入,阻塞等警告】
 * @note     【重大修改】
  *************************************************************************************/
void app_led_indicator_task(void)
{
    
    app_led_indicator_state_manage();

    app_led_indicator_process();



    if(dehy_init_enable > 0)
    {
        speed_limit_val = supershake_speed_limit(LOGIC_INIT);
        dehy_speed_up(LOGIC_INIT, acc_value, current_speed, speed_limit_val);

        dehy_init_enable = 0;
    }

    if(dehy_enable > 0)
    {
        speed_limit_val = supershake_speed_limit(LOGIC_RUN);
        dehy_speed_up(LOGIC_RUN, acc_value, current_speed, speed_limit_val);
    }
}

/*************************************************************************************
 * @brief    led app应用类 初始化逻辑
 * 
 * @warning  【不可重入,阻塞等警告】
 * @note     【重大修改】
  *************************************************************************************/
void app_led_init(void)
{
    led_indicator_mode = led_mode_idle;
    indicator_local_machState = 0;
    rgb_local_machState = 0;
}

/*************************************************************************************
 * @brief    渐变RGB灯例程
 * @return * void      【返回值注释】
 * 
 * @warning  【不可重入,阻塞等警告】
 * @note     【重大修改】
  *************************************************************************************/
void app_RGB_process(void)
{
    static uint16_t tmp_red_val;
    static uint16_t tmp_green_val;
    static uint16_t tmp_blue_val;

    mw_led_timer_t rgb_timer = mw_get_rgb_timer_obj();
    mw_led_t rgb_red = mw_get_led_obj(LED_RGB_RED);
    mw_led_t rgb_green = mw_get_led_obj(LED_RGB_GREEN);
    mw_led_t rgb_blue = mw_get_led_obj(LED_RGB_BLUE);
    switch(rgb_local_machState)
    {
        case 0:
            tmp_red_val = 255;
            tmp_green_val = 0;
            tmp_blue_val = 0;
            rgb_timer.start_timer(LED_RGB_CHANGE_PERIOD);
            // mw_softTimer_RGB_config(LED_RGB_CHANGE_PERIOD);
            rgb_local_machState = 1;
            break;
        case 1:
            // if(mw_softTimer_get_RGB_timeUp_flag() > 0)
            if(rgb_timer.get_over_time_flag())
            {
                tmp_red_val--;
                tmp_green_val++;
                if(tmp_red_val == 0)
                {
                    rgb_local_machState = 2;
                }
                else
                {
                    // mw_softTimer_RGB_config(LED_RGB_CHANGE_PERIOD);
                    rgb_timer.start_timer(LED_RGB_CHANGE_PERIOD);
                }
            }
            break;
        case 2:
            tmp_red_val = 0;
            tmp_green_val = 255;
            tmp_blue_val = 0;
            // mw_softTimer_RGB_config(LED_RGB_CHANGE_PERIOD);
            rgb_timer.start_timer(LED_RGB_CHANGE_PERIOD);
            rgb_local_machState = 3;
            break;
        case 3:
            // if(mw_softTimer_get_RGB_timeUp_flag() > 0)
            if(rgb_timer.get_over_time_flag())
            {
                tmp_green_val--;
                tmp_blue_val++;
                if(tmp_green_val == 0)
                {
                    rgb_local_machState = 4;
                }
                else
                {
                    // mw_softTimer_RGB_config(LED_RGB_CHANGE_PERIOD);
                    rgb_timer.start_timer(LED_RGB_CHANGE_PERIOD);
                }
            }
            break;
        case 4:
            tmp_red_val = 0;
            tmp_green_val = 0;
            tmp_blue_val = 255;
            // mw_softTimer_RGB_config(LED_RGB_CHANGE_PERIOD);
            rgb_timer.start_timer(LED_RGB_CHANGE_PERIOD);
            rgb_local_machState = 5;
            break;
        case 5:
            // if(mw_softTimer_get_RGB_timeUp_flag() > 0)
            if(rgb_timer.get_over_time_flag())
            {
                tmp_blue_val--;
                tmp_red_val++;
                if(tmp_blue_val == 0)
                {
                    rgb_local_machState = 0;
                }
                else
                {
                    // mw_softTimer_RGB_config(LED_RGB_CHANGE_PERIOD);
                    rgb_timer.start_timer(LED_RGB_CHANGE_PERIOD);
                }
            }
            break;
        default:
            tmp_red_val = 0;
            tmp_green_val = 0;
            tmp_blue_val = 0;
            break;
    }
    // mw_setRGB_RedBrightness(tmp_red_val);
    rgb_red.changeBrightness(tmp_red_val);
    // mw_setRGB_GreenBrightness(tmp_green_val);
    rgb_green.changeBrightness(tmp_green_val);
    // mw_setRGB_BlueBrightness(tmp_blue_val);
    rgb_blue.changeBrightness(tmp_blue_val);

}

