qmk

QMK Firmware
git clone git://git.z3bra.org/qmk.git
Log | Files | Refs | Submodules | LICENSE

action_tapping.c (14926B)


      1 #include <stdint.h>
      2 #include <stdbool.h>
      3 #include "action.h"
      4 #include "action_layer.h"
      5 #include "action_tapping.h"
      6 #include "keycode.h"
      7 #include "timer.h"
      8 
      9 #ifdef DEBUG_ACTION
     10 #    include "debug.h"
     11 #else
     12 #    include "nodebug.h"
     13 #endif
     14 
     15 #ifndef NO_ACTION_TAPPING
     16 
     17 #    define IS_TAPPING() !IS_NOEVENT(tapping_key.event)
     18 #    define IS_TAPPING_PRESSED() (IS_TAPPING() && tapping_key.event.pressed)
     19 #    define IS_TAPPING_RELEASED() (IS_TAPPING() && !tapping_key.event.pressed)
     20 #    define IS_TAPPING_KEY(k) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (k)))
     21 
     22 __attribute__((weak)) uint16_t get_tapping_term(uint16_t keycode) { return TAPPING_TERM; }
     23 
     24 #    ifdef TAPPING_TERM_PER_KEY
     25 #        define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < get_tapping_term(get_event_keycode(tapping_key.event)))
     26 #    else
     27 #        define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < TAPPING_TERM)
     28 #    endif
     29 
     30 static keyrecord_t tapping_key                         = {};
     31 static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {};
     32 static uint8_t     waiting_buffer_head                 = 0;
     33 static uint8_t     waiting_buffer_tail                 = 0;
     34 
     35 static bool process_tapping(keyrecord_t *record);
     36 static bool waiting_buffer_enq(keyrecord_t record);
     37 static void waiting_buffer_clear(void);
     38 static bool waiting_buffer_typed(keyevent_t event);
     39 static bool waiting_buffer_has_anykey_pressed(void);
     40 static void waiting_buffer_scan_tap(void);
     41 static void debug_tapping_key(void);
     42 static void debug_waiting_buffer(void);
     43 
     44 /** \brief Action Tapping Process
     45  *
     46  * FIXME: Needs doc
     47  */
     48 void action_tapping_process(keyrecord_t record) {
     49     if (process_tapping(&record)) {
     50         if (!IS_NOEVENT(record.event)) {
     51             debug("processed: ");
     52             debug_record(record);
     53             debug("\n");
     54         }
     55     } else {
     56         if (!waiting_buffer_enq(record)) {
     57             // clear all in case of overflow.
     58             debug("OVERFLOW: CLEAR ALL STATES\n");
     59             clear_keyboard();
     60             waiting_buffer_clear();
     61             tapping_key = (keyrecord_t){};
     62         }
     63     }
     64 
     65     // process waiting_buffer
     66     if (!IS_NOEVENT(record.event) && waiting_buffer_head != waiting_buffer_tail) {
     67         debug("---- action_exec: process waiting_buffer -----\n");
     68     }
     69     for (; waiting_buffer_tail != waiting_buffer_head; waiting_buffer_tail = (waiting_buffer_tail + 1) % WAITING_BUFFER_SIZE) {
     70         if (process_tapping(&waiting_buffer[waiting_buffer_tail])) {
     71             debug("processed: waiting_buffer[");
     72             debug_dec(waiting_buffer_tail);
     73             debug("] = ");
     74             debug_record(waiting_buffer[waiting_buffer_tail]);
     75             debug("\n\n");
     76         } else {
     77             break;
     78         }
     79     }
     80     if (!IS_NOEVENT(record.event)) {
     81         debug("\n");
     82     }
     83 }
     84 
     85 /** \brief Tapping
     86  *
     87  * Rule: Tap key is typed(pressed and released) within TAPPING_TERM.
     88  *       (without interfering by typing other key)
     89  */
     90 /* return true when key event is processed or consumed. */
     91 bool process_tapping(keyrecord_t *keyp) {
     92     keyevent_t event = keyp->event;
     93 
     94     // if tapping
     95     if (IS_TAPPING_PRESSED()) {
     96         if (WITHIN_TAPPING_TERM(event)) {
     97             if (tapping_key.tap.count == 0) {
     98                 if (IS_TAPPING_KEY(event.key) && !event.pressed) {
     99                     // first tap!
    100                     debug("Tapping: First tap(0->1).\n");
    101                     tapping_key.tap.count = 1;
    102                     debug_tapping_key();
    103                     process_record(&tapping_key);
    104 
    105                     // copy tapping state
    106                     keyp->tap = tapping_key.tap;
    107                     // enqueue
    108                     return false;
    109                 }
    110                 /* Process a key typed within TAPPING_TERM
    111                  * This can register the key before settlement of tapping,
    112                  * useful for long TAPPING_TERM but may prevent fast typing.
    113                  */
    114 #    if defined(TAPPING_TERM_PER_KEY) || (!defined(PER_KEY_TAPPING_TERM) && TAPPING_TERM >= 500) || defined(PERMISSIVE_HOLD)
    115 #        ifdef TAPPING_TERM_PER_KEY
    116                 else if ((get_tapping_term(get_event_keycode(tapping_key.event)) >= 500) && IS_RELEASED(event) && waiting_buffer_typed(event))
    117 #        else
    118                 else if (IS_RELEASED(event) && waiting_buffer_typed(event))
    119 #        endif
    120                 {
    121                     debug("Tapping: End. No tap. Interfered by typing key\n");
    122                     process_record(&tapping_key);
    123                     tapping_key = (keyrecord_t){};
    124                     debug_tapping_key();
    125                     // enqueue
    126                     return false;
    127                 }
    128 #    endif
    129                 /* Process release event of a key pressed before tapping starts
    130                  * Without this unexpected repeating will occur with having fast repeating setting
    131                  * https://github.com/tmk/tmk_keyboard/issues/60
    132                  */
    133                 else if (IS_RELEASED(event) && !waiting_buffer_typed(event)) {
    134                     // Modifier should be retained till end of this tapping.
    135                     action_t action = layer_switch_get_action(event.key);
    136                     switch (action.kind.id) {
    137                         case ACT_LMODS:
    138                         case ACT_RMODS:
    139                             if (action.key.mods && !action.key.code) return false;
    140                             if (IS_MOD(action.key.code)) return false;
    141                             break;
    142                         case ACT_LMODS_TAP:
    143                         case ACT_RMODS_TAP:
    144                             if (action.key.mods && keyp->tap.count == 0) return false;
    145                             if (IS_MOD(action.key.code)) return false;
    146                             break;
    147                     }
    148                     // Release of key should be process immediately.
    149                     debug("Tapping: release event of a key pressed before tapping\n");
    150                     process_record(keyp);
    151                     return true;
    152                 } else {
    153                     // set interrupted flag when other key preesed during tapping
    154                     if (event.pressed) {
    155                         tapping_key.tap.interrupted = true;
    156                     }
    157                     // enqueue
    158                     return false;
    159                 }
    160             }
    161             // tap_count > 0
    162             else {
    163                 if (IS_TAPPING_KEY(event.key) && !event.pressed) {
    164                     debug("Tapping: Tap release(");
    165                     debug_dec(tapping_key.tap.count);
    166                     debug(")\n");
    167                     keyp->tap = tapping_key.tap;
    168                     process_record(keyp);
    169                     tapping_key = *keyp;
    170                     debug_tapping_key();
    171                     return true;
    172                 } else if (is_tap_key(event.key) && event.pressed) {
    173                     if (tapping_key.tap.count > 1) {
    174                         debug("Tapping: Start new tap with releasing last tap(>1).\n");
    175                         // unregister key
    176                         process_record(&(keyrecord_t){.tap = tapping_key.tap, .event.key = tapping_key.event.key, .event.time = event.time, .event.pressed = false});
    177                     } else {
    178                         debug("Tapping: Start while last tap(1).\n");
    179                     }
    180                     tapping_key = *keyp;
    181                     waiting_buffer_scan_tap();
    182                     debug_tapping_key();
    183                     return true;
    184                 } else {
    185                     if (!IS_NOEVENT(event)) {
    186                         debug("Tapping: key event while last tap(>0).\n");
    187                     }
    188                     process_record(keyp);
    189                     return true;
    190                 }
    191             }
    192         }
    193         // after TAPPING_TERM
    194         else {
    195             if (tapping_key.tap.count == 0) {
    196                 debug("Tapping: End. Timeout. Not tap(0): ");
    197                 debug_event(event);
    198                 debug("\n");
    199                 process_record(&tapping_key);
    200                 tapping_key = (keyrecord_t){};
    201                 debug_tapping_key();
    202                 return false;
    203             } else {
    204                 if (IS_TAPPING_KEY(event.key) && !event.pressed) {
    205                     debug("Tapping: End. last timeout tap release(>0).");
    206                     keyp->tap = tapping_key.tap;
    207                     process_record(keyp);
    208                     tapping_key = (keyrecord_t){};
    209                     return true;
    210                 } else if (is_tap_key(event.key) && event.pressed) {
    211                     if (tapping_key.tap.count > 1) {
    212                         debug("Tapping: Start new tap with releasing last timeout tap(>1).\n");
    213                         // unregister key
    214                         process_record(&(keyrecord_t){.tap = tapping_key.tap, .event.key = tapping_key.event.key, .event.time = event.time, .event.pressed = false});
    215                     } else {
    216                         debug("Tapping: Start while last timeout tap(1).\n");
    217                     }
    218                     tapping_key = *keyp;
    219                     waiting_buffer_scan_tap();
    220                     debug_tapping_key();
    221                     return true;
    222                 } else {
    223                     if (!IS_NOEVENT(event)) {
    224                         debug("Tapping: key event while last timeout tap(>0).\n");
    225                     }
    226                     process_record(keyp);
    227                     return true;
    228                 }
    229             }
    230         }
    231     } else if (IS_TAPPING_RELEASED()) {
    232         if (WITHIN_TAPPING_TERM(event)) {
    233             if (event.pressed) {
    234                 if (IS_TAPPING_KEY(event.key)) {
    235 #    ifndef TAPPING_FORCE_HOLD
    236                     if (!tapping_key.tap.interrupted && tapping_key.tap.count > 0) {
    237                         // sequential tap.
    238                         keyp->tap = tapping_key.tap;
    239                         if (keyp->tap.count < 15) keyp->tap.count += 1;
    240                         debug("Tapping: Tap press(");
    241                         debug_dec(keyp->tap.count);
    242                         debug(")\n");
    243                         process_record(keyp);
    244                         tapping_key = *keyp;
    245                         debug_tapping_key();
    246                         return true;
    247                     }
    248 #    endif
    249                     // FIX: start new tap again
    250                     tapping_key = *keyp;
    251                     return true;
    252                 } else if (is_tap_key(event.key)) {
    253                     // Sequential tap can be interfered with other tap key.
    254                     debug("Tapping: Start with interfering other tap.\n");
    255                     tapping_key = *keyp;
    256                     waiting_buffer_scan_tap();
    257                     debug_tapping_key();
    258                     return true;
    259                 } else {
    260                     // should none in buffer
    261                     // FIX: interrupted when other key is pressed
    262                     tapping_key.tap.interrupted = true;
    263                     process_record(keyp);
    264                     return true;
    265                 }
    266             } else {
    267                 if (!IS_NOEVENT(event)) debug("Tapping: other key just after tap.\n");
    268                 process_record(keyp);
    269                 return true;
    270             }
    271         } else {
    272             // FIX: process_action here?
    273             // timeout. no sequential tap.
    274             debug("Tapping: End(Timeout after releasing last tap): ");
    275             debug_event(event);
    276             debug("\n");
    277             tapping_key = (keyrecord_t){};
    278             debug_tapping_key();
    279             return false;
    280         }
    281     }
    282     // not tapping state
    283     else {
    284         if (event.pressed && is_tap_key(event.key)) {
    285             debug("Tapping: Start(Press tap key).\n");
    286             tapping_key = *keyp;
    287             process_record_tap_hint(&tapping_key);
    288             waiting_buffer_scan_tap();
    289             debug_tapping_key();
    290             return true;
    291         } else {
    292             process_record(keyp);
    293             return true;
    294         }
    295     }
    296 }
    297 
    298 /** \brief Waiting buffer enq
    299  *
    300  * FIXME: Needs docs
    301  */
    302 bool waiting_buffer_enq(keyrecord_t record) {
    303     if (IS_NOEVENT(record.event)) {
    304         return true;
    305     }
    306 
    307     if ((waiting_buffer_head + 1) % WAITING_BUFFER_SIZE == waiting_buffer_tail) {
    308         debug("waiting_buffer_enq: Over flow.\n");
    309         return false;
    310     }
    311 
    312     waiting_buffer[waiting_buffer_head] = record;
    313     waiting_buffer_head                 = (waiting_buffer_head + 1) % WAITING_BUFFER_SIZE;
    314 
    315     debug("waiting_buffer_enq: ");
    316     debug_waiting_buffer();
    317     return true;
    318 }
    319 
    320 /** \brief Waiting buffer clear
    321  *
    322  * FIXME: Needs docs
    323  */
    324 void waiting_buffer_clear(void) {
    325     waiting_buffer_head = 0;
    326     waiting_buffer_tail = 0;
    327 }
    328 
    329 /** \brief Waiting buffer typed
    330  *
    331  * FIXME: Needs docs
    332  */
    333 bool waiting_buffer_typed(keyevent_t event) {
    334     for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
    335         if (KEYEQ(event.key, waiting_buffer[i].event.key) && event.pressed != waiting_buffer[i].event.pressed) {
    336             return true;
    337         }
    338     }
    339     return false;
    340 }
    341 
    342 /** \brief Waiting buffer has anykey pressed
    343  *
    344  * FIXME: Needs docs
    345  */
    346 __attribute__((unused)) bool waiting_buffer_has_anykey_pressed(void) {
    347     for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
    348         if (waiting_buffer[i].event.pressed) return true;
    349     }
    350     return false;
    351 }
    352 
    353 /** \brief Scan buffer for tapping
    354  *
    355  * FIXME: Needs docs
    356  */
    357 void waiting_buffer_scan_tap(void) {
    358     // tapping already is settled
    359     if (tapping_key.tap.count > 0) return;
    360     // invalid state: tapping_key released && tap.count == 0
    361     if (!tapping_key.event.pressed) return;
    362 
    363     for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
    364         if (IS_TAPPING_KEY(waiting_buffer[i].event.key) && !waiting_buffer[i].event.pressed && WITHIN_TAPPING_TERM(waiting_buffer[i].event)) {
    365             tapping_key.tap.count       = 1;
    366             waiting_buffer[i].tap.count = 1;
    367             process_record(&tapping_key);
    368 
    369             debug("waiting_buffer_scan_tap: found at [");
    370             debug_dec(i);
    371             debug("]\n");
    372             debug_waiting_buffer();
    373             return;
    374         }
    375     }
    376 }
    377 
    378 /** \brief Tapping key debug print
    379  *
    380  * FIXME: Needs docs
    381  */
    382 static void debug_tapping_key(void) {
    383     debug("TAPPING_KEY=");
    384     debug_record(tapping_key);
    385     debug("\n");
    386 }
    387 
    388 /** \brief Waiting buffer debug print
    389  *
    390  * FIXME: Needs docs
    391  */
    392 static void debug_waiting_buffer(void) {
    393     debug("{ ");
    394     for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
    395         debug("[");
    396         debug_dec(i);
    397         debug("]=");
    398         debug_record(waiting_buffer[i]);
    399         debug(" ");
    400     }
    401     debug("}\n");
    402 }
    403 
    404 #endif