qmk_firmware

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

matrix.c (4116B)


      1 /*
      2  * Copyright 2018-2023 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 <hal_pal.h>
     20 #include <math.h>
     21 #include "wait.h"
     22 
     23 // STM32-specific watchdog config calculations
     24 // timeout = 31.25us * PR * (RL + 1)
     25 #define _STM32_IWDG_LSI(us) ((us) / 31.25)
     26 #define STM32_IWDG_PR_US(us) (uint8_t)(log(_STM32_IWDG_LSI(us)) / log(2) - 11)
     27 #define STM32_IWDG_PR_MS(s) STM32_IWDG_PR_US(s * 1000.0)
     28 #define STM32_IWDG_PR_S(s) STM32_IWDG_PR_US(s * 1000000.0)
     29 #define _STM32_IWDG_SCALAR(us) (2 << ((uint8_t)STM32_IWDG_PR_US(us) + 1))
     30 #define STM32_IWDG_RL_US(us) (uint64_t)(_STM32_IWDG_LSI(us)) / _STM32_IWDG_SCALAR(us)
     31 #define STM32_IWDG_RL_MS(s) STM32_IWDG_RL_US(s * 1000.0)
     32 #define STM32_IWDG_RL_S(s) STM32_IWDG_RL_US(s * 1000000.0)
     33 
     34 #if !defined(PLANCK_WATCHDOG_TIMEOUT)
     35 #   define PLANCK_WATCHDOG_TIMEOUT 1.0
     36 #endif
     37 
     38 /* matrix state(1:on, 0:off) */
     39 static pin_t matrix_row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
     40 static pin_t matrix_col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
     41 
     42 static matrix_row_t matrix_inverted[MATRIX_COLS];
     43 
     44 void matrix_init_custom(void) {
     45     // actual matrix setup - cols
     46     for (int i = 0; i < MATRIX_COLS; i++) {
     47         gpio_set_pin_output(matrix_col_pins[i]);
     48         gpio_write_pin_low(matrix_col_pins[i]);
     49     }
     50 
     51     // rows
     52     for (int i = 0; i < MATRIX_ROWS; i++) {
     53         gpio_set_pin_input_low(matrix_row_pins[i]);
     54     }
     55 
     56     // encoder A & B setup
     57     gpio_set_pin_input_low(B12);
     58     gpio_set_pin_input_low(B13);
     59 
     60 #ifndef PLANCK_WATCHDOG_DISABLE
     61     wdgInit();
     62 
     63     static WDGConfig wdgcfg;
     64     wdgcfg.pr   = STM32_IWDG_PR_S(PLANCK_WATCHDOG_TIMEOUT);
     65     wdgcfg.rlr  = STM32_IWDG_RL_S(PLANCK_WATCHDOG_TIMEOUT);
     66     wdgcfg.winr = STM32_IWDG_WIN_DISABLED;
     67     wdgStart(&WDGD1, &wdgcfg);
     68 #endif
     69 }
     70 
     71 bool matrix_scan_custom(matrix_row_t current_matrix[]) {
     72 #ifndef PLANCK_WATCHDOG_DISABLE
     73     // reset watchdog
     74     wdgReset(&WDGD1);
     75 #endif
     76 
     77     bool changed = false;
     78 
     79     // actual matrix
     80     for (int col = 0; col < MATRIX_COLS; col++) {
     81         matrix_row_t data = 0;
     82 
     83         // strobe col
     84         gpio_write_pin_high(matrix_col_pins[col]);
     85 
     86         // need wait to settle pin state
     87         wait_us(20);
     88 
     89         // read row data
     90         for (int row = 0; row < MATRIX_ROWS; row++) {
     91             data |= (gpio_read_pin(matrix_row_pins[row]) << row);
     92         }
     93 
     94         // unstrobe col
     95         gpio_write_pin_low(matrix_col_pins[col]);
     96 
     97         if (matrix_inverted[col] != data) {
     98             matrix_inverted[col] = data;
     99         }
    100     }
    101 
    102     for (int row = 0; row < MATRIX_ROWS; row++) {
    103         matrix_row_t old = current_matrix[row];
    104         current_matrix[row] = 0;
    105         for (int col = 0; col < MATRIX_COLS; col++) {
    106             current_matrix[row] |= ((matrix_inverted[col] & (1 << row) ? 1 : 0) << col);
    107         }
    108         changed |= old != current_matrix[row];
    109     }
    110 
    111     return changed;
    112 }
    113 
    114 #if defined(ENCODER_ENABLE) || defined(ENCODER_MAP_ENABLE)
    115 #if !defined(PLANCK_ENCODER_SETTLE_PIN_STATE_DELAY)
    116 #   define PLANCK_ENCODER_SETTLE_PIN_STATE_DELAY 10
    117 #endif
    118 
    119 void encoder_quadrature_init_pin(uint8_t index, bool pad_b) {
    120 }
    121 
    122 uint8_t encoder_quadrature_read_pin(uint8_t index, bool pad_b) {
    123     pin_t col_pin = pad_b ? B13 : B12;
    124     gpio_set_pin_output(col_pin);
    125     gpio_write_pin_high(col_pin);
    126     wait_us(PLANCK_ENCODER_SETTLE_PIN_STATE_DELAY);
    127     uint8_t ret = gpio_read_pin(matrix_row_pins[index]) ? 0 : 1;
    128     gpio_set_pin_input_low(col_pin);
    129     return ret;
    130 }
    131 #endif // ENCODER_ENABLE || ENCODER_MAP_ENABLE