http://home.clear.net.nz/pages/joecolquitt/pic_keyboard.html
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



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
nop
nop
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
tblrd*+
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
;================================================ ;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
Questions:
Code:
| file: /Techref/microchip/io/dev/keyboard/ps2-jc.htm, 16KB, , updated: 2020/6/24 09:34, local time: 2025/10/27 08:53,
216.73.216.180,10-8-63-169:LOG IN
|
| ©2025 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? <A HREF="http://www.massmind.org/Techref/microchip/io/dev/keyboard/ps2-jc.htm"> PIC Microcontroler, Microchip PIC, PS2 Keyboard, PC keyboard capture, PC keyboard emulator</A> |
| Did you find what you needed? |
Welcome to massmind.org! |
Welcome to www.massmind.org! |
.