;*************************** ; >-< G Soft Creations >-< ;--------------------------- ; AT Keyboard Routines ;*************************** ;---------------- ; RAM Usage: ;---------------- ; Keyboard vars .equ KB_OK, 0x45 .equ KB_DATA, 0x46 .equ KB_STATS, 0x47 .equ KB_SCAN, 0x48 .equ KB_TEMP, 0x49 ; For the da*n pause key ;------------------ ; Defines ;------------------ ;XXXXXXXXXXXXXXXXXXXXXXXX KeyBoard XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX .flag KEYB_DATA, P1.5 ; AT Keyboard data (change this for your hardware) .flag KEYB_CLOCK, P3.2 ; AT Keyboard Clock (change this for your hardware) ; This 2 pins should be connected to the keyboard crresponded pins with an 4K7 Pullup. ; The keyboard also needs GND and +5V. .equ KB_LSHIFT, 0x12 .equ KB_RSHIFT, 0x59 .equ KB_CTRL, 0x14 .equ KB_ALT, 0x11 .equ KB_CAPS, 0x58 .equ KB_SCROLL, 0x7E .equ KB_NUML, 0x77 .equ KB_TAB, 0x0D .equ KB_REL, 0xF0 .equ KB_EXT, 0xE0 .equ KB_PAUSE, 0xE1 ; For the stauts flags (KB_STATS) .equ CAPS, 0x01 .equ NUML, 0x02 .equ SCROLL, 0x04 .equ SHIFT, 0x08 .equ ACK, 0x10 .equ CTRL, 0x20 .equ ALT, 0x40 .equ RELEASE, 0x80 ; For the stauts flags 2 (KB_OK) .equ PAUSED, 0x40 .equ EXTENDED, 0x80 ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ;--------------------- ; Keyboard Routines: ;--------------------- ;************************************* ; WaitKB: Wait for keypress ;************************************* WaitKB: acall Check_Keyb jnc WaitKB ret ;************************************* ; InitKeyb: c=1 if ACK OK ;************************************* CheckACK: mov a, KB_STATS mov c, acc.4 clr acc.4 mov KB_STATS, a ret ;************************************* ; InitKeyb: ;************************************* InitKeyb: mov KB_TEMP, #0 mov KB_OK, #0 mov r1, #0xFF acall Write_Keyb acall Check_Keyb acall CheckACK jnc InitKeyb mov r1, #0xF4 ; Enable acall Write_Keyb acall Check_Keyb acall CheckACK jnc KeybErr mov r1, #0xF3 ; Set Typematic acall Write_Keyb acall Check_Keyb acall CheckACK jnc KeybErr mov r1, #0x00 ; Typematic = 250 ms / 30 cps acall Write_Keyb acall Check_Keyb acall CheckACK jnc KeybErr mov KB_OK, #1 mov KB_STATS, #2 ; Num Lock ON ;************************************* ; Keyb_Leds: Set KB_STATS as leds ;************************************* Keyb_Leds: mov r1, #0xED ; Set Leds acall Write_Keyb acall Check_Keyb acall CheckACK jnc KeybErr mov r1, KB_STATS acall Write_Keyb acall Check_Keyb acall CheckACK KeybErr: ret ;************************************* ; Zero2One: Wait for 0 to 1 on kb ; clock line, read the kb data line ; and shift right the bit to acc.7 ;************************************* Zero2One: jnb KEYB_CLOCK, * jb KEYB_CLOCK, * mov c, KEYB_DATA rrc a ret ;************************************* ; Check_Keyb: Check to see if any key ; are pressed or release, returns ; ASCII codes on KB_DATA, or 1 for ; special keys, 2 for same special ; with shift. Return also the scan ; code on KB_SCAN. ; Special Keys are basicaly all non ; printable keys. See the table below ; all 1 and 2 returned are special keys ;************************************* Check_Keyb: setb KEYB_DATA setb KEYB_CLOCK ; CLOCK & DATA high = Idle Pos mov r0, #50 CheckAgain: jnb KEYB_CLOCK, KeyHit djnz r0, CheckAgain ; check r0 times sjmp KeyEnd KeyHit: jnb KEYB_DATA, KeyHit2 ; Start bit must be 0 KeyEnd: clr KEYB_CLOCK ; disable keyb clr c ; c=0 = no keypress ret KeyHit2: mov r0, #8 ; 8 bits clr a KeyHit3: acall Zero2One djnz r0, KeyHit3 mov r1, a clr a acall Zero2One ; Parity bit acall Zero2One ; Stop bit ; acc.7 = stop, acc.6 = parity clr KEYB_CLOCK mov a, KB_TEMP jz NoIgnore dec KB_TEMP ; Igonre pause scans sjmp ChkKbEndNC NoIgnore: mov KB_SCAN, r1 cjne r1, #0xFA, NoKbACK orl KB_STATS, #ACK sjmp ChkKbEndNC NoKbACK: cjne r1, #KB_PAUSE, NoKbPause mov KB_TEMP, #7 ; Ignore next 7 scans mov a, KB_OK cpl acc.6 mov KB_OK, a sjmp ChkKbEndNC NoKbPause: cjne r1, #KB_EXT, NoKbExt orl KB_OK, #EXTENDED sjmp ChkKbEndNC NoKbExt: cjne r1, #KB_REL, NoRelease orl KB_STATS, #RELEASE sjmp ChkKbEndNC NoRelease: ; Test Num lock, if pressed toggle led cjne r1, #KB_NUML, NoNumLock mov a, KB_STATS jnb acc.7, ChkKbEndNC cpl acc.1 clr acc.7 mov KB_STATS, a acall Keyb_Leds sjmp ChkKbEndNC NoNumLock: ; Test Caps lock, if pressed toggle led cjne r1, #KB_CAPS, NoCapsLock mov a, KB_STATS jnb acc.7, ChkKbEndNC cpl acc.2 clr acc.7 mov KB_STATS, a acall Keyb_Leds sjmp ChkKbEndNC NoCapsLock: ; Test Scroll lock, if pressed toggle led cjne r1, #KB_SCROLL, NoScrollLock mov a, KB_STATS jnb acc.7, ChkKbEndNC cpl acc.0 clr acc.7 mov KB_STATS, a acall Keyb_Leds ChkKbEndNC: clr c ret NoScrollLock: ; Test L & R shifts, set bit if pressed, clear on release cjne r1, #KB_LSHIFT, NoShift1 ShiftOK: mov a, KB_STATS jbc acc.7, ShiftRel setb acc.3 ; not releasing, so Set SHIFT bit sjmp ShiftEnd ShiftRel: clr acc.3 ; releasing, so Clear SHIFT bit ShiftEnd: mov KB_STATS, a sjmp ChkKbEndNC NoShift1: cjne r1, #KB_RSHIFT, NoShift sjmp ShiftOK NoShift: cjne r1, #KB_CTRL, NoCtrl mov a, KB_STATS jbc acc.7, CtrlRel setb acc.5 ; not releasing, so Set CTRL bit sjmp CtrlEnd CtrlRel: clr acc.5 ; releasing, so Clear SHIFT bit CtrlEnd: mov KB_STATS, a sjmp ChkKbEndNC NoCtrl: cjne r1, #KB_ALT, NoAlt mov a, KB_STATS jbc acc.7, AltRel setb acc.6 ; not releasing, so Set ALT bit sjmp AltEnd AltRel: clr acc.6 ; releasing, so Clear ALT bit AltEnd: mov KB_STATS, a sjmp ChkKbEndNC NoAlt: mov a, KB_STATS ; Releasing key test jnb acc.7, NoRel2 clr acc.7 ; if releasing > clear mov KB_STATS, a ; rel bit on KB_STATS clr c ; and do nothing ret NoRel2: mov a, KB_OK ; Extended key test jnb acc.7, KbChars clr acc.7 ; if Extended > clear mov KB_OK, a ; EXT bit on KB_OK clr c ; and do nothing ret KbChars: mov dptr, #KbScanCodes mov a, KB_STATS jnb acc.2, TestShift jb acc.3, KbChkOK mov a, r1 movc a, @a+dptr mov r0, a subb a, #97 jc KbChkOK mov a, r0 subb a, #123 jnc KbChkOK mov dptr, #KbScanCodes2 ; if (a to z) & Caps > table 2 sjmp KbChkOK TestShift: jnb acc.3, KbChkOK mov dptr, #KbScanCodes2 ; with shift table 2 KbChkOK: mov a, r1 movc a, @a+dptr mov KB_DATA, a setb c ret ;************************************* ; Zero2One2: Wait for high to low in ; kb clock line ;************************************* Zero2One2: jnb KEYB_CLOCK, * jb KEYB_CLOCK, * ret ;************************************* ; Write_Keyb: Send r1 to the kb ;************************************* Write_Keyb: mov r0, #8 ; 8 bits to receive clr KEYB_CLOCK ; break the Keyboard mov r7, #0x00 ; some delay (safety reasons) _WKwait:djnz r7, _WKwait clr KEYB_DATA ; request to send setb KEYB_CLOCK ; enable the Keyboard acall Zero2One2 ; Start Bit mov a, r1 ; Data Bits TxData: rrc a mov KEYB_DATA, c acall Zero2One2 djnz r0, TxData mov a, r1 ; calculate parity bit mov c, psw.0 ; this is Even parity cpl c ; and Keyboard needs Odd parity mov KEYB_DATA, c ; send parity bit acall Zero2One2 setb KEYB_DATA ; send stop bit acall Zero2One2 acall Zero2One2 mov c, KEYB_DATA ; get ACK bit clr KEYB_CLOCK ; stop the keyboard ret ;************************************************************************* ; Main Routine: Example of kb usage ;************************************************************************* Start: acall InitKeyb mov a, KB_OK jz KBNotOK Loop: acall Check_Keyb jnc Loop mov a, KB_SCAN cjne a, #0x71, NoCtrlAltDel ; Check for extended Del mov a, KB_STATS jnb acc.5, NoCtrlAltDel ; Check for Ctrl jnb acc.6, NoCtrlAltDel ; Check for Alt ljmp Start ; If Ctrl+Alt+Del Reset NoCtrlAltDel: mov a, KB_DATA cjne a, #1, ChkEsp2 ; Here handle Especial Keys mov a, KB_SCAN cjne a, #5, NoF1Key ; Do something here for F1 NoF1Key: cjne a, #6, NoF2Key ; Do something here for F2 NoF2Key: cjne a, #4, NoF3Key ; Do something here for F1 NoF3Key: sjmp Loop ChkEsp2: cjne a, #2, NoEsp ; Here handle Shift + Especial Keys mov a, KB_SCAN cjne a, #5, NoShfF1Key ; Do something here for Shift + F1 NoShfF1Key: sjmp Loop NoEsp: ; Rest of prgram sjmp Loop ; last 262 addr of code mem with scan codes tables .org 0x1EF8 KbScanCodes: ; Keyboard Scancodes ; ?, F9, ?, F5, F4, F1, F2, F12, ?, F10, F8, F6, F4, TAB, ~ .db 0, 1 , 0, 1 , 1 , 1 , 1 , 1 , 0, 1 , 1 , 1 , 1 , 1 , '~' ; ?, ?,Lalt,Lshf, ?,Lctr, Q , ! , ?, ?, ?, Z , S , A , W , @ .db 0, 0, 0 , 0 , 0, 0 , 'q', '1', 0, 0, 0, 'z', 's', 'a', 'w', '2' ; ?, ?, C , X , D , E , $ , # , ?, ?, " ", V , F , T , R .db 0, 0, 'c', 'x', 'd', 'e', '4', '3', 0, 0, ' ', 'v', 'f', 't', 'r' ; % , ?, ?, N , B , H , G , Y , ^ , ?, ?, ?, M , J , U , & .db '5', 0, 0, 'n', 'b', 'h', 'g', 'y', '6', 0, 0, 0, 'm', 'j', 'u', '7' ; * , ?, ?, < , K , I , O , ) , ( , ?, ?, > , ? , L , : , P .db '8', 0, 0, ',', 'k', 'i', 'o', '0', '9', 0, 0, '.', '/', 'l', ';', 'p' ; _ , ?, ?, ?, " , ?, { , + , ?, ?,Caps,Rshf,Entr, } , ?, | .db '-', 0, 0, 0, ''', 0, '[', '=', 0, 0, 0 , 0 , 1 , ']', 0, 92 ; ?, ?, ?, ?, ?, ?, ?, ?,BkSp, ?, ?, 1 , ?, 4 , 7 , ?, ?, ?, 0 .db 0, 0, 0, 0, 0, 0, 0, 0, 1 , 0, 0, '1', 0, '4', '7', 0, 0, 0, '0' ; . , 2 , 5 , 6 , 8 , ESC,Numl, F11, + , 3 , - , * , 9 ,Scrl .db '.', '2', '5', '6', '8', 1 , 0 , 1 , '+', '3', '-', '*', '9', 0 ; ?, ?, ?, ?, F7 .db 0, 0, 0, 0, 1 KbScanCodes2: ; Keyboard Scancodes with shift ; ?, F9, ?, F5, F4, F1, F2, F12, ?, F10, F8, F6, F4, TAB, ~ .db 0, 2 , 0, 2 , 2 , 2 , 2 , 2 , 0, 2 , 2 , 2 , 2 , 2 , '`' ; ?, ?,Lalt,Lshf, ?,Lctr, Q , ! , ?, ?, ?, Z , S , A , W , @ .db 0, 0, 0 , 0 , 0, 0 , 'Q', '!', 0, 0, 0, 'Z', 'S', 'A', 'W', '@' ; ?, ?, C , X , D , E , $ , # , ?, ?, " ", V , F , T , R .db 0, 0, 'C', 'X', 'D', 'E', '$', '#', 0, 0, ' ', 'V', 'F', 'T', 'R' ; % , ?, ?, N , B , H , G , Y , ^ , ?, ?, ?, M , J , U , & .db '%', 0, 0, 'N', 'B', 'H', 'G', 'Y', '^', 0, 0, 0, 'M', 'J', 'U', '&' ; * , ?, ?, < , K , I , O , ) , ( , ?, ?, > , ? , L , : , P .db '*', 0, 0, '<', 'K', 'I', 'O', ')', '(', 0, 0, '>', '?', 'L', ':', 'P' ; _ , ?, ?, ?, " , ?, { , + , ?, ?,Caps,Rshf,Entr, } , ?, | .db '_', 0, 0, 0, '"', 0, '{', '+', 0, 0, 0 , 0 , 2 , '}', 0, '|' ; ?, ?, ?, ?, ?, ?, ?, ?,BkSp, ?, ?, 1 , ?, 4 , 7 , ?, ?, ?, 0 .db 0, 0, 0, 0, 0, 0, 0, 0, 2 , 0, 0, '1', 0, '4', '7', 0, 0, 0, '0' ; . , 2 , 5 , 6 , 8 , ESC,Numl, F11, + , 3 , - , * , 9 ,Scrl .db '.', '2', '5', '6', '8', 2 , 0 , 2 , '+', '3', '-', '*', '9', 0 ; ?, ?, ?, ?, F7 .db 0, 0, 0, 0, 2