[Keyboard] Small Refactor of Duck boards (#5521)
[jackhill/qmk/firmware.git] / keyboards / duck / lightsaver / matrix.c
CommitLineData
41d5d3e6
RS
1/*
2Copyright 2016-2017 Ralf Schmitt <ralf@bunkertor.net> Rasmus Schults <rasmusx@gmail.com>
3This program is free software: you can redistribute it and/or modify
4it under the terms of the GNU General Public License as published by
5the Free Software Foundation, either version 2 of the License, or
6(at your option) any later version.
7
8This program is distributed in the hope that it will be useful,
9but WITHOUT ANY WARRANTY; without even the implied warranty of
10MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11GNU General Public License for more details.
12
13You should have received a copy of the GNU General Public License
14along with this program. If not, see <http://www.gnu.org/licenses/>.
15*/
16
17#include <util/delay.h>
18#include <avr/io.h>
19#include <stdio.h>
20#include "matrix.h"
21#include "util.h"
22#include "print.h"
23#include "debug.h"
24
25static uint8_t debouncing = DEBOUNCING_DELAY;
26
27/* matrix state(1:on, 0:off) */
28static matrix_row_t matrix[MATRIX_ROWS];
29static matrix_row_t matrix_debouncing[MATRIX_ROWS];
30
31static uint8_t read_rows(void);
32static uint8_t read_fwkey(void);
33static void init_rows(void);
34static void unselect_cols(void);
35static void select_col(uint8_t col);
36
41d5d3e6
RS
37
38__attribute__ ((weak))
39void matrix_init_kb(void) {
40 matrix_init_user();
41}
42
43__attribute__ ((weak))
44void matrix_scan_kb(void) {
45 matrix_scan_user();
46}
47
48__attribute__ ((weak))
49void matrix_init_user(void) {
50}
51
52__attribute__ ((weak))
53void matrix_scan_user(void) {
54}
55
56void matrix_init(void) {
57 DDRD |= 0b11010000;
58 PORTD &= ~0b01010000;
59 DDRB |= 0b00011111;
60 PORTB &= ~0b00001110;
61 PORTB |= 0b00010001;
62 DDRE |= 0b01000000;
63 PORTE &= ~0b01000000;
64
65 unselect_cols();
66 init_rows();
67
68 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
69 matrix[i] = 0;
70 matrix_debouncing[i] = 0;
71 }
72
73 matrix_init_quantum();
74}
75
76uint8_t matrix_scan(void) {
77 for (uint8_t col = 0; col < MATRIX_COLS; col++) {
78 select_col(col);
79 _delay_us(3);
80
81 uint8_t rows = read_rows();
82 if(col == 0) {
83 rows |= read_fwkey();
84 }
85 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
86 bool prev_bit = matrix_debouncing[row] & ((matrix_row_t)1<<col);
87 bool curr_bit = rows & (1<<row);
88 if (prev_bit != curr_bit) {
89 matrix_debouncing[row] ^= ((matrix_row_t)1<<col);
cb2f2fd2
M
90 if (debouncing) {
91 dprint("bounce!: "); dprintf("%02X", debouncing); dprintln();
92 }
41d5d3e6
RS
93 debouncing = DEBOUNCING_DELAY;
94 }
95 }
96 unselect_cols();
97 }
98
99 if (debouncing) {
100 if (--debouncing) {
101 _delay_ms(1);
102 } else {
103 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
104 matrix[i] = matrix_debouncing[i];
105 }
106 }
107 }
108
109 matrix_scan_quantum();
110 return 1;
111}
112
113inline matrix_row_t matrix_get_row(uint8_t row) {
114 return matrix[row];
115}
116
117void matrix_print(void) {
118 print("\nr/c 0123456789ABCDEF\n");
119 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
120 xprintf("%02X: %032lb\n", row, bitrev32(matrix_get_row(row)));
121 }
122}
123
124/* Row pin configuration
125 * row: 0 1 2 3 4 5
126 * pin: PB7 PD0 PD1 PD2 PD3 PD5
127 *
128 * Esc uses its own pin PE2
129 */
130static void init_rows(void) {
131 DDRB &= ~0b10000000;
132 PORTB &= ~0b10000000;
133
134 DDRD &= ~0b00101111;
135 PORTD &= ~0b00101111;
136
137 DDRE &= ~0b00000100;
138 PORTE |= 0b00000100;
139}
140
141static uint8_t read_rows() {
142 return (PINB&(1<<7) ? (1<<0) : 0) |
143 (PIND&(1<<0) ? (1<<1) : 0) |
144 (PIND&(1<<1) ? (1<<2) : 0) |
145 (PIND&(1<<2) ? (1<<3) : 0) |
146 (PIND&(1<<3) ? (1<<4) : 0) |
147 (PIND&(1<<5) ? (1<<5) : 0);
148}
149
150static uint8_t read_fwkey(void)
151{
152 return PINE&(1<<2) ? 0 : (1<<0);
153}
154
155/* Columns 0 - 15
156 * These columns uses two 74HC237D 3 to 8 bit demultiplexers.
157 * col / pin: PC6 PB6 PF0 PF1 PC7
158 * 0: 1 0 0 0 0
159 * 1: 1 0 1 0 0
160 * 2: 1 0 0 1 0
161 * 3: 1 0 1 1 0
162 * 4: 1 0 0 0 1
163 * 5: 1 0 1 0 1
164 * 6: 1 0 0 1 1
165 * 7: 1 0 1 1 1
166 * 8: 0 1 0 0 0
167 * 9: 0 1 1 0 0
168 * 10: 0 1 0 1 0
169 * 11: 0 1 1 1 0
170 * 12: 0 1 0 0 1
171 * 13: 0 1 1 0 1
172 * 14: 0 1 0 1 1
173 * 15: 0 1 1 1 1
174 *
175 * col: 16
176 * pin: PB5
177 *
178 * col: 17
179 * pin: PB4
180 *
181 * col: 18
182 * pin: PD7
183 */
184static void unselect_cols(void) {
185 DDRB |= 0b01110000;
186 PORTB &= ~0b01110000;
187
188 DDRC |= (1<<6) | (1<<7);
189 PORTC &= ~((1<<6) | (1<<7));
190
191 DDRF |= (1<<0) | (1<<1);
192 PORTF &= ~((1<<0) | (1<<1));
193
194 DDRD |= (1<<7);
195 PORTD &= ~(1<<7);
196}
197
198static void select_col(uint8_t col) {
199 switch (col) {
200 case 0:
201 PORTC |= (1<<6);
202 break;
203 case 1:
204 PORTC |= (1<<6);
205 PORTF |= (1<<0);
206 break;
207 case 2:
208 PORTC |= (1<<6);
209 PORTF |= (1<<1);
210 break;
211 case 3:
212 PORTC |= (1<<6);
213 PORTF |= (1<<0) | (1<<1);
214 break;
215 case 4:
216 PORTC |= (1<<6);
217 PORTC |= (1<<7);
218 break;
219 case 5:
220 PORTC |= (1<<6);
221 PORTF |= (1<<0);
222 PORTC |= (1<<7);
223 break;
224 case 6:
225 PORTC |= (1<<6);
226 PORTF |= (1<<1);
227 PORTC |= (1<<7);
228 break;
229 case 7:
230 PORTC |= (1<<6);
231 PORTF |= (1<<0) | (1<<1);
232 PORTC |= (1<<7);
233 break;
234 case 8:
235 PORTB |= (1<<6);
236 break;
237 case 9:
238 PORTB |= (1<<6);
239 PORTF |= (1<<0);
240 break;
241 case 10:
242 PORTB |= (1<<6);
243 PORTF |= (1<<1);
244 break;
245 case 11:
246 PORTB |= (1<<6);
247 PORTF |= (1<<0) | (1<<1);
248 break;
249 case 12:
250 PORTB |= (1<<6);
251 PORTC |= (1<<7);
252 break;
253 case 13:
254 PORTB |= (1<<6);
255 PORTF |= (1<<0);
256 PORTC |= (1<<7);
257 break;
258 case 14:
259 PORTB |= (1<<6);
260 PORTF |= (1<<1);
261 PORTC |= (1<<7);
262 break;
263 case 15:
264 PORTB |= (1<<6);
265 PORTF |= (1<<0) | (1<<1);
266 PORTC |= (1<<7);
267 break;
268 case 16:
269 PORTB |= (1<<5);
270 break;
271 case 17:
272 PORTB |= (1<<4);
273 break;
274 case 18:
275 PORTD |= (1<<7);
276 break;
277 }
278}