/********************************************************************************
Copyright (C), Sinowealth Electronic. Ltd.
Author: 	Sino
Version: 	V0.0
Date: 		2020/04/26
History:
	V2.0	2020/04/26		 Preliminary
********************************************************************************/
#include "Main.h"


BOOL	bKeyFlg;
U16	data 	uiKeyValidCnt;
U16	data 	uiKeyInvalidCnt;
U8	data 	ucKeyValue;
U8	data 	ucKeyOldValue;
U8	data 	ucKeyValueBK;

/*************************************************************************************************
* 函数名: ScanKey
* 参  数: 无
* 返回值: 无
* 描  述: 1. 短按时，按键必须弹起后，才能识别为短按按键。
          2. 长按和长按持续，按键无需弹起，就能识别为长按按键或长按持续。
          3. 按键有优先级，多个按键被同时按下时，仅处理第一个被按下的按键。
          4.同一个按键一直被按着，先触发长按，后触发长按持续，长按和长按持续都会被触发。
          5. bKeyFlg：当检测到有效按键后，置位1
		  6. ucKeyValue：高4bit表示按键状态（短按、长按、长按继续、长按结束）；低4bit表示键值
          7. ucKeyValueBK 保存按键状态：无按键、有按键1、有按键2
          8. uiKeyValidCnt 按键按下滤波计数器
          9. uiKeyInvalidCnt 按键弹起滤波计数器
*************************************************************************************************/
void KeyScan(void)
{
	if(!bKeyFlg)
	{
		ucKeyValueBK = KEYVAL_NULL;                                 //先默认无按键按下
        
#ifdef KEY_NUM1_DEF                                                 //1个按键
		if(!KEY_1_IO_RD)
		{
			ucKeyValueBK = KEYVAL_1;
		}
#endif
#ifdef KEY_NUM2_DEF                                                 //2个按键
		if(!KEY_1_IO_RD)
		{
			ucKeyValueBK = KEYVAL_1;                                //按键按下后，获取新键值
		}
        else if(!KEY_2_IO_RD)
        {
			ucKeyValueBK = KEYVAL_2;                                //按键按下后，获取新键值
        }
#endif
#ifdef KEY_NUM3_DEF                                                 //3个按键
		if(!KEY_1_IO_RD)
		{
			ucKeyValueBK = KEYVAL_1;
		}
        else if(!KEY_2_IO_RD)
        {
			ucKeyValueBK = KEYVAL_2;
        }
        else if(!KEY_3_IO_RD)
        {
			ucKeyValueBK = KEYVAL_3;
        }
#endif
		if(ucKeyValueBK != ucKeyOldValue)                           //ucKeyValueBK中存放了新的键值，如果新键值跟老键值不同，
		{
			uiKeyInvalidCnt++;                                      //按键弹起滤波计数器，当按键第一次按下时会清0，当按键弹起时会一直计数
			if(uiKeyValidCnt >= KEY_S_TIME)                         //按键按下滤波计数器，当按键被按下后一直计数，按键弹起后停止计数
			{                                                       //按下又弹起且未触发长按时，如果uiKeyValidCnt >= KEY_S_TIME，则可能是短按
				if(uiKeyInvalidCnt >= KEY_S_TIME)                   //按键弹起滤波计数器达到短按消抖时间，则认为是一次按下和弹起都消抖过的有效按键
				{
					if(uiKeyValidCnt >= KEY_L_TIME)                 //在此区分是短按，还是长按结束
					{
						ucKeyValue = ucKeyOldValue | KEY_STATE_LE;  //按下的时间超过长按时间，认为是长按已经结束了。该状态目前未使用
					}
					else
					{
						ucKeyValue = ucKeyOldValue | KEY_STATE_S;   //按下的时间没有超过长按时间，认为是一次有效的短按按键
					}
					bKeyFlg = 1;                                    //短按有效，暂停按键检测，去处理按键事件
					goto scanend;
				}
//				else
//				{
//					uiKeyValidCnt++;                                //该行应该删掉，否则当KEY_S_TIME等于KEY_L_TIME的一半及以上时，会把短按误识别为长按结束。
//				}
			}
			else                                                    //每当按键按下的时间连短按消抖时间都不够时，认为是无效按键，重新初始化
			{
				goto scanend;
			}
		}
		else                                                        //ucKeyValueBK中存放了新的键值，新键值跟老键值相同，说明是同一个按键。
		{
			if(ucKeyValueBK != KEYVAL_NULL)                         //继续处理被按下的按键
			{
				uiKeyInvalidCnt = 0;                                //清弹起计数器
				uiKeyValidCnt++;                                    //累加按下计数器
				if(uiKeyValidCnt == KEY_L_TIME)                     //当按下时间达到长按滤波时间时，认为此按键为长按键
				{
					ucKeyValue = ucKeyOldValue | KEY_STATE_L;
					bKeyFlg = 1;
				}
				else if(uiKeyValidCnt == KEY_LC_TIME)               //当按下时间达到长按持续滤波时间时，认为此按键为长按持续
				{
					uiKeyValidCnt = KEY_L_TIME;
					ucKeyValue = ucKeyOldValue | KEY_STATE_LC;
					bKeyFlg = 1;
				}
			}
			else                                                    //新键值是空键值，说明全部按键都释放了
			{
				ucKeyValue = KEYVAL_NULL;                           //全部按键都释放了，需要重新初始化检测寄存器
scanend:
				uiKeyValidCnt = 0;
				uiKeyInvalidCnt = 0;
				ucKeyOldValue = ucKeyValueBK;
			}
		}
	}
}
