logo

qmk_firmware

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

matrix.c (7100B)


  1. /*
  2. Copyright 2021 mtei
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. // clang-format off
  15. #ifndef readPort
  16. # include "gpio_extr.h"
  17. #endif
  18. #include "atomic_util.h"
  19. #include "util.h"
  20. #include "matrix.h"
  21. #include "matrix_extr.h"
  22. #include "debounce.h"
  23. #define ALWAYS_INLINE inline __attribute__((always_inline))
  24. #define NO_INLINE __attribute__((noinline))
  25. #define LOCAL_FUNC static
  26. #define LOCAL_DATA static
  27. #ifndef _BV
  28. # define _BV(bit) (1 << (bit))
  29. #endif
  30. #ifndef MATRIX_DEBUG_PIN
  31. # define MATRIX_DEBUG_PIN_INIT()
  32. # define MATRIX_DEBUG_SCAN_START()
  33. # define MATRIX_DEBUG_SCAN_END()
  34. # define MATRIX_DEBUG_DELAY_START()
  35. # define MATRIX_DEBUG_DELAY_END()
  36. # define MATRIX_DEBUG_GAP()
  37. #else
  38. # define MATRIX_DEBUG_GAP() asm volatile("nop \n nop":::"memory")
  39. #endif
  40. typedef uint16_t port_width_t;
  41. #if MATRIX_TYPE == DIRECT_SWITCH || MATRIX_TYPE == DIODE_COL2ROW
  42. # define MATRIX_LINES MATRIX_ROWS
  43. typedef matrix_row_t matrix_line_t;
  44. #endif
  45. #if MATRIX_TYPE == DIODE_ROW2COL
  46. # define MATRIX_LINES MATRIX_COLS
  47. typedef matrix_col_t matrix_line_t;
  48. #endif
  49. typedef struct _port_descriptor {
  50. int device;
  51. pin_t port;
  52. } port_descriptor;
  53. /* matrix state(1:on, 0:off) */
  54. extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values
  55. extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values
  56. #define setPortBitOutput_writeLow(port, bit) \
  57. do { setPortBitOutput(port, bit); writePortBitLow(port, bit); } while(0)
  58. #define setPortBitOutput_writeLow_atomic(port, bit) \
  59. do { ATOMIC_BLOCK_FORCEON { setPortBitOutput_writeLow(port, bit); } } while(0)
  60. #define setPortBitInputHigh_atomic(port, bit) \
  61. do { ATOMIC_BLOCK_FORCEON { setPortBitInputHigh(port, bit); } } while(0)
  62. #if defined(MATRIX_IN_PORTS) && defined(MATRIX_IN_PINS)
  63. # include "matrix_config_expand.c"
  64. #else
  65. # error matrix.c need defined MATRIX_IN_PORTS and MATRIX_IN_PINS
  66. #endif
  67. LOCAL_FUNC
  68. void unselect_output(uint8_t out_index) {
  69. unselect_output_inline(out_index);
  70. }
  71. LOCAL_FUNC
  72. void init_output_ports(void) {
  73. for (int i = 0; i < END_outpin_index; i++) {
  74. unselect_output(i);
  75. }
  76. }
  77. LOCAL_FUNC
  78. void init_all_ports(void) {
  79. init_input_ports();
  80. init_output_ports();
  81. init_inport_mask();
  82. init_extension();
  83. }
  84. LOCAL_FUNC ALWAYS_INLINE void select_line_and_read_input_ports(uint8_t current_line, port_width_t port_buffer[NUM_OF_INPUT_PORTS]);
  85. LOCAL_FUNC void select_line_and_read_input_ports(uint8_t current_line, port_width_t port_buffer[NUM_OF_INPUT_PORTS]) {
  86. // Select row (or col)
  87. select_output(current_line);
  88. matrix_output_select_delay();
  89. // Read ports
  90. read_all_input_ports(port_buffer, false);
  91. // Unselect row (or col)
  92. unselect_output_inline(current_line);
  93. }
  94. LOCAL_FUNC ALWAYS_INLINE void read_matrix_line(matrix_line_t phy_matrix[], uint8_t current_line);
  95. #if MATRIX_TYPE == DIODE_ROW2COL || MATRIX_TYPE == DIODE_COL2ROW
  96. LOCAL_FUNC void read_matrix_line(matrix_line_t phy_matrix[], uint8_t current_line) {
  97. // Start with a clear matrix row
  98. matrix_line_t current_line_value = 0;
  99. port_width_t port_buffer[NUM_OF_INPUT_PORTS];
  100. #ifdef MATRIX_GPIO_NEED_SEPARATE_ATOMIC
  101. select_line_and_read_input_ports(current_line, port_buffer);
  102. #else
  103. ATOMIC_BLOCK_FORCEON {
  104. select_line_and_read_input_ports(current_line, port_buffer);
  105. }
  106. #endif
  107. // Build row (or col)
  108. current_line_value = build_matrix_line(port_buffer);
  109. // Wait signal raise up
  110. if (current_line_value) {
  111. MATRIX_DEBUG_DELAY_START();
  112. wait_unselect_done();
  113. MATRIX_DEBUG_DELAY_END();
  114. }
  115. phy_matrix[current_line] = current_line_value;
  116. }
  117. #endif // MATRIX_TYPE == DIODE_ROW2COL || MATRIX_TYPE == DIODE_COL2ROW
  118. #if MATRIX_TYPE == DIRECT_SWITCH
  119. LOCAL_FUNC void read_matrix_line(matrix_line_t phy_matrix[], uint8_t current_line) {
  120. port_width_t port_buffer[NUM_OF_INPUT_PORTS];
  121. if (current_line != 0) {
  122. return;
  123. }
  124. for (uint8_t i = 0; i < MATRIX_LINES; i++) {
  125. phy_matrix[i] = 0;
  126. }
  127. read_all_input_ports(port_buffer, false);
  128. // Build matrix
  129. build_matrix_direct(port_buffer, phy_matrix);
  130. }
  131. #endif // MATRIX_TYPE == DIRECT_SWITCH
  132. void matrix_init(void) {
  133. // initialize key pins
  134. init_all_ports();
  135. // initialize matrix state: all keys off
  136. for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
  137. raw_matrix[i] = 0;
  138. matrix[i] = 0;
  139. }
  140. debounce_init(MATRIX_ROWS);
  141. matrix_init_kb();
  142. }
  143. uint8_t matrix_scan(void) {
  144. matrix_line_t phy_matrix[MATRIX_LINES];
  145. MATRIX_DEBUG_PIN_INIT();
  146. MATRIX_DEBUG_SCAN_START();
  147. // read I/O port to phy_matrix[] (physical matrix)
  148. //select line, read inputs
  149. for (uint8_t current_line = 0; current_line < MATRIX_LINES; current_line++) {
  150. read_matrix_line(phy_matrix, current_line);
  151. }
  152. MATRIX_DEBUG_SCAN_END(); MATRIX_DEBUG_GAP(); MATRIX_DEBUG_SCAN_START();
  153. bool changed = false;
  154. #if MATRIX_TYPE == DIRECT_SWITCH || MATRIX_TYPE == DIODE_COL2ROW
  155. // copy phy_matrix[] to raw_matrix[]
  156. for (uint8_t current_line = 0; current_line < MATRIX_ROWS; current_line++) {
  157. if (raw_matrix[current_line] != phy_matrix[current_line]) {
  158. changed = true;
  159. raw_matrix[current_line] = phy_matrix[current_line];
  160. }
  161. }
  162. #endif
  163. #if MATRIX_TYPE == DIODE_ROW2COL
  164. // transpose phy_matrix[] to raw_matrix[]
  165. matrix_row_t trans_matrix[MATRIX_ROWS];
  166. for (uint8_t i = 0; i < MATRIX_ROWS; i++ ) {
  167. trans_matrix[i] = 0;
  168. }
  169. for (uint8_t src_line = 0; src_line < MATRIX_LINES; src_line++) {
  170. matrix_line_t src_line_data = phy_matrix[src_line];
  171. matrix_row_t dist_bit = MATRIX_ROW_SHIFTER << src_line;
  172. for (uint8_t dist_rows = 0; dist_rows < MATRIX_ROWS; dist_rows++) {
  173. if ((src_line_data & 1) == 1) {
  174. trans_matrix[dist_rows] |= dist_bit;
  175. }
  176. src_line_data >>= 1;
  177. }
  178. }
  179. for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
  180. if (raw_matrix[current_row] != trans_matrix[current_row]) {
  181. changed = true;
  182. raw_matrix[current_row] = trans_matrix[current_row];
  183. }
  184. }
  185. #endif
  186. MATRIX_DEBUG_SCAN_END(); MATRIX_DEBUG_GAP(); MATRIX_DEBUG_SCAN_START();
  187. // debounce raw_matrix[] to matrix[]
  188. debounce(raw_matrix, matrix, MATRIX_ROWS, changed);
  189. MATRIX_DEBUG_SCAN_END(); MATRIX_DEBUG_GAP();
  190. MATRIX_DEBUG_SCAN_START();
  191. matrix_scan_kb();
  192. MATRIX_DEBUG_SCAN_END();
  193. return (uint8_t)changed;
  194. }