aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Ong <the.onga@gmail.com>2019-04-04 08:45:55 +1100
committerDrashna Jaelre <drashna@live.com>2019-04-03 14:45:55 -0700
commit17e7762de7e3fdfc61c20aa61022f47370630c6a (patch)
treeacad10cdb64e24d78154c7c04de3585dece32cc3
parente1e08a494bf9ea46e1385559df76d5f49b8e9087 (diff)
downloadqmk_firmware-17e7762de7e3fdfc61c20aa61022f47370630c6a.tar.gz
qmk_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.md5
-rw-r--r--keyboards/ergodox_ez/matrix.c458
-rw-r--r--keyboards/ergodox_ez/rules.mk1
-rw-r--r--quantum/debounce/eager_pr.c100
-rw-r--r--quantum/debounce/readme.md2
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.
33# Changing between included debouncing methods 33# Changing between included debouncing methods
34You can either use your own code, by including your own debounce.c, or switch to another included one. 34You can either use your own code, by including your own debounce.c, or switch to another included one.
35Included debounce methods are: 35Included debounce methods are:
36* eager_pk - debouncing per key. On any state change, response is immediate, followed by ```DEBOUNCE_DELAY``` millseconds of no further input for that key 36* 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.
37For 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
38appropriate 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.
39* eager_pk - debouncing per key. On any state change, response is immediate, followed by ```DEBOUNCE_DELAY``` milliseconds of no further input for that key
37* 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. 40* 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.
38 41
39 42
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/>.
33#include "debug.h" 33#include "debug.h"
34#include "util.h" 34#include "util.h"
35#include "matrix.h" 35#include "matrix.h"
36#include "debounce.h"
36#include QMK_KEYBOARD_H 37#include QMK_KEYBOARD_H
37#ifdef DEBUG_MATRIX_SCAN_RATE 38#ifdef DEBUG_MATRIX_SCAN_RATE
38#include "timer.h" 39# include "timer.h"
39#endif 40#endif
40 41
41/* 42/*
42 * This constant define not debouncing time in msecs, but amount of matrix 43 * This constant define not debouncing time in msecs, assuming eager_pr.
43 * scan loops which should be made to get stable debounced results.
44 * 44 *
45 * On Ergodox matrix scan rate is relatively low, because of slow I2C. 45 * On Ergodox matrix scan rate is relatively low, because of slow I2C.
46 * Now it's only 317 scans/second, or about 3.15 msec/scan. 46 * 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/>.
52 */ 52 */
53 53
54#ifndef DEBOUNCE 54#ifndef DEBOUNCE
55# define DEBOUNCE 5 55# define DEBOUNCE 5
56#endif 56#endif
57 57
58/* matrix state(1:on, 0:off) */ 58/* matrix state(1:on, 0:off) */
59static matrix_row_t matrix[MATRIX_ROWS]; 59static matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values
60/* 60static matrix_row_t matrix[MATRIX_ROWS]; // debounced values
61 * matrix state(1:on, 0:off)
62 * contains the raw values without debounce filtering of the last read cycle.
63 */
64static matrix_row_t raw_matrix[MATRIX_ROWS];
65
66// Debouncing: store for each key the number of scans until it's eligible to
67// change. When scanning the matrix, ignore any changes in keys that have
68// already changed in the last DEBOUNCE scans.
69static uint8_t debounce_matrix[MATRIX_ROWS * MATRIX_COLS];
70 61
71static matrix_row_t read_cols(uint8_t row); 62static matrix_row_t read_cols(uint8_t row);
72static void init_cols(void); 63static void init_cols(void);
73static void unselect_rows(void); 64static void unselect_rows(void);
74static void select_row(uint8_t row); 65static void select_row(uint8_t row);
75 66
76static uint8_t mcp23018_reset_loop; 67static uint8_t mcp23018_reset_loop;
77// static uint16_t mcp23018_reset_loop; 68// static uint16_t mcp23018_reset_loop;
@@ -81,197 +72,137 @@ uint32_t matrix_timer;
81uint32_t matrix_scan_count; 72uint32_t matrix_scan_count;
82#endif 73#endif
83 74
75__attribute__((weak)) void matrix_init_user(void) {}
84 76
85__attribute__ ((weak)) 77__attribute__((weak)) void matrix_scan_user(void) {}
86void matrix_init_user(void) {}
87 78
88__attribute__ ((weak)) 79__attribute__((weak)) void matrix_init_kb(void) { matrix_init_user(); }
89void matrix_scan_user(void) {}
90 80
91__attribute__ ((weak)) 81__attribute__((weak)) void matrix_scan_kb(void) { matrix_scan_user(); }
92void matrix_init_kb(void) {
93 matrix_init_user();
94}
95 82
96__attribute__ ((weak)) 83inline uint8_t matrix_rows(void) { return MATRIX_ROWS; }
97void matrix_scan_kb(void) {
98 matrix_scan_user();
99}
100
101inline
102uint8_t matrix_rows(void)
103{
104 return MATRIX_ROWS;
105}
106 84
107inline 85inline uint8_t matrix_cols(void) { return MATRIX_COLS; }
108uint8_t matrix_cols(void)
109{
110 return MATRIX_COLS;
111}
112 86
113void matrix_init(void) 87void matrix_init(void) {
114{ 88 // initialize row and col
115 // initialize row and col
116 89
117 mcp23018_status = init_mcp23018(); 90 mcp23018_status = init_mcp23018();
118 91
92 unselect_rows();
93 init_cols();
119 94
120 unselect_rows(); 95 // initialize matrix state: all keys off
121 init_cols(); 96 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
122 97 matrix[i] = 0;
123 // initialize matrix state: all keys off 98 raw_matrix[i] = 0;
124 for (uint8_t i=0; i < MATRIX_ROWS; i++) { 99 }
125 matrix[i] = 0;
126 raw_matrix[i] = 0;
127 for (uint8_t j=0; j < MATRIX_COLS; ++j) {
128 debounce_matrix[i * MATRIX_COLS + j] = 0;
129 }
130 }
131 100
132#ifdef DEBUG_MATRIX_SCAN_RATE 101#ifdef DEBUG_MATRIX_SCAN_RATE
133 matrix_timer = timer_read32(); 102 matrix_timer = timer_read32();
134 matrix_scan_count = 0; 103 matrix_scan_count = 0;
135#endif 104#endif
136 105 debounce_init(MATRIX_ROWS);
137 matrix_init_quantum(); 106 matrix_init_quantum();
138
139} 107}
140 108
141void matrix_power_up(void) { 109void matrix_power_up(void) {
142 mcp23018_status = init_mcp23018(); 110 mcp23018_status = init_mcp23018();
143 111
144 unselect_rows(); 112 unselect_rows();
145 init_cols(); 113 init_cols();
146 114
147 // initialize matrix state: all keys off 115 // initialize matrix state: all keys off
148 for (uint8_t i=0; i < MATRIX_ROWS; i++) { 116 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
149 matrix[i] = 0; 117 matrix[i] = 0;
150 } 118 }
151 119
152#ifdef DEBUG_MATRIX_SCAN_RATE 120#ifdef DEBUG_MATRIX_SCAN_RATE
153 matrix_timer = timer_read32(); 121 matrix_timer = timer_read32();
154 matrix_scan_count = 0; 122 matrix_scan_count = 0;
155#endif 123#endif
156} 124}
157 125
158// Returns a matrix_row_t whose bits are set if the corresponding key should be 126uint8_t matrix_scan(void) {
159// eligible to change in this scan. 127 if (mcp23018_status) { // if there was an error
160matrix_row_t debounce_mask(matrix_row_t rawcols, uint8_t row) { 128 if (++mcp23018_reset_loop == 0) {
161 matrix_row_t result = 0; 129 // if (++mcp23018_reset_loop >= 1300) {
162 matrix_row_t change = rawcols ^ raw_matrix[row]; 130 // since mcp23018_reset_loop is 8 bit - we'll try to reset once in 255 matrix scans
163 raw_matrix[row] = rawcols; 131 // this will be approx bit more frequent than once per second
164 for (uint8_t i = 0; i < MATRIX_COLS; ++i) { 132 print("trying to reset mcp23018\n");
165 if (debounce_matrix[row * MATRIX_COLS + i]) { 133 mcp23018_status = init_mcp23018();
166 --debounce_matrix[row * MATRIX_COLS + i]; 134 if (mcp23018_status) {
167 } else { 135 print("left side not responding\n");
168 result |= (1 << i); 136 } else {
169 } 137 print("left side attached\n");
170 if (change & (1 << i)) { 138 ergodox_blink_all_leds();
171 debounce_matrix[row * MATRIX_COLS + i] = DEBOUNCE; 139 }
172 } 140 }
173 } 141 }
174 return result;
175}
176
177matrix_row_t debounce_read_cols(uint8_t row) {
178 // Read the row without debouncing filtering and store it for later usage.
179 matrix_row_t cols = read_cols(row);
180 // Get the Debounce mask.
181 matrix_row_t mask = debounce_mask(cols, row);
182 // debounce the row and return the result.
183 return (cols & mask) | (matrix[row] & ~mask);;
184}
185
186uint8_t matrix_scan(void)
187{
188 if (mcp23018_status) { // if there was an error
189 if (++mcp23018_reset_loop == 0) {
190 // if (++mcp23018_reset_loop >= 1300) {
191 // since mcp23018_reset_loop is 8 bit - we'll try to reset once in 255 matrix scans
192 // this will be approx bit more frequent than once per second
193 print("trying to reset mcp23018\n");
194 mcp23018_status = init_mcp23018();
195 if (mcp23018_status) {
196 print("left side not responding\n");
197 } else {
198 print("left side attached\n");
199 ergodox_blink_all_leds();
200 }
201 }
202 }
203 142
204#ifdef DEBUG_MATRIX_SCAN_RATE 143#ifdef DEBUG_MATRIX_SCAN_RATE
205 matrix_scan_count++; 144 matrix_scan_count++;
206 145
207 uint32_t timer_now = timer_read32(); 146 uint32_t timer_now = timer_read32();
208 if (TIMER_DIFF_32(timer_now, matrix_timer)>1000) { 147 if (TIMER_DIFF_32(timer_now, matrix_timer) > 1000) {
209 print("matrix scan frequency: "); 148 print("matrix scan frequency: ");
210 pdec(matrix_scan_count); 149 pdec(matrix_scan_count);
211 print("\n"); 150 print("\n");
212 151
213 matrix_timer = timer_now; 152 matrix_timer = timer_now;
214 matrix_scan_count = 0; 153 matrix_scan_count = 0;
215 } 154 }
216#endif 155#endif
217 156
218#ifdef LEFT_LEDS 157#ifdef LEFT_LEDS
219 mcp23018_status = ergodox_left_leds_update(); 158 mcp23018_status = ergodox_left_leds_update();
220#endif // LEFT_LEDS 159#endif // LEFT_LEDS
221 for (uint8_t i = 0; i < MATRIX_ROWS_PER_SIDE; i++) { 160 for (uint8_t i = 0; i < MATRIX_ROWS_PER_SIDE; i++) {
222 select_row(i); 161 // select rows from left and right hands
223 // and select on left hand 162 select_row(i);
224 select_row(i + MATRIX_ROWS_PER_SIDE); 163 select_row(i + MATRIX_ROWS_PER_SIDE);
225 // we don't need a 30us delay anymore, because selecting a 164
226 // left-hand row requires more than 30us for i2c. 165 // we don't need a 30us delay anymore, because selecting a
227 166 // left-hand row requires more than 30us for i2c.
228 // grab cols from left hand 167
229 matrix[i] = debounce_read_cols(i); 168 // grab left + right cols.
230 // grab cols from right hand 169 raw_matrix[i] = read_cols(i);
231 matrix[i + MATRIX_ROWS_PER_SIDE] = debounce_read_cols(i + MATRIX_ROWS_PER_SIDE); 170 raw_matrix[i+MATRIX_ROWS_PER_SIDE] = read_cols(i+MATRIX_ROWS_PER_SIDE);
232 171
233 unselect_rows(); 172 unselect_rows();
234 } 173 }
235 174
236 matrix_scan_quantum(); 175 debounce(raw_matrix, matrix, MATRIX_ROWS, true);
176 matrix_scan_quantum();
237 177
238 return 1; 178 return 1;
239} 179}
240 180
241bool matrix_is_modified(void) // deprecated and evidently not called. 181bool matrix_is_modified(void) // deprecated and evidently not called.
242{ 182{
243 return true; 183 return true;
244} 184}
245 185
246inline 186inline bool matrix_is_on(uint8_t row, uint8_t col) { return (matrix[row] & ((matrix_row_t)1 << col)); }
247bool matrix_is_on(uint8_t row, uint8_t col)
248{
249 return (matrix[row] & ((matrix_row_t)1<<col));
250}
251 187
252inline 188inline matrix_row_t matrix_get_row(uint8_t row) { return matrix[row]; }
253matrix_row_t matrix_get_row(uint8_t row)
254{
255 return matrix[row];
256}
257 189
258void matrix_print(void) 190void matrix_print(void) {
259{ 191 print("\nr/c 0123456789ABCDEF\n");
260 print("\nr/c 0123456789ABCDEF\n"); 192 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
261 for (uint8_t row = 0; row < MATRIX_ROWS; row++) { 193 phex(row);
262 phex(row); print(": "); 194 print(": ");
263 pbin_reverse16(matrix_get_row(row)); 195 pbin_reverse16(matrix_get_row(row));
264 print("\n"); 196 print("\n");
265 } 197 }
266} 198}
267 199
268uint8_t matrix_key_count(void) 200uint8_t matrix_key_count(void) {
269{ 201 uint8_t count = 0;
270 uint8_t count = 0; 202 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
271 for (uint8_t i = 0; i < MATRIX_ROWS; i++) { 203 count += bitpop16(matrix[i]);
272 count += bitpop16(matrix[i]); 204 }
273 } 205 return count;
274 return count;
275} 206}
276 207
277/* Column pin configuration 208/* Column pin configuration
@@ -284,43 +215,45 @@ uint8_t matrix_key_count(void)
284 * col: 0 1 2 3 4 5 215 * col: 0 1 2 3 4 5
285 * pin: B5 B4 B3 B2 B1 B0 216 * pin: B5 B4 B3 B2 B1 B0
286 */ 217 */
287static void init_cols(void) 218static void init_cols(void) {
288{ 219 // init on mcp23018
289 // init on mcp23018 220 // not needed, already done as part of init_mcp23018()
290 // not needed, already done as part of init_mcp23018() 221
291 222 // init on teensy
292 // init on teensy 223 // Input with pull-up(DDR:0, PORT:1)
293 // Input with pull-up(DDR:0, PORT:1) 224 DDRF &= ~(1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 1 | 1 << 0);
294 DDRF &= ~(1<<7 | 1<<6 | 1<<5 | 1<<4 | 1<<1 | 1<<0); 225 PORTF |= (1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 1 | 1 << 0);
295 PORTF |= (1<<7 | 1<<6 | 1<<5 | 1<<4 | 1<<1 | 1<<0);
296} 226}
297 227
298static matrix_row_t read_cols(uint8_t row) 228static matrix_row_t read_cols(uint8_t row) {
299{ 229 if (row < 7) {
300 if (row < 7) { 230 if (mcp23018_status) { // if there was an error
301 if (mcp23018_status) { // if there was an error 231 return 0;
302 return 0;
303 } else {
304 uint8_t data = 0;
305 mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
306 mcp23018_status = i2c_write(GPIOB, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
307 mcp23018_status = i2c_start(I2C_ADDR_READ, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
308 mcp23018_status = i2c_read_nack(ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status < 0) goto out;
309 data = ~((uint8_t)mcp23018_status);
310 mcp23018_status = I2C_STATUS_SUCCESS;
311 out:
312 i2c_stop();
313 return data;
314 }
315 } else { 232 } else {
316 /* read from teensy 233 uint8_t data = 0;
317 * bitmask is 0b11110011, but we want those all 234 mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT);
318 * in the lower six bits. 235 if (mcp23018_status) goto out;
319 * we'll return 1s for the top two, but that's harmless. 236 mcp23018_status = i2c_write(GPIOB, ERGODOX_EZ_I2C_TIMEOUT);
320 */ 237 if (mcp23018_status) goto out;
321 238 mcp23018_status = i2c_start(I2C_ADDR_READ, ERGODOX_EZ_I2C_TIMEOUT);
322 return ~((PINF & 0x03) | ((PINF & 0xF0) >> 2)); 239 if (mcp23018_status) goto out;
240 mcp23018_status = i2c_read_nack(ERGODOX_EZ_I2C_TIMEOUT);
241 if (mcp23018_status < 0) goto out;
242 data = ~((uint8_t)mcp23018_status);
243 mcp23018_status = I2C_STATUS_SUCCESS;
244 out:
245 i2c_stop();
246 return data;
323 } 247 }
248 } else {
249 /* read from teensy
250 * bitmask is 0b11110011, but we want those all
251 * in the lower six bits.
252 * we'll return 1s for the top two, but that's harmless.
253 */
254
255 return ~((PINF & 0x03) | ((PINF & 0xF0) >> 2));
256 }
324} 257}
325 258
326/* Row pin configuration 259/* Row pin configuration
@@ -333,69 +266,70 @@ static matrix_row_t read_cols(uint8_t row)
333 * row: 0 1 2 3 4 5 6 266 * row: 0 1 2 3 4 5 6
334 * pin: A0 A1 A2 A3 A4 A5 A6 267 * pin: A0 A1 A2 A3 A4 A5 A6
335 */ 268 */
336static void unselect_rows(void) 269static void unselect_rows(void) {
337{ 270 // no need to unselect on mcp23018, because the select step sets all
338 // no need to unselect on mcp23018, because the select step sets all 271 // the other row bits high, and it's not changing to a different
339 // the other row bits high, and it's not changing to a different 272 // direction
340 // direction 273
341 274 // unselect on teensy
342 // unselect on teensy 275 // Hi-Z(DDR:0, PORT:0) to unselect
343 // Hi-Z(DDR:0, PORT:0) to unselect 276 DDRB &= ~(1 << 0 | 1 << 1 | 1 << 2 | 1 << 3);
344 DDRB &= ~(1<<0 | 1<<1 | 1<<2 | 1<<3); 277 PORTB &= ~(1 << 0 | 1 << 1 | 1 << 2 | 1 << 3);
345 PORTB &= ~(1<<0 | 1<<1 | 1<<2 | 1<<3); 278 DDRD &= ~(1 << 2 | 1 << 3);
346 DDRD &= ~(1<<2 | 1<<3); 279 PORTD &= ~(1 << 2 | 1 << 3);
347 PORTD &= ~(1<<2 | 1<<3); 280 DDRC &= ~(1 << 6);
348 DDRC &= ~(1<<6); 281 PORTC &= ~(1 << 6);
349 PORTC &= ~(1<<6);
350} 282}
351 283
352static void select_row(uint8_t row) 284static void select_row(uint8_t row) {
353{ 285 if (row < 7) {
354 if (row < 7) { 286 // select on mcp23018
355 // select on mcp23018 287 if (mcp23018_status) { // if there was an error
356 if (mcp23018_status) { // if there was an error 288 // do nothing
357 // do nothing
358 } else {
359 // set active row low : 0
360 // set other rows hi-Z : 1
361 mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
362 mcp23018_status = i2c_write(GPIOA, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
363 mcp23018_status = i2c_write(0xFF & ~(1<<row), ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
364 out:
365 i2c_stop();
366 }
367 } else { 289 } else {
368 // select on teensy 290 // set active row low : 0
369 // Output low(DDR:1, PORT:0) to select 291 // set other rows hi-Z : 1
370 switch (row) { 292 mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT);
371 case 7: 293 if (mcp23018_status) goto out;
372 DDRB |= (1<<0); 294 mcp23018_status = i2c_write(GPIOA, ERGODOX_EZ_I2C_TIMEOUT);
373 PORTB &= ~(1<<0); 295 if (mcp23018_status) goto out;
374 break; 296 mcp23018_status = i2c_write(0xFF & ~(1 << row), ERGODOX_EZ_I2C_TIMEOUT);
375 case 8: 297 if (mcp23018_status) goto out;
376 DDRB |= (1<<1); 298 out:
377 PORTB &= ~(1<<1); 299 i2c_stop();
378 break; 300 }
379 case 9: 301 } else {
380 DDRB |= (1<<2); 302 // select on teensy
381 PORTB &= ~(1<<2); 303 // Output low(DDR:1, PORT:0) to select
382 break; 304 switch (row) {
383 case 10: 305 case 7:
384 DDRB |= (1<<3); 306 DDRB |= (1 << 0);
385 PORTB &= ~(1<<3); 307 PORTB &= ~(1 << 0);
386 break; 308 break;
387 case 11: 309 case 8:
388 DDRD |= (1<<2); 310 DDRB |= (1 << 1);
389 PORTD &= ~(1<<2); 311 PORTB &= ~(1 << 1);
390 break; 312 break;
391 case 12: 313 case 9:
392 DDRD |= (1<<3); 314 DDRB |= (1 << 2);
393 PORTD &= ~(1<<3); 315 PORTB &= ~(1 << 2);
394 break; 316 break;
395 case 13: 317 case 10:
396 DDRC |= (1<<6); 318 DDRB |= (1 << 3);
397 PORTC &= ~(1<<6); 319 PORTB &= ~(1 << 3);
398 break; 320 break;
399 } 321 case 11:
322 DDRD |= (1 << 2);
323 PORTD &= ~(1 << 2);
324 break;
325 case 12:
326 DDRD |= (1 << 3);
327 PORTD &= ~(1 << 3);
328 break;
329 case 13:
330 DDRC |= (1 << 6);
331 PORTC &= ~(1 << 6);
332 break;
400 } 333 }
334 }
401} 335}
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
83API_SYSEX_ENABLE = no 83API_SYSEX_ENABLE = no
84RGBLIGHT_ENABLE = yes 84RGBLIGHT_ENABLE = yes
85RGB_MATRIX_ENABLE = no # enable later 85RGB_MATRIX_ENABLE = no # enable later
86DEBOUNCE_TYPE = eager_pr
86 87
87ifeq ($(strip $(RGB_MATRIX_ENABLE)), no) 88ifeq ($(strip $(RGB_MATRIX_ENABLE)), no)
88 SRC += i2c_master.c 89 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 @@
1/*
2Copyright 2019 Alex Ong<the.onga@gmail.com>
3This program is free software: you can redistribute it and/or modify
4it under the terms of the GNU General Public License as published by
5the Free Software Foundation, either version 2 of the License, or
6(at your option) any later version.
7This program is distributed in the hope that it will be useful,
8but WITHOUT ANY WARRANTY; without even the implied warranty of
9MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10GNU General Public License for more details.
11You should have received a copy of the GNU General Public License
12along with this program. If not, see <http://www.gnu.org/licenses/>.
13*/
14
15/*
16Basic per-row algorithm. Uses an 8-bit counter per row.
17After pressing a key, it immediately changes state, and sets a counter.
18No further inputs are accepted until DEBOUNCE milliseconds have occurred.
19*/
20
21#include "matrix.h"
22#include "timer.h"
23#include "quantum.h"
24#include <stdlib.h>
25
26#ifndef DEBOUNCE
27 #define DEBOUNCE 5
28#endif
29
30
31#define debounce_counter_t uint8_t
32
33static debounce_counter_t *debounce_counters;
34
35#define DEBOUNCE_ELAPSED 251
36#define MAX_DEBOUNCE (DEBOUNCE_ELAPSED - 1)
37
38void update_debounce_counters(uint8_t num_rows, uint8_t current_time);
39void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time);
40
41//we use num_rows rather than MATRIX_ROWS to support split keyboards
42void debounce_init(uint8_t num_rows)
43{
44 debounce_counters = (debounce_counter_t*)malloc(num_rows*sizeof(debounce_counter_t));
45 for (uint8_t r = 0; r < num_rows; r++)
46 {
47 debounce_counters[r] = DEBOUNCE_ELAPSED;
48 }
49}
50
51void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed)
52{
53 uint8_t current_time = timer_read() % MAX_DEBOUNCE;
54 update_debounce_counters(num_rows, current_time);
55 transfer_matrix_values(raw, cooked, num_rows, current_time);
56}
57
58//If the current time is > debounce counter, set the counter to enable input.
59void update_debounce_counters(uint8_t num_rows, uint8_t current_time)
60{
61 debounce_counter_t *debounce_pointer = debounce_counters;
62 for (uint8_t row = 0; row < num_rows; row++)
63 {
64 if (*debounce_pointer != DEBOUNCE_ELAPSED)
65 {
66 if (TIMER_DIFF(current_time, *debounce_pointer, MAX_DEBOUNCE) >= DEBOUNCE) {
67 *debounce_pointer = DEBOUNCE_ELAPSED;
68 }
69 }
70 debounce_pointer++;
71 }
72}
73
74// upload from raw_matrix to final matrix;
75void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time)
76{
77 debounce_counter_t *debounce_pointer = debounce_counters;
78 for (uint8_t row = 0; row < num_rows; row++)
79 {
80 matrix_row_t existing_row = cooked[row];
81 matrix_row_t raw_row = raw[row];
82
83 //determine new value basd on debounce pointer + raw value
84 if (*debounce_pointer == DEBOUNCE_ELAPSED &&
85 (existing_row != raw_row))
86 {
87 *debounce_pointer = current_time;
88 existing_row = raw_row;
89 }
90 cooked[row] = existing_row;
91
92 debounce_pointer++;
93 }
94}
95
96bool debounce_active(void)
97{
98 return true;
99}
100
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:
22sym_g.c 22sym_g.c
23sym_pk.c 23sym_pk.c
24sym_pr.c 24sym_pr.c
25sym_pr_cycles.c //currently used in ergo-dox 25sym_pr_cycles.c
26eager_g.c 26eager_g.c
27eager_pk.c 27eager_pk.c
28eager_pr.c //could be used in ergo-dox! 28eager_pr.c //could be used in ergo-dox!