matrix_common.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. #include "matrix.h"
  2. #include "debounce.h"
  3. #include "wait.h"
  4. #include "print.h"
  5. #include "debug.h"
  6. #ifdef SPLIT_KEYBOARD
  7. # include "split_common/split_util.h"
  8. # include "split_common/transactions.h"
  9. # include <string.h>
  10. #endif
  11. #ifndef MATRIX_IO_DELAY
  12. # define MATRIX_IO_DELAY 30
  13. #endif
  14. /* matrix state(1:on, 0:off) */
  15. matrix_row_t raw_matrix[MATRIX_ROWS];
  16. matrix_row_t matrix[MATRIX_ROWS];
  17. #ifdef SPLIT_KEYBOARD
  18. // row offsets for each hand
  19. uint8_t thisHand, thatHand;
  20. #endif
  21. #ifdef MATRIX_MASKED
  22. extern const matrix_row_t matrix_mask[];
  23. #endif
  24. // user-defined overridable functions
  25. __attribute__((weak)) void matrix_init_kb(void) {
  26. matrix_init_user();
  27. }
  28. __attribute__((weak)) void matrix_scan_kb(void) {
  29. matrix_scan_user();
  30. }
  31. __attribute__((weak)) void matrix_init_user(void) {}
  32. __attribute__((weak)) void matrix_scan_user(void) {}
  33. // helper functions
  34. inline uint8_t matrix_rows(void) {
  35. return MATRIX_ROWS;
  36. }
  37. inline uint8_t matrix_cols(void) {
  38. return MATRIX_COLS;
  39. }
  40. inline bool matrix_is_on(uint8_t row, uint8_t col) {
  41. return (matrix[row] & ((matrix_row_t)1 << col));
  42. }
  43. inline matrix_row_t matrix_get_row(uint8_t row) {
  44. // Matrix mask lets you disable switches in the returned matrix data. For example, if you have a
  45. // switch blocker installed and the switch is always pressed.
  46. #ifdef MATRIX_MASKED
  47. return matrix[row] & matrix_mask[row];
  48. #else
  49. return matrix[row];
  50. #endif
  51. }
  52. #if (MATRIX_COLS <= 8)
  53. # define print_matrix_header() print("\nr/c 01234567\n")
  54. # define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
  55. #elif (MATRIX_COLS <= 16)
  56. # define print_matrix_header() print("\nr/c 0123456789ABCDEF\n")
  57. # define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row))
  58. #elif (MATRIX_COLS <= 32)
  59. # define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n")
  60. # define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row))
  61. #endif
  62. void matrix_print(void) {
  63. print_matrix_header();
  64. for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
  65. print_hex8(row);
  66. print(": ");
  67. print_matrix_row(row);
  68. print("\n");
  69. }
  70. }
  71. #ifdef SPLIT_KEYBOARD
  72. bool matrix_post_scan(void) {
  73. bool changed = false;
  74. if (is_keyboard_master()) {
  75. static bool last_connected = false;
  76. matrix_row_t slave_matrix[MATRIX_ROWS_PER_HAND] = {0};
  77. if (transport_master_if_connected(matrix + thisHand, slave_matrix)) {
  78. changed = memcmp(matrix + thatHand, slave_matrix, sizeof(slave_matrix)) != 0;
  79. last_connected = true;
  80. } else if (last_connected) {
  81. // reset other half when disconnected
  82. memset(slave_matrix, 0, sizeof(slave_matrix));
  83. changed = true;
  84. last_connected = false;
  85. }
  86. if (changed) memcpy(matrix + thatHand, slave_matrix, sizeof(slave_matrix));
  87. matrix_scan_kb();
  88. } else {
  89. transport_slave(matrix + thatHand, matrix + thisHand);
  90. matrix_slave_scan_kb();
  91. }
  92. return changed;
  93. }
  94. #endif
  95. /* `matrix_io_delay ()` exists for backwards compatibility. From now on, use matrix_output_unselect_delay(). */
  96. __attribute__((weak)) void matrix_io_delay(void) {
  97. wait_us(MATRIX_IO_DELAY);
  98. }
  99. __attribute__((weak)) void matrix_output_select_delay(void) {
  100. waitInputPinDelay();
  101. }
  102. __attribute__((weak)) void matrix_output_unselect_delay(uint8_t line, bool key_pressed) {
  103. matrix_io_delay();
  104. }
  105. // CUSTOM MATRIX 'LITE'
  106. __attribute__((weak)) void matrix_init_custom(void) {}
  107. __attribute__((weak)) bool matrix_scan_custom(matrix_row_t current_matrix[]) {
  108. return true;
  109. }
  110. #ifdef SPLIT_KEYBOARD
  111. __attribute__((weak)) void matrix_slave_scan_kb(void) {
  112. matrix_slave_scan_user();
  113. }
  114. __attribute__((weak)) void matrix_slave_scan_user(void) {}
  115. #endif
  116. __attribute__((weak)) void matrix_init(void) {
  117. #ifdef SPLIT_KEYBOARD
  118. thisHand = is_keyboard_left() ? 0 : (MATRIX_ROWS_PER_HAND);
  119. thatHand = MATRIX_ROWS_PER_HAND - thisHand;
  120. #endif
  121. matrix_init_custom();
  122. // initialize matrix state: all keys off
  123. for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
  124. raw_matrix[i] = 0;
  125. matrix[i] = 0;
  126. }
  127. debounce_init();
  128. matrix_init_kb();
  129. }
  130. __attribute__((weak)) uint8_t matrix_scan(void) {
  131. bool changed = matrix_scan_custom(raw_matrix);
  132. #ifdef SPLIT_KEYBOARD
  133. changed = debounce(raw_matrix, matrix + thisHand, changed) | matrix_post_scan();
  134. #else
  135. changed = debounce(raw_matrix, matrix, changed);
  136. matrix_scan_kb();
  137. #endif
  138. return changed;
  139. }
  140. __attribute__((weak)) bool peek_matrix(uint8_t row_index, uint8_t col_index, bool raw) {
  141. return 0 != ((raw ? raw_matrix[row_index] : matrix[row_index]) & (MATRIX_ROW_SHIFTER << col_index));
  142. }