You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

137 lines
3.7 KiB

  1. // Copyright 2022 @sadekbaroudi (Sadek Baroudi)
  2. // Copyright 2023 @jasonhazel (Jason Hazel)
  3. // SPDX-License-Identifier: GPL-3.0-or-later
  4. #include "quantum.h"
  5. #include "spi_master.h"
  6. #include <string.h> /* memset */
  7. #include <unistd.h> /* close */
  8. #include "quantum.h"
  9. #include "matrix.h"
  10. #if (!defined(SHIFTREG_MATRIX_COL_CS))
  11. # error Missing shift register I/O pin definitions
  12. #endif
  13. int matrixArraySize = SHIFTREG_ROWS * sizeof(matrix_row_t);
  14. matrix_row_t oldMatrix[SHIFTREG_ROWS];
  15. #define SHIFTREG_OUTPUT_BITS 8
  16. pin_t rowPinsSR[SHIFTREG_ROWS] = MATRIX_ROW_PINS_SR;
  17. // semaphore to make sure SPI doesn't get called multiple times
  18. static bool shiftRegisterSPILocked = false;
  19. void semaphore_lock(bool value) {
  20. shiftRegisterSPILocked = value;
  21. }
  22. bool semaphore_is_locked(void) {
  23. return shiftRegisterSPILocked;
  24. }
  25. void sr_74hc595_spi_stop(void) {
  26. spi_stop();
  27. semaphore_lock(false);
  28. }
  29. bool sr_74hc595_spi_start(void) {
  30. if (!spi_start(SHIFTREG_MATRIX_COL_CS, false, 0, SHIFTREG_DIVISOR)) {
  31. dprintf("74hc595 matrix: failed to start spi\n");
  32. sr_74hc595_spi_stop();
  33. return false;
  34. }
  35. semaphore_lock(true);
  36. wait_us(1); // not sure if I need this
  37. return true;
  38. }
  39. bool sr_74hc595_spi_send_byte(uint8_t data) {
  40. sr_74hc595_spi_start();
  41. writePinLow(SHIFTREG_MATRIX_COL_CS);
  42. matrix_io_delay();
  43. spi_write(data);
  44. matrix_io_delay();
  45. gpio_write_pin_high(SHIFTREG_MATRIX_COL_CS);
  46. sr_74hc595_spi_stop();
  47. return true;
  48. }
  49. /**
  50. * Set the entire shift register to be full of inactive bits
  51. */
  52. void clearColumns(void) {
  53. uint8_t value = 0b00000000;
  54. sr_74hc595_spi_send_byte(value);
  55. }
  56. void setColumn(int columnShift, bool test_run) {
  57. uint8_t columnShiftByte = ((uint8_t)1 << columnShift);
  58. if(test_run) {
  59. dprintf("byte sent: %d\n", columnShiftByte);
  60. }
  61. sr_74hc595_spi_send_byte(columnShiftByte);
  62. }
  63. /*
  64. * override of the qmk intialization function
  65. */
  66. void matrix_init_custom(void) {
  67. wait_ms(300);
  68. spi_init();
  69. // Set up the initial states for all the row pins
  70. for (int r = 0; r < SHIFTREG_ROWS; r++) {
  71. // Note: This needs to use the internal pull down resistors, and atmegas do *not* support that
  72. setPinInputLow(rowPinsSR[r]);
  73. }
  74. // Set the CS to low by default, and specify as an output pin
  75. gpio_write_pin_high(SHIFTREG_MATRIX_COL_CS); // should be high when using SPI?
  76. setPinOutput(SHIFTREG_MATRIX_COL_CS);
  77. // Since it's the init, deactivate all the columns. We'll activate once we get to the matrix scan
  78. clearColumns();
  79. }
  80. bool matrix_scan_custom(matrix_row_t current_matrix[]) {
  81. // respect the semaphore
  82. if (semaphore_is_locked()) {
  83. return false;
  84. }
  85. // Keep track of if something was modified
  86. bool matrix_has_changed = false;
  87. // reset the current matrix, as we'll be updating and comparing to the old matrix
  88. memset(current_matrix, 0, matrixArraySize);
  89. bool debug_output = false;
  90. // Loop through the columns, activating one at a time, and read the rows, and place in the new current_matrix
  91. for (int c = 0; c < SHIFTREG_COLS; c++) {
  92. if (debug_output) {
  93. dprintf("column iteration: %d\n", c);
  94. }
  95. setColumn(c, debug_output);
  96. matrix_io_delay();
  97. for (int r = 0; r < SHIFTREG_ROWS; r++) {
  98. current_matrix[r] |= ((gpio_read_pin(rowPinsSR[r]) ? 1 : 0) << c);
  99. }
  100. }
  101. matrix_has_changed = memcmp(current_matrix, oldMatrix, matrixArraySize) != 0;
  102. memcpy(oldMatrix, current_matrix, matrixArraySize);
  103. if (matrix_has_changed) {
  104. matrix_print();
  105. }
  106. // Deactivate all the columns for the next run.
  107. clearColumns();
  108. matrix_io_delay();
  109. return matrix_has_changed;
  110. }