matrix.c (9245B)
1 /* 2 Copyright 2012-2018 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 "wait.h" 18 #include "print.h" 19 #include "debug.h" 20 #include "util.h" 21 #include "matrix.h" 22 #include "debounce.h" 23 24 #if (MATRIX_COLS <= 8) 25 # define print_matrix_header() print("\nr/c 01234567\n") 26 # define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row)) 27 # define ROW_SHIFTER ((uint8_t)1) 28 #elif (MATRIX_COLS <= 16) 29 # define print_matrix_header() print("\nr/c 0123456789ABCDEF\n") 30 # define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row)) 31 # define ROW_SHIFTER ((uint16_t)1) 32 #elif (MATRIX_COLS <= 32) 33 # define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n") 34 # define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row)) 35 # define ROW_SHIFTER ((uint32_t)1) 36 #endif 37 38 #ifdef MATRIX_MASKED 39 extern const matrix_row_t matrix_mask[]; 40 #endif 41 42 #ifdef DIRECT_PINS 43 static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS; 44 #elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW) 45 // static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; 46 static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; 47 #endif 48 49 /* matrix state(1:on, 0:off) */ 50 static matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values 51 static matrix_row_t matrix[MATRIX_ROWS]; // debounced values 52 53 __attribute__((weak)) void matrix_init_kb(void) { 54 matrix_init_user(); 55 } 56 57 __attribute__((weak)) void matrix_scan_kb(void) { 58 matrix_scan_user(); 59 } 60 61 __attribute__((weak)) void matrix_init_user(void) {} 62 63 __attribute__((weak)) void matrix_scan_user(void) {} 64 65 inline uint8_t matrix_rows(void) { 66 return MATRIX_ROWS; 67 } 68 69 inline uint8_t matrix_cols(void) { 70 return MATRIX_COLS; 71 } 72 73 inline bool matrix_is_on(uint8_t row, uint8_t col) { 74 return (matrix[row] & ((matrix_row_t)1 << col)); 75 } 76 77 inline matrix_row_t matrix_get_row(uint8_t row) { 78 // Matrix mask lets you disable switches in the returned matrix data. For example, if you have a 79 // switch blocker installed and the switch is always pressed. 80 #ifdef MATRIX_MASKED 81 return matrix[row] & matrix_mask[row]; 82 #else 83 return matrix[row]; 84 #endif 85 } 86 87 void matrix_print(void) { 88 print_matrix_header(); 89 90 for (uint8_t row = 0; row < MATRIX_ROWS; row++) { 91 print_hex8(row); 92 print(": "); 93 print_matrix_row(row); 94 print("\n"); 95 } 96 } 97 98 #ifdef DIRECT_PINS 99 100 static void init_pins(void) { 101 for (int row = 0; row < MATRIX_ROWS; row++) { 102 for (int col = 0; col < MATRIX_COLS; col++) { 103 pin_t pin = direct_pins[row][col]; 104 if (pin != NO_PIN) { 105 gpio_set_pin_input_high(pin); 106 } 107 } 108 } 109 } 110 111 static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { 112 matrix_row_t last_row_value = current_matrix[current_row]; 113 current_matrix[current_row] = 0; 114 115 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { 116 pin_t pin = direct_pins[current_row][col_index]; 117 if (pin != NO_PIN) { 118 current_matrix[current_row] |= gpio_read_pin(pin) ? 0 : (ROW_SHIFTER << col_index); 119 } 120 } 121 122 return (last_row_value != current_matrix[current_row]); 123 } 124 125 #elif (DIODE_DIRECTION == COL2ROW) 126 /* Rows 0 - 5 127 * These rows use a 74HC237D 3 to 8 bit demultiplexer. 128 * C B A 129 * row / pin: PB0 PB1 PB2 130 * 0: 0 0 0 131 * 1: 0 0 1 132 * 2: 0 1 0 133 * 3: 0 1 1 134 * 4: 1 0 0 135 * 5: 1 0 1 136 */ 137 static void select_row(uint8_t col) { 138 switch (col) { 139 case 0: 140 gpio_write_pin_low(B0); 141 gpio_write_pin_low(B1); 142 gpio_write_pin_low(B2); 143 break; 144 case 1: 145 gpio_write_pin_low(B0); 146 gpio_write_pin_low(B1); 147 break; 148 case 2: 149 gpio_write_pin_low(B0); 150 gpio_write_pin_low(B2); 151 break; 152 case 3: 153 gpio_write_pin_low(B0); 154 break; 155 case 4: 156 gpio_write_pin_low(B1); 157 gpio_write_pin_low(B2); 158 break; 159 case 5: 160 gpio_write_pin_low(B1); 161 break; 162 } 163 } 164 165 static void unselect_row(uint8_t col) { 166 switch (col) { 167 case 0: 168 gpio_write_pin_high(B0); 169 gpio_write_pin_high(B1); 170 gpio_write_pin_high(B2); 171 break; 172 case 1: 173 gpio_write_pin_high(B0); 174 gpio_write_pin_high(B1); 175 break; 176 case 2: 177 gpio_write_pin_high(B0); 178 gpio_write_pin_high(B2); 179 break; 180 case 3: 181 gpio_write_pin_high(B0); 182 break; 183 case 4: 184 gpio_write_pin_high(B1); 185 gpio_write_pin_high(B2); 186 break; 187 case 5: 188 gpio_write_pin_high(B1); 189 break; 190 } 191 } 192 193 static void unselect_rows(void) { 194 gpio_set_pin_output(B0); 195 gpio_set_pin_output(B1); 196 gpio_set_pin_output(B2); 197 // make all pins high to select Y7, nothing is connected to that (otherwise the first row will act weird) 198 gpio_write_pin_high(B0); 199 gpio_write_pin_high(B1); 200 gpio_write_pin_high(B2); 201 } 202 203 static void init_pins(void) { 204 unselect_rows(); 205 for (uint8_t x = 0; x < MATRIX_COLS; x++) { 206 gpio_set_pin_input_high(col_pins[x]); 207 } 208 } 209 210 static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { 211 // Store last value of row prior to reading 212 matrix_row_t last_row_value = current_matrix[current_row]; 213 214 // Clear data in matrix row 215 current_matrix[current_row] = 0; 216 217 // Select row and wait for row selecton to stabilize 218 select_row(current_row); 219 wait_us(30); 220 221 // For each col... 222 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { 223 // Select the col pin to read (active low) 224 uint8_t pin_state = gpio_read_pin(col_pins[col_index]); 225 226 // Populate the matrix row with the state of the col pin 227 current_matrix[current_row] |= pin_state ? 0 : (ROW_SHIFTER << col_index); 228 } 229 230 // Unselect row 231 unselect_row(current_row); 232 233 return (last_row_value != current_matrix[current_row]); 234 } 235 236 #elif (DIODE_DIRECTION == ROW2COL) 237 238 static void select_col(uint8_t col) { 239 gpio_set_pin_output(col_pins[col]); 240 gpio_write_pin_low(col_pins[col]); 241 } 242 243 static void unselect_col(uint8_t col) { 244 gpio_set_pin_input_high(col_pins[col]); 245 } 246 247 static void unselect_cols(void) { 248 for (uint8_t x = 0; x < MATRIX_COLS; x++) { 249 gpio_set_pin_input_high(col_pins[x]); 250 } 251 } 252 253 static void init_pins(void) { 254 unselect_cols(); 255 for (uint8_t x = 0; x < MATRIX_ROWS; x++) { 256 gpio_set_pin_input_high(row_pins[x]); 257 } 258 } 259 260 static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) { 261 bool matrix_changed = false; 262 263 // Select col and wait for col selecton to stabilize 264 select_col(current_col); 265 wait_us(30); 266 267 // For each row... 268 for (uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) { 269 // Store last value of row prior to reading 270 matrix_row_t last_row_value = current_matrix[row_index]; 271 272 // Check row pin state 273 if (gpio_read_pin(row_pins[row_index]) == 0) { 274 // Pin LO, set col bit 275 current_matrix[row_index] |= (ROW_SHIFTER << current_col); 276 } else { 277 // Pin HI, clear col bit 278 current_matrix[row_index] &= ~(ROW_SHIFTER << current_col); 279 } 280 281 // Determine if the matrix changed state 282 if ((last_row_value != current_matrix[row_index]) && !(matrix_changed)) { 283 matrix_changed = true; 284 } 285 } 286 287 // Unselect col 288 unselect_col(current_col); 289 290 return matrix_changed; 291 } 292 293 #endif 294 295 void matrix_init(void) { 296 // initialize key pins 297 init_pins(); 298 299 // initialize matrix state: all keys off 300 for (uint8_t i = 0; i < MATRIX_ROWS; i++) { 301 raw_matrix[i] = 0; 302 matrix[i] = 0; 303 } 304 305 debounce_init(); 306 307 matrix_init_kb(); 308 } 309 310 uint8_t matrix_scan(void) { 311 bool changed = false; 312 313 #if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW) 314 // Set row, read cols 315 for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) { 316 changed |= read_cols_on_row(raw_matrix, current_row); 317 } 318 #elif (DIODE_DIRECTION == ROW2COL) 319 // Set col, read rows 320 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { 321 changed |= read_rows_on_col(raw_matrix, current_col); 322 } 323 #endif 324 325 debounce(raw_matrix, matrix, changed); 326 327 matrix_scan_kb(); 328 return 1; 329 }