Better key state tracking

We need to store the previous state of the keys, to figure out when a specific
key is released, as opposed to simply not being pressed. This is required for
layer keys such as `Mod` and `Fn` to work properly when there are more than one
of them on the keymap.

Without being able to tell when a key is released, we would not be able to turn
a layer off only when no layer key is held. Not easily, anyway: we'd have to
track the state of all layer keys... but then it is easier to just track them
all.

Thankfully, the memcpy at the end is fast, as it only needs to copy 70 bytes.

Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
This commit is contained in:
Gergely Nagy
2016-12-12 20:14:09 +01:00
parent 6aedaf7074
commit 265988ee25

View File

@@ -4,6 +4,9 @@
static uint8_t keyMasks[SLOT_COUNT][MAX_KEY_COUNT_PER_MODULE];
static uint8_t modifierState = 0;
static uint8_t prevLeftKeyStates[KEY_STATE_COUNT];
static uint8_t prevRightKeyStates[KEY_STATE_COUNT];
static inline __attribute__((always_inline)) uhk_key_t getKeycode(KEYBOARD_LAYOUT(layout), uint8_t slotId, uint8_t keyId)
{
if (keyId < MAX_KEY_COUNT_PER_MODULE) {
@@ -15,7 +18,7 @@ static inline __attribute__((always_inline)) uhk_key_t getKeycode(KEYBOARD_LAYOU
uhk_key_t k = layout[modifierState][slotId][keyId];
keyMasks[slotId][keyId] = modifierState;
if (k.raw == 0) {
if (k.type == UHK_KEY_TRANSPARENT) {
k = layout[0][slotId][keyId];
}
@@ -67,18 +70,32 @@ bool layerOff(uhk_key_t key) {
return false;
}
bool handleKey(uhk_key_t key, int scancodeIdx, usb_keyboard_report_t *report, uint8_t keyState) {
bool key_toggled_on (const uint8_t *prevKeyStates, const uint8_t *currKeyStates, uint8_t keyId) {
return (!prevKeyStates[keyId]) && currKeyStates[keyId];
}
bool key_is_pressed (const uint8_t *prevKeyStates, const uint8_t *currKeyStates, uint8_t keyId) {
return currKeyStates[keyId];
}
bool key_toggled_off (const uint8_t *prevKeyStates, const uint8_t *currKeyStates, uint8_t keyId) {
return (!currKeyStates[keyId]) && prevKeyStates[keyId];
}
bool handleKey(uhk_key_t key, int scancodeIdx, usb_keyboard_report_t *report, const uint8_t *prevKeyStates, const uint8_t *currKeyStates, uint8_t keyId) {
switch (key.type) {
case UHK_KEY_SIMPLE:
if (keyState) {
if (key_is_pressed (prevKeyStates, currKeyStates, keyId)) {
return pressKey (key, scancodeIdx, report);
}
break;
case UHK_KEY_LAYER:
if (keyState) {
return layerOn(key);
if (key_toggled_on (prevKeyStates, currKeyStates, keyId)) {
return layerOn (key);
}
if (key_toggled_off (prevKeyStates, currKeyStates, keyId)) {
return layerOff (key);
}
return layerOff(key);
break;
default:
break;
@@ -98,7 +115,7 @@ void fillKeyboardReport(usb_keyboard_report_t *report, const uint8_t *leftKeySta
uhk_key_t code = getKeycode(layout, SLOT_ID_RIGHT_KEYBOARD_HALF, keyId);
if (handleKey(code, scancodeIdx, report, rightKeyStates[keyId])) {
if (handleKey(code, scancodeIdx, report, prevRightKeyStates, rightKeyStates, keyId)) {
scancodeIdx++;
}
}
@@ -110,8 +127,11 @@ void fillKeyboardReport(usb_keyboard_report_t *report, const uint8_t *leftKeySta
uhk_key_t code = getKeycode(layout, SLOT_ID_LEFT_KEYBOARD_HALF, keyId);
if (handleKey(code, scancodeIdx, report, leftKeyStates[keyId])) {
if (handleKey(code, scancodeIdx, report, prevLeftKeyStates, leftKeyStates, keyId)) {
scancodeIdx++;
}
}
memcpy (prevLeftKeyStates, leftKeyStates, KEY_STATE_COUNT);
memcpy (prevRightKeyStates, rightKeyStates, KEY_STATE_COUNT);
}