Commit | Line | Data |
---|---|---|
d5ac5444 | 1 | /* |
2 | Copyright 2012 Jun Wako <wakojun@gmail.com> | |
3 | ||
4 | This program is free software: you can redistribute it and/or modify | |
5 | it under the terms of the GNU General Public License as published by | |
6 | the Free Software Foundation, either version 2 of the License, or | |
7 | (at your option) any later version. | |
8 | ||
9 | This program is distributed in the hope that it will be useful, | |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | GNU General Public License for more details. | |
13 | ||
14 | You should have received a copy of the GNU General Public License | |
15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | */ | |
17 | ||
18 | /* | |
19 | * scan matrix | |
20 | */ | |
21 | #include <stdint.h> | |
22 | #include <stdbool.h> | |
23 | #include <avr/io.h> | |
24 | #include <util/delay.h> | |
25 | #include "print.h" | |
26 | #include "debug.h" | |
27 | #include "util.h" | |
28 | #include "matrix.h" | |
29 | ||
30 | ||
31 | #ifndef DEBOUNCE | |
32 | # define DEBOUNCE 5 | |
33 | #endif | |
34 | static uint8_t debouncing = DEBOUNCE; | |
35 | ||
36 | /* matrix state(1:on, 0:off) */ | |
37 | static matrix_row_t matrix[MATRIX_ROWS]; | |
38 | static matrix_row_t matrix_debouncing[MATRIX_ROWS]; | |
39 | ||
40 | static matrix_row_t read_cols(void); | |
41 | static void init_cols(void); | |
42 | static void unselect_rows(void); | |
43 | static void select_row(uint8_t row); | |
44 | ||
45 | ||
46 | inline | |
47 | uint8_t matrix_rows(void) | |
48 | { | |
49 | return MATRIX_ROWS; | |
50 | } | |
51 | ||
52 | inline | |
53 | uint8_t matrix_cols(void) | |
54 | { | |
55 | return MATRIX_COLS; | |
56 | } | |
57 | ||
58 | void matrix_init(void) | |
59 | { | |
60 | // initialize row and col | |
61 | unselect_rows(); | |
62 | init_cols(); | |
63 | ||
64 | // initialize matrix state: all keys off | |
65 | for (uint8_t i=0; i < MATRIX_ROWS; i++) { | |
66 | matrix[i] = 0; | |
67 | matrix_debouncing[i] = 0; | |
68 | } | |
507ebb34 | 69 | |
70 | //debug | |
71 | debug_matrix = true; | |
72 | LED_ON(); | |
73 | _delay_ms(500); | |
74 | LED_OFF(); | |
d5ac5444 | 75 | } |
76 | ||
77 | uint8_t matrix_scan(void) | |
78 | { | |
79 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |
80 | select_row(i); | |
81 | _delay_us(30); // without this wait read unstable value. | |
82 | matrix_row_t cols = read_cols(); | |
83 | if (matrix_debouncing[i] != cols) { | |
84 | matrix_debouncing[i] = cols; | |
85 | if (debouncing) { | |
86 | debug("bounce!: "); debug_hex(debouncing); debug("\n"); | |
87 | } | |
88 | debouncing = DEBOUNCE; | |
89 | } | |
90 | unselect_rows(); | |
91 | } | |
92 | ||
93 | if (debouncing) { | |
94 | if (--debouncing) { | |
95 | _delay_ms(1); | |
96 | } else { | |
97 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |
98 | matrix[i] = matrix_debouncing[i]; | |
99 | } | |
100 | } | |
101 | } | |
102 | ||
65faab3b JH |
103 | matrix_scan_quantum(); |
104 | ||
d5ac5444 | 105 | return 1; |
106 | } | |
107 | ||
108 | inline | |
109 | bool matrix_is_on(uint8_t row, uint8_t col) | |
110 | { | |
111 | return (matrix[row] & ((matrix_row_t)1<<col)); | |
112 | } | |
113 | ||
114 | inline | |
115 | matrix_row_t matrix_get_row(uint8_t row) | |
116 | { | |
117 | return matrix[row]; | |
118 | } | |
119 | ||
120 | void matrix_print(void) | |
121 | { | |
122 | print("\nr/c 0123456789ABCDEF\n"); | |
123 | for (uint8_t row = 0; row < MATRIX_ROWS; row++) { | |
124 | phex(row); print(": "); | |
125 | pbin_reverse16(matrix_get_row(row)); | |
126 | print("\n"); | |
127 | } | |
128 | } | |
129 | ||
130 | /* Column pin configuration | |
131 | * col: 0 1 2 3 4 5 6 7 | |
132 | * pin: B0 B1 B2 B3 B4 B5 B6 B7 | |
133 | */ | |
134 | static void init_cols(void) | |
135 | { | |
136 | // Input with pull-up(DDR:0, PORT:1) | |
137 | DDRB &= ~0b11111111; | |
138 | PORTB |= 0b11111111; | |
139 | } | |
140 | ||
141 | /* Returns status of switches(1:on, 0:off) */ | |
142 | static matrix_row_t read_cols(void) | |
143 | { | |
144 | // Invert because PIN indicates 'switch on' with low(0) and 'off' with high(1) | |
145 | return ~PINB; | |
146 | } | |
147 | ||
148 | /* Row pin configuration | |
149 | * row: 0 1 2 3 4 5 6 7 | |
150 | * pin: D0 D1 D2 D3 D4 D5 D6 C2 | |
151 | */ | |
152 | static void unselect_rows(void) | |
153 | { | |
154 | // Hi-Z(DDR:0, PORT:0) to unselect | |
155 | DDRD &= ~0b01111111; | |
156 | PORTD &= ~0b01111111; | |
157 | DDRC &= ~0b00000100; | |
6fe4af82 | 158 | PORTC &= ~0b00000100; |
d5ac5444 | 159 | } |
160 | ||
de577995 | 161 | |
d5ac5444 | 162 | static void select_row(uint8_t row) |
163 | { | |
164 | // Output low(DDR:1, PORT:0) to select | |
165 | switch (row) { | |
166 | case 0: | |
167 | DDRD |= (1<<0); | |
168 | PORTD &= ~(1<<0); | |
169 | break; | |
170 | case 1: | |
171 | DDRD |= (1<<1); | |
172 | PORTD &= ~(1<<1); | |
173 | break; | |
174 | case 2: | |
175 | DDRD |= (1<<2); | |
176 | PORTD &= ~(1<<2); | |
177 | break; | |
178 | case 3: | |
179 | DDRD |= (1<<3); | |
180 | PORTD &= ~(1<<3); | |
181 | break; | |
182 | case 4: | |
183 | DDRD |= (1<<4); | |
184 | PORTD &= ~(1<<4); | |
185 | break; | |
186 | case 5: | |
187 | DDRD |= (1<<5); | |
188 | PORTD &= ~(1<<5); | |
189 | break; | |
190 | case 6: | |
191 | DDRD |= (1<<6); | |
192 | PORTD &= ~(1<<6); | |
193 | break; | |
194 | case 7: | |
195 | DDRC |= (1<<2); | |
196 | PORTC &= ~(1<<2); | |
197 | break; | |
198 | } | |
199 | } |