qmk_firmware

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

matrix.c (3625B)


      1 // Copyright 2022 Christopher Courtney, aka Drashna Jael're  (@drashna) <drashna@live.com>
      2 // SPDX-License-Identifier: GPL-2.0-or-later
      3 
      4 /*
      5  * scan matrix
      6  */
      7 #include "matrix.h"
      8 #include <string.h>
      9 #include "atomic_util.h"
     10 #include "wait.h"
     11 #include "debug.h"
     12 #include "util.h"
     13 #include "debounce.h"
     14 
     15 /* matrix state(1:on, 0:off) */
     16 extern matrix_row_t matrix[MATRIX_ROWS];     // debounced values
     17 extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values
     18 
     19 static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
     20 static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
     21 #define MATRIX_ROW_SHIFTER ((matrix_row_t)1)
     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_output_high(pin_t pin) {
     31     ATOMIC_BLOCK_FORCEON {
     32         gpio_set_pin_output(pin);
     33         gpio_write_pin_high(pin);
     34     }
     35 }
     36 
     37 static inline void gpio_atomic_set_pin_input_high(pin_t pin) {
     38     ATOMIC_BLOCK_FORCEON {
     39         gpio_set_pin_input_high(pin);
     40     }
     41 }
     42 
     43 static inline uint8_t readMatrixPin(pin_t pin) {
     44     if (pin != NO_PIN) {
     45         return gpio_read_pin(pin);
     46     } else {
     47         return 1;
     48     }
     49 }
     50 
     51 static bool select_row(uint8_t row) {
     52     pin_t pin = row_pins[row];
     53     if (pin != NO_PIN) {
     54         gpio_atomic_set_pin_output_low(pin);
     55         return true;
     56     }
     57     return false;
     58 }
     59 
     60 static void unselect_row(uint8_t row) {
     61     pin_t pin = row_pins[row];
     62     if (pin != NO_PIN) {
     63         gpio_atomic_set_pin_input_high(pin);
     64     }
     65 }
     66 
     67 static void unselect_rows(void) {
     68     for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
     69         unselect_row(x);
     70     }
     71 }
     72 
     73 __attribute__((weak)) void matrix_init_custom(void) {
     74     unselect_rows();
     75     for (uint8_t x = 0; x < MATRIX_COLS; x++) {
     76         if (col_pins[x] != NO_PIN) {
     77             gpio_atomic_set_pin_input_high(col_pins[x]);
     78         }
     79     }
     80     gpio_atomic_set_pin_input_high(F7);
     81     gpio_atomic_set_pin_input_high(F0);
     82 }
     83 
     84 void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
     85     // Start with a clear matrix row
     86     matrix_row_t current_row_value = 0;
     87 
     88     if (!select_row(current_row)) { // Select row
     89         return;                     // skip NO_PIN row
     90     }
     91     matrix_output_select_delay();
     92 
     93     // For each col...
     94     matrix_row_t row_shifter = MATRIX_ROW_SHIFTER;
     95     for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++, row_shifter <<= 1) {
     96         uint8_t pin_state = 0;
     97         if (current_row == 3 && col_index == 0) {
     98             pin_state = !readMatrixPin(F7);
     99         } else if (current_row == 3 && col_index == 3) {
    100             pin_state = !readMatrixPin(F0);
    101         } else {
    102             pin_state = readMatrixPin(col_pins[col_index]);
    103         }
    104         // Populate the matrix row with the state of the col pin
    105         current_row_value |= pin_state ? 0 : row_shifter;
    106     }
    107 
    108     // Unselect row
    109     unselect_row(current_row);
    110     matrix_output_unselect_delay(current_row, current_row_value != 0); // wait for all Col signals to go HIGH
    111 
    112     // Update the matrix
    113     current_matrix[current_row] = current_row_value;
    114 }
    115 
    116 bool matrix_scan_custom(matrix_row_t current_matrix[]) {
    117     static matrix_row_t temp_matrix[MATRIX_ROWS] = {0};
    118 
    119     for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
    120         matrix_read_cols_on_row(temp_matrix, current_row);
    121     }
    122 
    123     bool changed = memcmp(current_matrix, temp_matrix, sizeof(temp_matrix)) != 0;
    124     if (changed) {
    125         memcpy(current_matrix, temp_matrix, sizeof(temp_matrix));
    126     }
    127     return changed;
    128 }