<b>
#define REPEAT_ENABLE 1			/* set non zero to enable key repeat */
#define KEY_RATE 5				/* Number of calls to key_scan() before 
								/* a key repeats */
/*
**
** keypad scanning program to decode the keypad via column to row
** sensing and decoding into a valid key code. This routine is
** designed to be called repeatively by a timed interrupt routine
** to support keypad filtering, debounce, and key repeat/held
** down logic.
**
** The keypad connects to the microcontroller via the following 
** connections. The numbers in the lower corner of each button
** the logical local key code for the button in hexadecimal.
** The numbers in the upper corner of each button are the 
** trnslated radio key codes.
**
** Note that this module generates logical key codes from the
** translate table that are +1 in value from those defined for
** the equipment interface so that a code of zero can indicate that
** no key is pressed.
**
**
**													
**													
**  +-1----+    +-2----+    +-3----+    +-A----+   	
**  |  1   |____|  2   |____|  3   |____| ESC  |_K4______ Row 0
**  | SW1  |    | SW2  |    | SW3  |    | SW4  |           P2.0
**  +----0-+    +----1-+    +----2-+    +----3-+   			
**     |           |           |           |		
**  +-4----+    +-5----+    +-6----+    +-E----+   			
**  |  4   |____|  5   |____|  6   |____| PREV |_K5______ Row 1
**  | SW5  |    | SW6  |    | SW7  |    | SW8  |           P2.1
**  +----4-+    +----5-+    +----6-+    +----7-+   			
**     |           |           |           |		
**  +-7----+    +-8----+    +-9----+    +-F----+   			
**  |  7   |____|  8   |____|  9   |____| NEXT |_K6______ Row 2
**  | SW9  |    | SW10 |    | SW11 |    | SW12 |           P2.2
**  +----8-+    +----9-+    +----A-+    +----B-+   			
**     |           |           |           |		
**  +-C----+    +-0----+    +-D----+    +-B----+   			
**  |  <   |____|  0   |____|  >   |____| ENT  |_K7______ Row 3
**  | SW13 |    | SW14 |    | SW15 |    | SW16 |           P2.3
**  +----C-+    +----D-+    +----E-+    +----F-+   	
**     |           |           |           |	   
**     |           |           |           |
**     |           |           |           +-----K3------ Col 3
**     |           |           |                           P2.7
**     |           |           |
**     |           |           +-----------------K2------ Col 2
**     |           |                                       P2.6
**     |           |
**     |           +-----------------------------K1------ Col 1
**     |                                                   P2.5
**     |
**     +-----------------------------------------K0------ Col 0
**                                                         P2.4
**
** The four rows K4-K7 are equipped with pullup resistors at the
** inputs to the microcontroller. In normal operation the 
** columns are held high and placed low one column at a time
** while looking at the row inputs and seeing if there is
** a key pressed.
**
** scan codes are composed from the row and columns as two 
** two bit pairs as RRCC to compose a nibble wise key code. 
**
*/

/* globals that handle keyboard state logic */
char key_code;					/* logical key code found in matrix */
char key_flag;					/* flag true of key_code has a key present */
								/*  0 = no keypress present */
								/* -1 = key in debounce state */
								/* +1 = key is valid press */
#if REPEAT_ENABLE
  char key_cnt;					/* used to count out the key repeat duration */
#endif
char key_inp;					/* this holds new key code detected */
								/* key fetch routine clears upon seeing key */

/*
**
** routine to initialize the board scan port logic to the inactive
** state. 
**
*/

void key_init(void)
{
	P2 = 0xFF;						/* init all of keyboard port as inputs */

	key_code=0;						/* clear keyboard status variables */
	key_flag=0;
#if REPEAT_ENABLE
	  key_cnt=0;
#endif
	key_inp=0;
}

/* table to translate from the logical key numbers of the key matrix */
/* to the equipment matrix keycodes. note that the initializer is laid */
/* out in matrix that is like the key pad locatioms */

// setup whatever scan codes you want in here, Dont use zero for one of them
const char key_xlat[16]={
						  RKEY_1,      RKEY_2,     RKEY_3,     RKEY_ESC,
						  RKEY_4,      RKEY_5,     RKEY_6,     RKEY_PREV,
						  RKEY_7,	   RKEY_8,     RKEY_9,	   RKEY_NEXT,
						  RKEY_LEFT,   RKEY_0,     RKEY_RIGHT, RKEY_ENT,
						};

/* this translates column number to low active column select bit */
const char col_xlat[4]={
							0xe0,	/* column code 1110 */
							0xd0,	/* column code 1101 */
							0xb0,	/* column code 1011 */
							0x70,	/* column code 0111 */
						};

/* this prioritizes scan decode to row 3-2-1-0. codes in */
/* table encode as high two bits of a nibble key code */
const char row_xlat[16]={
							0x0,	 /* row code 0000 */
							0x0,	 /* row code 0001 */
							0x4,	 /* row code 0010 */
						    0x4,	 /* row code 0011 */
							0x8,	 /* row code 0100 */
						    0x8,	 /* row code 0101 */
							0x8,	 /* row code 0110 */
							0x8,	 /* row code 0111 */
							0xc,	 /* row code 1000 */
							0xc,	 /* row code 1001 */
							0xc,	 /* row code 1010 */
							0xc,	 /* row code 1011 */
							0xc,	 /* row code 1100 */
							0xc,	 /* row code 1101 */
							0xc,	 /* row code 1110 */
							0xc,	 /* row code 1111 */
						};

/*
**
** routine to scan the keypad matrix to detect keys that 
** are pressed. This routine is designed to be called
** at a regular repeatitive rate. (100 Hz is recommended).
** a key is valid is detected for two successive calls
** to this routine. A key detection is signalled by placing
** the key code into the "key_inp" variable with the MSB set.
** A separate key fetch routine would see this flag set 
** capture the key and then clear the flag.
**
** The key scanner will repeat a key that is seen held
** down for an extended period of time causing repeated
** insertions of the code into the "key_inp" variable.
**
** This routine uses a single key lockout scheme and
** puts a priority on the scan order and stop at the 
** first key seen. Is multiple keys are pressed the
** highest priority one takes precidence.
**
*/

void key_scan(void)
{
	char col;
	char row;
	char key;

	for(col=0; col<4; col++)
	{
		P2=P2 | col_xlat[col];

	    row=P2;							/* fetch in the row data */

		row=(row&0x0f)^0x0f;			/* keep low bits and invert */
		if(row != 0)					/* if a row bit set	then some key */
		{
			key=row_xlat[row]+col;		/* get key code */
			key=key_xlat[key];			/* translate to radio code+1 */
			P2|=0xf0;					/* force column bits high */
			if(key_flag == 0)			/* new key found */
			{
				key_flag=-1;			/* setup the debounce state */
				key_code=key;
				return;
			}
			if(key == key_code)			/* matching last time? */
			{
				if(key_flag < 0) 		/* 2nd sighting of same key */
				{
					key_flag=1;			/* show valid key code */
#if REPEAT_ENABLE
					key_cnt=KEY_DELAY;	/* init for initial repeat */
#endif
					key_inp=key;		/* set new key out */
					return;
				}
#if REPEAT_ENABLE
				if(key_cnt-- <= 0)
				{
					key_cnt=KEY_RATE;	/* set period to repeat */
					key_inp=key;		/* show key press */
				}
#endif
				return;
			}
			else
			{
				key_flag=-1;			/* setup debounce for this new one */
				key_code=key;
				return;
			}
		}	
	}
	P2|=0xf0;							/* force all column bits high */

	/* no key seen so remove indication of any key */
	key_code=0;
	key_flag=0;
#if REPEAT_ENABLE
	key_cnt=0;
#endif
}

/*
** 
** routine to check if a particular key code is being held down
** for an external check for a repeat function of sorts.
**
*/

char keydown(char key)
{
	if((key_flag > 0) && (key == key_code))
	{
		/* show that key is pressed */
		return(1);
	}

	/* show that this key is not pressed */
	return(0);
}


/*
** 
** function to get a key code if any present.
** this will return the key code value and that will 
** valid of > 0. A return value of zero indicates that no
** key is pressed.
**
*/

char getkey(void)
{
	char key;

	if(key_inp)
	{
		key=key_inp;
		key_inp=0;
		return(key);
	}
	return(0);
}

/*
**
** routine to check is a key is present
** this will return a zero value if mo
** key is present
**
*/

char chkkey(void)
{
	if(key_inp)
	{
		return(1);		/* key is ready */
	}
	return(0);			/* no key ready */
}

</b>