OSDev.org

The Place to Start for Operating System Developers
It is currently Fri Mar 29, 2024 8:33 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 49 posts ]  Go to page Previous  1, 2, 3, 4  Next
Author Message
 Post subject: Re: Keyboard decoder logic
PostPosted: Fri Feb 03, 2017 12:27 pm 
Offline
Member
Member
User avatar

Joined: Fri Aug 07, 2015 6:13 am
Posts: 1134
Schol-R-LEA wrote:
octacone wrote:
FusT wrote:
You may be going way too fast for the PS/2 controller


"Too fast" (working on this for past 2 weeks). :P


I think that FusT meant that your handler is going to fast, not the code development, and is saying that you need to insert a wait of some kind into the code.


:oops: Oh, code is going too fast! That is probably why it was getting stuck. By looking at some old PS/2 code I was able to read all the correct port values. Also I added some buffer waiting and now I can write and read just fine. My self-test keeps failing I assume that is because of what Sortie said.

Edit:
I keep getting 0x71 as a response when sending 0xAA command. That should not happen at all.

_________________
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader


Top
 Profile  
 
 Post subject: Re: Keyboard decoder logic
PostPosted: Sat Feb 04, 2017 4:12 am 
Offline
Member
Member
User avatar

Joined: Fri Aug 07, 2015 6:13 am
Posts: 1134
Hooray!
Attachment:
PS2andKeyboard.png
PS2andKeyboard.png [ 10.32 KiB | Viewed 2946 times ]

:wink: :-D 8)

After an entire night of bug haunting and writing my PS/2 controller, it is finally over. I can proudly say that I have one really solid PS/2 initialization sequence.
It was a rough ride, almost dropped it all cause of bug. Later I also found out that laptops will not allow me to use the second key set. My time was worth it. It is great when you code something and it pays off. Also I forgot to mention that I added like device types abstraction.

State machine hold in there, I am coming. It shouldn't take me more than a week to get it all sorted out.

_________________
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader


Top
 Profile  
 
 Post subject: Keyboard State Machine Logic
PostPosted: Sun Feb 05, 2017 6:02 am 
Offline
Member
Member
User avatar

Joined: Fri Aug 07, 2015 6:13 am
Posts: 1134
I have a question about that state machine you guys were talking about. How am I supposed to read for e.g 10 bytes when I can only get one per interrupt? One key press = one interrupt, how do I read multiple bytes when I only get one? It all has to happen inside one interrupt because imagine pressing right alt for three times just to get one event... From my point of view it is impossible to achieve. Also other guys that were suggesting multiple tables for each situation but what about when there are two situations? For e.g caps lock is on, number pad is on and I am holding shift?

_________________
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader


Top
 Profile  
 
 Post subject: Re: Keyboard State Machine Logic
PostPosted: Sun Feb 05, 2017 8:01 am 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
Hi,

octacone wrote:
I have a question about that state machine you guys were talking about. How am I supposed to read for e.g 10 bytes when I can only get one per interrupt? One key press = one interrupt, how do I read multiple bytes when I only get one? It all has to happen inside one interrupt because imagine pressing right alt for three times just to get one event... From my point of view it is impossible to achieve.


I answered that question the last time you asked it. Mostly, each time an IRQ occurs you receive one byte, and you use the current state and the received byte to determine which state to transition to next and if a whole scancode has been received.

octacone wrote:
Also other guys that were suggesting multiple tables for each situation but what about when there are two situations? For e.g caps lock is on, number pad is on and I am holding shift?


Imagine a "current mode" variable where bit 0 is used as a "with/without capslock" flag, bit 1 is used as a "with/without number lock" flag, bit 2 is used as a "with/without shift key" flag, etc.

Now imagine you convert (variable sized) scan-codes into your own (fixed sized 8-bit integer) key-code; and then did:
Code:
    table_entry = &lookup_table[current_mode << 8 | key_code];


This means that you can have a single lookup table for everything.

After that, you could also do:
Code:
    current_mode = (current_mode & table_entry->mode_mask) ^ table_entry->mode_reversed_flags;


This means that the lookup table can contain information to control/maintain the "current_mode" variable. Note that the "AND then XOR" thing allows the lookup table to clear bit/s, set bit/s, invert bit/s and leave bit/s unchanged; all without any branches or anything.

In that case (lookup table controls/maintains the "current_mode" variable) the keyboard driver's code doesn't really need to know/care what the lookup table uses each bit in the "current_mode" variable for. One lookup table (maybe for "International/English QWERTY") might use bit 0 for a "with/without AltGr" flag, and a different lookup table (maybe for "US Dvorak") might use bit 0 for "with/without capslock" flag.

However, you could design it is so that the lowest n bits of "current_mode" reflect the keyboard's LEDs; and have a "LED_mask" (that can be different for different keyboard layouts - e.g. loaded from a "keyboard layout file"). This allows you to do something like:

Code:
    old_mode = current_mode;
    current_mode = (current_mode & table_entry->mode_mask) ^ table_entry->mode_reversed_flags;
    if( ((old_mode ^ current_mode) & LED_mask) != 0) {
        // LEDs have changed
        set_LEDs(current_mode & LED_mask);
    }


That way, the keyboard driver doesn't need to know/care about how many LEDs there are or what they're used for (only the "keyboard layout file" would know/care).

With some trickery; most of the keyboard driver (everything except loading/parsing the "keyboard layout file") could probably be done with less than 30 lines of code, including full support for all possible keyboard layouts.

Please note that I'm not necessarily suggesting you should write a keyboard driver exactly like this. Mostly I'm using "keyboard code" as a way to trick you into learning a few programming techniques that could be beneficial for more than just keyboard . ;)


Cheers,

Brendan

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
 Post subject: Re: Keyboard State Machine Logic
PostPosted: Sun Feb 05, 2017 9:11 am 
Offline
Member
Member
User avatar

Joined: Fri Aug 07, 2015 6:13 am
Posts: 1134
Brendan wrote:
Hi,

octacone wrote:
I have a question about that state machine you guys were talking about. How am I supposed to read for e.g 10 bytes when I can only get one per interrupt? One key press = one interrupt, how do I read multiple bytes when I only get one? It all has to happen inside one interrupt because imagine pressing right alt for three times just to get one event... From my point of view it is impossible to achieve.


I answered that question the last time you asked it. Mostly, each time an IRQ occurs you receive one byte, and you use the current state and the received byte to determine which state to transition to next and if a whole scancode has been received.

octacone wrote:
Also other guys that were suggesting multiple tables for each situation but what about when there are two situations? For e.g caps lock is on, number pad is on and I am holding shift?


Imagine a "current mode" variable where bit 0 is used as a "with/without capslock" flag, bit 1 is used as a "with/without number lock" flag, bit 2 is used as a "with/without shift key" flag, etc.


Now imagine you convert (variable sized) scan-codes into your own (fixed sized 8-bit integer) key-code; and then did:
Code:
    table_entry = &lookup_table[current_mode << 8 | key_code];


This means that you can have a single lookup table for everything.

After that, you could also do:
Code:
    current_mode = (current_mode & table_entry->mode_mask) ^ table_entry->mode_reversed_flags;


This means that the lookup table can contain information to control/maintain the "current_mode" variable. Note that the "AND then XOR" thing allows the lookup table to clear bit/s, set bit/s, invert bit/s and leave bit/s unchanged; all without any branches or anything.

In that case (lookup table controls/maintains the "current_mode" variable) the keyboard driver's code doesn't really need to know/care what the lookup table uses each bit in the "current_mode" variable for. One lookup table (maybe for "International/English QWERTY") might use bit 0 for a "with/without AltGr" flag, and a different lookup table (maybe for "US Dvorak") might use bit 0 for "with/without capslock" flag.

However, you could design it is so that the lowest n bits of "current_mode" reflect the keyboard's LEDs; and have a "LED_mask" (that can be different for different keyboard layouts - e.g. loaded from a "keyboard layout file"). This allows you to do something like:

Code:
    old_mode = current_mode;
    current_mode = (current_mode & table_entry->mode_mask) ^ table_entry->mode_reversed_flags;
    if( ((old_mode ^ current_mode) & LED_mask) != 0) {
        // LEDs have changed
        set_LEDs(current_mode & LED_mask);
    }


That way, the keyboard driver doesn't need to know/care about how many LEDs there are or what they're used for (only the "keyboard layout file" would know/care).

With some trickery; most of the keyboard driver (everything except loading/parsing the "keyboard layout file") could probably be done with less than 30 lines of code, including full support for all possible keyboard layouts.

Please note that I'm not necessarily suggesting you should write a keyboard driver exactly like this. Mostly I'm using "keyboard code" as a way to trick you into learning a few programming techniques that could be beneficial for more than just keyboard . ;)


Cheers,

Brendan


Wow! This was very inspiring. I actually came up with something that could actually work very well if coded properly.
Attachment:
idea.png
idea.png [ 37.7 KiB | Viewed 2870 times ]

This way I wouldn't have to have tens of lookup tables. I can see that your are trying to get me deeper these into coding techniques. :D
But still, I don't get one thing... Doesn't matter how many times I read your state machine reply, I still don't get it. I don't get the part where I should see what key it was. Like okay I received 0xE0 but that is it, how do I know if it was alt gr or pause?
Attachment:
confused.png
confused.png [ 30 KiB | Viewed 2870 times ]

Also I never get pure 0xE0 it is more like other bytes for that key except 0xE0. :? :? :? :?

_________________
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader


Top
 Profile  
 
 Post subject: Re: Keyboard decoder logic
PostPosted: Sun Feb 05, 2017 11:02 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5103
octacone wrote:
Like okay I received 0xE0 but that is it, how do I know if it was alt gr or pause?

The answer is: you don't! You have to wait until the next time you receive a byte to figure out what it is.

The state machine is how you remember that you received 0xE0 last time, so if you receive 0x38 this time, it means AltGr instead of Alt.


Top
 Profile  
 
 Post subject: Re: Keyboard decoder logic
PostPosted: Sun Feb 05, 2017 11:25 am 
Offline
Member
Member
User avatar

Joined: Fri Aug 07, 2015 6:13 am
Posts: 1134
Octocontrabass wrote:
octacone wrote:
Like okay I received 0xE0 but that is it, how do I know if it was alt gr or pause?

The answer is: you don't! You have to wait until the next time you receive a byte to figure out what it is.

The state machine is how you remember that you received 0xE0 last time, so if you receive 0x38 this time, it means AltGr instead of Alt.


But that is the problem. In order to store that I would have to press that key X times to get it only once.
Also can you explain how is this possible. When I press right alt:
Attachment:
how.png
how.png [ 477 Bytes | Viewed 2843 times ]

That is what I get when I print raw scan code. But I can't figure out how to harvest all those scan codes from only one read.
Like this is what I do:
Code:
uint8_t scancode = Inportb(0x60);
   TTY_Put_Character('\n', 0x0F);
   TTY_Put_Hex(scancode, 0x0F);

See that "scancode" variable? How is that possible? How can it store all the scan codes but not allow me to read more than one?

_________________
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader


Top
 Profile  
 
 Post subject: Re: Keyboard decoder logic
PostPosted: Sun Feb 05, 2017 12:12 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5103
octacone wrote:
But that is the problem. In order to store that I would have to press that key X times to get it only once.

Why?


Top
 Profile  
 
 Post subject: Re: Keyboard decoder logic
PostPosted: Sun Feb 05, 2017 12:32 pm 
Offline
Member
Member
User avatar

Joined: Fri Aug 07, 2015 6:13 am
Posts: 1134
Octocontrabass wrote:
octacone wrote:
But that is the problem. In order to store that I would have to press that key X times to get it only once.

Why?

Attachment:
what.png
what.png [ 56.25 KiB | Viewed 2833 times ]

_________________
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader


Top
 Profile  
 
 Post subject: Re: Keyboard decoder logic
PostPosted: Sun Feb 05, 2017 12:44 pm 
Offline
Member
Member
User avatar

Joined: Sat Dec 27, 2014 9:11 am
Posts: 901
Location: Maadi, Cairo, Egypt
I think you are missing the concept of the PS/2 escape sequence. Some keys (like Right Alt, arrow keys, ...) use the same scancodes as other keys, except that they have an escape sequence before the make code and before the break code. For example, 0x47 is the numpad 7 key, and 0xE0 0x47 is the Home key. Now, software that is aware of the escape sequence can parse it to determine whether it was the numpad key or the Home key that was pressed. Older software, which is not aware of the escape sequence, wouldn't break due to the changes; and instead will always assume the Home key has been pressed.
Assuming a user presses and releases the home key, the scancodes sent to the PS/2 driver would look like:
Code:
0xE0 0x47 0xE0 0xC7

Now let's assume a user presses and releases the numpad 7 key:
Code:
0x47 0xC7


Get the picture? Some scancodes can be "prefixed" with sequences that somewhat change their meaning. There is another escape sequence that uses the value 0xE1, but I haven't implemented this yet, but you can search for it. :)

EDIT FOR CLARIFICATION: Notice that you can only read ONE byte on each IRQ. Based on the example above assuming the user pressed and released the Home key, you will receive a total of four IRQs for the four scancode bytes sent to your driver.

_________________
You know your OS is advanced when you stop using the Intel programming guide as a reference.


Top
 Profile  
 
 Post subject: Re: Keyboard decoder logic
PostPosted: Sun Feb 05, 2017 1:24 pm 
Offline
Member
Member
User avatar

Joined: Fri Aug 07, 2015 6:13 am
Posts: 1134
omarrx024 wrote:
I think you are missing the concept of the PS/2 escape sequence. Some keys (like Right Alt, arrow keys, ...) use the same scancodes as other keys, except that they have an escape sequence before the make code and before the break code. For example, 0x47 is the numpad 7 key, and 0xE0 0x47 is the Home key. Now, software that is aware of the escape sequence can parse it to determine whether it was the numpad key or the Home key that was pressed. Older software, which is not aware of the escape sequence, wouldn't break due to the changes; and instead will always assume the Home key has been pressed.
Assuming a user presses and releases the home key, the scancodes sent to the PS/2 driver would look like:
Code:
0xE0 0x47 0xE0 0xC7

Now let's assume a user presses and releases the numpad 7 key:
Code:
0x47 0xC7


Get the picture? Some scancodes can be "prefixed" with sequences that somewhat change their meaning. There is another escape sequence that uses the value 0xE1, but I haven't implemented this yet, but you can search for it. :)

EDIT FOR CLARIFICATION: Notice that you can only read ONE byte on each IRQ. Based on the example above assuming the user pressed and released the Home key, you will receive a total of four IRQs for the four scancode bytes sent to your driver.


Thanks!!!!!!!!!!!! =D> [-o< :lol:


Attachments:
1j11bh.jpg
1j11bh.jpg [ 20.27 KiB | Viewed 2805 times ]

_________________
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
Top
 Profile  
 
 Post subject: Re: Keyboard decoder logic
PostPosted: Sun Feb 05, 2017 2:51 pm 
Offline
Member
Member
User avatar

Joined: Tue Aug 02, 2016 1:52 pm
Posts: 286
Location: East Riding of Yorkshire, UK
octacone wrote:
Octocontrabass wrote:
octacone wrote:
But that is the problem. In order to store that I would have to press that key X times to get it only once.

Why?

Attachment:
what.png

Why is Travolta in your keyboard driver?

_________________
com.sun.java.swing.plaf.nimbus.InternalFrameInternalFrameTitlePaneInternalFrameTitlePaneMaximizeButtonWindowNotFocusedState
Compiler Development Forum


Top
 Profile  
 
 Post subject: Re: Keyboard decoder logic
PostPosted: Sun Feb 05, 2017 3:04 pm 
Offline
Member
Member

Joined: Tue Mar 04, 2014 5:27 am
Posts: 1108
matt11235 wrote:
Why is Travolta in your keyboard driver?


It could've been Homunculus Loxodontus, waiting for interrupts to arrive.


Top
 Profile  
 
 Post subject: Re: Keyboard decoder logic
PostPosted: Sun Feb 05, 2017 3:15 pm 
Offline
Member
Member
User avatar

Joined: Fri Aug 07, 2015 6:13 am
Posts: 1134
matt11235 wrote:
Attachment:
what.png

Why is Travolta in your keyboard driver?


Cause I feel the same as him. :P

alexfru wrote:
matt11235 wrote:
Why is Travolta in your keyboard driver?


It could've been Homunculus Loxodontus, waiting for interrupts to arrive.


That thing looks amazing, it is so good I can't even pronounce it's name. :D

_________________
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader


Top
 Profile  
 
 Post subject: Re: Keyboard decoder logic
PostPosted: Sun Feb 05, 2017 4:17 pm 
Offline
Member
Member
User avatar

Joined: Fri Aug 07, 2015 6:13 am
Posts: 1134
Finally after some time I am getting there. Really really proud because of what I've done. I have a bug doe, how am I supposed to handle an equal state?
For example: 0xE0 = backspace, also 0xE0 == state 2 trigger. Then I need "case 0x1D:" but it is inside the same state...
Attachment:
BugsEtc.png
BugsEtc.png [ 12.68 KiB | Viewed 2769 times ]

Code:
case 0:
      {
         switch(scancode)
         {
                                ....
            case 0xE0:
            {
               current_state = 1; // && is defined backspace trigger <--------
               break;
            }
            default:
            {
               return;
            }
         }
         break;
      }
case 1:
      {
         switch(scancode)
         {
                                ...
            case 0x1D:
            {
               current_state = 2; // && also pause pressed <--------
               break;
            }
            default:
            {
               return;
            }
         }   
         break;
      }

_________________
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 49 posts ]  Go to page Previous  1, 2, 3, 4  Next

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot], Gigasoft and 192 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group