diff options
Diffstat (limited to 'quantum/process_keycode')
| -rw-r--r-- | quantum/process_keycode/process_combo.c | 107 | ||||
| -rw-r--r-- | quantum/process_keycode/process_combo.h | 20 | 
2 files changed, 96 insertions, 31 deletions
| diff --git a/quantum/process_keycode/process_combo.c b/quantum/process_keycode/process_combo.c index a6cfed11aa..ff7e8aba55 100644 --- a/quantum/process_keycode/process_combo.c +++ b/quantum/process_keycode/process_combo.c @@ -1,11 +1,6 @@  #include "process_combo.h"  #include "print.h" -// __attribute__ ((weak)) -// combo_t key_combos[] = { - -// }; -  #define SEND_KEY(key) \  do { \      register_code16(key); \ @@ -13,54 +8,110 @@ do { \      unregister_code16(key); \  } while(0) +#define COMBO_TIMER_ELAPSED -1 + +#if COMBO_TERM +#define IS_COMBO_KEY_HELD(combo)            (COMBO_TIMER_ELAPSED == combo->timer ? false : true) +#define RESET_COMBO_TIMER_AND_KEY(combo)    combo->timer = 0; combo->key = 0 +#else +#define IS_COMBO_KEY_HELD(combo)            (true) +#define RESET_COMBO_TIMER_AND_KEY(combo)    do {} while (0) +#endif + + +__attribute__ ((weak)) +combo_t key_combos[COMBO_COUNT] = { + +}; + +static inline void reset_combo(combo_t *combo) +{ +    combo->state = 0; +    RESET_COMBO_TIMER_AND_KEY(combo); +}  #define ALL_COMBO_KEYS_ARE_DOWN (((1<<count)-1) == combo->state) +#define NO_COMBO_KEYS_ARE_DOWN  (0 == combo->state) +#define KEY_STATE_DOWN(key)     do{ combo->state |= (1<<key); } while(0) +#define KEY_STATE_UP(key)       do{ combo->state &= ~(1<<key); } while(0)  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; +    uint8_t index = -1; +    /* Find index of keycode and number of combo keys */ +    for (const uint16_t *keys = combo->keys; ;++count) { +        uint16_t key = pgm_read_word(&keys[count]); +        if (keycode == key) index = count; +        if (COMBO_END == key) break; +    } -    // Count the number of combo keys -    for (const uint16_t *key = combo->keys; COMBO_END != pgm_read_word(key); ++key, ++count); +    /* Return if not a combo key */ +    if (-1 == index) return false; -    for (uint8_t i = 0; i < count; ++i) { -        uint16_t key = pgm_read_word(&combo->keys[i]); +    bool is_combo_active = IS_COMBO_KEY_HELD(combo); -        if (key == keycode) { -            is_combo_key = true; +    if (record->event.pressed) { +        KEY_STATE_DOWN(index); +         +#if COMBO_TERM +        if (is_combo_active) { +            combo->timer = timer_read(); +            combo->key = keycode; +        } +#endif -            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; -                } +    } else { +        if (is_combo_active && combo->state) { /* Combo key was tapped */ +            RESET_COMBO_TIMER_AND_KEY(combo);             +            SEND_KEY(keycode); +        } -                combo->state &= ~(1<<i); -                SEND_KEY(key); -            } +#if COMBO_TERM +        if (!is_combo_active && keycode == combo->key) { /* Held combo key was released */ +            unregister_code16(combo->key);          } +#endif + +        KEY_STATE_UP(index);      } -    if (ALL_COMBO_KEYS_ARE_DOWN) { +    if (ALL_COMBO_KEYS_ARE_DOWN && is_combo_active) {          SEND_KEY(combo->action); -        combo->state = 0;     +        reset_combo(combo); +    }  +     +    if(NO_COMBO_KEYS_ARE_DOWN && !is_combo_active) { +        reset_combo(combo);      } -    return is_combo_key; +    return is_combo_active;  } -  bool process_combo(uint16_t keycode, keyrecord_t *record)  {      bool is_combo_key = false; -    for (int i = 0; i < NUM_ELEMS(key_combos); ++i) { +    for (int i = 0; i < COMBO_COUNT; ++i) {          combo_t *combo = &key_combos[i];          is_combo_key |= process_single_combo(combo, keycode, record);      }          return !is_combo_key; +} + +void matrix_scan_combo(void) +{ +#if COMBO_TERM +    for (int i = 0; i < COMBO_COUNT; ++i) { +        combo_t *combo = &key_combos[i]; +        if (combo->timer &&  +            combo->timer != COMBO_TIMER_ELAPSED &&  +            timer_elapsed(combo->timer) > COMBO_TERM) { + +            combo->timer = COMBO_TIMER_ELAPSED; +            unregister_code16(combo->key); +            register_code16(combo->key); +        } +    } +#endif  }
\ No newline at end of file diff --git a/quantum/process_keycode/process_combo.h b/quantum/process_keycode/process_combo.h index 68786c0f19..c475acd332 100644 --- a/quantum/process_keycode/process_combo.h +++ b/quantum/process_keycode/process_combo.h @@ -5,21 +5,35 @@  #include "progmem.h"  #include "quantum.h" +#ifndef COMBO_TERM +#define COMBO_TERM TAPPING_TERM +#endif  typedef struct  {      const uint16_t *keys;      uint16_t action;              uint32_t state; +#if COMBO_TERM +    uint16_t timer; +    uint16_t key; +#endif  } combo_t; +#if COMBO_TERM +#define COMBO(ck, ca) {.keys = &(ck)[0], .action = (ca), .state = 0, .timer = 0, .key = 0} +#else +#define COMBO(ck, ca) {.keys = &(ck)[0], .action = (ca), .state = 0 } +#endif  #define COMBO_END 0 -#define NUM_ELEMS(a) (sizeof(a)/sizeof 0[a]) +#ifndef COMBO_COUNT +#define COMBO_COUNT 0 +#endif - -extern combo_t key_combos[1]; +extern combo_t key_combos[COMBO_COUNT];  bool process_combo(uint16_t keycode, keyrecord_t *record); +void matrix_scan_combo(void);  #endif
\ No newline at end of file | 
