logo

qmk_firmware

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

djinn_portscan_matrix.c (4224B)


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