matrix.c (4928B)
1 /* 2 Copyright 2012-2020 Jun Wako, Jack Humbert, Yiancar 3 4 This program is free software: you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation, either version 2 of the License, or 7 (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 #include "atomic_util.h" 18 #include "wait.h" 19 #include "matrix.h" 20 #include "i2c_master.h" 21 22 #define PORT_EXPANDER_ADDRESS 0x20 23 24 static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; 25 static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; 26 27 static inline void gpio_atomic_set_pin_output_low(pin_t pin) { 28 ATOMIC_BLOCK_FORCEON { 29 gpio_set_pin_output(pin); 30 gpio_write_pin_low(pin); 31 } 32 } 33 34 static inline void gpio_atomic_set_pin_output_high(pin_t pin) { 35 ATOMIC_BLOCK_FORCEON { 36 gpio_set_pin_output(pin); 37 gpio_write_pin_high(pin); 38 } 39 } 40 41 static inline void gpio_atomic_set_pin_input_high(pin_t pin) { 42 ATOMIC_BLOCK_FORCEON { 43 gpio_set_pin_input_high(pin); 44 } 45 } 46 47 static inline uint8_t readMatrixPin(pin_t pin) { 48 if (pin != NO_PIN) { 49 return (gpio_read_pin(pin) == 0) ? 0 : 1; 50 } else { 51 return 1; 52 } 53 } 54 55 static bool select_row(uint8_t row) { 56 pin_t pin = row_pins[row]; 57 if (pin != NO_PIN) { 58 gpio_atomic_set_pin_output_low(pin); 59 return true; 60 } 61 return false; 62 } 63 64 static void unselect_row(uint8_t row) { 65 pin_t pin = row_pins[row]; 66 if (pin != NO_PIN) { 67 gpio_atomic_set_pin_input_high(pin); 68 } 69 } 70 71 static void unselect_rows(void) { 72 for (uint8_t x = 0; x < MATRIX_ROWS; x++) { 73 unselect_row(x); 74 } 75 } 76 77 static void init_pins(void) { 78 unselect_rows(); 79 // Set I/O 80 uint8_t send_data = 0xFF; 81 i2c_write_register((PORT_EXPANDER_ADDRESS << 1), 0x00, &send_data, 1, 20); 82 // Set Pull-up 83 i2c_write_register((PORT_EXPANDER_ADDRESS << 1), 0x06, &send_data, 1, 20); 84 85 for (uint8_t x = 0; x < MATRIX_COLS; x++) { 86 if (col_pins[x] != NO_PIN) { 87 gpio_atomic_set_pin_input_high(col_pins[x]); 88 } 89 } 90 } 91 92 void matrix_init_custom(void) { 93 // TODO: initialize hardware here 94 // Initialize I2C 95 i2c_init(); 96 97 // initialize key pins 98 init_pins(); 99 wait_ms(50); 100 } 101 102 static bool matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { 103 // Store last value of row prior to reading 104 matrix_row_t last_row_value = current_matrix[current_row]; 105 106 // Clear data in matrix row 107 current_matrix[current_row] = 0; 108 109 // Select row and wait for row selecton to stabilize 110 select_row(current_row); 111 matrix_output_select_delay(); 112 113 uint8_t port_expander_buffer; 114 i2c_read_register((PORT_EXPANDER_ADDRESS << 1), 0x09, &port_expander_buffer, 1, 20); 115 116 // For each col... 117 // matrix_row_t row_shifter = MATRIX_ROW_SHIFTER; 118 for(uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { 119 uint8_t pin_state; 120 // Select the col pin to read (active low) 121 switch (col_index) { 122 case 6 : 123 pin_state = port_expander_buffer & (1 << 0); 124 break; 125 case 7 : 126 pin_state = port_expander_buffer & (1 << 1); 127 break; 128 case 8 : 129 pin_state = port_expander_buffer & (1 << 2); 130 break; 131 case 9 : 132 pin_state = port_expander_buffer & (1 << 3); 133 break; 134 case 10 : 135 pin_state = port_expander_buffer & (1 << 4); 136 break; 137 case 11 : 138 pin_state = port_expander_buffer & (1 << 5); 139 break; 140 case 12 : 141 pin_state = port_expander_buffer & (1 << 6); 142 break; 143 case 13 : 144 pin_state = port_expander_buffer & (1 << 7); 145 break; 146 default : 147 pin_state = readMatrixPin(col_pins[col_index]); 148 } 149 150 // Populate the matrix row with the state of the col pin 151 current_matrix[current_row] |= pin_state ? 0 : (MATRIX_ROW_SHIFTER << col_index); 152 } 153 154 // Unselect row 155 unselect_row(current_row); 156 157 return (last_row_value != current_matrix[current_row]); 158 } 159 160 bool matrix_scan_custom(matrix_row_t current_matrix[]) { 161 bool matrix_has_changed = false; 162 163 // Set row, read cols 164 for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) { 165 matrix_has_changed |= matrix_read_cols_on_row(current_matrix, current_row); 166 } 167 168 return matrix_has_changed; 169 }