/** ##########################################################################
**     Filename  : keyboard_drive.c
**     Project   : RGB LED
**     Module    :
**     Processor : Cypress CY8C4125LQE-S433
**     Version   : V1.0
**     Compiler  : PSoC Creator 4.2
**     Date/Time : 2020/02/26
**     Abstract  :
**
**     Contents  :
**
**
**     (c) Copyright dmdz Co.,Ltd
**  --------------------------------------------------------------------------
**               R E V I S I O N   H I S T O R Y
**  --------------------------------------------------------------------------
**  Date       Ver   Author             Description

**  ---------  ----  -----------------  --------------------------------------
** #########################################################################*/
#include "key_adc_driver.h"
#include "adc.h"

#include "common_memory.h"

/*****************************************************************************
* I N C L U D E   F I L E S
*****************************************************************************/
void key_adc_driver_check_channel(u16 adc_value,key_adc_driver_s *p_key_sm,const key_adc_range_cfg_s *p_key_cfg);
static u8 key_adc_driver_check_state(u8 count,key_adc_driver_s *p_key_sm,const key_adc_range_cfg_s *p_key_cfg);
static void key_adc_driver_check_channel_op(u8 result1,key_adc_driver_s *p_key_sm,const key_adc_range_cfg_s *p_key_cfg);

/*****************************************************************************
* D E F I N E S
*****************************************************************************/
static key_adc_driver_s g_key_adc_driver[KEY_ADC_CHANNEL_TOTALS];

/*****************************************************************************
|Prototype		: void key_adc_drive_init(void)
|Called by		: None
|Preconditions		: None
|Input parameters	: None
|Output parameters	: None
|Return value		: None
|Description		: cycle task
*****************************************************************************/
void key_adc_driver_init(void)
{
	common_memory_clear((u8*)&g_key_adc_driver,(u16)sizeof(g_key_adc_driver));
}


/*****************************************************************************
|Prototype		: void key_adc_drive_task(void)
|Called by		: None
|Preconditions		: None
|Input parameters	: None
|Output parameters	: None
|Return value		: None
|Description		: cycle task
*****************************************************************************/
void key_adc_driver_task(void)
{
	u8 i;
	adc_result_t l_adc_value[KEY_ADC_CHANNEL_TOTALS];
	key_adc_driver_cfg_get_value(KEY_ADC_CHANNEL_TOTALS,&l_adc_value[0]);
	for(i=0u;i<KEY_ADC_CHANNEL_TOTALS;i++)
	{
		#ifdef KEY_ADC_DEBUG_EN
		g_key_adc_driver[i].adc_org = l_adc_value[i];
		#endif
		key_adc_driver_check_channel(l_adc_value[i],&g_key_adc_driver[i],&g_key_adc_range_cfg[i][0]);
	}
}

static u8 key_adc_driver_check_state(u8 count,key_adc_driver_s *p_key_sm,const key_adc_range_cfg_s *p_key_cfg)
{
	u8 j=count;
	u8 l_result=0xffu;
	switch(p_key_sm->jude_line[j])
	{
		case KEY_ADC_RESULT_IDLE:
			if(p_key_cfg[j].valid == 0x80u)
			{
				p_key_sm->count++;
				if(p_key_sm->count>=g_key_cfg_times[KEY_ADC_FAULT_TIME_ID])  /* p_key_cfg[j].debounce */
				{
					p_key_sm->count =0;
					p_key_sm->jude_line[j] = KEY_ADC_RESULT_PRESSS;
					l_result = j;
				}
			}
			else
			{
				p_key_sm->count++;
				if(p_key_sm->count>=g_key_cfg_times[KEY_ADC_DEBOUNCE_TIME_ID])  /*p_key_cfg[j].debounce*/
				{
					p_key_sm->count =0;
					p_key_sm->jude_line[j] = KEY_ADC_RESULT_PRESSS;
					l_result = j;
				}
			}
		break;
		#if 0
		case KEY_ADC_RESULT_PRESSS:
			p_key_sm->count++;
			if(p_key_sm->count>=p_key_cfg[j].long_press)
			{
				/*p_key_sm->count =0;*/
				p_key_sm->jude_line[j] = KEY_RESULT_LONG;
			}
		break;
		case KEY_RESULT_LONG:
			p_key_sm->count++;
			if(p_key_sm->count>=p_key_cfg[j].stick_press)
			{
				/*p_key_sm->count =0;*/
				p_key_sm->jude_line[j] = KEY_ADC_RESULT_STICK;
			}
		break;
		#else
			case KEY_ADC_RESULT_PRESSS:
			l_result = j;
			p_key_sm->count=0u;
			break;
		#endif
		default:
			/*code*/
		break;
	}
	return l_result;
}

static void key_adc_driver_check_channel_op(u8 result1,key_adc_driver_s *p_key_sm,const key_adc_range_cfg_s *p_key_cfg)
{
	u8 j;
	u8 l_result = result1;
	/*如果是沒有任何按鍵有效*/
	if(l_result == 0xffu)
	{
		#if 0
		for(j=0;j<KEY_ADC_1CHANNEL_JUDGE_TOTALS;j++)
		{
			p_key_sm->jude_line[j] = KEY_ADC_RESULT_IDLE;
		}
		for(j=0;j<KEY_ADC_1CHANNEL_PHY_TOTALS;j++)
		{
			p_key_sm->result[j] = KEY_ADC_RESULT_IDLE;
		}
		#endif
	}
	else
	{
		for(j=0;j<KEY_ADC_1CHANNEL_PHY_TOTALS;j++)
		{
			if( (p_key_cfg[l_result].valid & (u8)((u8)0x01<<j) ) != 0u)	/*PRQA S 4571*/
			{
				//该判断句，是为了，在fault时，不能直接置成功
				//if( (p_key_sm->result[j]!=KEY_ADC_RESULT_FAULT) )// &&　(p_key_sm->pre_state!=KEY_ADC_STATE_FAULT) )
				{
					p_key_sm->result[j] = KEY_ADC_RESULT_PRESSS;
				}
			}
			else
			{
				//第一个判断句，是为了保持上次fault，第二个判断句，是为了弹起时，才清除状态
				//if( (p_key_sm->result[j] != KEY_ADC_RESULT_FAULT) || (p_key_sm->state==KEY_ADC_STATE_IDLE) )
				{
					p_key_sm->result[j] =KEY_ADC_RESULT_IDLE;
				}
			}
			/*机械故障*/
			if(p_key_cfg[l_result].valid == 0x80u)
			{
				p_key_sm->result[j] =KEY_ADC_RESULT_FAULT;
				p_key_sm->state = KEY_ADC_STATE_FAULT;  //在错误的范围
			}
		}
		//
	}
}

/*****************************************************************************
|Prototype		: void key_adc_drive_task(void)
|Called by		: None
|Preconditions		: None
|Input parameters	: None
|Output parameters	: None
|Return value		: None
|Description		: cycle task
*****************************************************************************/
void key_adc_driver_check_channel(u16 adc_value,key_adc_driver_s *p_key_sm,const key_adc_range_cfg_s *p_key_cfg)
{
	u8 j,k;
	u8 l_result = 0xffu;
	u8 l_breakout =0u;
	for(j=0;j<KEY_ADC_1CHANNEL_JUDGE_TOTALS;j++)
	{
		if( (adc_value>= p_key_cfg[j].min) && (adc_value <= p_key_cfg[j].max) )  /*&& (p_key_cfg[j].valid!=0u) )*/
		{
			p_key_sm->state = (key_adc_state_e)j;
			if(p_key_sm->pre_state != p_key_sm->state)
			{
				p_key_sm->count =0;
				for(k=0;k<KEY_ADC_1CHANNEL_JUDGE_TOTALS;k++)
				{
					p_key_sm->jude_line[k] = KEY_ADC_RESULT_IDLE;
				}
			}
			else
			{
				/*code*/
			}
			l_result = key_adc_driver_check_state(j,p_key_sm,p_key_cfg);
			l_breakout=1u;
			/*break;*/
		}
		else
		{
			/*p_key_sm->jude_line[j] = KEY_ADC_RESULT_IDLE;*/
			if(p_key_sm->jude_line[j] != KEY_ADC_RESULT_IDLE)
			{
				p_key_sm->count++;
				if(p_key_sm->count>=p_key_cfg[j].debounce)
				{
					p_key_sm->count =0;
					p_key_sm->jude_line[j] = KEY_ADC_RESULT_IDLE;
					l_result = 0xffu;
					l_breakout=1u;
					/*break;*/
				}
			}
		}
		if(l_breakout==1u)
		{
			break;
		}
	}

	//不在任何范围内
	if(l_breakout==0u)
	{
		//消抖的时间，要更久一点，达到秒级
		p_key_sm->count++;
		if(p_key_sm->count>=g_key_cfg_times[KEY_ADC_OTHER_FAULT_TIME_ID])
		{
			p_key_sm->count =0;
			l_result = 0xffu;

			for(j=0;j<KEY_ADC_1CHANNEL_JUDGE_TOTALS;j++)
			{
				p_key_sm->jude_line[j] = KEY_ADC_RESULT_IDLE;
			}
			for(j=0;j<KEY_ADC_1CHANNEL_PHY_TOTALS;j++)
			{
				p_key_sm->result[j] = KEY_ADC_RESULT_FAULT;
			}
			p_key_sm->state = KEY_ADC_STATE_FAULT;  //不在任何判斷範圍
		}
	}

	key_adc_driver_check_channel_op(l_result,p_key_sm,p_key_cfg);

	p_key_sm->pre_state = p_key_sm->state;
}

/*****************************************************************************
|Prototype		: void key_adc_driver_get_result(void)
|Called by		: None
|Preconditions		: None
|Input parameters	: channel AD邏輯通道  sub_id 內部的key排序
|Output parameters	: None
|Return value		: None
|Description		:
*****************************************************************************/
key_adc_result_e key_adc_driver_get_result(u8 channel,u8 sub_id)
{
	key_adc_result_e l_result=KEY_ADC_RESULT_IDLE;
	if(channel<=KEY_ADC_CHANNEL_TOTALS)
	{
		if(sub_id<=KEY_ADC_1CHANNEL_PHY_TOTALS)
		{
			if(g_key_adc_driver[channel].result[sub_id] != KEY_ADC_RESULT_IDLE)
			{
				l_result = g_key_adc_driver[channel].result[sub_id];
			}
			else
			{
				l_result = KEY_ADC_RESULT_IDLE;
			}
		}
	}
	return l_result;
}


/*****************************************************************************
|Prototype		: void key_adc_goto_sleep(void)
|Called by		: None
|Preconditions		: None
|Input parameters	: None
|Output parameters	: None
|Return value		: None
|Description		: cycle task
*****************************************************************************/
/* software detailed  design ID ：  */
void key_adc_goto_sleep(void)
{
	#if 1
		common_memory_clear((u8*)&g_key_adc_driver,(u16)sizeof(g_key_adc_driver));
	#else
	u8 i;
	for(i=0u;i<KEY_ADC_CHANNEL_TOTALS;i++)
	{
		g_key_adc_driver[i].result[i] = KEY_ADC_RESULT_IDLE;
	}
	#endif
}


/*****************************************************************************
|Prototype		: void key_adc_goto_sleep(void)
|Called by		: None
|Preconditions		: None
|Input parameters	: None
|Output parameters	: None
|Return value		: None
|Description		: cycle task
*****************************************************************************/
/* software detailed  design ID ：  */
void key_adc_goto_wakeup(void)
{


}



/* [] END OF FILE */
