matrix.c (3964B)
1 /* Copyright 2021 Jay Greco 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 <string.h> 18 #include "split_util.h" 19 #include "wait.h" 20 21 #define VIRT_COLS_PER_HAND 1 22 #define PHYS_COLS_PER_HAND (MATRIX_COLS - VIRT_COLS_PER_HAND) 23 #define ROWS_PER_HAND (MATRIX_ROWS / 2) 24 #define COL_SHIFTER ((uint32_t)1) 25 #define EXT_PIN_ROW 2 26 #define EXT_PIN_COL 8 27 28 // Row & column pins 29 static uint8_t row_pins_left[MATRIX_ROWS] = MATRIX_ROW_PINS; 30 static uint8_t col_pins_left[MATRIX_MUX_COLS] = MATRIX_COL_MUX_PINS; 31 static uint8_t row_pins_right[MATRIX_ROWS] = MATRIX_ROW_PINS_RIGHT; 32 static uint8_t col_pins_right[MATRIX_MUX_COLS] = MATRIX_COL_MUX_PINS_RIGHT; 33 static uint8_t* row_pins = row_pins_left; 34 static uint8_t* col_pins = col_pins_left; 35 36 // Internal functions 37 static void init_pins(void) { 38 // Set cols to outputs, low 39 for (uint8_t pin = 0; pin < MATRIX_MUX_COLS; pin++) { 40 gpio_set_pin_output(col_pins[pin]); 41 } 42 43 // Unselect cols 44 for (uint8_t bit = 0; bit < MATRIX_MUX_COLS; bit++) { 45 gpio_write_pin_low(col_pins[bit]); 46 } 47 48 // Set rows to input, pullup 49 for (uint8_t pin = 0; pin < ROWS_PER_HAND; pin++) { 50 gpio_set_pin_input_high(row_pins[pin]); 51 } 52 53 // Set extended pin (only on right side) 54 if (!isLeftHand) { 55 // Set extended pin to input, pullup 56 gpio_set_pin_input_high(MATRIX_EXT_PIN_RIGHT); 57 } 58 } 59 60 static void select_col(uint8_t col) { 61 // Drive demux with correct column address 62 for (uint8_t bit = 0; bit < MATRIX_MUX_COLS; bit++) { 63 uint8_t state = (col & (0b1 << bit)) >> bit; 64 gpio_write_pin(col_pins[bit], !state); 65 } 66 } 67 68 static void read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) { 69 select_col(current_col % PHYS_COLS_PER_HAND); 70 wait_us(5); 71 72 // Read each row sequentially 73 for (uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++) { 74 if (gpio_read_pin(row_pins[row_index]) == 0) { 75 current_matrix[row_index] |= (COL_SHIFTER << current_col); 76 } else { 77 current_matrix[row_index] &= ~(COL_SHIFTER << current_col); 78 } 79 } 80 } 81 82 static void read_ext_pin(matrix_row_t current_matrix[]) { 83 // Read the state of the extended matrix pin 84 if (!isLeftHand) { 85 if (gpio_read_pin(MATRIX_EXT_PIN_RIGHT) == 0) { 86 current_matrix[EXT_PIN_ROW] |= (COL_SHIFTER << EXT_PIN_COL); 87 } else { 88 current_matrix[EXT_PIN_ROW] &= ~(COL_SHIFTER << EXT_PIN_COL); 89 } 90 } 91 } 92 93 void matrix_init_custom(void) { 94 if (!isLeftHand) { 95 row_pins = row_pins_right; 96 col_pins = col_pins_right; 97 } 98 99 init_pins(); 100 } 101 102 bool matrix_scan_custom(matrix_row_t current_matrix[]) { 103 matrix_row_t last_matrix[MATRIX_ROWS]; 104 memcpy(last_matrix, current_matrix, sizeof(last_matrix)); 105 106 #ifdef DEBUG_SLOW_MATRIX 107 // Slow for debugging 108 wait_ms(1000); 109 #endif 110 111 // Set col, read rows 112 for (uint8_t current_col = 0; current_col < PHYS_COLS_PER_HAND; current_col++) { 113 read_rows_on_col(current_matrix, current_col); 114 } 115 116 // Read extended pin and store in matrix 117 read_ext_pin(current_matrix); 118 119 // Check if the matrix changed 120 bool changed = memcmp(last_matrix, current_matrix, sizeof(last_matrix)) != 0; 121 122 return changed; 123 }