qmk_firmware

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

matrix.c (4468B)


      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 #include "atomic_util.h"
     19 
     20 static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
     21 static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
     22 
     23 static inline void gpio_atomic_set_pin_output_low(pin_t pin) {
     24     ATOMIC_BLOCK_FORCEON {
     25         gpio_set_pin_output(pin);
     26         gpio_write_pin_low(pin);
     27     }
     28 }
     29 
     30 static inline void gpio_atomic_set_pin_input_high(pin_t pin) {
     31     ATOMIC_BLOCK_FORCEON { gpio_set_pin_input_high(pin); }
     32 }
     33 
     34 static void select_row(uint8_t row) {
     35     gpio_atomic_set_pin_output_low(row_pins[row]);
     36 }
     37 
     38 static void unselect_row(uint8_t row) {
     39     gpio_atomic_set_pin_input_high(row_pins[row]);
     40 }
     41 
     42 static void unselect_rows(void) {
     43     for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
     44         gpio_atomic_set_pin_input_high(row_pins[x]);
     45     }
     46 }
     47 
     48 static void select_col(uint8_t col) {
     49     gpio_atomic_set_pin_output_low(col_pins[col]);
     50 }
     51 
     52 static void unselect_col(uint8_t col) {
     53     gpio_atomic_set_pin_input_high(col_pins[col]);
     54 }
     55 
     56 static void unselect_cols(void) {
     57     for (uint8_t x = 0; x < MATRIX_COLS; x++) {
     58         gpio_atomic_set_pin_input_high(col_pins[x]);
     59     }
     60 }
     61 
     62 static void init_pins(void) {
     63     unselect_rows();
     64     for (uint8_t x = 0; x < MATRIX_COLS; x++) {
     65         gpio_atomic_set_pin_input_high(col_pins[x]);
     66     }
     67     unselect_cols();
     68     for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
     69         gpio_atomic_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     // Select row
     78     select_row(current_row);
     79     matrix_io_delay();
     80 
     81     // For each col...
     82     for (uint8_t col_index = 0; col_index < MATRIX_COLS / 2; col_index++) {
     83         // Check row pin state
     84         if (gpio_read_pin(col_pins[col_index])) {
     85             // Pin HI, clear col bit
     86             current_matrix[current_row] &= ~(MATRIX_ROW_SHIFTER << col_index);
     87         } else {
     88             // Pin LO, set col bit
     89             current_matrix[current_row] |= (MATRIX_ROW_SHIFTER << col_index);
     90         }
     91     }
     92 
     93     // Unselect row
     94     unselect_row(current_row);
     95 
     96     return (last_row_value != current_matrix[current_row]);
     97 }
     98 
     99 static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {
    100     bool matrix_changed = false;
    101 
    102     // Select col
    103     select_col(current_col);
    104     matrix_io_delay();
    105 
    106     // For each row...
    107     for (uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) {
    108         // Store last value of row prior to reading
    109         matrix_row_t last_row_value = current_matrix[row_index];
    110 
    111         // Check row pin state
    112         if (gpio_read_pin(row_pins[row_index])) {
    113             // Pin HI, clear col bit
    114             current_matrix[row_index] &= ~(MATRIX_ROW_SHIFTER << ( current_col + MATRIX_COLS/2));
    115         } else {
    116             // Pin LO, set col bit
    117             current_matrix[row_index] |= (MATRIX_ROW_SHIFTER << ( current_col + MATRIX_COLS/2));
    118         }
    119 
    120         // Determine if the matrix changed state
    121         if ((last_row_value != current_matrix[row_index]) && !(matrix_changed)) {
    122             matrix_changed = true;
    123         }
    124     }
    125 
    126     // Unselect col
    127     unselect_col(current_col);
    128 
    129     return matrix_changed;
    130 }
    131 
    132 void matrix_init_custom(void) {
    133     init_pins();
    134 }
    135 
    136 bool matrix_scan_custom(matrix_row_t current_matrix[]) {
    137     bool changed = false;
    138 
    139     // Set row, read cols
    140     for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
    141         changed |= read_cols_on_row(current_matrix, current_row);
    142     }
    143     // Set col, read rows
    144     for (uint8_t current_col = 0; current_col < (MATRIX_COLS/2); current_col++) {
    145         changed |= read_rows_on_col(current_matrix, current_col);
    146     }
    147 
    148     return (uint8_t)changed;
    149 }