The code is too long to include everything on this page, so I'll just cover the two important specifics:
-Main Scan Code Look-up
-Capture Interrupt Routine
The main program loop is used to decode the scan-code and print the appropriate key. An excerpt of the switch statement that does this can be seen below.
Main Loop
------------« Begin Code »------------
#include <p18f452.h>
#include <cature.h>
#include <timers.h>
#include <delays.h>
..
...
..
void main(void){
TRISA = 0x00;
TRISB = 0x00;
TRISC = 0xFF;
TRISD = 0x01;
PORTA = 0x00;
PORTB = 0x00;
PORTC = 0x00;
PORTD = 0x00;
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 : prnt('a');
break;
...
....
..
break;
case 0x45 : prnt('0');
break;
case 0x66 : commd(0b00010000);
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 »------------
Basically, the switch statement pulls from the scan code FIFO and checks if it matches any codes in the switch-statement look up table. If it does some output occurs, whether it is a letter/number print or a delete function. Below is the capture routine for understanding the PS/2 clock and data inputs. The capture function catches PS/2 data until a full PS/2 communication completes, then it throws the data into a FIFO buffer for the main loop to evaluate.
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.