qmk_firmware

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

matrix.c (3610B)


      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 
     18 #include "matrix.h"
     19 #include "sn74x138.h"
     20 
     21 static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
     22 static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
     23 
     24 /* Columns 6 and 9-15 use a 74HC138 3-to-8 demultiplexer.
     25  * D4 is the enable pin, must be set high to use it.
     26  *
     27  * 0:  F7
     28  * 1:  F5
     29  * 2:  F6
     30  * 3:  F1
     31  * 4:  F4
     32  * 5:  F0
     33  *
     34  *     A2   A1   A0
     35  *     D0   D1   D2
     36  * 6:   1    1    1
     37  *
     38  * 7:  D5
     39  * 8:  D3
     40  *
     41  * 9:   1    1    0
     42  * 10:  1    0    1
     43  * 11:  1    0    0
     44  * 12:  0    1    1
     45  * 13:  0    1    0
     46  * 14:  0    0    1
     47  * 15:  0    0    0
     48  */
     49 static void select_col(uint8_t col) {
     50     if (col_pins[col] != NO_PIN) {
     51         gpio_write_pin_low(col_pins[col]);
     52     } else {
     53         sn74x138_set_addr((col == 6) ? 7 : 15 - col);
     54         sn74x138_set_enabled(true);
     55     }
     56 }
     57 
     58 static void unselect_col(uint8_t col) {
     59     if (col_pins[col] != NO_PIN) {
     60         gpio_set_pin_output(col_pins[col]);
     61         gpio_write_pin_high(col_pins[col]);
     62     } else {
     63         sn74x138_set_enabled(false);
     64     }
     65 }
     66 
     67 static void unselect_cols(void) {
     68     // Native
     69     for (uint8_t x = 0; x < MATRIX_COLS; x++) {
     70         if (col_pins[x] != NO_PIN) {
     71             gpio_set_pin_output(col_pins[x]);
     72             gpio_write_pin_high(col_pins[x]);
     73         }
     74     }
     75 
     76     // Demultiplexer
     77     sn74x138_set_enabled(false);
     78 }
     79 
     80 static void init_pins(void) {
     81     unselect_cols();
     82     for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
     83         gpio_set_pin_input_high(row_pins[x]);
     84     }
     85 }
     86 
     87 static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {
     88     bool matrix_changed = false;
     89 
     90     // Select col and wait for col selection to stabilize
     91     select_col(current_col);
     92     matrix_io_delay();
     93 
     94     // For each row...
     95     for (uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) {
     96         // Store last value of row prior to reading
     97         matrix_row_t last_row_value = current_matrix[row_index];
     98 
     99         // Check row pin state
    100         if (gpio_read_pin(row_pins[row_index]) == 0) {
    101             // Pin LO, set col bit
    102             current_matrix[row_index] |= (MATRIX_ROW_SHIFTER << current_col);
    103         } else {
    104             // Pin HI, clear col bit
    105             current_matrix[row_index] &= ~(MATRIX_ROW_SHIFTER << current_col);
    106         }
    107 
    108         // Determine if the matrix changed state
    109         if ((last_row_value != current_matrix[row_index]) && !(matrix_changed)) {
    110             matrix_changed = true;
    111         }
    112     }
    113 
    114     // Unselect col
    115     unselect_col(current_col);
    116 
    117     return matrix_changed;
    118 }
    119 
    120 void matrix_init_custom(void) {
    121     // initialize demultiplexer
    122     sn74x138_init();
    123     // initialize key pins
    124     init_pins();
    125 }
    126 
    127 bool matrix_scan_custom(matrix_row_t current_matrix[]) {
    128     bool changed = false;
    129 
    130     // Set col, read rows
    131     for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
    132         changed |= read_rows_on_col(current_matrix, current_col);
    133     }
    134 
    135     return changed;
    136 }