matrix.c (15768B)
1 /* 2 Copyright 2012-2018 Jun Wako, Jack Humbert, Yiancar 3 Copyright 2019 Evy Dekkers 4 5 This program is free software: you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation, either version 2 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #include "wait.h" 20 #include "util.h" 21 #include "matrix.h" 22 #include "debounce.h" 23 24 #ifdef DIRECT_PINS 25 static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS; 26 #elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW) 27 static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; 28 //static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; 29 #endif 30 31 // matrix code 32 33 #ifdef DIRECT_PINS 34 35 static void init_pins(void) { 36 for (int row = 0; row < MATRIX_ROWS; row++) { 37 for (int col = 0; col < MATRIX_COLS; col++) { 38 pin_t pin = direct_pins[row][col]; 39 if (pin != NO_PIN) { 40 gpio_set_pin_input_high(pin); 41 } 42 } 43 } 44 } 45 46 static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { 47 matrix_row_t last_row_value = current_matrix[current_row]; 48 current_matrix[current_row] = 0; 49 50 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { 51 pin_t pin = direct_pins[current_row][col_index]; 52 if (pin != NO_PIN) { 53 current_matrix[current_row] |= gpio_read_pin(pin) ? 0 : (MATRIX_ROW_SHIFTER << col_index); 54 } 55 } 56 57 return (last_row_value != current_matrix[current_row]); 58 } 59 60 #elif (DIODE_DIRECTION == COL2ROW) 61 62 static void select_row(uint8_t row) { 63 gpio_set_pin_output(row_pins[row]); 64 gpio_write_pin_low(row_pins[row]); 65 } 66 67 static void unselect_row(uint8_t row) { gpio_set_pin_input_high(row_pins[row]); } 68 69 static void unselect_rows(void) { 70 for (uint8_t x = 0; x < MATRIX_ROWS; x++) { 71 gpio_set_pin_input_high(row_pins[x]); 72 } 73 } 74 75 static void init_pins(void) { 76 unselect_rows(); 77 for (uint8_t x = 0; x < MATRIX_COLS; x++) { 78 gpio_set_pin_input_high(col_pins[x]); 79 } 80 } 81 82 static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { 83 // Store last value of row prior to reading 84 matrix_row_t last_row_value = current_matrix[current_row]; 85 86 // Clear data in matrix row 87 current_matrix[current_row] = 0; 88 89 // Select row and wait for row selecton to stabilize 90 select_row(current_row); 91 wait_us(30); 92 93 // For each col... 94 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { 95 96 // Select the col pin to read (active low) 97 uint8_t pin_state = gpio_read_pin(col_pins[col_index]); 98 99 // Populate the matrix row with the state of the col pin 100 current_matrix[current_row] |= pin_state ? 0 : (MATRIX_ROW_SHIFTER << col_index); 101 } 102 103 // Unselect row 104 unselect_row(current_row); 105 106 return (last_row_value != current_matrix[current_row]); 107 } 108 109 #elif (DIODE_DIRECTION == ROW2COL) 110 111 /* Cols 0 - 16 112 * These columns use two 74HC138 3 to 8 bit demultiplexer. B4, C7 is the enable pin, must be set high (1) to use it. 113 * 114 * col / pin: PA0 PA1 PA2 PB4 PC7 PC2 PC3 PC5 115 * 0: 0 ── 0 ── 0 1 ── 0 0 0 0 116 * ──────────────────────────────────────────── 117 * 1: 0 ── 0 ── 1 1 ── 0 0 0 0 118 * ──────────────────────────────────────────── 119 * 2: 0 ── 1 ── 0 1 ── 0 0 0 0 120 * ──────────────────────────────────────────── 121 * 3: 0 ── 1 ── 1 1 ── 0 0 0 0 122 * ──────────────────────────────────────────── 123 * 4: 1 ── 0 ── 0 1 ── 0 0 0 0 124 * ──────────────────────────────────────────── 125 * 5: 1 ── 0 ── 1 1 ── 0 0 0 0 126 * ──────────────────────────────────────────── 127 * 6: 1 ── 1 ── 0 1 ── 0 0 0 0 128 * ──────────────────────────────────────────── 129 * 7: 1 ── 1 ── 1 1 ── 0 0 0 0 130 * ──────────────────────────────────────────── 131 * 8: 1 ── 1 ── 1 0 ── 1 0 0 0 132 * ──────────────────────────────────────────── 133 * 9: 0 ── 0 ── 0 0 ── 1 0 0 0 134 * ──────────────────────────────────────────── 135 *10: 0 ── 0 ── 1 0 ── 1 0 0 0 136 * ──────────────────────────────────────────── 137 *11: 0 ── 1 ── 0 0 ── 1 0 0 0 138 * ──────────────────────────────────────────── 139 *12: 0 ── 1 ── 1 0 ── 1 0 0 0 140 * ──────────────────────────────────────────── 141 *13: 1 ── 0 ── 0 0 ── 1 0 0 0 142 * ──────────────────────────────────────────── 143 *14: 1 ── 0 ── 1 0 ── 1 0 0 0 144 * ──────────────────────────────────────────── 145 *15: 1 ── 1 ── 0 0 ── 1 0 0 0 146 * ──────────────────────────────────────────── 147 *16: 0 ── 0 ── 0 0 ── 0 1 0 0 148 * ──────────────────────────────────────────── 149 *17: 0 ── 0 ── 0 0 ── 0 0 1 0 150 * ──────────────────────────────────────────── 151 *18: 0 ── 0 ── 0 0 ── 0 0 0 1 152 * 153 */ 154 static void select_col(uint8_t col) { 155 switch (col) { 156 case 0: 157 gpio_write_pin_low(A0); 158 gpio_write_pin_low(A1); 159 gpio_write_pin_low(A2); 160 gpio_write_pin_high(B4); 161 break; 162 case 1: 163 gpio_write_pin_low(A0); 164 gpio_write_pin_low(A1); 165 gpio_write_pin_high(A2); 166 gpio_write_pin_high(B4); 167 break; 168 case 2: 169 gpio_write_pin_low(A0); 170 gpio_write_pin_high(A1); 171 gpio_write_pin_low(A2); 172 gpio_write_pin_high(B4); 173 break; 174 case 3: 175 gpio_write_pin_low(A0); 176 gpio_write_pin_high(A1); 177 gpio_write_pin_high(A2); 178 gpio_write_pin_high(B4); 179 break; 180 case 4: 181 gpio_write_pin_high(A0); 182 gpio_write_pin_low(A1); 183 gpio_write_pin_low(A2); 184 gpio_write_pin_high(B4); 185 break; 186 case 5: 187 gpio_write_pin_high(A0); 188 gpio_write_pin_low(A1); 189 gpio_write_pin_high(A2); 190 gpio_write_pin_high(B4); 191 break; 192 case 6: 193 gpio_write_pin_high(A0); 194 gpio_write_pin_high(A1); 195 gpio_write_pin_low(A2); 196 gpio_write_pin_high(B4); 197 break; 198 case 7: 199 gpio_write_pin_high(A0); 200 gpio_write_pin_high(A1); 201 gpio_write_pin_high(A2); 202 gpio_write_pin_high(B4); 203 break; 204 case 8: 205 gpio_write_pin_high(A0); 206 gpio_write_pin_high(A1); 207 gpio_write_pin_high(A2); 208 gpio_write_pin_high(C7); 209 break; 210 case 9: 211 gpio_write_pin_low(A0); 212 gpio_write_pin_low(A1); 213 gpio_write_pin_low(A2); 214 gpio_write_pin_high(C7); 215 break; 216 case 10: 217 gpio_write_pin_low(A0); 218 gpio_write_pin_low(A1); 219 gpio_write_pin_high(A2); 220 gpio_write_pin_high(C7); 221 break; 222 case 11: 223 gpio_write_pin_low(A0); 224 gpio_write_pin_high(A1); 225 gpio_write_pin_low(A2); 226 gpio_write_pin_high(C7); 227 break; 228 case 12: 229 gpio_write_pin_low(A0); 230 gpio_write_pin_high(A1); 231 gpio_write_pin_high(A2); 232 gpio_write_pin_high(C7); 233 break; 234 case 13: 235 gpio_write_pin_high(A0); 236 gpio_write_pin_low(A1); 237 gpio_write_pin_low(A2); 238 gpio_write_pin_high(C7); 239 break; 240 case 14: 241 gpio_write_pin_high(A0); 242 gpio_write_pin_low(A1); 243 gpio_write_pin_high(A2); 244 gpio_write_pin_high(C7); 245 break; 246 case 15: 247 gpio_write_pin_high(A0); 248 gpio_write_pin_high(A1); 249 gpio_write_pin_low(A2); 250 gpio_write_pin_high(C7); 251 break; 252 case 16: 253 gpio_write_pin_low(C2); 254 break; 255 case 17: 256 gpio_write_pin_low(C3); 257 break; 258 case 18: 259 gpio_write_pin_low(C5); 260 break; 261 } 262 } 263 264 static void unselect_col(uint8_t col) { 265 switch (col) { 266 case 0: 267 gpio_write_pin_high(A0); 268 gpio_write_pin_high(A1); 269 gpio_write_pin_high(A2); 270 gpio_write_pin_low(B4); 271 break; 272 case 1: 273 gpio_write_pin_high(A0); 274 gpio_write_pin_high(A1); 275 gpio_write_pin_low(A2); 276 gpio_write_pin_low(B4); 277 break; 278 case 2: 279 gpio_write_pin_high(A0); 280 gpio_write_pin_low(A1); 281 gpio_write_pin_high(A2); 282 gpio_write_pin_low(B4); 283 break; 284 case 3: 285 gpio_write_pin_high(A0); 286 gpio_write_pin_low(A1); 287 gpio_write_pin_low(A2); 288 gpio_write_pin_low(B4); 289 break; 290 case 4: 291 gpio_write_pin_low(A0); 292 gpio_write_pin_high(A1); 293 gpio_write_pin_high(A2); 294 gpio_write_pin_low(B4); 295 break; 296 case 5: 297 gpio_write_pin_low(A0); 298 gpio_write_pin_high(A1); 299 gpio_write_pin_low(A2); 300 gpio_write_pin_low(B4); 301 break; 302 case 6: 303 gpio_write_pin_low(A0); 304 gpio_write_pin_low(A1); 305 gpio_write_pin_high(A2); 306 gpio_write_pin_low(B4); 307 break; 308 case 7: 309 gpio_write_pin_low(A0); 310 gpio_write_pin_low(A1); 311 gpio_write_pin_low(A2); 312 gpio_write_pin_low(B4); 313 break; 314 case 8: 315 gpio_write_pin_low(A0); 316 gpio_write_pin_low(A1); 317 gpio_write_pin_low(A2); 318 gpio_write_pin_low(C7); 319 break; 320 case 9: 321 gpio_write_pin_high(A0); 322 gpio_write_pin_high(A1); 323 gpio_write_pin_high(A2); 324 gpio_write_pin_low(C7); 325 break; 326 case 10: 327 gpio_write_pin_high(A0); 328 gpio_write_pin_high(A1); 329 gpio_write_pin_low(A2); 330 gpio_write_pin_low(C7); 331 break; 332 case 11: 333 gpio_write_pin_high(A0); 334 gpio_write_pin_low(A1); 335 gpio_write_pin_high(A2); 336 gpio_write_pin_low(C7); 337 break; 338 case 12: 339 gpio_write_pin_high(A0); 340 gpio_write_pin_low(A1); 341 gpio_write_pin_low(A2); 342 gpio_write_pin_low(C7); 343 break; 344 case 13: 345 gpio_write_pin_low(A0); 346 gpio_write_pin_high(A1); 347 gpio_write_pin_high(A2); 348 gpio_write_pin_low(C7); 349 break; 350 case 14: 351 gpio_write_pin_low(A0); 352 gpio_write_pin_high(A1); 353 gpio_write_pin_low(A2); 354 gpio_write_pin_low(C7); 355 break; 356 case 15: 357 gpio_write_pin_low(A0); 358 gpio_write_pin_low(A1); 359 gpio_write_pin_high(A2); 360 gpio_write_pin_low(C7); 361 break; 362 case 16: 363 gpio_write_pin_high(C2); 364 break; 365 case 17: 366 gpio_write_pin_high(C3); 367 break; 368 case 18: 369 gpio_write_pin_high(C5); 370 break; 371 } 372 } 373 374 static void unselect_cols(void) { 375 //Native 376 gpio_write_pin_high(C2); 377 gpio_write_pin_high(C3); 378 gpio_write_pin_high(C5); 379 380 //Demultiplexer 381 gpio_write_pin_low(B4); 382 gpio_write_pin_low(C7); 383 gpio_write_pin_high(A0); 384 gpio_write_pin_high(A1); 385 gpio_write_pin_high(A2); 386 } 387 388 static void init_pins(void) { 389 unselect_cols(); 390 for (uint8_t x = 0; x < MATRIX_ROWS; x++) { 391 gpio_set_pin_input_high(row_pins[x]); 392 } 393 gpio_set_pin_output(A0); 394 gpio_set_pin_output(A1); 395 gpio_set_pin_output(A2); 396 gpio_set_pin_output(B4); 397 gpio_set_pin_output(C7); 398 gpio_set_pin_output(C2); 399 gpio_set_pin_output(C3); 400 gpio_set_pin_output(C5); 401 } 402 403 static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) { 404 bool matrix_changed = false; 405 406 // Select col and wait for col selecton to stabilize 407 select_col(current_col); 408 wait_us(30); 409 410 // For each row... 411 for (uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) { 412 // Store last value of row prior to reading 413 matrix_row_t last_row_value = current_matrix[row_index]; 414 415 // Check row pin state 416 if (gpio_read_pin(row_pins[row_index]) == 0) { 417 // Pin LO, set col bit 418 current_matrix[row_index] |= (MATRIX_ROW_SHIFTER << current_col); 419 } else { 420 // Pin HI, clear col bit 421 current_matrix[row_index] &= ~(MATRIX_ROW_SHIFTER << current_col); 422 } 423 424 // Determine if the matrix changed state 425 if ((last_row_value != current_matrix[row_index]) && !(matrix_changed)) { 426 matrix_changed = true; 427 } 428 } 429 430 // Unselect col 431 unselect_col(current_col); 432 433 return matrix_changed; 434 } 435 436 #endif 437 438 void matrix_init_custom(void) { 439 // initialize key pins 440 init_pins(); 441 } 442 443 bool matrix_scan_custom(matrix_row_t current_matrix[]) { 444 bool changed = false; 445 446 #if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW) 447 // Set row, read cols 448 for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) { 449 changed |= read_cols_on_row(current_matrix, current_row); 450 } 451 #elif (DIODE_DIRECTION == ROW2COL) 452 // Set col, read rows 453 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { 454 changed |= read_rows_on_col(current_matrix, current_col); 455 } 456 #endif 457 458 return changed; 459 }