qmk_firmware

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

sym_eager_pk.c (5203B)


      1 /*
      2 Copyright 2017 Alex Ong<the.onga@gmail.com>
      3 Copyright 2021 Simon Arlott
      4 This program is free software: you can redistribute it and/or modify
      5 it under the terms of the GNU General Public License as published by
      6 the Free Software Foundation, either version 2 of the License, or
      7 (at your option) any later version.
      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 You should have received a copy of the GNU General Public License
     13 along with this program.  If not, see <http://www.gnu.org/licenses/>.
     14 */
     15 
     16 /*
     17 Basic per-key algorithm. Uses an 8-bit counter per key.
     18 After pressing a key, it immediately changes state, and sets a counter.
     19 No further inputs are accepted until DEBOUNCE milliseconds have occurred.
     20 */
     21 
     22 #include "debounce.h"
     23 #include "timer.h"
     24 #include "util.h"
     25 
     26 #ifndef DEBOUNCE
     27 #    define DEBOUNCE 5
     28 #endif
     29 
     30 // Maximum debounce: 255ms
     31 #if DEBOUNCE > UINT8_MAX
     32 #    undef DEBOUNCE
     33 #    define DEBOUNCE UINT8_MAX
     34 #endif
     35 
     36 #define DEBOUNCE_ELAPSED 0
     37 
     38 #if DEBOUNCE > 0
     39 typedef uint8_t debounce_counter_t;
     40 // Uses MATRIX_ROWS_PER_HAND instead of MATRIX_ROWS to support split keyboards
     41 static debounce_counter_t debounce_counters[MATRIX_ROWS_PER_HAND * MATRIX_COLS] = {DEBOUNCE_ELAPSED};
     42 static bool               counters_need_update;
     43 static bool               matrix_need_update;
     44 static bool               cooked_changed;
     45 
     46 static inline void update_debounce_counters(uint8_t elapsed_time);
     47 static inline void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[]);
     48 
     49 void debounce_init(void) {}
     50 
     51 bool debounce(matrix_row_t raw[], matrix_row_t cooked[], bool changed) {
     52     static fast_timer_t last_time;
     53     bool                updated_last = false;
     54     cooked_changed                   = false;
     55 
     56     if (counters_need_update) {
     57         fast_timer_t now          = timer_read_fast();
     58         fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time);
     59 
     60         last_time    = now;
     61         updated_last = true;
     62 
     63         if (elapsed_time > 0) {
     64             // Update debounce counters with elapsed timer clamped to UINT8_MAX
     65             update_debounce_counters(MIN(elapsed_time, UINT8_MAX));
     66         }
     67     }
     68 
     69     if (changed || matrix_need_update) {
     70         if (!updated_last) {
     71             last_time = timer_read_fast();
     72         }
     73 
     74         transfer_matrix_values(raw, cooked);
     75     }
     76 
     77     return cooked_changed;
     78 }
     79 
     80 /**
     81  * @brief Updates per-key debounce counters and determines if matrix needs updating.
     82  *
     83  * Iterates through each key in the matrix and checks its debounce counter. If the debounce
     84  * period has elapsed, the counter is reset and the matrix is marked for update. Otherwise,
     85  * the counter is decremented by the elapsed time and marked for further updates if needed.
     86  *
     87  * @param elapsed_time The time elapsed since the last debounce update, in milliseconds.
     88  */
     89 static inline void update_debounce_counters(uint8_t elapsed_time) {
     90     counters_need_update = false;
     91     matrix_need_update   = false;
     92 
     93     for (uint8_t row = 0; row < MATRIX_ROWS_PER_HAND; row++) {
     94         uint16_t row_offset = row * MATRIX_COLS;
     95 
     96         for (uint8_t col = 0; col < MATRIX_COLS; col++) {
     97             uint16_t index = row_offset + col;
     98 
     99             if (debounce_counters[index] != DEBOUNCE_ELAPSED) {
    100                 if (debounce_counters[index] <= elapsed_time) {
    101                     debounce_counters[index] = DEBOUNCE_ELAPSED;
    102                     matrix_need_update       = true;
    103                 } else {
    104                     debounce_counters[index] -= elapsed_time;
    105                     counters_need_update = true;
    106                 }
    107             }
    108         }
    109     }
    110 }
    111 
    112 /**
    113  * @brief Transfers debounced key states from the raw matrix to the cooked matrix.
    114  *
    115  * For each key in the matrix, this function checks if its state has changed and if its
    116  * debounce counter has elapsed. If so, the debounce counter is reset, the cooked matrix
    117  * is updated to reflect the new state, and the matrix is marked for further updates.
    118  *
    119  * @param raw The current raw key state matrix.
    120  * @param cooked The debounced key state matrix to be updated.
    121  */
    122 static inline void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[]) {
    123     matrix_need_update = false;
    124 
    125     for (uint8_t row = 0; row < MATRIX_ROWS_PER_HAND; row++) {
    126         uint16_t     row_offset   = row * MATRIX_COLS;
    127         matrix_row_t delta        = raw[row] ^ cooked[row];
    128         matrix_row_t existing_row = cooked[row];
    129 
    130         for (uint8_t col = 0; col < MATRIX_COLS; col++) {
    131             uint16_t index = row_offset + col;
    132 
    133             matrix_row_t col_mask = (MATRIX_ROW_SHIFTER << col);
    134             if (delta & col_mask) {
    135                 if (debounce_counters[index] == DEBOUNCE_ELAPSED) {
    136                     debounce_counters[index] = DEBOUNCE;
    137                     counters_need_update     = true;
    138                     existing_row ^= col_mask; // flip the bit.
    139                     cooked_changed = true;
    140                 }
    141             }
    142         }
    143         cooked[row] = existing_row;
    144     }
    145 }
    146 
    147 #else
    148 #    include "none.c"
    149 #endif