/*****************************************************************************
**	Filename  : keyboard_drive.c
**	Project   :
**	Module	  :
**	Processor : Freescale S12Z
**	Date/Time : 2019-09-04, 9:00
**	Abstract  :
**	Contents  :
**	Author	  : mingyea
**	http	  :
**	mail	  :
**	--------------------------------------------------------------------------
**
**	--------------------------------------------------------------------------
******************************************************************************/
#include "common_types.h"
#include "common_memory.h"
#include "key_digital_driver.h"
/*****************************************************************************
* Include Files
*****************************************************************************/

/*****************************************************************************
* Defines
*****************************************************************************/

/*****************************************************************************
* Macros
*****************************************************************************/

/*****************************************************************************
* Type Defines
*****************************************************************************/

/*****************************************************************************
*Static Variable
*****************************************************************************/

/*****************************************************************************
*Global Variable
*****************************************************************************/

/*****************************************************************************
*Constant
*****************************************************************************/

/*****************************************************************************
*Function Prototype
*****************************************************************************/


static key_digital_driver_s  g_key_digital_driver;

static void key_digital_driver_alone_checkio(u8 id);
static void key_digital_driver_alone_up_task(u8 id);
static void key_digital_driver_alone_task(u8 id);
static void key_digital_driver_alone_shortdown_task(u8 id);
static void key_digital_driver_alone_longdown_task(u8 id);
static void key_digital_driver_alone_stick_task(u8 id);

/*****************************************************************************
|Prototype         :
|Called by         :
|Preconditions     : -
|Input parameters  : None
|Output parameters : None
|Return value      : None
|Description       :
*****************************************************************************/
void key_digital_driver_init(void)
{
	u8 i;
	key_digital_driver_cfg_init();
	common_memory_clear((u8*)&g_key_digital_driver,sizeof(g_key_digital_driver));
	for(i = 0; i < KEY_DIGITAL_DRIVER_KEY_TOTAL; i++)
	{
		g_key_digital_driver.digital_key[i].event = KEY_DIGITAL_EVENT_NULL;
	}
}

/*****************************************************************************
|Prototype         :
|Called by         :
|Preconditions     : -
|Input parameters  : None  id 是邏輯id
|Output parameters : None
|Return value      : None
|Description       :  越界保護，由key_digital_driver_alone_task來保證
*****************************************************************************/
static void key_digital_driver_alone_checkio(u8 id)
{
	u8 l_ret;
	const key_digital_driver_cfg_tab_s *p_key_table;
	p_key_table = (const key_digital_driver_cfg_tab_s*)&g_key_digital_driver_cfg_tab[id];
	#ifdef KEY_DIGITAL_DRIVER_DEBUG
	l_ret = key_digital_driver_cfg_debug_read_pin(id);
	#else
	l_ret = gpio_read_pin_input(p_key_table->gpio_base,p_key_table->pin_id);
	#endif
	g_key_digital_driver.digital_key[id].phy_cur_level = l_ret;
	if(l_ret == (u8)(p_key_table->valid_level))
	{
		g_key_digital_driver.digital_key[id].logic_cur_level =  1u;
	}
	else
	{
		g_key_digital_driver.digital_key[id].logic_cur_level =  0u;
	}

	//變化時，計時清零
	if(g_key_digital_driver.digital_key[id].phy_cur_level != g_key_digital_driver.digital_key[id].phy_pre_level)
	{
		g_key_digital_driver.digital_key[id].timecount =  0u;
	}
	g_key_digital_driver.digital_key[id].timecount++;
	g_key_digital_driver.digital_key[id].phy_pre_level = g_key_digital_driver.digital_key[id].phy_cur_level;
	g_key_digital_driver.digital_key[id].logic_pre_level = g_key_digital_driver.digital_key[id].logic_cur_level;
}

/*****************************************************************************
|Prototype         :
|Called by         :
|Preconditions     : -
|Input parameters  : None  id 是邏輯id
|Output parameters : None
|Return value      : None
|Description       :  越界保護，由key_digital_driver_alone_task來保證
*****************************************************************************/
static void key_digital_driver_alone_up_task(u8 id)
{
	//key_digital_driver_cfg_tab_s *p_key_table;
	//p_key_table = (key_digital_driver_cfg_tab_s*)&g_key_digital_driver_cfg_tab[id];
	#ifdef KEY_DIGITAL_INIT_INVALID
	if(KEY_DIGITAL_DRIVER_SUBSTATE_UP == g_key_digital_driver.digital_key[id].sub_state)
	#else
	if(1)
	#endif
	{
		if(g_key_digital_driver.digital_key[id].timecount>=g_key_digital_driver_cfg_tab[id].debounce_time)//g_key_cfg_times[KEY_DIGITAL_DITHERING_TIME_ID])  //p_key_table->debounce_time
		{
			//g_key_digital_driver.digital_key[id].timecount=0u;
			if(g_key_digital_driver.digital_key[id].logic_cur_level!=0u) //邏輯有效
			{
				g_key_digital_driver.digital_key[id].sub_state=KEY_DIGITAL_DRIVER_SUBSTATE_INIT;
				g_key_digital_driver.digital_key[id].state = KEY_DIGITAL_DRIVER_STATE_SHORT_DOWN;
				g_key_digital_driver.digital_key[id].event |= KEY_DIGITAL_EVENT_PRESSED;
			}
			else
			{
				//g_key_digital_driver.digital_key[id].sub_state=KEY_DIGITAL_DRIVER_SUBSTATE_UP;
			}
		}
	}
	else
	{
		if(g_key_digital_driver.digital_key[id].timecount>=g_key_digital_driver_cfg_tab[id].debounce_time)//g_key_cfg_times[KEY_DIGITAL_DITHERING_TIME_ID])   /*PRQA S 2880*/  /*KEY_DIGITAL_INIT_INVALID关闭了*/
		{
			g_key_digital_driver.digital_key[id].timecount=0u;
			if(g_key_digital_driver.digital_key[id].logic_cur_level!=0u) //邏輯有效
			{
				g_key_digital_driver.digital_key[id].sub_state=KEY_DIGITAL_DRIVER_SUBSTATE_ERROR;
			}
			else
			{
				g_key_digital_driver.digital_key[id].sub_state=KEY_DIGITAL_DRIVER_SUBSTATE_UP;
			}
		}
	}
}

/*****************************************************************************
|Prototype         :
|Called by         :
|Preconditions     : -
|Input parameters  : None  id 是邏輯id
|Output parameters : None
|Return value      : None
|Description       :  越界保護，由key_digital_driver_alone_task來保證
*****************************************************************************/
static void key_digital_driver_alone_shortdown_task(u8 id)
{
	//key_digital_driver_cfg_tab_s *p_key_table;
	//p_key_table = (key_digital_driver_cfg_tab_s*)&g_key_digital_driver_cfg_tab[id];
	if(g_key_digital_driver.digital_key[id].logic_cur_level!=0u) //邏輯有效
	{
		//長按有效
		if(g_key_digital_driver.digital_key[id].timecount>=g_key_digital_driver_cfg_tab[id].long_down_time)//g_key_cfg_times[KEY_DIGITAL_LONGDOWN_TIMEOUT_ID])
		{
			g_key_digital_driver.digital_key[id].sub_state=KEY_DIGITAL_DRIVER_SUBSTATE_INIT;


			g_key_digital_driver.digital_key[id].state = KEY_DIGITAL_DRIVER_STATE_LONG_DOWN;
			g_key_digital_driver.digital_key[id].event |= KEY_DIGITAL_EVENT_LONG_DOWN;
		}
	}
	else
	{
		//彈起
		if(g_key_digital_driver.digital_key[id].timecount>=g_key_digital_driver_cfg_tab[id].debounce_time)//g_key_cfg_times[KEY_DIGITAL_DITHERING_TIME_ID])
		{
			g_key_digital_driver.digital_key[id].timecount=0u;
			g_key_digital_driver.digital_key[id].sub_state=KEY_DIGITAL_DRIVER_SUBSTATE_UP;
			g_key_digital_driver.digital_key[id].state = KEY_DIGITAL_DRIVER_STATE_UP;
			g_key_digital_driver.digital_key[id].event = KEY_DIGITAL_EVENT_RELEASE;
			g_key_digital_driver.digital_key[id].event |= KEY_DIGITAL_EVENT_SHORT_DOWN_RELEASE;
		}
	}
}

/*****************************************************************************
|Prototype         :
|Called by         :
|Preconditions     : -
|Input parameters  : None  id 是邏輯id
|Output parameters : None
|Return value      : None
|Description       :  越界保護，由key_digital_driver_alone_task來保證
*****************************************************************************/
static void key_digital_driver_alone_longdown_task(u8 id)
{
	//key_digital_driver_cfg_tab_s *p_key_table;
	//p_key_table = (key_digital_driver_cfg_tab_s*)&g_key_digital_driver_cfg_tab[id];
	if(g_key_digital_driver.digital_key[id].logic_cur_level!=0u) //邏輯有效
	{
		//卡住有效
		if(g_key_digital_driver.digital_key[id].timecount>=g_key_digital_driver_cfg_tab[id].stick_time)//g_key_cfg_times[KEY_DIGITAL_STUCK_TIMEOUT_ID])
		{
			g_key_digital_driver.digital_key[id].sub_state=KEY_DIGITAL_DRIVER_SUBSTATE_INIT;
			g_key_digital_driver.digital_key[id].state = KEY_DIGITAL_DRIVER_STATE_STICK;
		}
	}
	else
	{
		//彈起
		if(g_key_digital_driver.digital_key[id].timecount>=g_key_digital_driver_cfg_tab[id].debounce_time)//g_key_cfg_times[KEY_DIGITAL_DITHERING_TIME_ID])
		{
			g_key_digital_driver.digital_key[id].timecount=0u;
			g_key_digital_driver.digital_key[id].sub_state=KEY_DIGITAL_DRIVER_SUBSTATE_UP;
			g_key_digital_driver.digital_key[id].state = KEY_DIGITAL_DRIVER_STATE_UP;
			g_key_digital_driver.digital_key[id].event = KEY_DIGITAL_EVENT_RELEASE;
		}
	}
}

/*****************************************************************************
|Prototype         :
|Called by         :
|Preconditions     : -
|Input parameters  : None  id 是邏輯id
|Output parameters : None
|Return value      : None
|Description       :  越界保護，由key_digital_driver_alone_task來保證
*****************************************************************************/
static void key_digital_driver_alone_stick_task(u8 id)
{
	//key_digital_driver_cfg_tab_s *p_key_table;
	//p_key_table = (key_digital_driver_cfg_tab_s*)&g_key_digital_driver_cfg_tab[id];
	if(g_key_digital_driver.digital_key[id].logic_cur_level!=0u) //邏輯有效
	{
		//卡住有效
		if(g_key_digital_driver.digital_key[id].timecount>=g_key_digital_driver_cfg_tab[id].stick_time)//g_key_cfg_times[KEY_DIGITAL_STUCK_TIMEOUT_ID])
		{
			g_key_digital_driver.digital_key[id].sub_state=KEY_DIGITAL_DRIVER_SUBSTATE_INIT;
			g_key_digital_driver.digital_key[id].state = KEY_DIGITAL_DRIVER_STATE_STICK;
		}
	}
	else
	{
		//彈起
		if(g_key_digital_driver.digital_key[id].timecount>=g_key_digital_driver_cfg_tab[id].debounce_time)//g_key_cfg_times[KEY_DIGITAL_DITHERING_TIME_ID])
		{
			g_key_digital_driver.digital_key[id].timecount=0u;
			g_key_digital_driver.digital_key[id].sub_state=KEY_DIGITAL_DRIVER_SUBSTATE_UP;
			g_key_digital_driver.digital_key[id].state = KEY_DIGITAL_DRIVER_STATE_UP;
		}
	}
}


/*****************************************************************************
|Prototype         :
|Called by         :
|Preconditions     : -
|Input parameters  : None  id 是邏輯id
|Output parameters : None
|Return value      : None
|Description       :
*****************************************************************************/
static void key_digital_driver_alone_task(u8 id)
{
	if(id<KEY_DIGITAL_DRIVER_KEY_TOTAL)
	{
		key_digital_driver_alone_checkio(id);

		switch(g_key_digital_driver.digital_key[id].state)
		{
			case KEY_DIGITAL_DRIVER_STATE_UP:
				key_digital_driver_alone_up_task(id);
			break;
			case KEY_DIGITAL_DRIVER_STATE_SHORT_DOWN:
				key_digital_driver_alone_shortdown_task(id);
			break;
			case KEY_DIGITAL_DRIVER_STATE_LONG_DOWN:
				key_digital_driver_alone_longdown_task(id);
			break;
			case KEY_DIGITAL_DRIVER_STATE_STICK:
				key_digital_driver_alone_stick_task(id);
			break;

			default:
			break;
		}
		//消抖後的按鍵狀態變化；
		if(g_key_digital_driver.digital_key[id].pre_state != g_key_digital_driver.digital_key[id].state)
		{

			g_key_digital_driver.digital_key[id].state_change=1u;
			if( (g_key_digital_driver.digital_key[id].state ==KEY_DIGITAL_DRIVER_STATE_SHORT_DOWN)
				|| (g_key_digital_driver.digital_key[id].state ==KEY_DIGITAL_DRIVER_STATE_UP) )
			{
				g_key_digital_driver.digital_key[id].change =1u;
			}
		}
		else
		{
			g_key_digital_driver.digital_key[id].state_change=0u;
			g_key_digital_driver.digital_key[id].change =0u;
		}
		g_key_digital_driver.digital_key[id].pre_state = g_key_digital_driver.digital_key[id].state;
	}
}



/*****************************************************************************
|Prototype         :
|Called by         :
|Preconditions     : -
|Input parameters  : None
|Output parameters : None
|Return value      : None
|Description       :
*****************************************************************************/
void key_digital_driver_normal_task(void)
{
	u8 i;
	
	for(i = 0u; i < KEY_DIGITAL_DRIVER_KEY_TOTAL; i ++)
	{
		key_digital_driver_alone_task(i);
	}
}



/*****************************************************************************
|Prototype         :
|Called by         :
|Preconditions     : -
|Input parameters  : None  id 是邏輯id
|Output parameters : None
|Return value      : None
|Description       : 回讀按鍵的狀態
*****************************************************************************/
key_digital_driver_state_e key_digital_driver_get_state(u8 id)
{
	key_digital_driver_state_e l_state;
	if(id<KEY_DIGITAL_DRIVER_KEY_TOTAL)
	{
		l_state = g_key_digital_driver.digital_key[id].state;
	}
	else
	{
		l_state= KEY_DIGITAL_DRIVER_STATE_UP;  //越界就是，無效
	}
	return l_state;
}

/*****************************************************************************
|Prototype         :
|Called by         :
|Preconditions     : -
|Input parameters  : None  id 是邏輯id
|Output parameters : None
|Return value      : None
|Description       : 回讀按鍵的狀態
*****************************************************************************/
key_digital_driver_state_e key_digital_driver_get_event(u8 id)
{
	key_digital_driver_state_e l_state;
	if(id<KEY_DIGITAL_DRIVER_KEY_TOTAL)
	{
		l_state = g_key_digital_driver.digital_key[id].event;
	}
	else
	{
		l_state= KEY_DIGITAL_EVENT_NULL;  //越界就是，無效
	}
	g_key_digital_driver.digital_key[id].event = KEY_DIGITAL_EVENT_NULL;
	return l_state;
}


/*****************************************************************************
|Prototype         :
|Called by         :
|Preconditions     : -
|Input parameters  : None  id 是邏輯id
|Output parameters : None
|Return value      : None
|Description       : 回讀按鍵的物理電平
*****************************************************************************/
u8 key_digital_driver_get_phy_level(u8 id)
{
	u8 l_level;
	if(id<KEY_DIGITAL_DRIVER_KEY_TOTAL)
	{
		l_level = g_key_digital_driver.digital_key[id].phy_cur_level;
	}
	else
	{	
		l_level= (u8)GPIO_LEVEL_LOW;
	}
	return l_level;
}

/*****************************************************************************
|Prototype         :
|Called by         :
|Preconditions     : -
|Input parameters  : None  id 是邏輯id
|Output parameters : None
|Return value      : None
|Description       : 回讀按鍵的物理電平
*****************************************************************************/
u8 key_digital_driver_get_logic_level(u8 id)
{
	u8 l_level;
	if(id<KEY_DIGITAL_DRIVER_KEY_TOTAL)
	{
		l_level = g_key_digital_driver.digital_key[id].logic_cur_level;
	}
	else
	{
		l_level =0u;
	}
	return l_level;
}

/*****************************************************************************
|Prototype         :
|Called by         :
|Preconditions     : -
|Input parameters  : None  id 是邏輯id
|Output parameters : None
|Return value      : None
|Description       : 回讀按鍵的變化，注意，要馬上處理，下一周期就無變化了,    一般用于按键从无效到有效。或者从有效到无效，且消抖后。
*****************************************************************************/
u8 key_digital_driver_get_change(u8 id)
{
	u8 l_change;
	if(id<KEY_DIGITAL_DRIVER_KEY_TOTAL)
	{
		l_change = g_key_digital_driver.digital_key[id].change;
	}
	else
	{
		l_change = 0u;

	}
	return l_change;
}

/*****************************************************************************
|Prototype         :
|Called by         :
|Preconditions     : -
|Input parameters  : None  id 是邏輯id
|Output parameters : None
|Return value      : None
|Description       : 回讀按鍵的變化，注意，要馬上處理，下一周期就無變化了,    一般用于按键从无效到有效。或者从有效到无效，且消抖后。
*****************************************************************************/
u8 key_digital_driver_get_state_change(u8 id)
{
	u8 l_change;
	if(id<KEY_DIGITAL_DRIVER_KEY_TOTAL)
	{
		l_change = g_key_digital_driver.digital_key[id].state_change;
	}
	else
	{
		l_change = 0u;

	}
	return l_change;
}
/*****************************************************************************
|Prototype         :
|Called by         :
|Preconditions     : -
|Input parameters  : None  id 是邏輯id
|Output parameters : None
|Return value      : None
|Description       : 回讀按鍵的計時，一般配合state一起使用
*****************************************************************************/
key_digital_key_tim_t key_digital_driver_get_timecount(u8 id)
{
	key_digital_key_tim_t l_timecount;
	if(id<KEY_DIGITAL_DRIVER_KEY_TOTAL)
	{
		l_timecount = g_key_digital_driver.digital_key[id].timecount;
	}
	else
	{
		l_timecount= KEY_DIGITAL_DRIVER_DEBOUNCE_INIT;
	}
	return l_timecount;
}


/*****************************************************************************
|Prototype         :
|Called by         :
|Preconditions     : -
|Input parameters  : None  id 是邏輯id
|Output parameters : None
|Return value      : None
|Description       : 进入sleep前，要做的事情;---把数据
*****************************************************************************/
void key_digital_driver_goto_sleep(void)
{
	u8 i;
	//再次记录 上次值和当前值，保持一致
	for(i=0u;i<KEY_DIGITAL_DRIVER_KEY_TOTAL;i++)
	{
		g_key_digital_driver.digital_key[i].phy_pre_level = g_key_digital_driver.digital_key[i].phy_cur_level;
		g_key_digital_driver.digital_key[i].logic_pre_level = g_key_digital_driver.digital_key[i].logic_cur_level;
		g_key_digital_driver.digital_key[i].state = KEY_DIGITAL_DRIVER_STATE_UP;
		g_key_digital_driver.digital_key[i].pre_state = g_key_digital_driver.digital_key[i].state;
	}
}



/*****************************************************************************
|Prototype         :
|Called by         :
|Preconditions     : -
|Input parameters  : None  id 是邏輯id
|Output parameters : None
|Return value      : None
|Description       : 进入sleep前，要做的事情;---把数据
*****************************************************************************/
void key_digital_driver_goto_wakeup(void)
{

}


/*****************************************************************************
|Prototype         :
|Called by         :
|Preconditions     : -
|Input parameters  : None  id 是邏輯id
|Output parameters : None
|Return value      : None
|Description       : 回讀按鍵的物理電平,上次的。 为了减少执行时间，不判断越界
*****************************************************************************/
u8 key_digital_driver_get_phy_pre_quick(u8 id)
{
	return g_key_digital_driver.digital_key[id].phy_pre_level;
}


/*****************************************************************************
|Prototype         :
|Called by         :
|Preconditions     : -
|Input parameters  : None  id 是邏輯id
|Output parameters : None
|Return value      : None
|Description       :  轻量级扫描,只在进入休眠后；
*****************************************************************************/
void key_digital_driver_quick_scan(void)
{
	u8 l_ret;
	u8 i;
	const key_digital_driver_cfg_tab_s *p_key_table;
	for(i=0u;i<KEY_DIGITAL_DRIVER_KEY_TOTAL;i++)
	{
		p_key_table = (const key_digital_driver_cfg_tab_s*)&g_key_digital_driver_cfg_tab[i];
		#ifdef KEY_DIGITAL_DRIVER_DEBUG
		l_ret = key_digital_driver_cfg_debug_read_pin(i);
		#else
		l_ret = gpio_read_pin_input(p_key_table->gpio_base,p_key_table->pin_id);
		#endif
		g_key_digital_driver.digital_key[i].phy_cur_level = l_ret;
		#if 1
		if(l_ret == (u8)(p_key_table->valid_level))
		{
			g_key_digital_driver.digital_key[i].logic_cur_level =  (u8)KEY_DIGITAL_DRIVER_LOGIC_VALID;
		}
		else
		{
			g_key_digital_driver.digital_key[i].logic_cur_level =  (u8)KEY_DIGITAL_DRIVER_LOGIC_INIT;
		}
		#endif
	}
}


/*****************************************************************************
|Prototype         :
|Called by         :
|Preconditions     : -
|Input parameters  : None  id 是邏輯id
|Output parameters : None
|Return value      : None
|Description       :  轻量级判斷，是否按鍵有變化； 0表示沒有變化，1表示有變化
*****************************************************************************/
key_digital_driver_diff_e key_digital_driver_judge_diff_wakeup(void)
{
	u8 i;
	key_digital_driver_diff_e l_result =KEY_DIGITAL_DRIVER_DIFF_NULL;
	for(i=0u;i<KEY_DIGITAL_DRIVER_KEY_TOTAL;i++)
	{
		if(g_key_digital_driver.digital_key[i].phy_cur_level != g_key_digital_driver.digital_key[i].phy_pre_level)
		{
			l_result=KEY_DIGITAL_DRIVER_DIFF_SURE;
			break;
		}
	}
	return l_result;
}



/*****************************************************************************
|Prototype         :
|Called by         :
|Preconditions     : -
|Input parameters  : None  id 是邏輯id
|Output parameters : None
|Return value      : None
|Description       :  判斷，是否按鍵有真正的，有效按下
*****************************************************************************/
key_digital_driver_diff_e key_digital_driver_judge_state_wakeup(void)
{
	u8 i;
	key_digital_driver_diff_e l_result =KEY_DIGITAL_DRIVER_DIFF_NULL;
	for(i=0u;i<KEY_DIGITAL_DRIVER_KEY_TOTAL;i++)
	{
		//if(g_key_digital_driver.digital_key[i].state != KEY_DIGITAL_DRIVER_STATE_UP)
		if(g_key_digital_driver.digital_key[i].logic_cur_level == 1u)
		{
			l_result=KEY_DIGITAL_DRIVER_DIFF_SURE;
			break;
		}
	}
	return l_result;
}



/*****************************************************************************
|Prototype         :
|Called by         :
|Preconditions     : -
|Input parameters  : None  id 是邏輯id
|Output parameters : None
|Return value      : None
|Description       : 回讀按鍵的物理電平;休眠之前的，用于于唤醒时，比较，是否有变化
*****************************************************************************/
u8 key_digital_driver_get_phy_pre_level(u8 id)
{
	u8 l_level;
	if(id<KEY_DIGITAL_DRIVER_KEY_TOTAL)
	{
		l_level = g_key_digital_driver.digital_key[id].phy_pre_level;
	}
	else
	{
		#if 0
		if(g_key_digital_driver_cfg_tab[id].valid_level==GPIO_LEVEL_LOW)
		{
			l_level= (u8)GPIO_LEVEL_HIGH;  //越界就是，配置的無效電平
		}
		else
		{
			l_level= (u8)GPIO_LEVEL_LOW;
		}
		#else
			l_level= (u8)GPIO_LEVEL_LOW;
		#endif
	}
	return l_level;
}
