Keyboard ISR design

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
User avatar
bubach
Member
Member
Posts: 1223
Joined: Sat Oct 23, 2004 11:00 pm
Location: Sweden
Contact:

Keyboard ISR design

Post by bubach »

Hello.
I have written a simple keyboard ISR that already, after just normal and shift keymaps, looks like ****... (spaghetti)
Is there a simple way to check for all shift, alt, ctrl versions (without 500 "cmp" and "jne"/"je")? :-)
It prints the char directly to screen after puting the char in one db var and the scan code in another.

The simplest possible scenario: My "shell" doesen?t want the char for a while, then after doing some things it will start listening for keypresses again, how will i determine if the key in the buffer is a new or old one?

And when i have multitasking, how will i make it know witch app to "send" it to?

And if i make for example a game, shoots with CTRL and jumps with Space+LeftArrow, how can i dectect "hard" combinations like that?

I really needs some ideas here....
thanks in advance..

/ Christoffer
"Simplicity is the ultimate sophistication."
http://bos.asmhackers.net/ - GitHub
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:Keyboard ISR design

Post by Candy »

bubach wrote: I have written a simple keyboard ISR that already, after just normal and shift keymaps, looks like ****... (spaghetti)
Is there a simple way to check for all shift, alt, ctrl versions (without 500 "cmp" and "jne"/"je")? :-)
It prints the char directly to screen after puting the char in one db var and the scan code in another.
Yes, the most obvious solution (which somebody probably patented in the US, but here she goes):

You make an array containing shift/alt/caps keypresses. Then you do not use cmp/jmp (which is unpredictable and thus also slow), you use an index.

Try:

Code: Select all

getkeycode:
  // call as getkeycode(int keycode, int shiftaltcaps) or first push shiftaltcaps, then keycode, then call
xor ebx, ebx
mov bl, [esp+4]
mov bh, [esp+8]
mov al, byte [keytable + ebx]
ret
The simplest possible scenario: My "shell" doesen?t want the char for a while, then after doing some things it will start listening for keypresses again, how will i determine if the key in the buffer is a new or old one?
By having a FIFO for it, which isn't a structure taught at school but very important. FIFO is like a queue, you always add to the front, and you remove from the back (conversely, you can swap the names front and back and keep some teachers your friend). The point why a FIFO isn't a queue is that a queue should never block. A fifo might block and be full.

Using this stuff, you can make a circular buffer with a write and a read pointer. You can lock both of them separately, making this good for multiprocessor systems (watch out for cache line conflicts! Try making the FIFO at least 256bytes, or preferably 4k-8k). You write at the write pointer and you read at the read pointer. If they are equal, the buffer is empty. If the write pointer is just before the read pointer, or the write pointer is at the absolute end and the read pointer at the absolute start (the combination of which is equivalent to doing (read-write) % count) it's full.

You put stuff in the buffer from the kernel-side of the code and you can read it out from the user-side. Notify the user if it's sleeping on the input that there's input, and that rounds it up for the kernel side.

The user side reads from the FIFO until it's empty, and if the function definition defines you should wait for more, wait.
And when i have multitasking, how will i make it know witch app to "send" it to?
which app

the app you send it to has the focus. You can timestamp all input items to be able to work out the exact order in which things went, so all keypresses arrive where the user expects them to. You can also not do that but just assume they arrive at the current app, or just plain ignore those where you don't know where to send them.

Windows and Linux are examples of the latter type. AtlantisOS of course tries to do the first :)
And if i make for example a game, shoots with CTRL and jumps with Space+LeftArrow, how can i dectect "hard" combinations like that?
These are normally not handled by the keyboard input API, but by a separate game-type input layer. This layer keeps a pressed-state for each key and offers the userlevel app a chance to just ask for a key being pressed, or a list of pressed keys. This way, these applications can use space-left for jumping left and ctrl-space-left for shooting while jumping left.

Note that most keyboards have a hardware limitation on the amount of keys they can detect at a time, my Compaq keyboard being the most crappy at that. If you type a space and an O at the same time an I comes out with a " on it.

HTH, Candy
ASHLEY4

Re:Keyboard ISR design

Post by ASHLEY4 »

Here's my simple keyboard, it's just a temp for testing:

Code: Select all

key_board:
                                                     ; Push registers
        pushad
        cli
        cld
        xor eax,eax
        in    AL,60h
        cmp   [game_write],0
        jne   write_text
        mov   BX,AX
        and   BX,007Fh            ; switch high bit of BX to zero
        and   AL,80h                ; check high bit of port value
        jz    Press
Release:                              ; high bit = 1: "release" code
        mov   [KeyDown+bx],00h                  
                                      ; write 00 to "down" array element
        jmp   Done
Press:                             ; high bit = 0: "press" code
        mov   [KeyDown+bx],01h        ; write 01 to "down" array element
        jmp   Done
write_text:
        cmp   al,128                          ; if below 128, then there is a key
   jae   nokey

   mov   edi,eax
        mov   al,[edi+normal_keymap]
next3:
        mov   [keybuffer],al
   jmp   nokey
Done:
        in    AL,61h                                ; read port 61h, system ctrl port
        mov   AH,AL                                 ; save value to AH
        or    AL,80h                                ; set top bit to "1" - reset kbd
        out   61h,AL                                ; write out value to port
        xchg  AH,AL                                 ; put original value back into AL
        out   61h,AL                                ; rewrite original value in AL
nokey:
        mov   AL,20h                                ; generate End of Interrupt
        out   20h,AL
        sti
        popad

        ret
;*********************************************************
game_write    db 0
keybuffer       db 0
KeyDown       rb 128 
If the var "game_write" is not 0 , then the keyboard is a normal (simple) keyboard, but if it's 0 then you can do multit keypress for game's etc.
This was from my gameOS, only needed keyboard for top score etc.

\\\\||////
(@@)
ASHLEY4.
User avatar
bubach
Member
Member
Posts: 1223
Joined: Sat Oct 23, 2004 11:00 pm
Location: Sweden
Contact:

Re:Keyboard ISR design

Post by bubach »

witch app
hehe, thats what i call bad spelling.. :-)
You make an array containing shift/alt/caps keypresses. Then you do not use cmp/jmp (which is unpredictable and thus also slow), you use an index.
i allready use this technic (i think that it?s slow anyway..), but for as many multiple keypresses as possible at the same time i would have ~500 cmp?s anyway.. ;)
i got 4 or 5 to check both left and right shifts for presses up/down and then i will have to add a "couple" more to check caps/num/scroll -lock...
short jumps just won?t do it anymore.. :(

i had a teacher that learned us FIFO.. :)

I?ll be back when i?ve doen some thinking about what you just said. ;)

i?ll have a look on your code ASHLEY4, it looks like mine but with about 40 deleted rows.. ::)

/ Christoffer
"Simplicity is the ultimate sophistication."
http://bos.asmhackers.net/ - GitHub
ASHLEY4

Re:Keyboard ISR design

Post by ASHLEY4 »

Yes i have made it smaller, sin i gave it to you.

\\\\||////
(@@)
ASHLEY4.
User avatar
bubach
Member
Member
Posts: 1223
Joined: Sat Oct 23, 2004 11:00 pm
Location: Sweden
Contact:

Re:Keyboard ISR design

Post by bubach »

I had a look one another swedish os and it was much better organized. So now i got my code much more readable.

To a completly diffrent problem:

When testing the keyboard ISR, i wrote this to handle enter presses.

Code: Select all

; Make a new line.
;-----------------------------------
new_line:
                push    edx
                push    eax

                call    getcursorxy
              ;  movzx   eax, bx
              ;  call    print_hex32

                cmp     dl, 0x18
                jb      .newline

                call    scroll_up   ; changes row by itself (without getcursorxy)
                jmp     .done

       .newline:
                call    getcursorxy
                mov     dh, 0x00
                inc     dl
                call    setcursorxy

          .done:
                pop     eax
                pop     edx
                ret
But i only works when i make some chars/spaces before i press enter...

is seems like my getcursorxy function sucks:

Code: Select all

; Get the cursor pos. OUT: DH = X   DL = Y
;------------------------------------------
getcursorxy:
                push    eax
                push    ebx

                call    getcursor

                xor     dx, dx
          .loop:
                sub     bx, 80
                inc     dl
                cmp     bx, 80
                ja      .loop

                mov     dh, bl

                pop     ebx
                pop     eax
                ret
i have "print_hex32":ed the result of getcursorxy and it works if the col is not zero.
if the cursor is on the first location on a row it gives me position 0x50 on the previous row.. and by doing this:

Code: Select all

                call    getcursorxy
                mov     dh, 0x00
                inc     dl
                call    setcursorxy
it will stand still on the same row..
i tried to change my getcursorxy function, but then some other things won?t work, like the check to see if i am at the end of a row.

any suggestions on how to fix it?

/ Christoffer
"Simplicity is the ultimate sophistication."
http://bos.asmhackers.net/ - GitHub
ASHLEY4

Re:Keyboard ISR design

Post by ASHLEY4 »

Y not ask ABBA, a great Swedish band ? javascript:grin() .
\\\\||////
(@@)
ASHLEY4.
distantvoices
Member
Member
Posts: 1600
Joined: Wed Oct 18, 2006 11:59 am
Location: Vienna/Austria
Contact:

Re:Keyboard ISR design

Post by distantvoices »

Christoffer, aren't you trying to oversimplify things a bit?

First commandment: Thou shalt never stay too long in the ISR.

Never forget about this and have the ISR just fetch scan codes and stuff them into the FIFO. Some Interruptible thread shall fetch the scancodes and produce readable input/output from them. That's merely a table look up.

With your current approach, you'll set yourself into the fire of devils den, believe me.

concerning x,y: I know, I know, memory access *is* slow, but why don't you just store actual x n y values in some memory location and fetch/update them at needs? with them at hands you can send the hardware cursor where ever you want to send it to - as long as it remains on screen of couse *gg*.

what is this 'getcursor' function doing?

What is this loop in getcursorxy good for? calculating the y value? Where do you get x then? I bet this causes quite some headaches especially when you encounter corner-values. works great in the middle, but denies working in the edges.

Pls put at least some crucial comments around the code to ease debugging. Tack sa mycket :-)

@ASHLEY: snide remarks aren't solving problems.
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
User avatar
bubach
Member
Member
Posts: 1223
Joined: Sat Oct 23, 2004 11:00 pm
Location: Sweden
Contact:

Re:Keyboard ISR design

Post by bubach »

I don?t think that the old band members of ABBA knows the answer.. :)

This isn?t in the ISR it?s in another function, monitor_echo...
Actually the ISR calls monitor_echo before it ret?s, but that is temporary.

The function getcursor, gets the "real" cursor pos., not the x/y values.
The function getcursorxy, checks if the value is above 80, if it is, then it removes 80 from the org. value and add 1 to a row counter. If it is not, then it returns the restoring value and the value in the row counter, wich makes the x and y values.
works great in the middle, but denies working in the edges.
So how should i do it? I don?t want to "cheat", by having the x and y values in vars..

/ Christoffer
"Simplicity is the ultimate sophistication."
http://bos.asmhackers.net/ - GitHub
distantvoices
Member
Member
Posts: 1600
Joined: Wed Oct 18, 2006 11:59 am
Location: Vienna/Austria
Contact:

Re:Keyboard ISR design

Post by distantvoices »

1. by keeping x and y separate - well, it is your memory and your program, so what say I. You'd avoid this looping. One call less. But either way, your program, your choice.

2. What is this setcursorxy function doing? Setting the hardwarecursor?
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Keyboard ISR design

Post by Pype.Clicker »

so, basically
- you're re-inventing the DIVision by substractions
- you're using slooooow I/Os instead of slow memory ops.

I suppose you have a really good reason to fetch the so-called "real" cursor pos rather than caching the last value you set, as it's certainly not the first time i see that on the forum and that i've tickled a few times before, already.

Now, your kernel could be arranged so that there's no chance something else that the console lib would be the only piece of code that sets the cursor position, no ?
User avatar
bubach
Member
Member
Posts: 1223
Joined: Sat Oct 23, 2004 11:00 pm
Location: Sweden
Contact:

Re:Keyboard ISR design

Post by bubach »

Now, your kernel could be arranged so that there's no chance something else that the console lib would be the only piece of code that sets the cursor position, no ?
No. The software running on my OS will have complete controll over the PC, running as ring 0.
- you're re-inventing the DIVision by substractions
Do you have a nice math formula for me?

/ Christoffer
"Simplicity is the ultimate sophistication."
http://bos.asmhackers.net/ - GitHub
ASHLEY4

Re:Keyboard ISR design

Post by ASHLEY4 »

@ASHLEY: snide remarks aren't solving problems.
It was not ment to be snide, you know it was a joke, as in "ABBA" knows a lot about keyboards.
Programming should be fun.

\\\\||////
(@@)
ASHLEY4.
User avatar
bubach
Member
Member
Posts: 1223
Joined: Sat Oct 23, 2004 11:00 pm
Location: Sweden
Contact:

Re:Keyboard ISR design

Post by bubach »

They may be masters at os deving for all we know.. ;D
"Simplicity is the ultimate sophistication."
http://bos.asmhackers.net/ - GitHub
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:Keyboard ISR design

Post by Solar »

bubach wrote:
- you're re-inventing the DIVision by substractions
Do you have a nice math formula for me?
One of my favourite rules: If it's a nail, use a hammer. If it's a screw, use a screwdriver.

If what you're wanting to do is a division, use DIV.
Every good solution is obvious once you've found it.
Post Reply