matrix.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /* Copyright 2022
  2. *
  3. * This program is free software: you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation, either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include "matrix.h"
  17. #include "gpio.h"
  18. #include "sn74x154.h"
  19. static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
  20. /* All columns use a 74HC154 4-to-16 demultiplexer.
  21. * D3 is the enable pin, must be set high to use it.
  22. *
  23. * A3 A2 A1 A0
  24. * D7 D6 D5 D4
  25. * 0: 0 0 0 0
  26. * 1: 0 0 0 1
  27. * 2: 0 0 1 0
  28. * 3: 0 0 1 1
  29. * 4: 0 1 0 0
  30. * 5: 0 1 0 1
  31. * 6: 0 1 1 0
  32. * 7: 0 1 1 1
  33. * 8: 1 0 0 0
  34. * 9: 1 0 0 1
  35. * 10: 1 0 1 0
  36. * 11: 1 0 1 1
  37. * 12: 1 1 0 0
  38. * 13: 1 1 0 1
  39. * 14: 1 1 1 0
  40. * 15: 1 1 1 1
  41. */
  42. static void select_col(uint8_t col) {
  43. sn74x154_set_addr(col);
  44. }
  45. static void init_pins(void) {
  46. for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
  47. setPinInputHigh(row_pins[x]);
  48. }
  49. }
  50. static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {
  51. bool matrix_changed = false;
  52. // Select col and wait for col seleciton to stabilize
  53. select_col(current_col);
  54. matrix_io_delay();
  55. // For each row...
  56. for (uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) {
  57. // Store last value of row prior to reading
  58. matrix_row_t last_row_value = current_matrix[row_index];
  59. // Check row pin state
  60. if (readPin(row_pins[row_index]) == 0) {
  61. // Pin LO, set col bit
  62. current_matrix[row_index] |= (MATRIX_ROW_SHIFTER << current_col);
  63. } else {
  64. // Pin HI, clear col bit
  65. current_matrix[row_index] &= ~(MATRIX_ROW_SHIFTER << current_col);
  66. }
  67. // Determine if the matrix changed state
  68. if ((last_row_value != current_matrix[row_index]) && !(matrix_changed)) {
  69. matrix_changed = true;
  70. }
  71. }
  72. return matrix_changed;
  73. }
  74. void matrix_init_custom(void) {
  75. // initialize demultiplexer
  76. sn74x154_init();
  77. sn74x154_set_enabled(true);
  78. // initialize key pins
  79. init_pins();
  80. }
  81. bool matrix_scan_custom(matrix_row_t current_matrix[]) {
  82. bool changed = false;
  83. // Set col, read rows
  84. for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
  85. changed |= read_rows_on_col(current_matrix, current_col);
  86. }
  87. return changed;
  88. }