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

#include "Key.h"

uint8_t KEY_RIGHT_TURN;     
uint8_t KEY_LEFT_TURN ;   
RotateKeyAttrStruct KeyMenu ;


uint8_t KeyDelaytimer1 ;    //20MS 
uint8_t KeyDelaytimer2 ;    //20MS 

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;
  }

}

/******************************************************************************
函数名：Key_Status_Detect_Service
功  能：按键检测服务函数,用于检测并更新按键的状态
参  数：无
返回值：无
******************************************************************************
注  意：该服务函数必须每20ms被调用一次
******************************************************************************/
void Key_Status_Detect_Service(void)
{
  uint8_t   i;
  volatile  uint8_t   *pSig;

  for (i = 0; i < KEY_TOTAL_NUMBER; i++)
  {
    pSig = KeyAttrTable[i].pInputSignal;

    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 < KEY_HOLD_THRESHOLD / 20)
        {
          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;
          }
        }
        break;

      case KEY_STUCK_ONLY       :
        if (KeyStatus[i].Timer < KEY_STUCK_THRESHOLD / 20)
        {
          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 < KEY_HOLD_THRESHOLD / 20)
        {
          if (KeyStatus[i].IdleTimer)
            KeyStatus[i].CurrentStatus = KEY_DOUBLE;
          else
            KeyStatus[i].CurrentStatus = KEY_PRESS;
        }
        else if (KeyStatus[i].Timer < KEY_STUCK_THRESHOLD / 20)
        {
          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 < KEY_HOLD_THRESHOLD / 20)
        {
          if (KeyStatus[i].IdleTimer)
            KeyStatus[i].CurrentStatus = KEY_DOUBLE;
          else
            KeyStatus[i].CurrentStatus = KEY_PRESS;
        }
        else if (KeyStatus[i].Timer < KEY_LONG_THRESHOLD / 20)
        {
          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 < KEY_HOLD_THRESHOLD / 20)
        {
          if (KeyStatus[i].IdleTimer)
            KeyStatus[i].CurrentStatus = KEY_DOUBLE;
          else
            KeyStatus[i].CurrentStatus = KEY_PRESS;
        }
        else if (KeyStatus[i].Timer < KEY_LONG_THRESHOLD / 20)
        {
          KeyStatus[i].CurrentStatus = KEY_HOLD;
        }
        else if (KeyStatus[i].Timer < KEY_STUCK_THRESHOLD / 20)
        {
          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)
            KeyStatus[i].IdleTimer = KEY_DOUBLE_INTERVAL / 20;
        }
        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].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;
}
/*****************************************************************************
函数名：Key_Knob
功  能：获取某一旋钮按键的当前状态
        返回的结果反映按键当前所处的状态,并不判定按键的最终状态,在按键符合某一
        状态的条件时实时变化为该状态()
参  数：KnobSwitch.Key_Step：当前旋钮的步数

返回值：无
*******************************************************************************/
void RotaryKey_Status_Detect_Service(RotateKeyAttrStruct *KeyMenu)
{	
#if 0
  if(!RotaryKEY0_In1 && !RotaryKEY0_In2)	
	{
	    KeyMenu->RotateState = keep_local;//默认
	    KeyMenu->RotateValid = 1;
	}
	
	if((RotaryKEY0_In1 && RotaryKEY0_In2)&&(KeyMenu->RotateValid == 1))  
	{
			KeyMenu->RotateValid = 0;
			
			if( KeyMenu->Rotary2Old == 0 ) 
			{
			    KeyDelaytimer1++ ; 
			    KEY_LEFT_TURN = 1 ;
			}   
			else if( KeyMenu->Rotary1Old == 0 ) 
			{
			    KeyDelaytimer2++ ;    
			    KEY_RIGHT_TURN = 1; 
			}
	}
	KeyMenu->Rotary1Old = RotaryKEY0_In1;
	KeyMenu->Rotary2Old = RotaryKEY0_In2;  	
#endif				   
}
