CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

PS/2 keyboard driver/decoder, interrupt driven, 16F and up

 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
stevenm86



Joined: 11 Jun 2006
Posts: 11

View user's profile Send private message

PS/2 keyboard driver/decoder, interrupt driven, 16F and up
PostPosted: Sat Jul 08, 2006 8:03 pm     Reply with quote

Hello.

I have written a nice PS/2 keyboard driver for the PIC. This reads data from a PS/2 keyboard, decodes it, and makes it available to whatever needs it. It decodes the scancodes, tracks shift and caps lock keys, and outputs pure ASCII of what is typed. The whole thing is interrupt driven so the program does not need to spend time waiting for keyboard input to happen while doing other things. Keys are read into a 16 byte circular buffer in memory which can be accessed with several simple functions.

The sendByte function was used to set the LED status on the keyboard (for caps lock) but it is currently turned off because it only worked with some of my keyboard. Some sort of timing issue? I don't know.. Whatever.

There are two pins you want from the keyboard- Clock and Data, and these are set with simple Defines. Data can be reassigned to anything, but Clock needs to be set to the External interrupt pin, which is usually B0. I know pic18 has multiple external interrupts, so you can use any one of those, assuming you also set the interrupt handler function to work on that interrupt.

The RS232 in the program is simply my debug console. You can get rid of it (as well as any printfs) if you wish.

The driver supports most basic input keys such as A-Z, 0-9, Space, and all punctuation marks. I think Escape and Backspace are also tracked. It is possible to add support for other keys pretty easily, you just need the scan code of the key. The scan code map is coded a bit weirdly, but this is mainly to make the code and tables as small as possible. Look at translate(), you will figure it out.

Functions you'll want to use-

keyhit() - tells you if there are any bytes in the buffer.
waitKey() - returns the next character in the buffer. If there is no data in the buffer, this will keep on waiting and will return whenever the next key is pressed. Shift and Caps Lock do not count, they are not considered keys that produce characters.

Again, you get back the full ASCII value of what was typed. Pressing A returns 'a', Pressing Shift+A returns 'A', pressing Capslock, Shift+A returns 'a', just like on a computer. Pressing Shift+1 returns '!'.

The program uses interrupts to read the keyboard, so as soona s a key is pressed, your code will pause running while the keyboard driver reads the incoming data. Normally this is not a problem, but if something is typed in the middle of a serial transmission, that transmission may be garbled. To fix this, simply disable interrupts during any operation that you do not want interrupted, and re-enable them after. Turning off interrupts disables the kebyoard driver, so any keys typed when they are disabled will not be processed.

I probably will not maintain this anymore, it worked well enough for me.. there may be occasional bugs, but you can fix them easily enough, and this thing works well enough anyway.


Here is the code, I hope you like it.
Steve




Code:

#include <16f877a>
#fuses HS,NOWDT,NOPROTECT,NOLVP,NOBROWNOUT,NOPUT
#use delay(clock=4096000)
#use RS232(Baud=2400,Xmit=PIN_D2,BITS=8,INVERT)

//D0 - Clock
//D1 - Data


// Clock must be the interrupt pin
#define CLOCK PIN_B0
#define DATA  PIN_D3

unsigned char bData[16];
unsigned char idx=0;
unsigned char tmp=0;

unsigned char readByte();
unsigned char processByte();
unsigned char waitKey();
byte keyhit();
unsigned char translate(unsigned char scancode);




volatile byte shiftSet = 0;

byte kbBuffer[16];
byte kbPos = 0;
byte kbSize = 0;
byte capsSet = 0;
volatile byte extFlag = 0;
volatile byte relFlag = 0;
volatile byte key=0;


void sendByte(byte b)
{
    byte a=0;
    byte p = 1;
    byte t = 0;

    return;         // THIS IS NOT FULLY WORKING ON ALL KEYBOARDS
                    // SO IT IS COMMENTED OUT
                    // Some kind of timing issue or something. Whatever, they're just LEDs



    disable_interrupts(GLOBAL);
    output_low(CLOCK);
    delay_us(300);
    output_low(DATA);
    input(CLOCK);

    for(a=0; a<8; a++)
    {
        t = b&(1<<a);
        while(input(CLOCK) == 1); //wait for 0
        output_bit(DATA, t);
        if(t)
            p++;
        while(input(CLOCK) == 0); //wait for 1
    }

    while(input(CLOCK) == 1); //wait for 0
    output_bit(DATA, p&0x01);
    while(input(CLOCK) == 0); //wait for 1

    input(DATA);
    while(input(DATA) == 1); //wait for 0
    while(input(CLOCK) == 1); //wait for 0

    delay_ms(10);

    clear_interrupt(INT_EXT);
    enable_interrupts(GLOBAL);
}

main()
{
    int i=0;
    unsigned char k=0;
    printf("READY >");

    output_b(0x00);
    input(CLOCK);

    delay_ms(100);

    ext_int_edge(H_to_L);
    enable_interrupts(INT_EXT);
    enable_interrupts(GLOBAL);

    while(1)
    {
        k = waitKey();
        printf("%c", k);

        while(keyhit())
            printf("%c", waitKey());
    }
}

byte keyhit()
{
    return kbSize != 0;
}

unsigned char waitKey()
{
    unsigned char k = 0;
    while(kbSize == 0);
    k = kbBuffer[(kbPos - kbSize)&0x0F];
    kbSize--;
    return k;
}

#int_ext
void kbInterrupt()
{
    volatile byte k=0;
    k = processByte();

    if(k != 0)
    {
        kbBuffer[kbPos] = k;
        kbPos = ++kbPos & 0x0F;
        kbSize++;
    }
    return;
}

unsigned char readByte()
{
    int i=0, t=0;
    idx=0;
    tmp=0;

    i=0;
    goto dataread;
   // while(INPUT(CLOCK) != 0);   // Wait for a keypress
            t=0;
       while(INPUT(CLOCK) != 0 && t<255)   // Wait for clock, time out if needed
       {
           delay_us(1);
           t++;
       }
    for(i=0; i<11; i++)
    {
        t=0;
        while(INPUT(CLOCK) != 0 && t<255)   // Wait for clock, time out if needed
        {
            delay_us(1);
            t++;
        }
        dataread:

        bData[idx]=INPUT(DATA);
        idx++;
        if(idx==9)
        {
            for(idx=1; idx<9; idx++)
                if(bData[idx]!=0)
                    tmp|=(1<<(idx-1));

            return tmp;
            idx=0;
            tmp=0;
        }
     //   while(INPUT(CLOCK) == 0);
        t=0;
        while(INPUT(CLOCK) == 0 && t<255)   // Wait for clock, time out if needed
        {
            delay_us(1);
            t++;
        }

    }
}

static const unsigned char scantableAZ[]={
0x1C, 0x32, 0x21, 0x23, 0x24, 0x2B, 0x34, 0x33, 0x43, 0x3B, 0x42, 0x4B, 0x3A, // A-Z
0x31, 0x44, 0x4D, 0x15, 0x2D, 0x1B, 0x2C, 0x3C, 0x2A, 0x1D, 0x22, 0x35, 0x1A};


// Normal numeric scancodes, starting with ',' .
static const unsigned char scantable09n[]=
{
0x41, 0x4E, 0x49, 0x4A, // , - . /
0x45, 0x16, 0x1E, 0x26, 0x25, 0x2E, 0x36, 0x3D, 0x3E, 0x46,     //Digits 0-9
0x00, 0x4C, 0x00, 0x55 // 0 ; 0 =
};

// Shift scancodes, starting at '!'
static const unsigned char scantable09s[]=
{
    0x16, 0x52, 0x26, 0x25, 0x2E, 0x3D, 0x00, 0x46, 0x45, 0x3E, 0x55
};

// Normal misc. scancode map. Scancode, ASCII value
static const unsigned char scanmapn[]=
{0x54, '[', 0x5B, ']', 0x0E, '`', 0x5D, '\\', 0x52, '\''};

// Shifted misc. scancode map. Scancode, ASCII value
static const unsigned char scanmaps[]=
{0x1E, '@', 0x36, '^', 0x4E, '_', 0x54, '{', 0x5B, '}', 0x5D, '|',
0x4C, ':', 0x41, '<', 0x49, '>', 0x4A, '?', 0x0E, '~'};


// Scancode map independent of Shift
static const unsigned char scanmapx[]=
{0x29, ' ', 0x5A, '\r', 0x0D, '\t', 0x76, 27, 0x66, 0x08};

// Extended scancode map
static const unsigned char scanmape[]=
{
0x71, 0x7F
};

unsigned char translate(unsigned char scancode)
{
    int i=0;

    if(extFlag == 0)
    {
        for(i=0; i<10; i+=2)
            if(scanmapx[i] == scancode)
                return scanmapx[i+1];

        for(i=0; i<26; i++)
            if(scantableAZ[i] == scancode)
                if(shiftSet ^ capsSet)
                    return i+65;
                else
                    return i+65 + 32;

        if(shiftSet)
        {
            for(i=0; i<11; i++)
                if(scantable09s[i] == scancode)
                    return i+'!';

            for(i=0; i<22; i+=2)
                if(scanmaps[i] == scancode)
                    return scanmaps[i+1];
        } else
        {
            for(i=0; i<18; i++)
                if(scantable09n[i] == scancode)
                    return i+',';

            for(i=0; i<10; i+=2)
                if(scanmapn[i] == scancode)
                    return scanmapn[i+1];
        }
    } else      // Extended keys
    {
        for(i=0; i<2; i+=2)
            if(scanmape[i] == scancode)
                return scanmape[i+1];
    }
    return '?';
}

unsigned char processByte()
{
    unsigned char i, j;
    i = readByte();

    if(i == 0xF0)       //A key is being released
    {
        relFlag = 1;
        return 0;
    }

    if(i == 0xE0)       // Extended key operation
    {
        extFlag = 1;
        relFlag = 0;    //0xE0 always first in sequence, OK to clear this
        return 0;
    }

    if(relFlag == 0)    // Pressing a key
    {
        if(extFlag == 0)    // Non-extended key pressed
        {
            if(i == 0x12 || i == 0x59)
            {
                shiftSet = 1;
                return 0;
            }

            if(i == 0x58)
            {
                sendByte(0xED);
                if(capsSet == 0)
                {
                    capsSet = 1;
                    sendByte(0x04);
                } else
                {
                    capsSet = 0;
                    sendByte(0x00);
                }
                return 0;
            }


        }
        j = translate(i);
        extFlag = 0;
        return j;
    }

    if(relFlag == 1)    //Releasing a key
    {
        relFlag = 0;    //If a flag was set but not handled, we wouldn't have gotten here
        extFlag = 0;    //OK to clear this here

        if(extFlag == 0)   // Releasing a nonextended key
        {
            if(i == 0x12 || i == 0x59)
            {
                shiftSet = 0;
                return 0;
            }

        }
//        } else              // Releasing an extended key
//        {
//            return 0;
//        }

//        return 0;
    }
    return 0;
}
[/code]
tranhuyky



Joined: 25 Dec 2006
Posts: 4

View user's profile Send private message

Please help me, turn on Numlock led
PostPosted: Mon Dec 25, 2006 7:35 am     Reply with quote

I connect a PS/2 Keyboard (Mitsumi) with PIC 16F877A. I want to turn on Numlock led, but i can't. i try many way but now is not Ok. Anyone else did it, Would you please help me.
foodwatch



Joined: 18 Apr 2006
Posts: 66

View user's profile Send private message Yahoo Messenger

Keyboard program
PostPosted: Sun Jan 14, 2007 7:40 pm     Reply with quote

Steve,I tried your program on an 18f4550 and it works fine. In my project I need to read a stand alone numeric keypad. I am a C novice and am having trouble figuring out how to modify/add the scan table to allow numeric keypad scan codes. I dont need any of the codes for a full keyboard. Thanks
smtpl04



Joined: 19 Apr 2007
Posts: 1
Location: India

View user's profile Send private message Send e-mail

ps/2 keyboard driver
PostPosted: Thu Apr 19, 2007 7:30 am     Reply with quote

I have tried your code & its working best for keyboard to PIC transfer. But not for PIC to keyboard transfer. I have modified your void sendByte(byte b) code(given below) for PIC to keyboard transfer & its working ok. Try it in your project & reply me.
Also I need another code for PIC to PC communication through ps/2 port. Please help me for this.

Thanks,
Sardar Patil.

Code:

void sendByte(byte b)
{
    byte a=0;
    byte p = 0;
    boolean t = 0;

  //  return;         // THIS IS NOT FULLY WORKING ON ALL KEYBOARDS
                    // SO IT IS COMMENTED OUT
                    // Some kind of timing issue or something. Whatever, they're just LEDs

    disable_interrupts(GLOBAL);
    output_low(KEYCLK);
    delay_us(80);
  //  input(KEYCLK);
    output_low(KEYDATA);
    output_high(KEYCLK);
    input(KEYCLK);

    for(a=0; a<8; a++)
    {
        while(input(KEYCLK) == 1); //wait for 0
        t = bit_test(b,a);
        output_bit(KEYDATA, t);
        if(t)
            p++;
        while(input(KEYCLK) == 0); //wait for 1
    }

    while(input(KEYCLK) == 1); //wait for 0
    t = bit_test(p,0);
        t = ~t;
    while(input(KEYCLK) == 0); //wait for 1
     output_bit(KEYDATA, t);   // input(KEYDATA);
    while(input(KEYCLK) == 1); //wait for 0
  ///  while(input(KEYCLK) == 0); //wait for 1
     output_float(KEYDATA);
    enable_interrupts(GLOBAL);
}
[/quote]
_________________
sardar
3dfx



Joined: 24 Mar 2007
Posts: 6

View user's profile Send private message

PostPosted: Sat May 12, 2007 5:04 am     Reply with quote

i have tested this code but i couldnt get any response from keyboard.is there any thing wrong?
Celso Missias



Joined: 24 Oct 2007
Posts: 1

View user's profile Send private message

PostPosted: Wed Oct 24, 2007 6:40 am     Reply with quote

Hi Steve

Thanks for the code,

After each key pressed a '?' is sended via serial too after the letter pressed.
So, when I press 'a', I receive 'a?',
'b', 'b?' and so on...
Why it is happening?

Thanks
Dimlow



Joined: 24 Nov 2007
Posts: 9

View user's profile Send private message

Parity bit
PostPosted: Tue Sep 30, 2008 10:44 am     Reply with quote

I think the parity bit in the send byte is wrong. Your Sending and even parity, not and odd parity!!! Probably why it don't work on all keyboards
Code:
output_bit(DATA, p&0x01);


should read
Code:
output_bit(DATA, p&0x10);
abo_shreek11



Joined: 27 Sep 2008
Posts: 10

View user's profile Send private message Send e-mail

Re: Keyboard program
PostPosted: Thu Nov 27, 2008 8:48 am     Reply with quote

foodwatch wrote:
Steve,I tried your program on an 18f4550 and it works fine. In my project I need to read a stand alone numeric keypad. I am a C novice and am having trouble figuring out how to modify/add the scan table to allow numeric keypad scan codes. I dont need any of the codes for a full keyboard. Thanks


May you tell me how much resistance is the pull-up resistor you used ? I have 18f4550 too, and when I press a button on key board it shows with some "?" character on the lcd. I have a doubt in the pull-up resistor I am using.
ThePraiodanish



Joined: 06 Mar 2010
Posts: 3

View user's profile Send private message

PostPosted: Sat Mar 06, 2010 7:36 am     Reply with quote

Hi all,

you can get rid of the "?" after each key pressed by replacing the line
Code:
return '?';

with
Code:
return 0x00;

in the function unsigned char translate(unsigned char scancode).

Although the code works great for me I have one problem:
For debugging purposes I print the received scancode to the rs232 port within the interrupt routine, the reading and printing of the circular buffer is disabled.
However if I write
Code:

while(1)
    {
   
    //printKey();
   //for(i=0 ; i < 10000 ; i++);
   delay_ms(1);   
       
    }

in the main() - function the scancodes returned are garbage!
It seems as if the delay-routine wasn't interrupted by the interrupt properly.
At first I thought it's due to the time the delay needs to finish the statement which is in progress before jumping to the interrupt handler but I saw that the author runs this code at 4 MHz clock which means there are about 40 cycyles between each interrupt. I'm running the code at 11,0592 MHz (=110 cycles between each interrupt) so there should be plenty time for jumping to the interrupt handler. Any Ideas?
Thanks a lot,

Thomas
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Mar 07, 2010 1:53 am     Reply with quote

Ask your question in the General Discussion forum. You'll get far
better exposure there, and your problem is likely related to general
programming issues, and not specifically to this PS/2 driver.
guntor



Joined: 10 Aug 2010
Posts: 1

View user's profile Send private message

PS2 Keyboard emulator v.1.0.0 alpha
PostPosted: Tue Aug 10, 2010 3:27 pm     Reply with quote

Maybe someone need a PS2 Keyboard emulator

Code:

#include <12F675.h>   
                       
#fuses INTRC_IO,NOWDT,NOMCLR,NOPROTECT
#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_A0,rcv=PIN_A1,bits=8,STREAM=DEBUG)
#use rs232(baud=9600,parity=N,xmit=PIN_A3,rcv=PIN_A2,bits=8,STREAM=RFID)
                                                                                                                                                                                                 
//#define DEBUGLONG
//#define DEBUGSHORT

#define KEYCLK PIN_A5
#define KEYDATA  PIN_A4     

typedef unsigned char uchar;
typedef boolean bit;
/*
                                                  -----                                                                   
                                      [+5V] VDD -|1   8|- VSS [GND]
   [KEYCLK] (with Pullup) GP5/T1CKI/OSC1/CLKIN  -|2   7|- GP0/AN0/CIN+/ICSPDAT [XMIT DEBUG]                               
[KEYDATA] (with Pullup) GP4/AN3/T1G/OSC2/CLKOUT -|3   6|- GP1/AN1/CIN-/VREF/ICSPCLK [RCV DEBUG]
                                   GP3/MCLR/VPP -|4   5|- GP2/AN2/T0CKI/INT/COU
                                                  -----   
*/                                                                                                                       
       

// A-Z, völlig willkürliche anordnung...
// http://www.computer-engineering.org/ps2keyboard/scancodes2.html
// Für break Code: vorher 0xF0 senden, dann wieder Code
const uchar t_a_z[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};

// 0-9, völlig willkürliche anordnung...
const uchar t_0_9[26]={0x45,0x16,0x1E,0x26,0x25,0x2E,0x36,0x3D,0x3E,0x46};

// ASCII translatedtoScantable
uchar atrsc[2];
uchar lastbyte;   


void sendNibble(boolean t);
bit getNibble();
void sendByte(byte sendbyte);
uchar receiveByte();
void senduchar(uchar sendb) ;
void translateASCIItoScanTable(uchar ASCII,uchar extended);
void sendString(uchar* str);                                                       

           
 
// SetBit: Einzelnes Bit senden...
//
//  ....        .........        ........
//  |  |...,....|       |........|      |........
//      10 w 30    40
//
void sendBit(boolean t){
   delay_us(10);//15
   output_bit(KEYDATA,t);
   delay_us(30);    //20             
   output_low(KEYCLK);
   delay_us(40);        //40             
   output_high(KEYCLK);
}

// getBit: Einzelnes Bit empfangen...
// 
//  ....        .........        ........
//  |  |........|   ,   |........|      |........
//         40    15 r 20
bit getBit(){
   bit t;
   output_low(KEYCLK);
   delay_us(40);
   output_high(KEYCLK);
   delay_us(15);
   t=input(KEYDATA);
   delay_us(20);

   return t;                                               
}

void sendByte(byte sendbyte){
                        
   uchar i;
   byte parity = 0;                             
   bit t = 0;   
   // ausgangslage
   output_high(KEYCLK);
   output_low(KEYDATA);
   
   // Delay, falks mehrere Bytes hintereinander gesendet werden...
   delay_us(250);
   
   // startbit
   output_high(KEYCLK);
   sendBit(0);

   for(i=0;i<8;i++){
      t=bit_test(sendbyte,i);       
      if(t)parity++;                                                     
      sendBit(t);
   }
   
   // Parity Bit
   t=~bit_test(parity,0);
   sendBit(t);
   
   // Stop bit
   sendBit(0);                 
   
   lastbyte=sendbyte;
   
   input(KEYCLK);
   input(KEYDATA);
}

uchar receiveByte(){
   
   uchar empf;                                                                                                                                 
   uchar parity;
   uchar i;                                                                                                                                   
   bit t;
   bit stopbit;                                                                                                                   
   // ignore startbit???
   // Generate Clock and receive bits.. LSB first...
   for(i=7;i!=0;i--){
      t=getBit();
      if(t){
         parity++;
         empf|=t<<i;
      }
   }
   // parity bit...
   t=getBit();
   
   // stop bit...
   stopbit=getBit();
   if(stopbit!=1){     
      #ifdef  DEBUGLONG
         fprintf(DEBUG,"Falsches Stopbit");
      #endif
      #ifdef  DEBUGSHORT
         fprintf(DEBUG,"fsb");
      #endif               
   }           
                  
   // ACK senden...
   delay_us(10);
   output_low(KEYDATA);
   delay_us(25);
   output_low(KEYCLK);
   delay_us(40);
   output_high(KEYCLK);
                    
   if(t!=~bit_test(parity,0)){     
      #ifdef  DEBUGLONG
         fprintf(DEBUG,"Haha, partity falsch");
      #endif
      #ifdef  DEBUGSHORT
         fprintf(DEBUG,"fp");
      #endif               
   }               
   #ifdef  DEBUGLONG                   
      fprintf(DEBUG,"empfanges byte %x",empf);
   #endif
   #ifdef  DEBUGSHORT
      fprintf(DEBUG,"eb %x",empf);
   #endif                                         
   return empf;     
}                     

                                       
                                                                             
void senduchar(uchar sendb) {
   uchar empf;

   unsigned int16 breaker;                 
   
   disable_interrupts(GLOBAL);


//Summary: Bus States
//Data = high, Clock = high:  Idle state.
//Data = high, Clock = low:  Communication Inhibited.
//Data = low, Clock = high:  Host Request-to-Send
                         
   while(true){
      // Host will was...
      if(input(KEYCLK)==0 && input(KEYDATA)==1){
         #ifdef  DEBUGLONG
            fprintf(DEBUG,"dammed, not free");
         #endif
         #ifdef  DEBUGSHORT
            fprintf(DEBUG,"nf");
         #endif         
         // 50ms zeit, um Data low zu ziehen und Clock auf high
         // Dann dürfen wir Clock spielen und nibbles empfangen...
         breaker=0;while(input(KEYDATA)==1&&input(KEYCLK)==0&&breaker<0xFFFFF)breaker++; // Wait for 0
         breaker=0;while(input(KEYCLK)==0&&breaker<0xFFFFF)breaker++; // Wait for 0
         #ifdef  DEBUGLONG
            fprintf(DEBUG,"ready to receive");
         #endif
         #ifdef  DEBUGSHORT
            fprintf(DEBUG,"rr");
         #endif
         
         // receive Byte
         empf=receiveByte();
         
         #ifdef  DEBUGLONG
            fprintf(DEBUG,"empfanges byte %x",empf);
         #endif
         #ifdef  DEBUGSHORT             
            fprintf(DEBUG,"eb %x",empf);
         #endif
         
         // Reset Keyboard (Too fast, false parity etc...)
         if(empf==0xFF){
            // Acknowledge                       
            sendbyte(0xFA);
                                 
            // BAT erfolgreich...                                                                                 
            sendbyte(0xAA);
            
            #ifdef  DEBUGLONG
               fprintf(DEBUG,"Bytes sent.");
            #endif
            #ifdef  DEBUGSHORT
               fprintf(DEBUG,"bs");
            #endif
         
         // Resend last byte...
         }else if(empf==0xFE){
              sendbyte(lastbyte);
         }     

      // Wenn Frei (CLK = HIGH),
      // Schauen, ob nach 50us immer noch frei, dann frei zur verwendung...
      }else{                                                                             
         delay_us(50);
         if(input(KEYCLK)==1){
            break;
         }                                                               
      }
   }                                 
   #ifdef  DEBUGLONG
         fprintf(DEBUG,"yeah, free");
   #endif
   #ifdef  DEBUGSHORT
         fprintf(DEBUG,"f");
   #endif                 
   
   // Todo: special caracters   
   translateASCIItoScanTable(sendb,0x00);
   
   // Todo: uppercase
   if(atrsc[1]!=0x00){
       sendbyte(atrsc[1]);
   }
   // Send Make Key...
   sendbyte(atrsc[0]);
   
   // Ssend Break Key...
   sendbyte(0xF0);
   sendbyte(atrsc[0]);   
   
   if(atrsc[1]!=0x00){
      sendbyte(0xF0);                                             
      sendbyte(atrsc[1]); 
   }
   
   // Not too many keys per second
   delay_ms(20);
                                       
   enable_interrupts(GLOBAL);
}           

void translateASCIItoScanTable(uchar ASCII,uchar extended){
   if(ASCII>='A' && ASCII<='Z'){
      atrsc[0]=t_a_z[ASCII-'A'];
      atrsc[1]=0x12;
       
   }else if(ASCII>='a' && ASCII<='z'){
      atrsc[0]=t_a_z[ASCII-'a'];
      atrsc[1]=0x00;                                                     
        
   }else if(ASCII>='0' && ASCII<='9'){
      atrsc[0]=t_0_9[ASCII-'0'];
      atrsc[1]=0x00;
   
   // Rest of Translation Table
   // layout spefific!!
   // layout: http://upload.wikimedia.org/wikipedia/commons/2/22/KB_US-International.svg
   // http://www.computer-engineering.org/ps2keyboard/scancodes2.html
   }else if(ASCII>=' ' && ASCII<=' '){                                     
      //atrsc[0]=t_a_z[ASCII-'A'];                                                                                           
      atrsc[0]=0x29;               
      atrsc[1]=0x00;
                   
   }
}
     
void sendString(uchar* str){
   while(*str!=0x00){
      senduchar(*str);
      str++;                                                                                                                             
   }                                                                                                                                 
}

void main() {

   while(TRUE){                           
      strcpy(RFID_rec.data,"ABCDE532d"); 
      sendString(RFID_rec.data);                                                                                           
      delay_ms(2500);
   }
                                  
}       
Tufican



Joined: 23 Feb 2011
Posts: 10
Location: Turkey- izmir

View user's profile Send private message

doesn't work :(((
PostPosted: Mon Sep 19, 2011 12:54 pm     Reply with quote

hi everybody i have a problem
i m using ccs c canbus kit pic18f4580

i wrote and add this lines to ps2 code
Code:

#include <18f4580.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP,NOBROWNOUT,NOPUT
#use delay(clock=20000000)  // my clock frequency
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
//my baud rate and rs 232 pins. serial is working fine..
#define Clock pin_d0
#define Data pin_d1


main();
.
.
.
set_tris_d(0b00000011); //  i am using my free pins d0 and d1 for input?


Where is my wrong please help me :( i m going crazy :((

i have a pc oscilloscope and when i push the button i can see clock and data
keyboard is working.

have a good day to everybody

the total code is here.
Code:

#include <18f4580.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP,NOBROWNOUT,NOPUT
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#define Clock pin_d0
#define Data pin_d1
//D0 - Clock
//D1 - Data


// Clock must be the interrupt pin 

unsigned char bData[16];
unsigned char idx=0;
unsigned char tmp=0;

unsigned char readByte();
unsigned char processByte();
unsigned char waitKey();
byte keyhit();
unsigned char translate(unsigned char scancode);




volatile byte shiftSet = 0;

byte kbBuffer[16];
byte kbPos = 0;
byte kbSize = 0;
byte capsSet = 0;
volatile byte extFlag = 0;
volatile byte relFlag = 0;
volatile byte key=0;


void sendByte(byte b)
{
    byte a=0;
    byte p = 1;
    byte t = 0;

    return;         // THIS IS NOT FULLY WORKING ON ALL KEYBOARDS
                    // SO IT IS COMMENTED OUT
                    // Some kind of timing issue or something. Whatever, they're just LEDs



    disable_interrupts(GLOBAL);
    output_low(CLOCK);
    delay_us(300);
    output_low(DATA);
    input(CLOCK);

    for(a=0; a<8; a++)
    {
        t = b&(1<<a);
        while(input(CLOCK) == 1); //wait for 0
        output_bit(DATA, t);
        if(t)
            p++;
        while(input(CLOCK) == 0); //wait for 1
    }

    while(input(CLOCK) == 1); //wait for 0
    output_bit(DATA, p&0x01);
    while(input(CLOCK) == 0); //wait for 1

    input(DATA);
    while(input(DATA) == 1); //wait for 0
    while(input(CLOCK) == 1); //wait for 0

    delay_ms(10);

    clear_interrupt(INT_EXT);
    enable_interrupts(GLOBAL);
}

main()
{

    int i=0;
    unsigned char k=0;
    printf("READY >");

    output_b(0x00);
    input(CLOCK);

    delay_ms(100);

    ext_int_edge(H_to_L);
    enable_interrupts(INT_EXT);
    enable_interrupts(GLOBAL);

set_tris_d(0b00000011);    // RA0 ucu giriş olarak ayarlandı.
    while(1)
    {
        k = waitKey();
        printf("%c", k);

        while(keyhit())
            printf("%c", waitKey());
    }
}

byte keyhit()
{
    return kbSize != 0;
}

unsigned char waitKey()
{
    unsigned char k = 0;
    while(kbSize == 0);
    k = kbBuffer[(kbPos - kbSize)&0x0F];
    kbSize--;
    return k;
}

#int_ext
void kbInterrupt()
{
    volatile byte k=0;
    k = processByte();

    if(k != 0)
    {
        kbBuffer[kbPos] = k;
        kbPos = ++kbPos & 0x0F;
        kbSize++;
    }
    return;
}

unsigned char readByte()
{
    int i=0, t=0;
    idx=0;
    tmp=0;

    i=0;
    goto dataread;
   // while(INPUT(CLOCK) != 0);   // Wait for a keypress
            t=0;
       while(INPUT(CLOCK) != 0 && t<255)   // Wait for clock, time out if needed
       {
           delay_us(1);
           t++;
       }
    for(i=0; i<11; i++)
    {
        t=0;
        while(INPUT(CLOCK) != 0 && t<255)   // Wait for clock, time out if needed
        {
            delay_us(1);
            t++;
        }
        dataread:

        bData[idx]=INPUT(DATA);
        idx++;
        if(idx==9)
        {
            for(idx=1; idx<9; idx++)
                if(bData[idx]!=0)
                    tmp|=(1<<(idx-1));

            return tmp;
            idx=0;
            tmp=0;
        }
     //   while(INPUT(CLOCK) == 0);
        t=0;
        while(INPUT(CLOCK) == 0 && t<255)   // Wait for clock, time out if needed
        {
            delay_us(1);
            t++;
        }

    }
}

static const unsigned char scantableAZ[]={
0x1C, 0x32, 0x21, 0x23, 0x24, 0x2B, 0x34, 0x33, 0x43, 0x3B, 0x42, 0x4B, 0x3A, // A-Z
0x31, 0x44, 0x4D, 0x15, 0x2D, 0x1B, 0x2C, 0x3C, 0x2A, 0x1D, 0x22, 0x35, 0x1A};


// Normal numeric scancodes, starting with ',' .
static const unsigned char scantable09n[]=
{
0x41, 0x4E, 0x49, 0x4A, // , - . /
0x45, 0x16, 0x1E, 0x26, 0x25, 0x2E, 0x36, 0x3D, 0x3E, 0x46,     //Digits 0-9
0x00, 0x4C, 0x00, 0x55 // 0 ; 0 =
};

// Shift scancodes, starting at '!'
static const unsigned char scantable09s[]=
{
    0x16, 0x52, 0x26, 0x25, 0x2E, 0x3D, 0x00, 0x46, 0x45, 0x3E, 0x55
};

// Normal misc. scancode map. Scancode, ASCII value
static const unsigned char scanmapn[]=
{0x54, '[', 0x5B, ']', 0x0E, '`', 0x5D, '\\', 0x52, '\''};

// Shifted misc. scancode map. Scancode, ASCII value
static const unsigned char scanmaps[]=
{0x1E, '@', 0x36, '^', 0x4E, '_', 0x54, '{', 0x5B, '}', 0x5D, '|',
0x4C, ':', 0x41, '<', 0x49, '>', 0x4A, '?', 0x0E, '~'};


// Scancode map independent of Shift
static const unsigned char scanmapx[]=
{0x29, ' ', 0x5A, '\r', 0x0D, '\t', 0x76, 27, 0x66, 0x08};

// Extended scancode map
static const unsigned char scanmape[]=
{
0x71, 0x7F
};

unsigned char translate(unsigned char scancode)
{
    int i=0;

    if(extFlag == 0)
    {
        for(i=0; i<10; i+=2)
            if(scanmapx[i] == scancode)
                return scanmapx[i+1];

        for(i=0; i<26; i++)
            if(scantableAZ[i] == scancode)
                if(shiftSet ^ capsSet)
                    return i+65;
                else
                    return i+65 + 32;

        if(shiftSet)
        {
            for(i=0; i<11; i++)
                if(scantable09s[i] == scancode)
                    return i+'!';

            for(i=0; i<22; i+=2)
                if(scanmaps[i] == scancode)
                    return scanmaps[i+1];
        } else
        {
            for(i=0; i<18; i++)
                if(scantable09n[i] == scancode)
                    return i+',';

            for(i=0; i<10; i+=2)
                if(scanmapn[i] == scancode)
                    return scanmapn[i+1];
        }
    } else      // Extended keys
    {
        for(i=0; i<2; i+=2)
            if(scanmape[i] == scancode)
                return scanmape[i+1];
    }
    return '?';
}

unsigned char processByte()
{
    unsigned char i, j;
    i = readByte();

    if(i == 0xF0)       //A key is being released
    {
        relFlag = 1;
        return 0;
    }

    if(i == 0xE0)       // Extended key operation
    {
        extFlag = 1;
        relFlag = 0;    //0xE0 always first in sequence, OK to clear this
        return 0;
    }

    if(relFlag == 0)    // Pressing a key
    {
        if(extFlag == 0)    // Non-extended key pressed
        {
            if(i == 0x12 || i == 0x59)
            {
                shiftSet = 1;
                return 0;
            }

            if(i == 0x58)
            {
                sendByte(0xED);
                if(capsSet == 0)
                {
                    capsSet = 1;
                    sendByte(0x04);
                } else
                {
                    capsSet = 0;
                    sendByte(0x00);
                }
                return 0;
            }


        }
        j = translate(i);
        extFlag = 0;
        return j;
    }

    if(relFlag == 1)    //Releasing a key
    {
        relFlag = 0;    //If a flag was set but not handled, we wouldn't have gotten here
        extFlag = 0;    //OK to clear this here

        if(extFlag == 0)   // Releasing a nonextended key
        {
            if(i == 0x12 || i == 0x59)
            {
                shiftSet = 0;
                return 0;
            }

        }
//        } else              // Releasing an extended key
//        {
//            return 0;
//        }

//        return 0;
    }
    return 0;
}
pocanada



Joined: 04 Feb 2013
Posts: 1

View user's profile Send private message

Reading keyboard PS/2 bytes
PostPosted: Mon Feb 04, 2013 6:32 pm     Reply with quote

Here is example of code I used to decode the PS/2 bytes. I used a PIC18F4550 with CLOCK = PIN_B1(Int1) and DATA = PIN_D4. It seemed to work better when I read all the bytes first rather than one at a time before decoding.
Code:

//------------------------------------------------------------------
//----------------------- PS2_Keyboard -----------------------------
//------------------------------------------------------------------
#include "18F4550.h"
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)
#use rs232(baud=19200,xmit=PIN_C6,rcv=PIN_C7,stream=prime)

//----------  PIC 18F4550 board stuff ------------------------------
#use fast_IO(B)
#use fast_IO(D)

#define led_on output_high(PIN_D3)
#define led_off output_high(PIN_D3)

#define y_led_on; output_low(PIN_D7)
#define y_led_off; output_high(PIN_D7)

#define g_led_on; output_low(PIN_D5)
#define g_led_off; output_high(PIN_D5)

#define but PIN_B4
#define but PIN_B4

//-------- Rotary Switch Stuff  A is the interrupt2 pin  ------------

#define A PIN_B2
#define B PIN_D6
#define PB PIN_D4

//------  PS2 Keyboard stuff---- Clock must be the interrupt1 pin ---

#define CLOCK PIN_B1
#define DATA  PIN_D1
//------------------
#define hi_clk_delay;  t=0;while(input(CLOCK)==1 && t<255){delay_us(1);t++;}
#define lo_clk_delay;  t=0;while(input(CLOCK)==0 && t<255){delay_us(1);t++;}
//------------------
int8 readabyte(void);
int8 processByte(void;
int8 translate(int1 shft,int8 scancode);
//------------------
int8 t;
int8 bData[16];

//------------------ scan codes --------------------------------------------
const int8 scan_byte[]={
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,
0x45, 0x16, 0x1E, 0x26, 0x25, 0x2E, 0x36, 0x3D, 0x3E, 0x46, 0x0E, 0x4E ,0x55,
0x5D, 0x29, 0x54, 0x5B, 0x4C, 0x52, 0x41, 0x49, 0x4A};
//------------------ upper case literals -----------------------------------
const int8 upper_char[]={
'A',  'B',  'C',  'D',  'E',  'F',  'G',  'H',  'I',  'J',  'K',  'L',  'M',
'N',  'O',  'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',  'X',  'Y',  'Z',
')',  '!',  '@',  '#',  '$',  '%',  '^',  '&',  '*',  '(',  '~',  '_',  '+',
'|',  ' ',  '{',  '}',  ':',  '"',  '<',  '>',  '?' };
//------------------ lower case literals ----------------------------------
const int8 lower_char[]={
'a',  'b',  'c',  'd',  'e',  'f',  'g',  'h',  'i',  'j',  'k',  'l',  'm',
'n',  'o',  'p',  'q',  'r',  's',  't',  'u',  'v',  'w',  'x',  'y',  'z',
'0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',  '8',  '9',  '`',  '-',  '=',
'\\', ' ',  '[',  ']',  ';',  '\'',  ',',  '.',  '/' };
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
#int_ext1
void kbInterrupt() {
int8 c=0;

   disable_interrupts(INT_EXT1_H2L);
   c = processByte();
   if(c !='?')
      fprintf(prime,"%c",c);
   enable_interrupts(INT_EXT1_H2L);
   
}   //kbInterrupt()

//-------------------------------------------------------------------------
main(){
 set_tris_b(0xFF);
 set_tris_d(0x5F);
 port_b_pullups(0xFF);
 
    fprintf(prime,"PS2_Keyboard - January 31, 2013\r\n");
    enable_interrupts(INT_EXT1_H2L);
    enable_interrupts(GLOBAL);

    while(1){
   
   }    //while(1)
}    //main


//---------------------------------------------------
//--------------------  my readabyte() -----------------
//---------------------------------------------------
int1 readabyte(void){
int8 i=0;
int8 n=0;
int8 bPar=0;
int8 tmp=0;
int1 enough=0;

      
      for(i=0;i<16;i++)
           bData[i]=0;
        while(input(CLOCK)==0);         //start pulse
        
      do{ 
         for(i=0;i<8;i++){             // following 8 pulses                   
            hi_clk_delay;
            shift_right(&bData[n],1,input(DATA));
            while(input(CLOCK)==0);
            lo_clk_delay;
         }   //for i<8
         for(i=0;i<2;i++){             // parity and stop pulse                   
            hi_clk_delay;
            shift_right(&bPar,1,input(DATA));
            while(input(CLOCK)==0);
            lo_clk_delay;
         }   //for i<2
         tmp++;
         hi_clk_delay;         // Inner pulses delay
         
         if(input(CLOCK)== 1)      // if after this clock still high ==  end
            enough = 1;
         else{
            n++;
            lo_clk_delay;         //start pulse delay
         }   //else
            
      }while((n < 16) && !enough);   //do
      
              return(tmp);
 
}   //readabyte()              
              

//------------------------------------------------
//-----------------------  my process byte  ----------
//------------------------------------------------
int8 processByte(void){
int8 k=0;
int8 j=0;
static int1 shift,caplock;


   k = readabyte();      //k = # bytes in bData array;

#ifdef PRINT_DATA
   int8 i;
   fprintf(prime,"%U:  ",k);
   for(i=0;i<k;i++)
       fprintf(prime,"%X  ",bData[i]);
    fprintf(prime,"\r\n");

#endif   

 //Look for cap locks first
 
    if((bData[0]==0x58)&&(!caplock)){
       shift=1;
       caplock=1;
    }   //if...
   else if((bData[0]==0x58)&&(caplock)){
      shift=0;
      caplock=0;
   }   //else if...
   
 //Then Look for L Shift or R Shift keys
 
     if((bData[0]==0x12)||(bData[0]==0x59))
       shift = 1;

    else{
       if(((bData[0]==0xF0)&&(bData[1]==0x12)||
       (bData[0]==0xF0)&&(bData[1]==0x59))&& !caplock)
          shift = 0;
    }   //else...

    
    j = translate(shift,bData[0]);    //"j" = int8 of the character returned                                 
 
   return(j);

}   //processByte()

//--------------------------------------------------------------
//------------------  my translate  -----------------------------
//------------------------------------------------------------

int8 translate(int1 shft,int8 scancode){
int8   i;
   
   if(shft){
      for(i=0; i<52; i++){
      if(scan_byte[i] == scancode)
         return(upper_char[i]);
      }   //for(i=...
   }   //shft
   else{
      for(i=0; i<52; i++){
      if(scan_byte[i] == scancode)
         return(lower_char[i]);
      }   //for(i=...
   }   //!shft      
     return('?'); 
}   //translate()
mariano



Joined: 06 Oct 2013
Posts: 1

View user's profile Send private message

Re: PS/2 keyboard driver/decoder, interrupt driven, 16F and
PostPosted: Sun Oct 06, 2013 9:50 am     Reply with quote

stevenm86 Hello.

Hey proven soft and the problem I had is that when you press the number buttons works well then pressing the shift key changes to the symbols even hi all well but when they press the shift key does not return to the numbers remaining in the Symbols could help me, thanks my name is Mariano and my email marianoarias1967@yahoo.com.ar
kalyan



Joined: 16 May 2014
Posts: 7

View user's profile Send private message Send e-mail

Re: PS/2 keyboard driver/decoder, interrupt driven, 16F and
PostPosted: Sat Jun 07, 2014 9:23 am     Reply with quote

mariano wrote:
stevenm86 Hello.

Hey proven soft and the problem I had is that when you press the number buttons works well then pressing the shift key changes to the symbols even hi all well but when they press the shift key does not return to the numbers remaining in the Symbols could help me, thanks my name is Mariano and my email marianoarias1967@yahoo.com.ar


even i am facing the same problem kindly help
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group