]> git.friedersdorff.com Git - max/tmk_keyboard.git/blob - keyboard/ghost_squid/matrix.c
Merge pull request #148 from cub-uanic/patch-1
[max/tmk_keyboard.git] / keyboard / ghost_squid / 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: PB1  PC2  PB6  PB4  PB3  PB5  PB0  PB2
127  *
128  */
129 static void init_rows(void)
130 {
131     DDRC &= ~0b00000100;
132     DDRB &= ~0b01111111;
133     PORTC |= 0b00000100;
134     PORTB |= 0b01111111;
135 }
136
137 static uint8_t read_rows(void)
138 {
139     return (PINB&(1<<1) ? 0 : (1<<0)) |
140            (PINC&(1<<2) ? 0 : (1<<1)) |
141            (PINB&(1<<6) ? 0 : (1<<2)) |
142            (PINB&(1<<4) ? 0 : (1<<3)) |
143            (PINB&(1<<3) ? 0 : (1<<4)) |
144            (PINB&(1<<5) ? 0 : (1<<5)) |
145            (PINB&(1<<0) ? 0 : (1<<6)) |
146            (PINB&(1<<2) ? 0 : (1<<7));
147 }
148
149 /*  These columns uses two 74HC42 4 to 10 bit demultiplexers (low active).
150  *
151  *   COL PD6 PD5 PD4 PD3 PD2 PD1
152  *   10   1   1   0   0   0   0
153  *   15   1   1   0   0   0   1
154  *    8   1   1   0   0   1   0
155  *   14   1   1   0   1   0   0
156  *    6   1   1   0   1   0   1
157  *   13   1   1   0   1   1   0
158  *   12   1   1   1   0   0   0
159  *    9   1   1   1   0   1   0
160  *   11   1   1   1   1   0   0
161  *    7   1   1   1   1   1   0
162  *
163  *   COL PD1 PD2 PD3 PD4 PD5 PD6
164  *    3   1   1   0   0   0   1
165  *    4   1   1   0   0   1   0
166  *   17   1   1   0   1   0   0
167  *   16   1   1   0   1   1   0
168  *    0   1   1   1   0   0   1
169  *    5   1   1   1   0   1   0
170  *    2   1   1   1   1   0   0
171  *    1   1   1   1   1   1   0
172  */
173 static void unselect_cols(void)
174 {
175     DDRD |= 0b01111111;
176     PORTD &= ~0b01111111;
177 }
178
179 static void select_col(uint8_t col)
180 {
181     switch (col) {
182         case 0:
183             PORTD |= (1<<6) | (1<<3) | (1<<2) | (1<<1);
184             break;
185         case 1:
186             PORTD |= (1<<5) | (1<<4) | (1<<3) | (1<<2) | (1<<1);
187             break;
188         case 2:
189             PORTD |= (1<<4) | (1<<3) | (1<<2) | (1<<1);
190             break;
191         case 3:
192             PORTD |= (1<<6) | (1<<2) | (1<<1);
193             break;
194         case 4:
195             PORTD |= (1<<5) | (1<<2) | (1<<1);
196             break;
197         case 5:
198             PORTD |= (1<<5) | (1<<3) | (1<<2) | (1<<1);
199             break;
200         case 6:
201             PORTD |= (1<<6) | (1<<5) | (1<<3) | (1<<1);
202             break;
203         case 7:
204             PORTD |= (1<<6) | (1<<5) | (1<<4) | (1<<3) | (1<<2);
205             break;
206         case 8:
207             PORTD |= (1<<6) | (1<<5) | (1<<2);
208             break;
209         case 9:
210             PORTD |= (1<<6) | (1<<5) | (1<<4) | (1<<2);
211             break;
212         case 10:
213             PORTD |= (1<<6) | (1<<5);
214             break;
215         case 11:
216             PORTD |= (1<<6) | (1<<5) | (1<<4) | (1<<3);
217             break;
218         case 12:
219             PORTD |= (1<<6) | (1<<5) | (1<<4);
220             break;
221         case 13:
222             PORTD |= (1<<6) | (1<<5) | (1<<3) | (1<<2);
223             break;
224         case 14:
225             PORTD |= (1<<6) | (1<<5) | (1<<3);
226             break;
227         case 15:
228             PORTD |= (1<<6) | (1<<5) | (1<<1);
229             break;
230         case 16:
231             PORTD |= (1<<5) | (1<<4) | (1<<2) | (1<<1);
232             break;
233         case 17:
234             PORTD |= (1<<4) | (1<<2) | (1<<1);
235             break;
236     }
237 }