/* Number of bits in a PS2 data packet (Start + 8 bits + Odd parity + Stop) */
#define PS2DATASIZE     11

// bit locations are down-count zero justified
#define PS2BIT_PARITY      1
#define PS2BIT_START       10
#define PS2BIT_LSB         9
#define PS2BIT_STOP        0

/* Special scan codes */
#define LSHIFT          0x12   /* Left-shift on PS2 keyboard */
#define RSHIFT          0x59   /* Right-shift on PS2 keyboard */
#define KEYRELEASE      0xF0   /* Preceeds key code when key released */
#define EXTENDED        0xE0   /* Used for numeric keypad & arrow keys */
#define CAPSLOCK        0x58   /* Caps Lock key code */


/* Static local variables */
static volatile _data unsigned char bc_char;      /* Scan code created by ISR */
static volatile _data unsigned char bc_char_temp; /* Scan code created by ISR */
static volatile _data unsigned char bc_bit_count; /* Bit counter for ISR */

static _bit BC_CHAR_RCVD;         /* Set when character has been received */
static _bit BC_SHIFT;             /* Set when shift key active */
static _bit BC_KEY_RELEASE;       /* Set when release code 0xF0 received */
static _bit BC_DATA_TEMP;         /* Temporary storage of incoming data bit */
static _bit BC_PARITY;            /* cumulative XOR of incoming bits until parity bit is reached, then 1|0 for good|bad parity */
static _bit reset_ch;             // set if start,parity,stop bits are incorrect 

unsigned char getbcch (void) // (unsigned char pos)
{

  register unsigned char rx_char;

  /* Initially assume that nothing has been received from scanner yet */
  rx_char = 0;

	// while(rx_char != 'r' && pos < TEXT_BUF_LENGTH)
	// {
		if (BC_CHAR_RCVD)
		{

			/* A PS2 byte has been received: process it */

			switch (bc_char)
			{
				case KEYRELEASE:
					/* Flag a key release event */
					BC_KEY_RELEASE = TRUE;
					break;

				case EXTENDED:
					/* The "extended" code has no meaning here, so ignore it */
					break;

				case LSHIFT:
				case RSHIFT:
					/* If the previous byte was a key release, then revert */
					/* back to lower case. Otherwise, flag a shift event.  */
					if (BC_KEY_RELEASE)
					{
						BC_SHIFT = FALSE;
						BC_KEY_RELEASE = FALSE;
					}
					else
					{
						BC_SHIFT = TRUE;
					}
					break;

				default:
					/* Any other code with bit 7 set is ignored ! */
					if (!(bc_char & 0x80))
					{
						/* If this follows a key release event, just clear */
						/* the key release flag */
						if (BC_KEY_RELEASE)
							BC_KEY_RELEASE = FALSE;
						else
						{
							/* Otherwise get the ASCII character from the lookup table. */
							/* NOTE: Illegal codes return NULL from the lookup process. */
							if (BC_SHIFT)
								rx_char = scan2ascii_shifted[bc_char];
							else
								rx_char = scan2ascii[bc_char];

							/* if(rx_char)
							{	
								// put_ch(0,pos,rx_char);
								text_buffer[pos++] = rx_char;
                msec_delay(2);
								// put_ch(1,pos,text_buffer[pos]);
                // pos++; */
							// }
						}
					}
					break;
			}

      // if (text_buffer[pos-1] == 'r')
        // text_buffer[pos-1]=' '; 

			/* Reset the bit counter in preparation for the next PS2 byte */
			bc_bit_count = PS2DATASIZE;
			BC_CHAR_RCVD = FALSE;
			BC_PARITY = FALSE;
			reset_ch = FALSE;

			EX1 = TRUE;     /* Enable EX1 interrupts again */
			PS2DAT = TRUE;
			PS2CLK = TRUE;  /* Unlock the scanner so that it can get more */
		}
	// }
  return (rx_char);

}

_interrupt(2) void ps2ck_interrupt (void)
{

   /* Shift in the data bit from PS2DAT */
#pragma asm
   PS2DATA equ P3.4
   mov  c,PS2DATA
   mov  _BC_DATA_TEMP,c
#pragma endasm

   switch (--bc_bit_count)
   {
     case PS2BIT_START:

       /* ps2 start bit should be LOW 
        * if its not reset PS2CLK to force a resend
        */
       if (BC_DATA_TEMP)
         reset_ch = TRUE;

       break;

     case PS2BIT_PARITY:

       /* PS2 calls for odd parity, so inverse of bitwise XOR
        * that has been built up in BC_PARITY should be the same
        * as the parity bit */
       if ( ~BC_PARITY != BC_DATA_TEMP )
         reset_ch = TRUE;

       break;

     case PS2BIT_STOP:

       /* Lock the scanner so that it doesn't send anything else */
       PS2CLK = 0;

       /* lastly check that the stop bit is high */
       if (!BC_DATA_TEMP)
       {
         reset_ch = TRUE;
       }
       else
       {
         /* Save the byte received */
         bc_char = bc_char_temp;

         /* Flag 'getbcch()' that there is a byte ready to be processed */
         BC_CHAR_RCVD = TRUE;

       }
       return;

     default:
       /* Not a start or parity bit, so shift in the data bit */

       /* the lsb of the data is assigned to parity, subseqeunt
        * bits are xor'd. later the inverse of BC_PARITY is 
        * compared to the parity bit of the PS2 packet */
       if (bc_bit_count == PS2BIT_LSB)
         BC_PARITY = BC_DATA_TEMP;
       else
         BC_PARITY ^= BC_DATA_TEMP;

#pragma asm
       mov     a,_bc_char_temp
         mov     c,_BC_DATA_TEMP
         rrc     a
         mov     _bc_char_temp,a
#pragma endasm

         break;
   }

   /* any data frame errors we reset the reception parameters */
   if(reset_ch)
   {
     /* ensure PS2DAT is high else the bc may be thinking a host
      * command is coming */
     PS2DAT = 1;
     PS2CLK = 0;    // pull low for at least 100us
     bc_bit_count = PS2DATASIZE;
     bc_char_temp = 0;
     BC_CHAR_RCVD = FALSE;
     BC_SHIFT = FALSE;
     BC_DATA_TEMP = 0;

     reset_ch = FALSE;
    
     /* put line high again to force a resend */
     PS2CLK = 1;

		 // clear the false interrupt made by messing with PS2CLK 
		 IE1 = 0;

   }

}
