Faster keyboard scan code detection in 8086 assembly

心不动则不痛 提交于 2020-01-05 03:31:29

问题


Is it possible to detect and collect keyboard makes and brakes faster than just reading from hardware port 60h?

Whenever I press a key, let's say the 'W' key, then very quickly press another key, the break code for the 'W' key is still returned by port 60h.

In the game i am writing, this has the effect of locking the player sprite in place when a user tries to quickly change direction.

I have tried using int 16h function 01h along with int 16h function 00, but it's very choppy and slow compared to port 60h.

Here's my input code using port 60h. I just pass a scancode into bp. All my procedures that require user input check the scancode in bp.

HANDLE_INPUT PROC

;CLEARS THE KEYBOARD TYPEHEAD BUFFER AND COLLECTS A SCANCODE 

;ALTERS BP

    push ax
    push es

    mov ax, 40h                
    mov es, ax                  ;access keyboard data area via segment 40h
    mov WORD PTR es:[1ah], 1eh  ;set the kbd buff head to start of buff
    mov WORD PTR es:[1ch], 1eh  ;set the kbd buff tail to same as buff head
                                ;the keyboard typehead buffer is now cleared
    xor ah, ah
    in al, 60h                  ;al -> scancode
    mov bp, ax                  ;bp -> scancode, accessible globally   

    pop es
    pop ax
    ret


HANDLE_INPUT ENDP

And here's the alternate version using int 16h, doesn't work nearly as well as the above version that uses port 60h.

HANDLE_INPUT PROC

;COLLECTS A SCANCODE 

;ALTERS BP

    push ax

    xor bp, bp    ;clear out bp
    mov ah, 1     ;Function 1, check key status.
    int 16h       ;Is a key ready? 
    jz NO_KEY     ;If zf cleared, then no.
    xor ah, ah    ;Otherwise, a key is waiting.
    int 16h       ;ah -> scancode
    xor al, al    
    xchg al, ah   ;ax -> scancode
    mov bp, ax    ;bp -> scancode, accessible globally


NO_KEY:

    pop ax
    ret


HANDLE_INPUT ENDP

回答1:


To answer my own question, scancodes provided via port 60h were not actually too slow, they were too fast.

In the following example given in my question: "Whenever I press a key, let's say the 'W' key, then very quickly press another key, the break code for the 'W' key is still returned by port 60h."

I thought the reason port 60h still returned the break code for the 'W' was due to the keyboard controller not having enough time to register the fact that I had struck a new key.

Actually, I was pressing the other key first, and the make code for the key was indeed being returned. Then, a split second later, my finger lifted from the 'W' key overwriting the byte returned by port 60h with the 'W' break code.

The solution: Only honor break codes if they correspond with the make code already stored in bp.

New HANDLE_INPUT procedure, now working much better:

HANDLE_INPUT PROC

;CLEARS THE KEYBOARD TYPEHEAD BUFFER AND COLLECTS A SCANCODE 

;ALTERS BP

    push ax
    push bx
    push es

    mov ax, 40h                
    mov es, ax                  ;access keyboard data area via segment 40h
    mov WORD PTR es:[1ah], 1eh  ;set the kbd buff head to start of buff
    mov WORD PTR es:[1ch], 1eh  ;set the kbd buff tail to same as buff head
                                ;the keyboard typehead buffer is now cleared
    xor ah, ah
    in al, 60h                  ;al -> scancode
    test al, 80h                ;Is a break code in al?
    jz ACCEPT_KEY               ;If not, accept it. 
                                ;If so, check to see if it's the break code
                                ;that corresponds with the make code in bp.
    mov bx, bp                  ;bx -> make code   
    or bl, 80h                  ;change make code into it's break code  
    cmp bl, al                  ;Do the new and old break codes match?
    je ACCEPT_KEY               ;If so, accept the break code.
    pop es                      ;If not, bp retains old make code.
    pop bx
    pop ax
    ret

ACCEPT_KEY: 
    mov bp, ax                  ;bp -> scancode, accessible globally

    pop es
    pop bx
    pop ax
    ret


HANDLE_INPUT ENDP


来源:https://stackoverflow.com/questions/47786199/faster-keyboard-scan-code-detection-in-8086-assembly

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!