qmk_firmware

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

matrix.c (3471B)


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