/******************************************************************************/
/*                        -- 居加居--                        */
/*
//  文件名：
//  说明：
//  编写人员：kinve
//  编写日期：2018-8-21
//  程序维护：
//  维护记录：
//
//
*/
// 免责声明：
// (c) Anxinke Corporation. All rights reserved.
/******************************************************************************/
#include "multi_led.h"

#define EVENT_CB(state)   if(handle->led_set_gpio) handle->led_set_gpio((bool)state)

//button handle list head.
static struct Led* head_handle = NULL;

/**
  * @brief  Initializes the button struct handle.
  * @param  handle: the button handle strcut.
  * @param  pin_level: read the HAL GPIO of the connet button level.
  * @param  active_level: pressed GPIO level.
  * @retval None
  */
void led_init_Head ( void )
{
    head_handle = NULL;
}
void led_init ( struct Led* handle, LedCallback led_set_gpio )
{
    memset ( handle, 0, sizeof ( struct Led ) );
    handle->led_set_gpio = led_set_gpio;
}

void led_set_state ( struct Led* handle, u8 ID, u8 OnOff, u8 Type, u16 FlashTime, u16 CloseTime, bool Res )
{
    if ( Type < LED_STATE_MAX )
    {
        handle->Play.ID = ID;
        handle->Play.Type = Type;

        if ( Type != LED_STATE4_NOT )
        {
            handle->Play.OnOff = OnOff;
        }

        handle->Play.FlashTime = FlashTime;
        handle->Play.CloseTime = CloseTime;
        handle->Play.Count = 0;
        handle->Play.Res = Res;
    }
}


/**
  * @brief  Button driver core function, driver state machine.
  * @param  handle: the button handle strcut.
  * @retval None
  */
void led_handler ( struct Led* handle )
{
    switch ( handle->Play.Type )
    {
    case LED_STATE0_OFF: 	//关
        EVENT_CB ( false );
        handle->Play.Type = LED_STATE_MAX;
        break;

    case LED_STATE1_ON: 	//开
        EVENT_CB ( true );
        handle->Play.Type = LED_STATE_MAX;
        break;

    case LED_STATE2_FLASH: //闪烁
        handle->Play.Count += LED_SCAN;

        if ( handle->Play.Count >= handle->Play.FlashTime )
        {
            handle->Play.Count = 0;
            EVENT_CB ( handle->Play.OnOff );
            handle->Play.OnOff = !handle->Play.OnOff;
        }

        break;

    case LED_STATE3_CONUT: //定时开关
        if ( handle->Play.CloseTime > 0 )
        {
            handle->Play.CloseTime -= LED_SCAN;
            EVENT_CB ( handle->Play.Res );	//开始
        }
        else
        {
            handle->Play.CloseTime = 0;
            EVENT_CB ( !handle->Play.Res );	//结束，与结果相反
            handle->Play.Type = LED_STATE_MAX;
        }

        break;

    case LED_STATE4_NOT: 	//取反
        EVENT_CB ( !handle->Play.OnOff );
        handle->Play.Type = LED_STATE_MAX;
        break;

    case LED_STATE5_FLASH_DELAY: 	//闪烁,延时关闭
        if ( handle->Play.CloseTime > 0 )
        {
            handle->Play.CloseTime -= LED_SCAN;
            //闪烁
            handle->Play.Count += LED_SCAN;		//开始

            if ( handle->Play.Count >= handle->Play.FlashTime )
            {
                handle->Play.Count = 0;
                EVENT_CB ( handle->Play.OnOff );
                handle->Play.OnOff = !handle->Play.OnOff;
            }
        }
        else
        {
            handle->Play.CloseTime = 0;
            EVENT_CB ( handle->Play.Res );	//结束，与结果
            handle->Play.Type = LED_STATE_MAX;
        }

        break;
    }
}

/**
  * @brief  Start the button work, add the handle into work list.
  * @param  handle: target handle strcut.
  * @retval 0: succeed. -1: already exist.
  */
int led_start ( struct Led* handle )
{
    struct Led* target = head_handle;

    while ( target )
    {
        if ( target == handle ) return -1;	//already exist.

        target = target->next;
    }

    handle->next = head_handle;
    head_handle = handle;
    return 0;
}

/**
  * @brief  Stop the button work, remove the handle off work list.
  * @param  handle: target handle strcut.
  * @retval None
  */
void led_stop ( struct Led* handle )
{
    struct Led** curr;

    for ( curr = &head_handle; *curr; )
    {
        struct Led* entry = *curr;

        if ( entry == handle )
        {
            *curr = entry->next;
//			free(entry);
        }
        else
        {
            curr = &entry->next;
        }
    }
}

/**
  * @brief  background ticks, timer repeat invoking interval 5ms.
  * @param  None.
  * @retval None
  */
void led_ticks()
{
    struct Led* target;

    for ( target = head_handle; target; target = target->next )
    {
        led_handler ( target );
    }
}

