//*************************************************************************************************
//  Copyright (c) 	深圳市赛元微电子有限公司
//	文件名称	:  S_TouchKeyCFG.c
//	作者		: 
//	模块功能	:  触控代码程序
// 	版本		:
// 	更改记录	:
//	注意事项	:  用户需要配置的文件在S_TouchKeyCFG.h中
//  库版本标记	: 
//************************************************************************************************
#include "S_TouchKeyCFG.h"
#include "SensorMethod.h"
#include "stdio.h"

/***************************************库类型选择********************************************************/
#define USING_TKKey_T1		//支持触控按键T1库
#define USING_SlideModule	//支持滑轮滑条库

/***************************************************************************************************/
//*************************************************************************************
//		844 寄存器定义
//*************************************************************************************
/*PSW*/
sfr 	TK_PSW	    = 	0xD0;	//程序状态字
sbit 	TK_CY		= 	TK_PSW^7;	//进位  

//===========================================================================
//全局变量定义
unsigned	char	xdata		SOCAPI_TouchKeyStatus;					//API接口状态：bit7-一轮扫描完成标志  1:完成 	0：未完成
																	    //			   bit6-通道触摸计数溢出标志 1:溢出	 0:未溢出
//===============================================================================
//全局变量声明：该区域不可修改
unsigned 	int 	xdata		RawData [SOCAPI_SET_TOUCHKEY_TOTAL];			
unsigned 	int		xdata		BaseLine[SOCAPI_SET_TOUCHKEY_TOTAL];
unsigned    int	 	xdata		FilterData[SOCAPI_SET_TOUCHKEY_TOTAL];
												
unsigned	char    xdata		RestAreaCnt[SOCAPI_SET_TOUCHKEY_TOTAL]; 			
unsigned	char    xdata		TouchCnt[SOCAPI_SET_TOUCHKEY_TOTAL];				
unsigned	char    xdata		NoTouchCnt[SOCAPI_SET_TOUCHKEY_TOTAL];  
			
unsigned	char	xdata		CurrentChannel[SOCAPI_SET_TOUCHKEY_TOTAL];	  
					     
unsigned    char    xdata 	    LowFingerDataCnt[SOCAPI_SET_TOUCHKEY_TOTAL];

unsigned	char    xdata		FloatAreaCnt[SOCAPI_SET_TOUCHKEY_TOTAL]; 

unsigned 	char 	xdata    	BaseLineAdjusttmp[SOCAPI_SET_TOUCHKEY_TOTAL]; 	

int                 xdata 	    DifferAccum[SOCAPI_SET_TOUCHKEY_TOTAL]; 
char	            xdata		SetNoiseThreshold;

unsigned 	char	xdata		ConfirmTouchCnt;
unsigned 	char	xdata		MultipleDealTpye = 0; 
unsigned 	char 	xdata  		BigNosicCount=0; 					    //大数据干扰计数

#if (defined USING_TKKey_T1)
//自定义变量
unsigned 	int 	xdata  	    UpdateBaseLNum; 						// 单键长按计数器
#endif
unsigned 	int 	xdata  	    MultipleLNum;						// 多按键干扰计数


//外部变量接口
extern 	unsigned	char	data		CurrentChannelMax;		//当前选中的keysensor的个数
extern  unsigned 	char 	data	UsingTKSlideModuleNumber;

extern  bit  bMultiple;	//多按键标志	
extern 	bit  GetIsNeedUpdateBaseline(void);
extern  void SetNeedUpdateBaseline(void);
extern  unsigned long int SensorKeyFlag(void);
extern  void MultipleDeal(unsigned char CycleCnt);
extern  void TouchKey_Service(void);
extern  void	FilterDataDealT1(unsigned char i);
extern  void	FilterDataDealT2(unsigned char i);
extern  void 	SensorRenovateT1(unsigned char i);
extern  void 	SensorRenovateT2();
extern  void 	TKSlideModuleSensorRenovate(TKSlideModulePCB *PCB);
extern  unsigned long	int data 	  	KeyFlag,KeyMark;

/*******************************库函数基础设置，一般不需要更改***************************************/
#define		SOCAPI_CFG_CYCLE_CNT					    32 		//取值范围10-255，触控初始化数据滤出次数，以及修正值初始化修正次数，默认32，取值越大触控初始化时间越长，触控数据越稳定  
#define		SOCAPI_CFG_OVERLOW_MAX_COUNT			    10		//低基线更新速度设置，代表发生低基线后，多少轮更新一次基线，更新步进noise/2，值越小基线更新速度越快
#define		SOCAPI_CFG_RESET_BASELINE_CNT			    10  	//低基线更新多少次后，如果还处于低基线状态，直接强制更新基线，值越小基线更新速度越快
																//SOCAPI_CFG_OVERLOW_MAX_COUNT和SOCAPI_CFG_RESET_BASELINE_CNT的取值乘积不能大于255
/***************************************************************************************/

/***************弹簧库独有***************/
#define		SOCAPI_SET_CS_FUNCTION						1		//0:表示不进行CS测试,1: 表示进行CS测试,默认0
#define		SOCAPI_INHIBITION_ZONE					    8		//抑制区间%，设置范围5-10，默认7,即（7*10）%=70% ，连水时加大该参数,对讲机设置小
#define		SOCAPI_MAX_KEY_MUTIPLE						300		//多少次干扰更新基线，默认300*5=1500
#define		SOCAPI_MAX_KEY_NUM_INVALID					3		//强制更新基线按键限制个数，默认3
/****************************************/


/***************************************滑动模块设置项********************************************************/
#define      USING_TKSlideModule_Number 		 1	

#ifdef	USING_SlideModule

TKSlideModulePCB TKSlideModulePCBArray[USING_TKSlideModule_Number] = 
{
/***************************************滑条********************************************************/
	{
		Bar,			//(需修改)		滑动块类型,bar:为滑条，Circle:为滑轮
		{28,29,30},	//(需修改)		按照滑动顺序，依次将使用到的滑条按键通道存入数组6->5->4->3滑动值逐渐变大
		3,			//(需修改)		当前滑动模块使用的TK通道数量
		32,			//(需修改)		滑动输出的档位最大级数（从1算起） 


		60,			//(可修改)		Differ值<SUB_DATA该Differ值无效，会设置为0，屏蔽干扰（修改灵敏度） 
		200,		//(可修改)		Differ值>LIB_DATA表示有键按下（修改灵敏度）


		{0},		//(无需修改)		存放内部TK通道排序都的index
		1,			//(无需修改)		扫描多少轮无滑条按键即更新基线，默认10   可修改
		0,			//(无需修改)		记录上一次输出的值
		0,			//(无需修改)		滑动输出值，通过该值获取输出结果
		0,			//(无需修改)		基线更新计数
		150,		//(无需修改)		可采用150默认值，耦合参数范围(100~200)，参数过小会出现出值缺失,例如滑动出值OutValue为1->2->3->5->6->7,参数过大会出现出值重叠,例如滑动出值OutValue为1->2->3->4->3->4->5->6->7
		0,			//(无需修改)		耦合参数，DeBug值,用于调试，调试时输出该值，滑动滑动模块取输出的最小值，根据最小值调节CouplingValue耦合参数
		0			//(无需修改)		滑动模块触发计数标志
	}, 	
};
/***************************************************************************************************/

#endif

#define	  	AppType			     			0
#define	  	IsDoubleKey			 			1			  // 0 弹簧 1 隔空
#define	  	AirSeparationDistance	 	    2			 //0 单按键  1 双按键
#define   	CONFIRMTOUCHCNT        	        3			 //按键确认次数
#define   	INIT_AUTO_UPDATE_TIME	 	    4
#define   	SET_KEY_CONTI_TIME     	        5  			 //按键最长输出
#define   	SET_SYNC_UPDATE 		 		6
#define   	SET_UPDATE_SPEED 		 		7	
#define   	AUTO_UPDATE_TIME	     	    8
#define	  	FilteredKValue		 			9
#define	  	SET_ANTIJAM		     			10
#define	  	BAUD		             		11
#define	  	DwellTime		         		12
#define   	SaveTime					    13
#define   	NOISE                  	        16

#define   	SET_TOUCH_FREQ		 			0
#define	  	SET_RESOLUTION		 			1
#define   	SET_GAIN_CFG			 		2
#define   	SCANTIME				 		3
#define   	SET_ICHA				 		4
#define   	FINGER_THRESHOLD_H	 		    6
#define   	FINGER_THRESHOLD_L	 		    7

//**********************************************************************************	
// 								宏定义接口调用部分								  //
//**********************************************************************************
unsigned 	char	code        CFG_OVERLOW_MAX_COUNT = SOCAPI_CFG_OVERLOW_MAX_COUNT;
unsigned 	char	code        CFG_RESET_BASELINE_CNT = SOCAPI_CFG_RESET_BASELINE_CNT;	
unsigned 	char	code        CFG_CYCLE_CNT = SOCAPI_CFG_CYCLE_CNT;

//**********************************************************************************	
// 								函数接口调用部分								  //
//**********************************************************************************
/**************************************************
*函数名称：unsigned int SetOneKeyPushResetTime(void) 
*函数功能：按键最长的输出时间
*入口参数：void
*出口参数：unsigned int SOCAPI_SET_KEY_CONTI_TIME
*备注	 ：这个返回值的设置， 是根据有多长时间启动TouchKeyRestart（）一次
例如10ms 启动一次， 那SOCAPI_SET_KEY_CONTI_TIME*10ms，超过时间后此按键无效。
**************************************************/
unsigned int SetOneKeyPushResetTime(void)   
{	  
	return  TKCFG[SET_KEY_CONTI_TIME];
}
/**************************************************
*函数名称：unsignedint  GetBaselineUpdateThreshold(void)
*函数功能：更新速度 
*入口参数：void
*出口参数：unsigned  int 
*备注	 ：
**************************************************/
int  GetBaselineUpdateThreshold(void)
{
	return TKCFG[SET_UPDATE_SPEED]; 
}

/**************************************************
*函数名称：unsigned char GetInitAutoUpdateTime(void)
*函数功能：初始化自动校准次数
*入口参数：void
*出口参数：unsigned  char 
*备注	 ：
**************************************************/
unsigned char GetInitAutoUpdateTime(void)
{
	return  TKCFG[INIT_AUTO_UPDATE_TIME];
}
/**************************************************
*函数名称：unsigned char GetCsFunction(void)
*函数功能：进行CS 测试
*入口参数：void
*出口参数：char SOCAPI_SET_CS_FUNCTION
*备注	 ：
**************************************************/
#ifdef USING_TKKey_T1
char GetCsFunction(void)
{
	return SOCAPI_SET_CS_FUNCTION; 
}
#endif
/**************************************************
*函数名称：int  GetCurrFingerValue(unsigned char i)
*函数功能：获取当前的finger 值
*入口参数：unsigned char
*出口参数：int 
*备注	 ：
**************************************************/
unsigned int   GetCurrFingerValue(unsigned char i)
{ 
	return	TKChannelCfg[i][FINGER_THRESHOLD_H]*256+TKChannelCfg[i][FINGER_THRESHOLD_L] ;
}

/**************************************************
*函数名称：unsigned char  GetScanTimeValue(unsigned char i)
*函数功能：获取当前通道的扫描时间
*入口参数：unsigned char
*出口参数：unsigned char 
*备注	 ：
**************************************************/
unsigned char  GetScanTimeValue(unsigned char i)
{ 
	return TKChannelCfg[i][SCANTIME];	  //
}
/**************************************************
*函数名称：unsigned char IsDoubleKeyOrSlideKey(void)
*函数功能：检测是否是弹簧滑条或者双键
*入口参数：void
*出口参数：unsigned char 
*备注	 ：
**************************************************/
#if (defined USING_TKKey_T1)
unsigned char IsDoubleKeyOrSlideKey(void)
{
    return TKCFG[IsDoubleKey];
}

/**************************************************
*函数名称：unsigned char GetUpConfirmCnt(void)
*函数功能：检测按键弹起次数
*入口参数：void
*出口参数：返回按键弹起确认次数 
*备注	 ：
**************************************************/
unsigned char GetUpConfirmCnt(void)
{
	return ConfirmTouchCnt>>1;
}

#endif
/**************************************************
*函数名称：unsigned char  GetBaseLineAdjustValue(unsigned char i)
*函数功能：获取当前通道的基线调整
j
*入口参数：unsigned char
*出口参数：unsigned char 
*备注	 ：
**************************************************/
unsigned char  GetBaseLineAdjustValue(unsigned char i)
{	
     return BaseLineAdjusttmp[i]; 
}

/**************************************************
*函数名称：unsigned char GetTKYzCnt(void)
*函数功能：获取按键抑制确认次数
*入口参数：void
*出口参数：返回抑制次数 
*备注	 ：
**************************************************/
#ifdef USING_TKKey_T1
unsigned char GetTKYzCnt(void)
{
	return (ConfirmTouchCnt/3);
}
/**************************************************
*函数名称：int GetTKYzThreshold(unsigned char i)
*函数功能：获取按键抑制区间
*入口参数：unsigned char i
*出口参数：返回抑制区间
*备注	 ：
**************************************************/
int GetTKYzThreshold(unsigned char i)
{	
	unsigned int SetFingerThresholdtmp; 
	
	SetFingerThresholdtmp = GetCurrFingerValue(i); 
    SetFingerThresholdtmp = SetFingerThresholdtmp*SOCAPI_INHIBITION_ZONE/10;

	return SetFingerThresholdtmp;
}
#endif
/**************************************************
*函数名称：void CurrentSensorChoose(void)
*函数功能：当前通道选择
*入口参数：void
*出口参数：void
*备注	 ：
**************************************************/
void CurrentSensorChoose(void)
{
	unsigned char  data	i, j, k= 0;
	unsigned char  data	Ctk_Channel_mark = 0;

   /**************************************************/
	unsigned long int  data  CurrentSensorKey ; 		 
	
	CurrentSensorKey = SOCAPI_SET_TOUCHKEY_CHANNEL; //触摸按键通道
	
	j = j;
	k = k;
	
	//将TK的触摸通道排序存在CurrentChannel
	for(i=0;i<31;i++)
	{
		CurrentSensorKey=CurrentSensorKey>>1;
		if(TK_CY)	
		{
			CurrentChannel[Ctk_Channel_mark] = i;						//选择触摸当前的通道
			Ctk_Channel_mark++;
			if(Ctk_Channel_mark >= SOCAPI_SET_TOUCHKEY_TOTAL)	//越界跳出
				break;
		}		
	}
#ifdef USING_SlideModule
	for(k = 0; k < UsingTKSlideModuleNumber; k ++)
	{
		for(i = 0;i<TKSlideModulePCBArray[k].UsingTKChannelNumber;i++)						//在CurrentChannel[]中取出滑条TK通道排列序号 
		{
			for(j=0;j<Ctk_Channel_mark;j++)
			{
				if(TKSlideModulePCBArray[k].TKChannel[i] == CurrentChannel[j])	//取序号
				{
					TKSlideModulePCBArray[k].TKOrderChannel[i]=j;	
				}
			}	
		}
	}
#endif
	
	CurrentChannelMax = Ctk_Channel_mark;							//当前选择的按键数
	
}

/**************************************************
*函数名称：unsigned char  GetCfgMsg(unsigned char i)
*函数功能：获取Touch KEY 配置信息
*入口参数：void
*出口参数：int 
*备注	 ：
**************************************************/
unsigned char  GetCfgMsg(unsigned char i)
{
	switch(i)
	{ 
		 case 0:  return TKChannelCfg[0][SET_TOUCH_FREQ];	  //0
		 case 1:  return TKChannelCfg[0][SET_RESOLUTION];	  //1
		 case 2:  return TKChannelCfg[0][SET_GAIN_CFG];		  //2		
		 case 3:  return GetBaseLineAdjustValue(0);//TKChannelCfg[0][SET_GAIN_CFG];
		 case 4:  return TKCFG[SET_ANTIJAM];			  //10 		0
		 default:return 0; 	 	
	}
}

/**************************************************
*函数名称：void CurrentSensorChoose(void)
*函数功能：初始化TK寄存器
*入口参数：void
*出口参数：void
*备注	 ：
**************************************************/
void TouchKeyCFGInit(void)
{
	unsigned char  data	i;
#ifdef USING_SlideModule
	unsigned char  data	k;
#endif
	
	UsingTKSlideModuleNumber = USING_TKSlideModule_Number;
	ConfirmTouchCnt = TKCFG[CONFIRMTOUCHCNT];
	SetNoiseThreshold = TKCFG[NOISE];	
	CurrentSensorChoose(); //
	 for(i=0;i<CurrentChannelMax;i++)
	{
	  BaseLineAdjusttmp[i] =TKChannelCfg[i][SET_ICHA];;	
	} 
	
#if	(defined USING_TKKey_T1)
	UpdateBaseLNum = 0; 
#endif
	
#ifdef USING_SlideModule
	for(k = 0; k < UsingTKSlideModuleNumber; k ++)
	{
		TKSlideModulePCBArray[k].UpdateBaseLineNumber = 0;
	}
#endif

}

/**************************************************
*函数名称：void FilterDataDeal(unsigned char i)
*函数功能：滤波处理
*入口参数：void
*出口参数：void
*备注	 ：
**************************************************/
void FilterDataDeal(unsigned char i)
{
	FilterDataDealT1(i);
}


#if (defined USING_SlideModule)
char TKSlideModuleCHIs(unsigned char ch)
{
	
#ifdef USING_SlideModule
	unsigned char i,k; 
	for(k = 0; k < UsingTKSlideModuleNumber; k ++)
	{
		for(i=0;i<TKSlideModulePCBArray[k].UsingTKChannelNumber;i++)
		{	
			if(ch == TKSlideModulePCBArray[k].TKOrderChannel[i])	  //序号
			{	
				break;	
			}
		}
		if(i != TKSlideModulePCBArray[k].UsingTKChannelNumber)
			break;
	}
	
	if(k != UsingTKSlideModuleNumber)
	{
		return 1;
	}
	
#endif
	ch = ch;
	return 0;
}
#endif

/**************************************************
*函数名称：unsigned  int SensorKeyFlag(void)
*函数功能：基线初始化
*入口参数：void
*出口参数：unsigned  int KeyFlag
*备注	 ：
**************************************************/	
unsigned long int SensorKeyFlagT1(void)
{
	unsigned char  i;
#ifdef USING_SlideModule
	unsigned char k;
#endif
	unsigned char SlideCount = 0;
	
	
 	IsInNosicValue = 0; 	
	for(i=0;i<CurrentChannelMax;i++)
	{  	
		SlideCount=1;		
		FilterDataDeal(i);					//IIR滤波
		
#ifdef USING_SlideModule
		if(TKSlideModuleCHIs(i))
		{
			SlideCount=0;
		}
#endif


#ifdef USING_TKKey_T1
		if(SlideCount==1)
		{
			SensorRenovateT1(i); //触摸按键更新	
		}
#endif
	}
	
#ifdef USING_SlideModule
	for(k = 0; k < UsingTKSlideModuleNumber; k ++)
	{
		TKSlideModuleSensorRenovate(&TKSlideModulePCBArray[k]);
	}
#endif
	
	return KeyFlag;	
}


/**************************************************
*函数名称：unsigned int TouchKeyScan(void)
*函数功能：检测按键接口
*入口参数：void
*出口参数：按键通道， 返回的是一个int , 通道数
*备注	 ：1,  调用触控库检测函数SensorKeyFlag()
		   2,  分析得出16个通道，哪个通道有按下，按下bit 位设置为1，否则为0
		   3,  检测是否需要立即更新baseline:  大于MAX_KEY_RESET_BASELINE 个按键按下时立即更新baseline
		   4,  双键或者单键按下时， 时间大于SetOneKeyPushResetTime()结果时更新baseline 
**************************************************/
unsigned long int TouchKeyScan(void)
{
#ifdef	USING_SlideModule
	unsigned char k;
#endif
	unsigned char data t = 0;
    unsigned char data MultipleCnt = 0;//按键计数
	unsigned long int data Keyvalue ; 
	unsigned long int data KeyData = 0; 
	
	
	if(GetIsNeedUpdateBaseline() == 0)				//检测是否需要更新baseline 
	{
		

		Keyvalue = SensorKeyFlagT1();					//Sensor判断, 这里如果bMultiple = 1 表示中间有干扰	 //分析按键，得出标准的16通道bit 位               

		
#if (defined USING_TKKey_T1)
		for(t=0;t<CurrentChannelMax;t++)
		{
			Keyvalue = Keyvalue>>1;
			if(TK_CY)
			{
				KeyData |= ((unsigned long int)0x01 << (CurrentChannel[t]));              
				MultipleCnt++;							
			}
		}                
		if(MultipleCnt >= 2) 	 									//进入多按键处理
		{			
			bMultiple = 1;			
			if(MultipleCnt >= SOCAPI_MAX_KEY_NUM_INVALID)
			{
				SetNeedUpdateBaseline(); 							// 立即更新baseline ,例如亚克力板盖上去
			}
			else
			{					
				if(IsDoubleKeyOrSlideKey())
				{
					bMultiple = 0;
				} 				 
			}			
		}			

		if(bMultiple == 0)							//进入按键判断
		{		
			if(KeyData != 0x0)					    //单个按键达到多长时间就update baseline ,松手检测
			{			
				UpdateBaseLNum++; 
			}
			else	
			{
				UpdateBaseLNum = 0; 	
			} 
		}	
		else
		{   
		    //考虑基线更新		
			MultipleLNum++; 
			KeyData = 0x00;
		}
#endif
		
#ifdef	USING_SlideModule
	
		for(k = 0; k < UsingTKSlideModuleNumber; k ++)
		{
			if(TKSlideModulePCBArray[k].OutValue != 0x00)					        //单个按键达到多长时间就update baseline ,松手检测
			{	
				if(TKSlideModulePCBArray[k].OutValue == TKSlideModulePCBArray[k].LastOutValue)
				{		
				   TKSlideModulePCBArray[k].UpdateBaseLineNumber++; 
				}
				else
				{
				   TKSlideModulePCBArray[k].LastOutValue = TKSlideModulePCBArray[k].OutValue;
				   TKSlideModulePCBArray[k].UpdateBaseLineNumber = 0; 
				}
			}
			else	
			{
				TKSlideModulePCBArray[k].UpdateBaseLineNumber = 0; 	
			}

			if(TKSlideModulePCBArray[k].UpdateBaseLineNumber >= SetOneKeyPushResetTime())	  //按键超出最长输出时间更新基线
			{
				SetNeedUpdateBaseline(); 
				TKSlideModulePCBArray[k].UpdateBaseLineNumber = 0;
			}
		}
#endif
		

#if (defined USING_TKKey_T1)
		/*************************************/
		if(UpdateBaseLNum >= SetOneKeyPushResetTime())	  //按键超出最长输出时间更新基线
		{
 			SetNeedUpdateBaseline(); 
			UpdateBaseLNum = 0;
		}

		
		if(MultipleLNum >SOCAPI_MAX_KEY_MUTIPLE)		  //干扰计数大于最大计数更新基线
 		{
			SetNeedUpdateBaseline(); 
			MultipleDealTpye = 1; 
			MultipleLNum = 0;
		}
#endif		
	}			
	else
	{
		MultipleDeal(TKCFG[AUTO_UPDATE_TIME]);										//基线复位处理
	}  
	
	return KeyData;
}

/**************************************************
*函数名称：void CTK_ISR(void) interrupt	11
*函数功能：触摸中断服务函数
*入口参数：void
*出口参数：void
*备注	 ：
**************************************************/
void CTK_ISR(void) interrupt	11
{
   TouchKey_Service();
}



