#include "Key.h"

/*本文件的函数，主要实现矩阵键盘的功能。矩阵键盘使用PA0到PA7引脚，其中，PA0到PA3固定为推挽输出，PA4到PA7固定为
下拉输入。即，无键按下时，对应PA4到PA7为0，有键按下时，PA4到PA7中，对应的引脚为高。
此程序有一点要注意：要用到的IO口，必须是PX0-PX7，，不能是其他连续的数字。。如果非要改。。如：已经没有连续的0-7的IO口，需要在几个地方修改，请注意！！
此程序带有松手检测。。。。*/

void GPIO_ConfigurationKey ( void ) //初始化矩阵键盘要使用的GPIO口。
{
#if key16_def
    GPIO_InitTypeDef  GPIOStru;
    RCC_APB2PeriphClockCmd ( KEY16_RCC_CONFIG, ENABLE );

    GPIOStru.GPIO_Mode = GPIO_Mode_Out_PP;  //定义PA0到PA3为推挽输出。
    GPIOStru.GPIO_Speed = GPIO_Speed_50MHz;
    GPIOStru.GPIO_Pin = KEY16_OUTPIN_CONFIG;
    GPIO_Init ( KEY16_PORT_CONFIG, &GPIOStru );

    GPIOStru.GPIO_Mode = GPIO_Mode_IPD;  	//定义PA4到PA7为下拉输入。
    GPIOStru.GPIO_Speed = GPIO_Speed_50MHz;
    GPIOStru.GPIO_Pin = KEY16_INPIN_CONFIG;
    GPIO_Init ( KEY16_PORT_CONFIG, &GPIOStru );
#endif
}

unsigned short ScanKey ( void ) //实现矩阵键盘。返回值为，各按键的键值，此键值由用户自己定义。
{
    unsigned short KeyVal = 0x0000;	 //keyVal为最后返回的键值。

    GPIO_Write ( KEY16_PORT_CONFIG, ( KEY16_PORT_CONFIG->ODR & 0xfff0 | 0xf ) ); //先让PA0到PA3全部输出高。

    if ( ( KEY16_PORT_CONFIG->IDR & 0x00f0 ) == 0x0000 ) //如果，PA4到PA7全为0，则，没有键按下。此时，返回值为-1.
        return KeyVal;

    GPIO_Write ( KEY16_PORT_CONFIG, ( KEY16_PORT_CONFIG->ODR & 0xfff0 | 0x1 ) );	//让PA3到PA0输出二进制的0001.
    KeyVal |= ( ( KEY16_PORT_CONFIG->IDR & 0x00f0 ) >> 4 ) << 0;

    GPIO_Write ( KEY16_PORT_CONFIG, ( KEY16_PORT_CONFIG->ODR & 0xfff0 | 0x2 ) );	//让PA3到PA0输出二进制的0010.
    KeyVal |= ( ( KEY16_PORT_CONFIG->IDR & 0x00f0 ) >> 4 ) << 4;

    GPIO_Write ( KEY16_PORT_CONFIG, ( KEY16_PORT_CONFIG->ODR & 0xfff0 | 0x4 ) );	//让PA3到PA0输出二进制的0100.
    KeyVal |= ( ( KEY16_PORT_CONFIG->IDR & 0x00f0 ) >> 4 ) << 8;

    GPIO_Write ( KEY16_PORT_CONFIG, ( KEY16_PORT_CONFIG->ODR & 0xfff0 | 0x8 ) );	//让PA3到PA0输出二进制的1000.
    KeyVal |= ( ( KEY16_PORT_CONFIG->IDR & 0x00f0 ) >> 4 ) << 12;

    return KeyVal;
}


/*tea5767
	K11: up+
	K12: down-
*/

/*ds1302
	K13: 开机时间复位
	K14: 菜单
	K15: up+
	K16: down-
*/

pKey Keys[16] =
{
    {0x00, KEY_UP_FLAG, 0, 0, 0, NO_KEY_FLAG},
    {0x01, KEY_UP_FLAG, 0, 0, 0, NO_KEY_FLAG},
    {0x02, KEY_UP_FLAG, 0, 0, 0, NO_KEY_FLAG},
    {0x03, KEY_UP_FLAG, 0, 0, 0, NO_KEY_FLAG},
    {0x04, KEY_UP_FLAG, 0, 0, 0, NO_KEY_FLAG},
    {0x05, KEY_UP_FLAG, 0, 0, 0, NO_KEY_FLAG},
    {0x06, KEY_UP_FLAG, 0, 0, 0, NO_KEY_FLAG},
    {0x07, KEY_UP_FLAG, 0, 0, 0, NO_KEY_FLAG},
    {0x08, KEY_UP_FLAG, 0, 0, 0, NO_KEY_FLAG},
    {0x09, KEY_UP_FLAG, 0, 0, 0, NO_KEY_FLAG},
    {0x0A, KEY_UP_FLAG, 0, 0, 0, NO_KEY_FLAG},
    {0x0B, KEY_UP_FLAG, 0, 0, 0, NO_KEY_FLAG},
    {0x0C, KEY_UP_FLAG, 0, 0, 0, NO_KEY_FLAG},
    {0x0D, KEY_UP_FLAG, 0, 0, 0, NO_KEY_FLAG},
    {0x0E, KEY_UP_FLAG, 0, 0, 0, NO_KEY_FLAG},
    {0x0F, KEY_UP_FLAG, 0, 0, 0, NO_KEY_FLAG}
};

//每40ms,进入一次
/*
	判断点:
	1.down: 400
	   down<120,			== 无效,去抖动
	   120<=down<400, 	== 进入2.继续判断

	2.down: 400  +	up:400
					up<400, == 进入3.继续判断
					up>400, == 短按

	3.down: 400  +	up:400	+	down: 400
								down>1200, == 长按
								down<400, == 单击++

*/
void KeyHander ( void )
{
#if key16_def
    unsigned short KeyVal = 0;
    unsigned char i;

    KeyVal = ScanKey();

    for ( i = 0; i < 16; i++ )
    {
        Keys[i].State = KeyVal & ( 1 << Keys[i].ID ) ? KEY_DOWN_FLAG : KEY_UP_FLAG;

        if ( Keys[i].State == KEY_DOWN_FLAG )
        {
            Keys[i].DnTime++;

            //超过1.2s,长按
            if ( ( Keys[i].DnTime > LONG_KEY_DOWN ) && ( Keys[i].Res != LONG_KEY_FLAG ) )
            {
                Keys[i].Res = LONG_KEY_FLAG;
                Keys[i].HitNum = 0;
            }

            if ( Keys[i].UpTime > 0 )
            {
                Keys[i].UpTime = 0;
            }
        }
        else if ( Keys[i].State == KEY_UP_FLAG )
        {
            Keys[i].UpTime ++;

            if ( Keys[i].UpTime < CANCEL_KEY_UP )
            {
                //松开0-320ms
                if ( Keys[i].DnTime > 0 )
                {
                    //根据按下时间，判断:
                    if ( Keys[i].DnTime < CANCEL_KEY_DOWN ) //1.抖动
                    {
                        Keys[i].Res = NO_KEY_FLAG;
                    }
                    else if ( Keys[i].DnTime < SHORT_KEY_DOWN ) //2.单击++
                    {
                        Keys[i].HitNum ++;
                    }

                    Keys[i].DnTime = 0;

                }
            }
            else if ( Keys[i].UpTime < ( CANCEL_KEY_UP + HANDLE_KEY_TIME ) )
            {
                //松开320-440ms，判断
                if ( Keys[i].HitNum > 0 ) //3.判断
                {
                    if ( Keys[i].HitNum == 1 )			Keys[i].Res = ONE_HITS_KEY_FLAG;
                    else if ( Keys[i].HitNum == 2 )	Keys[i].Res = TWO_HITS_KEY_FLAG;
                    else if ( Keys[i].HitNum == 3 )	Keys[i].Res = THREE_HITS_KEY_FLAG;

                    Keys[i].HitNum = 0;
                }
            }
            else if ( Keys[i].Res != NO_KEY_FLAG )
            {
                //松开400ms,状态变为， 无按键
                Keys[i].Res = NO_KEY_FLAG;
            }

        }


    }

#endif
}

