/*************************** (C) COPYRIGHT 2017 CXHY ****************************
 * 文件名  ：key.c
 * 描  述  ：开关驱动程序
 * 版  本  ：V1.0
 * 作  者  ：XuZhongPing
 * 日  期  ：2020/03/30 
*********************************************************************************/
#include "key.h"
#include "timer.h"

//按键检测接口
#define KEY1_PORT_PeriphClock 	RCC_APB2Periph_GPIOA
#define KEY1_PORT								GPIOA
#define KEY1_PIN								GPIO_Pin_5

#define KEY2_PORT_PeriphClock 	RCC_APB2Periph_GPIOA
#define KEY2_PORT								GPIOA
#define KEY2_PIN								GPIO_Pin_7

#define KEY3_PORT_PeriphClock 	RCC_APB2Periph_GPIOC
#define KEY3_PORT								GPIOC
#define KEY3_PIN								GPIO_Pin_5

#define KEY4_PORT_PeriphClock 	RCC_APB2Periph_GPIOB
#define KEY4_PORT								GPIOB
#define KEY4_PIN								GPIO_Pin_1

//LED指示灯接口
#define KEY1_LED_PeriphClock 		RCC_APB2Periph_GPIOA
#define KEY1_LED_PORT						GPIOA	
#define KEY1_LED_PIN						GPIO_Pin_4

#define KEY2_LED_PeriphClock 		RCC_APB2Periph_GPIOA
#define KEY2_LED_PORT						GPIOA	
#define KEY2_LED_PIN						GPIO_Pin_6

#define KEY3_LED_PeriphClock 		RCC_APB2Periph_GPIOC
#define KEY3_LED_PORT						GPIOC
#define KEY3_LED_PIN						GPIO_Pin_4

#define KEY4_LED_PeriphClock 		RCC_APB2Periph_GPIOB
#define KEY4_LED_PORT						GPIOB
#define KEY4_LED_PIN						GPIO_Pin_0

//限位开关
#define LIMI_KEY1_PeriphClock 	RCC_APB2Periph_GPIOB
#define LIMI_KEY1_PORT					GPIOB
#define LIMI_KEY1_PIN						GPIO_Pin_8

#define LIMI_KEY2_PeriphClock 	RCC_APB2Periph_GPIOB
#define LIMI_KEY2_PORT					GPIOB
#define LIMI_KEY2_PIN						GPIO_Pin_9

#define LIMI_KEY3_PeriphClock 	RCC_APB2Periph_GPIOC
#define LIMI_KEY3_PORT					GPIOC
#define LIMI_KEY3_PIN						GPIO_Pin_0

#define LIMI_KEY4_PeriphClock 	RCC_APB2Periph_GPIOC
#define LIMI_KEY4_PORT					GPIOC
#define LIMI_KEY4_PIN						GPIO_Pin_1

uint8_t keyBit = 0;											//按键采集按位组合后的值
uint8_t keyReleaseMark = 0;							//按键松开标志
uint8_t keyValue;												//按钮键值

uint8_t keyNum = 0;											//向外输出的按键编号
uint8_t keyStatus = 0;									//对应输出的按键状态
	
/*
***********************************************************************
*	函 数 名: KeyInit
*	功能说明: 开关IO口初始化
*	形    参：无
*	返 回 值: 无
***********************************************************************
*/
void KeyInit(void)
{ 
 	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(KEY1_PORT_PeriphClock, ENABLE);		//使能IO口时钟
	RCC_APB2PeriphClockCmd(KEY2_PORT_PeriphClock, ENABLE);
	RCC_APB2PeriphClockCmd(KEY3_PORT_PeriphClock, ENABLE);
	RCC_APB2PeriphClockCmd(KEY4_PORT_PeriphClock, ENABLE);
	
	RCC_APB2PeriphClockCmd(KEY1_LED_PeriphClock, ENABLE);		//使能IO口时钟
	RCC_APB2PeriphClockCmd(KEY2_LED_PeriphClock, ENABLE);
	RCC_APB2PeriphClockCmd(KEY3_LED_PeriphClock, ENABLE);
	RCC_APB2PeriphClockCmd(KEY4_LED_PeriphClock, ENABLE);
	
	RCC_APB2PeriphClockCmd(LIMI_KEY1_PeriphClock, ENABLE);		//使能IO口时钟
	RCC_APB2PeriphClockCmd(LIMI_KEY2_PeriphClock, ENABLE);
	RCC_APB2PeriphClockCmd(LIMI_KEY3_PeriphClock, ENABLE);
	RCC_APB2PeriphClockCmd(LIMI_KEY4_PeriphClock, ENABLE);

// 	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);		//关闭JTAG的PB3,PB4复用功能

//按键接口初始化----------------	
	//第一路按键IO口配置
	GPIO_InitStructure.GPIO_Pin = KEY1_PIN;			 				
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 		 		
	GPIO_Init(KEY1_PORT, &GPIO_InitStructure);	
	
	//第二路按键IO口配置
	GPIO_InitStructure.GPIO_Pin = KEY2_PIN;			 				
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 		 			
	GPIO_Init(KEY2_PORT, &GPIO_InitStructure);	
	
	//第三路按键IO口配置
	GPIO_InitStructure.GPIO_Pin = KEY3_PIN;			 				
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 		 		
	GPIO_Init(KEY3_PORT, &GPIO_InitStructure);	
	
	//第四路按键IO口配置
	GPIO_InitStructure.GPIO_Pin = KEY4_PIN;			 				
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 			
	GPIO_Init(KEY4_PORT, &GPIO_InitStructure);

//LED灯接口初始化----------------
	//第一路按键灯IO口配置
	GPIO_InitStructure.GPIO_Pin = KEY1_LED_PIN;													
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 		
 	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 							
 	GPIO_Init(KEY1_LED_PORT, &GPIO_InitStructure);		

	//第二路按键灯IO口配置
	GPIO_InitStructure.GPIO_Pin = KEY2_LED_PIN;													
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 	
 	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 							
 	GPIO_Init(KEY2_LED_PORT, &GPIO_InitStructure);
	
	//第三路按键灯IO口配置
	GPIO_InitStructure.GPIO_Pin = KEY3_LED_PIN;													
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 	
 	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 							
 	GPIO_Init(KEY3_LED_PORT, &GPIO_InitStructure);
	
	//第四路按键灯IO口配置
	GPIO_InitStructure.GPIO_Pin = KEY4_LED_PIN;													
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 	
 	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 							
 	GPIO_Init(KEY4_LED_PORT, &GPIO_InitStructure);
	
//限位开关接口初始化----------------	
	//第一路限位开关IO口配置
	GPIO_InitStructure.GPIO_Pin = LIMI_KEY1_PIN;													
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 		 				 							
 	GPIO_Init(LIMI_KEY1_PORT, &GPIO_InitStructure);	
	
	//第二路限位开关IO口配置
	GPIO_InitStructure.GPIO_Pin = LIMI_KEY2_PIN;													
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 		 				 							
 	GPIO_Init(LIMI_KEY2_PORT, &GPIO_InitStructure);	
	
	//第三路限位开关IO口配置
	GPIO_InitStructure.GPIO_Pin = LIMI_KEY3_PIN;													
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 		 				 							
 	GPIO_Init(LIMI_KEY3_PORT, &GPIO_InitStructure);
	
	//第四路限位开关IO口配置
	GPIO_InitStructure.GPIO_Pin = LIMI_KEY4_PIN;													
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 		 				 							
 	GPIO_Init(LIMI_KEY4_PORT, &GPIO_InitStructure);
}

/*
***********************************************************************
*	函 数 名: KeyScanning
*	功能说明: 按键扫描
*	形    参：无
*	返 回 值: 返回对应开关的键值
***********************************************************************
*/
uint8_t KeyScanning(void)
{
	static uint8_t key_state = 0, key_value;
	uint8_t key_press, key_return = 0;
	
	static timer keyLongPressTimer;
	static uint8_t timer_ok = 0;
	if(timer_ok == 0)
	{
		timer_ok = 1;
		timer_set(&keyLongPressTimer, CLOCK_SECOND*2);		//设定长按时间为2S
	}

	switch (key_state)
	{
		case 0x00:		// 按键初始态
			if(KEY1 == 0)
			{	
				key_value = 1; 
				key_state = 0x01;					// 键被按下，状态转换到键确认态
			}else if(KEY2 == 0){
				key_value = 2; 
				key_state = 0x01;					// 键被按下，状态转换到键确认态
			}
			else if(KEY3 == 0){
				key_value = 3; 
				key_state = 0x01;					// 键被按下，状态转换到键确认态
			}
			else if(KEY4 == 0){
				key_value = 4; 
				key_state = 0x01;					// 键被按下，状态转换到键确认态
			}else{
				key_value = 0;
			}
			break;
			
		case 0x01:		// 按键确认态
			if(KEY1 == 0)
			{	
				key_press = 1; 
			}else if(KEY2 == 0){
				key_press = 2; 
			}
			else if(KEY3 == 0){
				key_press = 3; 
			}
			else if(KEY4 == 0){
				key_press = 4; 
			}else{
				key_press = 0;
			}

			if(key_value == key_press)
			{
			 	key_return = key_value;
				key_state = 0x02;	 				// 键被按下，状态转换到键确认态
				printf("\r\n短按KEY = %d\r\n", key_return);
				timer_restart(&keyLongPressTimer);
				break;
			}else{
			
				key_state = 0x00;
			}
			break;
			
		case 0x02:		// 长按检测
			if(timer_expired(&keyLongPressTimer))
			{
				if(key_value == 1)						//按键1长按下输出11
				{
					key_return = 0x11;
				}else if(key_value == 2){
					key_return = 0x22;
				}else if(key_value == 3){
					key_return = 0x33;
				}else if(key_value == 4){
					key_return = 0x44;
				}
				key_state = 0x03;
				
// 				printf("\r\n长按KEY = %d\r\n", key_return);
				break;
			}
			
			if((KEY1 == 1) && (KEY2 == 1) && (KEY3 == 1) && (KEY4 == 1))
			{
				keyReleaseMark = 1;
				key_state = 0x00;	// 按键已释放，转换到按键初始态
				printf("\r\n短按松开\r\n");
				break;
			}
			break;

		case 0x03:		// 按键释放
			if((KEY1 == 1) && (KEY2 == 1) && (KEY3 == 1) && (KEY4 == 1))
			{
				keyReleaseMark = 1;
				key_state = 0x00;	// 按键已释放，转换到按键初始态
// 				printf("\r\n长按松开\r\n");
			}
			break;
	}	
	return key_return;
}

/*
***********************************************************************
*	函 数 名: TouchKeysCanning
*	功能说明: 触摸按键扫描
*	形    参：无
*	返 回 值: 返回对应开关的键值
***********************************************************************
*/
uint8_t TouchKeysCanning(void)
{
	static uint8_t key_state = 0, key_value;
	uint8_t key_press, key_return = 0;
	
	static timer keyLongPressTimer;
	static uint8_t timer_ok = 0;
	if(timer_ok == 0)
	{
		timer_ok = 1;
		timer_set(&keyLongPressTimer, CLOCK_SECOND*2);		//设定长按时间为2S
	}
	
	keyBit = (KEY3 << 2) | (KEY2 << 1) | KEY1;
// 	printf("\r\nswkey = %x\r\n", keyBit);
	switch (key_state)
	{
		case 0x00:		// 按键初始态
			if(keyBit > 0)
			{
				switch(keyBit)
				{
					case 0x01: key_value = 1; break;
					case 0x02: key_value = 2; break;
					case 0x03: key_value = 3; break;
					case 0x04: key_value = 4; break;
					case 0x05: key_value = 5; break;
					default:	 key_value = 0; break;
				}
				key_state = 0x01;					// 键被按下，状态转换到键确认态
			}else{
				key_value = 0;
			}
			break;
			
		case 0x01:		// 按键确认态
			if(keyBit > 0)
			{
				switch(keyBit)
				{
					case 0x01: key_press = 1; break;
					case 0x02: key_press = 2; break;
					case 0x03: key_press = 3; break;
					case 0x04: key_press = 4; break;
					case 0x05: key_press = 5; break;
					default:	 key_press = 0; break;
				}
			}else{
				key_value = 0;
			}
			
			if(key_value == key_press)
			{
			 	key_return = key_value;
				key_state = 0x02;	 				// 键被按下，状态转换到键确认态
// 				printf("\r\n短按KEY = %d\r\n", key_return);
				timer_restart(&keyLongPressTimer);
				break;
			}else{
				key_state = 0x00;
			}
			break;
			
		case 0x02:		// 长按检测
			if(timer_expired(&keyLongPressTimer))
			{
				if(key_value == 1)						//按键1长按下输出11
				{
					key_return = 0x11;
				}else if(key_value == 2){
					key_return = 0x22;
				}else if(key_value == 3){
					key_return = 0x33;
				}else if(key_value == 4){
					key_return = 0x44;
				}else if(key_value == 5){
					key_return = 0x55;
				}
				key_state = 0x03;
				
// 				printf("\r\n长按KEY = %d\r\n", key_return);
				break;
			}
			
			if(keyBit == 0x00)
			{
				key_state = 0x00;	// 按键已释放，转换到按键初始态
				keyReleaseMark = 1;
// 				printf("\r\n短按松开\r\n");
				break;
			}
			break;

		case 0x03:		// 按键释放
			if(keyBit == 0x00)
			{
				key_state = 0x00;	// 按键已释放，转换到按键初始态
				keyReleaseMark = 1;
// 				printf("\r\n长按松开\r\n");
			}
			break;
	}	
	return key_return;
}

/*
***********************************************************************
*	函 数 名: SetKeyLedON
*	功能说明: 点亮按键对应的LED灯
*	形    参:	whichOne -> 指定的LED灯
*	返 回 值: 无
***********************************************************************
*/
void SetKeyLedON(uint8_t whichOne)
{
	switch(whichOne)
	{
		case 1:
			GPIO_SetBits(KEY1_LED_PORT, KEY1_LED_PIN);
			break;
			
		case 2:
			GPIO_SetBits(KEY2_LED_PORT, KEY2_LED_PIN);
			break; 
			
		case 3:
			GPIO_SetBits(KEY3_LED_PORT, KEY3_LED_PIN);
			break;
			
		case 4:
			GPIO_SetBits(KEY4_LED_PORT, KEY4_LED_PIN);
			break; 
			
		default:
			break;
	}
}

/*
***********************************************************************
*	函 数 名: SetKeyLedAllON
*	功能说明: 点亮全部按键的LED灯
*	形    参:	无
*	返 回 值: 无
***********************************************************************
*/
void SetKeyLedAllON(void)
{
	GPIO_SetBits(KEY1_LED_PORT, KEY1_LED_PIN);
	GPIO_SetBits(KEY2_LED_PORT, KEY2_LED_PIN);
	GPIO_SetBits(KEY3_LED_PORT, KEY3_LED_PIN);
	GPIO_SetBits(KEY4_LED_PORT, KEY4_LED_PIN);
}

/*
***********************************************************************
*	函 数 名: SetKeyLedOFF
*	功能说明: 熄灯按键对应的LED灯
*	形    参:	whichOne -> 指定的LED灯
*	返 回 值: 无
***********************************************************************
*/
void SetKeyLedOFF(uint8_t whichOne)
{
	switch(whichOne)
	{
		case 1:
			GPIO_ResetBits(KEY1_LED_PORT, KEY1_LED_PIN);
			break;
			
		case 2:
			GPIO_ResetBits(KEY2_LED_PORT, KEY2_LED_PIN);
			break; 
			
		case 3:
			GPIO_ResetBits(KEY3_LED_PORT, KEY3_LED_PIN);
			break;
			
		case 4:
			GPIO_ResetBits(KEY4_LED_PORT, KEY4_LED_PIN);
			break; 
			
		default:
			break;
	}
}

/*
***********************************************************************
*	函 数 名: SetKeyLedAllOFF
*	功能说明: 熄灯全部按键的LED灯
*	形    参:	无
*	返 回 值: 无
***********************************************************************
*/
void SetKeyLedAllOFF(void)
{
	GPIO_ResetBits(KEY1_LED_PORT, KEY1_LED_PIN);
	GPIO_ResetBits(KEY2_LED_PORT, KEY2_LED_PIN);
	GPIO_ResetBits(KEY3_LED_PORT, KEY3_LED_PIN);
	GPIO_ResetBits(KEY4_LED_PORT, KEY4_LED_PIN);
}

/*
***********************************************************************
*	函 数 名: KeysTest
*	功能说明: 按键及其指示灯测试
*	形    参:	无
*	返 回 值: 无
***********************************************************************
*/
void KeysTest(void)
{
	static uint8_t keyStatus1 = 0;
	
	if(keyValue > 0)
	{		
		SetKeyLedAllOFF();
		SetKeyLedON(keyValue);
		
		keyValue = 0;
	}
	
// 	if((keyStatus1 != keyValue))
// 	{
// 		keyStatus1 = keyValue;
// 		
// 		SetKeyLedAllOFF();
// 		SetKeyLedON(keyValue);
// 	}
}

/*
***********************************************************************
*	函 数 名: LimitKeysTest
*	功能说明: 限位开关测试
*	形    参:	无
*	返 回 值: 无
***********************************************************************
*/
void LimitKeysTest(void)
{
	uint8_t limitKeySta1 = 0;
	uint8_t limitKeySta2 = 0;
	uint8_t limitKeySta3 = 0;
	uint8_t limitKeySta4 = 0;
	
	static uint8_t limitKeyStaPre1 = 0;
	static uint8_t limitKeyStaPre2 = 0;
	static uint8_t limitKeyStaPre3 = 0;
	static uint8_t limitKeyStaPre4 = 0;
	
	if(LIMI_KEY1 == 0)
	{
		limitKeySta1 = 1;
	}else{
		limitKeySta1 = 0;
	}
	
	if(LIMI_KEY2 == 0)
	{
		limitKeySta2 = 1;
	}else{
		limitKeySta2 = 0;
	}
	
	if(LIMI_KEY3 == 0)
	{
		limitKeySta3 = 1;
	}else{
		limitKeySta3 = 0;
	}
	
	if(LIMI_KEY4 == 0)
	{
		limitKeySta4 = 1;
	}else{
		limitKeySta4 = 0;
	}
	
	
	if((limitKeySta1 != limitKeyStaPre1) || 
		 (limitKeySta2 != limitKeyStaPre2) ||
		 (limitKeySta3 != limitKeyStaPre3) ||
		 (limitKeySta4 != limitKeyStaPre4))
	{
		limitKeyStaPre1 = limitKeySta1;
		limitKeyStaPre2 = limitKeySta2;
		limitKeyStaPre3 = limitKeySta3;
		limitKeyStaPre4 = limitKeySta4;
		
		if(limitKeySta1)
		{
			printf("\r\n限位开关1限位\r\n");
		}
		if(limitKeySta2)
		{
			printf("\r\n限位开关2限位\r\n");
		}
		if(limitKeySta3)
		{
			printf("\r\n限位开关3限位\r\n");
		}
		if(limitKeySta4)
		{
			printf("\r\n限位开关4限位\r\n");
		}
	}
}

/******************** (C) COPYRIGHT 2018 Ping *****END OF FILE*******************/
