Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace debouncing code #1

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions keyboard/ergodox/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,22 @@ Project located at <https://github.com/benblazak/ergodox-firmware>
/* define if matrix has ghost */
//#define MATRIX_HAS_GHOST

/* Set 0 if debouncing isn't needed */
/*
* This constant define not debouncing time in msecs, but amount of matrix
* scan loops which should be made to get stable debounced results.
* DEBOUNCE describes how many matrix scan phases a key must stabilize after an
* edge was detected before a new edge is accepted.
*
* 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.
* According to Cherry specs, debouncing time is 5 msec.
*
* And so, there is no sense to have DEBOUNCE higher than 2.
* Older Cherry switches were observed to have a debounce time of 8 to 10ms, so
* we set this to 4 by default. The current debouncing code will transmit the
* keypress to the PC instantly on the first edge, so this value does not
* influence the latency at all.
*
* This value must be larger or equal to one.
*/
#define DEBOUNCE 2
//#define DEBOUNCE 4
#define TAPPING_TERM 230

/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
Expand Down
103 changes: 76 additions & 27 deletions keyboard/ergodox/matrix.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,26 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "timer.h"
#endif

// This configures how many matrix scans a key must have settled before the
// next state change is accepted. The matrix is scanned about every 3ms, so
// this gives us roughly 12ms.
#ifndef DEBOUNCE
# define DEBOUNCE 5
# define DEBOUNCE 4
#endif
static uint8_t debouncing = DEBOUNCE;

#if DEBOUNCE < 1
# error "DEBOUNCE must be larger or equal 1"
#endif


/* matrix state(1:on, 0:off) */
static matrix_row_t matrix[MATRIX_ROWS];
static matrix_row_t matrix_debouncing[MATRIX_ROWS];

// matrix_debouncing is used to implement debouncing. If a bit is set, the key
// has recently changed and needs to calm down first, so the change is ignored.
static matrix_row_t matrix_debouncing[DEBOUNCE][MATRIX_ROWS];

static void advance_debouncing_matrix(void);

static matrix_row_t read_cols(uint8_t row);
static void init_cols(void);
Expand Down Expand Up @@ -78,7 +90,13 @@ void matrix_init(void)
// initialize matrix state: all keys off
for (uint8_t i=0; i < MATRIX_ROWS; i++) {
matrix[i] = 0;
matrix_debouncing[i] = 0;
}

// initialize debouncing shadow copies
for (uint8_t d = 0; d < DEBOUNCE; d++) {
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
matrix_debouncing[d][i] = 0;
}
}

#ifdef DEBUG_MATRIX_SCAN_RATE
Expand All @@ -87,6 +105,23 @@ void matrix_init(void)
#endif
}

inline static void advance_debouncing_matrix()
{
#if DEBOUNCE > 1
// advance debouncing shadow copies
for (uint8_t d = 0; d < DEBOUNCE-1; d++) {
for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
matrix_debouncing[d][row] = matrix_debouncing[d+1][row];
}
}
#endif

// clear last debouncing matrix
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
matrix_debouncing[DEBOUNCE-1][i] = 0;
}
}

uint8_t matrix_scan(void)
{
if (mcp23018_status) { // if there was an error
Expand Down Expand Up @@ -166,36 +201,50 @@ uint8_t matrix_scan(void)
mcp23018_status = ergodox_left_leds_update();
#endif

for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
select_row(i);
matrix_row_t cols = read_cols(i);
if (matrix_debouncing[i] != cols) {
matrix_debouncing[i] = cols;
if (debouncing) {
debug("bounce!: "); debug_hex(debouncing); debug("\n");
}
debouncing = DEBOUNCE;
matrix_row_t changes, mask;
for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
// read cols for current row
select_row(row);
matrix_row_t cols = read_cols(row);

// read changed keys in current row
changes = matrix[row] ^ cols;

// compute mask for debouncing for current row
mask = ~matrix_debouncing[0][row];

#ifdef DEBUG_BOUNCING
if (changes > 0 && (changes & mask) == 0) {
print("masked changes in row ");
print_hex8(row);
print(": ");
print_hex8(changes);
print(", demasked: ");
print_hex8(changes & mask);
print("\n");
}
unselect_rows();
}
#endif

if (debouncing) {
if (--debouncing) {
_delay_ms(1);
} else {
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
matrix[i] = matrix_debouncing[i];
// mask out keys that have changed recently, the bits are set it
// matrix_debouncing.
changes &= mask;

if (changes > 0) {
// apply changes to matrix
matrix[row] ^= changes;

// set bits in shadow matrixes
for (uint8_t d = 0; d < DEBOUNCE; d++) {
matrix_debouncing[d][row] |= changes;
}
}

unselect_rows();
}

return 1;
}
advance_debouncing_matrix();

bool matrix_is_modified(void)
{
if (debouncing) return false;
return true;
return 1;
}

inline
Expand Down