matrix.c (3625B)
1 // Copyright 2022 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com> 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 "debug.h" 12 #include "util.h" 13 #include "debounce.h" 14 15 /* matrix state(1:on, 0:off) */ 16 extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values 17 extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values 18 19 static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; 20 static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; 21 #define MATRIX_ROW_SHIFTER ((matrix_row_t)1) 22 23 static inline void gpio_atomic_set_pin_output_low(pin_t pin) { 24 ATOMIC_BLOCK_FORCEON { 25 gpio_set_pin_output(pin); 26 gpio_write_pin_low(pin); 27 } 28 } 29 30 static inline void gpio_atomic_set_pin_output_high(pin_t pin) { 31 ATOMIC_BLOCK_FORCEON { 32 gpio_set_pin_output(pin); 33 gpio_write_pin_high(pin); 34 } 35 } 36 37 static inline void gpio_atomic_set_pin_input_high(pin_t pin) { 38 ATOMIC_BLOCK_FORCEON { 39 gpio_set_pin_input_high(pin); 40 } 41 } 42 43 static inline uint8_t readMatrixPin(pin_t pin) { 44 if (pin != NO_PIN) { 45 return gpio_read_pin(pin); 46 } else { 47 return 1; 48 } 49 } 50 51 static bool select_row(uint8_t row) { 52 pin_t pin = row_pins[row]; 53 if (pin != NO_PIN) { 54 gpio_atomic_set_pin_output_low(pin); 55 return true; 56 } 57 return false; 58 } 59 60 static void unselect_row(uint8_t row) { 61 pin_t pin = row_pins[row]; 62 if (pin != NO_PIN) { 63 gpio_atomic_set_pin_input_high(pin); 64 } 65 } 66 67 static void unselect_rows(void) { 68 for (uint8_t x = 0; x < MATRIX_ROWS; x++) { 69 unselect_row(x); 70 } 71 } 72 73 __attribute__((weak)) void matrix_init_custom(void) { 74 unselect_rows(); 75 for (uint8_t x = 0; x < MATRIX_COLS; x++) { 76 if (col_pins[x] != NO_PIN) { 77 gpio_atomic_set_pin_input_high(col_pins[x]); 78 } 79 } 80 gpio_atomic_set_pin_input_high(F7); 81 gpio_atomic_set_pin_input_high(F0); 82 } 83 84 void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { 85 // Start with a clear matrix row 86 matrix_row_t current_row_value = 0; 87 88 if (!select_row(current_row)) { // Select row 89 return; // skip NO_PIN row 90 } 91 matrix_output_select_delay(); 92 93 // For each col... 94 matrix_row_t row_shifter = MATRIX_ROW_SHIFTER; 95 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++, row_shifter <<= 1) { 96 uint8_t pin_state = 0; 97 if (current_row == 3 && col_index == 0) { 98 pin_state = !readMatrixPin(F7); 99 } else if (current_row == 3 && col_index == 3) { 100 pin_state = !readMatrixPin(F0); 101 } else { 102 pin_state = readMatrixPin(col_pins[col_index]); 103 } 104 // Populate the matrix row with the state of the col pin 105 current_row_value |= pin_state ? 0 : row_shifter; 106 } 107 108 // Unselect row 109 unselect_row(current_row); 110 matrix_output_unselect_delay(current_row, current_row_value != 0); // wait for all Col signals to go HIGH 111 112 // Update the matrix 113 current_matrix[current_row] = current_row_value; 114 } 115 116 bool matrix_scan_custom(matrix_row_t current_matrix[]) { 117 static matrix_row_t temp_matrix[MATRIX_ROWS] = {0}; 118 119 for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) { 120 matrix_read_cols_on_row(temp_matrix, current_row); 121 } 122 123 bool changed = memcmp(current_matrix, temp_matrix, sizeof(temp_matrix)) != 0; 124 if (changed) { 125 memcpy(current_matrix, temp_matrix, sizeof(temp_matrix)); 126 } 127 return changed; 128 }