logo

qmk_firmware

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

matrix.c (10467B)


  1. /*
  2. Copyright 2012-2018 Jun Wako, Jack Humbert, Yiancar
  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. #include <stdint.h>
  15. #include <stdbool.h>
  16. #include <string.h>
  17. #include "util.h"
  18. #include "matrix.h"
  19. #include "debounce.h"
  20. #include "atomic_util.h"
  21. #ifdef SPLIT_KEYBOARD
  22. # include "split_common/split_util.h"
  23. # include "split_common/transactions.h"
  24. # define ROWS_PER_HAND (MATRIX_ROWS / 2)
  25. #else
  26. # define ROWS_PER_HAND (MATRIX_ROWS)
  27. #endif
  28. #ifdef DIRECT_PINS_RIGHT
  29. # define SPLIT_MUTABLE
  30. #else
  31. # define SPLIT_MUTABLE const
  32. #endif
  33. #ifdef MATRIX_ROW_PINS_RIGHT
  34. # define SPLIT_MUTABLE_ROW
  35. #else
  36. # define SPLIT_MUTABLE_ROW const
  37. #endif
  38. #ifdef MATRIX_COL_PINS_RIGHT
  39. # define SPLIT_MUTABLE_COL
  40. #else
  41. # define SPLIT_MUTABLE_COL const
  42. #endif
  43. #ifndef MATRIX_INPUT_PRESSED_STATE
  44. # define MATRIX_INPUT_PRESSED_STATE 0
  45. #endif
  46. #ifdef DIRECT_PINS
  47. static SPLIT_MUTABLE pin_t direct_pins[ROWS_PER_HAND][MATRIX_COLS] = DIRECT_PINS;
  48. #elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW)
  49. # ifdef MATRIX_ROW_PINS
  50. static SPLIT_MUTABLE_ROW pin_t row_pins[ROWS_PER_HAND] = MATRIX_ROW_PINS;
  51. # endif // MATRIX_ROW_PINS
  52. # ifdef MATRIX_COL_PINS
  53. static SPLIT_MUTABLE_COL pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
  54. # endif // MATRIX_COL_PINS
  55. #endif
  56. /* matrix state(1:on, 0:off) */
  57. extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values
  58. extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values
  59. #ifdef SPLIT_KEYBOARD
  60. // row offsets for each hand
  61. extern uint8_t thisHand, thatHand;
  62. #endif
  63. // user-defined overridable functions
  64. __attribute__((weak)) void matrix_init_pins(void);
  65. __attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row);
  66. __attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col, matrix_row_t row_shifter);
  67. static inline void gpio_atomic_set_pin_output_low(pin_t pin) {
  68. ATOMIC_BLOCK_FORCEON {
  69. gpio_set_pin_output(pin);
  70. gpio_write_pin_low(pin);
  71. }
  72. }
  73. static inline void gpio_atomic_set_pin_output_high(pin_t pin) {
  74. ATOMIC_BLOCK_FORCEON {
  75. gpio_set_pin_output(pin);
  76. gpio_write_pin_high(pin);
  77. }
  78. }
  79. static inline void gpio_atomic_set_pin_input_high(pin_t pin) {
  80. ATOMIC_BLOCK_FORCEON {
  81. gpio_set_pin_input_high(pin);
  82. }
  83. }
  84. static inline uint8_t readMatrixPin(pin_t pin) {
  85. if (pin != NO_PIN) {
  86. return (gpio_read_pin(pin) == MATRIX_INPUT_PRESSED_STATE) ? 0 : 1;
  87. } else {
  88. return 1;
  89. }
  90. }
  91. // matrix code
  92. #ifdef DIRECT_PINS
  93. __attribute__((weak)) void matrix_init_pins(void) {
  94. for (int row = 0; row < ROWS_PER_HAND; row++) {
  95. for (int col = 0; col < MATRIX_COLS; col++) {
  96. pin_t pin = direct_pins[row][col];
  97. if (pin != NO_PIN) {
  98. gpio_set_pin_input_high(pin);
  99. }
  100. }
  101. }
  102. }
  103. __attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
  104. // Start with a clear matrix row
  105. matrix_row_t current_row_value = 0;
  106. matrix_row_t row_shifter = MATRIX_ROW_SHIFTER;
  107. for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++, row_shifter <<= 1) {
  108. pin_t pin = direct_pins[current_row][col_index];
  109. current_row_value |= readMatrixPin(pin) ? 0 : row_shifter;
  110. }
  111. // Update the matrix
  112. current_matrix[current_row] = current_row_value;
  113. }
  114. #elif defined(DIODE_DIRECTION)
  115. # if defined(MATRIX_ROW_PINS) && defined(MATRIX_COL_PINS)
  116. # if (DIODE_DIRECTION == COL2ROW)
  117. static bool select_row(uint8_t row) {
  118. pin_t pin = row_pins[row];
  119. if (pin != NO_PIN) {
  120. gpio_atomic_set_pin_output_low(pin);
  121. return true;
  122. }
  123. return false;
  124. }
  125. static void unselect_row(uint8_t row) {
  126. pin_t pin = row_pins[row];
  127. if (pin != NO_PIN) {
  128. # ifdef MATRIX_UNSELECT_DRIVE_HIGH
  129. gpio_atomic_set_pin_output_high(pin);
  130. # else
  131. gpio_atomic_set_pin_input_high(pin);
  132. # endif
  133. }
  134. }
  135. static void unselect_rows(void) {
  136. for (uint8_t x = 0; x < ROWS_PER_HAND; x++) {
  137. unselect_row(x);
  138. }
  139. }
  140. __attribute__((weak)) void matrix_init_pins(void) {
  141. unselect_rows();
  142. for (uint8_t x = 0; x < MATRIX_COLS; x++) {
  143. if (col_pins[x] != NO_PIN) {
  144. gpio_atomic_set_pin_input_high(col_pins[x]);
  145. }
  146. }
  147. }
  148. __attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
  149. // Start with a clear matrix row
  150. matrix_row_t current_row_value = 0;
  151. if (!select_row(current_row)) { // Select row
  152. return; // skip NO_PIN row
  153. }
  154. matrix_output_select_delay();
  155. // For each col...
  156. matrix_row_t row_shifter = MATRIX_ROW_SHIFTER;
  157. for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++, row_shifter <<= 1) {
  158. uint8_t pin_state = readMatrixPin(col_pins[col_index]);
  159. // Populate the matrix row with the state of the col pin
  160. current_row_value |= pin_state ? 0 : row_shifter;
  161. }
  162. // Unselect row
  163. unselect_row(current_row);
  164. matrix_output_unselect_delay(current_row, current_row_value != 0); // wait for all Col signals to go HIGH
  165. // Update the matrix
  166. current_matrix[current_row] = current_row_value;
  167. }
  168. # elif (DIODE_DIRECTION == ROW2COL)
  169. static bool select_col(uint8_t col) {
  170. pin_t pin = col_pins[col];
  171. if (pin != NO_PIN) {
  172. gpio_atomic_set_pin_output_low(pin);
  173. return true;
  174. }
  175. return false;
  176. }
  177. static void unselect_col(uint8_t col) {
  178. pin_t pin = col_pins[col];
  179. if (pin != NO_PIN) {
  180. # ifdef MATRIX_UNSELECT_DRIVE_HIGH
  181. gpio_atomic_set_pin_output_high(pin);
  182. # else
  183. gpio_atomic_set_pin_input_high(pin);
  184. # endif
  185. }
  186. }
  187. static void unselect_cols(void) {
  188. for (uint8_t x = 0; x < MATRIX_COLS; x++) {
  189. unselect_col(x);
  190. }
  191. }
  192. __attribute__((weak)) void matrix_init_pins(void) {
  193. unselect_cols();
  194. for (uint8_t x = 0; x < ROWS_PER_HAND; x++) {
  195. if (row_pins[x] != NO_PIN) {
  196. gpio_atomic_set_pin_input_high(row_pins[x]);
  197. }
  198. }
  199. }
  200. __attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col, matrix_row_t row_shifter) {
  201. bool key_pressed = false;
  202. // Select col
  203. if (!select_col(current_col)) { // select col
  204. return; // skip NO_PIN col
  205. }
  206. matrix_output_select_delay();
  207. // For each row...
  208. for (uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++) {
  209. // Check row pin state
  210. if (readMatrixPin(row_pins[row_index]) == 0) {
  211. // Pin LO, set col bit
  212. current_matrix[row_index] |= row_shifter;
  213. key_pressed = true;
  214. } else {
  215. // Pin HI, clear col bit
  216. current_matrix[row_index] &= ~row_shifter;
  217. }
  218. }
  219. // Unselect col
  220. unselect_col(current_col);
  221. matrix_output_unselect_delay(current_col, key_pressed); // wait for all Row signals to go HIGH
  222. }
  223. # else
  224. # error DIODE_DIRECTION must be one of COL2ROW or ROW2COL!
  225. # endif
  226. # endif // defined(MATRIX_ROW_PINS) && defined(MATRIX_COL_PINS)
  227. #else
  228. # error DIODE_DIRECTION is not defined!
  229. #endif
  230. void matrix_init(void) {
  231. #ifdef SPLIT_KEYBOARD
  232. // Set pinout for right half if pinout for that half is defined
  233. if (!isLeftHand) {
  234. # ifdef DIRECT_PINS_RIGHT
  235. const pin_t direct_pins_right[ROWS_PER_HAND][MATRIX_COLS] = DIRECT_PINS_RIGHT;
  236. for (uint8_t i = 0; i < ROWS_PER_HAND; i++) {
  237. for (uint8_t j = 0; j < MATRIX_COLS; j++) {
  238. direct_pins[i][j] = direct_pins_right[i][j];
  239. }
  240. }
  241. # endif
  242. # ifdef MATRIX_ROW_PINS_RIGHT
  243. const pin_t row_pins_right[ROWS_PER_HAND] = MATRIX_ROW_PINS_RIGHT;
  244. for (uint8_t i = 0; i < ROWS_PER_HAND; i++) {
  245. row_pins[i] = row_pins_right[i];
  246. }
  247. # endif
  248. # ifdef MATRIX_COL_PINS_RIGHT
  249. const pin_t col_pins_right[MATRIX_COLS] = MATRIX_COL_PINS_RIGHT;
  250. for (uint8_t i = 0; i < MATRIX_COLS; i++) {
  251. col_pins[i] = col_pins_right[i];
  252. }
  253. # endif
  254. }
  255. thisHand = isLeftHand ? 0 : (ROWS_PER_HAND);
  256. thatHand = ROWS_PER_HAND - thisHand;
  257. #endif
  258. // initialize key pins
  259. matrix_init_pins();
  260. // initialize matrix state: all keys off
  261. memset(matrix, 0, sizeof(matrix));
  262. memset(raw_matrix, 0, sizeof(raw_matrix));
  263. debounce_init(ROWS_PER_HAND);
  264. matrix_init_kb();
  265. }
  266. #ifdef SPLIT_KEYBOARD
  267. // Fallback implementation for keyboards not using the standard split_util.c
  268. __attribute__((weak)) bool transport_master_if_connected(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
  269. transport_master(master_matrix, slave_matrix);
  270. return true; // Treat the transport as always connected
  271. }
  272. #endif
  273. uint8_t matrix_scan(void) {
  274. matrix_row_t curr_matrix[MATRIX_ROWS] = {0};
  275. #if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW)
  276. // Set row, read cols
  277. for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) {
  278. matrix_read_cols_on_row(curr_matrix, current_row);
  279. }
  280. #elif (DIODE_DIRECTION == ROW2COL)
  281. // Set col, read rows
  282. matrix_row_t row_shifter = MATRIX_ROW_SHIFTER;
  283. for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++, row_shifter <<= 1) {
  284. matrix_read_rows_on_col(curr_matrix, current_col, row_shifter);
  285. }
  286. #endif
  287. bool changed = memcmp(raw_matrix, curr_matrix, sizeof(curr_matrix)) != 0;
  288. if (changed) memcpy(raw_matrix, curr_matrix, sizeof(curr_matrix));
  289. #ifdef SPLIT_KEYBOARD
  290. changed = debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, changed) | matrix_post_scan();
  291. #else
  292. changed = debounce(raw_matrix, matrix, ROWS_PER_HAND, changed);
  293. matrix_scan_kb();
  294. #endif
  295. return (uint8_t)changed;
  296. }