]> git.donarmstrong.com Git - tmk_firmware.git/blob - keyboard/kitten_paw/matrix.c
Merge remote-tracking branch 'tmk/master' into cub_layout
[tmk_firmware.git] / keyboard / kitten_paw / matrix.c
1 /*
2 Copyright 2014 Ralf Schmitt <ralf@bunkertor.net>
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <stdint.h>
19 #include <stdbool.h>
20 #include <avr/io.h>
21 #include <util/delay.h>
22 #include "print.h"
23 #include "debug.h"
24 #include "util.h"
25 #include "matrix.h"
26
27 #ifndef DEBOUNCE
28 #   define DEBOUNCE 0
29 #endif
30 static uint8_t debouncing = DEBOUNCE;
31
32 static matrix_row_t matrix[MATRIX_ROWS];
33 static matrix_row_t matrix_debouncing[MATRIX_ROWS];
34
35 static uint8_t read_rows(void);
36 static void init_rows(void);
37 static void unselect_cols(void);
38 static void select_col(uint8_t col);
39
40 inline uint8_t matrix_rows(void)
41 {
42     return MATRIX_ROWS;
43 }
44
45 inline uint8_t matrix_cols(void)
46 {
47     return MATRIX_COLS;
48 }
49
50 void matrix_init(void)
51 {
52     unselect_cols();
53     init_rows();
54     for (uint8_t i=0; i < MATRIX_ROWS; i++)  {
55         matrix[i] = 0;
56         matrix_debouncing[i] = 0;
57     }
58 }
59
60 uint8_t matrix_scan(void)
61 {
62     for (uint8_t col = 0; col < MATRIX_COLS; col++) {
63         select_col(col);
64         _delay_us(3);
65         uint8_t rows = read_rows();
66         for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
67             bool prev_bit = matrix_debouncing[row] & ((matrix_row_t)1<<col);
68             bool curr_bit = rows & (1<<row);
69             if (prev_bit != curr_bit) {
70                 matrix_debouncing[row] ^= ((matrix_row_t)1<<col);
71                 debouncing = DEBOUNCE;
72             }
73         }
74         unselect_cols();
75     }
76
77     if (debouncing) {
78         if (--debouncing) {
79             _delay_ms(1);
80         } else {
81             for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
82                 matrix[i] = matrix_debouncing[i];
83             }
84         }
85     }
86
87     return 1;
88 }
89
90 bool matrix_is_modified(void)
91 {
92     if (debouncing) return false;
93     return true;
94 }
95
96 inline bool matrix_is_on(uint8_t row, uint8_t col)
97 {
98     return (matrix[row] & ((matrix_row_t)1<<col));
99 }
100
101 inline matrix_row_t matrix_get_row(uint8_t row)
102 {
103     return matrix[row];
104 }
105
106 void matrix_print(void)
107 {
108     print("\nr/c 0123456789ABCDEF\n");
109     for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
110         xprintf("%02X: %032lb\n", row, bitrev32(matrix_get_row(row)));
111     }
112 }
113
114 uint8_t matrix_key_count(void)
115 {
116     uint8_t count = 0;
117     for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
118         count += bitpop32(matrix[i]);
119     }
120     return count;
121 }
122
123 /* Row pin configuration
124  *
125  * row: 0    1    2    3    4    5    6    7
126  * pin: PC2  PB1  PB2  PB3  PC7  PB4  PB5  PB6
127  *
128  */
129 static void init_rows(void)
130 {
131     DDRC &= ~0b10000100;
132     DDRB &= ~0b01111110;
133     PORTC |= 0b10000100;
134     PORTB |= 0b01111110;
135 }
136
137 static uint8_t read_rows(void)
138 {
139     return (PINC&(1<<2) ? 0 : (1<<0)) |
140            (PINB&(1<<1) ? 0 : (1<<1)) |
141            (PINB&(1<<2) ? 0 : (1<<2)) |
142            (PINB&(1<<3) ? 0 : (1<<3)) |
143            (PINC&(1<<7) ? 0 : (1<<4)) |
144            (PINB&(1<<4) ? 0 : (1<<5)) |
145            (PINB&(1<<5) ? 0 : (1<<6)) |
146            (PINB&(1<<6) ? 0 : (1<<7));
147 }
148
149 /*  These columns uses two 74HC42 4 to 10 bit demultiplexers (low active).
150  *
151  *   COL PD1 PD0 PD2 PD6 PD5 PD4
152  *   12   1   1   0   0   0   0
153  *   11   1   1   0   0   0   1
154  *   10   1   1   0   0   1   0
155  *    9   1   1   0   0   1   1
156  *    8   1   1   0   1   0   0
157  *    7   1   1   0   1   0   1
158  *    6   1   1   0   1   1   0
159  *    5   1   1   0   1   1   1
160  *    4   1   1   1   0   0   0
161  *    3   1   1   1   0   0   1
162
163  *   COL PD2 PD6 PD1 PD0 PD5 PD4
164  *    2   1   1   0   0   0   0
165  *    1   1   1   0   0   0   1
166  *    0   1   1   0   0   1   0
167  *   17   1   1   0   0   1   1
168  *   16   1   1   0   1   0   0
169  *        1   1   0   1   0   1
170  *        1   1   0   1   1   0
171  *   15   1   1   0   1   1   1
172  *   14   1   1   1   0   0   0
173  *   13   1   1   1   0   0   1
174  */
175 static void unselect_cols(void)
176 {
177     DDRD |= 0b01110111;
178     PORTD &= ~0b01110111;
179 }
180
181 static void select_col(uint8_t col)
182 {
183     switch (col) {
184         case 0:
185             PORTD |= (1<<5) | (1<<6) | (1<<2);
186             break;
187         case 1:
188             PORTD |= (1<<4) | (1<<6) | (1<<2);
189             break;
190         case 2:
191             PORTD |= (1<<6) | (1<<2);
192             break;
193         case 3:
194             PORTD |= (1<<4) | (1<<2) | (1<<0) | (1<<1);
195             break;
196         case 4:
197             PORTD |= (1<<2) | (1<<0) | (1<<1);
198             break;
199         case 5:
200             PORTD |= (1<<4) | (1<<5) | (1<<6) | (1<<0) | (1<<1);
201             break;
202         case 6:
203             PORTD |= (1<<5) | (1<<6) | (1<<0) | (1<<1);
204             break;
205         case 7:
206             PORTD |= (1<<4) | (1<<6) | (1<<0) | (1<<1);
207             break;
208         case 8:
209             PORTD |= (1<<6) | (1<<0) | (1<<1);
210             break;
211         case 9:
212             PORTD |= (1<<4) | (1<<5) | (1<<0) | (1<<1);
213             break;
214         case 10:
215             PORTD |= (1<<5) | (1<<0) | (1<<1);
216             break;
217         case 11:
218             PORTD |= (1<<4) | (1<<0) | (1<<1);
219             break;
220         case 12:
221             PORTD |= (1<<0) | (1<<1);
222             break;
223         case 13:
224             PORTD |= (1<<4) | (1<<1) | (1<<6) | (1<<2);
225             break;
226         case 14:
227             PORTD |= (1<<1) | (1<<6) | (1<<2);
228             break;
229         case 15:
230             PORTD |= (1<<4) | (1<<5) | (1<<0) | (1<<6) | (1<<2);
231             break;
232         case 16:
233             PORTD |= (1<<0) | (1<<6) | (1<<2);
234             break;
235         case 17:
236             PORTD |= (1<<4) | (1<<5) | (1<<6) | (1<<2);
237             break;
238     }
239 }