diff options
author | Jack Humbert <jack.humb@gmail.com> | 2016-07-04 11:45:58 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-07-04 11:45:58 -0400 |
commit | 8e88d55bfd7c88cb15845e0c6415e4e892532861 (patch) | |
tree | 281f82e47a34c9c7176537cdd85c76c387a8286d /quantum/matrix.c | |
parent | 21ee3eb569caffdf2ad581c668682c0109c978e5 (diff) | |
download | qmk_firmware-8e88d55bfd7c88cb15845e0c6415e4e892532861.tar.gz qmk_firmware-8e88d55bfd7c88cb15845e0c6415e4e892532861.zip |
reverts #343 for the most part (#474)
Diffstat (limited to 'quantum/matrix.c')
-rw-r--r-- | quantum/matrix.c | 292 |
1 files changed, 163 insertions, 129 deletions
diff --git a/quantum/matrix.c b/quantum/matrix.c index a38c13f15..094917025 100644 --- a/quantum/matrix.c +++ b/quantum/matrix.c | |||
@@ -26,32 +26,46 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
26 | #include "util.h" | 26 | #include "util.h" |
27 | #include "matrix.h" | 27 | #include "matrix.h" |
28 | 28 | ||
29 | #ifdef MATRIX_HAS_GHOST | 29 | /* Set 0 if debouncing isn't needed */ |
30 | # error "The universal matrix.c file cannot be used for this keyboard." | 30 | /* |
31 | #endif | 31 | * This constant define not debouncing time in msecs, but amount of matrix |
32 | * scan loops which should be made to get stable debounced results. | ||
33 | * | ||
34 | * On Ergodox matrix scan rate is relatively low, because of slow I2C. | ||
35 | * Now it's only 317 scans/second, or about 3.15 msec/scan. | ||
36 | * According to Cherry specs, debouncing time is 5 msec. | ||
37 | * | ||
38 | * And so, there is no sense to have DEBOUNCE higher than 2. | ||
39 | */ | ||
32 | 40 | ||
33 | #ifndef DEBOUNCING_DELAY | 41 | #ifndef DEBOUNCING_DELAY |
34 | # define DEBOUNCING_DELAY 5 | 42 | # define DEBOUNCING_DELAY 5 |
35 | #endif | 43 | #endif |
44 | static uint8_t debouncing = DEBOUNCING_DELAY; | ||
36 | 45 | ||
37 | static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; | 46 | static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; |
38 | static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; | 47 | static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; |
39 | /* matrix state */ | 48 | |
40 | #if DIODE_DIRECTION == COL2ROW | 49 | /* matrix state(1:on, 0:off) */ |
41 | static matrix_row_t matrix[MATRIX_ROWS]; | 50 | static matrix_row_t matrix[MATRIX_ROWS]; |
42 | #else | 51 | static matrix_row_t matrix_debouncing[MATRIX_ROWS]; |
43 | static matrix_col_t matrix[MATRIX_COLS]; | 52 | |
53 | #if DIODE_DIRECTION == ROW2COL | ||
54 | static matrix_row_t matrix_reversed[MATRIX_COLS]; | ||
55 | static matrix_row_t matrix_reversed_debouncing[MATRIX_COLS]; | ||
44 | #endif | 56 | #endif |
45 | static int8_t debouncing_delay = -1; | ||
46 | 57 | ||
47 | #if DIODE_DIRECTION == COL2ROW | 58 | #if MATRIX_COLS > 16 |
48 | static void toggle_row(uint8_t row); | 59 | #define SHIFTER 1UL |
49 | static matrix_row_t read_cols(void); | ||
50 | #else | 60 | #else |
51 | static void toggle_col(uint8_t col); | 61 | #define SHIFTER 1 |
52 | static matrix_col_t read_rows(void); | ||
53 | #endif | 62 | #endif |
54 | 63 | ||
64 | static matrix_row_t read_cols(void); | ||
65 | static void init_cols(void); | ||
66 | static void unselect_rows(void); | ||
67 | static void select_row(uint8_t row); | ||
68 | |||
55 | __attribute__ ((weak)) | 69 | __attribute__ ((weak)) |
56 | void matrix_init_quantum(void) { | 70 | void matrix_init_quantum(void) { |
57 | matrix_init_kb(); | 71 | matrix_init_kb(); |
@@ -80,10 +94,12 @@ __attribute__ ((weak)) | |||
80 | void matrix_scan_user(void) { | 94 | void matrix_scan_user(void) { |
81 | } | 95 | } |
82 | 96 | ||
97 | inline | ||
83 | uint8_t matrix_rows(void) { | 98 | uint8_t matrix_rows(void) { |
84 | return MATRIX_ROWS; | 99 | return MATRIX_ROWS; |
85 | } | 100 | } |
86 | 101 | ||
102 | inline | ||
87 | uint8_t matrix_cols(void) { | 103 | uint8_t matrix_cols(void) { |
88 | return MATRIX_COLS; | 104 | return MATRIX_COLS; |
89 | } | 105 | } |
@@ -113,161 +129,179 @@ uint8_t matrix_cols(void) { | |||
113 | // } | 129 | // } |
114 | 130 | ||
115 | void matrix_init(void) { | 131 | void matrix_init(void) { |
116 | /* frees PORTF by setting the JTD bit twice within four cycles */ | 132 | // To use PORTF disable JTAG with writing JTD bit twice within four cycles. |
117 | #ifdef __AVR_ATmega32U4__ | 133 | #ifdef __AVR_ATmega32U4__ |
118 | MCUCR |= _BV(JTD); | 134 | MCUCR |= _BV(JTD); |
119 | MCUCR |= _BV(JTD); | 135 | MCUCR |= _BV(JTD); |
120 | #endif | 136 | #endif |
121 | /* initializes the I/O pins */ | 137 | |
122 | #if DIODE_DIRECTION == COL2ROW | 138 | // initialize row and col |
123 | for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { | 139 | unselect_rows(); |
124 | /* DDRxn */ | 140 | init_cols(); |
125 | _SFR_IO8((row_pins[r] >> 4) + 1) |= _BV(row_pins[r] & 0xF); | 141 | |
126 | toggle_row(r); | 142 | // initialize matrix state: all keys off |
127 | } | 143 | for (uint8_t i=0; i < MATRIX_ROWS; i++) { |
128 | for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { | 144 | matrix[i] = 0; |
129 | /* PORTxn */ | 145 | matrix_debouncing[i] = 0; |
130 | _SFR_IO8((col_pins[c] >> 4) + 2) |= _BV(col_pins[c] & 0xF); | ||
131 | } | ||
132 | #else | ||
133 | for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { | ||
134 | /* DDRxn */ | ||
135 | _SFR_IO8((col_pins[c] >> 4) + 1) |= _BV(col_pins[c] & 0xF); | ||
136 | toggle_col(c); | ||
137 | } | ||
138 | for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { | ||
139 | /* PORTxn */ | ||
140 | _SFR_IO8((row_pins[r] >> 4) + 2) |= _BV(row_pins[r] & 0xF); | ||
141 | } | 146 | } |
142 | #endif | 147 | |
143 | matrix_init_quantum(); | 148 | matrix_init_quantum(); |
144 | } | 149 | } |
145 | 150 | ||
151 | uint8_t matrix_scan(void) | ||
152 | { | ||
153 | |||
146 | #if DIODE_DIRECTION == COL2ROW | 154 | #if DIODE_DIRECTION == COL2ROW |
147 | uint8_t matrix_scan(void) { | 155 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { |
148 | static matrix_row_t debouncing_matrix[MATRIX_ROWS]; | 156 | select_row(i); |
149 | for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { | 157 | wait_us(30); // without this wait read unstable value. |
150 | toggle_row(r); | 158 | matrix_row_t cols = read_cols(); |
151 | matrix_row_t state = read_cols(); | 159 | if (matrix_debouncing[i] != cols) { |
152 | if (debouncing_matrix[r] != state) { | 160 | matrix_debouncing[i] = cols; |
153 | debouncing_matrix[r] = state; | 161 | if (debouncing) { |
154 | debouncing_delay = DEBOUNCING_DELAY; | 162 | debug("bounce!: "); debug_hex(debouncing); debug("\n"); |
155 | } | ||
156 | toggle_row(r); | ||
157 | } | ||
158 | if (debouncing_delay >= 0) { | ||
159 | dprintf("Debouncing delay remaining: %X\n", debouncing_delay); | ||
160 | --debouncing_delay; | ||
161 | if (debouncing_delay >= 0) { | ||
162 | wait_ms(1); | ||
163 | } | ||
164 | else { | ||
165 | for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { | ||
166 | matrix[r] = debouncing_matrix[r]; | ||
167 | } | 163 | } |
164 | debouncing = DEBOUNCING_DELAY; | ||
168 | } | 165 | } |
166 | unselect_rows(); | ||
169 | } | 167 | } |
170 | matrix_scan_quantum(); | ||
171 | return 1; | ||
172 | } | ||
173 | |||
174 | static void toggle_row(uint8_t row) { | ||
175 | /* PINxn */ | ||
176 | _SFR_IO8((row_pins[row] >> 4)) = _BV(row_pins[row] & 0xF); | ||
177 | } | ||
178 | 168 | ||
179 | static matrix_row_t read_cols(void) { | 169 | if (debouncing) { |
180 | matrix_row_t state = 0; | 170 | if (--debouncing) { |
181 | for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { | 171 | wait_us(1); |
182 | /* PINxn */ | 172 | } else { |
183 | if (!(_SFR_IO8((col_pins[c] >> 4)) & _BV(col_pins[c] & 0xF))) { | 173 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { |
184 | state |= (matrix_row_t)1 << c; | 174 | matrix[i] = matrix_debouncing[i]; |
175 | } | ||
185 | } | 176 | } |
186 | } | 177 | } |
187 | return state; | ||
188 | } | ||
189 | |||
190 | matrix_row_t matrix_get_row(uint8_t row) { | ||
191 | return matrix[row]; | ||
192 | } | ||
193 | |||
194 | #else | 178 | #else |
195 | uint8_t matrix_scan(void) { | 179 | for (uint8_t i = 0; i < MATRIX_COLS; i++) { |
196 | static matrix_col_t debouncing_matrix[MATRIX_COLS]; | 180 | select_row(i); |
197 | for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { | 181 | wait_us(30); // without this wait read unstable value. |
198 | toggle_col(c); | 182 | matrix_row_t rows = read_cols(); |
199 | matrix_col_t state = read_rows(); | 183 | if (matrix_reversed_debouncing[i] != rows) { |
200 | if (debouncing_matrix[c] != state) { | 184 | matrix_reversed_debouncing[i] = rows; |
201 | debouncing_matrix[c] = state; | 185 | if (debouncing) { |
202 | debouncing_delay = DEBOUNCING_DELAY; | 186 | debug("bounce!: "); debug_hex(debouncing); debug("\n"); |
187 | } | ||
188 | debouncing = DEBOUNCING_DELAY; | ||
203 | } | 189 | } |
204 | toggle_col(c); | 190 | unselect_rows(); |
205 | } | 191 | } |
206 | if (debouncing_delay >= 0) { | 192 | |
207 | dprintf("Debouncing delay remaining: %X\n", debouncing_delay); | 193 | if (debouncing) { |
208 | --debouncing_delay; | 194 | if (--debouncing) { |
209 | if (debouncing_delay >= 0) { | 195 | wait_us(1); |
210 | wait_ms(1); | 196 | } else { |
211 | } | 197 | for (uint8_t i = 0; i < MATRIX_COLS; i++) { |
212 | else { | 198 | matrix_reversed[i] = matrix_reversed_debouncing[i]; |
213 | for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { | ||
214 | matrix[c] = debouncing_matrix[c]; | ||
215 | } | 199 | } |
216 | } | 200 | } |
217 | } | 201 | } |
202 | for (uint8_t y = 0; y < MATRIX_ROWS; y++) { | ||
203 | matrix_row_t row = 0; | ||
204 | for (uint8_t x = 0; x < MATRIX_COLS; x++) { | ||
205 | row |= ((matrix_reversed[x] & (1<<y)) >> y) << x; | ||
206 | } | ||
207 | matrix[y] = row; | ||
208 | } | ||
209 | #endif | ||
210 | |||
218 | matrix_scan_quantum(); | 211 | matrix_scan_quantum(); |
212 | |||
219 | return 1; | 213 | return 1; |
220 | } | 214 | } |
221 | 215 | ||
222 | static void toggle_col(uint8_t col) { | 216 | bool matrix_is_modified(void) |
223 | /* PINxn */ | 217 | { |
224 | _SFR_IO8((col_pins[col] >> 4)) = _BV(col_pins[col] & 0xF); | 218 | if (debouncing) return false; |
219 | return true; | ||
225 | } | 220 | } |
226 | 221 | ||
227 | static matrix_col_t read_rows(void) { | 222 | inline |
228 | matrix_col_t state = 0; | 223 | bool matrix_is_on(uint8_t row, uint8_t col) |
229 | for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { | 224 | { |
230 | /* PINxn */ | 225 | return (matrix[row] & ((matrix_row_t)1<col)); |
231 | if (!(_SFR_IO8((row_pins[r] >> 4)) & _BV(row_pins[r] & 0xF))) { | 226 | } |
232 | state |= (matrix_col_t)1 << r; | 227 | |
233 | } | 228 | inline |
229 | matrix_row_t matrix_get_row(uint8_t row) | ||
230 | { | ||
231 | return matrix[row]; | ||
232 | } | ||
233 | |||
234 | void matrix_print(void) | ||
235 | { | ||
236 | print("\nr/c 0123456789ABCDEF\n"); | ||
237 | for (uint8_t row = 0; row < MATRIX_ROWS; row++) { | ||
238 | phex(row); print(": "); | ||
239 | pbin_reverse16(matrix_get_row(row)); | ||
240 | print("\n"); | ||
234 | } | 241 | } |
235 | return state; | ||
236 | } | 242 | } |
237 | 243 | ||
238 | matrix_row_t matrix_get_row(uint8_t row) { | 244 | uint8_t matrix_key_count(void) |
239 | matrix_row_t state = 0; | 245 | { |
240 | matrix_col_t mask = (matrix_col_t)1 << row; | 246 | uint8_t count = 0; |
241 | for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { | 247 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { |
242 | if (matrix[c] & mask) { | 248 | count += bitpop16(matrix[i]); |
243 | state |= (matrix_row_t)1 << c; | ||
244 | } | ||
245 | } | 249 | } |
246 | return state; | 250 | return count; |
247 | } | 251 | } |
248 | 252 | ||
253 | static void init_cols(void) | ||
254 | { | ||
255 | #if DIODE_DIRECTION == COL2ROW | ||
256 | for(int x = 0; x < MATRIX_COLS; x++) { | ||
257 | int pin = col_pins[x]; | ||
258 | #else | ||
259 | for(int x = 0; x < MATRIX_ROWS; x++) { | ||
260 | int pin = row_pins[x]; | ||
249 | #endif | 261 | #endif |
250 | 262 | _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); | |
251 | bool matrix_is_modified(void) { | 263 | _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); |
252 | if (debouncing_delay >= 0) return false; | 264 | } |
253 | return true; | ||
254 | } | 265 | } |
255 | 266 | ||
256 | bool matrix_is_on(uint8_t row, uint8_t col) { | 267 | static matrix_row_t read_cols(void) |
257 | return matrix_get_row(row) & (matrix_row_t)1 << col; | 268 | { |
258 | } | 269 | matrix_row_t result = 0; |
259 | 270 | ||
260 | void matrix_print(void) { | 271 | #if DIODE_DIRECTION == COL2ROW |
261 | dprintln("Human-readable matrix state:"); | 272 | for(int x = 0; x < MATRIX_COLS; x++) { |
262 | for (uint8_t r = 0; r < MATRIX_ROWS; r++) { | 273 | int pin = col_pins[x]; |
263 | dprintf("State of row %X: %016b\n", r, bitrev16(matrix_get_row(r))); | 274 | #else |
275 | for(int x = 0; x < MATRIX_ROWS; x++) { | ||
276 | int pin = row_pins[x]; | ||
277 | #endif | ||
278 | result |= (_SFR_IO8(pin >> 4) & _BV(pin & 0xF)) ? 0 : (SHIFTER << x); | ||
264 | } | 279 | } |
280 | return result; | ||
265 | } | 281 | } |
266 | 282 | ||
267 | uint8_t matrix_key_count(void) { | 283 | static void unselect_rows(void) |
268 | uint8_t count = 0; | 284 | { |
269 | for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { | 285 | #if DIODE_DIRECTION == COL2ROW |
270 | count += bitpop16(matrix_get_row(r)); | 286 | for(int x = 0; x < MATRIX_ROWS; x++) { |
287 | int pin = row_pins[x]; | ||
288 | #else | ||
289 | for(int x = 0; x < MATRIX_COLS; x++) { | ||
290 | int pin = col_pins[x]; | ||
291 | #endif | ||
292 | _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); | ||
293 | _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); | ||
271 | } | 294 | } |
272 | return count; | 295 | } |
296 | |||
297 | static void select_row(uint8_t row) | ||
298 | { | ||
299 | |||
300 | #if DIODE_DIRECTION == COL2ROW | ||
301 | int pin = row_pins[row]; | ||
302 | #else | ||
303 | int pin = col_pins[row]; | ||
304 | #endif | ||
305 | _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); | ||
306 | _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); | ||
273 | } | 307 | } |