aboutsummaryrefslogtreecommitdiff
path: root/keyboards/handwired/promethium/matrix.c
diff options
context:
space:
mode:
Diffstat (limited to 'keyboards/handwired/promethium/matrix.c')
-rw-r--r--keyboards/handwired/promethium/matrix.c306
1 files changed, 306 insertions, 0 deletions
diff --git a/keyboards/handwired/promethium/matrix.c b/keyboards/handwired/promethium/matrix.c
new file mode 100644
index 000000000..72dbe8d4d
--- /dev/null
+++ b/keyboards/handwired/promethium/matrix.c
@@ -0,0 +1,306 @@
1/*
2Copyright 2012 Jun Wako
3Copyright 2014 Jack Humbert
4Copyright 2017 Priyadi Iman Nurcahyo
5
6This program is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation, either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19#include <stdint.h>
20#include <stdbool.h>
21#if defined(__AVR__)
22#include <avr/io.h>
23#endif
24#include "wait.h"
25#include "print.h"
26#include "debug.h"
27#include "util.h"
28#include "matrix.h"
29#include "timer.h"
30
31
32/* Set 0 if debouncing isn't needed */
33
34#ifndef DEBOUNCING_DELAY
35# define DEBOUNCING_DELAY 5
36#endif
37
38#if (DEBOUNCING_DELAY > 0)
39 static uint16_t debouncing_time;
40 static bool debouncing = false;
41#endif
42
43#if (MATRIX_COLS <= 8)
44# define print_matrix_header() print("\nr/c 01234567\n")
45# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
46# define matrix_bitpop(i) bitpop(matrix[i])
47# define ROW_SHIFTER ((uint8_t)1)
48#elif (MATRIX_COLS <= 16)
49# define print_matrix_header() print("\nr/c 0123456789ABCDEF\n")
50# define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row))
51# define matrix_bitpop(i) bitpop16(matrix[i])
52# define ROW_SHIFTER ((uint16_t)1)
53#elif (MATRIX_COLS <= 32)
54# define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n")
55# define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row))
56# define matrix_bitpop(i) bitpop32(matrix[i])
57# define ROW_SHIFTER ((uint32_t)1)
58#endif
59
60#ifdef MATRIX_MASKED
61 extern const matrix_row_t matrix_mask[];
62#endif
63
64static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
65static const uint8_t tp_pins[3] = TRACKPOINT_PINS;
66
67/* matrix state(1:on, 0:off) */
68static matrix_row_t matrix[MATRIX_ROWS];
69static matrix_row_t matrix_debouncing[MATRIX_ROWS];
70
71static void init_cols(void);
72static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row);
73static void unselect_rows(void);
74static void select_row(uint8_t row);
75static void unselect_row(uint8_t row);
76
77__attribute__ ((weak))
78void matrix_init_quantum(void) {
79 matrix_init_kb();
80}
81
82__attribute__ ((weak))
83void matrix_scan_quantum(void) {
84 matrix_scan_kb();
85}
86
87__attribute__ ((weak))
88void matrix_init_kb(void) {
89 matrix_init_user();
90}
91
92__attribute__ ((weak))
93void matrix_scan_kb(void) {
94 matrix_scan_user();
95}
96
97__attribute__ ((weak))
98void matrix_init_user(void) {
99}
100
101__attribute__ ((weak))
102void matrix_scan_user(void) {
103}
104
105inline
106uint8_t matrix_rows(void) {
107 return MATRIX_ROWS;
108}
109
110inline
111uint8_t matrix_cols(void) {
112 return MATRIX_COLS;
113}
114
115void matrix_init(void) {
116
117 // To use PORTF disable JTAG with writing JTD bit twice within four cycles.
118 #if (defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega32U4__))
119 MCUCR |= _BV(JTD);
120 MCUCR |= _BV(JTD);
121 #endif
122
123 // initialize row and col
124 unselect_rows();
125 init_cols();
126
127 // initialize matrix state: all keys off
128 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
129 matrix[i] = 0;
130 matrix_debouncing[i] = 0;
131 }
132
133 matrix_init_quantum();
134}
135
136uint8_t matrix_scan(void)
137{
138 // Set row, read cols
139 for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
140# if (DEBOUNCING_DELAY > 0)
141 bool matrix_changed = read_cols_on_row(matrix_debouncing, current_row);
142
143 if (matrix_changed) {
144 debouncing = true;
145 debouncing_time = timer_read();
146 }
147
148# else
149 read_cols_on_row(matrix, current_row);
150# endif
151
152 }
153
154# if (DEBOUNCING_DELAY > 0)
155 if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCING_DELAY)) {
156 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
157 matrix[i] = matrix_debouncing[i];
158 }
159 debouncing = false;
160 }
161# endif
162
163 matrix_scan_quantum();
164 return 1;
165}
166
167bool matrix_is_modified(void)
168{
169#if (DEBOUNCING_DELAY > 0)
170 if (debouncing) return false;
171#endif
172 return true;
173}
174
175inline
176bool matrix_is_on(uint8_t row, uint8_t col)
177
178{
179 return (matrix[row] & ((matrix_row_t)1<col));
180}
181
182inline
183matrix_row_t matrix_get_row(uint8_t row)
184{
185 // Matrix mask lets you disable switches in the returned matrix data. For example, if you have a
186 // switch blocker installed and the switch is always pressed.
187#ifdef MATRIX_MASKED
188 return matrix[row] & matrix_mask[row];
189#else
190 return matrix[row];
191#endif
192}
193
194void matrix_print(void)
195{
196 print_matrix_header();
197
198 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
199 phex(row); print(": ");
200 print_matrix_row(row);
201 print("\n");
202 }
203}
204
205uint8_t matrix_key_count(void)
206{
207 uint8_t count = 0;
208 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
209 count += matrix_bitpop(i);
210 }
211 return count;
212}
213
214
215#define ROW_MASK 0b11100000
216
217static const uint8_t row_bit[MATRIX_ROWS] = {
218 // 76543210
219 0b00000000,
220 0b00100000,
221 0b01000000,
222 0b01100000,
223 0b10000000,
224 0b10100000,
225 0b11000000,
226 0b11100000,
227};
228
229static void init_cols(void)
230{
231 // columns
232 for(uint8_t x = 0; x < MATRIX_COLS; x++) {
233 uint8_t pin = col_pins[x];
234 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
235 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
236 }
237
238 // rows
239 DDRF |= ROW_MASK;
240 PORTF &= ~ROW_MASK;
241
242 // trackpoint
243 for(uint8_t x = 0; x < 3; x++) {
244 uint8_t pin = tp_pins[x];
245 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
246 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
247 }
248}
249
250static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
251 {
252 // Store last value of row prior to reading
253 matrix_row_t last_row_value = current_matrix[current_row];
254
255 // Clear data in matrix row
256 current_matrix[current_row] = 0;
257
258 // special case for trackpoint
259 if (current_row == 8) {
260 for(uint8_t tp_index = 0; tp_index < 3; tp_index++) {
261
262 // Select the TP pin to read (active low)
263 uint8_t pin = tp_pins[tp_index];
264 uint8_t pin_state = (_SFR_IO8(pin >> 4) & _BV(pin & 0xF));
265
266 // Populate the matrix row with the state of the col pin
267 current_matrix[current_row] |= pin_state ? 0 : (ROW_SHIFTER << tp_index);
268 }
269 return (last_row_value != current_matrix[current_row]);
270 }
271
272 // Select row and wait for row selecton to stabilize
273 select_row(current_row);
274 _delay_us(5); // without this wait it won't read stable value.
275 // wait_us(50);
276
277 // For each col...
278 for(uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
279
280 // Select the col pin to read (active low)
281 uint8_t pin = col_pins[col_index];
282 uint8_t pin_state = (_SFR_IO8(pin >> 4) & _BV(pin & 0xF));
283
284 // Populate the matrix row with the state of the col pin
285 current_matrix[current_row] |= pin_state ? 0 : (ROW_SHIFTER << col_index);
286 }
287
288 // Unselect row
289 unselect_row(current_row);
290
291 return (last_row_value != current_matrix[current_row]);
292}
293
294static void select_row(uint8_t row)
295{
296 PORTF = row_bit[row] | (PORTF & ~ROW_MASK);
297}
298
299static void unselect_row(uint8_t row)
300{
301}
302
303static void unselect_rows(void)
304{
305}
306