/**
 * This example for the PIC16f628a communicates with a PS/2 keyboard.
 * The keyboard's CLOCK line is attached directly to B0, the CLOCK line 
 * to B3, a LED of some sort to B5, and some sort of serial display to 
 * B2.  The keyboard's power and ground lines must of course be attached 
 * to 5V and ground.
 *
 * Both the data and clock lines of a PS/2 keyboard are open-collector;
 * this means neither the keyboard nor the PIC ever drive high values, 
 * just low ones, with a pullup resistor producing a logic 1 whenever
 * neither end is sending anything.  This is why we keep twiddling the 
 * TRISB values instead of the PORTB ones;  PORTB is always zero for the 
 * clock and data bits, we just tristate them unless we want to express 
 * that zero.
 *
 * After a PS/2 keyboard powers on, it waits a quarter of a second then 
 * sends 0xAA to announce it is online.  Once it sees this, the PIC
 * will give the keyboard an echo request, 0xEE, and get back 0xEE
 * from the keyboard.  All transmission and reception is logged with 
 * RS232 output, with outgoing bytes surrounded by angle brackets.
 *
 * For more details on the PS/2 protocol, see Adam Chapweske's
 * very helpful page at http://computer-engineering.org/ps2protocol/
 *
 * This example has been expanded from 0012-keyboard.c into a
 * general-purpose ps2-to-rs232 converter.  It is designed for a US
 * keyboard, and converting it to any other may be a very difficult 
 * task since I have used tricks assuming ASCII alphanumerics to
 * cram that many keys into so small an EEPROM space.  It may be 
 * possible to just dump all the arrays into code space to get enough.
 * I tried to make it as complete as possible.
 *
 * It currently understands the standard alphanumeric keys,
 * shift, numpad, caps/scroll/numlock, tab, backspace, enter,
 * control-keys, alt-keys, F1-F12, arrow keys, sysrq, printscreen, 
 * pause, and pgup/pgdn/ins/del/home/end.
 *
 * ENTER sends \r\n.  This is easy to change if you don't want the \r.
 *
 * Scroll-lock sends xon/xoff characters.
 *
 * CTRL-key sends the ASCII value of the character with the 0x40 bit 
 * masked out.
 * ALT-key sends the ASCII value of the character with the 0x80 bit on.
 *
 * caps-lock sends uppercase letters when enabled.  shift plus enabled
 * capslock sends lowercase again.
 *
 * Numlock sends numbers typed on the numpad when enabled, ESC codes 
 * when disabled.
 *
 * Direction keys, pgup/pgdn/etc, and F1-F2 send ESC codes.
 *
 * SysRQ blips the FIN_BIT line off when pressed.
 * Pause toggles it.
 * Print screen toggles it and repeats if you hold it.
 */
#define __16f628a
#include "pic/pic16f628a.h"
#include "tsmtypes.h"
#include "tsmee.h"

// Set the __CONFIG word:
Uint16 at 0x2007  __CONFIG = CONFIG_WORD;

/**
 * Note we use the fact that a-z and A-Z are contiguous in ASCII
 * to save a lot of EEPROM space.  Converting to a foreign character
 * set may involve putting that section into code space and refactoring
 * a bit.
 */

/**
 * This should be a [12][4] array, or even a struct, but sdcc produces
 * many times more code for multidimensional arrays than single ones.
 *
 * It's an array of key codes vs output codes for function keys f1-f12,
 * sorted by keycode to make it more efficient.
 */
static const Uint8 fkeys[12*4]={
/*f9*/	0x01,	0x32,	0x30,	0x7e,
/*f5*/	0x03,	0x5b,	0x45,	0x00,
/*f3*/	0x04,	0x5b,	0x43,	0x00,
/*f1*/	0x05,	0x5b,	0x41,	0x00,
/*f2*/	0x06,	0x5b,	0x42,	0x00,
/*f12*/	0x07,	0x32,	0x34,	0x7e,
/*f10*/	0x09,	0x32,	0x31,	0x7e,
/*f8*/	0x0a,	0x31,	0x39,	0x7e,
/*f6*/	0x0b,	0x31,	0x37,	0x7e,
/*f4*/	0x0c,	0x5b,	0x44,	0x00,
/*f11*/	0x78,	0x32,	0x33,	0x7e,
/*f7*/	0x83,	0x31,	0x38,	0x7e,	};

/* ASCII letters from a to z, in order, 
   make is ascii[n], break is 0xf0 ascii[n] */
const Uint8 at PIC14_EEPROM ascii[26]={
		0x1c,	0x32,	0x21,	0x23,
		0x24,	0x2b,	0x34,	0x33,
		0x43,	0x3b,	0x42,	0x4b,
		0x3a,	0x31,	0x44,	0x4d,
		0x15,	0x2d,	0x1b,	0x2c,
		0x3c,	0x2a,	0x1d,	0x22,
		0x35,	0x1a			};

#define ASCII_BEGIN	0
#define ASCII_END	(sizeof(ascii)+ASCII_BEGIN)

/**
 * Keys that SHIFT doesn't modify.  Like ENTER and so forth.
 * Note that this array is sorted by key code and must remain so!
 */
const Uint8 at PIC14_EEPROM+ASCII_END noshift[]={
		/* Tab key */
		0x0d, '\t',
		/* Space bar */
		0x29, ' ',
		/* Enter Key */
		0x5a, '\n',
		/* Backspace */
		0x66, '\b',
		/* Escape key */
		0x76, '\x1b',
		/* Keypad plus */
		0x79, '+',
		/* Keypad minus */
		0x7b, '-',
		/* Keypad asterisk */
		0x7c, '*',
	};

#define NOSHIFT_BEGIN	(ASCII_END)
#define NOSHIFT_END	(ASCII_END+sizeof(noshift))

/* keys with two meanings defined by shift keys.
   Sorted by keycode!  yes, 4 and 3 are swapped! */
const Uint8 at PIC14_EEPROM+NOSHIFT_END shift[]={
		0x0e, '`', '~',
		0x16, '1', '!',
		0x1e, '2', '@',
		0x25, '4', '$',
		0x26, '3', '#',
		0x2e, '5', '%',
		0x36, '6', '^',
		0x3d, '7', '&',
		0x3e, '8', '*',
		0x41, ',', '<',
		0x45, '0', ')',
		0x46, '9', '(',
		0x49, '.', '>',
		0x4a, '/', '?',
		0x4c, ';', ':',
		0x4e, '-', '_',
		0x52, '\'', '"',
		0x54, '[', '{',
		0x55, '=', '+',
		0x5b, ']', '}',
		0x5d, '\\', '|',
	};
#define SHIFT_BEGIN NOSHIFT_END
#define SHIFT_END	(SHIFT_BEGIN+sizeof(shift))

/**
 * Numpad keycodes in order 0 through 9, for lookup when numlock is on.
 */
const Uint8 at PIC14_EEPROM+SHIFT_END numpad[]={
	0x70, 0x69, 0x72, 0x7a, 0x6b,
	0x73, 0x74, 0x6c, 0x75, 0x7d};
#define NUMPAD_BEGIN	SHIFT_END
#define NUMPAD_END	(SHIFT_END+sizeof(numpad))

const Uint8 at PIC14_EEPROM+NUMPAD_END arrows[]={
	// Up
	0x75,
	// Down
	0x72,
	// Right
	0x74,
	// Left
	0x6b	};
#define ARROW_BEGIN	NUMPAD_END
#define ARROW_END	(ARROW_BEGIN+sizeof(arrows))

const Uint8 at PIC14_EEPROM+ARROW_END fnctn[]={
	// home
	0x6c,
	// insert
	0x70,
	// del
	0x71,
	// end
	0x69,
	// pgup
	0x7d,
	// pgdn
	0x7a
	};
#define FNCTN_BEGIN	ARROW_END
#define FNCTN_END	(ARROW_END+sizeof(fnctn))


// If KHZ is not specified by the makefile, assume it to be 4 MHZ
#ifndef KHZ
#define KHZ	4000
#endif

// RX_PORT, TX_PORT are fixed.  The 16f628a can use only these pins as RS232.
enum
{
	// PS2 clock attached to B0
	CLK_PORT=0,
	// RS232 receive hardwired to B1
	RX_PORT=1,
	// RS232 send hardwired to B2
	TX_PORT=2,
	// PS2 data attached to B3
	DAT_PORT=3,
	// LED attached to B5
	FIN_PORT=5,

	CLK_BIT=(1<<CLK_PORT),
	TX_BIT=(1<<TX_PORT),
	RX_BIT=(1<<RX_PORT),
	DAT_BIT=(1<<DAT_PORT),
	FIN_BIT=(1<<FIN_PORT)
};

// Twiddle these as you like BUT remember that not all values work right!
// See the datasheet for what values can work with what clock frequencies.
#define	BAUD	9600
#define BAUD_HI	1

// This section calculates the proper value for SPBRG from the given
// values of BAUD and BAUD_HI.  Derived from Microchip's datasheet.
#if	(BAUD_HI == 1)
#define	BAUD_FACTOR	(16L*BAUD)
#else
#define	BAUD_FACTOR	(64L*BAUD)
#endif
#define SPBRG_VALUE	(unsigned char)(((KHZ*1000L)-BAUD_FACTOR)/BAUD_FACTOR)

// Lookup table for hex-to-ascii and BCD-to-ascii macro
static const char hex[]={'0','1','2','3','4','5','6','7','8','9',
			'A','B','C','D','E','F'};

// Wait until the PIC is finished transmitting over RS232
#define FLUSH()		while(!TXIF)

// Sends a literal character down the RS232 pipe.  I.E.  SEND('Q');
#define SEND(C)		do {	FLUSH();	TXREG=C;	} while(0)

// Sends two hex chars.  I.E.  SENDHEX(0xab) will send 'A', then 'B'
#define SENDHEX(H)	do {	SEND(hex[(H)>>4]);		\
				SEND(hex[(H)&0x0f]); } while(0)

enum
{
	// Does not pull clock or data low.
	PS2_IDLE=(TX_BIT|RX_BIT|CLK_BIT|DAT_BIT),
	// Pulls clock low.
	PS2_ASSERT=(TX_BIT|RX_BIT|DAT_BIT),
	// Pulls data low.
	PS2_ZERO=(TX_BIT|RX_BIT|CLK_BIT),
	// Pulls clock low
	PS2_INHIBIT=(TX_BIT|RX_BIT|CLK_BIT)
};

// Wait for high-to-low transition on clock.
#define PS2_WAITLO()	while(PORTB&CLK_BIT)
// Wait for low-to-high transition on clock.
#define PS2_WAITHI()	while(!(PORTB&CLK_BIT))
// Wait for data to go low
#define PS2_WAITDAT()	while(PORTB&DAT_BIT)

// 0-25 send ctrl-A through ctrl-Z
#define SEND_CTRLCHAR(N)	SEND((N)+1)

/*	Measured these from my own PS/2 numeric keypad.
 *	Key		Press	Release
 *	===============================
 *	7/home		6c	F0,6c
 *	8		75	F0,75
 *	9/pgup		7d	F0,7d
 *	4		6b	f0,6b
 *	5		73	f0,73
 *	6		74	f0,74
 *	1		69	f0,69
 *	2		72	f0,72
 *	3		7a	f0,7a
 *	0		70	f0,70
 *	DEL		71	f0,71
 *	ENTER		E0,5A	E0,F0,5A
 *	ESC		76	f0,76
 *	+		79	F0,79
 *	-		7B	F0,7b
 *	*		7c	f0,7c
 *	/		E0,4A	E0,F0,4A
 */

// When we read a bytecode from the keyboard it ends up in here.
static unsigned char ps2=0;
void ps2_sendchar(unsigned char c);
void ps2_getchar(void);

/* what bits in the mod variable have what meanings. */
enum
{
	BIT_MOD_LALT=0x00,
	BIT_MOD_RALT=0x01,
	BIT_MOD_LCTRL=0x02,
	BIT_MOD_RCTRL=0x03,
	BIT_MOD_RSHIFT=0x04,
	BIT_MOD_LSHIFT=0x05,
	BIT_MOD_E0=0x06,
	BIT_MOD_KEYUP=0x07,
};

/* what bits in the special variable have what meanings. */
enum
{
	BIT_SPECIAL_E0_12=0x08,
	BIT_SPECIAL_SCROLL=0x19,
	BIT_SPECIAL_NUMLOCK=0x1a,
	BIT_SPECIAL_CAPS=0x1b,
	BIT_SPECIAL_LMETA=0x0c,
	BIT_SPECIAL_RMETA=0x0d,
	BIT_SPECIAL_MENU=0x0e,
	BIT_SPECIAL_E1=0x0f,
};

// BIT(0) is binary 0001, BIT(1) is binary 0010, BIT(2) is binary 0100, etc
#define BIT(N)	(1<<((N)&0x07))

/* Bitmasks for bits given above */
enum
{
	/* When releasing a key, a PS2 keyboard adds the byte F0. */
	MOD_KEYUP	=BIT(BIT_MOD_KEYUP),
	/**
	 * Certain keys are prefixed with the special code E0.
	 * In particular, left control and right control are identical
	 * except for which has E0 appended.
	 */
	MOD_E0		=BIT(BIT_MOD_E0),
	/* We want to track when shift keys are pressed and released. */
	MOD_LSHIFT	=BIT(BIT_MOD_LSHIFT),
	MOD_RSHIFT	=BIT(BIT_MOD_RSHIFT),
	/* Ditto for control keys. */
	MOD_LCTRL	=BIT(BIT_MOD_LCTRL),
	MOD_RCTRL	=BIT(BIT_MOD_RCTRL),
	/* Same for alt keys. */
	MOD_LALT	=BIT(BIT_MOD_LALT),
	MOD_RALT	=BIT(BIT_MOD_RALT),

	/* Signifies the odd E0-12 part of a PRINT SCREEN key has been
           received. */
	SPECIAL_E0_12		=BIT(BIT_SPECIAL_E0_12),
	SPECIAL_CAPS		=BIT(BIT_SPECIAL_CAPS),
	SPECIAL_NUMLOCK		=BIT(BIT_SPECIAL_NUMLOCK),
	SPECIAL_SCROLL		=BIT(BIT_SPECIAL_SCROLL),
	SPECIAL_LMETA		=BIT(BIT_SPECIAL_LMETA),
	SPECIAL_RMETA		=BIT(BIT_SPECIAL_RMETA),
	SPECIAL_MENU		=BIT(BIT_SPECIAL_MENU),
	SPECIAL_E1		=BIT(BIT_SPECIAL_E1),

	SPECIAL_LEDS		=(SPECIAL_CAPS	|
					SPECIAL_NUMLOCK	|
					SPECIAL_SCROLL),

	MOD_CTRL	=MOD_RCTRL|MOD_LCTRL,
	MOD_SHIFT	=MOD_RSHIFT|MOD_LSHIFT,
	MOD_ALT		=MOD_LALT|MOD_RALT,
	MOD_ANY		=MOD_CTRL|MOD_ALT,
	SPECIAL_META	=SPECIAL_LMETA|SPECIAL_RMETA,
};

/* software flow control.  We send xon/xoff for scroll lock. */
enum
{
	XON=0x10,
	XOFF=0x12
};

Uint8 find_x(unsigned char start, unsigned char end);
Uint8 find_x_sort(unsigned char start, unsigned char end, unsigned char step);

#define find_ascii()	find_x(ASCII_BEGIN, ASCII_END)
#define find_numpad()	find_x(NUMPAD_BEGIN, NUMPAD_END)
#define find_fnctn()	find_x(FNCTN_BEGIN, FNCTN_END)
#define find_arrow()	find_x(ARROW_BEGIN, ARROW_END)
#define find_shift()	find_x_sort(SHIFT_BEGIN, SHIFT_END, 3)
#define find_noshift()	find_x_sort(NOSHIFT_BEGIN, NOSHIFT_END, 2)
Uint8 find_fkey(void);

void main(void)
{
	static Uint8 mod, special;

	NOT_RBPU=0;	// Enable pullups

	TRISB=PS2_IDLE;		// Setup I/O on port B
	PORTB=0;

	SPBRG=SPBRG_VALUE;	// Baud Rate register, calculated by macro
	BRGH=BAUD_HI;

	SYNC=0;			// Disable Synchronous/Enable Asynchronous
	SPEN=1;			// Enable serial port
	TXEN=1;			// Enable transmission mode

	// Wait until the keyboard initializes
	while(ps2 != 0xAA)
		ps2_getchar();

	// Request an ACK.
	ps2_sendchar(0xEE);
	ps2_getchar();
	// If we get what we expected, light the debug light.
	if(ps2==0xEE)
		PORTB=FIN_BIT;

	mod=0;
	special=0;
	while(1)
	{
		static Uint8 n;

		ps2_getchar();

		/* pause is extremely "special" */
		if(special & SPECIAL_E1)
		{
			if(ps2 == 0xf0)	mod|=MOD_KEYUP;

			if((ps2 == 0x77) && (mod&MOD_KEYUP))
			{
				special &= ~SPECIAL_E1;
				mod &= MOD_KEYUP;

				if(PORTB & FIN_BIT)
					PORTB=0;
				else	PORTB=FIN_BIT;

				goto SKIP_KEYCODE;
			}
			continue;
		}

		n=0xff;
		switch(ps2)
		{
		case 0xf0:
			mod|=MOD_KEYUP;
			continue;
		case 0xe0:
			mod|=MOD_E0;
			continue;
		case 0xe1:
			special|=SPECIAL_E1;
			continue;
		case 0x11:
			n=BIT_MOD_LALT;
			break;
		case 0x14:
			n=BIT_MOD_LCTRL;
			break;
		case 0x12:
			/* print-screen is extremely "special" */
			if(mod&MOD_E0)
				goto SKIP_KEYCODE;

			n=BIT_MOD_LSHIFT;			
			break;
		case 0x59:
			n=BIT_MOD_RSHIFT;
			break;
		case 0x1f:
			n=BIT_SPECIAL_LMETA;
			break;
		case 0x27:
			n=BIT_SPECIAL_RMETA;
			break;
		case 0x77:
			n=BIT_SPECIAL_NUMLOCK;
			break;
		case 0x58:
			n=BIT_SPECIAL_CAPS;
			break;
		case 0x7e:
			n=BIT_SPECIAL_SCROLL;
			break;

		/* Print Screen is very "special" */
		case 0x7c:
			if((special&SPECIAL_E0_12) &&
				(mod&MOD_E0))
			{
				if(!(mod&MOD_KEYUP))
				{
					if(PORTB&FIN_BIT)
						PORTB=0;
					else	PORTB=FIN_BIT;
				}
//				SEND('#');
				goto SKIP_KEYCODE;
			}
			break;

		/* SysRQ key is alt-printscreen.  It isn't supposed
			to produce a keycode but do something to
			hardware.  so we toggle FIN_BIT. */
		case 0x84:
			if(mod&MOD_KEYUP)
				PORTB=FIN_BIT;
			else	PORTB=0x00;
			goto SKIP_KEYCODE;

		default:
			break;
		}

		if(n != 0xff)
		{
			Uint8 q=1<<(n&0x07);
			/* variables in 'special' */
			if(n&0x08)
			{
				if(n&0x10)
				{
					if(!(mod&MOD_KEYUP))
					{
						special^=q;
						if(n == BIT_SPECIAL_SCROLL)
						{
							if(special&SPECIAL_SCROLL)
								SEND(XOFF);
							else
								SEND(XON);
						}
						// Reset leds
						ps2_sendchar(0xED);
						n=special&SPECIAL_LEDS;
						n>>=1;
						ps2_sendchar(n);
						ps2_getchar();
						if(ps2 != 0xfa)
							PORTB=0;
					}
				}
				else if(mod&MOD_KEYUP)
					special&=~q;
				else	special|=q;
			}
			else
			{
				if(mod&MOD_E0)
					q<<=1;

//				SEND('@');
//				SENDHEX(q);

				if(mod&MOD_KEYUP)
					mod&=~q;
				else	mod|=q;
			}

			goto SKIP_KEYCODE;
		}

		if(mod&MOD_KEYUP)
			goto SKIP_KEYCODE;

		if((special&SPECIAL_NUMLOCK) &&
			((n=find_numpad())<NUMPAD_END))
		{
			n-=NUMPAD_BEGIN;
			n=hex[n];
		}
		else if((n=find_ascii()) < ASCII_END)
		{
			n=n+'a';

			if(mod&MOD_ANY)
			{
				n&=~0x20;
				if(mod&MOD_CTRL)	n&=~0x40;
				if(mod&MOD_ALT)		n|= 0x80;
			}
			else
			{
				if(mod&MOD_SHIFT)
					n ^= 0x20;
				if(special&SPECIAL_CAPS)
					n ^= 0x20;
			}
		}
		else if((n=find_noshift()) < NOSHIFT_END)
		{
			n++;
			n=EEPROM_READ_ADDRESS(n);
			if(EEDATA == (Uint8)'\n')
				SEND('\r');
		}
		else if((n=find_shift()) < SHIFT_END)
		{
			n++;
			if(mod & MOD_SHIFT)	n++;
			n=EEPROM_READ_ADDRESS(n);
			if(mod & MOD_CTRL)	n &= ~0x40;
			if(mod & MOD_ALT)	n |=  0x80;
		}
		else if((n=find_fnctn()) < FNCTN_END)
		{
			n -= FNCTN_BEGIN;
			/**
			 * if ps2 == fnctn[n], then output
			 * '\x1b', '[', 0x31+n, '\x7e'
			 */
			SEND('\x1b');
			SEND('[');
			SEND('1'+n);
			SEND('\x7e');
			goto SKIP_KEYCODE;
		}
		else if((n=find_arrow()) < ARROW_END)
		{
			n-=ARROW_BEGIN;
		/* If ps2 == arrows[n], then output '\x1b', '[', 0x41+n	 */
			SEND('\x1b');
			SEND('[');
			SEND(n + 0x41);
			goto SKIP_KEYCODE;
		}
		else if((n=find_fkey()) < (12*4))
		{
			SEND('\x1b');
			SEND('\x5b');
			if(fkeys[++n])	SEND(fkeys[n]);
			if(fkeys[++n])	SEND(fkeys[n]);
			if(fkeys[++n])	SEND(fkeys[n]);
			goto SKIP_KEYCODE;
		}
		else
		{
			SEND('!');
			SENDHEX(ps2);
			SEND(' ');
			goto SKIP_KEYCODE;
		}

		SEND(n);

SKIP_KEYCODE:
		if((mod&MOD_KEYUP)&&(ps2 == 0x12)&&(special&SPECIAL_E0_12))
		{
			special&=~SPECIAL_E0_12;
		}
		else if((mod&MOD_E0) && (ps2 == 0x12))
			special|=SPECIAL_E0_12;

		/**
		 * These two flags aren't persistent.  We clear them
		 * every time we're ready for a new keycode.
                 */
		mod &= ~(MOD_E0|MOD_KEYUP);
	}
}

/**
 * Note that we're doing funny things with TRISB for the keyboard data
 * and clock here.  PORTB pullups MUST be enabled for this to work.
 * The relevant PORTB bits must always be set to zero!
 *
 * To signify a 1, we just set the line as an input and let the pullups 
 * pullup.
 *
 * To signify a 0, we set the line as an output and let it overpower the
 * pullup.
 *
 * This way, we need never touch PORTB itself and only alter the TRISB 
 * register.
 *
 * It overwrites TRISB entirely, so if you need other bits of TRISB 
 * always set as what you want, be sure to add the relevant bits to the
 * PS2_* macros.
 */
void ps2_sendchar(Uint8 c)
{
	static Uint8 i, p;
	p=0;

	TRISB=PS2_ASSERT;
	for(i=0; i<15; i++);	// This loop for 4MHZ, scale accordingly
	TRISB=PS2_ZERO;

	for(i=0; i<8; i++)
	{
		PS2_WAITLO();
		if(c & 0x01)
		{
			p++;
			TRISB=PS2_IDLE;
		}
		else
			TRISB=PS2_ZERO;

		c>>=1;
		PS2_WAITHI();
	}

	PS2_WAITLO();
	if(p&1)	TRISB=PS2_ZERO;
	else	TRISB=PS2_IDLE;
	PS2_WAITHI();

	PS2_WAITLO();
	TRISB=PS2_IDLE;
	PS2_WAITHI();

	while(PORTB&DAT_BIT);
	while(PORTB&CLK_BIT);

	while(!(PORTB&DAT_BIT));
	while(!(PORTB&CLK_BIT));
}

void ps2_getchar(void)
{
	static Uint8 i;

	TRISB=PS2_IDLE;

	// Start bit
	PS2_WAITLO();
	PS2_WAITHI();

	// D0-D8
	for(i=0; i<8; i++)
	{
		ps2>>=1;
		PS2_WAITLO();
		if(PORTB&DAT_BIT)	ps2|=0x80;
		PS2_WAITHI();
	}

	// Parity bit
	PS2_WAITLO();
	PS2_WAITHI();

	//Stop bit
	PS2_WAITLO();
	if(!(PORTB&DAT_BIT))
		return;

	PS2_WAITHI();
//	SENDHEX(ps2);
}

Uint8 find_x(unsigned char start, unsigned char end)
{
	while(start < end)
	{
		if(EEPROM_READ_ADDRESS(start) == ps2)
			break;

		start ++;
	}

	return(start);
}

Uint8 find_x_sort(unsigned char start, unsigned char end, unsigned char step)
{
	while(start < end)
	{
		if(EEPROM_READ_ADDRESS(start) == ps2)
			break;

		if(ps2 < EEDATA)
			start=end;
		else	start += step;
	}

	return(start);
}

Uint8 find_fkey(void)
{
	Uint8 n;
	for(n=0; n<(12*4); n+=4)
	{
		if(fkeys[n] == ps2)
			break;

		if(fkeys[n] > ps2)
			n=12*4;
	}

	return(n);
}
