aboutsummaryrefslogtreecommitdiff
path: root/quantum/matrix.c
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/matrix.c')
-rw-r--r--quantum/matrix.c143
1 files changed, 87 insertions, 56 deletions
diff --git a/quantum/matrix.c b/quantum/matrix.c
index 34d6af2e6..566d9ff34 100644
--- a/quantum/matrix.c
+++ b/quantum/matrix.c
@@ -16,6 +16,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/ 16*/
17#include <stdint.h> 17#include <stdint.h>
18#include <stdbool.h> 18#include <stdbool.h>
19#include <string.h>
19#include "util.h" 20#include "util.h"
20#include "matrix.h" 21#include "matrix.h"
21#include "debounce.h" 22#include "debounce.h"
@@ -24,14 +25,23 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
24#ifdef DIRECT_PINS 25#ifdef DIRECT_PINS
25static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS; 26static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS;
26#elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW) 27#elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW)
28# ifdef MATRIX_ROW_PINS
27static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; 29static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
30# endif // MATRIX_ROW_PINS
31# ifdef MATRIX_COL_PINS
28static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; 32static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
33# endif // MATRIX_COL_PINS
29#endif 34#endif
30 35
31/* matrix state(1:on, 0:off) */ 36/* matrix state(1:on, 0:off) */
32extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values 37extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values
33extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values 38extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values
34 39
40// user-defined overridable functions
41__attribute__((weak)) void matrix_init_pins(void);
42__attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row);
43__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col);
44
35static inline void setPinOutput_writeLow(pin_t pin) { 45static inline void setPinOutput_writeLow(pin_t pin) {
36 ATOMIC_BLOCK_FORCEON { 46 ATOMIC_BLOCK_FORCEON {
37 setPinOutput(pin); 47 setPinOutput(pin);
@@ -43,11 +53,19 @@ static inline void setPinInputHigh_atomic(pin_t pin) {
43 ATOMIC_BLOCK_FORCEON { setPinInputHigh(pin); } 53 ATOMIC_BLOCK_FORCEON { setPinInputHigh(pin); }
44} 54}
45 55
56static inline uint8_t readMatrixPin(pin_t pin) {
57 if (pin != NO_PIN) {
58 return readPin(pin);
59 } else {
60 return 1;
61 }
62}
63
46// matrix code 64// matrix code
47 65
48#ifdef DIRECT_PINS 66#ifdef DIRECT_PINS
49 67
50static void init_pins(void) { 68__attribute__((weak)) void matrix_init_pins(void) {
51 for (int row = 0; row < MATRIX_ROWS; row++) { 69 for (int row = 0; row < MATRIX_ROWS; row++) {
52 for (int col = 0; col < MATRIX_COLS; col++) { 70 for (int col = 0; col < MATRIX_COLS; col++) {
53 pin_t pin = direct_pins[row][col]; 71 pin_t pin = direct_pins[row][col];
@@ -58,7 +76,7 @@ static void init_pins(void) {
58 } 76 }
59} 77}
60 78
61static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { 79__attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
62 // Start with a clear matrix row 80 // Start with a clear matrix row
63 matrix_row_t current_row_value = 0; 81 matrix_row_t current_row_value = 0;
64 82
@@ -69,46 +87,57 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
69 } 87 }
70 } 88 }
71 89
72 // If the row has changed, store the row and return the changed flag. 90 // Update the matrix
73 if (current_matrix[current_row] != current_row_value) { 91 current_matrix[current_row] = current_row_value;
74 current_matrix[current_row] = current_row_value;
75 return true;
76 }
77 return false;
78} 92}
79 93
80#elif defined(DIODE_DIRECTION) 94#elif defined(DIODE_DIRECTION)
81# if (DIODE_DIRECTION == COL2ROW) 95# if defined(MATRIX_ROW_PINS) && defined(MATRIX_COL_PINS)
96# if (DIODE_DIRECTION == COL2ROW)
82 97
83static void select_row(uint8_t row) { setPinOutput_writeLow(row_pins[row]); } 98static bool select_row(uint8_t row) {
99 pin_t pin = row_pins[row];
100 if (pin != NO_PIN) {
101 setPinOutput_writeLow(pin);
102 return true;
103 }
104 return false;
105}
84 106
85static void unselect_row(uint8_t row) { setPinInputHigh_atomic(row_pins[row]); } 107static void unselect_row(uint8_t row) {
108 pin_t pin = row_pins[row];
109 if (pin != NO_PIN) {
110 setPinInputHigh_atomic(pin);
111 }
112}
86 113
87static void unselect_rows(void) { 114static void unselect_rows(void) {
88 for (uint8_t x = 0; x < MATRIX_ROWS; x++) { 115 for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
89 setPinInputHigh_atomic(row_pins[x]); 116 unselect_row(x);
90 } 117 }
91} 118}
92 119
93static void init_pins(void) { 120__attribute__((weak)) void matrix_init_pins(void) {
94 unselect_rows(); 121 unselect_rows();
95 for (uint8_t x = 0; x < MATRIX_COLS; x++) { 122 for (uint8_t x = 0; x < MATRIX_COLS; x++) {
96 setPinInputHigh_atomic(col_pins[x]); 123 if (col_pins[x] != NO_PIN) {
124 setPinInputHigh_atomic(col_pins[x]);
125 }
97 } 126 }
98} 127}
99 128
100static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { 129__attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
101 // Start with a clear matrix row 130 // Start with a clear matrix row
102 matrix_row_t current_row_value = 0; 131 matrix_row_t current_row_value = 0;
103 132
104 // Select row 133 if (!select_row(current_row)) { // Select row
105 select_row(current_row); 134 return; // skip NO_PIN row
135 }
106 matrix_output_select_delay(); 136 matrix_output_select_delay();
107 137
108 // For each col... 138 // For each col...
109 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { 139 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
110 // Select the col pin to read (active low) 140 uint8_t pin_state = readMatrixPin(col_pins[col_index]);
111 uint8_t pin_state = readPin(col_pins[col_index]);
112 141
113 // Populate the matrix row with the state of the col pin 142 // Populate the matrix row with the state of the col pin
114 current_row_value |= pin_state ? 0 : (MATRIX_ROW_SHIFTER << col_index); 143 current_row_value |= pin_state ? 0 : (MATRIX_ROW_SHIFTER << col_index);
@@ -118,79 +147,78 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
118 unselect_row(current_row); 147 unselect_row(current_row);
119 matrix_output_unselect_delay(); // wait for all Col signals to go HIGH 148 matrix_output_unselect_delay(); // wait for all Col signals to go HIGH
120 149
121 // If the row has changed, store the row and return the changed flag. 150 // Update the matrix
122 if (current_matrix[current_row] != current_row_value) { 151 current_matrix[current_row] = current_row_value;
123 current_matrix[current_row] = current_row_value; 152}
153
154# elif (DIODE_DIRECTION == ROW2COL)
155
156static bool select_col(uint8_t col) {
157 pin_t pin = col_pins[col];
158 if (pin != NO_PIN) {
159 setPinOutput_writeLow(pin);
124 return true; 160 return true;
125 } 161 }
126 return false; 162 return false;
127} 163}
128 164
129# elif (DIODE_DIRECTION == ROW2COL) 165static void unselect_col(uint8_t col) {
130 166 pin_t pin = col_pins[col];
131static void select_col(uint8_t col) { setPinOutput_writeLow(col_pins[col]); } 167 if (pin != NO_PIN) {
132 168 setPinInputHigh_atomic(pin);
133static void unselect_col(uint8_t col) { setPinInputHigh_atomic(col_pins[col]); } 169 }
170}
134 171
135static void unselect_cols(void) { 172static void unselect_cols(void) {
136 for (uint8_t x = 0; x < MATRIX_COLS; x++) { 173 for (uint8_t x = 0; x < MATRIX_COLS; x++) {
137 setPinInputHigh_atomic(col_pins[x]); 174 unselect_col(x);
138 } 175 }
139} 176}
140 177
141static void init_pins(void) { 178__attribute__((weak)) void matrix_init_pins(void) {
142 unselect_cols(); 179 unselect_cols();
143 for (uint8_t x = 0; x < MATRIX_ROWS; x++) { 180 for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
144 setPinInputHigh_atomic(row_pins[x]); 181 if (row_pins[x] != NO_PIN) {
182 setPinInputHigh_atomic(row_pins[x]);
183 }
145 } 184 }
146} 185}
147 186
148static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) { 187__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {
149 bool matrix_changed = false;
150
151 // Select col 188 // Select col
152 select_col(current_col); 189 if (!select_col(current_col)) { // select col
190 return; // skip NO_PIN col
191 }
153 matrix_output_select_delay(); 192 matrix_output_select_delay();
154 193
155 // For each row... 194 // For each row...
156 for (uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) { 195 for (uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) {
157 // Store last value of row prior to reading
158 matrix_row_t last_row_value = current_matrix[row_index];
159 matrix_row_t current_row_value = last_row_value;
160
161 // Check row pin state 196 // Check row pin state
162 if (readPin(row_pins[row_index]) == 0) { 197 if (readMatrixPin(row_pins[row_index]) == 0) {
163 // Pin LO, set col bit 198 // Pin LO, set col bit
164 current_row_value |= (MATRIX_ROW_SHIFTER << current_col); 199 current_matrix[row_index] |= (MATRIX_ROW_SHIFTER << current_col);
165 } else { 200 } else {
166 // Pin HI, clear col bit 201 // Pin HI, clear col bit
167 current_row_value &= ~(MATRIX_ROW_SHIFTER << current_col); 202 current_matrix[row_index] &= ~(MATRIX_ROW_SHIFTER << current_col);
168 }
169
170 // Determine if the matrix changed state
171 if ((last_row_value != current_row_value)) {
172 matrix_changed |= true;
173 current_matrix[row_index] = current_row_value;
174 } 203 }
175 } 204 }
176 205
177 // Unselect col 206 // Unselect col
178 unselect_col(current_col); 207 unselect_col(current_col);
179 matrix_output_unselect_delay(); // wait for all Row signals to go HIGH 208 matrix_output_unselect_delay(); // wait for all Row signals to go HIGH
180
181 return matrix_changed;
182} 209}
183 210
184# else 211# else
185# error DIODE_DIRECTION must be one of COL2ROW or ROW2COL! 212# error DIODE_DIRECTION must be one of COL2ROW or ROW2COL!
186# endif 213# endif
214# endif // defined(MATRIX_ROW_PINS) && defined(MATRIX_COL_PINS)
187#else 215#else
188# error DIODE_DIRECTION is not defined! 216# error DIODE_DIRECTION is not defined!
189#endif 217#endif
190 218
191void matrix_init(void) { 219void matrix_init(void) {
192 // initialize key pins 220 // initialize key pins
193 init_pins(); 221 matrix_init_pins();
194 222
195 // initialize matrix state: all keys off 223 // initialize matrix state: all keys off
196 for (uint8_t i = 0; i < MATRIX_ROWS; i++) { 224 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
@@ -204,20 +232,23 @@ void matrix_init(void) {
204} 232}
205 233
206uint8_t matrix_scan(void) { 234uint8_t matrix_scan(void) {
207 bool changed = false; 235 matrix_row_t curr_matrix[MATRIX_ROWS] = {0};
208 236
209#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW) 237#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW)
210 // Set row, read cols 238 // Set row, read cols
211 for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) { 239 for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
212 changed |= read_cols_on_row(raw_matrix, current_row); 240 matrix_read_cols_on_row(curr_matrix, current_row);
213 } 241 }
214#elif (DIODE_DIRECTION == ROW2COL) 242#elif (DIODE_DIRECTION == ROW2COL)
215 // Set col, read rows 243 // Set col, read rows
216 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { 244 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
217 changed |= read_rows_on_col(raw_matrix, current_col); 245 matrix_read_rows_on_col(curr_matrix, current_col);
218 } 246 }
219#endif 247#endif
220 248
249 bool changed = memcmp(raw_matrix, curr_matrix, sizeof(curr_matrix)) != 0;
250 if (changed) memcpy(raw_matrix, curr_matrix, sizeof(curr_matrix));
251
221 debounce(raw_matrix, matrix, MATRIX_ROWS, changed); 252 debounce(raw_matrix, matrix, MATRIX_ROWS, changed);
222 253
223 matrix_scan_quantum(); 254 matrix_scan_quantum();