qmk_firmware

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

matrix.c (3158B)


      1 /* Copyright 2019
      2  *
      3  * This program is free software: you can redistribute it and/or modify
      4  * it under the terms of the GNU General Public License as published by
      5  * the Free Software Foundation, either version 2 of the License, or
      6  * (at your option) any later version.
      7  *
      8  * This program is distributed in the hope that it will be useful,
      9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     11  * GNU General Public License for more details.
     12  *
     13  * You should have received a copy of the GNU General Public License
     14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
     15  */
     16 #include "matrix.h"
     17 #include "pca9555.h"
     18 
     19 // PCA9555 slave addresses
     20 #define IC1 0x20
     21 #define IC2 0x21
     22 
     23 //_____Utility funcs___________________________________________________________
     24 
     25 static void init_pins(void) {
     26     // init all rows - IC1 port0 input
     27     pca9555_set_config(IC1, PCA9555_PORT0, ALL_INPUT);  // same as initial state
     28 
     29     // init all cols high - IC2 all input
     30     pca9555_set_config(IC1, PCA9555_PORT1, ALL_INPUT);  // same as initial state
     31     pca9555_set_config(IC2, PCA9555_PORT0, ALL_INPUT);  // same as initial state
     32     pca9555_set_config(IC2, PCA9555_PORT1, ALL_INPUT);  // same as initial state
     33     
     34     pca9555_set_output(IC1, PCA9555_PORT0, ALL_LOW);
     35 }
     36 
     37 static void select_row(uint8_t row) {
     38     // For the Southpaw Ext 65% pins 1-6 are used for the rows
     39     uint8_t pin  = row;
     40     uint8_t mask = 2 << pin;
     41 
     42     pca9555_set_config(IC1, PCA9555_PORT0, ALL_INPUT & (~mask));
     43 }
     44 
     45 static uint32_t read_cols(void) {
     46     //Read column inputs. Pins 13-31 are used. Split across both ICs but they are sequential
     47     uint8_t state_1 = 0;
     48     uint8_t state_2 = 0;
     49     uint8_t state_3 = 0;
     50     pca9555_read_pins(IC1, PCA9555_PORT1, &state_1);
     51     pca9555_read_pins(IC2, PCA9555_PORT0, &state_2);
     52     pca9555_read_pins(IC2, PCA9555_PORT1, &state_3);
     53 
     54     uint32_t state = ((((uint32_t)state_3 & 0b01111111) << 12) | ((uint32_t)state_2 << 4) | (((uint32_t)state_1 & 0b11110000) >> 4));
     55     return ~state;
     56 }
     57 
     58 static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
     59     // Store last value of row prior to reading
     60     matrix_row_t last_row_value = current_matrix[current_row];
     61 
     62     // Clear data in matrix row
     63     current_matrix[current_row] = 0;
     64 
     65     // Select row and wait for row selection to stabilize
     66     select_row(current_row);
     67     // Skip the wait_us(30); as i2c is slow enough to debounce the io changes
     68 
     69     current_matrix[current_row] = read_cols();
     70 
     71     // No need to Unselect row as the next `select_row` will blank everything
     72 
     73     return (last_row_value != current_matrix[current_row]);
     74 }
     75 
     76 //_____CUSTOM MATRIX IMPLEMENTATION____________________________________________________
     77 
     78 void matrix_init_custom(void) {
     79     pca9555_init(IC1);
     80     pca9555_init(IC2);
     81 
     82     init_pins();
     83 }
     84 
     85 bool matrix_scan_custom(matrix_row_t current_matrix[]) {
     86     bool changed = false;
     87     for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
     88         changed |= read_cols_on_row(current_matrix, current_row);
     89     }
     90     return changed;
     91 }