/* Copyright 2016 Kai Ryu This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* * scan matrix */ #include #include #include #include #include "debug.h" #include "util.h" #include "matrix.h" #include "expander.h" #include "keymap_in_eeprom.h" #include "timer.h" #ifndef DEBOUNCE # define DEBOUNCE 5 #endif /* matrix state(1:on, 0:off) */ static matrix_row_t matrix[MATRIX_ROWS]; #define IMPROVED_DEBOUNCE 1 #if IMPROVED_DEBOUNCE #define DEBOUNCE_MASK ((1 << DEBOUNCE) - 1) static uint8_t matrix_current_row; static uint16_t matrix_row_timestamp[MATRIX_ROWS]; static uint8_t matrix_debouncing[MATRIX_ROWS][MATRIX_COLS]; #else static uint8_t debouncing = DEBOUNCE; static matrix_row_t matrix_debouncing[MATRIX_ROWS]; static matrix_row_t read_row(void); #endif static uint16_t matrix_scan_timestamp; static void read_cols(void); static uint8_t get_col(uint8_t col); static void init_cols(void); static void unselect_rows(void); static void select_row(uint8_t row); inline uint8_t matrix_rows(void) { return MATRIX_ROWS; } inline uint8_t matrix_cols(void) { return MATRIX_COLS; } void matrix_init(void) { // disable JTAG MCUCR = (1<= 1000) { dprintf("======== 1s task ========\n"); dprintf("Scan: %u\n", matrix_scan_timestamp); matrix_scan_timestamp = timer_read(); expander_scan(); dprintf("=========================\n"); } #if IMPROVED_DEBOUNCE uint16_t elapsed = timer_elapsed(matrix_row_timestamp[matrix_current_row]); if (elapsed >= 1) { matrix_row_timestamp[matrix_current_row] = timer_read(); select_row(matrix_current_row); _delay_us(30); read_cols(); for (uint8_t i = 0; i < matrix_cols(); i++) { uint8_t *debounce = &matrix_debouncing[matrix_current_row][i]; uint8_t col = get_col(i); uint8_t count = elapsed; do { *debounce <<= 1; *debounce |= col; } while (--count); matrix_row_t *row = &matrix[matrix_current_row]; matrix_row_t mask = ((matrix_row_t)1 << i); switch (*debounce & DEBOUNCE_MASK) { case DEBOUNCE_MASK: #if DEBOUNCE > 1 case (DEBOUNCE_MASK >> 1): #if DEBOUNCE > 2 case (DEBOUNCE_MASK >> 2): #if DEBOUNCE > 3 case (DEBOUNCE_MASK >> 3): #if DEBOUNCE > 4 case (DEBOUNCE_MASK >> 4): #if DEBOUNCE > 5 case (DEBOUNCE_MASK >> 5): #if DEBOUNCE > 6 case (DEBOUNCE_MASK >> 6): #if DEBOUNCE > 7 case (DEBOUNCE_MASK >> 7): #if DEBOUNCE > 8 case (DEBOUNCE_MASK >> 8): #if DEBOUNCE > 9 case (DEBOUNCE_MASK >> 9): #if DEBOUNCE > 10 case (DEBOUNCE_MASK >> 10): #endif #endif #endif #endif #endif #endif #endif #endif #endif #endif if ((*row & mask) == 0) { *row |= mask; } break; #if DEBOUNCE > 1 case ((DEBOUNCE_MASK << 1) & DEBOUNCE_MASK): #if DEBOUNCE > 2 case ((DEBOUNCE_MASK << 2) & DEBOUNCE_MASK): #if DEBOUNCE > 3 case ((DEBOUNCE_MASK << 3) & DEBOUNCE_MASK): #if DEBOUNCE > 4 case ((DEBOUNCE_MASK << 4) & DEBOUNCE_MASK): #if DEBOUNCE > 5 case ((DEBOUNCE_MASK << 5) & DEBOUNCE_MASK): #if DEBOUNCE > 6 case ((DEBOUNCE_MASK << 6) & DEBOUNCE_MASK): #if DEBOUNCE > 7 case ((DEBOUNCE_MASK << 7) & DEBOUNCE_MASK): #if DEBOUNCE > 8 case ((DEBOUNCE_MASK << 8) & DEBOUNCE_MASK): #if DEBOUNCE > 9 case ((DEBOUNCE_MASK << 9) & DEBOUNCE_MASK): #if DEBOUNCE > 10 case ((DEBOUNCE_MASK << 10) & DEBOUNCE_MASK): #endif #endif #endif #endif #endif #endif #endif #endif #endif #endif break; case 0: if ((*row & mask) != 0) { *row &= ~mask; } break; default: debug("bounce!: "); debug_bin8(*debounce & DEBOUNCE_MASK); debug("\n"); break; } } unselect_rows(); } matrix_current_row++; if (matrix_current_row >= matrix_rows()) { matrix_current_row = 0; } #else for (uint8_t i = 0; i < matrix_rows(); i++) { select_row(i); _delay_us(30); // without this wait read unstable value. matrix_row_t cols = read_row(); if (matrix_debouncing[i] != cols) { matrix_debouncing[i] = cols; if (debouncing) { debug("bounce!: "); debug_hex(debouncing); debug("\n"); } debouncing = DEBOUNCE; } unselect_rows(); } if (debouncing) { if (--debouncing) { _delay_ms(1); } else { for (uint8_t i = 0; i < matrix_rows(); i++) { matrix[i] = matrix_debouncing[i]; } } } #endif return 1; } #if IMPROVED_DEBOUNCE #else bool matrix_is_modified(void) { if (debouncing) return false; return true; } #endif inline bool matrix_is_on(uint8_t row, uint8_t col) { return (matrix[row] & ((matrix_row_t)1<