diff options
Diffstat (limited to 'quantum/matrix.c')
| -rw-r--r-- | quantum/matrix.c | 331 |
1 files changed, 223 insertions, 108 deletions
diff --git a/quantum/matrix.c b/quantum/matrix.c index 3174e0739..5337e2626 100644 --- a/quantum/matrix.c +++ b/quantum/matrix.c | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | Copyright 2012 Jun Wako | 2 | Copyright 2012-2017 Jun Wako, Jack Humbert |
| 3 | Copyright 2014 Jack Humbert | ||
| 4 | 3 | ||
| 5 | This program is free software: you can redistribute it and/or modify | 4 | This program is free software: you can redistribute it and/or modify |
| 6 | it under the terms of the GNU General Public License as published by | 5 | it under the terms of the GNU General Public License as published by |
| @@ -25,37 +24,66 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 25 | #include "debug.h" | 24 | #include "debug.h" |
| 26 | #include "util.h" | 25 | #include "util.h" |
| 27 | #include "matrix.h" | 26 | #include "matrix.h" |
| 27 | #include "timer.h" | ||
| 28 | |||
| 28 | 29 | ||
| 29 | /* Set 0 if debouncing isn't needed */ | 30 | /* Set 0 if debouncing isn't needed */ |
| 30 | 31 | ||
| 31 | #ifndef DEBOUNCING_DELAY | 32 | #ifndef DEBOUNCING_DELAY |
| 32 | # define DEBOUNCING_DELAY 5 | 33 | # define DEBOUNCING_DELAY 5 |
| 33 | #endif | 34 | #endif |
| 34 | static uint8_t debouncing = DEBOUNCING_DELAY; | ||
| 35 | 35 | ||
| 36 | #if (DEBOUNCING_DELAY > 0) | ||
| 37 | static uint16_t debouncing_time; | ||
| 38 | static bool debouncing = false; | ||
| 39 | #endif | ||
| 40 | |||
| 41 | #if (MATRIX_COLS <= 8) | ||
| 42 | # define print_matrix_header() print("\nr/c 01234567\n") | ||
| 43 | # define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row)) | ||
| 44 | # define matrix_bitpop(i) bitpop(matrix[i]) | ||
| 45 | # define ROW_SHIFTER ((uint8_t)1) | ||
| 46 | #elif (MATRIX_COLS <= 16) | ||
| 47 | # define print_matrix_header() print("\nr/c 0123456789ABCDEF\n") | ||
| 48 | # define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row)) | ||
| 49 | # define matrix_bitpop(i) bitpop16(matrix[i]) | ||
| 50 | # define ROW_SHIFTER ((uint16_t)1) | ||
| 51 | #elif (MATRIX_COLS <= 32) | ||
| 52 | # define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n") | ||
| 53 | # define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row)) | ||
| 54 | # define matrix_bitpop(i) bitpop32(matrix[i]) | ||
| 55 | # define ROW_SHIFTER ((uint32_t)1) | ||
| 56 | #endif | ||
| 57 | |||
| 58 | #ifdef MATRIX_MASKED | ||
| 59 | extern const matrix_row_t matrix_mask[]; | ||
| 60 | #endif | ||
| 61 | |||
| 62 | #if (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW) | ||
| 36 | static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; | 63 | static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; |
| 37 | static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; | 64 | static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; |
| 65 | #endif | ||
| 38 | 66 | ||
| 39 | /* matrix state(1:on, 0:off) */ | 67 | /* matrix state(1:on, 0:off) */ |
| 40 | static matrix_row_t matrix[MATRIX_ROWS]; | 68 | static matrix_row_t matrix[MATRIX_ROWS]; |
| 69 | |||
| 41 | static matrix_row_t matrix_debouncing[MATRIX_ROWS]; | 70 | static matrix_row_t matrix_debouncing[MATRIX_ROWS]; |
| 42 | 71 | ||
| 43 | #if DIODE_DIRECTION == ROW2COL | ||
| 44 | static matrix_row_t matrix_reversed[MATRIX_COLS]; | ||
| 45 | static matrix_row_t matrix_reversed_debouncing[MATRIX_COLS]; | ||
| 46 | #endif | ||
| 47 | 72 | ||
| 48 | #if MATRIX_COLS > 16 | 73 | #if (DIODE_DIRECTION == COL2ROW) |
| 49 | #define SHIFTER 1UL | 74 | static void init_cols(void); |
| 50 | #else | 75 | static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row); |
| 51 | #define SHIFTER 1 | 76 | static void unselect_rows(void); |
| 77 | static void select_row(uint8_t row); | ||
| 78 | static void unselect_row(uint8_t row); | ||
| 79 | #elif (DIODE_DIRECTION == ROW2COL) | ||
| 80 | static void init_rows(void); | ||
| 81 | static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col); | ||
| 82 | static void unselect_cols(void); | ||
| 83 | static void unselect_col(uint8_t col); | ||
| 84 | static void select_col(uint8_t col); | ||
| 52 | #endif | 85 | #endif |
| 53 | 86 | ||
| 54 | static matrix_row_t read_cols(void); | ||
| 55 | static void init_cols(void); | ||
| 56 | static void unselect_rows(void); | ||
| 57 | static void select_row(uint8_t row); | ||
| 58 | |||
| 59 | __attribute__ ((weak)) | 87 | __attribute__ ((weak)) |
| 60 | void matrix_init_quantum(void) { | 88 | void matrix_init_quantum(void) { |
| 61 | matrix_init_kb(); | 89 | matrix_init_kb(); |
| @@ -95,7 +123,7 @@ uint8_t matrix_cols(void) { | |||
| 95 | } | 123 | } |
| 96 | 124 | ||
| 97 | // void matrix_power_up(void) { | 125 | // void matrix_power_up(void) { |
| 98 | // #if DIODE_DIRECTION == COL2ROW | 126 | // #if (DIODE_DIRECTION == COL2ROW) |
| 99 | // for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { | 127 | // for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { |
| 100 | // /* DDRxn */ | 128 | // /* DDRxn */ |
| 101 | // _SFR_IO8((row_pins[r] >> 4) + 1) |= _BV(row_pins[r] & 0xF); | 129 | // _SFR_IO8((row_pins[r] >> 4) + 1) |= _BV(row_pins[r] & 0xF); |
| @@ -105,7 +133,7 @@ uint8_t matrix_cols(void) { | |||
| 105 | // /* PORTxn */ | 133 | // /* PORTxn */ |
| 106 | // _SFR_IO8((col_pins[c] >> 4) + 2) |= _BV(col_pins[c] & 0xF); | 134 | // _SFR_IO8((col_pins[c] >> 4) + 2) |= _BV(col_pins[c] & 0xF); |
| 107 | // } | 135 | // } |
| 108 | // #else | 136 | // #elif (DIODE_DIRECTION == ROW2COL) |
| 109 | // for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { | 137 | // for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { |
| 110 | // /* DDRxn */ | 138 | // /* DDRxn */ |
| 111 | // _SFR_IO8((col_pins[c] >> 4) + 1) |= _BV(col_pins[c] & 0xF); | 139 | // _SFR_IO8((col_pins[c] >> 4) + 1) |= _BV(col_pins[c] & 0xF); |
| @@ -119,15 +147,21 @@ uint8_t matrix_cols(void) { | |||
| 119 | // } | 147 | // } |
| 120 | 148 | ||
| 121 | void matrix_init(void) { | 149 | void matrix_init(void) { |
| 150 | |||
| 122 | // To use PORTF disable JTAG with writing JTD bit twice within four cycles. | 151 | // To use PORTF disable JTAG with writing JTD bit twice within four cycles. |
| 123 | #ifdef __AVR_ATmega32U4__ | 152 | #if (defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega32U4__)) |
| 124 | MCUCR |= _BV(JTD); | 153 | MCUCR |= _BV(JTD); |
| 125 | MCUCR |= _BV(JTD); | 154 | MCUCR |= _BV(JTD); |
| 126 | #endif | 155 | #endif |
| 127 | 156 | ||
| 128 | // initialize row and col | 157 | // initialize row and col |
| 158 | #if (DIODE_DIRECTION == COL2ROW) | ||
| 129 | unselect_rows(); | 159 | unselect_rows(); |
| 130 | init_cols(); | 160 | init_cols(); |
| 161 | #elif (DIODE_DIRECTION == ROW2COL) | ||
| 162 | unselect_cols(); | ||
| 163 | init_rows(); | ||
| 164 | #endif | ||
| 131 | 165 | ||
| 132 | // initialize matrix state: all keys off | 166 | // initialize matrix state: all keys off |
| 133 | for (uint8_t i=0; i < MATRIX_ROWS; i++) { | 167 | for (uint8_t i=0; i < MATRIX_ROWS; i++) { |
| @@ -141,71 +175,60 @@ void matrix_init(void) { | |||
| 141 | uint8_t matrix_scan(void) | 175 | uint8_t matrix_scan(void) |
| 142 | { | 176 | { |
| 143 | 177 | ||
| 144 | #if DIODE_DIRECTION == COL2ROW | 178 | #if (DIODE_DIRECTION == COL2ROW) |
| 145 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | ||
| 146 | select_row(i); | ||
| 147 | wait_us(30); // without this wait read unstable value. | ||
| 148 | matrix_row_t cols = read_cols(); | ||
| 149 | if (matrix_debouncing[i] != cols) { | ||
| 150 | matrix_debouncing[i] = cols; | ||
| 151 | if (debouncing) { | ||
| 152 | debug("bounce!: "); debug_hex(debouncing); debug("\n"); | ||
| 153 | } | ||
| 154 | debouncing = DEBOUNCING_DELAY; | ||
| 155 | } | ||
| 156 | unselect_rows(); | ||
| 157 | } | ||
| 158 | 179 | ||
| 159 | if (debouncing) { | 180 | // Set row, read cols |
| 160 | if (--debouncing) { | 181 | for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) { |
| 161 | wait_ms(1); | 182 | # if (DEBOUNCING_DELAY > 0) |
| 162 | } else { | 183 | bool matrix_changed = read_cols_on_row(matrix_debouncing, current_row); |
| 163 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | 184 | |
| 164 | matrix[i] = matrix_debouncing[i]; | 185 | if (matrix_changed) { |
| 186 | debouncing = true; | ||
| 187 | debouncing_time = timer_read(); | ||
| 165 | } | 188 | } |
| 166 | } | 189 | |
| 190 | # else | ||
| 191 | read_cols_on_row(matrix, current_row); | ||
| 192 | # endif | ||
| 193 | |||
| 167 | } | 194 | } |
| 168 | #else | 195 | |
| 169 | for (uint8_t i = 0; i < MATRIX_COLS; i++) { | 196 | #elif (DIODE_DIRECTION == ROW2COL) |
| 170 | select_row(i); | 197 | |
| 171 | wait_us(30); // without this wait read unstable value. | 198 | // Set col, read rows |
| 172 | matrix_row_t rows = read_cols(); | 199 | for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { |
| 173 | if (matrix_reversed_debouncing[i] != rows) { | 200 | # if (DEBOUNCING_DELAY > 0) |
| 174 | matrix_reversed_debouncing[i] = rows; | 201 | bool matrix_changed = read_rows_on_col(matrix_debouncing, current_col); |
| 175 | if (debouncing) { | 202 | if (matrix_changed) { |
| 176 | debug("bounce!: "); debug_hex(debouncing); debug("\n"); | 203 | debouncing = true; |
| 204 | debouncing_time = timer_read(); | ||
| 177 | } | 205 | } |
| 178 | debouncing = DEBOUNCING_DELAY; | 206 | # else |
| 179 | } | 207 | read_rows_on_col(matrix, current_col); |
| 180 | unselect_rows(); | 208 | # endif |
| 209 | |||
| 181 | } | 210 | } |
| 182 | 211 | ||
| 183 | if (debouncing) { | 212 | #endif |
| 184 | if (--debouncing) { | 213 | |
| 185 | wait_ms(1); | 214 | # if (DEBOUNCING_DELAY > 0) |
| 186 | } else { | 215 | if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCING_DELAY)) { |
| 187 | for (uint8_t i = 0; i < MATRIX_COLS; i++) { | 216 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { |
| 188 | matrix_reversed[i] = matrix_reversed_debouncing[i]; | 217 | matrix[i] = matrix_debouncing[i]; |
| 189 | } | 218 | } |
| 219 | debouncing = false; | ||
| 190 | } | 220 | } |
| 191 | } | 221 | # endif |
| 192 | for (uint8_t y = 0; y < MATRIX_ROWS; y++) { | ||
| 193 | matrix_row_t row = 0; | ||
| 194 | for (uint8_t x = 0; x < MATRIX_COLS; x++) { | ||
| 195 | row |= ((matrix_reversed[x] & (1<<y)) >> y) << x; | ||
| 196 | } | ||
| 197 | matrix[y] = row; | ||
| 198 | } | ||
| 199 | #endif | ||
| 200 | 222 | ||
| 201 | matrix_scan_quantum(); | 223 | matrix_scan_quantum(); |
| 202 | |||
| 203 | return 1; | 224 | return 1; |
| 204 | } | 225 | } |
| 205 | 226 | ||
| 206 | bool matrix_is_modified(void) | 227 | bool matrix_is_modified(void) |
| 207 | { | 228 | { |
| 229 | #if (DEBOUNCING_DELAY > 0) | ||
| 208 | if (debouncing) return false; | 230 | if (debouncing) return false; |
| 231 | #endif | ||
| 209 | return true; | 232 | return true; |
| 210 | } | 233 | } |
| 211 | 234 | ||
| @@ -218,15 +241,22 @@ bool matrix_is_on(uint8_t row, uint8_t col) | |||
| 218 | inline | 241 | inline |
| 219 | matrix_row_t matrix_get_row(uint8_t row) | 242 | matrix_row_t matrix_get_row(uint8_t row) |
| 220 | { | 243 | { |
| 244 | // Matrix mask lets you disable switches in the returned matrix data. For example, if you have a | ||
| 245 | // switch blocker installed and the switch is always pressed. | ||
| 246 | #ifdef MATRIX_MASKED | ||
| 247 | return matrix[row] & matrix_mask[row]; | ||
| 248 | #else | ||
| 221 | return matrix[row]; | 249 | return matrix[row]; |
| 250 | #endif | ||
| 222 | } | 251 | } |
| 223 | 252 | ||
| 224 | void matrix_print(void) | 253 | void matrix_print(void) |
| 225 | { | 254 | { |
| 226 | print("\nr/c 0123456789ABCDEF\n"); | 255 | print_matrix_header(); |
| 256 | |||
| 227 | for (uint8_t row = 0; row < MATRIX_ROWS; row++) { | 257 | for (uint8_t row = 0; row < MATRIX_ROWS; row++) { |
| 228 | phex(row); print(": "); | 258 | phex(row); print(": "); |
| 229 | pbin_reverse16(matrix_get_row(row)); | 259 | print_matrix_row(row); |
| 230 | print("\n"); | 260 | print("\n"); |
| 231 | } | 261 | } |
| 232 | } | 262 | } |
| @@ -235,63 +265,148 @@ uint8_t matrix_key_count(void) | |||
| 235 | { | 265 | { |
| 236 | uint8_t count = 0; | 266 | uint8_t count = 0; |
| 237 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | 267 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { |
| 238 | count += bitpop16(matrix[i]); | 268 | count += matrix_bitpop(i); |
| 239 | } | 269 | } |
| 240 | return count; | 270 | return count; |
| 241 | } | 271 | } |
| 242 | 272 | ||
| 273 | |||
| 274 | |||
| 275 | #if (DIODE_DIRECTION == COL2ROW) | ||
| 276 | |||
| 243 | static void init_cols(void) | 277 | static void init_cols(void) |
| 244 | { | 278 | { |
| 245 | #if DIODE_DIRECTION == COL2ROW | 279 | for(uint8_t x = 0; x < MATRIX_COLS; x++) { |
| 246 | for(int x = 0; x < MATRIX_COLS; x++) { | 280 | uint8_t pin = col_pins[x]; |
| 247 | int pin = col_pins[x]; | 281 | _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN |
| 248 | #else | 282 | _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI |
| 249 | for(int x = 0; x < MATRIX_ROWS; x++) { | ||
| 250 | int pin = row_pins[x]; | ||
| 251 | #endif | ||
| 252 | _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); | ||
| 253 | _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); | ||
| 254 | } | 283 | } |
| 255 | } | 284 | } |
| 256 | 285 | ||
| 257 | static matrix_row_t read_cols(void) | 286 | static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) |
| 258 | { | 287 | { |
| 259 | matrix_row_t result = 0; | 288 | // Store last value of row prior to reading |
| 289 | matrix_row_t last_row_value = current_matrix[current_row]; | ||
| 260 | 290 | ||
| 261 | #if DIODE_DIRECTION == COL2ROW | 291 | // Clear data in matrix row |
| 262 | for(int x = 0; x < MATRIX_COLS; x++) { | 292 | current_matrix[current_row] = 0; |
| 263 | int pin = col_pins[x]; | 293 | |
| 264 | #else | 294 | // Select row and wait for row selecton to stabilize |
| 265 | for(int x = 0; x < MATRIX_ROWS; x++) { | 295 | select_row(current_row); |
| 266 | int pin = row_pins[x]; | 296 | wait_us(30); |
| 267 | #endif | 297 | |
| 268 | result |= (_SFR_IO8(pin >> 4) & _BV(pin & 0xF)) ? 0 : (SHIFTER << x); | 298 | // For each col... |
| 299 | for(uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { | ||
| 300 | |||
| 301 | // Select the col pin to read (active low) | ||
| 302 | uint8_t pin = col_pins[col_index]; | ||
| 303 | uint8_t pin_state = (_SFR_IO8(pin >> 4) & _BV(pin & 0xF)); | ||
| 304 | |||
| 305 | // Populate the matrix row with the state of the col pin | ||
| 306 | current_matrix[current_row] |= pin_state ? 0 : (ROW_SHIFTER << col_index); | ||
| 269 | } | 307 | } |
| 270 | return result; | 308 | |
| 309 | // Unselect row | ||
| 310 | unselect_row(current_row); | ||
| 311 | |||
| 312 | return (last_row_value != current_matrix[current_row]); | ||
| 313 | } | ||
| 314 | |||
| 315 | static void select_row(uint8_t row) | ||
| 316 | { | ||
| 317 | uint8_t pin = row_pins[row]; | ||
| 318 | _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT | ||
| 319 | _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW | ||
| 320 | } | ||
| 321 | |||
| 322 | static void unselect_row(uint8_t row) | ||
| 323 | { | ||
| 324 | uint8_t pin = row_pins[row]; | ||
| 325 | _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN | ||
| 326 | _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI | ||
| 271 | } | 327 | } |
| 272 | 328 | ||
| 273 | static void unselect_rows(void) | 329 | static void unselect_rows(void) |
| 274 | { | 330 | { |
| 275 | #if DIODE_DIRECTION == COL2ROW | 331 | for(uint8_t x = 0; x < MATRIX_ROWS; x++) { |
| 276 | for(int x = 0; x < MATRIX_ROWS; x++) { | 332 | uint8_t pin = row_pins[x]; |
| 277 | int pin = row_pins[x]; | 333 | _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN |
| 278 | #else | 334 | _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI |
| 279 | for(int x = 0; x < MATRIX_COLS; x++) { | ||
| 280 | int pin = col_pins[x]; | ||
| 281 | #endif | ||
| 282 | _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); | ||
| 283 | _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); | ||
| 284 | } | 335 | } |
| 285 | } | 336 | } |
| 286 | 337 | ||
| 287 | static void select_row(uint8_t row) | 338 | #elif (DIODE_DIRECTION == ROW2COL) |
| 339 | |||
| 340 | static void init_rows(void) | ||
| 288 | { | 341 | { |
| 342 | for(uint8_t x = 0; x < MATRIX_ROWS; x++) { | ||
| 343 | uint8_t pin = row_pins[x]; | ||
| 344 | _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN | ||
| 345 | _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI | ||
| 346 | } | ||
| 347 | } | ||
| 289 | 348 | ||
| 290 | #if DIODE_DIRECTION == COL2ROW | 349 | static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) |
| 291 | int pin = row_pins[row]; | 350 | { |
| 292 | #else | 351 | bool matrix_changed = false; |
| 293 | int pin = col_pins[row]; | 352 | |
| 294 | #endif | 353 | // Select col and wait for col selecton to stabilize |
| 295 | _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); | 354 | select_col(current_col); |
| 296 | _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); | 355 | wait_us(30); |
| 356 | |||
| 357 | // For each row... | ||
| 358 | for(uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) | ||
| 359 | { | ||
| 360 | |||
| 361 | // Store last value of row prior to reading | ||
| 362 | matrix_row_t last_row_value = current_matrix[row_index]; | ||
| 363 | |||
| 364 | // Check row pin state | ||
| 365 | if ((_SFR_IO8(row_pins[row_index] >> 4) & _BV(row_pins[row_index] & 0xF)) == 0) | ||
| 366 | { | ||
| 367 | // Pin LO, set col bit | ||
| 368 | current_matrix[row_index] |= (ROW_SHIFTER << current_col); | ||
| 369 | } | ||
| 370 | else | ||
| 371 | { | ||
| 372 | // Pin HI, clear col bit | ||
| 373 | current_matrix[row_index] &= ~(ROW_SHIFTER << current_col); | ||
| 374 | } | ||
| 375 | |||
| 376 | // Determine if the matrix changed state | ||
| 377 | if ((last_row_value != current_matrix[row_index]) && !(matrix_changed)) | ||
| 378 | { | ||
| 379 | matrix_changed = true; | ||
| 380 | } | ||
| 381 | } | ||
| 382 | |||
| 383 | // Unselect col | ||
| 384 | unselect_col(current_col); | ||
| 385 | |||
| 386 | return matrix_changed; | ||
| 297 | } | 387 | } |
| 388 | |||
| 389 | static void select_col(uint8_t col) | ||
| 390 | { | ||
| 391 | uint8_t pin = col_pins[col]; | ||
| 392 | _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT | ||
| 393 | _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW | ||
| 394 | } | ||
| 395 | |||
| 396 | static void unselect_col(uint8_t col) | ||
| 397 | { | ||
| 398 | uint8_t pin = col_pins[col]; | ||
| 399 | _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN | ||
| 400 | _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI | ||
| 401 | } | ||
| 402 | |||
| 403 | static void unselect_cols(void) | ||
| 404 | { | ||
| 405 | for(uint8_t x = 0; x < MATRIX_COLS; x++) { | ||
| 406 | uint8_t pin = col_pins[x]; | ||
| 407 | _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN | ||
| 408 | _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI | ||
| 409 | } | ||
| 410 | } | ||
| 411 | |||
| 412 | #endif | ||
