qmk_firmware

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

matrix.c (4439B)


      1 /*
      2 Copyright 2012-2018 Jun Wako, Jack Humbert, Yiancar
      3 
      4 This program is free software: you can redistribute it and/or modify
      5 it under the terms of the GNU General Public License as published by
      6 the Free Software Foundation, either version 2 of the License, or
      7 (at your option) any later version.
      8 
      9 This program is distributed in the hope that it will be useful,
     10 but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12 GNU General Public License for more details.
     13 
     14 You should have received a copy of the GNU General Public License
     15 along with this program.  If not, see <http://www.gnu.org/licenses/>.
     16 */
     17 #include "matrix.h"
     18 
     19 #if (MATRIX_COLS <= 8)
     20 #    define ROW_SHIFTER ((uint8_t)1)
     21 #elif (MATRIX_COLS <= 16)
     22 #    define ROW_SHIFTER ((uint16_t)1)
     23 #elif (MATRIX_COLS <= 32)
     24 #    define ROW_SHIFTER  ((uint32_t)1)
     25 #endif
     26 
     27 static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
     28 static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
     29 
     30 static void select_row(uint8_t row) {
     31     gpio_set_pin_output(row_pins[row]);
     32     gpio_write_pin_low(row_pins[row]);
     33 }
     34 
     35 static void unselect_row(uint8_t row) {
     36     gpio_set_pin_input_high(row_pins[row]);
     37 }
     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_col(uint8_t col) {
     46     gpio_set_pin_output(col_pins[col]);
     47     gpio_write_pin_low(col_pins[col]);
     48 }
     49 
     50 static void unselect_col(uint8_t col) {
     51     gpio_set_pin_input_high(col_pins[col]);
     52 }
     53 
     54 static void unselect_cols(void) {
     55     for (uint8_t x = 0; x < MATRIX_COLS; x++) {
     56         gpio_set_pin_input_high(col_pins[x]);
     57     }
     58 }
     59 
     60 static void init_pins(void) {
     61     unselect_rows();
     62     unselect_cols();
     63 
     64     for (uint8_t x = 0; x < MATRIX_COLS; x++) {
     65         gpio_set_pin_input_high(col_pins[x]);
     66     }
     67 
     68     for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
     69         gpio_set_pin_input_high(row_pins[x]);
     70     }
     71 }
     72 
     73 static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
     74     // Store last value of row prior to reading
     75     matrix_row_t last_row_value = current_matrix[current_row];
     76 
     77     // Clear data in matrix row
     78     current_matrix[current_row] = 0;
     79 
     80     // Select row and wait for row selecton to stabilize
     81     select_row(current_row);
     82     matrix_io_delay();
     83 
     84     // For each col...
     85     for(uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
     86 
     87         // Select the col pin to read (active low)
     88         uint8_t pin_state = gpio_read_pin(col_pins[col_index]);
     89 
     90         // Populate the matrix row with the state of the col pin
     91         current_matrix[current_row] |=  pin_state ? 0 : (ROW_SHIFTER << col_index);
     92     }
     93 
     94     // Unselect row
     95     unselect_row(current_row);
     96 
     97     return (last_row_value != current_matrix[current_row]);
     98 }
     99 
    100 static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {
    101     bool matrix_changed = false;
    102 
    103     // Select col and wait for col selecton to stabilize
    104     select_col(current_col);
    105     matrix_io_delay();
    106 
    107     // For each row...
    108     for(uint8_t row_index = 0; row_index < MATRIX_ROWS / 2; row_index++) {
    109         uint8_t tmp = row_index + MATRIX_ROWS / 2;
    110         // Store last value of row prior to reading
    111         matrix_row_t last_row_value = current_matrix[tmp];
    112 
    113         // Check row pin state
    114         if (gpio_read_pin(row_pins[row_index]) == 0) {
    115             // Pin LO, set col bit
    116             current_matrix[tmp] |= (ROW_SHIFTER << current_col);
    117         } else {
    118             // Pin HI, clear col bit
    119             current_matrix[tmp] &= ~(ROW_SHIFTER << current_col);
    120         }
    121 
    122         // Determine if the matrix changed state
    123         if ((last_row_value != current_matrix[tmp]) && !(matrix_changed)) {
    124             matrix_changed = true;
    125         }
    126     }
    127 
    128     // Unselect col
    129     unselect_col(current_col);
    130 
    131     return matrix_changed;
    132 }
    133 
    134 void matrix_init_custom(void) {
    135     // initialize key pins
    136     init_pins();
    137 }
    138 
    139 bool matrix_scan_custom(matrix_row_t current_matrix[]) {
    140     bool changed = false;
    141 
    142     // Set row, read cols
    143     for (uint8_t current_row = 0; current_row < MATRIX_ROWS / 2; current_row++) {
    144         changed |= read_cols_on_row(current_matrix, current_row);
    145     }
    146 
    147     // Set col, read rows
    148     for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
    149         changed |= read_rows_on_col(current_matrix, current_col);
    150     }
    151 
    152     return changed;
    153 }