dip_switch.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /*
  2. * Copyright 2018 Jack Humbert <jack.humb@gmail.com>
  3. * Copyright 2019 Drashna Jaelre (Christopher Courtney) <drashna@live.com>
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <string.h> // for memcpy
  19. #include "dip_switch.h"
  20. #ifdef SPLIT_KEYBOARD
  21. # include "keyboard.h"
  22. # include "split_common/split_util.h"
  23. #endif
  24. #if !defined(DIP_SWITCH_PINS) && !defined(DIP_SWITCH_MATRIX_GRID)
  25. # error "Either DIP_SWITCH_PINS or DIP_SWITCH_MATRIX_GRID must be defined."
  26. #endif
  27. #if defined(DIP_SWITCH_PINS) && defined(DIP_SWITCH_MATRIX_GRID)
  28. # error "Both DIP_SWITCH_PINS and DIP_SWITCH_MATRIX_GRID are defined."
  29. #endif
  30. #ifdef DIP_SWITCH_PINS
  31. static pin_t dip_switch_pad[] = DIP_SWITCH_PINS;
  32. #endif
  33. #ifdef DIP_SWITCH_MATRIX_GRID
  34. static matrix_intersection_t dip_switch_pad[] = DIP_SWITCH_MATRIX_GRID;
  35. extern bool peek_matrix(uint8_t row_index, uint8_t col_index, bool read_raw);
  36. static uint16_t scan_count;
  37. #endif /* DIP_SWITCH_MATRIX_GRID */
  38. static bool dip_switch_state[NUM_DIP_SWITCHES] = {0};
  39. static bool last_dip_switch_state[NUM_DIP_SWITCHES] = {0};
  40. __attribute__((weak)) bool dip_switch_update_user(uint8_t index, bool active) {
  41. return true;
  42. }
  43. __attribute__((weak)) bool dip_switch_update_kb(uint8_t index, bool active) {
  44. return dip_switch_update_user(index, active);
  45. }
  46. __attribute__((weak)) bool dip_switch_update_mask_user(uint32_t state) {
  47. return true;
  48. }
  49. __attribute__((weak)) bool dip_switch_update_mask_kb(uint32_t state) {
  50. return dip_switch_update_mask_user(state);
  51. }
  52. #ifdef DIP_SWITCH_MAP_ENABLE
  53. # include "keymap_introspection.h"
  54. # include "action.h"
  55. # include "wait.h"
  56. # ifndef DIP_SWITCH_MAP_KEY_DELAY
  57. # define DIP_SWITCH_MAP_KEY_DELAY TAP_CODE_DELAY
  58. # endif
  59. static void dip_switch_exec_mapping(uint8_t index, bool on) {
  60. // The delays below cater for Windows and its wonderful requirements.
  61. action_exec(on ? MAKE_DIPSWITCH_ON_EVENT(index, true) : MAKE_DIPSWITCH_OFF_EVENT(index, true));
  62. # if DIP_SWITCH_MAP_KEY_DELAY > 0
  63. wait_ms(DIP_SWITCH_MAP_KEY_DELAY);
  64. # endif // DIP_SWITCH_MAP_KEY_DELAY > 0
  65. action_exec(on ? MAKE_DIPSWITCH_ON_EVENT(index, false) : MAKE_DIPSWITCH_OFF_EVENT(index, false));
  66. # if DIP_SWITCH_MAP_KEY_DELAY > 0
  67. wait_ms(DIP_SWITCH_MAP_KEY_DELAY);
  68. # endif // DIP_SWITCH_MAP_KEY_DELAY > 0
  69. }
  70. #endif // DIP_SWITCH_MAP_ENABLE
  71. void dip_switch_init(void) {
  72. #ifdef DIP_SWITCH_PINS
  73. # if defined(SPLIT_KEYBOARD) && defined(DIP_SWITCH_PINS_RIGHT)
  74. if (!is_keyboard_left()) {
  75. const pin_t dip_switch_pad_right[] = DIP_SWITCH_PINS_RIGHT;
  76. for (uint8_t i = 0; i < NUM_DIP_SWITCHES; i++) {
  77. dip_switch_pad[i] = dip_switch_pad_right[i];
  78. }
  79. }
  80. # endif
  81. for (uint8_t i = 0; i < NUM_DIP_SWITCHES; i++) {
  82. gpio_set_pin_input_high(dip_switch_pad[i]);
  83. }
  84. dip_switch_read(true);
  85. #endif
  86. #ifdef DIP_SWITCH_MATRIX_GRID
  87. scan_count = 0;
  88. #endif
  89. }
  90. void dip_switch_read(bool forced) {
  91. bool has_dip_state_changed = false;
  92. uint32_t dip_switch_mask = 0;
  93. #ifdef DIP_SWITCH_MATRIX_GRID
  94. bool read_raw = false;
  95. if (scan_count < 500) {
  96. scan_count++;
  97. if (scan_count == 10) {
  98. read_raw = true;
  99. forced = true; /* First reading of the dip switch */
  100. } else {
  101. return;
  102. }
  103. }
  104. #endif
  105. for (uint8_t i = 0; i < NUM_DIP_SWITCHES; i++) {
  106. #ifdef DIP_SWITCH_PINS
  107. dip_switch_state[i] = !gpio_read_pin(dip_switch_pad[i]);
  108. #endif
  109. #ifdef DIP_SWITCH_MATRIX_GRID
  110. dip_switch_state[i] = peek_matrix(dip_switch_pad[i].row, dip_switch_pad[i].col, read_raw);
  111. #endif
  112. dip_switch_mask |= dip_switch_state[i] << i;
  113. if (last_dip_switch_state[i] != dip_switch_state[i] || forced) {
  114. has_dip_state_changed = true;
  115. #ifndef DIP_SWITCH_MAP_ENABLE
  116. dip_switch_update_kb(i, dip_switch_state[i]);
  117. #else
  118. dip_switch_exec_mapping(i, dip_switch_state[i]);
  119. #endif
  120. }
  121. }
  122. if (has_dip_state_changed) {
  123. #ifndef DIP_SWITCH_MAP_ENABLE
  124. dip_switch_update_mask_kb(dip_switch_mask);
  125. #endif
  126. memcpy(last_dip_switch_state, dip_switch_state, sizeof(dip_switch_state));
  127. }
  128. }
  129. void dip_switch_task(void) {
  130. dip_switch_read(false);
  131. }