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.

116 lines
3.8 KiB

  1. // Copyright 2018-2022 Nick Brassel (@tzarc)
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "quantum.h"
  4. #include <hal_pal.h>
  5. #include "djinn.h"
  6. #define GPIOB_BITMASK (1 << 13 | 1 << 14 | 1 << 15) // B13, B14, B15
  7. #define GPIOB_OFFSET 13
  8. #define GPIOB_COUNT 3
  9. #define GPIOC_BITMASK (1 << 6 | 1 << 7 | 1 << 8) // C6, C7, C8
  10. #define GPIOC_OFFSET 6
  11. // Pin definitions
  12. static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
  13. static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
  14. void matrix_wait_for_pin(pin_t pin, uint8_t target_state) {
  15. rtcnt_t start = chSysGetRealtimeCounterX();
  16. rtcnt_t end = start + 5000;
  17. while (chSysIsCounterWithinX(chSysGetRealtimeCounterX(), start, end)) {
  18. if (readPin(pin) == target_state) {
  19. break;
  20. }
  21. }
  22. }
  23. void matrix_wait_for_port(stm32_gpio_t *port, uint32_t target_bitmask) {
  24. rtcnt_t start = chSysGetRealtimeCounterX();
  25. rtcnt_t end = start + 5000;
  26. while (chSysIsCounterWithinX(chSysGetRealtimeCounterX(), start, end)) {
  27. if ((palReadPort(port) & target_bitmask) == target_bitmask) {
  28. break;
  29. }
  30. }
  31. }
  32. void matrix_init_custom(void) {
  33. for (int i = 0; i < MATRIX_ROWS; ++i) {
  34. setPinInputHigh(row_pins[i]);
  35. }
  36. for (int i = 0; i < MATRIX_COLS; ++i) {
  37. setPinInputHigh(col_pins[i]);
  38. }
  39. }
  40. bool matrix_scan_custom(matrix_row_t current_matrix[]) {
  41. static matrix_row_t temp_matrix[MATRIX_ROWS] = {0};
  42. for (int current_col = 0; current_col < MATRIX_COLS; ++current_col) {
  43. // Keep track of the pin we're working with
  44. pin_t curr_col_pin = col_pins[current_col];
  45. // Setup the output column pin
  46. setPinOutput(curr_col_pin);
  47. writePinLow(curr_col_pin);
  48. matrix_wait_for_pin(curr_col_pin, 0);
  49. // Read the row ports
  50. uint32_t gpio_b = palReadPort(GPIOB);
  51. uint32_t gpio_c = palReadPort(GPIOC);
  52. // Unselect the row pin
  53. setPinInputHigh(curr_col_pin);
  54. // Construct the packed bitmask for the pins
  55. uint32_t readback = ~(((gpio_b & GPIOB_BITMASK) >> GPIOB_OFFSET) | (((gpio_c & GPIOC_BITMASK) >> GPIOC_OFFSET) << GPIOB_COUNT));
  56. // Inject values into the matrix
  57. for (int i = 0; i < MATRIX_ROWS; ++i) {
  58. if (readback & (1 << i)) {
  59. temp_matrix[i] |= (1ul << current_col);
  60. } else {
  61. temp_matrix[i] &= ~(1ul << current_col);
  62. }
  63. }
  64. // Wait for readback of the unselected column to go high
  65. matrix_wait_for_pin(curr_col_pin, 1);
  66. // Wait for readback of each port to go high -- unselecting the row would have been completed
  67. matrix_wait_for_port(GPIOB, GPIOB_BITMASK);
  68. matrix_wait_for_port(GPIOC, GPIOC_BITMASK);
  69. }
  70. // Check if we've changed, return the last-read data
  71. bool changed = memcmp(current_matrix, temp_matrix, sizeof(temp_matrix)) != 0;
  72. if (changed) {
  73. memcpy(current_matrix, temp_matrix, sizeof(temp_matrix));
  74. }
  75. return changed;
  76. }
  77. void matrix_wait_for_interrupt(void) {
  78. // Set up row/col pins and attach callback
  79. for (int i = 0; i < sizeof(col_pins) / sizeof(pin_t); ++i) {
  80. setPinOutput(col_pins[i]);
  81. writePinLow(col_pins[i]);
  82. }
  83. for (int i = 0; i < sizeof(row_pins) / sizeof(pin_t); ++i) {
  84. setPinInputHigh(row_pins[i]);
  85. palEnableLineEvent(row_pins[i], PAL_EVENT_MODE_BOTH_EDGES);
  86. }
  87. // Wait for an interrupt
  88. __WFI();
  89. // Now that the interrupt has woken us up, reset all the row/col pins back to defaults
  90. for (int i = 0; i < sizeof(row_pins) / sizeof(pin_t); ++i) {
  91. palDisableLineEvent(row_pins[i]);
  92. writePinHigh(row_pins[i]);
  93. setPinInputHigh(row_pins[i]);
  94. }
  95. for (int i = 0; i < sizeof(col_pins) / sizeof(pin_t); ++i) {
  96. writePinHigh(col_pins[i]);
  97. setPinInputHigh(col_pins[i]);
  98. }
  99. }