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: Select all
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: Select all
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: Select all
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