qmk_firmware

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

matrix.c (7328B)


      1 /*
      2 Copyright 2019 worthlessowl
      3 based on work by:
      4 Jun Wako <wakojun@gmail.com>
      5 Cole Markham <cole@ccmcomputing.net>
      6 
      7 This program is free software: you can redistribute it and/or modify
      8 it under the terms of the GNU General Public License as published by
      9 the Free Software Foundation, either version 2 of the License, or
     10 (at your option) any later version.
     11 This program is distributed in the hope that it will be useful,
     12 but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 GNU General Public License for more details.
     15 You should have received a copy of the GNU General Public License
     16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
     17 */
     18 
     19 /*
     20  * scan matrix
     21  */
     22 #include <stdint.h>
     23 #include <stdbool.h>
     24 #include "wait.h"
     25 #include "print.h"
     26 #include "debug.h"
     27 #include "util.h"
     28 #include "matrix.h"
     29 #include "timer.h"
     30 
     31 #if (MATRIX_COLS <= 8)
     32 #    define print_matrix_header() print("\nr/c 01234567\n")
     33 #    define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
     34 #    define ROW_SHIFTER ((uint8_t)1)
     35 #elif (MATRIX_COLS <= 16)
     36 #    define print_matrix_header() print("\nr/c 0123456789ABCDEF\n")
     37 #    define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row))
     38 #    define ROW_SHIFTER ((uint16_t)1)
     39 #elif (MATRIX_COLS <= 32)
     40 #    define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n")
     41 #    define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row))
     42 #    define ROW_SHIFTER ((uint32_t)1)
     43 #endif
     44 
     45 static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
     46 static const uint8_t col_select_pins[3]    = MATRIX_COL_SELECT_PINS;
     47 static const uint8_t dat_pin               = MATRIX_COL_DATA_PIN;
     48 
     49 /* matrix state(1:on, 0:off) */
     50 static matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values
     51 static matrix_row_t matrix[MATRIX_ROWS];     // raw values
     52 
     53 /* 2d array containing binary representation of its index */
     54 static const uint8_t num_in_binary[8][3] = {
     55     {0, 0, 0}, {0, 0, 1}, {0, 1, 0}, {0, 1, 1}, {1, 0, 0}, {1, 0, 1}, {1, 1, 0}, {1, 1, 1},
     56 };
     57 
     58 static void select_col_analog(uint8_t col);
     59 static void mux_pin_control(const uint8_t binary[]);
     60 void        debounce_init(void);
     61 void        debounce(matrix_row_t raw[], matrix_row_t cooked[], bool changed);
     62 
     63 __attribute__((weak)) void matrix_init_user(void) {}
     64 
     65 __attribute__((weak)) void matrix_scan_user(void) {}
     66 
     67 __attribute__((weak)) void matrix_init_kb(void) {
     68     matrix_init_user();
     69 }
     70 
     71 __attribute__((weak)) void matrix_scan_kb(void) {
     72     matrix_scan_user();
     73 }
     74 
     75 inline uint8_t matrix_rows(void) {
     76     return MATRIX_ROWS;
     77 }
     78 
     79 inline uint8_t matrix_cols(void) {
     80     return MATRIX_COLS;
     81 }
     82 
     83 inline bool matrix_is_on(uint8_t row, uint8_t col) {
     84     return (matrix[row] & ((matrix_row_t)1 << col));
     85 }
     86 
     87 inline matrix_row_t matrix_get_row(uint8_t row) {
     88     // Matrix mask lets you disable switches in the returned matrix data. For example, if you have a
     89     // switch blocker installed and the switch is always pressed.
     90 #ifdef MATRIX_MASKED
     91     return matrix[row] & matrix_mask[row];
     92 #else
     93     return matrix[row];
     94 #endif
     95 }
     96 
     97 void matrix_print(void) {
     98     print_matrix_header();
     99 
    100     for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
    101         print_hex8(row);
    102         print(": ");
    103         print_matrix_row(row);
    104         print("\n");
    105     }
    106 }
    107 
    108 // uses standard row code
    109 static void select_row(uint8_t row) {
    110     gpio_set_pin_output(row_pins[row]);
    111     gpio_write_pin_low(row_pins[row]);
    112 }
    113 
    114 static void unselect_row(uint8_t row) {
    115     gpio_set_pin_input_high(row_pins[row]);
    116 }
    117 
    118 static void unselect_rows(void) {
    119     for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
    120         gpio_set_pin_input_high(row_pins[x]);
    121     }
    122 }
    123 
    124 static void init_pins(void) { // still need some fixing, this might not work
    125     unselect_rows();          // with the loop
    126     /*
    127     for (uint8_t x = 0; x < MATRIX_COLS; x++) {
    128       gpio_set_pin_input_high(col_pins[x]);
    129     }
    130     */
    131     gpio_set_pin_input_high(dat_pin);
    132 }
    133 
    134 static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
    135     // Store last value of row prior to reading
    136     matrix_row_t last_row_value = current_matrix[current_row];
    137 
    138     // Clear data in matrix row
    139     current_matrix[current_row] = 0;
    140 
    141     // Select row and wait for row selecton to stabilize
    142     select_row(current_row);
    143     wait_us(30);
    144 
    145     // For each col...
    146     for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
    147         // Select the col pin to read (active low)
    148         select_col_analog(col_index);
    149         wait_us(30);
    150         uint8_t pin_state = gpio_read_pin(dat_pin);
    151 
    152         // Populate the matrix row with the state of the col pin
    153         current_matrix[current_row] |= pin_state ? 0 : (ROW_SHIFTER << col_index);
    154     }
    155 
    156     // Unselect row
    157     unselect_row(current_row);
    158 
    159     return (last_row_value != current_matrix[current_row]);
    160 }
    161 
    162 void matrix_init(void) {
    163     // initialize key pins
    164     init_pins();
    165 
    166     // initialize matrix state: all keys off
    167     for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
    168         raw_matrix[i] = 0;
    169         matrix[i]     = 0;
    170     }
    171 
    172     debounce_init();
    173 
    174     matrix_init_kb();
    175 
    176     gpio_set_pin_input(D5);
    177     gpio_set_pin_input(B0);
    178 }
    179 
    180 // modified for per col read matrix scan
    181 uint8_t matrix_scan(void) {
    182     bool changed = false;
    183 
    184     for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
    185         changed |= read_cols_on_row(raw_matrix, current_row);
    186     }
    187 
    188     debounce(raw_matrix, matrix, changed);
    189 
    190     matrix_scan_kb();
    191     return (uint8_t)changed;
    192 }
    193 
    194 /*
    195 uint8_t matrix_scan(void)
    196 {
    197   bool changed = false;
    198 
    199 #if (DIODE_DIRECTION == COL2ROW)
    200   // Set row, read cols
    201   for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
    202     changed |= read_cols_on_row(raw_matrix, current_row);
    203   }
    204 #endif
    205 
    206   debounce(raw_matrix, matrix, changed);
    207 
    208   matrix_scan_kb();
    209   return (uint8_t)changed;
    210 }
    211 */
    212 
    213 static void select_col_analog(uint8_t col) {
    214     switch (col) {
    215         case 0:
    216             mux_pin_control(num_in_binary[0]);
    217             break;
    218         case 1:
    219             mux_pin_control(num_in_binary[1]);
    220             break;
    221         case 2:
    222             mux_pin_control(num_in_binary[2]);
    223             break;
    224         case 3:
    225             mux_pin_control(num_in_binary[3]);
    226             break;
    227         case 4:
    228             mux_pin_control(num_in_binary[4]);
    229             break;
    230         case 5:
    231             mux_pin_control(num_in_binary[5]);
    232             break;
    233         case 6:
    234             mux_pin_control(num_in_binary[6]);
    235             break;
    236         case 7:
    237             mux_pin_control(num_in_binary[7]);
    238             break;
    239         default:
    240             break;
    241     }
    242 }
    243 
    244 static void mux_pin_control(const uint8_t binary[]) {
    245     // set pin0
    246     gpio_set_pin_output(col_select_pins[0]);
    247     if (binary[2] == 0) {
    248         gpio_write_pin_low(col_select_pins[0]);
    249     } else {
    250         gpio_write_pin_high(col_select_pins[0]);
    251     }
    252     // set pin1
    253     gpio_set_pin_output(col_select_pins[1]);
    254     if (binary[1] == 0) {
    255         gpio_write_pin_low(col_select_pins[1]);
    256     } else {
    257         gpio_write_pin_high(col_select_pins[1]);
    258     }
    259     // set pin2
    260     gpio_set_pin_output(col_select_pins[2]);
    261     if (binary[0] == 0) {
    262         gpio_write_pin_low(col_select_pins[2]);
    263     } else {
    264         gpio_write_pin_high(col_select_pins[2]);
    265     }
    266 }