Add customisable EEPROM driver selection (#7274)
[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 "util.h"
21#include "matrix.h"
28929ad0 22#include "debounce.h"
7fe03d08 23#include "quantum.h"
f4030289 24
0137b023 25#ifdef DIRECT_PINS
26static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS;
27#elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW)
7fe03d08 28static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
29static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
8cbf61c9 30#endif
8e88d55b
JH
31
32/* matrix state(1:on, 0:off) */
48cac9e3
JC
33extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values
34extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values
8e88d55b 35
dcb7ca3f 36// matrix code
5bb7ef00 37
0137b023 38#ifdef DIRECT_PINS
39
40static void init_pins(void) {
b624f32f 41 for (int row = 0; row < MATRIX_ROWS; row++) {
42 for (int col = 0; col < MATRIX_COLS; col++) {
43 pin_t pin = direct_pins[row][col];
44 if (pin != NO_PIN) {
45 setPinInputHigh(pin);
46 }
47 }
0137b023 48 }
0137b023 49}
508eddf8 50
0137b023 51static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
b624f32f 52 matrix_row_t last_row_value = current_matrix[current_row];
53 current_matrix[current_row] = 0;
508eddf8 54
b624f32f 55 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
56 pin_t pin = direct_pins[current_row][col_index];
57 if (pin != NO_PIN) {
dcb7ca3f 58 current_matrix[current_row] |= readPin(pin) ? 0 : (MATRIX_ROW_SHIFTER << col_index);
b624f32f 59 }
0137b023 60 }
0137b023 61
b624f32f 62 return (last_row_value != current_matrix[current_row]);
0137b023 63}
64
eb5d267e 65#elif defined(DIODE_DIRECTION)
66# if (DIODE_DIRECTION == COL2ROW)
0137b023 67
b624f32f 68static void select_row(uint8_t row) {
0137b023 69 setPinOutput(row_pins[row]);
70 writePinLow(row_pins[row]);
71}
72
b624f32f 73static void unselect_row(uint8_t row) { setPinInputHigh(row_pins[row]); }
0137b023 74
b624f32f 75static void unselect_rows(void) {
76 for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
f2689937 77 setPinInputHigh(row_pins[x]);
8e88d55b 78 }
04885a3b
JH
79}
80
0137b023 81static void init_pins(void) {
b624f32f 82 unselect_rows();
83 for (uint8_t x = 0; x < MATRIX_COLS; x++) {
84 setPinInputHigh(col_pins[x]);
85 }
0137b023 86}
87
b624f32f 88static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
f4030289
I
89 // Store last value of row prior to reading
90 matrix_row_t last_row_value = current_matrix[current_row];
91
4c696083
I
92 // Clear data in matrix row
93 current_matrix[current_row] = 0;
5bb7ef00 94
4c696083
I
95 // Select row and wait for row selecton to stabilize
96 select_row(current_row);
97 wait_us(30);
508eddf8 98
4c696083 99 // For each col...
b624f32f 100 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
4c696083 101 // Select the col pin to read (active low)
7fe03d08 102 uint8_t pin_state = readPin(col_pins[col_index]);
4c696083
I
103
104 // Populate the matrix row with the state of the col pin
dcb7ca3f 105 current_matrix[current_row] |= pin_state ? 0 : (MATRIX_ROW_SHIFTER << col_index);
4c696083 106 }
32f88c07
I
107
108 // Unselect row
109 unselect_row(current_row);
f4030289 110
a06115df 111 return (last_row_value != current_matrix[current_row]);
04885a3b
JH
112}
113
eb5d267e 114# elif (DIODE_DIRECTION == ROW2COL)
0137b023 115
b624f32f 116static void select_col(uint8_t col) {
0137b023 117 setPinOutput(col_pins[col]);
118 writePinLow(col_pins[col]);
508eddf8
I
119}
120
b624f32f 121static void unselect_col(uint8_t col) { setPinInputHigh(col_pins[col]); }
508eddf8 122
b624f32f 123static void unselect_cols(void) {
124 for (uint8_t x = 0; x < MATRIX_COLS; x++) {
0137b023 125 setPinInputHigh(col_pins[x]);
aaa758f1 126 }
8e88d55b
JH
127}
128
0137b023 129static void init_pins(void) {
b624f32f 130 unselect_cols();
131 for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
132 setPinInputHigh(row_pins[x]);
133 }
508eddf8 134}
8e88d55b 135
b624f32f 136static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {
f4030289 137 bool matrix_changed = false;
508eddf8 138
4c696083
I
139 // Select col and wait for col selecton to stabilize
140 select_col(current_col);
141 wait_us(30);
508eddf8 142
4c696083 143 // For each row...
b624f32f 144 for (uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) {
f4030289
I
145 // Store last value of row prior to reading
146 matrix_row_t last_row_value = current_matrix[row_index];
4c696083 147
32f88c07 148 // Check row pin state
b624f32f 149 if (readPin(row_pins[row_index]) == 0) {
32f88c07 150 // Pin LO, set col bit
dcb7ca3f 151 current_matrix[row_index] |= (MATRIX_ROW_SHIFTER << current_col);
b624f32f 152 } else {
32f88c07 153 // Pin HI, clear col bit
dcb7ca3f 154 current_matrix[row_index] &= ~(MATRIX_ROW_SHIFTER << current_col);
32f88c07 155 }
f4030289
I
156
157 // Determine if the matrix changed state
b624f32f 158 if ((last_row_value != current_matrix[row_index]) && !(matrix_changed)) {
f4030289
I
159 matrix_changed = true;
160 }
4c696083 161 }
32f88c07
I
162
163 // Unselect col
164 unselect_col(current_col);
f4030289
I
165
166 return matrix_changed;
508eddf8
I
167}
168
eb5d267e 169# else
170# error DIODE_DIRECTION must be one of COL2ROW or ROW2COL!
171# endif
172#else
173# error DIODE_DIRECTION is not defined!
0137b023 174#endif
508eddf8 175
0137b023 176void matrix_init(void) {
0137b023 177 // initialize key pins
178 init_pins();
179
180 // initialize matrix state: all keys off
b624f32f 181 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
0137b023 182 raw_matrix[i] = 0;
b624f32f 183 matrix[i] = 0;
508eddf8 184 }
0137b023 185
186 debounce_init(MATRIX_ROWS);
187
188 matrix_init_quantum();
508eddf8
I
189}
190
b624f32f 191uint8_t matrix_scan(void) {
192 bool changed = false;
0137b023 193
194#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW)
b624f32f 195 // Set row, read cols
196 for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
197 changed |= read_cols_on_row(raw_matrix, current_row);
198 }
0137b023 199#elif (DIODE_DIRECTION == ROW2COL)
b624f32f 200 // Set col, read rows
201 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
202 changed |= read_rows_on_col(raw_matrix, current_col);
203 }
508eddf8 204#endif
0137b023 205
b624f32f 206 debounce(raw_matrix, matrix, MATRIX_ROWS, changed);
0137b023 207
b624f32f 208 matrix_scan_quantum();
209 return (uint8_t)changed;
0137b023 210}