logo

qmk_firmware

custom branch of QMK firmware git clone https://anongit.hacktivis.me/git/qmk_firmware.git

matrix.c (3748B)


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