please dont rip this site

PIC Microcontroller PC PS2 Keyboard I/O

By Jinx

PC keyboard capture/emulation

The object of this project is to capture keys of a standard AT keyboard. They
can be stored, compiled as strings, and re-transmitted either to the PC or to
some other device, as the original key presses or as extracted commands

For example, the PIC could capture strings, and perform actions

Such as

sc:1329:040810[enter] to set the PIC's clock-calendar to 1:29pm, 4th August 2010
ky:[F1]a:1000:050810[enter] to simulate pressing F1 then 'a' at 10:00am on 5th August 2010
ir:94:2030:060810[enter] to send the number 94 by infra-red at 8:30pm on the 6th

[ ] indicates the code for a special key. [F1] has the value 0x05 for instance.
[enter] may not always be suitable for the string terminator. Perhaps [Esc] or
'<' or [Tab] for example as alternates

Circuit Schematic

This is the proof-of-concept prototype. The second version will be based on an
18F2520, which has more RAM/Flash. Also the timing will be crystal-derived for
more accurate long-term timekeeping

During development I used a header in parallel with the keyboard's wires, rather
than connect the circuit in the final in-line configuration. This allowed signals to
be read by an analyser and also the circuit power could be controlled during
programming and amendments

This is the timing diagram of the 'f' key, as sent from the keyboard to the PC
and its release, some 300ms later. 'F0' is 'any key released', '2b' tells the
PC that it was the 'f' key

Here is the PIC simulation of an 'f' key press

Note that the PIC does not have the same lengthy Clock low after the Stop bit. As
I guess it, the real keyboard holds Clock low to prevent the PC sending it commands,
which the PC would initiate by pulling Clock low for at least 60us

Read the PC keyboard specifications for that and more information - PC Keyboard Spec Sheet

PIC pin definitions ;

#define  ir_data   lata,0       ;infra-red drive
#define  pickup   porta,1       ;press to store keys
#define  kbd_out   lata,2       ;keyboard data out (transistor drive, ie inverted logic)
#define  kbc_out   lata,3       ;keyboard clock out (transistor drive, ie inverted logic)
#define  send     porta,4       ;press to manually transmit stored key(s)
;#define  mclr    porta,5       ;reset
#define  led       lata,6       ;LED
#define  rw        lata,7       ;LCD R/W
#define  kbc_in   portb,0       ;keyboard clock in, normally high
#define  kbd_in   portb,1       ;keyboard data in, normally high
#define  en        latb,2       ;LCD Enable
#define  rs        latb,3       ;LCD RS
;#define          portb,4       ;LCD data, 4-bit mode
;#define          portb,5
;#define          portb,6
;#define          portb,7
;        Receive and store key data
;Keyboard Clock (kbc_in) and Data (kbd_in) normally high,
;open-collectors with pullups
;release clock and data lines (ie no transistor drive, resistors pull lines high)
         bcf     kbd_out
         bcf     kbc_out
;Data format -
;1 start bit, '0' 
;8 data bits, LSb first 
;1 parity bit, odd
;1 stop bit, '1'
;Data changes when clock = 1, valid when clock = 0
As the keyboard codes have no direct relationship to ASCII codes, the key code
is used as a pointer to its ASCII code in a table, but simply for display in
my case. The key code itself would be stored if required for re-transmission
In the s/w presented here, only the basic layout is shown. For example letters
are all lower case. By detecting the Shift, Alt and Ctrl keys, the corresponding
alternate layout can be displayed. This can be done by calculation, for example
a (lower case) = 0x61, Shift a (or A, upper case) = 0x41
b              = 0x62,             B              = 0x42
and so on, or by adding more tables, still using the key value as the pointer
For example a Shift layout could be used to get Shift number characters - ! @ # $ etc
For my project, I used arbitrary conversions for non-alphanumeric keys so that
each key has a unique representation and assignment
;0x00           no conversion available (ie no key exists)
;0x20 to 0x7f   LCD display code in ASCII
;0x80 to 0x8f   function key, 0x80 + function key number
;0xf0 to 0xff   special key, as assigned
;f0 Tab, f1 tilde, f2 left shift, f3 Ctrl, f4 Caps Lock, f5 right shift, f6 Enter
;f7 backslash, f8 backspace, f9 back space, fa Esc, fb Num Lock, fc Alt
;Note that right-hand versions of some same-name keys (eg Ctrl) are preceded by
;0xE0, as can be seen in the keyboard codes diagram below
;Others, such as the numeric keypad, are treated differently by the PC depending
;on the status of Lock keys. The transmitted code is still the same, only the
;interpretation (for display and usage etc) by s/w changes
kb_loop  call    data_st        ;detect and get key into kbdat1
;        Convert key data to key name
kb_dec   movlw   upper(kb_codes);base address = kb_codes
         movwf   tblptru
         movlw   high(kb_codes)
         movwf   tblptrh
         movlw   low(kb_codes)
         addwf   kbdat1,w       ;add k/b value
         movwf   tblptrl
         movff   tablat,temp0   ;get value from table
         movfw   temp0
         bz      no_key         ;no equivalent
         movlw   0xf0
         cpfslt  temp0          ;if temp0 < f0
         bra     special        ;else f? (special key)
         movlw   0x80
         cpfslt  temp0          ;if temp0 < 80
         bra     function       ;else 8? (function key)
         call    store          ;store the key if necessary
         movfw   temp0
         dispw                  ;otherwise, printable on LCD
         goto    release        ;detect either 0xf0 or another key pressed
special keys routines           ;process (and store) special key, check release
function keys routine           ;process (and store) function key, check release
store routine                   ;if desired, store the key in a queue for
                                ;later retrieval and transmission
release  call    data_st        ;get data
         movlw   0xf0           ;key release code
         xorwf   kbdat1,w
At this point -
The XOR result will be 0, ie a key released. Get more data to determine
which key it was, if more than one key was down
For example,
if 'A' was pressed and released, the sequence will be 0x1c 0xf0 0x1c
If Left Ctrl '.', the sequence will be 0x14 0x49 0xf0 0x49 0xf0 0x14

ie Left Ctrl pressed, '.' pressed, '.' released, Left Ctrl released

Or the XOR result will be <> 0, meaning either a key is down and is repeating or a second key is pressed. Get more data. If the first key down is a special key such as Shift, Ctrl or Alt, then the next key detected may need to be looked up in an alternate conversion table. eg Shift ',' to make '<'
Include a timing routine to test for repeat. Default time before repeating starts is around 500ms. Time between repeats is the Typematic setting

;================================================ ; Receive key from PC ;================================================ ;Clock line shared with mouse, so use Data line for activity detection data_st btfsc kbd_in ;Data low, k/b is active bra $-2 ;Start bit btfsc kbc_in ;keyboard clock low bra $-2 btfss kbc_in ;end of Start bit bra $-2 movlw .8 ;data bit counter movwf temp1 clrf kbdat1 ;receiving buffer ;pick up 8 bits, data valid when clock is low kb8 rrncf kbdat1 ;shift bit through buffer, 1st time is dummy bcf bit_in ;data = default 0 btfsc kbc_in ;wait for clock = 0 bra $-2 btfsc kbd_in ;skip if data is 0 bsf bit_in ;else store 1 btfss kbc_in ;wait for clock = 1 bra $-2 decfsz temp1 ;counter bra kb8 ;Parity bit - receive, ignore btfsc kbc_in bra $-2 btfss kbc_in bra $-2 ;Stop bit - receive, ignore btfsc kbc_in bra $-2 btfss kbc_in bra $-2 return ;with key in kbdat1 ;================================================ ; Transmit key to PC ;================================================ ;1 start bit, '0' ;8 data bits, LSb first ;1 parity bit, odd ;1 stop bit, '1' ;Data changes when clock = 1, valid when clock = 0 ;Clock and data outputs are inverted by transistors ;ie PIC '1' drives transistor to ground the line ;data in temp0 transmit movwf temp0 ;byte to transmit movlw .8 movwf temp1 ;data bit counter clrf temp4 ;parity counter ;Start bit bsf kbd_out ;data line low call _17us ;hold for 17us bsf kbc_out ;clock line low call _44us ;hold for 44us bcf kbc_out ;clock line high call _17us ;5us > delay < 25us before data transition ;begin data transmission. key_loop movlw b'00000001' ;test data bit to send andwf temp0,w bnz _1bit ;data = 1 _0bit bsf kbd_out ;data = 0 (ground data line) bra bit_del _1bit bcf kbd_out ;data = 1 (release data line) incf temp4 ;parity count bit_del call _25us ;25us delay bsf kbc_out ;data valid call _44us ;hold for 44us bcf kbc_out ;clock high call _17us ;hold for 17us rrncf temp0 ;shift in next data bit decfsz temp1 ;bit counter bra key_loop movlw b'00000001' ;test parity count andwf temp4,w bz parity1 parity0 bsf kbd_out ;result odd, send '0' -> odd parity bra tx_end parity1 bcf kbd_out ;result even, send '1' -> odd parity tx_end call _25us bsf kbc_out call _44us bcf kbc_out ;Stop bit call _17us bcf kbd_out ;data line idle call _25us usec usec bsf kbc_out ;clock line low call _44us bcf kbc_out ;clock line idle return

Keyboard codes, as transmitted to PC

;convert keyboard data to key name and/or ASCII character for PIC's use
;data received from keyboard
;00  01  02  03  04  05  06  07  08  09  0a  0b  0c  0d  0e  0f    data received
;    F9      F5  F3  F1  F2  F12     F10 F8  F6  F4  Tab ~         = key pressed
;10  11  12  13  14  15  16  17  18  19  1a  1b  1c  1d  1e  1f
;    Alt LSh     Ctl q   1               z   s   a   w   2    
;20  21  22  23  24  25  26  27  28  29  2a  2b  2c  2d  2e  2f
;    c   x   d   e   4   3           SP  v   f   t   r   5    
;30  31  32  33  34  35  36  37  38  39  3a  3b  3c  3d  3e  3f
;    n   b   h   g   y   6               m   j   u   7   8    
;40  41  42  43  44  45  46  47  48  49  4a  4b  4c  4d  4e  4f
;    ,   k   i   o   0   9           .       l       p   -    
;50  51  52  53  54  55  56  57  58  59  5a  5b  5c  5d  5e  5f
;                [   =           Cap RSh Ent ]       \       
;60  61  62  63  64  65  66  67  68  69  6a  6b  6c  6d  6e  6f     'n' indicates
;                        Bksp        1n      4n  7n                 numeric keypad
;70  71  72  73  74  75  76  77  78  79  7a  7b  7c  7d  7e  7f
;0n  .n  2n  5n  6n  8n  Esc Num F11 +n  3n      *n      -n
;80  81  82  83  84  85  86  87  88  89  8a  8b  8c  8d  8e  8f
;            F7
  org    kb_codes ;ASCII and special codes for keys
Examples -
;key received is 0x2d. Data at table address 0x2d is 0x72 = ASCII r
;key received is 0x78. Data at table address 0x78 is 0x8b = F11
;key received is 0x12. Data at table address 0x12 is 0xf2 = Left Shift
;key received is 0x47. Data at table address 0x47 is 0x00 = no equivalent
;18F table, basic layout
;           1 0    3 2    5 4    7 6    9 8    b a    d c    f e
  data   0x8900,0x8500,0x8183,0x8c82,0x8a00,0x8688,0xfc84,0x00f1 ;0x
  data   0xf900,0x00f2,0x71f3,0x0031,0x0000,0x737a,0x7761,0x0032 ;1x
  data   0x6300,0x6478,0x3465,0x0033,0x2000,0x6676,0x7274,0x0035 ;2x
  data   0x6e00,0x6862,0x7967,0x0036,0x0000,0x6a6d,0x3775,0x0038 ;3x
  data   0x2c00,0x696b,0x306f,0x0039,0x2e00,0x6c00,0x7000,0x002d ;4x
  data   0x0000,0x0000,0x3d7b,0x0000,0xf5f4,0x7df6,0xf700,0x0000 ;5x
  data   0x0000,0x0000,0x0000,0x00f8,0x3100,0x3400,0x0037,0x0000 ;6x
  data   0x2e30,0x3532,0x3836,0xfbfa,0x2b8b,0x0033,0x002a,0x002d ;7x
  data   0x0000,0x8700,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 ;8x
;16F table, basic layout
;       0    1    2    3    4    5    6    7    8    9    a    b    c    d    e    f
;  dt 0x00,0x89,0x00,0x85,0x83,0x81,0x82,0x8c,0x00,0x8a,0x88,0x86,0x84,0xfc,0xf1,0x00 ;0x
;  dt 0x00,0xf9,0xf2,0x00,0xf3,0x71,0x31,0x00,0x00,0x00,0x7a,0x73,0x61,0x77,0x32,0x00 ;1x
;  dt 0x00,0x63,0x78,0x64,0x65,0x34,0x33,0x00,0x00,0x20,0x76,0x66,0x74,0x72,0x35,0x00 ;2x
;  dt 0x00,0x6e,0x62,0x68,0x67,0x79,0x36,0x00,0x00,0x00,0x6d,0x6a,0x75,0x37,0x38,0x00 ;3x
;  dt 0x00,0x2c,0x6b,0x69,0x6f,0x30,0x39,0x00,0x00,0x2e,0x00,0x6c,0x00,0x70,0x2d,0x00 ;4x
;  dt 0x00,0x00,0x00,0x00,0x7b,0x3d,0x00,0x00,0xf4,0xf5,0xf6,0x7d,0x00,0xf7,0x00,0x00 ;5x
;  dt 0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x00,0x00,0x31,0x00,0x34,0x37,0x00,0x00,0x00 ;6x
;  dt 0x30,0x2e,0x32,0x35,0x36,0x38,0xfa,0xfb,0x8b,0x2b,0x33,0x00,0x2a,0x00,0x2d,0x00 ;7x
;  dt 0x00,0x00,0x00,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ;8x


file: /Techref/microchip/io/dev/keyboard/ps2-jc.htm, 15KB, , updated: 2014/8/19 14:11, local time: 2017/10/23 01:34,

 ©2017 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions?
Please DO link to this page! Digg it! / MAKE! / 

<A HREF=""> PIC Microcontroler, Microchip PIC, PS2 Keyboard, PC keyboard capture, PC keyboard emulator</A>

After you find an appropriate page, you are invited to your to this massmind site! (posts will be visible only to you before review) Just type in the box and press the Post button. (HTML welcomed, but not the <A tag: Instead, use the link box to link to another page. A tutorial is available Members can login to post directly, become page editors, and be credited for their posts.

Link? Put it here: 
if you want a response, please enter your email address: 
Attn spammers: All posts are reviewed before being made visible to anyone other than the poster.
Did you find what you needed?

  PICList 2017 contributors:
o List host: MIT, Site host, Top posters @20171023 RussellMc, Van Horn, David, James Cameron, Sean Breheny, IVP, alan.b.pearce, Neil, David C Brown, Bob Blick, Denny Esterline,
* Page Editors: James Newton, David Cary, and YOU!
* Roman Black of Black Robotics donates from sales of Linistep stepper controller kits.
* Ashley Roll of Digital Nemesis donates from sales of RCL-1 RS232 to TTL converters.
* Monthly Subscribers: Gregg Rew. on-going support is MOST appreciated!
* Contributors: Richard Seriani, Sr.

Welcome to!