Add rules.mk defaults for f103,f072,f042 (#7704)
[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>
aaa758f1 19#include "wait.h"
04885a3b
JH
20#include "print.h"
21#include "debug.h"
22#include "util.h"
23#include "matrix.h"
28929ad0 24#include "debounce.h"
7fe03d08 25#include "quantum.h"
f4030289 26
508eddf8 27#if (MATRIX_COLS <= 8)
b624f32f 28# define print_matrix_header() print("\nr/c 01234567\n")
29# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
30# define matrix_bitpop(i) bitpop(matrix[i])
508eddf8
I
31# define ROW_SHIFTER ((uint8_t)1)
32#elif (MATRIX_COLS <= 16)
b624f32f 33# define print_matrix_header() print("\nr/c 0123456789ABCDEF\n")
34# define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row))
35# define matrix_bitpop(i) bitpop16(matrix[i])
508eddf8
I
36# define ROW_SHIFTER ((uint16_t)1)
37#elif (MATRIX_COLS <= 32)
b624f32f 38# define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n")
39# define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row))
40# define matrix_bitpop(i) bitpop32(matrix[i])
41# define ROW_SHIFTER ((uint32_t)1)
508eddf8
I
42#endif
43
17170ba7 44#ifdef MATRIX_MASKED
b624f32f 45extern const matrix_row_t matrix_mask[];
5bb7ef00
JH
46#endif
47
0137b023 48#ifdef DIRECT_PINS
49static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS;
50#elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW)
7fe03d08 51static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
52static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
8cbf61c9 53#endif
8e88d55b
JH
54
55/* matrix state(1:on, 0:off) */
b624f32f 56static matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values
57static matrix_row_t matrix[MATRIX_ROWS]; // debounced values
4c696083 58
b624f32f 59__attribute__((weak)) void matrix_init_quantum(void) { matrix_init_kb(); }
35a81f5b 60
b624f32f 61__attribute__((weak)) void matrix_scan_quantum(void) { matrix_scan_kb(); }
13bb6b4b 62
b624f32f 63__attribute__((weak)) void matrix_init_kb(void) { matrix_init_user(); }
13bb6b4b 64
b624f32f 65__attribute__((weak)) void matrix_scan_kb(void) { matrix_scan_user(); }
13bb6b4b 66
b624f32f 67__attribute__((weak)) void matrix_init_user(void) {}
13bb6b4b 68
b624f32f 69__attribute__((weak)) void matrix_scan_user(void) {}
35a81f5b 70
b624f32f 71inline uint8_t matrix_rows(void) { return MATRIX_ROWS; }
04885a3b 72
b624f32f 73inline uint8_t matrix_cols(void) { return MATRIX_COLS; }
04885a3b 74
b624f32f 75// Deprecated.
76bool matrix_is_modified(void) {
28929ad0 77 if (debounce_active()) return false;
8e88d55b 78 return true;
aaa758f1 79}
5bb7ef00 80
b624f32f 81inline bool matrix_is_on(uint8_t row, uint8_t col) { return (matrix[row] & ((matrix_row_t)1 << col)); }
8e88d55b 82
b624f32f 83inline matrix_row_t matrix_get_row(uint8_t row) {
17170ba7
I
84 // Matrix mask lets you disable switches in the returned matrix data. For example, if you have a
85 // switch blocker installed and the switch is always pressed.
86#ifdef MATRIX_MASKED
87 return matrix[row] & matrix_mask[row];
88#else
8e88d55b 89 return matrix[row];
17170ba7 90#endif
8e88d55b
JH
91}
92
b624f32f 93void matrix_print(void) {
508eddf8 94 print_matrix_header();
17170ba7 95
8e88d55b 96 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
b624f32f 97 phex(row);
98 print(": ");
508eddf8 99 print_matrix_row(row);
8e88d55b 100 print("\n");
04885a3b 101 }
04885a3b
JH
102}
103
b624f32f 104uint8_t matrix_key_count(void) {
8e88d55b
JH
105 uint8_t count = 0;
106 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
508eddf8 107 count += matrix_bitpop(i);
aaa758f1 108 }
8e88d55b 109 return count;
aaa758f1 110}
5bb7ef00 111
0137b023 112#ifdef DIRECT_PINS
113
114static void init_pins(void) {
b624f32f 115 for (int row = 0; row < MATRIX_ROWS; row++) {
116 for (int col = 0; col < MATRIX_COLS; col++) {
117 pin_t pin = direct_pins[row][col];
118 if (pin != NO_PIN) {
119 setPinInputHigh(pin);
120 }
121 }
0137b023 122 }
0137b023 123}
508eddf8 124
0137b023 125static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
b624f32f 126 matrix_row_t last_row_value = current_matrix[current_row];
127 current_matrix[current_row] = 0;
508eddf8 128
b624f32f 129 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
130 pin_t pin = direct_pins[current_row][col_index];
131 if (pin != NO_PIN) {
132 current_matrix[current_row] |= readPin(pin) ? 0 : (ROW_SHIFTER << col_index);
133 }
0137b023 134 }
0137b023 135
b624f32f 136 return (last_row_value != current_matrix[current_row]);
0137b023 137}
138
139#elif (DIODE_DIRECTION == COL2ROW)
140
b624f32f 141static void select_row(uint8_t row) {
0137b023 142 setPinOutput(row_pins[row]);
143 writePinLow(row_pins[row]);
144}
145
b624f32f 146static void unselect_row(uint8_t row) { setPinInputHigh(row_pins[row]); }
0137b023 147
b624f32f 148static void unselect_rows(void) {
149 for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
f2689937 150 setPinInputHigh(row_pins[x]);
8e88d55b 151 }
04885a3b
JH
152}
153
0137b023 154static void init_pins(void) {
b624f32f 155 unselect_rows();
156 for (uint8_t x = 0; x < MATRIX_COLS; x++) {
157 setPinInputHigh(col_pins[x]);
158 }
0137b023 159}
160
b624f32f 161static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
f4030289
I
162 // Store last value of row prior to reading
163 matrix_row_t last_row_value = current_matrix[current_row];
164
4c696083
I
165 // Clear data in matrix row
166 current_matrix[current_row] = 0;
5bb7ef00 167
4c696083
I
168 // Select row and wait for row selecton to stabilize
169 select_row(current_row);
170 wait_us(30);
508eddf8 171
4c696083 172 // For each col...
b624f32f 173 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
4c696083 174 // Select the col pin to read (active low)
7fe03d08 175 uint8_t pin_state = readPin(col_pins[col_index]);
4c696083
I
176
177 // Populate the matrix row with the state of the col pin
b624f32f 178 current_matrix[current_row] |= pin_state ? 0 : (ROW_SHIFTER << col_index);
4c696083 179 }
32f88c07
I
180
181 // Unselect row
182 unselect_row(current_row);
f4030289 183
a06115df 184 return (last_row_value != current_matrix[current_row]);
04885a3b
JH
185}
186
0137b023 187#elif (DIODE_DIRECTION == ROW2COL)
188
b624f32f 189static void select_col(uint8_t col) {
0137b023 190 setPinOutput(col_pins[col]);
191 writePinLow(col_pins[col]);
508eddf8
I
192}
193
b624f32f 194static void unselect_col(uint8_t col) { setPinInputHigh(col_pins[col]); }
508eddf8 195
b624f32f 196static void unselect_cols(void) {
197 for (uint8_t x = 0; x < MATRIX_COLS; x++) {
0137b023 198 setPinInputHigh(col_pins[x]);
aaa758f1 199 }
8e88d55b
JH
200}
201
0137b023 202static void init_pins(void) {
b624f32f 203 unselect_cols();
204 for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
205 setPinInputHigh(row_pins[x]);
206 }
508eddf8 207}
8e88d55b 208
b624f32f 209static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {
f4030289 210 bool matrix_changed = false;
508eddf8 211
4c696083
I
212 // Select col and wait for col selecton to stabilize
213 select_col(current_col);
214 wait_us(30);
508eddf8 215
4c696083 216 // For each row...
b624f32f 217 for (uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) {
f4030289
I
218 // Store last value of row prior to reading
219 matrix_row_t last_row_value = current_matrix[row_index];
4c696083 220
32f88c07 221 // Check row pin state
b624f32f 222 if (readPin(row_pins[row_index]) == 0) {
32f88c07
I
223 // Pin LO, set col bit
224 current_matrix[row_index] |= (ROW_SHIFTER << current_col);
b624f32f 225 } else {
32f88c07
I
226 // Pin HI, clear col bit
227 current_matrix[row_index] &= ~(ROW_SHIFTER << current_col);
228 }
f4030289
I
229
230 // Determine if the matrix changed state
b624f32f 231 if ((last_row_value != current_matrix[row_index]) && !(matrix_changed)) {
f4030289
I
232 matrix_changed = true;
233 }
4c696083 234 }
32f88c07
I
235
236 // Unselect col
237 unselect_col(current_col);
f4030289
I
238
239 return matrix_changed;
508eddf8
I
240}
241
0137b023 242#endif
508eddf8 243
0137b023 244void matrix_init(void) {
0137b023 245 // initialize key pins
246 init_pins();
247
248 // initialize matrix state: all keys off
b624f32f 249 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
0137b023 250 raw_matrix[i] = 0;
b624f32f 251 matrix[i] = 0;
508eddf8 252 }
0137b023 253
254 debounce_init(MATRIX_ROWS);
255
256 matrix_init_quantum();
508eddf8
I
257}
258
b624f32f 259uint8_t matrix_scan(void) {
260 bool changed = false;
0137b023 261
262#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW)
b624f32f 263 // Set row, read cols
264 for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
265 changed |= read_cols_on_row(raw_matrix, current_row);
266 }
0137b023 267#elif (DIODE_DIRECTION == ROW2COL)
b624f32f 268 // Set col, read rows
269 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
270 changed |= read_rows_on_col(raw_matrix, current_col);
271 }
508eddf8 272#endif
0137b023 273
b624f32f 274 debounce(raw_matrix, matrix, MATRIX_ROWS, changed);
0137b023 275
b624f32f 276 matrix_scan_quantum();
277 return (uint8_t)changed;
0137b023 278}