/******************************************************************************
文 件 名：Key.c
功能描述：按键检测函数库文件
作    者：张暄
版    本：V1.0
日    期：2016.11.21
******************************************************************************/

#include "Key.h"
#include "AW93015.h"
#include "gpio.h"

KeyDetectStruct  KeyStatus[KEY_TOTAL_NUMBER];

/******************************************************************************
函数名：Key_Status_Init
功  能：初始化按键状态
参  数：无
返回值：无
******************************************************************************/
void Key_Status_Init(void)
{
  uint8_t i;
  
  for (i = 0; i < KEY_TOTAL_NUMBER; i++)
  {
    KeyStatus[i].UpdateEnable  = 1;
    KeyStatus[i].Timer         = 0;
    KeyStatus[i].IdleTimer     = 0;
    KeyStatus[i].FinalStatus   = KEY_IDLE;
    KeyStatus[i].CurrentStatus = KEY_IDLE;
  }
}

/******************************************************************************
函数名：Get_Key1_Line_In_Sts
功  能：获取按键电平状态
参  数：无
返回值：无
******************************************************************************/
uint8_t Get_Key1_Line_In_Sts(void)
{
    uint8_t u8Result = 0u;
    u8Result = (GET_Key_Prosess() == 1) ? 1 : 0;
    return u8Result;
} 
/******************************************************************************
函数名：Get_Key1_Line_In_Sts
功  能：获取按键电平状态
参  数：无
返回值：无
******************************************************************************/
uint8_t Get_Key2_Line_In_Sts(void)
{
    uint8_t u8Result = 0u;
    u8Result = (GET_Key_Prosess() == 2) ? 1 : 0;
    return u8Result;
} 
/******************************************************************************
函数名：Key_Status_Detect_Service
功  能：按键检测服务函数,用于检测并更新按键的状态
参  数：无
返回值：无
******************************************************************************
注  意：该服务函数必须每10ms被调用一次
******************************************************************************/
void Key_Status_Detect_Service(void)
{
  uint8_t   i;
  volatile  uint8_t   pSig = 0;
	
  
  for (i = 0; i < KEY_TOTAL_NUMBER; i++)
  {
    if(KeyAttrTable[i].InputSignal != (( void * )0) ){
        pSig = KeyAttrTable[i].InputSignal();
    }

    
    if (pSig)
    {
      if (KeyStatus[i].Timer < 0xFFFF)
        KeyStatus[i].Timer++;
        
      switch (KeyAttrTable[i].HoldDetMode)
      {
        case KEY_HOLD_DISABLE     : if (KeyAttrTable[i].DoubleDetEn)
                                    {
                                      if (KeyStatus[i].IdleTimer)
                                      {
                                        KeyStatus[i].CurrentStatus = KEY_DOUBLE;
                                        if (KeyStatus[i].UpdateEnable)
                                        {
                                          KeyStatus[i].FinalStatus  = KEY_DOUBLE;
                                          KeyStatus[i].UpdateEnable = 0;
                                        }
                                      }
                                      else
                                        KeyStatus[i].CurrentStatus = KEY_PRESS;                                    
                                    }
                                    else
                                    {
                                      KeyStatus[i].CurrentStatus = KEY_PRESS;
                                      if (KeyStatus[i].UpdateEnable)
                                      {
                                        KeyStatus[i].FinalStatus  = KEY_PRESS;
                                        KeyStatus[i].UpdateEnable = 0;
                                      }
                                    }
                                    break;
                                    
        case KEY_HOLD_ONLY        : if (KeyStatus[i].Timer < KeyHoldThreshold[i] / 10)
                                    {
                                      if (KeyStatus[i].IdleTimer)
                                        KeyStatus[i].CurrentStatus = KEY_DOUBLE;
                                      else
                                        KeyStatus[i].CurrentStatus = KEY_PRESS;
                                    }
                                    else
                                    {
                                      KeyStatus[i].CurrentStatus = KEY_HOLD;
                                      if (KeyStatus[i].UpdateEnable)
                                      {                                       
                                        KeyStatus[i].FinalStatus  = KEY_HOLD;
                                        KeyStatus[i].UpdateEnable = 0;
                                        //KeyStatus[i].IdleTimer = 25;
                                      }
                                      else
                                      {
                                         /*if (KeyStatus[i].IdleTimer)
                                            KeyStatus[i].IdleTimer--;
                                         else
                                         {
                                            KeyStatus[i].FinalStatus  = KEY_HOLD;
                                            KeyStatus[i].IdleTimer = 25;
                                         }*/
                                       }
                                    }
                                    break;
        
        case KEY_STUCK_ONLY       : if (KeyStatus[i].Timer < KEY_STUCK_THRESHOLD / 10)
                                    {
                                      if (KeyStatus[i].IdleTimer)
                                        KeyStatus[i].CurrentStatus = KEY_DOUBLE;
                                      else
                                        KeyStatus[i].CurrentStatus = KEY_PRESS;
                                    }
                                    else
                                    {
                                      KeyStatus[i].CurrentStatus = KEY_STUCK;
                                      if (KeyStatus[i].UpdateEnable)
                                      {
                                        KeyStatus[i].FinalStatus  = KEY_STUCK;
                                        KeyStatus[i].UpdateEnable = 0;
                                      }
                                    }
                                    break;
        
        case KEY_HOLD_STUCK       : if (KeyStatus[i].Timer < KeyHoldThreshold[i] / 10)
                                    {
                                      if (KeyStatus[i].IdleTimer)
                                        KeyStatus[i].CurrentStatus = KEY_DOUBLE;
                                      else
                                        KeyStatus[i].CurrentStatus = KEY_PRESS;
                                    }
                                    else if (KeyStatus[i].Timer < KEY_STUCK_THRESHOLD / 10)
                                    {
                                      KeyStatus[i].CurrentStatus = KEY_HOLD;
                                    }
                                    else
                                    {
                                      KeyStatus[i].CurrentStatus = KEY_STUCK;
                                      if (KeyStatus[i].UpdateEnable)
                                      {
                                        KeyStatus[i].FinalStatus  = KEY_STUCK;
                                        KeyStatus[i].UpdateEnable = 0;
                                      }
                                    }
                                    break;
        
        case KEY_HOLD_LONG        : if (KeyStatus[i].Timer < KeyHoldThreshold[i] / 10)
                                    {
                                      if (KeyStatus[i].IdleTimer)
                                        KeyStatus[i].CurrentStatus = KEY_DOUBLE;
                                      else
                                        KeyStatus[i].CurrentStatus = KEY_PRESS;
                                    }
                                    else if (KeyStatus[i].Timer < KEY_LONG_THRESHOLD / 10)
                                    {
                                      KeyStatus[i].CurrentStatus = KEY_HOLD;
                                    }
                                    else
                                    {
                                      KeyStatus[i].CurrentStatus = KEY_LONG;
                                      if (KeyStatus[i].UpdateEnable)
                                      {
                                        KeyStatus[i].FinalStatus  = KEY_LONG;
                                        KeyStatus[i].UpdateEnable = 0;
                                      }
                                    }
                                    break;
                                     
        case KEY_HOLD_LONG_STUCK  : if (KeyStatus[i].Timer < KeyHoldThreshold[i] / 10)
                                    {
                                      if (KeyStatus[i].IdleTimer)
                                        KeyStatus[i].CurrentStatus = KEY_DOUBLE;
                                      else
                                        KeyStatus[i].CurrentStatus = KEY_PRESS;
                                    }
                                    else if (KeyStatus[i].Timer < KEY_LONG_THRESHOLD / 10)
                                    {
                                      KeyStatus[i].CurrentStatus = KEY_HOLD;
                                    }
                                    else if (KeyStatus[i].Timer < KEY_STUCK_THRESHOLD / 10)
                                    {
                                      KeyStatus[i].CurrentStatus = KEY_LONG;
                                    }
                                    else
                                    {
                                      KeyStatus[i].CurrentStatus = KEY_STUCK;
                                      if (KeyStatus[i].UpdateEnable)
                                      {
                                        KeyStatus[i].FinalStatus  = KEY_STUCK;
                                        KeyStatus[i].UpdateEnable = 0;
                                      }
                                    }
                                    break;
                                    
        default                    : break;
      }
    }
    else
    {
      if (KeyAttrTable[i].DoubleDetEn)
      {
        if (KeyStatus[i].CurrentStatus == KEY_PRESS)
        {
          if (KeyStatus[i].Timer == 0)
            KeyStatus[i].IdleTimer = KEY_DOUBLE_INTERVAL / 10;
        }
        else
          KeyStatus[i].IdleTimer = 0;
          
        if (KeyStatus[i].IdleTimer)
          KeyStatus[i].IdleTimer--;
        else
        {
          if ((KeyStatus[i].CurrentStatus != KEY_IDLE) && (KeyStatus[i].UpdateEnable != 0))
            KeyStatus[i].FinalStatus = KeyStatus[i].CurrentStatus;
          KeyStatus[i].CurrentStatus = KEY_IDLE;
          KeyStatus[i].UpdateEnable = 1;
        }
      }
      else
      {
        if ((KeyStatus[i].CurrentStatus != KEY_IDLE) && (KeyStatus[i].UpdateEnable != 0))
          KeyStatus[i].FinalStatus = KeyStatus[i].CurrentStatus;
        KeyStatus[i].CurrentStatus = KEY_IDLE;
        KeyStatus[i].UpdateEnable = 1;
        KeyStatus[i].IdleTimer = 0;
      }
      
      KeyStatus[i].Timer = 0;
    }
  }
}

/******************************************************************************
函数名：Reset_Key_Status
功  能：复位某一按键的按键检测状态        
参  数：Key：需要复位的按键
返回值：无
******************************************************************************/
void Reset_Key_Status(uint8_t Key)
{
  KeyStatus[Key].UpdateEnable  = 1;
  KeyStatus[Key].Timer         = 0;
  KeyStatus[Key].IdleTimer     = 0;
  KeyStatus[Key].FinalStatus   = KEY_IDLE;
  KeyStatus[Key].CurrentStatus = KEY_IDLE;
}

/******************************************************************************
函数名：Key_Get_Status
功  能：获取某一按键的检测结果
        按键的检测结果在按键的状态可以被确定时更新
        经由此函数获取检测结果后,按键检测结果被自动清除至KEY_IDLE状态
参  数：Key：需要获取结果的按键
返回值：无
******************************************************************************/
KeyStatusEnum Key_Get_Status(uint8_t Key)
{
  KeyStatusEnum   Status;
  
  Status = KeyStatus[Key].FinalStatus;
  KeyStatus[Key].FinalStatus = KEY_IDLE;
  return Status;
}

/******************************************************************************
函数名：Key_Get_Current_Status
功  能：获取某一按键的当前状态
        返回的结果反映按键当前所处的状态,并不判定按键的最终状态,在按键符合某一
        状态的条件时实时变化为该状态(包括按键释放后恢复为KEY_IDLE状态)
参  数：Key：需要获取状态的按键
返回值：无
******************************************************************************/
KeyStatusEnum Key_Get_Current_Status(uint8_t Key)
{
  return KeyStatus[Key].CurrentStatus;
}

