qmk_firmware

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

examples.c (6720B)


      1 /* Copyright 2022 Jouke Witteveen
      2  *
      3  * This program is free software: you can redistribute it and/or modify
      4  * it under the terms of the GNU General Public License as published by
      5  * the Free Software Foundation, either version 2 of the License, or
      6  * (at your option) any later version.
      7  *
      8  * This program is distributed in the hope that it will be useful,
      9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     11  * GNU General Public License for more details.
     12  *
     13  * You should have received a copy of the GNU General Public License
     14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
     15  */
     16 
     17 #include "quantum.h"
     18 #include "examples.h"
     19 #include "keymap_introspection.h"
     20 
     21 // Example code from the tap dance documentation, adapted for testing
     22 
     23 // clang-format off
     24 
     25 // Example 1
     26 
     27 void dance_egg(tap_dance_state_t *state, void *user_data) {
     28     if (state->count >= 100) {
     29         // SEND_STRING("Safety dance!");
     30         tap_code(KC_C);
     31         reset_tap_dance(state);
     32     }
     33 }
     34 
     35 
     36 // Example 2
     37 
     38 void dance_flsh_each(tap_dance_state_t *state, void *user_data) {
     39     switch (state->count) {
     40         case 1:
     41             register_code(KC_3);
     42             break;
     43         case 2:
     44             register_code(KC_2);
     45             break;
     46         case 3:
     47             register_code(KC_1);
     48             break;
     49         case 4:
     50             unregister_code(KC_3);
     51             // wait_ms(50);
     52             unregister_code(KC_2);
     53             // wait_ms(50);
     54             unregister_code(KC_1);
     55     }
     56 }
     57 
     58 void dance_flsh_finished(tap_dance_state_t *state, void *user_data) {
     59     if (state->count >= 4) {
     60         // reset_keyboard();
     61         tap_code(KC_R);
     62     }
     63 }
     64 
     65 void dance_flsh_reset(tap_dance_state_t *state, void *user_data) {
     66     unregister_code(KC_1);
     67     // wait_ms(50);
     68     unregister_code(KC_2);
     69     // wait_ms(50);
     70     unregister_code(KC_3);
     71 }
     72 
     73 
     74 // Example 3
     75 
     76 typedef struct {
     77     uint16_t tap;
     78     uint16_t hold;
     79     uint16_t held;
     80 } tap_dance_tap_hold_t;
     81 
     82 bool process_record_user(uint16_t keycode, keyrecord_t *record) {
     83     tap_dance_action_t *action;
     84     tap_dance_state_t* state;
     85 
     86     switch (keycode) {
     87         case TD(CT_CLN):
     88             action = tap_dance_get(QK_TAP_DANCE_GET_INDEX(keycode));
     89             state = tap_dance_get_state(QK_TAP_DANCE_GET_INDEX(keycode));
     90             if (!record->event.pressed && state != NULL && state->count && !state->finished) {
     91                 tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)action->user_data;
     92                 tap_code16(tap_hold->tap);
     93             }
     94     }
     95     return true;
     96 }
     97 
     98 void tap_dance_tap_hold_finished(tap_dance_state_t *state, void *user_data) {
     99     tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)user_data;
    100 
    101     if (state->pressed) {
    102         if (state->count == 1
    103 #ifndef PERMISSIVE_HOLD
    104             && !state->interrupted
    105 #endif
    106         ) {
    107             register_code16(tap_hold->hold);
    108             tap_hold->held = tap_hold->hold;
    109         } else {
    110             register_code16(tap_hold->tap);
    111             tap_hold->held = tap_hold->tap;
    112         }
    113     }
    114 }
    115 
    116 void tap_dance_tap_hold_reset(tap_dance_state_t *state, void *user_data) {
    117     tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)user_data;
    118 
    119     if (tap_hold->held) {
    120         unregister_code16(tap_hold->held);
    121         tap_hold->held = 0;
    122     }
    123 }
    124 
    125 #define ACTION_TAP_DANCE_TAP_HOLD(tap, hold) \
    126     { .fn = {NULL, tap_dance_tap_hold_finished, tap_dance_tap_hold_reset}, .user_data = (void *)&((tap_dance_tap_hold_t){tap, hold, 0}), }
    127 
    128 
    129 // Example 4
    130 
    131 typedef enum {
    132     TD_NONE,
    133     TD_UNKNOWN,
    134     TD_SINGLE_TAP,
    135     TD_SINGLE_HOLD,
    136     TD_DOUBLE_TAP,
    137     TD_DOUBLE_HOLD,
    138     TD_DOUBLE_SINGLE_TAP,
    139     TD_TRIPLE_TAP,
    140     TD_TRIPLE_HOLD
    141 } td_state_t;
    142 
    143 typedef struct {
    144     bool is_press_action;
    145     td_state_t state;
    146 } td_tap_t;
    147 
    148 td_state_t cur_dance(tap_dance_state_t *state) {
    149     if (state->count == 1) {
    150         if (state->interrupted || !state->pressed) return TD_SINGLE_TAP;
    151         else return TD_SINGLE_HOLD;
    152     } else if (state->count == 2) {
    153         if (state->interrupted) return TD_DOUBLE_SINGLE_TAP;
    154         else if (state->pressed) return TD_DOUBLE_HOLD;
    155         else return TD_DOUBLE_TAP;
    156     }
    157 
    158     if (state->count == 3) {
    159         if (state->interrupted || !state->pressed) return TD_TRIPLE_TAP;
    160         else return TD_TRIPLE_HOLD;
    161     } else return TD_UNKNOWN;
    162 }
    163 
    164 static td_tap_t xtap_state = {
    165     .is_press_action = true,
    166     .state = TD_NONE
    167 };
    168 
    169 void x_finished(tap_dance_state_t *state, void *user_data) {
    170     xtap_state.state = cur_dance(state);
    171     switch (xtap_state.state) {
    172         case TD_SINGLE_TAP: register_code(KC_X); break;
    173         case TD_SINGLE_HOLD: register_code(KC_LCTL); break;
    174         case TD_DOUBLE_TAP: register_code(KC_ESC); break;
    175         case TD_DOUBLE_HOLD: register_code(KC_LALT); break;
    176         case TD_DOUBLE_SINGLE_TAP: tap_code(KC_X); register_code(KC_X);
    177         default: break;  // Not present in documentation
    178     }
    179 }
    180 
    181 void x_reset(tap_dance_state_t *state, void *user_data) {
    182     switch (xtap_state.state) {
    183         case TD_SINGLE_TAP: unregister_code(KC_X); break;
    184         case TD_SINGLE_HOLD: unregister_code(KC_LCTL); break;
    185         case TD_DOUBLE_TAP: unregister_code(KC_ESC); break;
    186         case TD_DOUBLE_HOLD: unregister_code(KC_LALT);
    187         case TD_DOUBLE_SINGLE_TAP: unregister_code(KC_X);
    188         default: break;  // Not present in documentation
    189     }
    190     xtap_state.state = TD_NONE;
    191 }
    192 
    193 static void release_press(tap_dance_state_t *state, void *user_data) {
    194     tap_code16(KC_P);
    195 }
    196 
    197 static void release_unpress(tap_dance_state_t *state, void *user_data) {
    198     tap_code16(KC_U);
    199 }
    200 
    201 static void release_unpress_mark_finished(tap_dance_state_t *state, void *user_data) {
    202     tap_code16(KC_U);
    203     state->finished = true;
    204 }
    205 
    206 static void release_finished(tap_dance_state_t *state, void *user_data) {
    207     tap_code16(KC_F);
    208 }
    209 
    210 static void release_reset(tap_dance_state_t *state, void *user_data) {
    211     tap_code16(KC_R);
    212 }
    213 
    214 tap_dance_action_t tap_dance_actions[] = {
    215     [TD_ESC_CAPS] = ACTION_TAP_DANCE_DOUBLE(KC_ESC, KC_CAPS),
    216     [CT_EGG]      = ACTION_TAP_DANCE_FN(dance_egg),
    217     [CT_FLSH]     = ACTION_TAP_DANCE_FN_ADVANCED(dance_flsh_each, dance_flsh_finished, dance_flsh_reset),
    218     [CT_CLN]      = ACTION_TAP_DANCE_TAP_HOLD(KC_COLN, KC_SCLN),
    219     [X_CTL]       = ACTION_TAP_DANCE_FN_ADVANCED(NULL, x_finished, x_reset),
    220     [TD_RELEASE]  = ACTION_TAP_DANCE_FN_ADVANCED_WITH_RELEASE(release_press, release_unpress, release_finished, release_reset),
    221     [TD_RELEASE_AND_FINISH]  = ACTION_TAP_DANCE_FN_ADVANCED_WITH_RELEASE(release_press, release_unpress_mark_finished, release_finished, release_reset),
    222 };
    223 
    224 // clang-format on