/*
******************************************************************************************************
 @Module        	KEY
 @Filename     	KEY.c
 @Project        	SEM-3000
-----------------------------------------------------------------------------------------------------
 @Controller     	Si1010

 @Compiler      	Keil 8.12

 @ Frequency   	Using Internal clock 24.5MHz

 @Codegenerator 	0.1

 @Description   

------------------------------------------------------------------------------------------------------
 @Date          		2013-07-05 11:00:00

******************************************************************************************************
*/



/*
*********************************************************************************************************
*                                          USER DEFINED CONSTANTS
*
* Note: These #defines would normally reside in your application specific code.

*                                             DESCRIPTION
*
*    The keyboard is assumed to be a matrix having 6 rows by 4 columns.  However, this code works for any
* matrix arrangements up to an 6 x 4 matrix.  By using from one to three of the column inputs, the driver
* can support "SHIFT" keys.  These keys are: SHIFT1, SHIFT2 and SHIFT3.
*
*    Your application software must declare (see KEY.H):
*
*    KEY_BUF_SIZE            Size of the KEYBOARD buffer
*
*    KEY_MAX_ROWS            The maximum number of rows    on the keyboard
*    KEY_MAX_COLS            The maximum number of columns on the keyboard
*
*    KEY_RPT_DLY             Number of scan times before auto repeat executes the function again
*    KEY_RPT_START_DLY       Number of scan times before auto repeat function engages
*
*    KEY_SCAN_TASK_DLY       The number of milliseconds between keyboard scans
*    KEY_SCAN_TASK_PRIO      Sets the priority of the keyboard scanning task
*    KEY_SCAN_TASK_STK_SIZE  The size of the keyboard scanning task stack
*
*    KEY_SHIFT1_MSK          The mask which determines which column input handles the SHIFT1 key
*                                (A 0x00 indicates that a SHIFT1 key is not present)
*    KEY_SHIFT1_OFFSET       The scan code offset to add when the SHIFT1 key is pressed
*
*    KEY_SHIFT2_MSK          The mask which determines which column input handles the SHIFT2 key
*                                (A 0x00 indicates that an SHIFT2 key is not present)
*    KEY_SHIFT2_OFFSET       The scan code offset to add when the SHIFT2 key is pressed
*
*    KEY_SHIFT3_MSK          The mask which determines which column input handles the SHIFT3 key
*                                (A 0x00 indicates that a SHIFT3 key is not present)
*    KEY_SHIFT3_OFFSET       The scan code offset to add when the SHIFT3 key is pressed
*
*
*    KEY_PORT_ROW            The port address of the keyboard matrix ROWs
*    KEY_PORT_COL            The port address of the keyboard matrix COLUMNs
*    KEY_PORT_CW             The port address of the keyboard I/O ports control word
*
*    KeyInitPort, KeySelRow() and KeyGetCol() are the only three hardware specific functions.  This has
*    been done to localize the interface to the hardware in only these two functions and thus make is
*    easier to adapt to your application.
*********************************************************************************************************
*/

#define _KEY_C_

/*
*********************************************************************************************************
*                                              INCLUDE FILES
*********************************************************************************************************
*/

#include "PROJECT_INCLUDES.H"


/*
*********************************************************************************************************
*                                           
*********************************************************************************************************
*/

#define KEY_SCAN_EVENT_RATIO		25	//35 KEY SCAN 주기 35mS 마다 

/*
*********************************************************************************************************
*                                          Key scanning states used in KeyScan()   
*********************************************************************************************************
*/

#define KEY_STATE_UP				1    
#define KEY_STATE_DEBOUNCE		2
#define KEY_STATE_RPT_START_DLY    	3
#define KEY_STATE_RPT_DLY 			4
#define KEY_STATE_PULL     			5


/*
*********************************************************************************************************
*                                            GLOBAL VARIABLES
*********************************************************************************************************
*/
                                         		
static	U8	hKey_Scan_Event_Timer; 

static	U16	KeyDownTmr;               	// Counts how long key has been pressed               
 
static	U8	KeyRptStartDlyCtr;        	// Number of scan times before auto repeat is started     
static	U8	KeyRptDlyCtr;           		// Number of scan times before auto repeat executes again

static	U8 	KeyScanState;             	// Current state of key scanning function                

static	U8	PressedWhenKeyValue;  	//키가 눌린 후 다시 띠었을 때 키 상태를 전송하기 위한 눌렸을 때 키 백업

static	U8	IsTheKey;  				// 입력된 키가 있는가? 를 Chick 하는 변수로  입력된 키가 있으면 TRUE, 없으면 FLASE 로 인지 된다.


/*
*********************************************************************************************************
*                                       LOCAL FUNCTION PROTOTYPES
*********************************************************************************************************
*/

static  U16  KeyGetKeyDownTime (void);
              
static  U8    isGetPressedKeyCode(void); 

static  U8    KeyDecode(void );     		// Get scan code from current key pressed   

////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//   Methods for KEY entering
//
//   void  KeyInit (void)
//
//   unsigned int  KeyGetKeyDownTime (void)
//
//   U8 KeyOut(void)
//
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////


/*
*********************************************************************************************************
*                                       KEYBOARD INITIALIZATION
*
* Description: Keyboard initialization function.  KeyInit() must be called before calling any other of
*              the user accessible functions.
* Arguments  : none
* Returns    : none
*********************************************************************************************************
*/

#define EEPSET              0x00
#define ICPSEL              0x02
#define KEYENABLE0          0x03
#define NOISEKEY            0x04
#define AUTOSLEEP_NSCANBF   0x05
#define I2C_DEVICE_ID       0x06
#define LEDCTRL             0x07
#define T1CHCNT             0x09
#define TCHDR               0x0A
#define REFGUARD            0x0B
#define THRGL               0x0C
#define THRLC0              0x0D
#define THRLC1              0x0E
#define THRLC2              0x0F
#define THRLC3              0x10
#define THRLC4              0x11
#define THRLC5              0x12
#define THRLC6              0x13
#define THRLC7              0x14
#define FC_SEN              0x17
#define FC_SYS              0x18
#define REFGENON            0x1A
#define PWONOVER            0x1B
#define PINT_OCTAL          0x1C
#define FSEN1_FSEN0         0x1D
#define FSEN3_FSEN2         0x1E
#define FSEN5_FSEN4         0x1F
#define FSEN7_FSEN6         0x20
#define FD_SYS_FSYS         0x21
#define CONCTCH             0x23
#define AUTORST             0x24
#define UPPERTHR            0x25
#define UNDERTHR            0x26
#define REFOPEN             0x27
#define TESTCTRL1           0x2D
#define TESTCTRL2           0x2E
#define TESTEEP             0x2F

void  Key_Initialization(void)
{

	KEY_EN_PORT=ENABLE_;   //Power Enable

	memset(&_Key, 0, sizeof(_Key) );	
 
	KeyRptStartDlyCtr=0;        	// Number of scan times before auto repeat is started     
	KeyRptDlyCtr=0;           		// Number of scan times before auto repeat executes again

	PressedWhenKeyValue=0;  	//키가 눌린 후 다시 띠었을 때 키 상태를 전송하기 위한 눌렸을 때 키 백업
		
    	KeyScanState = KEY_STATE_UP;          										/* Keyboard should not have a key pressed          */
    	KeyDownTmr   = 0;	
	IsTheKey  = FALSE;
	      		
	hKey_Scan_Event_Timer = timer_mSecHandleAssign();						/* Key Scan timer Assign                                    */
	
	timer_mSecTimerSet(hKey_Scan_Event_Timer, KEY_SCAN_EVENT_RATIO);		/* Start key scan timer                                       */

#if 1
//	Touch_Byte_Write(1    ,0);
//	Touch_Byte_Write(1    ,0);

	Touch_Byte_Write(EEPSET           ,0x00);  //  0x03
	Touch_Byte_Write(ICPSEL           ,0x01);
	Touch_Byte_Write(KEYENABLE0       ,0x1F);
	Touch_Byte_Write(NOISEKEY         ,0x00);
	Touch_Byte_Write(AUTOSLEEP_NSCANBF,0x00);
	
	Touch_Byte_Write(I2C_DEVICE_ID     ,Touch_CT1C08_ADDRES );  // 0xB8
	
	Touch_Byte_Write(LEDCTRL          ,0x00);
	Touch_Byte_Write(T1CHCNT          ,0x00);
	Touch_Byte_Write(TCHDR            ,0x03);
	Touch_Byte_Write(REFGUARD         ,0x35);
	Touch_Byte_Write(THRGL            ,0x03);
	Touch_Byte_Write(THRLC0           ,0x31);
	Touch_Byte_Write(THRLC1           ,0x36);
	Touch_Byte_Write(THRLC2           ,0x3B);
	Touch_Byte_Write(THRLC3           ,0x2D);
	Touch_Byte_Write(THRLC4           ,0x23);
	Touch_Byte_Write(THRLC5           ,0xFF);
	Touch_Byte_Write(THRLC6           ,0xFF);
	Touch_Byte_Write(THRLC7           ,0xFF);
	Touch_Byte_Write(FC_SEN           ,0x00);
	Touch_Byte_Write(FC_SYS           ,0x04);
	Touch_Byte_Write(REFGENON         ,0x14);
	Touch_Byte_Write(PWONOVER         ,0xEE);
	Touch_Byte_Write(PINT_OCTAL       ,0x01);
	Touch_Byte_Write(FSEN1_FSEN0      ,0x44);
	Touch_Byte_Write(FSEN3_FSEN2      ,0x44);
	Touch_Byte_Write(FSEN5_FSEN4      ,0x44);
	Touch_Byte_Write(FSEN7_FSEN6      ,0x44);
	Touch_Byte_Write(FD_SYS_FSYS      ,0x14);
	Touch_Byte_Write(CONCTCH          ,0x03);
	Touch_Byte_Write(AUTORST          ,0x8F);
	Touch_Byte_Write(UPPERTHR         ,0xAB);
	Touch_Byte_Write(UNDERTHR         ,0xC9);
	Touch_Byte_Write(REFOPEN          ,0x3F);
	Touch_Byte_Write(TESTCTRL1        ,0x00);
	Touch_Byte_Write(TESTCTRL2        ,0x00);
	Touch_Byte_Write(TESTEEP          ,0x00);
	
#endif

}


/*
*********************************************************************************************************
*                                  GET HOW LONG KEY HAS BEEN PRESSED
*
* Description : This function returns the amount of time the key has been pressed.
* Arguments   : none
* Returns     : key down time in 'milliseconds'
*********************************************************************************************************
*/


static  U16  KeyGetKeyDownTime (void)
{
   idata  U16 volatile  tmr;

    tmr = KeyDownTmr;
    
    return (tmr * KEY_SCAN_TASK_DLY);
}




U8 Key_Get(void)
{
	if(IsTheKey == FALSE)  return NONE_KEY;

	IsTheKey = FALSE;


	if(_Key.Element.Chk_Push_Pull == KEY_EVENT_PULL){

							_Key.Element.DoubleKey_Flag = KEY_KIND_SHORT;

							_Key.Element.LongKey_Flag = KEY_KIND_SHORT;

							KeyDownTmr = 0;
							
							return _Key.Value;
	}
		
		
	if(KeyGetKeyDownTime() >= LONG_KEY_CRITERION ) {

						_Key.Element.LongKey_Flag = KEY_KIND_LONG;
				
						return _Key.Value;
	}


	return _Key.Value;

	
}


U8 Toucch_Key_Scan(void){
	idata U8 volatile ReadData=0;

	Touch_Byte_Read(Touch_Output_Data,  &ReadData);  

	ReadData &=0x1f;

	//printf("\n Toucch=%02x ", (U16)ReadData );	

	return ReadData;
}


/*
*********************************************************************************************************
*                                         KEYBOARD SCANNING TASK
*
* Description	: 이 함수는 키보드를 스켄 하는 기능을 한다.
*                   
* Arguments	: NONE
* Returns		:   
* Notes		: - An auto repeat of the key pressed will be executed after the key has been pressed for
*                 more than KEY_RPT_START_DLY scan times.  Once the auto repeat has started, the key will
*                 be repeated every KEY_RPT_DLY scan times as long as the key is pressed.  For example,
*                 if the scanning of the keyboard occurs every 50 mS and KEY_RPT_START_DLY is set to 40
*                 and KEY_RPT_DLY is set to 2, then the auto repeat function will engage after 2 seconds
*                 and will repeat every 100 mS (10 times per second).
*********************************************************************************************************
*/


void  KeyScanTask (void)
{
   	idata  U8 volatile KeyCode;

      if(time_mSecTimeExpired(hKey_Scan_Event_Timer) == TIMER_RUNNING ) return;
		     
	timer_mSecTimerSet(hKey_Scan_Event_Timer, KEY_SCAN_EVENT_RATIO);				/* Start key scan timer reset                     */
    	 
        switch (KeyScanState) {

			
            	case KEY_STATE_UP:                         											/* See if need to look for a key pressed      */
                					 if (KeyDecode()) {                    			 				/* See if key is pressed                              */              
                     					KeyScanState = KEY_STATE_DEBOUNCE;    				/* Next call we will have debounced the key */
                     					KeyDownTmr   = 0;                     						/* Reset key down timer                             */ 
                     				}
									 
							break;

            	case KEY_STATE_DEBOUNCE:                       										/* Key pressed, get scan code and buffer    */

							KeyCode = KeyDecode();  	
							
							if (KeyCode) {                     								/*  See if key is pressed                             */                 		
                    
                    					
								_Key.Element.DoubleKey_Flag = KEY_KIND_SHORT;		/* Input key save                                      */
								_Key.Element.Chk_Push_Pull   = KEY_EVENT_PUSH;
								_Key.Element.Value                = KeyCode;
								IsTheKey = TRUE;									/*  Set Key Input flag                                 */
											
                    						PressedWhenKeyValue = KeyCode;						/*  Save the value of the pressed key          */
                     					KeyRptStartDlyCtr = KEY_RPT_START_DLY;				/*  Start delay to auto-repeat function         */  
                     					KeyScanState        = KEY_STATE_RPT_START_DLY;
										
							} else  KeyScanState   = KEY_STATE_UP;     					/* Key was not pressed after all!                 */
                 					
										
                 					break;
										

            	case KEY_STATE_RPT_START_DLY:

							KeyCode = KeyDecode();

							if (KeyCode) {                     									/*  See if key is still pressed                       */

								if (KeyRptStartDlyCtr > 0) {            							/*  See if we need to delay before auto rpt   */
                         						KeyRptStartDlyCtr--;                     						/*  Yes, decrement counter to start of rpt     */ 
														
                         						if (KeyRptStartDlyCtr == 0) {   						/*  If delay to auto repeat is completed ...    */
                         						                             						
										_Key.Element.DoubleKey_Flag = KEY_KIND_DOUBLE;	/* Input key save                                      */
										_Key.Element.Value                = KeyCode;
										IsTheKey = TRUE;								/*  Set Key Input flag                                 */
								

										KeyRptDlyCtr = KEY_RPT_DLY;  						/* Reload delay counter before auto repeat  */
										
                             						 KeyScanState = KEY_STATE_RPT_DLY;
                             					}
                     					}
								
                 					} else  KeyScanState = KEY_STATE_PULL;    						/* Key was not pressed after all                  */      
                 														
                 					break;

	

            	case KEY_STATE_RPT_DLY:
				
                 					KeyCode = KeyDecode();  	
							
							if (KeyCode) {                     									/* See if key is pressed                              */   
							
                     					if (KeyRptDlyCtr > 0) {              							/* See if we need to wait before repeat key */
									 KeyRptDlyCtr--;                   							/* Yes, dec. wait time to next key repeat     */
									 
                        						 if (KeyRptDlyCtr == 0) {       							/* See if it's time to repeat key                   */
                            						
										_Key.Element.DoubleKey_Flag = KEY_KIND_DOUBLE;	/* Input key save                                      */
										_Key.Element.Value                = KeyCode;
										IsTheKey = TRUE;								/* Set Key Input flag                                 */
										
                             						KeyRptDlyCtr = KEY_RPT_DLY;  						/* Reload delay counter before auto repeat  */
									}
                    						 }
										
                					 } else {
                					 
                     					KeyScanState = KEY_STATE_PULL;   				 			/* Key was not pressed after all                  */
                					 }

							break;

		case  KEY_STATE_PULL:
							KeyCode = KeyDecode();  	
							
							if (KeyCode) {          
					                    						   	
                     					KeyRptStartDlyCtr = KEY_RPT_START_DLY;					/* Start delay to auto-repeat function           */
                     					KeyScanState        = KEY_STATE_RPT_START_DLY;
										
							} else {

								_Key.Element.Chk_Push_Pull   = KEY_EVENT_PULL;				/* Chk KEY PULL                                        */
								_Key.Element.DoubleKey_Flag = KEY_KIND_SHORT;			
								_Key.Element.Value                = PressedWhenKeyValue;		/* Input key save                                      */	
								IsTheKey = TRUE;										/*  Set Key Input flag                                 */
								
								_Key.Element.Chk_Push_Pull = KEY_EVENT_PULL;
															
								KeyScanState   = KEY_STATE_UP;     				    	 	/* Go back First state                                  */
							}
							
                 					break;
        	}        
   
}


/*$PAGE*/
/*
*********************************************************************************************************
*                                           DECODE KEYBOARD
*
* Description : This function is called to determine the key scan code of the key pressed.
* Arguments   : none
* Returns     : the key scan code
*********************************************************************************************************
*/

#define SET_KEY_NUM		5								/*  Set key의 갯수                                */

#define KEY_NOT_PRESSED	0x0					   			/*  아무런 KEY가 안 눌리면                     */

static  U8  isGetPressedKeyCode(void)
{
	idata U8 volatile	Index;
	idata U8 volatile     ChkKeyCode;
	
	ChkKeyCode = Toucch_Key_Scan();						/*   Toucch KEY INPUT                           */
	
	if( ChkKeyCode == KEY_NOT_PRESSED)  return  KEY_NONE;
		
	for(Index=0; Index < SET_KEY_NUM; Index++){
		
		if((ChkKeyCode >> Index) & 0x01)return (Index+1);    		/*  눌려진 키 값을 리턴 한다.                   */
	}
	
	return  KEY_NONE;							             		/*  눌려진 KEY가 없으면                           */

}



static  U8  KeyDecode (void )
{ 	    
    	U8   idata volatile PressedKey=0;

	 PressedKey = isGetPressedKeyCode();

	 if (PressedKey) {   
	 	
		KeyDownTmr++;      					      							// Update key down counter 
		
	 }
	
    	return (PressedKey);  													// CLOCK Key가 눌려 있는 상태에서 다른 키가 입력 되었다면 Offset 를 더한다.

}




