qmk_firmware

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

matrix.c (4434B)


      1 #include "matrix.h"
      2 #include <string.h>
      3 #include "timer.h"
      4 #include "wait.h"
      5 #include "debug.h"
      6 #include "i2c_master.h"
      7 #include "ergodox_stm32.h"
      8 
      9 #ifndef DEBOUNCE
     10 #define DEBOUNCE 10
     11 #endif
     12 
     13 static uint8_t mcp23017_reset_loop = 0;
     14 
     15 volatile matrix_row_t matrix[MATRIX_ROWS];
     16 volatile matrix_row_t raw_matrix[MATRIX_ROWS];
     17 volatile uint8_t debounce_matrix[MATRIX_ROWS * MATRIX_COLS];
     18 
     19 static matrix_row_t read_cols(uint8_t row);
     20 
     21 static void init_cols(void);
     22 
     23 static void unselect_rows(void);
     24 
     25 static void select_row(uint8_t row);
     26 
     27 static void init_rows(void);
     28 
     29 __attribute__((weak)) void matrix_init_user(void) {}
     30 
     31 __attribute__((weak)) void matrix_scan_user(void) {}
     32 
     33 __attribute__((weak)) void matrix_init_kb(void) {
     34   matrix_init_user();
     35 }
     36 
     37 __attribute__((weak)) void matrix_scan_kb(void) {
     38   matrix_scan_user();
     39 }
     40 
     41 void matrix_init(void) {
     42   mcp23017_status = init_mcp23017();
     43   (void) mcp23017_reset_loop;
     44   init_rows();
     45   unselect_rows();
     46   init_cols();
     47 
     48 
     49   for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
     50     matrix[i] = 0;
     51     raw_matrix[i] = 0;
     52     for (uint8_t j = 0; j < MATRIX_COLS; ++j) {
     53       debounce_matrix[i * MATRIX_COLS + j] = 0;
     54     }
     55   }
     56   matrix_init_kb();
     57 }
     58 
     59 void matrix_power_up(void) {
     60   mcp23017_status = init_mcp23017();
     61 
     62   init_rows();
     63   unselect_rows();
     64   init_cols();
     65 
     66   for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
     67     matrix[i] = 0;
     68   }
     69 }
     70 
     71 matrix_row_t debounce_mask(matrix_row_t rawcols, uint8_t row) {
     72   matrix_row_t result = 0;
     73   matrix_row_t change = rawcols ^raw_matrix[row];
     74   raw_matrix[row] = rawcols;
     75   for (uint8_t i = 0; i < MATRIX_COLS; ++i) {
     76     if (debounce_matrix[row * MATRIX_COLS + i]) {
     77       --debounce_matrix[row * MATRIX_COLS + i];
     78     } else {
     79       result |= (1 << i);
     80     }
     81     if (change & (1 << i)) {
     82       debounce_matrix[row * MATRIX_COLS + i] = DEBOUNCE;
     83     }
     84   }
     85   return result;
     86 }
     87 
     88 matrix_row_t debounce_read_cols(uint8_t row) {
     89   // Read the row without debouncing filtering and store it for later usage.
     90   matrix_row_t cols = read_cols(row);
     91   // Get the Debounce mask.
     92   matrix_row_t mask = debounce_mask(cols, row);
     93   // debounce the row and return the result.
     94   return (cols & mask) | (matrix[row] & ~mask);;
     95 }
     96 
     97 uint8_t matrix_scan(void) {
     98   if (mcp23017_status) {
     99     if (++mcp23017_reset_loop == 0) {
    100       mcp23017_status = init_mcp23017();
    101         if (!mcp23017_status) {
    102             ergodox_blink_all_leds();
    103         }
    104     }
    105   }
    106   for (uint8_t i = 0; i < MATRIX_ROWS_PER_SIDE; i++) {
    107     select_row(i);
    108     select_row(i + MATRIX_ROWS_PER_SIDE);
    109 
    110     matrix[i] = debounce_read_cols(i);
    111     matrix[i + MATRIX_ROWS_PER_SIDE] = debounce_read_cols(i + MATRIX_ROWS_PER_SIDE);
    112 
    113     unselect_rows();
    114   }
    115   matrix_scan_kb();
    116   return 0;
    117 }
    118 
    119 inline
    120 bool matrix_is_on(uint8_t row, uint8_t col) {
    121   return (matrix[row] & (1 << col));
    122 }
    123 
    124 inline
    125 matrix_row_t matrix_get_row(uint8_t row) {
    126   return matrix[row];
    127 }
    128 
    129 void matrix_print(void) {
    130 }
    131 
    132 static matrix_row_t read_cols(uint8_t row) {
    133   if (row < MATRIX_ROWS_PER_SIDE) {
    134     uint8_t data = 0xFF;
    135     if (!mcp23017_status) {
    136       uint8_t regAddr = I2C_GPIOB;
    137       mcp23017_status = i2c_read_register(I2C_ADDR, regAddr, &data, 1, 10);
    138     }
    139     if (mcp23017_status) {
    140       return 0;
    141     }
    142     return (~data) & 0x3F;
    143   } else {
    144       uint8_t data_p = (GPIOB -> IDR);
    145       uint8_t data = data_p;
    146     return ((~data) & 0x3f);
    147   }
    148 }
    149 
    150 static void init_cols(void) {
    151   palSetPadMode(GPIOB, 0, PAL_MODE_INPUT_PULLUP);
    152   palSetPadMode(GPIOB, 1, PAL_MODE_INPUT_PULLUP);
    153   palSetPadMode(GPIOB, 2, PAL_MODE_INPUT_PULLUP);
    154   palSetPadMode(GPIOB, 3, PAL_MODE_INPUT_PULLUP);
    155   palSetPadMode(GPIOB, 4, PAL_MODE_INPUT_PULLUP);
    156   palSetPadMode(GPIOB, 5, PAL_MODE_INPUT_PULLUP);
    157 }
    158 
    159 static void init_rows(void) {
    160   palSetPadMode(GPIOB, 8, PAL_MODE_OUTPUT_PUSHPULL);
    161   palSetPadMode(GPIOB, 9, PAL_MODE_OUTPUT_PUSHPULL);
    162   palSetPadMode(GPIOB, 10, PAL_MODE_OUTPUT_PUSHPULL);
    163   palSetPadMode(GPIOB, 11, PAL_MODE_OUTPUT_PUSHPULL);
    164   palSetPadMode(GPIOB, 12, PAL_MODE_OUTPUT_PUSHPULL);
    165   palSetPadMode(GPIOB, 13, PAL_MODE_OUTPUT_PUSHPULL);
    166   palSetPadMode(GPIOB, 14, PAL_MODE_OUTPUT_PUSHPULL);
    167 }
    168 
    169 static void unselect_rows(void) {
    170   GPIOB->BSRR = 0b1111111 << 8;
    171 }
    172 
    173 static void select_row(uint8_t row) {
    174   if (row < MATRIX_ROWS_PER_SIDE) {
    175     if (!mcp23017_status) {
    176       uint8_t data = (0xFF & ~(1 << row));
    177       mcp23017_status = i2c_write_register(I2C_ADDR, I2C_GPIOA, &data, 1, 10);
    178     }
    179   } else {
    180     GPIOB->BRR = 0x1 << (row+1);
    181   }
    182 }