Browse Source

Implemented basic key combination feature

Ofer Plesser 8 năm trước cách đây
mục cha
commit
eac8fa7999

+ 5 - 0
build_keyboard.mk

@@ -144,6 +144,11 @@ ifeq ($(strip $(MIDI_ENABLE)), yes)
 	SRC += $(QUANTUM_DIR)/process_keycode/process_midi.c
 endif
 
+ifeq ($(strip $(COMBO_ENABLE)), yes)
+    OPT_DEFS += -DCOMBO_ENABLE
+	SRC += $(QUANTUM_DIR)/process_keycode/process_combo.c
+endif
+
 ifeq ($(strip $(VIRTSER_ENABLE)), yes)
     OPT_DEFS += -DVIRTSER_ENABLE
 endif

+ 66 - 0
quantum/process_keycode/process_combo.c

@@ -0,0 +1,66 @@
+#include "process_combo.h"
+#include "print.h"
+
+// __attribute__ ((weak))
+// combo_t key_combos[] = {
+
+// };
+
+#define SEND_KEY(key) \
+do { \
+    register_code16(key); \
+    send_keyboard_report(); \
+    unregister_code16(key); \
+} while(0)
+
+
+#define ALL_COMBO_KEYS_ARE_DOWN (((1<<count)-1) == combo->state)
+static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *record) 
+{
+    uint8_t count = 0;
+    bool is_combo_key = false;
+    // bool combo_key_released = false;
+
+    // Count the number of combo keys
+    for (const uint16_t *key = combo->keys; COMBO_END != pgm_read_word(key); ++key, ++count);
+
+    for (uint8_t i = 0; i < count; ++i) {
+        uint16_t key = pgm_read_word(&combo->keys[i]);
+
+        if (key == keycode) {
+            is_combo_key = true;
+
+            if (record->event.pressed) {
+                combo->state |= (1<<i);
+            } else { // Combo key released
+                if (!combo->state) {
+                    // The combo was sent, no need to send released key
+                    return true;
+                }
+
+                combo->state &= ~(1<<i);
+                SEND_KEY(key);
+            }
+        }
+    }
+
+    if (ALL_COMBO_KEYS_ARE_DOWN) {
+        SEND_KEY(combo->action);
+        combo->state = 0;    
+    }
+
+    return is_combo_key;
+}
+
+
+bool process_combo(uint16_t keycode, keyrecord_t *record)
+{
+    bool is_combo_key = false;
+
+    for (int i = 0; i < NUM_ELEMS(key_combos); ++i) {
+        combo_t *combo = &key_combos[i];
+        is_combo_key |= process_single_combo(combo, keycode, record);
+    }    
+
+    return !is_combo_key;
+}

+ 25 - 0
quantum/process_keycode/process_combo.h

@@ -0,0 +1,25 @@
+#ifndef PROCESS_COMBO_H
+#define PROCESS_COMBO_H
+
+#include <stdint.h>
+#include "progmem.h"
+#include "quantum.h"
+
+
+typedef struct
+{
+    const uint16_t *keys;
+    uint16_t action;        
+    uint32_t state;
+} combo_t;
+
+
+#define COMBO_END 0
+#define NUM_ELEMS(a) (sizeof(a)/sizeof 0[a])
+
+
+extern combo_t key_combos[1];
+
+bool process_combo(uint16_t keycode, keyrecord_t *record);
+
+#endif

+ 3 - 0
quantum/quantum.c

@@ -113,6 +113,9 @@ bool process_record_quantum(keyrecord_t *record) {
 
   if (!(
     process_record_kb(keycode, record) &&
+  #ifdef COMBO_ENABLE
+    process_combo(keycode, record) &&
+  #endif
   #ifdef MIDI_ENABLE
     process_midi(keycode, record) &&
   #endif

+ 4 - 0
quantum/quantum.h

@@ -63,6 +63,10 @@ extern uint32_t default_layer_state;
 	#include "process_printer.h"
 #endif
 
+#ifdef COMBO_ENABLE
+	#include "process_combo.h"
+#endif
+
 #define SEND_STRING(str) send_string(PSTR(str))
 void send_string(const char *str);