diff options
Diffstat (limited to 'quantum/matrix.c')
| -rw-r--r-- | quantum/matrix.c | 330 | 
1 files changed, 200 insertions, 130 deletions
| diff --git a/quantum/matrix.c b/quantum/matrix.c index 412662a794..3174e07390 100644 --- a/quantum/matrix.c +++ b/quantum/matrix.c @@ -17,211 +17,281 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  */  #include <stdint.h>  #include <stdbool.h> +#if defined(__AVR__)  #include <avr/io.h> +#endif  #include "wait.h"  #include "print.h"  #include "debug.h"  #include "util.h"  #include "matrix.h" -#ifdef MATRIX_HAS_GHOST -#   error "The universal matrix.c file cannot be used for this keyboard." -#endif +/* Set 0 if debouncing isn't needed */  #ifndef DEBOUNCING_DELAY  #   define DEBOUNCING_DELAY 5  #endif +static uint8_t debouncing = DEBOUNCING_DELAY; -static const io_pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; -static const io_pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; -/* matrix state */ -#if DIODE_DIRECTION == COL2ROW +static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; +static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; + +/* matrix state(1:on, 0:off) */  static matrix_row_t matrix[MATRIX_ROWS]; -#else -static matrix_col_t matrix[MATRIX_COLS]; +static matrix_row_t matrix_debouncing[MATRIX_ROWS]; + +#if DIODE_DIRECTION == ROW2COL +    static matrix_row_t matrix_reversed[MATRIX_COLS]; +    static matrix_row_t matrix_reversed_debouncing[MATRIX_COLS];  #endif -static int8_t debouncing_delay = -1; -#if DIODE_DIRECTION == COL2ROW -static void toggle_row(uint8_t row); -static matrix_row_t read_cols(void); +#if MATRIX_COLS > 16 +    #define SHIFTER 1UL  #else -static void toggle_col(uint8_t col); -static matrix_col_t read_rows(void); +    #define SHIFTER 1  #endif +static matrix_row_t read_cols(void); +static void init_cols(void); +static void unselect_rows(void); +static void select_row(uint8_t row); +  __attribute__ ((weak))  void matrix_init_quantum(void) { +    matrix_init_kb();  }  __attribute__ ((weak))  void matrix_scan_quantum(void) { +    matrix_scan_kb(); +} + +__attribute__ ((weak)) +void matrix_init_kb(void) { +    matrix_init_user(); +} + +__attribute__ ((weak)) +void matrix_scan_kb(void) { +    matrix_scan_user(); +} + +__attribute__ ((weak)) +void matrix_init_user(void) { +} + +__attribute__ ((weak)) +void matrix_scan_user(void) {  } +inline  uint8_t matrix_rows(void) {      return MATRIX_ROWS;  } +inline  uint8_t matrix_cols(void) {      return MATRIX_COLS;  } +// void matrix_power_up(void) { +// #if DIODE_DIRECTION == COL2ROW +//     for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { +//         /* DDRxn */ +//         _SFR_IO8((row_pins[r] >> 4) + 1) |= _BV(row_pins[r] & 0xF); +//         toggle_row(r); +//     } +//     for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { +//         /* PORTxn */ +//         _SFR_IO8((col_pins[c] >> 4) + 2) |= _BV(col_pins[c] & 0xF); +//     } +// #else +//     for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { +//         /* DDRxn */ +//         _SFR_IO8((col_pins[c] >> 4) + 1) |= _BV(col_pins[c] & 0xF); +//         toggle_col(c); +//     } +//     for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { +//         /* PORTxn */ +//         _SFR_IO8((row_pins[r] >> 4) + 2) |= _BV(row_pins[r] & 0xF); +//     } +// #endif +// } +  void matrix_init(void) { -    /* frees PORTF by setting the JTD bit twice within four cycles */ +    // To use PORTF disable JTAG with writing JTD bit twice within four cycles.      #ifdef __AVR_ATmega32U4__          MCUCR |= _BV(JTD);          MCUCR |= _BV(JTD);      #endif -    /* initializes the I/O pins */ -#if DIODE_DIRECTION == COL2ROW -    for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { -        /* DDRxn */ -        _SFR_IO8(row_pins[r].input_addr + 1) |= _BV(row_pins[r].bit); -        toggle_row(r); -    } -    for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { -        /* PORTxn */ -        _SFR_IO8(col_pins[c].input_addr + 2) |= _BV(col_pins[c].bit); -    } -#else -    for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { -        /* DDRxn */ -        _SFR_IO8(col_pins[c].input_addr + 1) |= _BV(col_pins[c].bit); -        toggle_col(c); -    } -    for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { -        /* PORTxn */ -        _SFR_IO8(row_pins[r].input_addr + 2) |= _BV(row_pins[r].bit); + +    // initialize row and col +    unselect_rows(); +    init_cols(); + +    // initialize matrix state: all keys off +    for (uint8_t i=0; i < MATRIX_ROWS; i++) { +        matrix[i] = 0; +        matrix_debouncing[i] = 0;      } -#endif +      matrix_init_quantum();  } +uint8_t matrix_scan(void) +{ +  #if DIODE_DIRECTION == COL2ROW -uint8_t matrix_scan(void) { -    static matrix_row_t debouncing_matrix[MATRIX_ROWS]; -    for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { -        toggle_row(r); -        matrix_row_t state = read_cols(); -        if (debouncing_matrix[r] != state) { -            debouncing_matrix[r] = state; -            debouncing_delay = DEBOUNCING_DELAY; -        } -        toggle_row(r); -    } -    if (debouncing_delay >= 0) { -        dprintf("Debouncing delay remaining: %X\n", debouncing_delay); -        --debouncing_delay; -        if (debouncing_delay >= 0) { -            wait_ms(1); -        } -        else { -            for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { -                matrix[r] = debouncing_matrix[r]; +    for (uint8_t i = 0; i < MATRIX_ROWS; i++) { +        select_row(i); +        wait_us(30);  // without this wait read unstable value. +        matrix_row_t cols = read_cols(); +        if (matrix_debouncing[i] != cols) { +            matrix_debouncing[i] = cols; +            if (debouncing) { +                debug("bounce!: "); debug_hex(debouncing); debug("\n");              } +            debouncing = DEBOUNCING_DELAY;          } +        unselect_rows();      } -    matrix_scan_quantum(); -    return 1; -} - -static void toggle_row(uint8_t row) { -    /* PINxn */ -    _SFR_IO8(row_pins[row].input_addr) = _BV(row_pins[row].bit); -} -static matrix_row_t read_cols(void) { -    matrix_row_t state = 0; -    for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { -        /* PINxn */ -        if (!(_SFR_IO8(col_pins[c].input_addr) & _BV(col_pins[c].bit))) { -            state |= (matrix_row_t)1 << c; +    if (debouncing) { +        if (--debouncing) { +            wait_ms(1); +        } else { +            for (uint8_t i = 0; i < MATRIX_ROWS; i++) { +                matrix[i] = matrix_debouncing[i]; +            }          }      } -    return state; -} - -matrix_row_t matrix_get_row(uint8_t row) { -    return matrix[row]; -} -  #else -uint8_t matrix_scan(void) { -    static matrix_col_t debouncing_matrix[MATRIX_COLS]; -    for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { -        toggle_col(c); -        matrix_col_t state = read_rows(); -        if (debouncing_matrix[c] != state) { -            debouncing_matrix[c] = state; -            debouncing_delay = DEBOUNCING_DELAY; +    for (uint8_t i = 0; i < MATRIX_COLS; i++) { +        select_row(i); +        wait_us(30);  // without this wait read unstable value. +        matrix_row_t rows = read_cols(); +        if (matrix_reversed_debouncing[i] != rows) { +            matrix_reversed_debouncing[i] = rows; +            if (debouncing) { +                debug("bounce!: "); debug_hex(debouncing); debug("\n"); +            } +            debouncing = DEBOUNCING_DELAY;          } -        toggle_col(c); +        unselect_rows();      } -    if (debouncing_delay >= 0) { -        dprintf("Debouncing delay remaining: %X\n", debouncing_delay); -        --debouncing_delay; -        if (debouncing_delay >= 0) { + +    if (debouncing) { +        if (--debouncing) {              wait_ms(1); -        } -        else { -            for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { -                matrix[c] = debouncing_matrix[c]; +        } else { +            for (uint8_t i = 0; i < MATRIX_COLS; i++) { +                matrix_reversed[i] = matrix_reversed_debouncing[i];              }          }      } +    for (uint8_t y = 0; y < MATRIX_ROWS; y++) { +        matrix_row_t row = 0; +        for (uint8_t x = 0; x < MATRIX_COLS; x++) { +            row |= ((matrix_reversed[x] & (1<<y)) >> y) << x; +        } +        matrix[y] = row; +    } +#endif +      matrix_scan_quantum(); +      return 1;  } -static void toggle_col(uint8_t col) { -    /* PINxn */ -    _SFR_IO8(col_pins[col].input_addr) = _BV(col_pins[col].bit); +bool matrix_is_modified(void) +{ +    if (debouncing) return false; +    return true; +} + +inline +bool matrix_is_on(uint8_t row, uint8_t col) +{ +    return (matrix[row] & ((matrix_row_t)1<col));  } -static matrix_col_t read_rows(void) { -    matrix_col_t state = 0; -    for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { -        /* PINxn */ -        if (!(_SFR_IO8(row_pins[r].input_addr) & _BV(row_pins[r].bit))) { -            state |= (matrix_col_t)1 << r; -        } +inline +matrix_row_t matrix_get_row(uint8_t row) +{ +    return matrix[row]; +} + +void matrix_print(void) +{ +    print("\nr/c 0123456789ABCDEF\n"); +    for (uint8_t row = 0; row < MATRIX_ROWS; row++) { +        phex(row); print(": "); +        pbin_reverse16(matrix_get_row(row)); +        print("\n");      } -    return state;  } -matrix_row_t matrix_get_row(uint8_t row) { -    matrix_row_t state = 0; -    matrix_col_t mask = (matrix_col_t)1 << row; -    for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { -        if (matrix[c] & mask) { -            state |= (matrix_row_t)1 << c; -        } +uint8_t matrix_key_count(void) +{ +    uint8_t count = 0; +    for (uint8_t i = 0; i < MATRIX_ROWS; i++) { +        count += bitpop16(matrix[i]);      } -    return state; +    return count;  } +static void init_cols(void) +{ +#if DIODE_DIRECTION == COL2ROW +    for(int x = 0; x < MATRIX_COLS; x++) { +        int pin = col_pins[x]; +#else +    for(int x = 0; x < MATRIX_ROWS; x++) { +        int pin = row_pins[x];  #endif - -bool matrix_is_modified(void) { -    if (debouncing_delay >= 0) return false; -    return true; +        _SFR_IO8((pin >> 4) + 1) &=  ~_BV(pin & 0xF); +        _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); +    }  } -bool matrix_is_on(uint8_t row, uint8_t col) { -    return matrix_get_row(row) & (matrix_row_t)1 << col; -} +static matrix_row_t read_cols(void) +{ +    matrix_row_t result = 0; -void matrix_print(void) { -    dprintln("Human-readable matrix state:"); -    for (uint8_t r = 0; r < MATRIX_ROWS; r++) { -        dprintf("State of row %X: %016b\n", r, bitrev16(matrix_get_row(r))); +#if DIODE_DIRECTION == COL2ROW +    for(int x = 0; x < MATRIX_COLS; x++) {      +        int pin = col_pins[x]; +#else +    for(int x = 0; x < MATRIX_ROWS; x++) { +        int pin = row_pins[x]; +#endif +        result |= (_SFR_IO8(pin >> 4) & _BV(pin & 0xF)) ? 0 : (SHIFTER << x);      } +    return result;  } -uint8_t matrix_key_count(void) { -    uint8_t count = 0; -    for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { -        count += bitpop16(matrix_get_row(r)); +static void unselect_rows(void) +{ +#if DIODE_DIRECTION == COL2ROW +    for(int x = 0; x < MATRIX_ROWS; x++) {  +        int pin = row_pins[x]; +#else +    for(int x = 0; x < MATRIX_COLS; x++) {  +        int pin = col_pins[x]; +#endif +        _SFR_IO8((pin >> 4) + 1) &=  ~_BV(pin & 0xF); +        _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF);      } -    return count; +} + +static void select_row(uint8_t row) +{ + +#if DIODE_DIRECTION == COL2ROW +    int pin = row_pins[row]; +#else +    int pin = col_pins[row]; +#endif +    _SFR_IO8((pin >> 4) + 1) |=  _BV(pin & 0xF); +    _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF);  } | 
