diff options
Diffstat (limited to 'quantum/matrix.c')
-rw-r--r-- | quantum/matrix.c | 326 |
1 files changed, 221 insertions, 105 deletions
diff --git a/quantum/matrix.c b/quantum/matrix.c index 3174e0739..07eb87bc3 100644 --- a/quantum/matrix.c +++ b/quantum/matrix.c | |||
@@ -25,37 +25,65 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
25 | #include "debug.h" | 25 | #include "debug.h" |
26 | #include "util.h" | 26 | #include "util.h" |
27 | #include "matrix.h" | 27 | #include "matrix.h" |
28 | #include "timer.h" | ||
29 | |||
28 | 30 | ||
29 | /* Set 0 if debouncing isn't needed */ | 31 | /* Set 0 if debouncing isn't needed */ |
30 | 32 | ||
31 | #ifndef DEBOUNCING_DELAY | 33 | #ifndef DEBOUNCING_DELAY |
32 | # define DEBOUNCING_DELAY 5 | 34 | # define DEBOUNCING_DELAY 5 |
33 | #endif | 35 | #endif |
34 | static uint8_t debouncing = DEBOUNCING_DELAY; | 36 | |
37 | #if (DEBOUNCING_DELAY > 0) | ||
38 | static uint16_t debouncing_time; | ||
39 | static bool debouncing = false; | ||
40 | #endif | ||
41 | |||
42 | #if (MATRIX_COLS <= 8) | ||
43 | # define print_matrix_header() print("\nr/c 01234567\n") | ||
44 | # define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row)) | ||
45 | # define matrix_bitpop(i) bitpop(matrix[i]) | ||
46 | # define ROW_SHIFTER ((uint8_t)1) | ||
47 | #elif (MATRIX_COLS <= 16) | ||
48 | # define print_matrix_header() print("\nr/c 0123456789ABCDEF\n") | ||
49 | # define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row)) | ||
50 | # define matrix_bitpop(i) bitpop16(matrix[i]) | ||
51 | # define ROW_SHIFTER ((uint16_t)1) | ||
52 | #elif (MATRIX_COLS <= 32) | ||
53 | # define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n") | ||
54 | # define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row)) | ||
55 | # define matrix_bitpop(i) bitpop32(matrix[i]) | ||
56 | # define ROW_SHIFTER ((uint32_t)1) | ||
57 | #endif | ||
58 | |||
59 | #ifdef MATRIX_MASKED | ||
60 | extern const matrix_row_t matrix_mask[]; | ||
61 | #endif | ||
35 | 62 | ||
36 | static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; | 63 | static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; |
37 | static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; | 64 | static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; |
38 | 65 | ||
39 | /* matrix state(1:on, 0:off) */ | 66 | /* matrix state(1:on, 0:off) */ |
40 | static matrix_row_t matrix[MATRIX_ROWS]; | 67 | static matrix_row_t matrix[MATRIX_ROWS]; |
68 | |||
69 | static matrix_row_t matrix_raw[MATRIX_ROWS]; | ||
41 | static matrix_row_t matrix_debouncing[MATRIX_ROWS]; | 70 | static matrix_row_t matrix_debouncing[MATRIX_ROWS]; |
42 | 71 | ||
43 | #if DIODE_DIRECTION == ROW2COL | ||
44 | static matrix_row_t matrix_reversed[MATRIX_COLS]; | ||
45 | static matrix_row_t matrix_reversed_debouncing[MATRIX_COLS]; | ||
46 | #endif | ||
47 | 72 | ||
48 | #if MATRIX_COLS > 16 | 73 | #if (DIODE_DIRECTION == COL2ROW) |
49 | #define SHIFTER 1UL | 74 | static void init_cols(void); |
50 | #else | 75 | static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row); |
51 | #define SHIFTER 1 | 76 | static void unselect_rows(void); |
77 | static void select_row(uint8_t row); | ||
78 | static void unselect_row(uint8_t row); | ||
79 | #else // ROW2COL | ||
80 | static void init_rows(void); | ||
81 | static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col); | ||
82 | static void unselect_cols(void); | ||
83 | static void unselect_col(uint8_t col); | ||
84 | static void select_col(uint8_t col); | ||
52 | #endif | 85 | #endif |
53 | 86 | ||
54 | static matrix_row_t read_cols(void); | ||
55 | static void init_cols(void); | ||
56 | static void unselect_rows(void); | ||
57 | static void select_row(uint8_t row); | ||
58 | |||
59 | __attribute__ ((weak)) | 87 | __attribute__ ((weak)) |
60 | void matrix_init_quantum(void) { | 88 | void matrix_init_quantum(void) { |
61 | matrix_init_kb(); | 89 | matrix_init_kb(); |
@@ -95,7 +123,7 @@ uint8_t matrix_cols(void) { | |||
95 | } | 123 | } |
96 | 124 | ||
97 | // void matrix_power_up(void) { | 125 | // void matrix_power_up(void) { |
98 | // #if DIODE_DIRECTION == COL2ROW | 126 | // #if (DIODE_DIRECTION == COL2ROW) |
99 | // for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { | 127 | // for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { |
100 | // /* DDRxn */ | 128 | // /* DDRxn */ |
101 | // _SFR_IO8((row_pins[r] >> 4) + 1) |= _BV(row_pins[r] & 0xF); | 129 | // _SFR_IO8((row_pins[r] >> 4) + 1) |= _BV(row_pins[r] & 0xF); |
@@ -119,19 +147,26 @@ uint8_t matrix_cols(void) { | |||
119 | // } | 147 | // } |
120 | 148 | ||
121 | void matrix_init(void) { | 149 | void matrix_init(void) { |
150 | |||
122 | // To use PORTF disable JTAG with writing JTD bit twice within four cycles. | 151 | // To use PORTF disable JTAG with writing JTD bit twice within four cycles. |
123 | #ifdef __AVR_ATmega32U4__ | 152 | #if (defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega32U4__)) |
124 | MCUCR |= _BV(JTD); | 153 | MCUCR |= _BV(JTD); |
125 | MCUCR |= _BV(JTD); | 154 | MCUCR |= _BV(JTD); |
126 | #endif | 155 | #endif |
127 | 156 | ||
128 | // initialize row and col | 157 | // initialize row and col |
158 | #if (DIODE_DIRECTION == COL2ROW) | ||
129 | unselect_rows(); | 159 | unselect_rows(); |
130 | init_cols(); | 160 | init_cols(); |
161 | #else // ROW2COL | ||
162 | unselect_cols(); | ||
163 | init_rows(); | ||
164 | #endif | ||
131 | 165 | ||
132 | // initialize matrix state: all keys off | 166 | // initialize matrix state: all keys off |
133 | for (uint8_t i=0; i < MATRIX_ROWS; i++) { | 167 | for (uint8_t i=0; i < MATRIX_ROWS; i++) { |
134 | matrix[i] = 0; | 168 | matrix[i] = 0; |
169 | matrix_raw[i] = 0; | ||
135 | matrix_debouncing[i] = 0; | 170 | matrix_debouncing[i] = 0; |
136 | } | 171 | } |
137 | 172 | ||
@@ -141,71 +176,60 @@ void matrix_init(void) { | |||
141 | uint8_t matrix_scan(void) | 176 | uint8_t matrix_scan(void) |
142 | { | 177 | { |
143 | 178 | ||
144 | #if DIODE_DIRECTION == COL2ROW | 179 | #if (DIODE_DIRECTION == COL2ROW) |
145 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | ||
146 | select_row(i); | ||
147 | wait_us(30); // without this wait read unstable value. | ||
148 | matrix_row_t cols = read_cols(); | ||
149 | if (matrix_debouncing[i] != cols) { | ||
150 | matrix_debouncing[i] = cols; | ||
151 | if (debouncing) { | ||
152 | debug("bounce!: "); debug_hex(debouncing); debug("\n"); | ||
153 | } | ||
154 | debouncing = DEBOUNCING_DELAY; | ||
155 | } | ||
156 | unselect_rows(); | ||
157 | } | ||
158 | 180 | ||
159 | if (debouncing) { | 181 | // Set row, read cols |
160 | if (--debouncing) { | 182 | for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) { |
161 | wait_ms(1); | 183 | # if (DEBOUNCING_DELAY > 0) |
162 | } else { | 184 | bool matrix_changed = read_cols_on_row(matrix_debouncing, current_row); |
163 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | 185 | |
164 | matrix[i] = matrix_debouncing[i]; | 186 | if (matrix_changed) { |
187 | debouncing = true; | ||
188 | debouncing_time = timer_read(); | ||
165 | } | 189 | } |
166 | } | 190 | |
191 | # else | ||
192 | read_cols_on_row(matrix, current_row); | ||
193 | # endif | ||
194 | |||
167 | } | 195 | } |
168 | #else | 196 | |
169 | for (uint8_t i = 0; i < MATRIX_COLS; i++) { | 197 | #else // ROW2COL |
170 | select_row(i); | 198 | |
171 | wait_us(30); // without this wait read unstable value. | 199 | // Set col, read rows |
172 | matrix_row_t rows = read_cols(); | 200 | for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { |
173 | if (matrix_reversed_debouncing[i] != rows) { | 201 | # if (DEBOUNCING_DELAY > 0) |
174 | matrix_reversed_debouncing[i] = rows; | 202 | bool matrix_changed = read_rows_on_col(matrix_debouncing, current_col); |
175 | if (debouncing) { | 203 | if (matrix_changed) { |
176 | debug("bounce!: "); debug_hex(debouncing); debug("\n"); | 204 | debouncing = true; |
205 | debouncing_time = timer_read(); | ||
177 | } | 206 | } |
178 | debouncing = DEBOUNCING_DELAY; | 207 | # else |
179 | } | 208 | read_rows_on_col(matrix, current_col); |
180 | unselect_rows(); | 209 | # endif |
210 | |||
181 | } | 211 | } |
182 | 212 | ||
183 | if (debouncing) { | 213 | #endif |
184 | if (--debouncing) { | 214 | |
185 | wait_ms(1); | 215 | # if (DEBOUNCING_DELAY > 0) |
186 | } else { | 216 | if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCING_DELAY)) { |
187 | for (uint8_t i = 0; i < MATRIX_COLS; i++) { | 217 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { |
188 | matrix_reversed[i] = matrix_reversed_debouncing[i]; | 218 | matrix[i] = matrix_debouncing[i]; |
189 | } | 219 | } |
220 | debouncing = false; | ||
190 | } | 221 | } |
191 | } | 222 | # endif |
192 | for (uint8_t y = 0; y < MATRIX_ROWS; y++) { | ||
193 | matrix_row_t row = 0; | ||
194 | for (uint8_t x = 0; x < MATRIX_COLS; x++) { | ||
195 | row |= ((matrix_reversed[x] & (1<<y)) >> y) << x; | ||
196 | } | ||
197 | matrix[y] = row; | ||
198 | } | ||
199 | #endif | ||
200 | 223 | ||
201 | matrix_scan_quantum(); | 224 | matrix_scan_quantum(); |
202 | |||
203 | return 1; | 225 | return 1; |
204 | } | 226 | } |
205 | 227 | ||
206 | bool matrix_is_modified(void) | 228 | bool matrix_is_modified(void) |
207 | { | 229 | { |
230 | #if (DEBOUNCING_DELAY > 0) | ||
208 | if (debouncing) return false; | 231 | if (debouncing) return false; |
232 | #endif | ||
209 | return true; | 233 | return true; |
210 | } | 234 | } |
211 | 235 | ||
@@ -218,15 +242,22 @@ bool matrix_is_on(uint8_t row, uint8_t col) | |||
218 | inline | 242 | inline |
219 | matrix_row_t matrix_get_row(uint8_t row) | 243 | matrix_row_t matrix_get_row(uint8_t row) |
220 | { | 244 | { |
245 | // Matrix mask lets you disable switches in the returned matrix data. For example, if you have a | ||
246 | // switch blocker installed and the switch is always pressed. | ||
247 | #ifdef MATRIX_MASKED | ||
248 | return matrix[row] & matrix_mask[row]; | ||
249 | #else | ||
221 | return matrix[row]; | 250 | return matrix[row]; |
251 | #endif | ||
222 | } | 252 | } |
223 | 253 | ||
224 | void matrix_print(void) | 254 | void matrix_print(void) |
225 | { | 255 | { |
226 | print("\nr/c 0123456789ABCDEF\n"); | 256 | print_matrix_header(); |
257 | |||
227 | for (uint8_t row = 0; row < MATRIX_ROWS; row++) { | 258 | for (uint8_t row = 0; row < MATRIX_ROWS; row++) { |
228 | phex(row); print(": "); | 259 | phex(row); print(": "); |
229 | pbin_reverse16(matrix_get_row(row)); | 260 | print_matrix_row(row); |
230 | print("\n"); | 261 | print("\n"); |
231 | } | 262 | } |
232 | } | 263 | } |
@@ -235,63 +266,148 @@ uint8_t matrix_key_count(void) | |||
235 | { | 266 | { |
236 | uint8_t count = 0; | 267 | uint8_t count = 0; |
237 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | 268 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { |
238 | count += bitpop16(matrix[i]); | 269 | count += matrix_bitpop(i); |
239 | } | 270 | } |
240 | return count; | 271 | return count; |
241 | } | 272 | } |
242 | 273 | ||
274 | |||
275 | |||
276 | #if (DIODE_DIRECTION == COL2ROW) | ||
277 | |||
243 | static void init_cols(void) | 278 | static void init_cols(void) |
244 | { | 279 | { |
245 | #if DIODE_DIRECTION == COL2ROW | 280 | for(uint8_t x = 0; x < MATRIX_COLS; x++) { |
246 | for(int x = 0; x < MATRIX_COLS; x++) { | 281 | uint8_t pin = col_pins[x]; |
247 | int pin = col_pins[x]; | 282 | _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN |
248 | #else | 283 | _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI |
249 | for(int x = 0; x < MATRIX_ROWS; x++) { | ||
250 | int pin = row_pins[x]; | ||
251 | #endif | ||
252 | _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); | ||
253 | _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); | ||
254 | } | 284 | } |
255 | } | 285 | } |
256 | 286 | ||
257 | static matrix_row_t read_cols(void) | 287 | static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) |
258 | { | 288 | { |
259 | matrix_row_t result = 0; | 289 | // Store last value of row prior to reading |
290 | matrix_row_t last_row_value = current_matrix[current_row]; | ||
260 | 291 | ||
261 | #if DIODE_DIRECTION == COL2ROW | 292 | // Clear data in matrix row |
262 | for(int x = 0; x < MATRIX_COLS; x++) { | 293 | current_matrix[current_row] = 0; |
263 | int pin = col_pins[x]; | 294 | |
264 | #else | 295 | // Select row and wait for row selecton to stabilize |
265 | for(int x = 0; x < MATRIX_ROWS; x++) { | 296 | select_row(current_row); |
266 | int pin = row_pins[x]; | 297 | wait_us(30); |
267 | #endif | 298 | |
268 | result |= (_SFR_IO8(pin >> 4) & _BV(pin & 0xF)) ? 0 : (SHIFTER << x); | 299 | // For each col... |
300 | for(uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { | ||
301 | |||
302 | // Select the col pin to read (active low) | ||
303 | uint8_t pin = col_pins[col_index]; | ||
304 | uint8_t pin_state = (_SFR_IO8(pin >> 4) & _BV(pin & 0xF)); | ||
305 | |||
306 | // Populate the matrix row with the state of the col pin | ||
307 | current_matrix[current_row] |= pin_state ? 0 : (ROW_SHIFTER << col_index); | ||
269 | } | 308 | } |
270 | return result; | 309 | |
310 | // Unselect row | ||
311 | unselect_row(current_row); | ||
312 | |||
313 | return (last_row_value != current_matrix[current_row]); | ||
314 | } | ||
315 | |||
316 | static void select_row(uint8_t row) | ||
317 | { | ||
318 | uint8_t pin = row_pins[row]; | ||
319 | _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT | ||
320 | _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW | ||
321 | } | ||
322 | |||
323 | static void unselect_row(uint8_t row) | ||
324 | { | ||
325 | uint8_t pin = row_pins[row]; | ||
326 | _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN | ||
327 | _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI | ||
271 | } | 328 | } |
272 | 329 | ||
273 | static void unselect_rows(void) | 330 | static void unselect_rows(void) |
274 | { | 331 | { |
275 | #if DIODE_DIRECTION == COL2ROW | 332 | for(uint8_t x = 0; x < MATRIX_ROWS; x++) { |
276 | for(int x = 0; x < MATRIX_ROWS; x++) { | 333 | uint8_t pin = row_pins[x]; |
277 | int pin = row_pins[x]; | 334 | _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN |
278 | #else | 335 | _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI |
279 | for(int x = 0; x < MATRIX_COLS; x++) { | ||
280 | int pin = col_pins[x]; | ||
281 | #endif | ||
282 | _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); | ||
283 | _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); | ||
284 | } | 336 | } |
285 | } | 337 | } |
286 | 338 | ||
287 | static void select_row(uint8_t row) | 339 | #else // ROW2COL |
340 | |||
341 | static void init_rows(void) | ||
288 | { | 342 | { |
343 | for(uint8_t x = 0; x < MATRIX_ROWS; x++) { | ||
344 | uint8_t pin = row_pins[x]; | ||
345 | _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN | ||
346 | _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI | ||
347 | } | ||
348 | } | ||
289 | 349 | ||
290 | #if DIODE_DIRECTION == COL2ROW | 350 | static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) |
291 | int pin = row_pins[row]; | 351 | { |
292 | #else | 352 | bool matrix_changed = false; |
293 | int pin = col_pins[row]; | 353 | |
294 | #endif | 354 | // Select col and wait for col selecton to stabilize |
295 | _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); | 355 | select_col(current_col); |
296 | _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); | 356 | wait_us(30); |
357 | |||
358 | // For each row... | ||
359 | for(uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) | ||
360 | { | ||
361 | |||
362 | // Store last value of row prior to reading | ||
363 | matrix_row_t last_row_value = current_matrix[row_index]; | ||
364 | |||
365 | // Check row pin state | ||
366 | if ((_SFR_IO8(row_pins[row_index] >> 4) & _BV(row_pins[row_index] & 0xF)) == 0) | ||
367 | { | ||
368 | // Pin LO, set col bit | ||
369 | current_matrix[row_index] |= (ROW_SHIFTER << current_col); | ||
370 | } | ||
371 | else | ||
372 | { | ||
373 | // Pin HI, clear col bit | ||
374 | current_matrix[row_index] &= ~(ROW_SHIFTER << current_col); | ||
375 | } | ||
376 | |||
377 | // Determine if the matrix changed state | ||
378 | if ((last_row_value != current_matrix[row_index]) && !(matrix_changed)) | ||
379 | { | ||
380 | matrix_changed = true; | ||
381 | } | ||
382 | } | ||
383 | |||
384 | // Unselect col | ||
385 | unselect_col(current_col); | ||
386 | |||
387 | return matrix_changed; | ||
297 | } | 388 | } |
389 | |||
390 | static void select_col(uint8_t col) | ||
391 | { | ||
392 | uint8_t pin = col_pins[col]; | ||
393 | _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT | ||
394 | _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW | ||
395 | } | ||
396 | |||
397 | static void unselect_col(uint8_t col) | ||
398 | { | ||
399 | uint8_t pin = col_pins[col]; | ||
400 | _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN | ||
401 | _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI | ||
402 | } | ||
403 | |||
404 | static void unselect_cols(void) | ||
405 | { | ||
406 | for(uint8_t x = 0; x < MATRIX_COLS; x++) { | ||
407 | uint8_t pin = col_pins[x]; | ||
408 | _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN | ||
409 | _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI | ||
410 | } | ||
411 | } | ||
412 | |||
413 | #endif | ||