Update Dvorak, Colemak and Workman keycode aliases (#8217)
[jackhill/qmk/firmware.git] / quantum / matrix.c
CommitLineData
04885a3b 1/*
7fe03d08 2Copyright 2012-2018 Jun Wako, Jack Humbert, Yiancar
04885a3b
JH
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
04885a3b
JH
17#include <stdint.h>
18#include <stdbool.h>
04885a3b
JH
19#include "util.h"
20#include "matrix.h"
28929ad0 21#include "debounce.h"
7fe03d08 22#include "quantum.h"
f4030289 23
0137b023 24#ifdef DIRECT_PINS
25static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS;
26#elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW)
7fe03d08 27static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
28static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
8cbf61c9 29#endif
8e88d55b
JH
30
31/* matrix state(1:on, 0:off) */
48cac9e3
JC
32extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values
33extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values
8e88d55b 34
dcb7ca3f 35// matrix code
5bb7ef00 36
0137b023 37#ifdef DIRECT_PINS
38
39static void init_pins(void) {
b624f32f 40 for (int row = 0; row < MATRIX_ROWS; row++) {
41 for (int col = 0; col < MATRIX_COLS; col++) {
42 pin_t pin = direct_pins[row][col];
43 if (pin != NO_PIN) {
44 setPinInputHigh(pin);
45 }
46 }
0137b023 47 }
0137b023 48}
508eddf8 49
0137b023 50static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
b624f32f 51 matrix_row_t last_row_value = current_matrix[current_row];
52 current_matrix[current_row] = 0;
508eddf8 53
b624f32f 54 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
55 pin_t pin = direct_pins[current_row][col_index];
56 if (pin != NO_PIN) {
dcb7ca3f 57 current_matrix[current_row] |= readPin(pin) ? 0 : (MATRIX_ROW_SHIFTER << col_index);
b624f32f 58 }
0137b023 59 }
0137b023 60
b624f32f 61 return (last_row_value != current_matrix[current_row]);
0137b023 62}
63
eb5d267e 64#elif defined(DIODE_DIRECTION)
65# if (DIODE_DIRECTION == COL2ROW)
0137b023 66
b624f32f 67static void select_row(uint8_t row) {
0137b023 68 setPinOutput(row_pins[row]);
69 writePinLow(row_pins[row]);
70}
71
b624f32f 72static void unselect_row(uint8_t row) { setPinInputHigh(row_pins[row]); }
0137b023 73
b624f32f 74static void unselect_rows(void) {
75 for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
f2689937 76 setPinInputHigh(row_pins[x]);
8e88d55b 77 }
04885a3b
JH
78}
79
0137b023 80static void init_pins(void) {
b624f32f 81 unselect_rows();
82 for (uint8_t x = 0; x < MATRIX_COLS; x++) {
83 setPinInputHigh(col_pins[x]);
84 }
0137b023 85}
86
b624f32f 87static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
f4030289
I
88 // Store last value of row prior to reading
89 matrix_row_t last_row_value = current_matrix[current_row];
90
4c696083
I
91 // Clear data in matrix row
92 current_matrix[current_row] = 0;
5bb7ef00 93
4c696083
I
94 // Select row and wait for row selecton to stabilize
95 select_row(current_row);
7707724d 96 matrix_io_delay();
508eddf8 97
4c696083 98 // For each col...
b624f32f 99 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
4c696083 100 // Select the col pin to read (active low)
7fe03d08 101 uint8_t pin_state = readPin(col_pins[col_index]);
4c696083
I
102
103 // Populate the matrix row with the state of the col pin
dcb7ca3f 104 current_matrix[current_row] |= pin_state ? 0 : (MATRIX_ROW_SHIFTER << col_index);
4c696083 105 }
32f88c07
I
106
107 // Unselect row
108 unselect_row(current_row);
f4030289 109
a06115df 110 return (last_row_value != current_matrix[current_row]);
04885a3b
JH
111}
112
eb5d267e 113# elif (DIODE_DIRECTION == ROW2COL)
0137b023 114
b624f32f 115static void select_col(uint8_t col) {
0137b023 116 setPinOutput(col_pins[col]);
117 writePinLow(col_pins[col]);
508eddf8
I
118}
119
b624f32f 120static void unselect_col(uint8_t col) { setPinInputHigh(col_pins[col]); }
508eddf8 121
b624f32f 122static void unselect_cols(void) {
123 for (uint8_t x = 0; x < MATRIX_COLS; x++) {
0137b023 124 setPinInputHigh(col_pins[x]);
aaa758f1 125 }
8e88d55b
JH
126}
127
0137b023 128static void init_pins(void) {
b624f32f 129 unselect_cols();
130 for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
131 setPinInputHigh(row_pins[x]);
132 }
508eddf8 133}
8e88d55b 134
b624f32f 135static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {
f4030289 136 bool matrix_changed = false;
508eddf8 137
4c696083
I
138 // Select col and wait for col selecton to stabilize
139 select_col(current_col);
7707724d 140 matrix_io_delay();
508eddf8 141
4c696083 142 // For each row...
b624f32f 143 for (uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) {
f4030289
I
144 // Store last value of row prior to reading
145 matrix_row_t last_row_value = current_matrix[row_index];
4c696083 146
32f88c07 147 // Check row pin state
b624f32f 148 if (readPin(row_pins[row_index]) == 0) {
32f88c07 149 // Pin LO, set col bit
dcb7ca3f 150 current_matrix[row_index] |= (MATRIX_ROW_SHIFTER << current_col);
b624f32f 151 } else {
32f88c07 152 // Pin HI, clear col bit
dcb7ca3f 153 current_matrix[row_index] &= ~(MATRIX_ROW_SHIFTER << current_col);
32f88c07 154 }
f4030289
I
155
156 // Determine if the matrix changed state
b624f32f 157 if ((last_row_value != current_matrix[row_index]) && !(matrix_changed)) {
f4030289
I
158 matrix_changed = true;
159 }
4c696083 160 }
32f88c07
I
161
162 // Unselect col
163 unselect_col(current_col);
f4030289
I
164
165 return matrix_changed;
508eddf8
I
166}
167
eb5d267e 168# else
169# error DIODE_DIRECTION must be one of COL2ROW or ROW2COL!
170# endif
171#else
172# error DIODE_DIRECTION is not defined!
0137b023 173#endif
508eddf8 174
0137b023 175void matrix_init(void) {
0137b023 176 // initialize key pins
177 init_pins();
178
179 // initialize matrix state: all keys off
b624f32f 180 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
0137b023 181 raw_matrix[i] = 0;
b624f32f 182 matrix[i] = 0;
508eddf8 183 }
0137b023 184
185 debounce_init(MATRIX_ROWS);
186
187 matrix_init_quantum();
508eddf8
I
188}
189
b624f32f 190uint8_t matrix_scan(void) {
191 bool changed = false;
0137b023 192
193#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW)
b624f32f 194 // Set row, read cols
195 for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
196 changed |= read_cols_on_row(raw_matrix, current_row);
197 }
0137b023 198#elif (DIODE_DIRECTION == ROW2COL)
b624f32f 199 // Set col, read rows
200 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
201 changed |= read_rows_on_col(raw_matrix, current_col);
202 }
508eddf8 203#endif
0137b023 204
b624f32f 205 debounce(raw_matrix, matrix, MATRIX_ROWS, changed);
0137b023 206
b624f32f 207 matrix_scan_quantum();
208 return (uint8_t)changed;
0137b023 209}