diff options
| author | Alex Ong <the.onga@gmail.com> | 2019-04-04 08:45:55 +1100 | 
|---|---|---|
| committer | Drashna Jaelre <drashna@live.com> | 2019-04-03 14:45:55 -0700 | 
| commit | 17e7762de7e3fdfc61c20aa61022f47370630c6a (patch) | |
| tree | acad10cdb64e24d78154c7c04de3585dece32cc3 | |
| parent | e1e08a494bf9ea46e1385559df76d5f49b8e9087 (diff) | |
| download | firmware-17e7762de7e3fdfc61c20aa61022f47370630c6a.tar.gz firmware-17e7762de7e3fdfc61c20aa61022f47370630c6a.tar.bz2 firmware-17e7762de7e3fdfc61c20aa61022f47370630c6a.zip | |
Eager Per Row Debouncing added (added to Ergodox) (#5498)
* Implemented Eager Per Row debouncing algorithm.
Good for when fingers can only press one row at a time (e.g. when keyboard is wired so that "rows" are vertical)
* Added documentation for eager_pr
* Ported ergodox_ez to eager_pr debouncing.
* Removed check for changes in matrix_scan.
* Added further clarification in docs.
* Accidental merge with ergodox_ez
* Small cleanup in eager_pr
* Forgot to debounce_init - this would probably cause seg-faults.
| -rw-r--r-- | docs/feature_debounce_type.md | 5 | ||||
| -rw-r--r-- | keyboards/ergodox_ez/matrix.c | 458 | ||||
| -rw-r--r-- | keyboards/ergodox_ez/rules.mk | 1 | ||||
| -rw-r--r-- | quantum/debounce/eager_pr.c | 100 | ||||
| -rw-r--r-- | quantum/debounce/readme.md | 2 | 
5 files changed, 302 insertions, 264 deletions
| diff --git a/docs/feature_debounce_type.md b/docs/feature_debounce_type.md index 5d4343f08..38eca3f37 100644 --- a/docs/feature_debounce_type.md +++ b/docs/feature_debounce_type.md @@ -33,7 +33,10 @@ The debounce code is compatible with split keyboards.  # Changing between included debouncing methods  You can either use your own code, by including your own debounce.c, or switch to another included one.  Included debounce methods are: -* eager_pk - debouncing per key. On any state change, response is immediate, followed by ```DEBOUNCE_DELAY``` millseconds of no further input for that key +* eager_pr - debouncing per row. On any state change, response is immediate, followed by locking the row ```DEBOUNCE_DELAY``` milliseconds of no further input for that row.  +For use in keyboards where refreshing ```NUM_KEYS``` 8-bit counters is computationally expensive / low scan rate, and fingers usually only hit one row at a time. This could be +appropriate for the ErgoDox models; the matrix is rotated 90°, and hence its "rows" are really columns, and each finger only hits a single "row" at a time in normal use. +* eager_pk - debouncing per key. On any state change, response is immediate, followed by ```DEBOUNCE_DELAY``` milliseconds of no further input for that key  * sym_g - debouncing per keyboard. On any state change, a global timer is set. When ```DEBOUNCE_DELAY``` milliseconds of no changes has occured, all input changes are pushed. diff --git a/keyboards/ergodox_ez/matrix.c b/keyboards/ergodox_ez/matrix.c index 860cf7b22..97f764113 100644 --- a/keyboards/ergodox_ez/matrix.c +++ b/keyboards/ergodox_ez/matrix.c @@ -33,14 +33,14 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #include "debug.h"  #include "util.h"  #include "matrix.h" +#include "debounce.h"  #include QMK_KEYBOARD_H  #ifdef DEBUG_MATRIX_SCAN_RATE -#include  "timer.h" +#  include "timer.h"  #endif  /* - * This constant define not debouncing time in msecs, but amount of matrix - * scan loops which should be made to get stable debounced results. + * This constant define not debouncing time in msecs, assuming eager_pr.   *   * On Ergodox matrix scan rate is relatively low, because of slow I2C.   * Now it's only 317 scans/second, or about 3.15 msec/scan. @@ -52,26 +52,17 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.   */  #ifndef DEBOUNCE -#   define DEBOUNCE	5 +#  define DEBOUNCE 5  #endif  /* matrix state(1:on, 0:off) */ -static matrix_row_t matrix[MATRIX_ROWS]; -/* - * matrix state(1:on, 0:off) - * contains the raw values without debounce filtering of the last read cycle. - */ -static matrix_row_t raw_matrix[MATRIX_ROWS]; - -// Debouncing: store for each key the number of scans until it's eligible to -// change.  When scanning the matrix, ignore any changes in keys that have -// already changed in the last DEBOUNCE scans. -static uint8_t debounce_matrix[MATRIX_ROWS * MATRIX_COLS]; +static matrix_row_t raw_matrix[MATRIX_ROWS];  // raw values +static matrix_row_t matrix[MATRIX_ROWS];      // debounced values  static matrix_row_t read_cols(uint8_t row); -static void init_cols(void); -static void unselect_rows(void); -static void select_row(uint8_t row); +static void         init_cols(void); +static void         unselect_rows(void); +static void         select_row(uint8_t row);  static uint8_t mcp23018_reset_loop;  // static uint16_t mcp23018_reset_loop; @@ -81,197 +72,137 @@ uint32_t matrix_timer;  uint32_t matrix_scan_count;  #endif +__attribute__((weak)) void matrix_init_user(void) {} -__attribute__ ((weak)) -void matrix_init_user(void) {} +__attribute__((weak)) void matrix_scan_user(void) {} -__attribute__ ((weak)) -void matrix_scan_user(void) {} +__attribute__((weak)) void matrix_init_kb(void) { matrix_init_user(); } -__attribute__ ((weak)) -void matrix_init_kb(void) { -  matrix_init_user(); -} +__attribute__((weak)) void matrix_scan_kb(void) { matrix_scan_user(); } -__attribute__ ((weak)) -void matrix_scan_kb(void) { -  matrix_scan_user(); -} - -inline -uint8_t matrix_rows(void) -{ -    return MATRIX_ROWS; -} +inline uint8_t matrix_rows(void) { return MATRIX_ROWS; } -inline -uint8_t matrix_cols(void) -{ -    return MATRIX_COLS; -} +inline uint8_t matrix_cols(void) { return MATRIX_COLS; } -void matrix_init(void) -{ -    // initialize row and col +void matrix_init(void) { +  // initialize row and col -    mcp23018_status = init_mcp23018(); +  mcp23018_status = init_mcp23018(); +  unselect_rows(); +  init_cols(); -    unselect_rows(); -    init_cols(); - -    // initialize matrix state: all keys off -    for (uint8_t i=0; i < MATRIX_ROWS; i++) { -        matrix[i] = 0; -        raw_matrix[i] = 0; -        for (uint8_t j=0; j < MATRIX_COLS; ++j) { -            debounce_matrix[i * MATRIX_COLS + j] = 0; -        } -    } +  // initialize matrix state: all keys off +  for (uint8_t i = 0; i < MATRIX_ROWS; i++) { +    matrix[i]     = 0; +    raw_matrix[i] = 0;     +  }  #ifdef DEBUG_MATRIX_SCAN_RATE -    matrix_timer = timer_read32(); -    matrix_scan_count = 0; +  matrix_timer      = timer_read32(); +  matrix_scan_count = 0;  #endif - -    matrix_init_quantum(); - +  debounce_init(MATRIX_ROWS); +  matrix_init_quantum();  }  void matrix_power_up(void) { -    mcp23018_status = init_mcp23018(); +  mcp23018_status = init_mcp23018(); -    unselect_rows(); -    init_cols(); +  unselect_rows(); +  init_cols(); -    // initialize matrix state: all keys off -    for (uint8_t i=0; i < MATRIX_ROWS; i++) { -        matrix[i] = 0; -    } +  // initialize matrix state: all keys off +  for (uint8_t i = 0; i < MATRIX_ROWS; i++) { +    matrix[i] = 0; +  }  #ifdef DEBUG_MATRIX_SCAN_RATE -    matrix_timer = timer_read32(); -    matrix_scan_count = 0; +  matrix_timer      = timer_read32(); +  matrix_scan_count = 0;  #endif  } -// Returns a matrix_row_t whose bits are set if the corresponding key should be -// eligible to change in this scan. -matrix_row_t debounce_mask(matrix_row_t rawcols, uint8_t row) { -  matrix_row_t result = 0; -  matrix_row_t change = rawcols ^ raw_matrix[row]; -  raw_matrix[row] = rawcols; -  for (uint8_t i = 0; i < MATRIX_COLS; ++i) { -    if (debounce_matrix[row * MATRIX_COLS + i]) { -      --debounce_matrix[row * MATRIX_COLS + i]; -    } else { -      result |= (1 << i); -    } -    if (change & (1 << i)) { -      debounce_matrix[row * MATRIX_COLS + i] = DEBOUNCE; +uint8_t matrix_scan(void) { +  if (mcp23018_status) {  // if there was an error +    if (++mcp23018_reset_loop == 0) { +      // if (++mcp23018_reset_loop >= 1300) { +      // since mcp23018_reset_loop is 8 bit - we'll try to reset once in 255 matrix scans +      // this will be approx bit more frequent than once per second +      print("trying to reset mcp23018\n"); +      mcp23018_status = init_mcp23018(); +      if (mcp23018_status) { +        print("left side not responding\n"); +      } else { +        print("left side attached\n"); +        ergodox_blink_all_leds(); +      }      }    } -  return result; -} - -matrix_row_t debounce_read_cols(uint8_t row) { -  // Read the row without debouncing filtering and store it for later usage. -  matrix_row_t cols = read_cols(row); -  // Get the Debounce mask. -  matrix_row_t mask = debounce_mask(cols, row); -  // debounce the row and return the result. -  return (cols & mask) | (matrix[row] & ~mask);; -} - -uint8_t matrix_scan(void) -{ -    if (mcp23018_status) { // if there was an error -        if (++mcp23018_reset_loop == 0) { -        // if (++mcp23018_reset_loop >= 1300) { -            // since mcp23018_reset_loop is 8 bit - we'll try to reset once in 255 matrix scans -            // this will be approx bit more frequent than once per second -            print("trying to reset mcp23018\n"); -            mcp23018_status = init_mcp23018(); -            if (mcp23018_status) { -                print("left side not responding\n"); -            } else { -                print("left side attached\n"); -                ergodox_blink_all_leds(); -            } -        } -    }  #ifdef DEBUG_MATRIX_SCAN_RATE -    matrix_scan_count++; +  matrix_scan_count++; -    uint32_t timer_now = timer_read32(); -    if (TIMER_DIFF_32(timer_now, matrix_timer)>1000) { -        print("matrix scan frequency: "); -        pdec(matrix_scan_count); -        print("\n"); +  uint32_t timer_now = timer_read32(); +  if (TIMER_DIFF_32(timer_now, matrix_timer) > 1000) { +    print("matrix scan frequency: "); +    pdec(matrix_scan_count); +    print("\n"); -        matrix_timer = timer_now; -        matrix_scan_count = 0; -    } +    matrix_timer      = timer_now; +    matrix_scan_count = 0; +  }  #endif  #ifdef LEFT_LEDS -    mcp23018_status = ergodox_left_leds_update(); -#endif // LEFT_LEDS -    for (uint8_t i = 0; i < MATRIX_ROWS_PER_SIDE; i++) { -        select_row(i); -        // and select on left hand -        select_row(i + MATRIX_ROWS_PER_SIDE); -        // we don't need a 30us delay anymore, because selecting a -        // left-hand row requires more than 30us for i2c. - -        // grab cols from left hand -        matrix[i] = debounce_read_cols(i); -        // grab cols from right hand -        matrix[i + MATRIX_ROWS_PER_SIDE] = debounce_read_cols(i + MATRIX_ROWS_PER_SIDE); - -        unselect_rows(); -    } - -    matrix_scan_quantum(); +  mcp23018_status = ergodox_left_leds_update(); +#endif  // LEFT_LEDS +  for (uint8_t i = 0; i < MATRIX_ROWS_PER_SIDE; i++) { +    // select rows from left and right hands +    select_row(i); +    select_row(i + MATRIX_ROWS_PER_SIDE); + +    // we don't need a 30us delay anymore, because selecting a +    // left-hand row requires more than 30us for i2c. + +    // grab left + right cols. +    raw_matrix[i] = read_cols(i);     +    raw_matrix[i+MATRIX_ROWS_PER_SIDE] = read_cols(i+MATRIX_ROWS_PER_SIDE); +     +    unselect_rows(); +  } +   +  debounce(raw_matrix, matrix, MATRIX_ROWS, true); +  matrix_scan_quantum(); -    return 1; +  return 1;  } -bool matrix_is_modified(void) // deprecated and evidently not called. +bool matrix_is_modified(void)  // deprecated and evidently not called.  { -    return true; +  return true;  } -inline -bool matrix_is_on(uint8_t row, uint8_t col) -{ -    return (matrix[row] & ((matrix_row_t)1<<col)); -} +inline bool matrix_is_on(uint8_t row, uint8_t col) { return (matrix[row] & ((matrix_row_t)1 << col)); } -inline -matrix_row_t matrix_get_row(uint8_t row) -{ -    return matrix[row]; -} +inline matrix_row_t matrix_get_row(uint8_t row) { return matrix[row]; } -void matrix_print(void) -{ -    print("\nr/c 0123456789ABCDEF\n"); -    for (uint8_t row = 0; row < MATRIX_ROWS; row++) { -        phex(row); print(": "); -        pbin_reverse16(matrix_get_row(row)); -        print("\n"); -    } +void matrix_print(void) { +  print("\nr/c 0123456789ABCDEF\n"); +  for (uint8_t row = 0; row < MATRIX_ROWS; row++) { +    phex(row); +    print(": "); +    pbin_reverse16(matrix_get_row(row)); +    print("\n"); +  }  } -uint8_t matrix_key_count(void) -{ -    uint8_t count = 0; -    for (uint8_t i = 0; i < MATRIX_ROWS; i++) { -        count += bitpop16(matrix[i]); -    } -    return count; +uint8_t matrix_key_count(void) { +  uint8_t count = 0; +  for (uint8_t i = 0; i < MATRIX_ROWS; i++) { +    count += bitpop16(matrix[i]); +  } +  return count;  }  /* Column pin configuration @@ -284,43 +215,45 @@ uint8_t matrix_key_count(void)   * col: 0   1   2   3   4   5   * pin: B5  B4  B3  B2  B1  B0   */ -static void  init_cols(void) -{ -    // init on mcp23018 -    // not needed, already done as part of init_mcp23018() - -    // init on teensy -    // Input with pull-up(DDR:0, PORT:1) -    DDRF  &= ~(1<<7 | 1<<6 | 1<<5 | 1<<4 | 1<<1 | 1<<0); -    PORTF |=  (1<<7 | 1<<6 | 1<<5 | 1<<4 | 1<<1 | 1<<0); +static void init_cols(void) { +  // init on mcp23018 +  // not needed, already done as part of init_mcp23018() + +  // init on teensy +  // Input with pull-up(DDR:0, PORT:1) +  DDRF &= ~(1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 1 | 1 << 0); +  PORTF |= (1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 1 | 1 << 0);  } -static matrix_row_t read_cols(uint8_t row) -{ -    if (row < 7) { -        if (mcp23018_status) { // if there was an error -            return 0; -        } else { -            uint8_t data = 0; -            mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT);    if (mcp23018_status) goto out; -            mcp23018_status = i2c_write(GPIOB, ERGODOX_EZ_I2C_TIMEOUT);             if (mcp23018_status) goto out; -            mcp23018_status = i2c_start(I2C_ADDR_READ, ERGODOX_EZ_I2C_TIMEOUT);     if (mcp23018_status) goto out; -            mcp23018_status = i2c_read_nack(ERGODOX_EZ_I2C_TIMEOUT);                if (mcp23018_status < 0) goto out; -            data = ~((uint8_t)mcp23018_status); -            mcp23018_status = I2C_STATUS_SUCCESS; -        out: -            i2c_stop(); -            return data; -        } +static matrix_row_t read_cols(uint8_t row) { +  if (row < 7) { +    if (mcp23018_status) {  // if there was an error +      return 0;      } else { -        /* read from teensy -	 * bitmask is 0b11110011, but we want those all -	 * in the lower six bits. -	 * we'll return 1s for the top two, but that's harmless. -	 */ - -        return ~((PINF & 0x03) | ((PINF & 0xF0) >> 2)); +      uint8_t data    = 0; +      mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); +      if (mcp23018_status) goto out; +      mcp23018_status = i2c_write(GPIOB, ERGODOX_EZ_I2C_TIMEOUT); +      if (mcp23018_status) goto out; +      mcp23018_status = i2c_start(I2C_ADDR_READ, ERGODOX_EZ_I2C_TIMEOUT); +      if (mcp23018_status) goto out; +      mcp23018_status = i2c_read_nack(ERGODOX_EZ_I2C_TIMEOUT); +      if (mcp23018_status < 0) goto out; +      data            = ~((uint8_t)mcp23018_status); +      mcp23018_status = I2C_STATUS_SUCCESS; +    out: +      i2c_stop(); +      return data;      } +  } else { +    /* read from teensy +     * bitmask is 0b11110011, but we want those all +     * in the lower six bits. +     * we'll return 1s for the top two, but that's harmless. +     */ + +    return ~((PINF & 0x03) | ((PINF & 0xF0) >> 2)); +  }  }  /* Row pin configuration @@ -333,69 +266,70 @@ static matrix_row_t read_cols(uint8_t row)   * row: 0   1   2   3   4   5   6   * pin: A0  A1  A2  A3  A4  A5  A6   */ -static void unselect_rows(void) -{ -    // no need to unselect on mcp23018, because the select step sets all -    // the other row bits high, and it's not changing to a different -    // direction - -    // unselect on teensy -    // Hi-Z(DDR:0, PORT:0) to unselect -    DDRB  &= ~(1<<0 | 1<<1 | 1<<2 | 1<<3); -    PORTB &= ~(1<<0 | 1<<1 | 1<<2 | 1<<3); -    DDRD  &= ~(1<<2 | 1<<3); -    PORTD &= ~(1<<2 | 1<<3); -    DDRC  &= ~(1<<6); -    PORTC &= ~(1<<6); +static void unselect_rows(void) { +  // no need to unselect on mcp23018, because the select step sets all +  // the other row bits high, and it's not changing to a different +  // direction + +  // unselect on teensy +  // Hi-Z(DDR:0, PORT:0) to unselect +  DDRB &= ~(1 << 0 | 1 << 1 | 1 << 2 | 1 << 3); +  PORTB &= ~(1 << 0 | 1 << 1 | 1 << 2 | 1 << 3); +  DDRD &= ~(1 << 2 | 1 << 3); +  PORTD &= ~(1 << 2 | 1 << 3); +  DDRC &= ~(1 << 6); +  PORTC &= ~(1 << 6);  } -static void select_row(uint8_t row) -{ -    if (row < 7) { -        // select on mcp23018 -        if (mcp23018_status) { // if there was an error -            // do nothing -        } else { -            // set active row low  : 0 -            // set other rows hi-Z : 1 -            mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT);        if (mcp23018_status) goto out; -            mcp23018_status = i2c_write(GPIOA, ERGODOX_EZ_I2C_TIMEOUT);                 if (mcp23018_status) goto out; -            mcp23018_status = i2c_write(0xFF & ~(1<<row), ERGODOX_EZ_I2C_TIMEOUT);      if (mcp23018_status) goto out; -        out: -            i2c_stop(); -        } +static void select_row(uint8_t row) { +  if (row < 7) { +    // select on mcp23018 +    if (mcp23018_status) {  // if there was an error +                            // do nothing      } else { -        // select on teensy -        // Output low(DDR:1, PORT:0) to select -        switch (row) { -            case 7: -                DDRB  |= (1<<0); -                PORTB &= ~(1<<0); -                break; -            case 8: -                DDRB  |= (1<<1); -                PORTB &= ~(1<<1); -                break; -            case 9: -                DDRB  |= (1<<2); -                PORTB &= ~(1<<2); -                break; -            case 10: -                DDRB  |= (1<<3); -                PORTB &= ~(1<<3); -                break; -            case 11: -                DDRD  |= (1<<2); -                PORTD &= ~(1<<2); -                break; -            case 12: -                DDRD  |= (1<<3); -                PORTD &= ~(1<<3); -                break; -            case 13: -                DDRC  |= (1<<6); -                PORTC &= ~(1<<6); -                break; -        } +      // set active row low  : 0 +      // set other rows hi-Z : 1 +      mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); +      if (mcp23018_status) goto out; +      mcp23018_status = i2c_write(GPIOA, ERGODOX_EZ_I2C_TIMEOUT); +      if (mcp23018_status) goto out; +      mcp23018_status = i2c_write(0xFF & ~(1 << row), ERGODOX_EZ_I2C_TIMEOUT); +      if (mcp23018_status) goto out; +    out: +      i2c_stop(); +    } +  } else { +    // select on teensy +    // Output low(DDR:1, PORT:0) to select +    switch (row) { +      case 7: +        DDRB |= (1 << 0); +        PORTB &= ~(1 << 0); +        break; +      case 8: +        DDRB |= (1 << 1); +        PORTB &= ~(1 << 1); +        break; +      case 9: +        DDRB |= (1 << 2); +        PORTB &= ~(1 << 2); +        break; +      case 10: +        DDRB |= (1 << 3); +        PORTB &= ~(1 << 3); +        break; +      case 11: +        DDRD |= (1 << 2); +        PORTD &= ~(1 << 2); +        break; +      case 12: +        DDRD |= (1 << 3); +        PORTD &= ~(1 << 3); +        break; +      case 13: +        DDRC |= (1 << 6); +        PORTC &= ~(1 << 6); +        break;      } +  }  } diff --git a/keyboards/ergodox_ez/rules.mk b/keyboards/ergodox_ez/rules.mk index 446ba3e21..e96cd2082 100644 --- a/keyboards/ergodox_ez/rules.mk +++ b/keyboards/ergodox_ez/rules.mk @@ -83,6 +83,7 @@ SLEEP_LED_ENABLE = no  API_SYSEX_ENABLE = no  RGBLIGHT_ENABLE = yes  RGB_MATRIX_ENABLE = no # enable later +DEBOUNCE_TYPE = eager_pr  ifeq ($(strip $(RGB_MATRIX_ENABLE)), no)    SRC += i2c_master.c diff --git a/quantum/debounce/eager_pr.c b/quantum/debounce/eager_pr.c new file mode 100644 index 000000000..9eb9480a7 --- /dev/null +++ b/quantum/debounce/eager_pr.c @@ -0,0 +1,100 @@ +/* +Copyright 2019 Alex Ong<the.onga@gmail.com> +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +GNU General Public License for more details. +You should have received a copy of the GNU General Public License +along with this program.  If not, see <http://www.gnu.org/licenses/>. +*/ + +/* +Basic per-row algorithm. Uses an 8-bit counter per row. +After pressing a key, it immediately changes state, and sets a counter. +No further inputs are accepted until DEBOUNCE milliseconds have occurred. +*/ + +#include "matrix.h" +#include "timer.h" +#include "quantum.h" +#include <stdlib.h> + +#ifndef DEBOUNCE +  #define DEBOUNCE 5 +#endif + + +#define debounce_counter_t uint8_t + +static debounce_counter_t *debounce_counters; + +#define DEBOUNCE_ELAPSED 251 +#define MAX_DEBOUNCE (DEBOUNCE_ELAPSED - 1) + +void update_debounce_counters(uint8_t num_rows, uint8_t current_time); +void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time); + +//we use num_rows rather than MATRIX_ROWS to support split keyboards +void debounce_init(uint8_t num_rows) +{ +  debounce_counters = (debounce_counter_t*)malloc(num_rows*sizeof(debounce_counter_t));   +  for (uint8_t r = 0; r < num_rows; r++) +  {     +    debounce_counters[r] = DEBOUNCE_ELAPSED; +  } +} + +void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) +{ +  uint8_t current_time = timer_read() % MAX_DEBOUNCE; +  update_debounce_counters(num_rows, current_time); +  transfer_matrix_values(raw, cooked, num_rows, current_time); +} + +//If the current time is > debounce counter, set the counter to enable input. +void update_debounce_counters(uint8_t num_rows, uint8_t current_time) +{ +  debounce_counter_t *debounce_pointer = debounce_counters; +  for (uint8_t row = 0; row < num_rows; row++) +  {     +    if (*debounce_pointer != DEBOUNCE_ELAPSED) +    { +      if (TIMER_DIFF(current_time, *debounce_pointer, MAX_DEBOUNCE) >= DEBOUNCE) { +        *debounce_pointer = DEBOUNCE_ELAPSED; +      } +    } +    debounce_pointer++; +  } +} + +// upload from raw_matrix to final matrix; +void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time) +{ +  debounce_counter_t *debounce_pointer = debounce_counters; +  for (uint8_t row = 0; row < num_rows; row++) +  { +    matrix_row_t existing_row = cooked[row];  +    matrix_row_t raw_row = raw[row]; +     +    //determine new value basd on debounce pointer + raw value +    if (*debounce_pointer == DEBOUNCE_ELAPSED && +      (existing_row != raw_row)) +    { +      *debounce_pointer = current_time; +      existing_row = raw_row;  +    } +    cooked[row] = existing_row; +     +    debounce_pointer++; +  }   +} + +bool debounce_active(void) +{ +  return true; +} + diff --git a/quantum/debounce/readme.md b/quantum/debounce/readme.md index 5b318d845..f77f78c76 100644 --- a/quantum/debounce/readme.md +++ b/quantum/debounce/readme.md @@ -22,7 +22,7 @@ Here are a few that could be implemented:  sym_g.c  sym_pk.c  sym_pr.c -sym_pr_cycles.c //currently used in ergo-dox +sym_pr_cycles.c   eager_g.c  eager_pk.c  eager_pr.c //could be used in ergo-dox! | 
