Advertisement  

Wednesday, 24 July 2019
     
 
Main Menu
Home Home
Shop Shop
News News
BASCOM-AVR BASCOM-AVR
BASCOM-8051 BASCOM-8051
Products Products
Application Notes Application Notes
Publications Publications
Links Links
Support Center Support Center
Downloads Downloads
Forum Forum
Resellers Resellers
Contact Us Contact Us
Updates Updates
MCS Wiki MCS Wiki
Online Help
BASCOM-AVR Help BASCOM-AVR Help
BASCOM-8051 Help BASCOM-8051 Help
Contents in Cart
Show Cart
Your Cart is currently empty.
Search the Shop

Products Search

User Login
Username

Password

If you have problem after log in with disappeared login data, please press F5 in your browser

RSS News
 
     
 

 
   
     
 
AN #05 - Reading an AT-PC Keyboard Print
Reading an AT-PC Keyboard

The following program was submitted by Dusko Djuricin.
It shows how to read a keyboard from an AT compatible PC.

Download source code in Bas file

' =========================================================================================
'
' Program: ATPCKBD.BAS
' Author: Dusko Djuricin
' E-mail: djdusko@eunet.yu
'
' This program demonstrates how to interface AT PC keyboard to 8031 microcontrollers family.
' Program was originally written and tested for ATMEL 89C2051. For keyboard interfacing it
' uses only two I/O lines with two pull up resistors. At the output, through serial channel,
' it sends ASCII code of pressed key. Other used I/O lines are not necessary.
' Complete description of PC keyboard operation, could be found at the following address:
'
' http://www.geocities.com/SiliconValley/Bay/8302/keybrd.htm#1
'
' =========================================================================================

Dim B1 As Byte , B2 As Byte , N As Byte , Status As Byte , Key As Byte
Dim Caps As Bit , Caps_lock As Bit , Ctrl As Bit , Alt As Bit , Tmp As Bit
Dim Temp As String * 1

Declare Sub Tx_byte(b1 As Byte)
Declare Sub Rx_byte
Declare Sub Kbd_status

Kbd_data
Alias P1.1 ' connected with 4K7 pull up resistor
Kbd_clk
Alias P1.0 ' connected with 4K7 pull up resistor
Buzzer
Alias P3.7 ' for details see BASCOM51 documentation
Res_sw
Alias P3.5 ' optional output (see code)

Dim Frequency As Const 2048
Dim Duration As Const 50
Dim L_shift As Const &H12
Dim R_shift As Const &H59
Dim Ctrl_key As Const &H14
Dim Alt_key As Const &H11
Dim Caps_key As Const &H58
Dim Scroll_key As Const &H7E

'---------------------------[Beginning of Program]-------------------------------

Reset Kbd_clk ' disable the Keyboard

Waitms 100
Do
 Tx_byte
&HFF ' reset the Keyboard and wait
 Rx_byte 
' till the Keyboard answer with
 
If B1 = &HFA Then Exit Do ' acknowledge byte
 
If B1 = &HAA Then Exit Do ' or Power On Self Test OK code
Loop

Print
Print "*** AT PC Keyboard Interface ***"
Print " author: Dusko Djuricin"
Print " E-mail: djdusko@eunet.yu"
Print "********************************"
Print

' KBD LED: Status.0 - Scroll Lock, Status.1 - Num Lock, Status.2 - Caps Lock
Status
= 2 ' initially Num Lock On
Kbd_status

Do
' KEY variable will hold ASCII value of pressed key
 Key
= 0 ' initial value
 Rx_byte 
' read scan code from PC keyboard into B1

 
Select Case B1
 
Case Ctrl_key:
 
Set Ctrl ' mark that CTRL key is pressed
 B1
= 0
 
Case Alt_key:
 
Set Alt ' same as above but for ALT key ...
 B1
= 0
 
Case L_shift:
 
Set Caps ' same as above but for Left SHIFT key ...
 B1
= 0
 
Case R_shift:
 
Set Caps ' same as above but for Right SHIFT key ...
 B1
= 0
 
Case &HE0: ' extended codes are not handled!
 B1
= 0
 
Case &HF0: ' BREAK CODE is detected (key depressed)
 Rx_byte 
' read again to see which key is depressed
 
If B1 = L_shift Then ' and keep tracking flags...
 
Reset Caps
 
Elseif B1 = R_shift Then
 
Reset Caps
 
End If
 
If B1 = Ctrl_key Then
 
Reset Ctrl
 
Elseif B1 = Alt_key Then
 
Reset Alt
 
End If
 B1
= 0
 
Case Caps_key: ' in a case of CAPS LOCK key
 Caps_lock
= Caps_lock Xor 1  ' there must be calculated status of it's LED
 Status
= Status Xor 4
 Kbd_status 
' and then we must send it to keyboard
 B1
= 0
 
Case Scroll_key: ' I use combination of Ctrl + Alt + ScrLock
 Tmp
= Ctrl And Alt ' keys to generate reset signal...
 
If Tmp = 1 Then
 
Reset Res_sw ' ...for my host controller
 Status
= Status Xor 1 ' (Scroll Lock LED will lit and buzzer beeps)
 Kbd_status
 
Sound Buzzer , Duration , 512
 
Waitms 100
 
Sound Buzzer , Duration , 512
 
Waitms 100
 
Sound Buzzer , Duration , 512
 
Waitms 100
 
Set Res_sw
 Status
= Status Xor 1 ' turn off Scroll Lock LED
 Kbd_status
 
End If
 B1
= 0
 
Case Else: ' handling of "printable" characters
 
If B1 > 131 Then ' this program handles only lower part
 B1
= 0 ' of ASCII code table (with exception of
 
End If ' function keys - see lookup table)
 
If Caps = 1 Then
 Key
= Lookup(b1 , With_shift) ' one table is for SHIFT + key combination
 
Else
 Key
= Lookup(b1 , No_shift) ' and another is for key WITHOUT SHIFT
 
End If
 
If Caps_lock = 1 Then
 
If Caps = 0 Then ' if CAPS LOCK was ON and there is no
 Temp
= Chr(key) ' SHIFT + key combination, then convert
 Temp
= Ucase(temp) ' pressed key into upper case letter
 Key
= Asc(temp)
 
End If
 
End If
 
End Select

 
If B1 <> 0 Then
 
Sound Buzzer , Duration , Frequency ' beep
 
Print Chr(key); ' and print pressed key
 
End If
 
Waitms 10 ' dummy delay ...
Loop

'-----------------------[Receive Byte from Keyboard]----------------------------

Sub Rx_byte
 
Set Kbd_clk ' enable Keyboard
 
mov {n},#0
 jb Kbd_clk
,*+0 ' wait CLK to become zero
' START bit
 jnb Kbd_data
,L_cont  ' if START bit is zero continue
 sjmp
.L_error ' if not exit via error label
' DATA bits
!L_cont:
 
Incr N ' this is counter of received bits
 acall zero2one
 
mov a,{b1} ' prepare buffer
 
mov c,Kbd_data ' read DATA bit
 rrc a 
' read it into the buffer
 
mov {b1},a ' store buffer value
 
mov a,{n}
 cjne a
,#8,L_cont ' if it isn't last bit repeat
' PARITY bit
 acall zero2one
 
mov a,{b2} ' prepare buffer
 
mov c,Kbd_data ' read ODD PARITY bit
 rrc a 
' store it into the buffer
' STOP bit
 acall zero2one
 
mov c,Kbd_data ' read STOP bit
 rrc a 
' store it into the buffer
 rrc a 
' now align bits to right...
 rrc a
 rrc a
 rrc a
 rrc a
 rrc a
 anl a
,#3 ' extract valuable bits and
 
mov {b2},a ' store to buffer
' check STOP bit
 anl a
,#2
 jz
.L_error
' PARITY checking
 
mov a,{b1}
 
mov c,psw.0 ' this is EVEN PARITY
 rlc a
 anl a
,#1
 xch a
,{b2}

 anl a
,#1
 xrl a
,{b2}
 jz
.L_error
 sjmp
.L_end
L_error
:  ' exit in case of an error
 
Waitms 1 ' wait end of transmission
 
mov a,#0
 
mov {b1},a
L_end
:
 
Reset Kbd_clk ' stop the Keyboard
End Sub

'------------------------[Transmit Byte to Keyboard]----------------------------

Sub Tx_byte(b1 As Byte)
 B2
= 8
 
Reset Kbd_clk ' break the Keyboard
 
Delay ' (safety reasons)
  
Delay
 
Delay
 
Delay
 
Delay
 
Delay
 
Reset Kbd_data ' request to send
 
Set Kbd_clk ' enable the Keyboard
' START BIT
 acall zero2one
' DATA BITS
 
mov a,{b1}
!L_tx_data:
 rrc a
 
mov Kbd_data,c
 acall zero2one
 djnz
{b2},L_tx_data
' PARITY BIT
 
mov a,{b1} ' calculate parity bit
 
mov c,psw.0 ' this is Even parity
 cpl c 
' and Keyboard needs Odd parity
 
mov Kbd_data,c ' send parity bit
 acall zero2one
' STOP BIT
 
Set Kbd_data ' send stop bit
 acall zero2one
' KBD ACK BIT
 acall zero2one
 
Reset Kbd_clk ' stop the keyboard
End Sub

'------------------[ASM Subroutine wait for falling edge]-----------------------

!zero2one:
 jnb Kbd_clk
,*+0  ' wait till CLK rise
 jb Kbd_clk
,*+0 ' now wait till CLK fall down
 
ret

'------------[Subroutine for sending LED status to the Keyboard]----------------

Sub Kbd_status:
 Tx_byte
&HED
 Rx_byte
 Tx_byte Status
 Rx_byte
End Sub

'---------------------[Scan Code to ASCII conversion table]---------------------
' Here are two lookup tables, one for handling ordinary keys and other for
' handling combination of SHIFT + key. I gave (under block remark) same tables
' written as strings, so matching with ASCII codes could be easier.
'
' Note that function keys (F1 to F12) are coded as one byte. F1 is coded as 129,
' F2 gives 130, F3 gives 131 and so on. This was OK for my application and it is
' because of simplicity.
'
' Gray keys are not handled (INS, DEL, HOME, ARROWS etc)! These keys returns ASCII
' value of appropriate key on numeric keypad (HOME will give 7, END gives 1, etc).
'
' Pressing of Num Lock key have no effects. Num Lock LED is always ON and serves
' as indicator that controller is turned on (if the keyboard is connected).
'
' Keyboard mapping is for ordinary 101 keys keyboard (standard US layout).
'
No_shift
:
'(
Data ""
Data "F9" , "" , "F5" , "F3" , "F1" , "F2" , "F12" , "" , "F10" , "F8"
Data "F6" , "F4" , "TAB" , "`" , "" , "" , "LAlt" , "LSh" , "" , "LCtr" , "q"
Data "1" , "" , "" , "" , "z" , "s" , "a" , "w" , "2" , ""
Data "" , "c" , "x" , "d" , "e" , "4" , "3" , "" , "" , " "
Data "v" , "f" , "t" , "r" , "5" , "" , "" , "n" , "b" , "h"
Data "g" , "y" , "6" , "" , "" , "" , "m" , "j" , "u" , "7"
Data "8" , "" , "" , "," , "k" , "i" , "o" , "0" , "9" , ""
Data "" , "." , "/" , "l" , ";" , "p" , "-" , "" , "" , ""
Data "'" , "" , "[" , "=" , "" , "" , "Caps" , "RSht" , "Enter" , "]"
Data "" , "" , "" , "" , "" , "" , "" , "" , "" , ""
Data "BkSp" , "" , "" , "1" , "" , "4" , "7" , "" , "" , ""
Data "0" , "." , "2" , "5" , "6" , "8" , "ESC" , "NumLck" , "F11" , "+"
Data "3" , "-" , "*" , "9" , "ScrLck" , "" , "" , "" , "" , "F7"
')
Data 0
Data 137 , 0 , 133 , 131 , 129 , 130 , 140 , 0 , 138 , 136
Data 134 , 132 , 9 , 96 , 0 , 0 , 0 , 0 , 0 , 0 , 113
Data 49 , 0 , 0 , 0 , 122 , 115 , 97 , 119 , 50 , 0
Data 0 , 99 , 120 , 100 , 101 , 52 , 51 , 0 , 0 , 32
Data 118 , 102 , 116 , 114 , 53 , 0 , 0 , 110 , 98 , 104
Data 103 , 121 , 54 , 0 , 0 , 0 , 109 , 106 , 117 , 55
Data 56 , 0 , 0 , 44 , 107 , 105 , 111 , 48 , 57 , 0
Data 0 , 46 , 47 , 108 , 59 , 112 , 45 , 0 , 0 , 0
Data 39 , 0 , 91 , 61 , 0 , 0 , 0 , 0 , 13 , 93
Data 0 , 92 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
Data 8 , 0 , 0 , 49 , 0 , 52 , 55 , 0 , 0 , 0
Data 48 , 46 , 50 , 53 , 54 , 56 , 27 , 0 , 139 , 43
Data 51 , 45 , 42 , 57 , 0 , 0 , 0 , 0 , 0 , 135

With_shift
:
'(
Data ""
Data "F9" , "" , "F5" , "F3" , "F1" , "F2" , "F12" , "" , "F10" , "F8"
Data "F6" , "F4" , "TAB" , "~" , "" , "" , "LAlt" , "LSh" , "" , "LCtr" , "Q"
Data "!" , "" , "" , "" , "Z" , "S" , "A" , "W" , "@" , ""
Data "" , "C" , "X" , "D" , "E" , "$" , "#" , "" , "" , " "
Data "V" , "F" , "T" , "R" , "%" , "" , "" , "N" , "B" , "H"
Data "G" , "Y" , "^" , "" , "" , "" , "M" , "J" , "U" , "&"
Data "*" , "" , "" , "<" , "K" , "I" , "O" , ")" , "(" , ""
Data "" , ">" , "?" , "L" , ":" , "P" , "_" , "" , "" , ""
Data 34 , 0 , "" , "{" , "+" , "" , "" , "Caps" , "RSht" , "Enter" , "}"
Data "" , "|" , "" , "" , "" , "" , "" , "" , "" , ""
Data "BkSp" , "" , "" , "1" , "" , "4" , "7" , "" , "" , ""
Data "0" , "." , "2" , "5" , "6" , "8" , "ESC" , "NumLck" , "F11" , "+"
Data "3" , "-" , "*" , "9" , "ScrLck" , "" , "" , "" , "" , "F7"
')
Data 0
Data 137 , 0 , 133 , 131 , 129 , 130 , 140 , 0 , 138 , 136
Data 134 , 132 , 9 , 126 , 0 , 0 , 0 , 0 , 0 , 0 , 81
Data 33 , 0 , 0 , 0 , 90 , 83 , 65 , 87 , 64 , 0
Data 0 , 67 , 88 , 68 , 69 , 36 , 35 , 0 , 0 , 32
Data 86 , 70 , 84 , 82 , 37 , 0 , 0 , 78 , 66 , 72
Data 71 , 89 , 94 , 0 , 0 , 0 , 77 , 74 , 85 , 38
Data 42 , 0 , 0 , 60 , 75 , 73 , 79 , 41 , 40 , 0
Data 0 , 62 , 63 , 76 , 58 , 80 , 95 , 0 , 0 , 0
Data 34 , 0 , 123 , 43 , 0 , 0 , 0 , 0 , 13 , 125
Data 0 , 124 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
Data 8 , 0 , 0 , 49 , 0 , 52 , 55 , 0 , 0 , 0
Data 48 , 46 , 50 , 53 , 54 , 56 , 27 , 0 , 139 , 43
Data 51 , 45 , 42 , 57 , 0 , 0 , 0 , 0 , 0 , 135

'-----------------------------[End of Program]----------------------------------