qmk_firmware

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

matrix.c (6456B)


      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 "wait.h"
     18 #include "print.h"
     19 #include "debug.h"
     20 #include "util.h"
     21 #include "matrix.h"
     22 #include "debounce.h"
     23 
     24 #if (MATRIX_COLS <= 8)
     25 #    define print_matrix_header() print("\nr/c 01234567\n")
     26 #    define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
     27 #    define ROW_SHIFTER ((uint8_t)1)
     28 #elif (MATRIX_COLS <= 16)
     29 #    define print_matrix_header() print("\nr/c 0123456789ABCDEF\n")
     30 #    define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row))
     31 #    define ROW_SHIFTER ((uint16_t)1)
     32 #elif (MATRIX_COLS <= 32)
     33 #    define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n")
     34 #    define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row))
     35 #    define ROW_SHIFTER ((uint32_t)1)
     36 #endif
     37 
     38 #ifdef MATRIX_MASKED
     39 extern const matrix_row_t matrix_mask[];
     40 #endif
     41 
     42 static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
     43 static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
     44 
     45 /* matrix state(1:on, 0:off) */
     46 static matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values
     47 static matrix_row_t matrix[MATRIX_ROWS];     // debounced values
     48 
     49 __attribute__((weak)) void matrix_init_kb(void) {
     50     matrix_init_user();
     51 }
     52 
     53 __attribute__((weak)) void matrix_scan_kb(void) {
     54     matrix_scan_user();
     55 }
     56 
     57 __attribute__((weak)) void matrix_init_user(void) {}
     58 
     59 __attribute__((weak)) void matrix_scan_user(void) {}
     60 
     61 inline uint8_t matrix_rows(void) {
     62     return MATRIX_ROWS;
     63 }
     64 
     65 inline uint8_t matrix_cols(void) {
     66     return MATRIX_COLS;
     67 }
     68 
     69 inline bool matrix_is_on(uint8_t row, uint8_t col) {
     70     return (matrix[row] & ((matrix_row_t)1 << col));
     71 }
     72 
     73 inline matrix_row_t matrix_get_row(uint8_t row) {
     74     // Matrix mask lets you disable switches in the returned matrix data. For example, if you have a
     75     // switch blocker installed and the switch is always pressed.
     76 #ifdef MATRIX_MASKED
     77     return matrix[row] & matrix_mask[row];
     78 #else
     79     return matrix[row];
     80 #endif
     81 }
     82 
     83 void matrix_print(void) {
     84     print_matrix_header();
     85 
     86     for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
     87         print_hex8(row);
     88         print(": ");
     89         print_matrix_row(row);
     90         print("\n");
     91     }
     92 }
     93 
     94 static void select_row(uint8_t row) {
     95     gpio_set_pin_output(row_pins[row]);
     96     gpio_write_pin_low(row_pins[row]);
     97 }
     98 
     99 static void unselect_row(uint8_t row) {
    100     gpio_set_pin_input_high(row_pins[row]);
    101 }
    102 
    103 static void unselect_rows(void) {
    104     for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
    105         gpio_set_pin_input_high(row_pins[x]);
    106     }
    107 }
    108 
    109 static void select_col(uint8_t col) {
    110     gpio_set_pin_output(col_pins[col]);
    111     gpio_write_pin_low(col_pins[col]);
    112 }
    113 
    114 static void unselect_col(uint8_t col) {
    115     gpio_set_pin_input_high(col_pins[col]);
    116 }
    117 
    118 static void unselect_cols(void) {
    119     for (uint8_t x = 0; x < MATRIX_COLS; x++) {
    120         gpio_set_pin_input_high(col_pins[x]);
    121     }
    122 }
    123 
    124 static void init_pins(void) {
    125     unselect_rows();
    126     unselect_cols();
    127     for (uint8_t x = 0; x < MATRIX_COLS; x++) {
    128         gpio_set_pin_input_high(col_pins[x]);
    129     }
    130     for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
    131         gpio_set_pin_input_high(row_pins[x]);
    132     }
    133 }
    134 
    135 static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
    136     // Store last value of row prior to reading
    137     matrix_row_t last_row_value = current_matrix[current_row];
    138 
    139     // Clear data in matrix row
    140     current_matrix[current_row] = 0;
    141 
    142     // Select row and wait for row selecton to stabilize
    143     select_row(current_row);
    144     wait_us(30);
    145 
    146     // For each col...
    147     for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
    148         // Select the col pin to read (active low)
    149         uint8_t pin_state = gpio_read_pin(col_pins[col_index]);
    150 
    151         // Populate the matrix row with the state of the col pin
    152         current_matrix[current_row] |= pin_state ? 0 : (ROW_SHIFTER << col_index);
    153     }
    154 
    155     // Unselect row
    156     unselect_row(current_row);
    157 
    158     return (last_row_value != current_matrix[current_row]);
    159 }
    160 
    161 static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {
    162     bool matrix_changed = false;
    163 
    164     // Select col and wait for col selecton to stabilize
    165     select_col(current_col);
    166     wait_us(30);
    167 
    168     // For each row...
    169     for (uint8_t row_index = 0; row_index < MATRIX_ROWS / 2; row_index++) {
    170         uint8_t tmp = row_index + MATRIX_ROWS / 2;
    171         // Store last value of row prior to reading
    172         matrix_row_t last_row_value = current_matrix[tmp];
    173 
    174         // Check row pin state
    175         if (gpio_read_pin(row_pins[row_index]) == 0) {
    176             // Pin LO, set col bit
    177             current_matrix[tmp] |= (ROW_SHIFTER << current_col);
    178         } else {
    179             // Pin HI, clear col bit
    180             current_matrix[tmp] &= ~(ROW_SHIFTER << current_col);
    181         }
    182 
    183         // Determine if the matrix changed state
    184         if ((last_row_value != current_matrix[tmp]) && !(matrix_changed)) {
    185             matrix_changed = true;
    186         }
    187     }
    188 
    189     // Unselect col
    190     unselect_col(current_col);
    191 
    192     return matrix_changed;
    193 }
    194 
    195 void matrix_init(void) {
    196     // initialize key pins
    197     init_pins();
    198 
    199     // initialize matrix state: all keys off
    200     for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
    201         raw_matrix[i] = 0;
    202         matrix[i]     = 0;
    203     }
    204 
    205     debounce_init();
    206 
    207     matrix_init_kb();
    208 }
    209 
    210 uint8_t matrix_scan(void) {
    211     bool changed = false;
    212 
    213     // Set row, read cols
    214     for (uint8_t current_row = 0; current_row < MATRIX_ROWS / 2; current_row++) {
    215         changed |= read_cols_on_row(raw_matrix, current_row);
    216     }
    217     // else
    218     //  Set col, read rows
    219     for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
    220         changed |= read_rows_on_col(raw_matrix, current_col);
    221     }
    222 
    223     debounce(raw_matrix, matrix, changed);
    224 
    225     matrix_scan_kb();
    226     return (uint8_t)changed;
    227 }