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