]> git.gir.st - tmk_keyboard.git/blob - macway/matrix.c
improve layer switching
[tmk_keyboard.git] / macway / 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 "controller.h"
11 #include "matrix_skel.h"
12
13 // matrix is active low. (key on: 0/key off: 1)
14 // row: Hi-Z(unselected)/low output(selected)
15 // PD0, PC7, PD7, PF6, PD6, PD1, PD2, PC6, PF7
16 // col: input w/pullup
17 // PB0-PB7
18
19 // matrix state buffer
20 static uint8_t *matrix;
21 static uint8_t *matrix_prev;
22 static uint8_t _matrix0[MATRIX_ROWS];
23 static uint8_t _matrix1[MATRIX_ROWS];
24
25 static bool matrix_has_ghost_in_row(uint8_t row);
26 static uint8_t read_col(void);
27 static void unselect_rows(void);
28 static void select_row(uint8_t row);
29
30
31 inline
32 int matrix_rows(void)
33 {
34 return MATRIX_ROWS;
35 }
36
37 inline
38 int matrix_cols(void)
39 {
40 return MATRIX_COLS;
41 }
42
43 // this must be called once before matrix_scan.
44 void matrix_init(void)
45 {
46 // initialize row and col
47 unselect_rows();
48 DDRB = 0x00;
49 PORTB = 0xFF;
50
51 // initialize matrix state: all keys off
52 for (int i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00;
53 for (int i=0; i < MATRIX_ROWS; i++) _matrix1[i] = 0x00;
54 matrix = _matrix0;
55 matrix_prev = _matrix1;
56 }
57
58 int matrix_scan(void)
59 {
60 uint8_t *tmp;
61
62 tmp = matrix_prev;
63 matrix_prev = matrix;
64 matrix = tmp;
65
66 for (int i = 0; i < MATRIX_ROWS; i++) {
67 select_row(i);
68 _delay_us(30); // without this wait read unstable value.
69 matrix[i] = ~read_col();
70 unselect_rows();
71 }
72 return 1;
73 }
74
75 bool matrix_is_modified(void)
76 {
77 for (int i = 0; i < MATRIX_ROWS; i++) {
78 if (matrix[i] != matrix_prev[i])
79 return true;
80 }
81 return false;
82 }
83
84 bool matrix_has_ghost(void)
85 {
86 for (int i = 0; i < MATRIX_ROWS; i++) {
87 if (matrix_has_ghost_in_row(i))
88 return true;
89 }
90 return false;
91 }
92
93 inline
94 bool matrix_is_on(int row, int col)
95 {
96 return (matrix[row] & (1<<col));
97 }
98
99 inline
100 uint16_t matrix_get_row(int row)
101 {
102 return matrix[row];
103 }
104
105 void matrix_print(void)
106 {
107 print("\nr/c 01234567\n");
108 for (int row = 0; row < matrix_rows(); row++) {
109 phex(row); print(": ");
110 pbin_reverse(matrix_get_row(row));
111 if (matrix_has_ghost_in_row(row)) {
112 print(" <ghost");
113 }
114 print("\n");
115 }
116 }
117
118 int matrix_key_count(void)
119 {
120 int count = 0;
121 for (int i = 0; i < MATRIX_ROWS; i++) {
122 count += bitpop(matrix[i]);
123 }
124 return count;
125 }
126
127 static bool matrix_has_ghost_in_row(uint8_t row)
128 {
129 // no ghost exists in case less than 2 keys on
130 if (((matrix[row] - 1) & matrix[row]) == 0)
131 return false;
132
133 // ghost exists in case same state as other row
134 for (int i=0; i < MATRIX_ROWS; i++) {
135 if (i != row && (matrix[i] & matrix[row]) == matrix[row])
136 return true;
137 }
138 return false;
139 }
140
141 static uint8_t read_col(void)
142 {
143 return PINB;
144 }
145
146 static void unselect_rows(void)
147 {
148 DDRD = 0x00;
149 PORTD = 0x00;
150 DDRC = 0x00;
151 PORTC = 0x00;
152 DDRF = 0x00;
153 PORTF = 0x00;
154 }
155
156 static void select_row(uint8_t row)
157 {
158 switch (row) {
159 case 0:
160 DDRD = (1<<0);
161 PORTD = 0x00;
162 DDRC = 0x00;
163 PORTC = 0x00;
164 DDRF = 0x00;
165 PORTF = 0x00;
166 break;
167 case 1:
168 DDRD = 0x00;
169 PORTD = 0x00;
170 DDRC = (1<<7);
171 PORTC = 0x00;
172 DDRF = 0x00;
173 PORTF = 0x00;
174 break;
175 case 2:
176 DDRD = (1<<7);
177 PORTD = 0x00;
178 DDRC = 0x00;
179 PORTC = 0x00;
180 DDRF = 0x00;
181 PORTF = 0x00;
182 break;
183 case 3:
184 DDRD = 0x00;
185 PORTD = 0x00;
186 DDRC = 0x00;
187 PORTC = 0x00;
188 DDRF = (1<<6);
189 PORTF = 0x00;
190 break;
191 case 4:
192 DDRD = (1<<6);
193 PORTD = 0x00;
194 DDRC = 0x00;
195 PORTC = 0x00;
196 DDRF = 0x00;
197 PORTF = 0x00;
198 break;
199 case 5:
200 DDRD = (1<<1);
201 PORTD = 0x00;
202 DDRC = 0x00;
203 PORTC = 0x00;
204 DDRF = 0x00;
205 PORTF = 0x00;
206 break;
207 case 6:
208 DDRD = (1<<2);
209 PORTD = 0x00;
210 DDRC = 0x00;
211 PORTC = 0x00;
212 DDRF = 0x00;
213 PORTF = 0x00;
214 break;
215 case 7:
216 DDRD = 0x00;
217 PORTD = 0x00;
218 DDRC = (1<<6);
219 PORTC = 0x00;
220 DDRF = 0x00;
221 PORTF = 0x00;
222 break;
223 case 8:
224 DDRD = 0x00;
225 PORTD = 0x00;
226 DDRC = 0x00;
227 PORTC = 0x00;
228 DDRF = (1<<7);
229 PORTF = 0x00;
230 break;
231 }
232 }
Imprint / Impressum