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