PS2 keypad driver with buffer

Have you got the greatest 48 bit multiplier ever conceived? Prove it - post your code here.

Moderator: phalanx

Post Reply
JohnLeung
Posts: 28
Joined: Wed Jun 22, 2005 4:18 am

PS2 keypad driver with buffer

Post by JohnLeung » Mon Jan 16, 2006 7:38 pm

Just posted a PS/2 keypad driver on web. Hope it would be helpful for somebody. Interested parties may also search my web page www.TechToys.com.hk for more PS/2 basics and documents...

John

Code: Select all

/*	
**************************************************************************************
*	PS2Main.c to demonstrate the power of PS2Key.c and PS2Key.h drivers 
*	Date		: 17th June 2004
*	Programmer	: John Leung, www.TechToys.com.hk under Downloads Section.
**************************************************************************************
*/


#include <16f877a.h>
#use delay(clock=20000000)
#fuses HS, NOWDT, NOLVP

#include <OS_CPU.h>				//typedef compatible with uCOS-II style

#include <PS2Key.h>
#include <PS2ScanCode.h>
#include <PS2Key.c>

INT8U PS2Key_Char;

#int_EXT
void ext_isr(void)
{
	PS2KeyIntHandler();
}

void main(void)
{
	INT8U outs = 0;

	PS2KeyInit();				//Init PS2 Keyboard
	enable_interrupts(global);	//enable global interrupts

	while(1)
	{
		if(PS2KeyHit())
		{
			/* PS2KeyNumPad[] ONLY, & OFFSET_SCH2 from PS2ScanCode.h */
			PS2Key_Char = PS2KeyNumPad[PS2KeyGetKey()-OFFSET_SCH2];	
		
			switch (PS2Key_Char){
				case '0':
				case '1':
				case '2':
				case '3':
				case '4':
				case '5':
				case '6':
				case '7':
				case '8':
				case '9':
					//Handle the numeric input, display to LCD for dig N.
					outs=~outs;
					output_bit(PIN_D0,outs);
					break;
				case 0x0D:
					//ENT Key, should print tag
					outs=~outs;
					output_bit(PIN_D1,outs);
					break;
				case 0x77:
					//NumLock, toggle between FreeHand mode & sequential mode
					outs=~outs;
					output_bit(PIN_D2,outs);
					break;
				case '+':
					//Increment on the sequential tag number, but no printed yet
					outs=~outs;
					output_bit(PIN_D3,outs);
					break;
				case '-':
					//Decrement on the sequential tag number, but no printed yet
					outs=~outs;
					output_bit(PIN_D4,outs);
					break;
				case '/':
					//Cancel key for clearing numeric input field
					outs=~outs;
					output_bit(PIN_D5,outs);
					break;
				case '*':
					//MENU and USER SETUP
					outs=~outs;
					output_bit(PIN_D6,outs);
					break;
				case '.':
					//cursor, for position toggle by repeating key, only for MENU and USER SETUP
					outs=~outs;
					output_bit(PIN_D7,outs);
					break;
			}	//end of switch 
		}		//end of if(PS2KeyHit())
	}			//end of while (1)
}

Code: Select all

/*
*********************************************************************************************************
*                                               uC/OS-II
*                                         The Real-Time Kernel
*
*                           (c) Copyright 2002, Nathan Brown, Longview, TX
*                                      http://www.sputnickonline.com/
*                                          All Rights Reserved
*
*                                       PIC18xxxx Specific Code
*                                       V1.00 - October 27, 2002
*
* File : OS_CPU.H
* By   : Nathan Brown, modified by John Leung for CCS PICC complier for low & mid - range CPUs
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                              DATA TYPES
*                               (Compiler Specific, CCS PICC in this case)
*********************************************************************************************************
*/

/* #define BOOLEAN short int (8 bits, -128<->127) as per 16F877A */
typedef unsigned char  		INT8U;                    /* Unsigned  8 bit quantity */
typedef signed   char  		INT8S;                    /* Signed    8 bit quantity */
typedef unsigned long int   INT16U;                   /* Unsigned 16 bit quantity */
typedef long int			INT16S;                   /* Signed   16 bit quantity */
typedef unsigned int32  	INT32U;                   /* Unsigned 32 bit quantity */
typedef signed int32  		INT32S;                   /* Signed   32 bit quantity */
typedef float          		FP32;                     /* Single precision floating point */

/* end */

Code: Select all

/*
**************************************************************************************************
*								Embedded Systems Building Blocks
*								PS/2 Keyboard 101/104 keys driver
*
*					Original obtained from www.picant.com, C2C complier web site
*						by Julio Cesar Silva Briano, modified by John Leung
*
* Filenmae 		: ps2key.h
* Programmer 	: John Leung, www.TechToys.com.hk under Downloads Section.
* Version		: Version 1.1 - 17th June 2004
* Remarks		: Consult www.beyong.org for PS/2 keyboard protocol
**************************************************************************************************
*

//											DESCRIPTION
// 			    The keyboard is assumed to be a standard PS/2 104 keyboard, or NumPad
/************************************************************************************************/
/* 										PORT configuration             				            
*  Hardware pin map:																		    
*  B0 CLOCK signal from PS/2, interrupt on falling edge.
*  A4 DATA signal from PS/2.
*/
/************************************************************************************************/
#byte 	TRISA 	= 0x85
#bit	TRISA4 	= TRISA.4
#byte	TRISB	= 0x86
#bit	TRISB0	= TRISB.0
					
#define PS2Key_Clk		PIN_B0	/* The pin address of the CLK signal (input) */			
#define	PS2Key_ClkTris	TRISB0	/* The pin direction of the CLK signal (1=input) */

#define PS2Key_Data 	PIN_A4	/* The pin address of the DATA signal (input) */
#define PS2Key_DataTris TRISA4	/* The pin direction of the DATA signal (1=input) */

/*
**************************************************************************************************
*											CONSTANTS											 *
**************************************************************************************************
*/


#define PS2Key_BUF_SIZE	10						/* Size of PS2 keyboard buffer */
#define PS2Key_START    1						/* Start bit for PS/2 protocol */
#define PS2Key_PARITY  10						/* Parity bit for PS/2 protocol */
#define PS2Key_STOP    11						/* Stop bit for PS/2 protocol */

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

INT8U PS2KeyGetKey(void);		/* Get a PS/2 scan code from driver if one is present, -1 else */
void PS2SendComm(INT8U cmd);	/* (not finished) Send a one byte command to PS/2 keyboard */
BOOLEAN PS2KeyHit(void);		/* See if a key has been pressed (TRUE if so, FALSE if not) */
void PS2KeyInit(void);			/* Initialize the PS2 Keyboard handler */

/*
**************************************************************************************************
*										 FUNCTION PROTOTYPES
*										  HARDWARE SPECIFIC
**************************************************************************************************
*/
void PS2KeyIntHandler( void );					/* Function for B0 INT, edge feom HIGH to LOW */

Code: Select all

/*
************************************************************************************************************
*								Embedded Systems Building Blocks
*								PS/2 Keyboard 101/104 keys driver
*
*					Original obtained from www.picant.com, C2C complier web site
*						by Julio Cesar Silva Briano, modified by John Leung
*
* Filenmae 		: ps2ScanCode.h
* Programmer 	: John Leung, www.TechToys.com.hk under Downloads Section.
* Version		: Version 1.1 - 17th June 2004
* Remarks		: Consult www.beyong.org for PS/2 keyboard protocol
*				
************************************************************************************************************
*											DESCRIPTION
* Three lookup tables PS2KeyUnshifted[], PS2KeyShifted[], and PS2KeyNumPad[] map PS2Key_Code to ASCII chars
* If it is going to be the Numpad ONLY, PS2KeyUnshifted[] and PS2KeyShifted[] can be undefined to save ROM
* PS2KeyNumPad[] provided for ASCII character map for Num pad, should choose % #define PS2_NUM_PAD_SCH1/2
* Application must declare PS2ScanCode.h if ASCII should be returned
************************************************************************************************************
*/


/*
************************************************************************************************************
											SCAN CODE TABLE
************************************************************************************************************
*/

/*
*****************************************************
*      												*
*   No-Shift - Lookup Table when Shift not hold     *
*      												*
*****************************************************
*/

//Uncomment the following #define if a full 104 keyboard ASCII map is included
//#define PS2_FULL_104KEY

#ifdef PS2_FULL_104KEY

const INT8U PS2KeyUnshifted[]={

0x00,	//00
0x00,	//01  F9
0x00,	//02
0x00,	//03  F5
0x00,	//04  F3
0x00,	//05  F1
0x00,	//06  F2	
0x00,	//07  F12
0x00,	//08
0x00,	//09  F10
0x00,	//0A  F8
0x00,	//0B  F6
0x00,	//0C  F4
0x09,	//0D  TAB
'`',	//0E  ` or ~
0x00,	//0F

0x00,	//10
0x00,	//11  Left ALT
0x00,	//12  Left SHIFT
0x00,	//13
0x00,	//14  Left Ctrl
'q',	//15  Q
'1',	//16  1 or !
0x00,	//17
0x00,	//18
0x00,	//19
'z',	//1A  Z
's',	//1B  S
'a',	//1C  A
'w',	//1D  W
'2',	//1E  2 or @
0x00,	//1F

0x00,	//20
'c',	//21  C
'x',	//22  X
'd',	//23  D
'e',	//24  E
'4',	//25  4 or $
'3',	//26  3 or #
0x00,	//27
0x00,	//28
' ',	//29  Space
'v',	//2A  V
'f',	//2B  F
't',	//2C  T
'r',	//2D  R
'5',	//2E  5 or %
0x00,	//2F

0x00,	//30
'n',	//31  N
'b',	//32  B
'h',	//33  H
'g',	//34  G
'y',	//35  Y
'6',	//36  6 or ^
0x00,	//37
0x00,	//38
0x00,	//39
'm',	//3A  M
'j',	//3B  J
'u',	//3C  U
'7',	//3D  7 or &
'8',	//3E  8 or *
0x00,	//3F

0x00,	//40
',',	//41  , or <
'k',	//42  K
'i',	//43  I
'o',	//44  O
'0',	//45  0 or )
'9',	//46  9 or (
0x00,	//47
0x00,	//48
'.',	//49  . or >
'/',	//4A  / or ?
'l',	//4B  L
';',	//4C  ; or :
'p',	//4D  P
'-',	//4E  - or _
0x00,	//4F

0x00,	//50
0x00,	//51
0x27,	//52  ' or "
0x00,	//53
'[',	//54  [ or {
'=',	//55  = or +
0x00,	//56
0x00,	//57
0x00,	//58  Caps Lock
0x00,	//59  Right Shift
0x0D,	//5A  Enter
']',	//5B  ] or }
0x00,	//5C
'\'',	//5D  \ or |
0x00,	//5E
0x00,	//5F

0x00,	//60
0x00,	//61
0x00,	//62
0x00,	//63
0x00,	//64
0x00,	//65
0x08,	//66  Backspace
0x00,	//67
0x00,	//68
'1',	//69  NUM - 1 or END
0x00,	//6A
'4',	//6B  NUM - 4 or LEFT
'7',	//6C  NUM - 7 or HOME
0x00,	//6D
0x00,	//6E
0x00,	//6F

'0',	//70  NUM - 0 or INS
'.',	//71  NUM - . or DEL
'2',	//72  NUM - 2 or DOWN
'5',	//73  NUM - 5
'6',	//74  NUM - 6 or RIGHT
'8',	//75  NUM - 8 or UP
0x1B,	//76  ESC
0x00,	//77  NUM LOCK
0x00,	//78  F11
'+',	//79  NUM - + (Plus)
'3',	//7A  NUM 3 or PAGE DOWN
'-',	//7B  NUM - - (Minus)
'*',	//7C  NUM - *
'9',	//7D  NUM - 9 or PAGE UP
0x00,	//7E  SCROLL LOCK
0x00,	//7F

0x00,	//80
0x00,	//81
0x00,	//82
0x00,	//83  F7
};

/*
*****************************************************
*                                                   *
*   Shift - Lookup Table Used when Shift Hold       *
*                                                   *
*****************************************************
*/

const INT8U PS2KeyShifted[]={
     0x00	//00
     0x00	//01  F9
     0x00	//02
     0x00	//03  F5
     0x00	//04  F3
     0x00	//05  F1
     0x00	//06  F2
     0x00	//07  F12
     0x00	//08
     0x00	//09  F10
     0x00	//0A  F8
     0x00	//0B  F6
     0x00	//0C  F4
     0x09	//0D  TAB
     '~'	//0E  ` or ~
     0x0	//0F

     0x00	//10
     0x00	//11  Left ALT
     0x00	//12  Left SHIFT
     0x00	//13
     0x00	//14  Left Ctrl
     'Q'	//15  Q
     '!'	//16  1 or !
     0x00	//17
     0x00	//18
     0x00	//19
     'Z'	//1A  Z
     'S'	//1B  S
     'A'	//1C  A
     'W'	//1D  W
     '@'	//1E  2 or @
     0x00	//1F

     0x00	//20
     'C'	//21  C
     'X'	//22  X
     'D'	//23  D
     'E'	//24  E
     '$'	//25  4 or $
     '#'	//26  3 or #
     0x00	//27
     0x00	//28
     ' '	//29  Space
     'V'	//2A  V
     'F'	//2B  F
     'T'	//2C  T
     'R'	//2D  R
     '%'	//2E  5 or %
     0x00	//2F

     0x00	//30
     'N'	//31  N
     'B'	//32  B
     'H'	//33  H
     'G'	//34  G
     'Y'	//35  Y
     '^'	//36  6 or ^
     0x00	//37
     0x00	//38
     0x00	//39
     'M'	//3A  M
     'J'	//3B  J
     'U'	//3C  U
     '&'	//3D  7 or &
     '*'	//3E  8 or *
     0x00	//3F

     0x0	//40
     '<'	//41  , or <
     'K'	//42  K
     'I'	//43  I
     'O'	//44  O
     ')'	//45  0 or )
     '('	//46  9 or (
     0x00	//47
     0x00	//48
     '>'	//49  > or .
     '?'	//4A  / or ?
     'L'	//4B  L
     ':'	//4C  ; or :
     'P'	//4D  P
     '_'	//4E  - or _
     0x00	//4F

     0x00	//50
     0x00	//51
     0x22	//52  ' or "
     0x00	//53
     '{'	//54  [ or {
     '+'	//55  = OR +
     0x00	//56
     0x00	//57
     0x00	//58  Caps Lock
     0x00	//59  Right Shift
     0x0D	//5A  Enter
     '}'	//5B  ] or }
     0x00	//5C
     '|'	//5D  \ or |
     0x00	//5E
     0x00	//5F

     0x00	//60
     0x00	//61
     0x00	//62
     0x00	//63
     0x00	//64
     0x00	//65
     0x08	//66  Backspace
     0x00	//67
     0x00	//68
     '1'	//69  NUM - 1 or END
     0x00	//6A
     '4'	//6B  NUM - 4 or LEFT
     '7'	//6C  NUM - 7 or HOME
     0x00	//6D
     0x00	//6E
     0x00	//6F

     '0'	//70  NUM - 0 or INS
     '.'	//71  NUM - . or DEL
     '2'	//72  NUM - 2 or DOWN
     '5'	//73  NUM - 5
     '6'	//74  NUM - 6 or RIGHT
     '8'	//75  NUM - 8 or UP
     0x1B	//76  ESC
     0x00	//77  NUM LOCK
     0x00	//78  F11
     '+'	//79  NUM - + (Plus)
     '3'	//7A  NUM 3 or PAGE DOWN
     '-'	//7B  NUM - - (Minus)
     '*'	//7C  NUM - *
     '9'	//7D  NUM - 9 or PAGE UP
     0x00	//7E  SCROLL LOCK
     0x00	//7F

     0x00	//80
     0x00	//81
     0x00	//82
     0x00	//83  F7
};

#endif


/*
*****************************************************
*                                                   *
*   Numeric KeyPad only - Lookup Table			    *
*                                                   *
*****************************************************
*/

//Uncomment the following #define if NumPad is used
//Should use a Decode() sub-routine to decode the array index.
//This method for Flash Rom space saving

//#define PS2_NUM_PAD_SCH1

#ifdef PS2_NUM_PAD_SCH1

const INT8U PS2KeyNumPad[17] ={0x70, 0x69, 0x72, 0x7A, 0x6B, 0x73, 0x74, 0x6C,\
							   0x75, 0x7D, 0x79, 0x7B, 0x7C, 0x4A, 0x71, 0x5A, 0x77};
 
/*
	Array index
	    0	//70  			NUM - 0 or INS   
		1	//69  			NUM - 1 or END
     	2	//72  			NUM - 2 or DOWN
     	3	//7A  			NUM - 3 or PAGE DOWN
     	4	//6B  			NUM - 4 or LEFT	
     	5	//73  			NUM - 5
     	6	//74  			NUM - 6 or RIGHT
     	7	//6C  			NUM - 7 or HOME
     	8	//75  			NUM - 8 or UP
     	9	//7D  			NUM - 9 or PAGE UP
     	10	//79  			NUM - + (Plus)
		11	//7B  			NUM - - (Minus)
		12	//7C  			NUM - *
		13  //4A or E04A  	NUM - /(division), extended code ignore here
		14	//71  			NUM - . or DEL
		15  //5A or E05A 	NUM - ENT, extended code ignore here
     	16	//77  			NUM LOCK
*/
#endif


/*
******************************************************
*                                                  	 *
*   Numeric KeyPad only - Lookup Table to ASCII      *
*   Remarks: NumLock is mapped to 0x77 in this table *
******************************************************
*/

//Uncomment the following #define if NumPad is used
//Should choose between PS2_NUM_PAD_SCH1 or SCH2
//Should shift by 0x4A to map the ASCII character

#define PS2_NUM_PAD_SCH2
#ifdef 	PS2_NUM_PAD_SCH2
#define OFFSET_SCH2		0x4A
const INT8U PS2KeyNumPad[] = {
'/',	//4A  / or ?
'l',	//4B  L
';',	//4C  ; or :
'p',	//4D  P
'-',	//4E  - or _
0x00,	//4F

0x00,	//50
0x00,	//51
0x27,	//52  ' or "
0x00,	//53
'[',	//54  [ or {
'=',	//55  = or +
0x00,	//56
0x00,	//57
0x00,	//58  Caps Lock
0x00,	//59  Right Shift
0x0D,	//5A  Enter
']',	//5B  ] or }
0x00,	//5C
'\'',	//5D  \ or |
0x00,	//5E
0x00,	//5F

0x00,	//60
0x00,	//61
0x00,	//62
0x00,	//63
0x00,	//64
0x00,	//65
0x08,	//66  Backspace
0x00,	//67
0x00,	//68
'1',	//69  NUM - 1 or END
0x00,	//6A
'4',	//6B  NUM - 4 or LEFT
'7',	//6C  NUM - 7 or HOME
0x00,	//6D
0x00,	//6E
0x00,	//6F

'0',	//70  NUM - 0 or INS
'.',	//71  NUM - . or DEL
'2',	//72  NUM - 2 or DOWN
'5',	//73  NUM - 5
'6',	//74  NUM - 6 or RIGHT
'8',	//75  NUM - 8 or UP
0x1B,	//76  ESC
0x77,	//77  NUM LOCK
0x00,	//78  F11
'+',	//79  NUM - + (Plus)
'3',	//7A  NUM 3 or PAGE DOWN
'-',	//7B  NUM - - (Minus)
'*',	//7C  NUM - *
'9',	//7D  NUM - 9 or PAGE UP
};
#endif

Code: Select all

/*
**************************************************************************************************
*								Embedded Systems Building Blocks
*						     PS/2 Keyboard 104 keys, NumPad driver
*
*					Original obtained from www.picant.com, C2C complier web site
*						by Julio Cesar Silva Briano, modified by John Leung
*
* Filenmae 		: ps2key.c
* Programmer 	: John Leung, www.TechToys.com.hk under Downloads Section.
* Version		: Version 1.1 - 17th June 2004
* Remarks		: Consult www.beyong.org for PS/2 keyboard protocol
**************************************************************************************************
*											DESCRIPTION
*		This is a PS/2 keyboard driver for standard 101/104 keyboard or Numerical Keypad
*	 			Application software must include PS2Key.h and PS2ScanCode.h
*							PS2Key.h contains hardware port configuration
*			PS2ScanCode.h configures if it is a complete 101 keyboard, or just the Numpad
*	Two lookup tables PS2KeyUnshifted[] and PS2KeyShifted[] map the PS2Key_Code to ASCII characters
* If it is going to be the Numpad ONLY, PS2KeyUnshifted[] and PS2KeyShifted[] can be undefined to save ROM
*					Application must declare the followings (see ps2key.h)
*	PS2key.c is PS/2 keyboard driver to handle ordinary PS/2 or AT-style keyboard with mcu
*	Global variable PS2Key_Code returns the raw key code of a key
*	Key Buffer is defined by constant PS2KEY_BUF_SIZE (in PS2Key.h)
*
*	PS2Key_Clk			The port address of the PS/2 CLK signal
*	PS2Key_Data			The port address of the PS/2 Data signal
*	PS2Key_BUF_SIZE 	Size of the PS/2 keyboard buffer
**************************************************************************************************
*/

/*
**************************************************************************************************
											GLOBAL VARIABLES
**************************************************************************************************
*/

INT8U	PS2KeyBuf[PS2KEY_BUF_SIZE];	//PS2 Keyboard buffer, the register to store characters key in
INT8U	PS2KeyBufInIx;				//Index into PS/2 key buf where next scan code will be inserted
INT8U	PS2KeyBufOutIx;				//Index into PS/2 key buf where next scan code will be removed
INT8U	PS2KeyNRead;				//Number of keys read from the PS/2 keyboard
INT8U	PS2Key_Code;				//Key code from PS/2 keyboard
INT8U	PS2Key_bit_Ix;				//bit index of the byte stream, Start_bit(1), Parity(10), Stop_bit(11)
BOOLEAN PS2_SHIFT;					//TRUE if left or right shift pressed
BOOLEAN	PS2_BREAKCODE;				//TRUE if a BREAKCODE received
 
/*
**************************************************************************************************
									LOCAL FUNCTION PROTOTYPES
**************************************************************************************************
*/
void 	PS2KeyBufIn(INT8U code);				/* Insert scan code into keyboard buffer */
INT8U 	PS2KeyDecode(void);					/* Function to decode a key stroke */


/*
**************************************************************************************************
*								INSERT KEY CHARACTER INTO KEYBOARD BUFFER
* Description: This function inserts a key character into the keyboard buffer from a PS/2 keyboard
**************************************************************************************************
*/
void PS2KeyBufIn (INT8U code)
{
	//OS_ENTER_CRITICAL();						//Start of critical section of code, disable ints
	if (PS2KeyNRead < PS2Key_BUF_SIZE) {		//make sure that we don't overflow the buffer
		PS2KeyNRead++;							//Increment the number of keys read
		PS2KeyBuf[PS2KeyBufInIx++] = code;		//Store the scan code into the buffer
		if (PS2KeyBufInIx >= PS2Key_BUF_SIZE) {	//Adjust index to the next scan code to put in buffer
			PS2KeyBufInIx = 0;
		}
	//OS_EXIT_CRITICAL();
	//Signal semaphore if an RTOS exist!
	} else {
		//OS_EXIT_CRITICAL();
	}
}

/*
**************************************************************************************************
*									DECODE PS/2 KEYBOARD SCAN CODE
* Description: This function is called to determine the key scane code of the PS/2 keyboard
* Arguments:   none
* Returns:	   the key scan code
**************************************************************************************************
*/
INT8U PS2KeyDecode(void)
{
	;
}

/*
**************************************************************************************************
*										GET KEY	
* Description: 	Get a PS/2 keyboard scan code from the keyboard driver
* Arguments:   	none
* Returns:	   	!=0xFF is the key scan code of the PS/2 keyboard key pressed
*				==0xFF indicates that there is on key in the PS2KeyBuf[PS2KEY_BUF_SIZE] buffer 
**************************************************************************************************
*/

INT8U PS2KeyGetKey (void)
{
	INT8U code;

			//OS_ENTER_CRITICAL();
	if (PS2KeyNRead > 0) {					/* See if we have keys in PS2KeyBuf[] */
		PS2KeyNRead--;						/* Decrement the number of keys in the buffer */
		code = PS2KeyBuf[PS2KeyBufOutIx];	/* Get scan code from the buffer */
		PS2KeyBufOutIx++;
		if (PS2KeyBufOutIx >= PS2Key_BUF_SIZE) {
			PS2KeyBufOutIx = 0;
			}
			//OS_EXIT_CRITICAL();
		return (code);						/* return the scan code of the key pressed */
		} else {
			//OS_EXIT_CRITICAL();
		return (0xFF);						/* No scan codes in buffer, return -1 */
	}
}

/*
**************************************************************************************************
*										SEND COMMAND
* Description: 	Send command to the PS/2 keyboard
* Arguments:   	cmd is the command to send
*				$ED Set Status LED's - This command can be used to turn on and off the Num Lock, Caps Lock & Scroll Lock LED's. 
*					After Sending ED, keyboard will reply with ACK (FA) and wait for another byte which determines their Status.
*					Bit 0 controls the Scroll Lock, Bit 1 the Num Lock and Bit 2 the Caps lock. Bits 3 to 7 are ignored.  
* 				$EE Echo - Upon sending a Echo command to the Keyboard, the keyboard should reply with a Echo (EE) 
*				$F0 Set Scan Code Set. Upon Sending F0, keyboard will reply with ACK (FA) and wait for another byte, 
					01-03 which determines the Scan Code Used. 
					Sending 00 as the second byte will return the Scan Code Set currently in Use
*				$F3 Set Typematic Repeat Rate. Keyboard will Acknowledge command with FA and wait for second byte, 
					which determines the Typematic Repeat Rate. 
*				$F4 Keyboard Enable - Clears the keyboards output buffer, enables Keyboard Scanning and returns an Acknowledgment. 
*				$F5 Keyboard Disable - Resets the keyboard, disables Keyboard Scanning and returns an Acknowledgment. 
*				$FE Resend - Upon receipt of the resend command the keyboard will re- transmit the last byte sent. 
*				$FF Reset - Resets the Keyboard. 

* Returns:	   	none 
* Remarks:		Refer to AN1723 of Motorola for detailed description of Host-to-KBD protocol
*				Is NOT working as per 17th June 2004. Should work more on this function.
**************************************************************************************************
*/

void PS2SendComm(INT8U cmd)
{
	PS2Key_bit_Ix = 0;				//bit index of the byte stream, Start_bit(1), Parity(10), Stop_bit(11), ACK_bit(12)
	
	disable_interrupts(INT_EXT);	//disable external interrupt B0 on falling edge

	output_low(PS2Key_Clk); 		//host forces PS2 clock line low.
	delay_us(35);					//After approx. 35us, the host pulls PS2 data line low
	output_low(PS2Key_Data);		//This sequence of event signals the keyboard that 
									//the host is about to transfer a command
	delay_us(125);					//The clock signal is released and pulled high by the keyboard's pullup
	PS2Key_ClkTris = 1;				//resisitor after the falling edge of the data signal

	/* Transfer of data from host to keyboard will start approx. 1ms after the rising edge of the clock */
	/* shift bit to PS2Key_Data on every falling edge of the PS2Key_Clk line */
	do
	{	while (input(PS2Key_Clk))
			; //hold when PS2Key_Clk is high
		output_bit(PS2Key_Data, cmd&0x01);
		cmd = cmd>>1;		
		//PS2Key_DataTris=1;
		PS2Key_bit_Ix++;
	} 	while(PS2Key_bit_Ix<=12);

	PS2Key_bit_Ix = 0;
	/* send data from host complete */
	PS2Key_DataTris = 1;			//release data line, reset to input

	ext_int_edge(0, H_TO_L);		//set external interrupt to falling edge
 	enable_interrupts(INT_EXT);		//release PS2 KBD clock line. driven high by PS2 KBD
}

/*
**************************************************************************************************
*									SEE IF ANY KEY IN BUFFER	
* Description: 	This function checks to see if a key was pressed
* Arguments:   	none
* Returns:	   	TRUE if a key has been pressed
*				FALSE if no key pressed
**************************************************************************************************
*/
BOOLEAN PS2KeyHit(void)
{
	BOOLEAN hit;

	//OS_ENTER_CRITICAL();
	hit = (BOOLEAN)(PS2KeyNRead > 0)? TRUE : FALSE;
	//OS_EXIT_CRITICAL();
	return(hit);
}

/*
*********************************************************************************************************
*                                  PS2 KEYBOARD DRIVER INITIALIZATION
*
* Description : This function initializes the PS2 driver.
* Arguments   : None.
* Returns     : None.
*********************************************************************************************************
*/

void PS2KeyInit(void)
{
	PS2KeyNRead 	=0;				//Clear the number of keys read
	PS2KeyBufInIx 	=0;				//Clear the key codes inserted at the beginning of the buffer
	PS2KeyBufOutIx	=0;				//Clear the key codes removed at the beginning of the buffer
	PS2_BREAKCODE	=FALSE;
	PS2_SHIFT		=FALSE;

	PS2Key_DataTris =1;				//Set Data line an input
	PS2Key_ClkTris	=1;				//Set clock line an input

	ext_int_edge(0, H_TO_L);		//set external interrupt to falling edge
	enable_interrupts(INT_EXT);		//enable external interrupt B0
}

/*
*********************************************************************************************************
*                                     PS2 KEYBOARD INTERRUPT HANDLER
* Description:  This function is called by an interrupt handler (e.g. B0 EXT INT on falling edge)
* 				Detect the clock pulse (High_to_Low) for new bit
* Arguments  : 	none
* Returns    : 	none
* Notes      : 	Put a scan code to PS2KeyBuf[] if a valid byte acquired
*				Set PS2KeyNRead then
*********************************************************************************************************
*/

void PS2KeyIntHandler(void)
{
	BOOLEAN	PS2Key_Data_State;	//Temp variable for Data pin, PS2Key_Data_State
	BOOLEAN	PS2Status_Parity;	//Parity bit	

		PS2Key_Data_State = input(PS2Key_Data);
		PS2Key_bit_Ix++;

		switch (PS2Key_bit_Ix)
  		{
    		case PS2Key_START:
         		if (PS2Key_Data_State || input(PS2Key_Clk))
            		PS2Key_bit_Ix=0;		//	Start bit clock is a high_to_low transition.
         									//	Start bit is a low bit. 
         		PS2Key_Code=0;
         		PS2Status_Parity=0;
         		break;
    		case PS2Key_PARITY:
         		PS2Status_Parity = PS2Key_Data_State;
         		break;
    		case PS2Key_STOP:									// Stop bit got, put key in buffer
				if (PS2Key_Code==0x12||PS2Key_Code==0x59)	// Key=Left shift or right shift
				{	if (PS2_BREAKCODE==TRUE)				
						PS2_SHIFT=FALSE;
					else
						PS2_SHIFT=TRUE;
				}

				if (PS2Key_Code==0xF0)						// Is a break code!
					PS2_BREAKCODE=TRUE;
				else if (PS2_BREAKCODE==TRUE)
					PS2_BREAKCODE=FALSE;
				else
	 				PS2KeyBufIn (PS2Key_Code);				// Put valid byte in PS2KeyBuf[], ignore break code

         		PS2Key_bit_Ix=0;
         		break;
    		default:
         		PS2Key_Code = PS2Key_Code >> 1;
       			  if (PS2Key_Data_State)
           		 		PS2Key_Code = PS2Key_Code | 0x80;
        		 break;
  		}//end of switch ofr KDB send to Host
}



Last edited by JohnLeung on Wed Feb 08, 2006 3:20 am, edited 3 times in total.

Tom J
Posts: 2
Joined: Thu Jan 26, 2006 11:31 am

Post by Tom J » Thu Jan 26, 2006 12:25 pm

Hi John,

Could you please give me some explanation on this code. I'm not a very experienced programmer. I've connected a keyboard to a board. I'd like to use your code to be able to type in a character that gets displayed on a standard alpha numeric LCD display. In the main function I tried to detect if a key has been hit by displaying a message on the LCD by adding a line after " if(PS2KeyHit()) "

But whenever a key has been pressed or not, the message always appears on the screen.
I also moved the clock to pin B1. (port a is used for the display)

I also don't quite understand what should happen on the outputs of port D in your example. Do the outputs toggle if (a) specified key(s) get pressed ?

Could you please have a look and help me ?

Kind regards,

Tom

Here's the code:

ps2main:

/*
**************************************************************************************
* PS2Main.c to demonstrate the power of PS2Key.c and PS2Key.h drivers
* Date : 17th June 2004
* Programmer : John Leung, www.emed-technologies.com under Downloads Section.
**************************************************************************************
*/


#include <16f877.h>
#use delay(clock=4000000)
#fuses HS, NOWDT, NOLVP

#define LCD_DB4 PIN_A0
#define LCD_DB5 PIN_A1
#define LCD_DB6 PIN_A2
#define LCD_DB7 PIN_A3

#define LCD_E PIN_A4
#define LCD_RS PIN_A5
#include <LCDflexTom.c>
setup_adc_ports( ALL_DIGITAL );

#include <OS_CPU.h> //typedef compatible with uCOS-II style

#include <PS2Key.h>
#include <PS2ScanCode.h>
#include <PS2Key.c>
setup_adc_ports( ALL_DIGITAL );
INT8U PS2Key_Char;

#int_EXT
void ext_isr(void)
{
PS2KeyIntHandler();
}

#define led pin_a5

delay_seconds(int sec) {
int i;
for(i=0;i<sec;i++)
delay_ms(1000);
}

void main(void)
{
INT8U outs = 0;
lcd_init();
PS2KeyInit(); //Init PS2 Keyboard
enable_interrupts(global); //enable global interrupts
printf(lcd_putc,"\fhallo");

while(1)
{
if(PS2KeyHit())
{
lcd_gotoxy(1,2);
printf(lcd_putc,"keystroke detected");
/* PS2KeyNumPad[] ONLY, & OFFSET_SCH2 from PS2ScanCode.h */
PS2Key_Char = PS2KeyNumPad[PS2KeyGetKey()-OFFSET_SCH2];
lcd_gotoxy(1,3);
lcd_putc(PS2Key_Char);
switch (PS2Key_Char){
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
//Handle the numeric input, display to LCD for dig N.
outs=~outs;
output_bit(PIN_D0,outs);
break;
case 0x0D:
//ENT Key, should print tag
outs=~outs;
output_bit(PIN_D1,outs);
break;
case 0x77:
//NumLock, toggle between FreeHand mode & sequential mode
outs=~outs;
output_bit(PIN_D2,outs);
break;
case '+':
//Increment on the sequential tag number, but no printed yet
outs=~outs;
output_bit(PIN_D3,outs);
break;
case '-':
//Decrement on the sequential tag number, but no printed yet
outs=~outs;
output_bit(PIN_D4,outs);
break;
case '/':
//Cancel key for clearing numeric input field
outs=~outs;
output_bit(PIN_D5,outs);
break;
case '*':
//MENU and USER SETUP
outs=~outs;
output_bit(PIN_D6,outs);
break;
case '.':
//cursor, for position toggle by repeating key, only for MENU and USER SETUP
outs=~outs;
output_bit(PIN_D7,outs);
break;
} //end of switch
} //end of if(PS2KeyHit())
} //end of while (1)
}



The PS2key.h file:

/*
**************************************************************************************************
* Embedded Systems Building Blocks
* PS/2 Keyboard 101/104 keys driver
*
* Original obtained from www.picant.com, C2C complier web site
* by Julio Cesar Silva Briano, modified by John Leung
*
* Filenmae : ps2key.h
* Programmer : John Leung, www.emed-technologies.com under Downloads Section.
* Version : Version 1.1 - 17th June 2004
* Remarks : Consult www.beyong.org for PS/2 keyboard protocol
**************************************************************************************************
*

// DESCRIPTION
// The keyboard is assumed to be a standard PS/2 104 keyboard, or NumPad
/************************************************************************************************/
/* PORT configuration
* Hardware pin map:
* B0 CLOCK signal from PS/2, interrupt on falling edge.
* A4 DATA signal from PS/2.
*/
/************************************************************************************************/
#byte TRISB = 0x86
#bit TRISB1 = TRISB.1
//#byte TRISB = 0x86
#bit TRISB0 = TRISB.0

#define PS2Key_Clk PIN_B0 /* The pin address of the CLK signal (input) */
#define PS2Key_ClkTris TRISB0 /* The pin direction of the CLK signal (1=input) */

#define PS2Key_Data PIN_B1 /* The pin address of the DATA signal (input) */
#define PS2Key_DataTris TRISB1 /* The pin direction of the DATA signal (1=input) */

/*
**************************************************************************************************
* CONSTANTS *
**************************************************************************************************
*/


#define PS2Key_BUF_SIZE 10 /* Size of PS2 keyboard buffer */
#define PS2Key_START 1 /* Start bit for PS/2 protocol */
#define PS2Key_PARITY 10 /* Parity bit for PS/2 protocol */
#define PS2Key_STOP 11 /* Stop bit for PS/2 protocol */

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

INT8U PS2KeyGetKey(void); /* Get a PS/2 scan code from driver if one is present, -1 else */
void PS2SendComm(INT8U cmd); /* (not finished) Send a one byte command to PS/2 keyboard */
BOOLEAN PS2KeyHit(void); /* See if a key has been pressed (TRUE if so, FALSE if not) */
void PS2KeyInit(void); /* Initialize the PS2 Keyboard handler */

/*
**************************************************************************************************
* FUNCTION PROTOTYPES
* HARDWARE SPECIFIC
**************************************************************************************************
*/
void PS2KeyIntHandler( void ); /* Function for B0 INT, edge feom HIGH to LOW */

JohnLeung
Posts: 28
Joined: Wed Jun 22, 2005 4:18 am

PS2 keypad driver

Post by JohnLeung » Thu Jan 26, 2006 9:12 pm

Hi Tom

Yes, I should have posted a better code. However, this code works out of my workbench. The original code just toggle a PORTD.x bit for debug purpose only. Sorry for misleading.

I have modified the code such that it displays the character key on a 2x20 LCD display. Please find the code below for ps2main.c and a new LCD driver lcd_x1.c. I am using the Melab's X1 board for experiment.

I will post more pictures and details on my web. Please take a look at the moment at www.emed-technologies.com. I am going to move the web presence to www.techtoys.com.hk afterwards.


Your code seems OK. If you still can't get the driver worked, write to me again.

John Leung

Code: Select all

/*	
**************************************************************************************
*	PS2Main.c to demonstrate the power of PS2Key.c and PS2Key.h drivers 
*	Date		: 17th June 2004
*	Programmer	: John Leung, www.emed-technologies.com under Downloads Section.
*	Hardware    : Tested on Melab's X1 board dated 27-Jan 2006
*	Web page	: www.techtoys.com.hk
**************************************************************************************
*/


#include <16f877a.h>
#use delay(clock=20000000)
#fuses HS, NOWDT, NOLVP

#include <OS_CPU.h>				//typedef compatible with uCOS-II style

#include <PS2Key.h>
#include <PS2ScanCode.h>
#include <PS2Key.c>
#include <lcd_x1.c>

INT8U PS2Key_Char;

#int_EXT
void ext_isr(void)
{
	PS2KeyIntHandler();
}

void main(void)
{
	INT8U cnt;
	INT8U ptr = 1;

	port_b_pullups(TRUE);
	setup_adc_ports(NO_ANALOGS);

	PS2KeyInit();				//Init PS2 Keyboard
    lcd_init();					//Init 2x20 characters LCD module

	lcd_putc('\f');				//clear the module
	lcd_gotoxy(1,1);			//goto position 1,1 of the LCD module
	lcd_putc("PS2 Keypad Test");//Put a fixed string on LCD

	enable_interrupts(global);	//enable global interrupts

	while(1)
	{
		if(PS2KeyHit())
		{
			/* PS2KeyNumPad[] ONLY, & OFFSET_SCH2 from PS2ScanCode.h */
			PS2Key_Char = PS2KeyNumPad[PS2KeyGetKey()-OFFSET_SCH2];	
		
			switch (PS2Key_Char){
				case '0':
				case '1':
				case '2':
				case '3':
				case '4':
				case '5':
				case '6':
				case '7':
				case '8':
				case '9':
				case '+':
				case '-':
				case '*':
				case '/':
				case '.':
					//Handle the numeric input, display to LCD for a num-pad
					lcd_gotoxy(ptr++,2);
					if(ptr>20) ptr=1;
					lcd_putc(PS2Key_Char);
					break;
				case 0x0D:
					//ENT Key, should print tag
					//function key, do the function you want
					break;
				case 0x77:
					//NumLock, another function key, like clearing the display
					for(cnt=1;cnt<21;cnt++) {lcd_gotoxy(cnt,2);lcd_putc(' ');}
					ptr=1; //reset the position pointer
					break;
			}	//end of switch 
		}		//end of if(PS2KeyHit())
	}			//end of while (1)
}

Code: Select all

///////////////////////////////////////////////////////////////////////////
////                             LCD_X1.C                                ////
////                 Driver for common LCD modules                     ////
////                                                                   ////
////  lcd_init()   Must be called before any other function.           ////
////                                                                   ////
////  lcd_putc(c)  Will display c on the next position of the LCD.     ////
////                     The following have special meaning:           ////
////                      \f  Clear display                            ////
////                      \n  Go to start of second line               ////
////                      \b  Move back one position                   ////
////                                                                   ////
////  lcd_gotoxy(x,y) Set write position on LCD (upper left is 1,1)    ////
////                                                                   ////
////  lcd_getc(x,y)   Returns character at position x,y on LCD         ////
////                                                                   ////
///////////////////////////////////////////////////////////////////////////
////        			Modified from CCS lcd.c driver                 ////
////				Fully working for read and write byte			   ////
////		 	Date: 7th June 2004, created by John Leung			   ////
////			Hardware : Melab's X1 board 						   ////
////			Web: www.techtoys.com.hk							   ////
///////////////////////////////////////////////////////////////////////////

// As defined in the following structure the pin connection is as follows:
//     E0  rs
//     E1  enable
//     E2  rw
//     D4  D4
//     D5  D5
//     D6  D6
//     D7  D7
//
//   LCD pins D0-D3 are not used.

// Un-comment the following define to use port B
// #define use_portb_lcd TRUE


struct lcd_pin_map {                 // This structure is overlayed
           BOOLEAN rs;               // on to an I/O port to gain
           BOOLEAN enable;           // access to the LCD pins.
           BOOLEAN rw;
        } lcd;

#byte lcd = 9           // ctl bits on to port E (at address 9)
#byte data = 8		// data on to port D (at address 8)

#define set_tris_lcd(x) set_tris_e(x)
#define set_tris_data(x) set_tris_d(x)

#define lcd_type 2           // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40    // LCD RAM address for the second line


BYTE const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6};
                             // These bytes need to be sent to the LCD
                             // to start it up.


                             // The following are used for setting
                             // the I/O port direction register.

//struct lcd_pin_map const LCD_WRITE = {0,0,0,0,0}; // For write mode all pins are out
//struct lcd_pin_map const LCD_READ = {0,0,0,0,15}; // For read mode data pins are in


BYTE lcd_read_byte() {
      BYTE low,high;
      //set_tris_lcd(LCD_READ);
      set_tris_lcd(0);
      set_tris_data(0xff);	
      lcd.rw = 1;
      delay_cycles(1);
      lcd.enable = 1;
      delay_cycles(1);
      high = data;
      lcd.enable = 0;
      delay_cycles(1);
      lcd.enable = 1;
      delay_us(1);
      low = data;
      lcd.enable = 0;
      //set_tris_lcd(LCD_WRITE);
      set_tris_data(0x00);
      return( (high&0xf0) | (low>>4));
}


void lcd_send_nibble( BYTE n ) {
      data = n;
      data<<=4;
      delay_cycles(1);
      lcd.enable = 1;
      delay_us(2);
      lcd.enable = 0;
}


void lcd_send_byte( BYTE address, BYTE n ) {

      lcd.rs = 0;
      while ( bit_test(lcd_read_byte(),7) ) ;
      lcd.rs = address;
      delay_cycles(1);
      lcd.rw = 0;
      delay_cycles(1);
      lcd.enable = 0;
      lcd_send_nibble(n >> 4);
      lcd_send_nibble(n & 0xf);
}


void lcd_init() {
    BYTE i;
    //set_tris_lcd(LCD_WRITE);
    set_tris_lcd(0);
    set_tris_data(0);
    lcd.rs = 0;
    lcd.rw = 0;
    lcd.enable = 0;
    delay_ms(15);
    for(i=1;i<=3;++i) {
       lcd_send_nibble(3);
       delay_ms(5);
    }
    lcd_send_nibble(2);
    for(i=0;i<=3;++i)
       lcd_send_byte(0,LCD_INIT_STRING[i]);
}


void lcd_gotoxy( BYTE x, BYTE y) {
   BYTE address;

   if(y!=1)
     address=lcd_line_two;
   else
     address=0;
   address+=x-1;
   lcd_send_byte(0,0x80|address);
}

void lcd_putc( char c) {
   switch (c) {
     case '\f'   : lcd_send_byte(0,1);
                   delay_ms(2);
                                           break;
     case '\n'   : lcd_gotoxy(1,2);        break;
     case '\b'   : lcd_send_byte(0,0x10);  break;
     default     : lcd_send_byte(1,c);     break;
   }
}

char lcd_getc( BYTE x, BYTE y) {
   char value;

    lcd_gotoxy(x,y);
    while ( bit_test(lcd_read_byte(),7) ); // wait until busy flag is low
    lcd.rs=1;
    value = lcd_read_byte();
    lcd.rs=0;
    return(value);
}
Last edited by JohnLeung on Sun Feb 12, 2006 1:54 am, edited 1 time in total.

Tom J
Posts: 2
Joined: Thu Jan 26, 2006 11:31 am

Post by Tom J » Thu Feb 02, 2006 12:51 am

Hi John,

Thanks for your response and a happy new year. ( I presume that you celebrate chinese new year in your area ? )
I got the code working. It turns out that it doesn't work on 4 mHz. Just changing the code to that low frequency doesn't work. Everything fell into place after I upgraded my board to 20 mHz.
I've been playing around with the code and it seems to be working fine now.

Thanks and regards,

Tom

JohnLeung
Posts: 28
Joined: Wed Jun 22, 2005 4:18 am

Spent too much time on switch case (PS2Key_STOP)

Post by JohnLeung » Thu Feb 02, 2006 9:32 am

Hi Tom

Thks. You have catched a bug for me. Because a 4MHz PIC is not fast enough for the swtich case (PS2Key_STOP) in void PS2KeyIntHandler(void), it couldn't catch a real key code. As you know, the period of the keyboard clk ranges from 30us - 50us. A 4Mhz PIC has a 1us machine cycle. That may not be enough if we haven't paid enough attention to timing. This is a bug, because this code should be able to handle 4Mhz-20Mhz.

I will revise the code soon.

John

JohnLeung
Posts: 28
Joined: Wed Jun 22, 2005 4:18 am

Revised version for 4MHz crystal

Post by JohnLeung » Thu Feb 02, 2006 11:43 pm

OK, now I know the problem.

The following actions solved the problem:

1. Change to 4MHz crystal
2. Add #use fast_io(b) in main()
3. The key modification in void PS2KeyIntHandler(void). Previously
switch (PS2Key_bit_Ix) case... applied but the assembly code
generated took too long for clock signal detection of keyboard.
Instead of a switch, a simple if() else if ... selection employed
4. Detection of PS2_BREAKCODE and PS2_SHIFT deleted from
PS2KeyIntHandler(void) to save interrupt time.
5. Finally, change A4 -> B1 for PS2Key_Data (for hardware simplicity only)

John Leung
May download the latest version from www.TechToys.com.hk now.

julioSilva
Posts: 1
Joined: Fri Oct 13, 2006 8:26 am

Post by julioSilva » Fri Oct 13, 2006 8:30 am

Hi. Im Julio Cesar Silva Briano.

great job John, Contratulations!

regards.

lopb
Posts: 8
Joined: Fri Dec 11, 2009 12:40 pm

any help will be apreciated

Post by lopb » Fri Dec 11, 2009 12:43 pm

I've trying to run this soft in a 16f628a, only changing the ports, and the pins of the USART port. in conclusion the serial port is working :shock: , (with a script test) and the por A i don't know. The keyboard is connected to the port A (in this case, this port handles the external OSC) and i don't know if that's the problem, because i've changed the oscilator to internal (4MHz) with no results. Can you help me with this, what should i do?
Thanks a lot :?

cupidraul
Posts: 1
Joined: Thu Apr 14, 2011 9:53 am

Re: PS2 keypad driver with buffer

Post by cupidraul » Thu Apr 14, 2011 10:05 am

Hi John,
I am trying to interface keyboard with pic 16f877a. I am using the code which you posted on the web. I am using a 20MHz crystal oscillator in my circuit. whenever I switch on my circuit without the crystal oscillator a message displays on the screen as PS2 Keypad Test. but when I use a 20MHz crystal oscillator my screen doesn't display anything. Can you tell me what is the problem. Also how do I see whether my keyboard is transmitting data or not.

haris rashid
Posts: 1
Joined: Tue Apr 10, 2012 2:11 am

Re: PS2 keypad driver with buffer

Post by haris rashid » Tue Apr 10, 2012 2:23 am

Hi John,
kindly send me the diagram of this project plz.......
thanks for paying attention

Post Reply