]> git.gir.st - tmk_keyboard.git/blob - hhkb/matrix.c
fixed hhkb to comply new API.
[tmk_keyboard.git] / hhkb / matrix.c
1 /*
2 * scan matrix
3 */
4 #include <stdint.h>
5 #include <stdbool.h>
6 #include <avr/io.h>
7 #include <util/delay.h>
8 #include "print.h"
9 #include "util.h"
10 #include "matrix.h"
11
12
13 #if (MATRIX_COLS > 16)
14 # error "MATRIX_COLS must not exceed 16"
15 #endif
16 #if (MATRIX_ROWS > 255)
17 # error "MATRIX_ROWS must not exceed 255"
18 #endif
19
20
21 // matrix state buffer(1:on, 0:off)
22 #if (MATRIX_COLS <= 8)
23 static uint8_t *matrix;
24 static uint8_t *matrix_prev;
25 static uint8_t _matrix0[MATRIX_ROWS];
26 static uint8_t _matrix1[MATRIX_ROWS];
27 #else
28 static uint16_t *matrix;
29 static uint16_t *matrix_prev;
30 static uint16_t _matrix0[MATRIX_ROWS];
31 static uint16_t _matrix1[MATRIX_ROWS];
32 #endif
33
34 #ifdef MATRIX_HAS_GHOST
35 static bool matrix_has_ghost_in_row(uint8_t row);
36 #endif
37
38
39 // matrix is active low. (key on: 0/key off: 1)
40 //
41 // HHKB has no ghost and no bounce.
42 // row: HC4051 select input channel(0-8)
43 // PB0, PB1, PB2(A, B, C)
44 // col: LS145 select low output line(0-8)
45 // PB3, PB4, PB5, PB6(A, B, C, D)
46 // use D as ENABLE: (enable: 0/unenable: 1)
47 // key: KEY: (on: 0/ off:1)
48 // KEY_PREV: (on: 1/ off: 0)
49 // PE6,PE7(KEY, KEY_PREV)
50 #define COL_ENABLE (1<<6)
51 #define KEY_SELELCT(ROW, COL) (PORTB = (PORTB&(1<<7))|COL_ENABLE|(((COL)&0x07)<<3)|((ROW)&0x07))
52 #define KEY_ENABLE (PORTB &= ~COL_ENABLE)
53 #define KEY_UNABLE (PORTB |= COL_ENABLE)
54 #define KEY_STATE (PINE&(1<<6))
55 #define KEY_PREV_ON (PORTE |= (1<<7))
56 #define KEY_PREV_OFF (PORTE &= ~(1<<7))
57
58
59 inline
60 uint8_t matrix_rows(void)
61 {
62 return MATRIX_ROWS;
63 }
64
65 inline
66 uint8_t matrix_cols(void)
67 {
68 return MATRIX_COLS;
69 }
70
71 void matrix_init(void)
72 {
73 // row & col output(PB0-6)
74 DDRB = 0xFF;
75 KEY_SELELCT(0, 0);
76 // KEY: input with pullup(PE6)
77 // KEY_PREV: output(PE7)
78 DDRE = 0xBF;
79 PORTE = 0x40;
80
81 // initialize matrix state: all keys off
82 for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00;
83 for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix1[i] = 0x00;
84 matrix = _matrix0;
85 matrix_prev = _matrix1;
86 }
87
88 uint8_t matrix_scan(void)
89 {
90 uint8_t *tmp;
91
92 tmp = matrix_prev;
93 matrix_prev = matrix;
94 matrix = tmp;
95
96 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
97 for (uint8_t col = 0; col < MATRIX_COLS; col++) {
98 KEY_SELELCT(row, col);
99 _delay_us(40); // from logic analyzer chart
100 if (matrix_prev[row] & (1<<col)) {
101 KEY_PREV_ON;
102 }
103 _delay_us(7); // from logic analyzer chart
104 KEY_ENABLE;
105 _delay_us(10); // from logic analyzer chart
106 if (KEY_STATE) {
107 matrix[row] &= ~(1<<col);
108 } else {
109 matrix[row] |= (1<<col);
110 }
111 KEY_PREV_OFF;
112 KEY_UNABLE;
113 _delay_us(150); // from logic analyzer chart
114 }
115 }
116 return 1;
117 }
118
119 bool matrix_is_modified(void)
120 {
121 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
122 if (matrix[i] != matrix_prev[i])
123 return true;
124 }
125 return false;
126 }
127
128 inline
129 bool matrix_has_ghost(void)
130 {
131 #ifdef MATRIX_HAS_GHOST
132 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
133 if (matrix_has_ghost_in_row(i))
134 return true;
135 }
136 #endif
137 return false;
138 }
139
140 inline
141 bool matrix_is_on(uint8_t row, uint8_t col)
142 {
143 return (matrix[row] & (1<<col));
144 }
145
146 inline
147 #if (MATRIX_COLS <= 8)
148 uint8_t matrix_get_row(uint8_t row)
149 #else
150 uint16_t matrix_get_row(uint8_t row)
151 #endif
152 {
153 return matrix[row];
154 }
155
156 void matrix_print(void)
157 {
158 #if (MATRIX_COLS <= 8)
159 print("\nr/c 01234567\n");
160 #else
161 print("\nr/c 0123456789ABCDEF\n");
162 #endif
163 for (uint8_t row = 0; row < matrix_rows(); row++) {
164 phex(row); print(": ");
165 #if (MATRIX_COLS <= 8)
166 pbin_reverse(matrix_get_row(row));
167 #else
168 pbin_reverse16(matrix_get_row(row));
169 #endif
170 #ifdef MATRIX_HAS_GHOST
171 if (matrix_has_ghost_in_row(row)) {
172 print(" <ghost");
173 }
174 #endif
175 print("\n");
176 }
177 }
178
179 uint8_t matrix_key_count(void)
180 {
181 uint8_t count = 0;
182 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
183 #if (MATRIX_COLS <= 8)
184 count += bitpop(matrix[i]);
185 #else
186 count += bitpop16(matrix[i]);
187 #endif
188 }
189 return count;
190 }
191
192 #ifdef MATRIX_HAS_GHOST
193 inline
194 static bool matrix_has_ghost_in_row(uint8_t row)
195 {
196 // no ghost exists in case less than 2 keys on
197 if (((matrix[row] - 1) & matrix[row]) == 0)
198 return false;
199
200 // ghost exists in case same state as other row
201 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
202 if (i != row && (matrix[i] & matrix[row]) == matrix[row])
203 return true;
204 }
205 return false;
206 }
207 #endif
Imprint / Impressum