matrix.c (3690B)
1 // Copyright 2023 Cameron Varley (@RustedAperture) 2 // SPDX-License-Identifier: GPL-2.0-or-later 3 4 /* 5 * scan matrix 6 */ 7 #include "matrix.h" 8 #include <string.h> 9 #include "atomic_util.h" 10 #include "wait.h" 11 #include "print.h" 12 #include "debug.h" 13 14 /* matrix state(1:on, 0:off) */ 15 extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values 16 extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values 17 18 static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; 19 static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; 20 #define MATRIX_ROW_SHIFTER ((matrix_row_t)1) 21 22 static inline void gpio_atomic_set_pin_output_low(pin_t pin) { 23 ATOMIC_BLOCK_FORCEON { 24 gpio_set_pin_output(pin); 25 gpio_write_pin_low(pin); 26 } 27 } 28 29 static inline void gpio_atomic_set_pin_output_high(pin_t pin) { 30 ATOMIC_BLOCK_FORCEON { 31 gpio_set_pin_output(pin); 32 gpio_write_pin_high(pin); 33 } 34 } 35 36 static inline void gpio_atomic_set_pin_input_high(pin_t pin) { 37 ATOMIC_BLOCK_FORCEON { 38 gpio_set_pin_input_high(pin); 39 } 40 } 41 42 static inline uint8_t readMatrixPin(pin_t pin) { 43 if (pin != NO_PIN) { 44 return gpio_read_pin(pin); 45 } else { 46 return 1; 47 } 48 } 49 50 static bool select_col(uint8_t col) { 51 pin_t pin = col_pins[col]; 52 if (pin != NO_PIN) { 53 gpio_atomic_set_pin_output_low(pin); 54 return true; 55 } 56 return false; 57 } 58 59 static void unselect_col(uint8_t col) { 60 pin_t pin = col_pins[col]; 61 if (pin != NO_PIN) { 62 # ifdef MATRIX_UNSELECT_DRIVE_HIGH 63 gpio_atomic_set_pin_output_high(pin); 64 # else 65 gpio_atomic_set_pin_input_high(pin); 66 # endif 67 } 68 } 69 70 static void unselect_cols(void) { 71 for (uint8_t x = 0; x < MATRIX_COLS; x++) { 72 unselect_col(x); 73 } 74 } 75 76 77 __attribute__((weak)) void matrix_init_custom(void) { 78 unselect_cols(); 79 for (uint8_t x = 0; x < MATRIX_ROWS; x++) { 80 if (row_pins[x] != NO_PIN) { 81 gpio_atomic_set_pin_input_high(row_pins[x]); 82 } 83 } 84 gpio_atomic_set_pin_input_high(B8); 85 } 86 87 __attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col, matrix_row_t row_shifter) { // Start with a clear matrix row 88 bool key_pressed = false; 89 90 // Select col 91 if (!select_col(current_col)) { // select col 92 return; // skip NO_PIN col 93 } 94 matrix_output_select_delay(); 95 96 // For each row... 97 for (uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) { 98 // Check row pin state 99 if (current_col == 3 && row_index == 2 && readMatrixPin(B8) == 1) { 100 current_matrix[row_index] |= row_shifter; 101 key_pressed = !readMatrixPin(B8); 102 } else if (readMatrixPin(row_pins[row_index]) == 0) { 103 // Pin LO, set col bit 104 current_matrix[row_index] |= row_shifter; 105 key_pressed = true; 106 } else { 107 // Pin HI, clear col bit 108 current_matrix[row_index] &= ~row_shifter; 109 } 110 } 111 112 // Unselect col 113 unselect_col(current_col); 114 matrix_output_unselect_delay(current_col, key_pressed); // wait for all Row signals to go HIGH 115 } 116 117 bool matrix_scan_custom(matrix_row_t current_matrix[]) { 118 static matrix_row_t temp_matrix[MATRIX_ROWS] = {0}; 119 120 matrix_row_t row_shifter = MATRIX_ROW_SHIFTER; 121 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { 122 matrix_read_rows_on_col(temp_matrix, current_col, row_shifter); 123 } 124 125 bool changed = memcmp(current_matrix, temp_matrix, sizeof(temp_matrix)) != 0; 126 if (changed) { 127 memcpy(current_matrix, temp_matrix, sizeof(temp_matrix)); 128 } 129 return changed; 130 }