qmk_firmware

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

matrix.c (3740B)


      1 // Copyright 2019 Mathias Andersson <wraul@dbox.se>
      2 // SPDX-License-Identifier: GPL-2.0-or-later
      3 #include "matrix.h"
      4 #include "pca9555.h"
      5 #include "wait.h"
      6 
      7 /*
      8  *       IC1 (PCA9555)                  IC2 (PCA9555)
      9  *       ,----------.                   ,----------.
     10  * SDA --| SDA  P00 |-- P1        SDA --| SDA  P00 |-- P17
     11  * SCL --| SCL  P01 |-- P2        SCL --| SCL  P01 |-- P18
     12  * INT --| INT  P02 |-- P3        INT --| INT  P02 |-- P19
     13  *       |      P03 |-- P4              |      P03 |-- P20
     14  * GND --| A0   P04 |-- P5        VCC --| A0   P04 |-- P21
     15  * SJ1 --| A1   P05 |-- P6        SJ1 --| A1   P05 |-- P22
     16  * GND --| A2   P06 |-- P7        GND --| A2   P06 |-- P23
     17  *       |      P07 |-- P8              |      P07 |-- P24
     18  *       |          |                   |          |
     19  *       |      P10 |-- P9              |      P10 |-- P25
     20  *       |      P11 |-- P10             |      P11 |-- P26
     21  *       |      P12 |-- P11             |      P12 |-- P27
     22  *       |      P13 |-- P12             |      P13 |-- P28
     23  *       |      P14 |-- P13             |      P14 |-- P29
     24  *       |      P15 |-- P14             |      P15 |-- P30
     25  *       |      P16 |-- P15             |      P16 |-- P31
     26  *       |      P17 |-- P16             |      P17 |-- P32
     27  *       `----------'                   `----------'
     28  */
     29 
     30 /*
     31  * | Row | Pin |   | Col | Pin |
     32  * | --- | --- |   | --- | --- |
     33  * | 0   | P1  |   | 0   | P25 |
     34  * | 1   | P2  |   | 1   | P26 |
     35  * | 2   | P3  |   | 2   | P27 |
     36  * | 3   | P4  |   | 3   | P28 |
     37  * | 4   | P5  |   | 4   | P29 |
     38  * | 5   | P6  |   | 5   | P30 |
     39  * | 6   | P7  |   | 6   | P20 |
     40  * | 7   | P8  |   | 7   | P21 |
     41  *                 | 8   | P22 |
     42  *                 | 9   | P23 |
     43  *                 | A   | P24 |
     44  */
     45 
     46 // PCA9555 slave addresses
     47 #define IC1 0x20
     48 #define IC2 0x21
     49 
     50 // PCA9555 column pin masks
     51 #define PORT0_COLS_MASK 0b11111000
     52 #define PORT1_COLS_MASK 0b00111111
     53 #define COLS_MASK 0b0000011111111111
     54 
     55 static void init_pins(void) {
     56   // init cols - IC2 port0 & IC2 port1 input
     57   pca9555_set_config(IC2, PCA9555_PORT0, ALL_INPUT);
     58   pca9555_set_config(IC2, PCA9555_PORT1, ALL_INPUT);
     59 
     60   // init rows - IC1 port0 output
     61   pca9555_set_config(IC1, PCA9555_PORT0, ALL_OUTPUT);
     62   pca9555_set_output(IC1, PCA9555_PORT0, ALL_HIGH);
     63 }
     64 
     65 static void select_row(uint8_t row) {
     66   // All rows are on the same IC and port
     67   uint8_t mask = 1 << row;
     68 
     69   // set active row low  : 0
     70   // set other rows hi-Z : 1
     71   pca9555_set_output(IC1, PCA9555_PORT0, ALL_HIGH & (~mask));
     72 }
     73 
     74 static uint16_t read_cols(void) {
     75   uint8_t state_1 = 0;
     76   uint8_t state_2 = 0;
     77   pca9555_read_pins(IC2, PCA9555_PORT0, &state_1);
     78   pca9555_read_pins(IC2, PCA9555_PORT1, &state_2);
     79 
     80   uint16_t state = (((uint16_t)state_1 & PORT0_COLS_MASK) << 3) | (((uint16_t)state_2 & PORT1_COLS_MASK));
     81 
     82   // A low pin indicates an active column
     83   return (~state) & COLS_MASK;
     84 }
     85 
     86 static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
     87   // Store last value of row prior to reading
     88   matrix_row_t last_row_value = current_matrix[current_row];
     89 
     90   // Clear data in matrix row
     91   current_matrix[current_row] = 0;
     92 
     93   // Select row and wait for row selection to stabilize
     94   select_row(current_row);
     95   wait_us(30);
     96 
     97   current_matrix[current_row] = read_cols();
     98 
     99   // No need to unselect as `select_row` sets all the pins.
    100 
    101   return (last_row_value != current_matrix[current_row]);
    102 }
    103 
    104 void matrix_init_custom(void) {
    105   pca9555_init(IC1);
    106   pca9555_init(IC2);
    107 
    108   init_pins();
    109 }
    110 
    111 bool matrix_scan_custom(matrix_row_t current_matrix[]) {
    112   bool changed = false;
    113   for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
    114     changed |= read_cols_on_row(current_matrix, current_row);
    115   }
    116   return changed;
    117 }