]> git.gir.st - tmk_keyboard.git/blob - keyboard/hbkb/matrix.c
Merge branch 'add_build_options'
[tmk_keyboard.git] / keyboard / hbkb / matrix.c
1 /*
2 Copyright 2012 Jun Wako <wakojun@gmail.com>
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
28 /*
29 * Happy Buckling Keyboard(IBM Model M mod)
30 *
31 * Pin usage:
32 * COL: PD0-7
33 * ROW: PB0-7, PF4-7
34 */
35 #ifndef DEBOUNCE
36 # define DEBOUNCE 10
37 #endif
38 static uint8_t debouncing = DEBOUNCE;
39
40 // matrix state buffer(1:on, 0:off)
41 static uint8_t *matrix;
42 static uint8_t *matrix_debouncing;
43 static uint8_t matrix0[MATRIX_ROWS];
44 static uint8_t matrix1[MATRIX_ROWS];
45
46 #ifdef MATRIX_HAS_GHOST
47 static bool matrix_has_ghost_in_row(uint8_t row);
48 #endif
49 static uint8_t read_col(void);
50 static void unselect_rows(void);
51 static void select_row(uint8_t row);
52
53
54 inline
55 uint8_t matrix_rows(void)
56 {
57 return MATRIX_ROWS;
58 }
59
60 inline
61 uint8_t matrix_cols(void)
62 {
63 return MATRIX_COLS;
64 }
65
66 void matrix_init(void)
67 {
68 print_enable = true;
69 debug_enable = true;
70 debug_matrix = true;
71 debug_keyboard = false;
72 debug_mouse = false;
73 print("debug enabled.\n");
74
75 // JTAG disable for PORT F. write JTD bit twice within four cycles.
76 MCUCR |= (1<<JTD);
77 MCUCR |= (1<<JTD);
78
79 // initialize rows
80 unselect_rows();
81
82 // initialize columns to input with pull-up(DDR:0, PORT:1)
83 DDRD = 0x00;
84 PORTD = 0xFF;
85
86 // initialize matrix state: all keys off
87 for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix0[i] = 0x00;
88 for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix1[i] = 0x00;
89 matrix = matrix0;
90 matrix_debouncing = matrix1;
91 }
92
93 uint8_t matrix_scan(void)
94 {
95 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
96 select_row(i);
97 _delay_us(30); // without this wait read unstable value.
98 if (matrix_debouncing[i] != read_col()) {
99 matrix_debouncing[i] = read_col();
100 if (debouncing) {
101 debug("bounce!: "); debug_hex(debouncing); debug("\n");
102 }
103 debouncing = DEBOUNCE;
104 }
105 unselect_rows();
106 }
107
108 if (debouncing) {
109 if (--debouncing) {
110 _delay_ms(1);
111 } else {
112 uint8_t *tmp = matrix;
113 matrix = matrix_debouncing;
114 matrix_debouncing = tmp;
115 }
116 }
117
118 return 1;
119 }
120
121 bool matrix_is_modified(void)
122 {
123 if (debouncing) return false;
124 return true;
125 }
126
127 inline
128 bool matrix_is_on(uint8_t row, uint8_t col)
129 {
130 return (matrix[row] & (1<<col));
131 }
132
133 inline
134 #if (MATRIX_COLS <= 8)
135 uint8_t matrix_get_row(uint8_t row)
136 #else
137 uint16_t matrix_get_row(uint8_t row)
138 #endif
139 {
140 return matrix[row];
141 }
142
143 void matrix_print(void)
144 {
145 print("\nr/c 01234567\n");
146 for (uint8_t row = 0; row < matrix_rows(); row++) {
147 phex(row); print(": ");
148 #if (MATRIX_COLS <= 8)
149 pbin_reverse(matrix_get_row(row));
150 #else
151 pbin_reverse16(matrix_get_row(row));
152 #endif
153 #ifdef MATRIX_HAS_GHOST
154 if (matrix_has_ghost_in_row(row)) {
155 print(" <ghost");
156 }
157 #endif
158 print("\n");
159 }
160 }
161
162 #ifdef MATRIX_HAS_GHOST
163 inline
164 static bool matrix_has_ghost_in_row(uint8_t row)
165 {
166 // no ghost exists in case less than 2 keys on
167 if (((matrix[row] - 1) & matrix[row]) == 0)
168 return false;
169
170 // ghost exists in case same state as other row
171 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
172 if (i != row && (matrix[i] & matrix[row]))
173 return true;
174 }
175 return false;
176 }
177 #endif
178
179 inline
180 static uint8_t read_col(void)
181 {
182 return ~PIND;
183 }
184
185 inline
186 static void unselect_rows(void)
187 {
188 // Hi-Z(DDR:0, PORT:0) to unselect
189 DDRB &= ~0b11111111;
190 PORTB &= ~0b11111111;
191 DDRF &= ~0b11110000;
192 PORTF &= ~0b11110000;
193 }
194
195 inline
196 static void select_row(uint8_t row)
197 {
198 // Output low(DDR:1, PORT:0) to select
199 switch (row) {
200 case 0:
201 case 1:
202 case 2:
203 case 3:
204 case 4:
205 case 5:
206 case 6:
207 case 7:
208 DDRB |= (1<<row);
209 PORTB &= ~(1<<row);
210 break;
211 case 8:
212 DDRF |= (1<<4);
213 PORTF &= ~(1<<4);
214 break;
215 case 9:
216 case 10:
217 case 11:
218 DDRF |= (1<<(row-4));
219 PORTF &= ~(1<<(row-4));
220 break;
221 }
222 }
Imprint / Impressum