qmk_firmware

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

matrix.c (5468B)


      1 /*
      2  * Copyright 2018 Jack Humbert <jack.humb@gmail.com>
      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 "debug.h"
     20 #include "timer.h"
     21 #include "wait.h"
     22 
     23 #ifndef DEBOUNCE
     24 #    define DEBOUNCE 5
     25 #endif
     26 
     27 typedef uint16_t matrix_col_t;
     28 
     29 /*
     30  *     col: { B11, B10, B2, B1, A7, B0 }
     31  *     row: { A10, A9, A8, B15, C13, C14, C15, A2 }
     32  */
     33 /* matrix state(1:on, 0:off) */
     34 static matrix_row_t matrix[MATRIX_ROWS];
     35 static matrix_col_t matrix_debouncing[MATRIX_COLS];
     36 static bool         debouncing      = false;
     37 static uint16_t     debouncing_time = 0;
     38 
     39 __attribute__((weak)) void matrix_init_user(void) {}
     40 
     41 __attribute__((weak)) void matrix_scan_user(void) {}
     42 
     43 __attribute__((weak)) void matrix_init_kb(void) {
     44     matrix_init_user();
     45 }
     46 
     47 __attribute__((weak)) void matrix_scan_kb(void) {
     48     matrix_scan_user();
     49 }
     50 
     51 void matrix_init(void) {
     52     dprintf("matrix init\n");
     53     // debug_matrix = true;
     54 
     55     // actual matrix setup
     56     palSetPadMode(GPIOB, 11, PAL_MODE_OUTPUT_PUSHPULL);
     57     palSetPadMode(GPIOB, 10, PAL_MODE_OUTPUT_PUSHPULL);
     58     palSetPadMode(GPIOB, 2, PAL_MODE_OUTPUT_PUSHPULL);
     59     palSetPadMode(GPIOB, 1, PAL_MODE_OUTPUT_PUSHPULL);
     60     palSetPadMode(GPIOA, 7, PAL_MODE_OUTPUT_PUSHPULL);
     61     palSetPadMode(GPIOB, 0, PAL_MODE_OUTPUT_PUSHPULL);
     62 
     63     palSetPadMode(GPIOA, 10, PAL_MODE_INPUT_PULLDOWN);
     64     palSetPadMode(GPIOA, 9, PAL_MODE_INPUT_PULLDOWN);
     65     palSetPadMode(GPIOA, 8, PAL_MODE_INPUT_PULLDOWN);
     66     palSetPadMode(GPIOB, 15, PAL_MODE_INPUT_PULLDOWN);
     67     palSetPadMode(GPIOC, 13, PAL_MODE_INPUT_PULLDOWN);
     68     palSetPadMode(GPIOC, 14, PAL_MODE_INPUT_PULLDOWN);
     69     palSetPadMode(GPIOC, 15, PAL_MODE_INPUT_PULLDOWN);
     70     palSetPadMode(GPIOA, 2, PAL_MODE_INPUT_PULLDOWN);
     71     palSetPadMode(GPIOA, 3, PAL_MODE_INPUT_PULLDOWN);
     72     palSetPadMode(GPIOA, 6, PAL_MODE_INPUT_PULLDOWN);
     73 
     74     memset(matrix, 0, MATRIX_ROWS * sizeof(matrix_row_t));
     75     memset(matrix_debouncing, 0, MATRIX_COLS * sizeof(matrix_col_t));
     76 
     77     matrix_init_kb();
     78 }
     79 
     80 uint8_t matrix_scan(void) {
     81     // actual matrix
     82     for (int col = 0; col < MATRIX_COLS; col++) {
     83         matrix_col_t data = 0;
     84 
     85         // strobe col { B11, B10, B2, B1, A7, B0 }
     86         switch (col) {
     87             case 0:
     88                 palSetPad(GPIOB, 11);
     89                 break;
     90             case 1:
     91                 palSetPad(GPIOB, 10);
     92                 break;
     93             case 2:
     94                 palSetPad(GPIOB, 2);
     95                 break;
     96             case 3:
     97                 palSetPad(GPIOB, 1);
     98                 break;
     99             case 4:
    100                 palSetPad(GPIOA, 7);
    101                 break;
    102             case 5:
    103                 palSetPad(GPIOB, 0);
    104                 break;
    105         }
    106 
    107         // need wait to settle pin state
    108         wait_us(20);
    109 
    110         // read row data { A10, A9, A8, B15, C13, C14, C15, A2 }
    111         data = ((palReadPad(GPIOA, 10) << 0) | (palReadPad(GPIOA, 9) << 1) | (palReadPad(GPIOA, 8) << 2) | (palReadPad(GPIOB, 15) << 3) | (palReadPad(GPIOC, 13) << 4) | (palReadPad(GPIOC, 14) << 5) | (palReadPad(GPIOC, 15) << 6) | (palReadPad(GPIOA, 2) << 7) | (palReadPad(GPIOA, 3) << 8) | (palReadPad(GPIOA, 6) << 9));
    112 
    113         // unstrobe  col { B11, B10, B2, B1, A7, B0 }
    114         switch (col) {
    115             case 0:
    116                 palClearPad(GPIOB, 11);
    117                 break;
    118             case 1:
    119                 palClearPad(GPIOB, 10);
    120                 break;
    121             case 2:
    122                 palClearPad(GPIOB, 2);
    123                 break;
    124             case 3:
    125                 palClearPad(GPIOB, 1);
    126                 break;
    127             case 4:
    128                 palClearPad(GPIOA, 7);
    129                 break;
    130             case 5:
    131                 palClearPad(GPIOB, 0);
    132                 break;
    133         }
    134 
    135         if (matrix_debouncing[col] != data) {
    136             matrix_debouncing[col] = data;
    137             debouncing             = true;
    138             debouncing_time        = timer_read();
    139         }
    140     }
    141 
    142     if (debouncing && timer_elapsed(debouncing_time) > DEBOUNCE) {
    143         for (int row = 0; row < MATRIX_ROWS; row++) {
    144             matrix[row] = 0;
    145             for (int col = 0; col < MATRIX_COLS; col++) {
    146                 matrix[row] |= ((matrix_debouncing[col] & (1 << row) ? 1 : 0) << col);
    147             }
    148         }
    149         debouncing = false;
    150     }
    151 
    152     matrix_scan_kb();
    153 
    154     return 1;
    155 }
    156 
    157 bool matrix_is_on(uint8_t row, uint8_t col) {
    158     return (matrix[row] & (1 << col));
    159 }
    160 
    161 matrix_row_t matrix_get_row(uint8_t row) {
    162     return matrix[row];
    163 }
    164 
    165 void matrix_print(void) {
    166     dprintf("\nr/c 01234567\n");
    167     for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
    168         dprintf("%X0: ", row);
    169         matrix_row_t data = matrix_get_row(row);
    170         for (int col = 0; col < MATRIX_COLS; col++) {
    171             if (data & (1 << col))
    172                 dprintf("1");
    173             else
    174                 dprintf("0");
    175         }
    176         dprintf("\n");
    177     }
    178 }