qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

matrix.c (3588B)


      1 /*
      2  * Copyright 2020 Richard Titmuss (richard.titmuss@gmail.com)
      3  * Copyright 2012-2018 Jun Wako, Jack Humbert, Yiancar
      4  *
      5  * 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
      7  * the Free Software Foundation, either version 2 of the License, or
      8  * (at your option) any later version.
      9  *
     10  * This program is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  * GNU General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU General Public License
     16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
     17  */
     18 
     19 #include "matrix.h"
     20 #include "mcp23018.h"
     21 
     22 #define SPLIT_MATRIX_COLS (MATRIX_COLS / 2)
     23 #define SECONDARY_ROW_OFFSET (MATRIX_ROWS / 2)
     24 
     25 typedef uint16_t mcp23018_pin_t;
     26 
     27 static const pin_t          row_pins[MATRIX_ROWS]                 = MATRIX_ROW_PINS;
     28 static const pin_t          col_pins[SPLIT_MATRIX_COLS]           = MATRIX_COL_PINS;
     29 static const mcp23018_pin_t secondary_row_pins[MATRIX_ROWS]       = SECONDARY_ROW_PINS;
     30 static const mcp23018_pin_t secondary_col_pins[SPLIT_MATRIX_COLS] = SECONDARY_COL_PINS;
     31 
     32 static void select_row(uint8_t row) {
     33     gpio_set_pin_output(row_pins[row]);
     34     gpio_write_pin_low(row_pins[row]);
     35 }
     36 
     37 static void unselect_row(uint8_t row) { gpio_set_pin_input_high(row_pins[row]); }
     38 
     39 static void unselect_rows(void) {
     40     for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
     41         gpio_set_pin_input_high(row_pins[x]);
     42     }
     43 }
     44 
     45 static void select_secondary_row(uint8_t row) {
     46     uint8_t gpioa = 0xFF & ~secondary_row_pins[row];
     47     mcp23018_writeReg(GPIOA, &gpioa, 1);
     48 }
     49 
     50 static void init_pins(void) {
     51     unselect_rows();
     52     for (uint8_t x = 0; x < SPLIT_MATRIX_COLS; x++) {
     53         gpio_set_pin_input_high(col_pins[x]);
     54     }
     55 }
     56 
     57 static matrix_row_t read_cols(void) {
     58     matrix_row_t state = 0;
     59 
     60     // For each col...
     61     for (uint8_t col_index = 0; col_index < SPLIT_MATRIX_COLS; col_index++) {
     62         // Select the col pin to read (active low)
     63         uint8_t pin_state = gpio_read_pin(col_pins[col_index]);
     64 
     65         // Populate the matrix row with the state of the col pin
     66         state |= pin_state ? 0 : (MATRIX_ROW_SHIFTER << col_index);
     67     }
     68 
     69     return state;
     70 }
     71 
     72 static matrix_row_t read_secondary_cols(void) {
     73     matrix_row_t state = 0;
     74 
     75     uint8_t mcp23018_pin_state[2];
     76     if (mcp23018_readReg(GPIOA, mcp23018_pin_state, 2)) {
     77         return 0;
     78     }
     79 
     80     uint16_t pins = mcp23018_pin_state[0] | (mcp23018_pin_state[1] << 8);
     81 
     82     for (uint8_t col_index = 0; col_index < SPLIT_MATRIX_COLS; col_index++) {
     83         uint16_t pin_state = pins & (secondary_col_pins[col_index]);
     84         state |= pin_state ? 0 : (MATRIX_ROW_SHIFTER << col_index);
     85     }
     86 
     87     return state;
     88 }
     89 
     90 static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
     91     matrix_row_t last_row_value = current_matrix[current_row];
     92 
     93     select_row(current_row);
     94     select_secondary_row(current_row);
     95 
     96     current_matrix[current_row] = read_cols() | (read_secondary_cols() << 6);
     97 
     98     unselect_row(current_row);
     99 
    100     return (last_row_value != current_matrix[current_row]);
    101 }
    102 
    103 void matrix_init_custom(void) { init_pins(); }
    104 
    105 bool matrix_scan_custom(matrix_row_t current_matrix[]) {
    106     bool changed = false;
    107 
    108     for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
    109         changed |= read_cols_on_row(current_matrix, current_row);
    110     }
    111 
    112     return changed;
    113 }