qmk_firmware

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

matrix.c (3002B)


      1 /* Copyright 2022
      2  *
      3  * This program is free software: you can redistribute it and/or modify
      4  * it under the terms of the GNU General Public License as published by
      5  * the Free Software Foundation, either version 2 of the License, or
      6  * (at your option) any later version.
      7  *
      8  * This program is distributed in the hope that it will be useful,
      9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     11  * GNU General Public License for more details.
     12  *
     13  * You should have received a copy of the GNU General Public License
     14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
     15  */
     16 
     17 #include "matrix.h"
     18 #include "gpio.h"
     19 #include "sn74x154.h"
     20 
     21 static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
     22 
     23 /* All columns use a 74HC154 4-to-16 demultiplexer.
     24  * D3 is the enable pin, must be set high to use it.
     25  *
     26  *     A3   A2   A1   A0
     27  *     D7   D6   D5   D4
     28  * 0:   0    0    0    0
     29  * 1:   0    0    0    1
     30  * 2:   0    0    1    0
     31  * 3:   0    0    1    1
     32  * 4:   0    1    0    0
     33  * 5:   0    1    0    1
     34  * 6:   0    1    1    0
     35  * 7:   0    1    1    1
     36  * 8:   1    0    0    0
     37  * 9:   1    0    0    1
     38  * 10:  1    0    1    0
     39  * 11:  1    0    1    1
     40  * 12:  1    1    0    0
     41  * 13:  1    1    0    1
     42  * 14:  1    1    1    0
     43  * 15:  1    1    1    1
     44  */
     45 static void select_col(uint8_t col) {
     46     sn74x154_set_addr(col);
     47 }
     48 
     49 static void init_pins(void) {
     50     for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
     51         gpio_set_pin_input_high(row_pins[x]);
     52     }
     53 }
     54 
     55 static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {
     56     bool matrix_changed = false;
     57 
     58     // Select col and wait for col seleciton to stabilize
     59     select_col(current_col);
     60     matrix_io_delay();
     61 
     62     // For each row...
     63     for (uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) {
     64         // Store last value of row prior to reading
     65         matrix_row_t last_row_value = current_matrix[row_index];
     66 
     67         // Check row pin state
     68         if (gpio_read_pin(row_pins[row_index]) == 0) {
     69             // Pin LO, set col bit
     70             current_matrix[row_index] |= (MATRIX_ROW_SHIFTER << current_col);
     71         } else {
     72             // Pin HI, clear col bit
     73             current_matrix[row_index] &= ~(MATRIX_ROW_SHIFTER << current_col);
     74         }
     75 
     76         // Determine if the matrix changed state
     77         if ((last_row_value != current_matrix[row_index]) && !(matrix_changed)) {
     78             matrix_changed = true;
     79         }
     80     }
     81 
     82     return matrix_changed;
     83 }
     84 
     85 void matrix_init_custom(void) {
     86     // initialize demultiplexer
     87     sn74x154_init();
     88     sn74x154_set_enabled(true);
     89     // initialize key pins
     90     init_pins();
     91 }
     92 
     93 bool matrix_scan_custom(matrix_row_t current_matrix[]) {
     94     bool changed = false;
     95 
     96     // Set col, read rows
     97     for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
     98         changed |= read_rows_on_col(current_matrix, current_col);
     99     }
    100 
    101     return changed;
    102 }