qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

leader.c (2695B)


      1 // Copyright 2023 QMK
      2 // SPDX-License-Identifier: GPL-2.0-or-later
      3 
      4 #include "leader.h"
      5 #include "timer.h"
      6 #include "util.h"
      7 
      8 #include <string.h>
      9 
     10 #ifndef LEADER_TIMEOUT
     11 #    define LEADER_TIMEOUT 300
     12 #endif
     13 
     14 // Leader key stuff
     15 bool     leading              = false;
     16 uint16_t leader_time          = 0;
     17 uint16_t leader_sequence[5]   = {0, 0, 0, 0, 0};
     18 uint8_t  leader_sequence_size = 0;
     19 
     20 __attribute__((weak)) void leader_start_user(void) {}
     21 
     22 __attribute__((weak)) void leader_end_user(void) {}
     23 
     24 __attribute__((weak)) bool leader_add_user(uint16_t keycode) {
     25     return false;
     26 }
     27 
     28 void leader_start(void) {
     29     if (leading) {
     30         return;
     31     }
     32     leader_start_user();
     33     leading              = true;
     34     leader_time          = timer_read();
     35     leader_sequence_size = 0;
     36     memset(leader_sequence, 0, sizeof(leader_sequence));
     37 }
     38 
     39 void leader_end(void) {
     40     leading = false;
     41     leader_end_user();
     42 }
     43 
     44 void leader_task(void) {
     45     if (leader_sequence_active() && leader_sequence_timed_out()) {
     46         leader_end();
     47     }
     48 }
     49 
     50 bool leader_sequence_active(void) {
     51     return leading;
     52 }
     53 
     54 bool leader_sequence_add(uint16_t keycode) {
     55     if (leader_sequence_size >= ARRAY_SIZE(leader_sequence)) {
     56         return false;
     57     }
     58 
     59 #if defined(LEADER_NO_TIMEOUT)
     60     if (leader_sequence_size == 0) {
     61         leader_reset_timer();
     62     }
     63 #endif
     64 
     65     leader_sequence[leader_sequence_size] = keycode;
     66     leader_sequence_size++;
     67 
     68     if (leader_add_user(keycode)) {
     69         leader_end();
     70     }
     71     return true;
     72 }
     73 
     74 bool leader_sequence_timed_out(void) {
     75 #if defined(LEADER_NO_TIMEOUT)
     76     return leader_sequence_size > 0 && timer_elapsed(leader_time) > LEADER_TIMEOUT;
     77 #else
     78     return timer_elapsed(leader_time) > LEADER_TIMEOUT;
     79 #endif
     80 }
     81 
     82 void leader_reset_timer(void) {
     83     leader_time = timer_read();
     84 }
     85 
     86 bool leader_sequence_is(uint16_t kc1, uint16_t kc2, uint16_t kc3, uint16_t kc4, uint16_t kc5) {
     87     return leader_sequence[0] == kc1 && leader_sequence[1] == kc2 && leader_sequence[2] == kc3 && leader_sequence[3] == kc4 && leader_sequence[4] == kc5;
     88 }
     89 
     90 bool leader_sequence_one_key(uint16_t kc) {
     91     return leader_sequence_is(kc, 0, 0, 0, 0);
     92 }
     93 
     94 bool leader_sequence_two_keys(uint16_t kc1, uint16_t kc2) {
     95     return leader_sequence_is(kc1, kc2, 0, 0, 0);
     96 }
     97 
     98 bool leader_sequence_three_keys(uint16_t kc1, uint16_t kc2, uint16_t kc3) {
     99     return leader_sequence_is(kc1, kc2, kc3, 0, 0);
    100 }
    101 
    102 bool leader_sequence_four_keys(uint16_t kc1, uint16_t kc2, uint16_t kc3, uint16_t kc4) {
    103     return leader_sequence_is(kc1, kc2, kc3, kc4, 0);
    104 }
    105 
    106 bool leader_sequence_five_keys(uint16_t kc1, uint16_t kc2, uint16_t kc3, uint16_t kc4, uint16_t kc5) {
    107     return leader_sequence_is(kc1, kc2, kc3, kc4, kc5);
    108 }