]> git.friedersdorff.com Git - max/tmk_keyboard.git/blob - macway/matrix.c
minor fix for HHKB Makefile and doc
[max/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 "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 static uint8_t read_col(void);
38 static void unselect_rows(void);
39 static void select_row(uint8_t row);
40
41
42 inline
43 uint8_t matrix_rows(void)
44 {
45     return MATRIX_ROWS;
46 }
47
48 inline
49 uint8_t matrix_cols(void)
50 {
51     return MATRIX_COLS;
52 }
53
54 void matrix_init(void)
55 {
56     // initialize row and col
57     unselect_rows();
58     // Input with pull-up(DDR:0, PORT:1)
59     DDRB = 0x00;
60     PORTB = 0xFF;
61
62     // initialize matrix state: all keys off
63     for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00;
64     for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix1[i] = 0x00;
65     matrix = _matrix0;
66     matrix_prev = _matrix1;
67 }
68
69 uint8_t matrix_scan(void)
70 {
71     uint8_t *tmp;
72
73     tmp = matrix_prev;
74     matrix_prev = matrix;
75     matrix = tmp;
76
77     for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
78         unselect_rows();
79         select_row(i);
80         _delay_us(30);  // without this wait read unstable value.
81         matrix[i] = ~read_col();
82     }
83     unselect_rows();
84     return 1;
85 }
86
87 bool matrix_is_modified(void)
88 {
89     for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
90         if (matrix[i] != matrix_prev[i])
91             return true;
92     }
93     return false;
94 }
95
96 inline
97 bool matrix_has_ghost(void)
98 {
99 #ifdef MATRIX_HAS_GHOST
100     for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
101         if (matrix_has_ghost_in_row(i))
102             return true;
103     }
104 #endif
105     return false;
106 }
107
108 inline
109 bool matrix_is_on(uint8_t row, uint8_t col)
110 {
111     return (matrix[row] & (1<<col));
112 }
113
114 inline
115 #if (MATRIX_COLS <= 8)
116 uint8_t matrix_get_row(uint8_t row)
117 #else
118 uint16_t matrix_get_row(uint8_t row)
119 #endif
120 {
121     return matrix[row];
122 }
123
124 void matrix_print(void)
125 {
126     print("\nr/c 01234567\n");
127     for (uint8_t row = 0; row < matrix_rows(); row++) {
128         phex(row); print(": ");
129 #if (MATRIX_COLS <= 8)
130         pbin_reverse(matrix_get_row(row));
131 #else
132         pbin_reverse16(matrix_get_row(row));
133 #endif
134 #ifdef MATRIX_HAS_GHOST
135         if (matrix_has_ghost_in_row(row)) {
136             print(" <ghost");
137         }
138 #endif
139         print("\n");
140     }
141 }
142
143 uint8_t matrix_key_count(void)
144 {
145     uint8_t count = 0;
146     for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
147 #if (MATRIX_COLS <= 8)
148         count += bitpop(matrix[i]);
149 #else
150         count += bitpop16(matrix[i]);
151 #endif
152     }
153     return count;
154 }
155
156 #ifdef MATRIX_HAS_GHOST
157 inline
158 static bool matrix_has_ghost_in_row(uint8_t row)
159 {
160     // no ghost exists in case less than 2 keys on
161     if (((matrix[row] - 1) & matrix[row]) == 0)
162         return false;
163
164     // ghost exists in case same state as other row
165     for (uint8_t i=0; i < MATRIX_ROWS; i++) {
166         if (i != row && (matrix[i] & matrix[row]) == matrix[row])
167             return true;
168     }
169     return false;
170 }
171 #endif
172
173 inline
174 static uint8_t read_col(void)
175 {
176     return PINB;
177 }
178
179 inline
180 static void unselect_rows(void)
181 {
182     // Hi-Z(DDR:0, PORT:0) to unselect
183     DDRC  &= ~0b11000000; // PC: 7,6
184     PORTC &= ~0b11000000;
185     DDRD  &= ~0b11000111; // PD: 7,6,2,1,0
186     PORTD &= ~0b11000111;
187     DDRF  &= ~0b11000000; // PF: 7,6
188     PORTF &= ~0b11000000;
189 }
190
191 inline
192 static void select_row(uint8_t row)
193 {
194     // Output low(DDR:1, PORT:0) to select
195     // row: 0    1    2    3    4    5    6    7    8
196     // pin: PD0, PC7, PD7, PF6, PD6, PD1, PD2, PC6, PF7
197     switch (row) {
198         case 0:
199             DDRD  |= (1<<0);
200             PORTD &= ~(1<<0);
201             break;
202         case 1:
203             DDRC  |= (1<<7);
204             PORTC &= ~(1<<7);
205             break;
206         case 2:
207             DDRD  |= (1<<7);
208             PORTD &= ~(1<<7);
209             break;
210         case 3:
211             DDRF  |= (1<<6);
212             PORTF &= ~(1<<6);
213             break;
214         case 4:
215             DDRD  |= (1<<6);
216             PORTD &= ~(1<<6);
217             break;
218         case 5:
219             DDRD  |= (1<<1);
220             PORTD &= ~(1<<1);
221             break;
222         case 6:
223             DDRD  |= (1<<2);
224             PORTD &= ~(1<<2);
225             break;
226         case 7:
227             DDRC  |= (1<<6);
228             PORTC &= ~(1<<6);
229             break;
230         case 8:
231             DDRF  |= (1<<7);
232             PORTF &= ~(1<<7);
233             break;
234     }
235 }