]> git.gir.st - tmk_keyboard.git/blob - matrix.c
add anti-ghost logic
[tmk_keyboard.git] / matrix.c
1 /*
2 * scan matrix
3 */
4 #include <avr/io.h>
5 #include <util/delay.h>
6 #include "keymap.h"
7 #include "matrix.h"
8 #include "print.h"
9
10 // matrix is active low. (key on: 0/key off: 1)
11 // row: Hi-Z(unselected)/low output(selected)
12 // PD:0,1,2,3,6,7/PC:6,7/PF:7
13 // col: input w/pullup
14 // PB:0-8
15
16 // matrix state buffer
17 uint8_t *matrix;
18 uint8_t *matrix_prev;
19 static uint8_t _matrix0[MATRIX_ROWS];
20 static uint8_t _matrix1[MATRIX_ROWS];
21
22 static uint8_t read_col(void);
23 static void unselect_rows(void);
24 static void select_row(uint8_t row);
25
26
27 // this must be called once before matrix_scan.
28 void matrix_init(void)
29 {
30 // initialize row and col
31 unselect_rows();
32 DDRB = 0x00;
33 PORTB = 0xFF;
34
35 // initialize matrix state: all keys off
36 for (int i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0xFF;
37 for (int i=0; i < MATRIX_ROWS; i++) _matrix1[i] = 0xFF;
38 matrix = _matrix0;
39 matrix_prev = _matrix1;
40 }
41
42 uint8_t matrix_scan(void)
43 {
44 uint8_t row, state;
45 uint8_t *tmp;
46
47 tmp = matrix_prev;
48 matrix_prev = matrix;
49 matrix = tmp;
50
51 for (row = 0; row < MATRIX_ROWS; row++) {
52 select_row(row);
53 _delay_us(30); // without this wait read unstable value.
54 state = read_col();
55 unselect_rows();
56
57 matrix[row] = state;
58 }
59 return 1;
60 }
61
62 bool matrix_is_modified(void) {
63 for (int i=0; i <MATRIX_ROWS; i++) {
64 if (matrix[i] != matrix_prev[i])
65 return true;
66 }
67 return false;
68 }
69
70 bool matrix_has_ghost(void) {
71 for (int i=0; i <MATRIX_ROWS; i++) {
72 if (matrix_has_ghost_in_row(i))
73 return true;
74 }
75 return false;
76 }
77
78 bool matrix_has_ghost_in_row(uint8_t row) {
79 uint8_t state = ~matrix[row];
80 // no ghost exists in case less than 2 keys on
81 if (((state - 1) & state) == 0)
82 return false;
83
84 // ghost exists in case same state as other row
85 for (int i=0; i < MATRIX_ROWS; i++) {
86 if (i == row) continue;
87 if ((~matrix[i] & state) == state) return true;
88 }
89 return false;
90 }
91
92 static uint8_t read_col(void)
93 {
94 return PINB;
95 }
96
97 static void unselect_rows(void) {
98 DDRD = 0x00;
99 PORTD = 0x00;
100 DDRC = 0x00;
101 PORTC = 0x00;
102 DDRF = 0x00;
103 PORTF = 0x00;
104 }
105
106 static void select_row(uint8_t row)
107 {
108 switch (row) {
109 case 0:
110 DDRD = (1<<0);
111 PORTD = 0x00;
112 DDRC = 0x00;
113 PORTC = 0x00;
114 DDRF = 0x00;
115 PORTF = 0x00;
116 break;
117 case 1:
118 DDRD = (1<<1);
119 PORTD = 0x00;
120 DDRC = 0x00;
121 PORTC = 0x00;
122 DDRF = 0x00;
123 PORTF = 0x00;
124 break;
125 case 2:
126 DDRD = (1<<2);
127 PORTD = 0x00;
128 DDRC = 0x00;
129 PORTC = 0x00;
130 DDRF = 0x00;
131 PORTF = 0x00;
132 break;
133 case 3:
134 DDRD = (1<<3);
135 PORTD = 0x00;
136 DDRC = 0x00;
137 PORTC = 0x00;
138 DDRF = 0x00;
139 PORTF = 0x00;
140 break;
141 case 4:
142 DDRD = (1<<6);
143 PORTD = 0x00;
144 DDRC = 0x00;
145 PORTC = 0x00;
146 DDRF = 0x00;
147 PORTF = 0x00;
148 break;
149 case 5:
150 DDRD = (1<<7);
151 PORTD = 0x00;
152 DDRC = 0x00;
153 PORTC = 0x00;
154 DDRF = 0x00;
155 PORTF = 0x00;
156 break;
157 case 6:
158 DDRD = 0x00;
159 PORTD = 0x00;
160 DDRC = (1<<6);
161 PORTC = 0x00;
162 DDRF = 0x00;
163 PORTF = 0x00;
164 break;
165 case 7:
166 DDRD = 0x00;
167 PORTD = 0x00;
168 DDRC = (1<<7);
169 PORTC = 0x00;
170 DDRF = 0x00;
171 PORTF = 0x00;
172 break;
173 case 8:
174 DDRD = 0x00;
175 PORTD = 0x00;
176 DDRC = 0x00;
177 PORTC = 0x00;
178 DDRF = (1<<7);
179 PORTF = 0x00;
180 break;
181 }
182 }
Imprint / Impressum