]> git.donarmstrong.com Git - tmk_firmware.git/blob - macway/matrix.c
improve layer switching
[tmk_firmware.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 }