Keyboard ISR design
Keyboard ISR design
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
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
Re:Keyboard ISR design
Yes, the most obvious solution (which somebody probably patented in the US, but here she goes):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.
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
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.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?
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.
which appAnd when i have multitasking, how will i make it know witch app to "send" it to?
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
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.And if i make for example a game, shoots with CTRL and jumps with Space+LeftArrow, how can i dectect "hard" combinations like that?
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
Re:Keyboard ISR design
Here's my simple keyboard, it's just a temp for testing:
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.
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
This was from my gameOS, only needed keyboard for top score etc.
\\\\||////
(@@)
ASHLEY4.
Re:Keyboard ISR design
hehe, thats what i call bad spelling..witch app
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..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 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
Re:Keyboard ISR design
Yes i have made it smaller, sin i gave it to you.
\\\\||////
(@@)
ASHLEY4.
\\\\||////
(@@)
ASHLEY4.
Re:Keyboard ISR design
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.
But i only works when i make some chars/spaces before i press enter...
is seems like my getcursorxy function sucks:
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:
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
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
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
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
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
Re:Keyboard ISR design
Y not ask ABBA, a great Swedish band ? javascript:grin() .
\\\\||////
(@@)
ASHLEY4.
\\\\||////
(@@)
ASHLEY4.
-
- Member
- Posts: 1600
- Joined: Wed Oct 18, 2006 11:59 am
- Location: Vienna/Austria
- Contact:
Re:Keyboard ISR design
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.
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
BlueillusionOS iso image
Re:Keyboard ISR design
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.
/ Christoffer
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.
So how should i do it? I don?t want to "cheat", by having the x and y values in vars..works great in the middle, but denies working in the edges.
/ Christoffer
-
- Member
- Posts: 1600
- Joined: Wed Oct 18, 2006 11:59 am
- Location: Vienna/Austria
- Contact:
Re:Keyboard ISR design
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?
2. What is this setcursorxy function doing? Setting the hardwarecursor?
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
BlueillusionOS iso image
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Keyboard ISR design
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 ?
- 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 ?
Re:Keyboard ISR design
No. The software running on my OS will have complete controll over the PC, running as ring 0.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 ?
Do you have a nice math formula for me?- you're re-inventing the DIVision by substractions
/ Christoffer
Re:Keyboard ISR design
It was not ment to be snide, you know it was a joke, as in "ABBA" knows a lot about keyboards.@ASHLEY: snide remarks aren't solving problems.
Programming should be fun.
\\\\||////
(@@)
ASHLEY4.
Re:Keyboard ISR design
They may be masters at os deving for all we know.. ;D
Re:Keyboard ISR design
One of my favourite rules: If it's a nail, use a hammer. If it's a screw, use a screwdriver.bubach wrote:Do you have a nice math formula for me?- you're re-inventing the DIVision by substractions
If what you're wanting to do is a division, use DIV.
Every good solution is obvious once you've found it.