aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Pritchard <awpr@google.com>2017-04-26 15:29:39 -0700
committerAndrew Pritchard <awpr@google.com>2017-04-26 15:29:39 -0700
commitcd30a60d0e4f108403b19ec4c1bc4270b54b8c27 (patch)
treeeacc9a73728bc060c5a71e668a47cfeeee69c430
parent7bd4559b4b8f323107de46ebf90d31bfa9880e78 (diff)
downloadqmk_firmware-cd30a60d0e4f108403b19ec4c1bc4270b54b8c27.tar.gz
qmk_firmware-cd30a60d0e4f108403b19ec4c1bc4270b54b8c27.zip
Change to per-key eager debouncing for ErgoDox EZ.
Empirically, waiting for N consecutive identical scans as a debouncing strategy doesn't work very well for the ErgoDox EZ where scans are very slow compared to most keyboards. Instead, debounce the signals by eagerly reporting a change as soon as one scan observes it, but then ignoring further changes from that key for the next N scans. This is implemented by keeping an extra matrix of uint8 countdowns, such that only keys whose countdown is currently zero are eligible to change. When we do observe a change, we bump that key's countdown to DEBOUNCE. During each scan, every nonzero countdown is decremented. With this approach to debouncing, much higher debounce constants are tolerable, because latency does not increase with the constant, and debounce countdowns on one key do not interfere with events on other keys. The only negative effect of increasing the constant is that the minimum duration of a keypress increases. Perhaps I'm just extremely unlucky w.r.t. key switch quality, but I saw occasional bounces even with DEBOUNCE=10; with 15, I've seen none so far. That's around 47ms, which seems like an absolutely insane amount of time for a key to be bouncy, but at least it works.
-rw-r--r--keyboards/ergodox/ez/config.h2
-rw-r--r--keyboards/ergodox/ez/matrix.c62
2 files changed, 38 insertions, 26 deletions
diff --git a/keyboards/ergodox/ez/config.h b/keyboards/ergodox/ez/config.h
index a3347de45..aa17c3e8d 100644
--- a/keyboards/ergodox/ez/config.h
+++ b/keyboards/ergodox/ez/config.h
@@ -58,7 +58,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
58#define RGBW 1 58#define RGBW 1
59 59
60/* Set 0 if debouncing isn't needed */ 60/* Set 0 if debouncing isn't needed */
61#define DEBOUNCE 5 61#define DEBOUNCE 15
62 62
63#define USB_MAX_POWER_CONSUMPTION 500 63#define USB_MAX_POWER_CONSUMPTION 500
64 64
diff --git a/keyboards/ergodox/ez/matrix.c b/keyboards/ergodox/ez/matrix.c
index 43f515259..21b60a542 100644
--- a/keyboards/ergodox/ez/matrix.c
+++ b/keyboards/ergodox/ez/matrix.c
@@ -53,11 +53,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
53#ifndef DEBOUNCE 53#ifndef DEBOUNCE
54# define DEBOUNCE 5 54# define DEBOUNCE 5
55#endif 55#endif
56static uint8_t debouncing = DEBOUNCE;
57 56
58/* matrix state(1:on, 0:off) */ 57/* matrix state(1:on, 0:off) */
59static matrix_row_t matrix[MATRIX_ROWS]; 58static matrix_row_t matrix[MATRIX_ROWS];
60static matrix_row_t matrix_debouncing[MATRIX_ROWS]; 59
60// Debouncing: store for each key the number of scans until it's eligible to
61// change. When scanning the matrix, ignore any changes in keys that have
62// already changed in the last DEBOUNCE scans.
63static uint8_t debounce_matrix[MATRIX_ROWS * MATRIX_COLS];
61 64
62static matrix_row_t read_cols(uint8_t row); 65static matrix_row_t read_cols(uint8_t row);
63static void init_cols(void); 66static void init_cols(void);
@@ -113,7 +116,9 @@ void matrix_init(void)
113 // initialize matrix state: all keys off 116 // initialize matrix state: all keys off
114 for (uint8_t i=0; i < MATRIX_ROWS; i++) { 117 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
115 matrix[i] = 0; 118 matrix[i] = 0;
116 matrix_debouncing[i] = 0; 119 for (uint8_t j=0; j < MATRIX_COLS; ++j) {
120 debounce_matrix[i * MATRIX_COLS + j] = 0;
121 }
117 } 122 }
118 123
119#ifdef DEBUG_MATRIX_SCAN_RATE 124#ifdef DEBUG_MATRIX_SCAN_RATE
@@ -134,14 +139,36 @@ void matrix_power_up(void) {
134 // initialize matrix state: all keys off 139 // initialize matrix state: all keys off
135 for (uint8_t i=0; i < MATRIX_ROWS; i++) { 140 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
136 matrix[i] = 0; 141 matrix[i] = 0;
137 matrix_debouncing[i] = 0;
138 } 142 }
139 143
140#ifdef DEBUG_MATRIX_SCAN_RATE 144#ifdef DEBUG_MATRIX_SCAN_RATE
141 matrix_timer = timer_read32(); 145 matrix_timer = timer_read32();
142 matrix_scan_count = 0; 146 matrix_scan_count = 0;
143#endif 147#endif
148}
149
150// Returns a matrix_row_t whose bits are set if the corresponding key should be
151// eligible to change in this scan.
152matrix_row_t debounce_mask(uint8_t row) {
153 matrix_row_t result = 0;
154 for (uint8_t j=0; j < MATRIX_COLS; ++j) {
155 if (debounce_matrix[row * MATRIX_COLS + j]) {
156 --debounce_matrix[row * MATRIX_COLS + j];
157 } else {
158 result |= (1 << j);
159 }
160 }
161 return result;
162}
144 163
164// Report changed keys in the given row. Resets the debounce countdowns
165// corresponding to each set bit in 'change' to DEBOUNCE.
166void debounce_report(matrix_row_t change, uint8_t row) {
167 for (uint8_t i = 0; i < MATRIX_COLS; ++i) {
168 if (change & (1 << i)) {
169 debounce_matrix[row * MATRIX_COLS + i] = DEBOUNCE;
170 }
171 }
145} 172}
146 173
147uint8_t matrix_scan(void) 174uint8_t matrix_scan(void)
@@ -178,26 +205,12 @@ uint8_t matrix_scan(void)
178 for (uint8_t i = 0; i < MATRIX_ROWS; i++) { 205 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
179 select_row(i); 206 select_row(i);
180 wait_us(30); // without this wait read unstable value. 207 wait_us(30); // without this wait read unstable value.
181 matrix_row_t cols = read_cols(i); 208 matrix_row_t mask = debounce_mask(i);
182 if (matrix_debouncing[i] != cols) { 209 matrix_row_t cols = (read_cols(i) & mask) | (matrix[i] & ~mask);
183 matrix_debouncing[i] = cols; 210 debounce_report(cols ^ matrix[i], i);
184 if (debouncing) { 211 matrix[i] = cols;
185 debug("bounce!: "); debug_hex(debouncing); debug("\n");
186 }
187 debouncing = DEBOUNCE;
188 }
189 unselect_rows();
190 }
191 212
192 if (debouncing) { 213 unselect_rows();
193 if (--debouncing) {
194 wait_us(1);
195 // this should be wait_ms(1) but has been left as-is at EZ's request
196 } else {
197 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
198 matrix[i] = matrix_debouncing[i];
199 }
200 }
201 } 214 }
202 215
203 matrix_scan_quantum(); 216 matrix_scan_quantum();
@@ -205,9 +218,8 @@ uint8_t matrix_scan(void)
205 return 1; 218 return 1;
206} 219}
207 220
208bool matrix_is_modified(void) 221bool matrix_is_modified(void) // deprecated and evidently not called.
209{ 222{
210 if (debouncing) return false;
211 return true; 223 return true;
212} 224}
213 225