PS/2 Keyboard Interface

Program Download:

Main C File
PIC_PS2_Interface.c
PIC_PS2_Interface.hex

The Software
           There are two main portions of code that we are concerned with:
    -Main Loop
    -Capture Interrupt Routine



           The main loop will have the job of running through the buffer of input commands and executing them to the 7-segment led. The code below is a little abridged, but you can get the general idea of what is going on.

Main Loop

------------« Begin Code »------------
#include <p18f452.h>
#include <cature.h>
#include <timers.h>
#include <delays.h>
//7-Segment Display Output
#define number_0 0b01111110
..
...
..
#define letter_a 0b11101110
#define letter_b 0b11111110
..
...
..
void main(void){
TRISC = 0xFF;
TRISD = 0x01;
PORTB = 0x00;
PORTC = 0x00;
     //7-Seg LED is Reverse Polarity
PORTD = 0x00 ^ 0xFF;
Delay10KTCYx(10);
INTCON = 0b11000000;
OpenCapture1( C1_EVERY_FALL_EDGE & CAPTURE_INT_ON );
OpenTimer1( TIMER_INT_ON & T1_SOURCE_INT & T1_PS_1_1 & T1_16BIT_RW );
WriteTimer1( 0x0000 );
while(1)
{
     if(buf_ready == 1){
     switch(scan_code_buf[0]){
     case 0x1C : PORTD = (letter_a ^ 0xFF);
          break;
     ...
     ....
     ..
          break;
     case 0x45 : PORTD = (number_0 ^ 0xFF);
          break;
     case 0x66 : PORTD = (delete ^ 0xFF);
          break;
     default :
          break;
     }
     //Shift Buffer Forward
     scan_code_buf[0] = scan_code_buf[1];
     scan_code_buf[1] = scan_code_buf[2];
     scan_code_buf[2] = scan_code_buf[3];
     scan_code_buf[3] = scan_code_buf[4];
     scan_code_buf[4] = scan_code_buf[5];
     scan_code_buf[5] = scan_code_buf[6];
     scan_code_buf[6] = scan_code_buf[7];
     scan_code_buf_cnt--;

          if(scan_code_buf_cnt == 0)
               buf_ready = 0;
     }
          Delay10KTCYx(1);
}
}
------------« End Code »------------

           So the main loop's purpose is to parse the incoming data that is inside of a fifo buffer. The code below is the interrupt service routine which receives the PS/2 data and puts it into that FIFO buffer. The Keypress release 0xF0 is ignored, only keyboard scan code are given any priority.

Two Interrupt Service Routines

------------« Begin Code »------------
void InterruptHandlerHigh(void) // Declaration of InterruptHandler
          //Check If TMR1 Interrupt Flag Is Set
     if(PIR1bits.CCP1IF){
         if(bit_counter < 10){
               current_scan_code = current_scan_code >> 1;
               current_scan_code += (PORTDbits.RD0*0b10000000000);
               bit_counter++;
          }
          else if(bit_counter == 10){
scan_code_buf[scan_code_buf_cnt]=(current_scan_code>>2)&0xFF;
               scan_code_buf_cnt++;
               buf_ready = 1;
               bit_counter = 0;
          }
          WriteTimer1( 0x0000 );
          //Clear CCP1 Overflow Flag Bit
          PIR1bits.CCP1IF = 0;
     }
          //Check If CCP1 Interrupt Flag Is Set
     else if(PIR1bits.TMR1IF){
          //Clear Timer1 Overflow Flag Bit
          bit_counter = 0;
          PIR1bits.TMR1IF = 0;
     }
     INTCONbits.GIE = 1;
}
------------« End Code »------------

           As you can see above, the Capture module interrupt and timer1 are used together to make sure that we only catch the 8 data bits and not the start, stop or parity bits. I'm sure a better parsing routine could be created, but for now, the one above works just fine.



;