aboutsummaryrefslogtreecommitdiff
path: root/quantum/matrix.c
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/matrix.c')
-rw-r--r--quantum/matrix.c297
1 files changed, 297 insertions, 0 deletions
diff --git a/quantum/matrix.c b/quantum/matrix.c
new file mode 100644
index 000000000..3174e0739
--- /dev/null
+++ b/quantum/matrix.c
@@ -0,0 +1,297 @@
1/*
2Copyright 2012 Jun Wako
3Copyright 2014 Jack Humbert
4
5This program is free software: you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation, either version 2 of the License, or
8(at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18#include <stdint.h>
19#include <stdbool.h>
20#if defined(__AVR__)
21#include <avr/io.h>
22#endif
23#include "wait.h"
24#include "print.h"
25#include "debug.h"
26#include "util.h"
27#include "matrix.h"
28
29/* Set 0 if debouncing isn't needed */
30
31#ifndef DEBOUNCING_DELAY
32# define DEBOUNCING_DELAY 5
33#endif
34static uint8_t debouncing = DEBOUNCING_DELAY;
35
36static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
37static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
38
39/* matrix state(1:on, 0:off) */
40static matrix_row_t matrix[MATRIX_ROWS];
41static matrix_row_t matrix_debouncing[MATRIX_ROWS];
42
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
48#if MATRIX_COLS > 16
49 #define SHIFTER 1UL
50#else
51 #define SHIFTER 1
52#endif
53
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))
60void matrix_init_quantum(void) {
61 matrix_init_kb();
62}
63
64__attribute__ ((weak))
65void matrix_scan_quantum(void) {
66 matrix_scan_kb();
67}
68
69__attribute__ ((weak))
70void matrix_init_kb(void) {
71 matrix_init_user();
72}
73
74__attribute__ ((weak))
75void matrix_scan_kb(void) {
76 matrix_scan_user();
77}
78
79__attribute__ ((weak))
80void matrix_init_user(void) {
81}
82
83__attribute__ ((weak))
84void matrix_scan_user(void) {
85}
86
87inline
88uint8_t matrix_rows(void) {
89 return MATRIX_ROWS;
90}
91
92inline
93uint8_t matrix_cols(void) {
94 return MATRIX_COLS;
95}
96
97// void matrix_power_up(void) {
98// #if DIODE_DIRECTION == COL2ROW
99// for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
100// /* DDRxn */
101// _SFR_IO8((row_pins[r] >> 4) + 1) |= _BV(row_pins[r] & 0xF);
102// toggle_row(r);
103// }
104// for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
105// /* PORTxn */
106// _SFR_IO8((col_pins[c] >> 4) + 2) |= _BV(col_pins[c] & 0xF);
107// }
108// #else
109// for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
110// /* DDRxn */
111// _SFR_IO8((col_pins[c] >> 4) + 1) |= _BV(col_pins[c] & 0xF);
112// toggle_col(c);
113// }
114// for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
115// /* PORTxn */
116// _SFR_IO8((row_pins[r] >> 4) + 2) |= _BV(row_pins[r] & 0xF);
117// }
118// #endif
119// }
120
121void matrix_init(void) {
122 // To use PORTF disable JTAG with writing JTD bit twice within four cycles.
123 #ifdef __AVR_ATmega32U4__
124 MCUCR |= _BV(JTD);
125 MCUCR |= _BV(JTD);
126 #endif
127
128 // initialize row and col
129 unselect_rows();
130 init_cols();
131
132 // initialize matrix state: all keys off
133 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
134 matrix[i] = 0;
135 matrix_debouncing[i] = 0;
136 }
137
138 matrix_init_quantum();
139}
140
141uint8_t matrix_scan(void)
142{
143
144#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
159 if (debouncing) {
160 if (--debouncing) {
161 wait_ms(1);
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 }
182
183 if (debouncing) {
184 if (--debouncing) {
185 wait_ms(1);
186 } else {
187 for (uint8_t i = 0; i < MATRIX_COLS; i++) {
188 matrix_reversed[i] = matrix_reversed_debouncing[i];
189 }
190 }
191 }
192 for (uint8_t y = 0; y < MATRIX_ROWS; y++) {
193 matrix_row_t row = 0;
194 for (uint8_t x = 0; x < MATRIX_COLS; x++) {
195 row |= ((matrix_reversed[x] & (1<<y)) >> y) << x;
196 }
197 matrix[y] = row;
198 }
199#endif
200
201 matrix_scan_quantum();
202
203 return 1;
204}
205
206bool matrix_is_modified(void)
207{
208 if (debouncing) return false;
209 return true;
210}
211
212inline
213bool matrix_is_on(uint8_t row, uint8_t col)
214{
215 return (matrix[row] & ((matrix_row_t)1<col));
216}
217
218inline
219matrix_row_t matrix_get_row(uint8_t row)
220{
221 return matrix[row];
222}
223
224void matrix_print(void)
225{
226 print("\nr/c 0123456789ABCDEF\n");
227 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
228 phex(row); print(": ");
229 pbin_reverse16(matrix_get_row(row));
230 print("\n");
231 }
232}
233
234uint8_t matrix_key_count(void)
235{
236 uint8_t count = 0;
237 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
238 count += bitpop16(matrix[i]);
239 }
240 return count;
241}
242
243static void init_cols(void)
244{
245#if DIODE_DIRECTION == COL2ROW
246 for(int x = 0; x < MATRIX_COLS; x++) {
247 int pin = col_pins[x];
248#else
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 }
255}
256
257static matrix_row_t read_cols(void)
258{
259 matrix_row_t result = 0;
260
261#if DIODE_DIRECTION == COL2ROW
262 for(int x = 0; x < MATRIX_COLS; x++) {
263 int pin = col_pins[x];
264#else
265 for(int x = 0; x < MATRIX_ROWS; x++) {
266 int pin = row_pins[x];
267#endif
268 result |= (_SFR_IO8(pin >> 4) & _BV(pin & 0xF)) ? 0 : (SHIFTER << x);
269 }
270 return result;
271}
272
273static void unselect_rows(void)
274{
275#if DIODE_DIRECTION == COL2ROW
276 for(int x = 0; x < MATRIX_ROWS; x++) {
277 int pin = row_pins[x];
278#else
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 }
285}
286
287static void select_row(uint8_t row)
288{
289
290#if DIODE_DIRECTION == COL2ROW
291 int pin = row_pins[row];
292#else
293 int pin = col_pins[row];
294#endif
295 _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF);
296 _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF);
297}