]>
Commit | Line | Data |
---|---|---|
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 | } |