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.

344 lines
8.5 KiB

  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 "wait.h"
  17. #include "util.h"
  18. #include "matrix.h"
  19. #include "debounce.h"
  20. #include "quantum.h"
  21. #ifdef DIRECT_PINS
  22. static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS;
  23. #elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW)
  24. static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
  25. //static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
  26. #endif
  27. // matrix code
  28. #ifdef DIRECT_PINS
  29. static void init_pins(void) {
  30. for (int row = 0; row < MATRIX_ROWS; row++) {
  31. for (int col = 0; col < MATRIX_COLS; col++) {
  32. pin_t pin = direct_pins[row][col];
  33. if (pin != NO_PIN) {
  34. setPinInputHigh(pin);
  35. }
  36. }
  37. }
  38. }
  39. static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
  40. matrix_row_t last_row_value = current_matrix[current_row];
  41. current_matrix[current_row] = 0;
  42. for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
  43. pin_t pin = direct_pins[current_row][col_index];
  44. if (pin != NO_PIN) {
  45. current_matrix[current_row] |= readPin(pin) ? 0 : (MATRIX_ROW_SHIFTER << col_index);
  46. }
  47. }
  48. return (last_row_value != current_matrix[current_row]);
  49. }
  50. #elif (DIODE_DIRECTION == COL2ROW)
  51. static void select_row(uint8_t row) {
  52. setPinOutput(row_pins[row]);
  53. writePinLow(row_pins[row]);
  54. }
  55. static void unselect_row(uint8_t row) { setPinInputHigh(row_pins[row]); }
  56. static void unselect_rows(void) {
  57. for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
  58. setPinInputHigh(row_pins[x]);
  59. }
  60. }
  61. static void init_pins(void) {
  62. unselect_rows();
  63. for (uint8_t x = 0; x < MATRIX_COLS; x++) {
  64. setPinInputHigh(col_pins[x]);
  65. }
  66. }
  67. static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
  68. // Store last value of row prior to reading
  69. matrix_row_t last_row_value = current_matrix[current_row];
  70. // Clear data in matrix row
  71. current_matrix[current_row] = 0;
  72. // Select row and wait for row selecton to stabilize
  73. select_row(current_row);
  74. wait_us(30);
  75. // For each col...
  76. for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
  77. // Select the col pin to read (active low)
  78. uint8_t pin_state = readPin(col_pins[col_index]);
  79. // Populate the matrix row with the state of the col pin
  80. current_matrix[current_row] |= pin_state ? 0 : (MATRIX_ROW_SHIFTER << col_index);
  81. }
  82. // Unselect row
  83. unselect_row(current_row);
  84. return (last_row_value != current_matrix[current_row]);
  85. }
  86. #elif (DIODE_DIRECTION == ROW2COL)
  87. /* Cols 0 - 15
  88. * col 0: C7
  89. * col 1: B6
  90. * col 2: C6
  91. * col 3: B4
  92. * col 4: B5
  93. * col 5: D7
  94. * These columns use a 74HC237D 3 to 8 bit demultiplexer.
  95. * A0 A1 A2
  96. * col / pin: PD2 PD1 PD0
  97. * 6: 1 1 1
  98. * 7: 0 1 1
  99. * 8: 1 0 1
  100. * 9: 0 0 1
  101. * 10: 1 1 0
  102. * 11: 0 1 0
  103. * 12: 1 0 0
  104. * col 13: D3
  105. * col 14: B7
  106. * col 15: B3
  107. */
  108. static void select_col(uint8_t col) {
  109. switch (col) {
  110. case 0:
  111. writePinLow(C7);
  112. break;
  113. case 1:
  114. writePinLow(B6);
  115. break;
  116. case 2:
  117. writePinLow(C6);
  118. break;
  119. case 3:
  120. writePinLow(B4);
  121. break;
  122. case 4:
  123. writePinLow(B5);
  124. break;
  125. case 5:
  126. writePinLow(D7);
  127. break;
  128. case 6:
  129. writePinHigh(D0);
  130. writePinHigh(D1);
  131. writePinHigh(D2);
  132. break;
  133. case 7:
  134. writePinHigh(D0);
  135. writePinHigh(D1);
  136. break;
  137. case 8:
  138. writePinHigh(D0);
  139. writePinHigh(D2);
  140. break;
  141. case 9:
  142. writePinHigh(D0);
  143. break;
  144. case 10:
  145. writePinHigh(D1);
  146. writePinHigh(D2);
  147. break;
  148. case 11:
  149. writePinHigh(D1);
  150. break;
  151. case 12:
  152. writePinHigh(D2);
  153. break;
  154. case 13:
  155. writePinLow(D3);
  156. break;
  157. case 14:
  158. writePinLow(B7);
  159. break;
  160. case 15:
  161. writePinLow(B3);
  162. break;
  163. }
  164. }
  165. static void unselect_col(uint8_t col) {
  166. switch (col) {
  167. case 0:
  168. writePinHigh(C7);
  169. break;
  170. case 1:
  171. writePinHigh(B6);
  172. break;
  173. case 2:
  174. writePinHigh(C6);
  175. break;
  176. case 3:
  177. writePinHigh(B4);
  178. break;
  179. case 4:
  180. writePinHigh(B5);
  181. break;
  182. case 5:
  183. writePinHigh(D7);
  184. break;
  185. case 6:
  186. writePinLow(D0);
  187. writePinLow(D1);
  188. writePinLow(D2);
  189. break;
  190. case 7:
  191. writePinLow(D0);
  192. writePinLow(D1);
  193. break;
  194. case 8:
  195. writePinLow(D0);
  196. writePinLow(D2);
  197. break;
  198. case 9:
  199. writePinLow(D0);
  200. break;
  201. case 10:
  202. writePinLow(D1);
  203. writePinLow(D2);
  204. break;
  205. case 11:
  206. writePinLow(D1);
  207. break;
  208. case 12:
  209. writePinLow(D2);
  210. break;
  211. case 13:
  212. writePinHigh(D3);
  213. break;
  214. case 14:
  215. writePinHigh(B7);
  216. break;
  217. case 15:
  218. writePinHigh(B3);
  219. break;
  220. }
  221. }
  222. static void unselect_cols(void) {
  223. //Native
  224. setPinOutput(D3);
  225. setPinOutput(D7);
  226. writePinHigh(D3);
  227. writePinHigh(D7);
  228. setPinOutput(C6);
  229. setPinOutput(C7);
  230. writePinHigh(C6);
  231. writePinHigh(C7);
  232. setPinOutput(B3);
  233. setPinOutput(B4);
  234. setPinOutput(B5);
  235. setPinOutput(B6);
  236. setPinOutput(B7);
  237. writePinHigh(B3);
  238. writePinHigh(B4);
  239. writePinHigh(B5);
  240. writePinHigh(B6);
  241. writePinHigh(B7);
  242. //Demultiplexer
  243. setPinOutput(D0);
  244. setPinOutput(D1);
  245. setPinOutput(D2);
  246. writePinLow(D0);
  247. writePinLow(D1);
  248. writePinLow(D2);
  249. }
  250. static void init_pins(void) {
  251. unselect_cols();
  252. for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
  253. setPinInputHigh(row_pins[x]);
  254. }
  255. }
  256. static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {
  257. bool matrix_changed = false;
  258. // Select col and wait for col selecton to stabilize
  259. select_col(current_col);
  260. wait_us(30);
  261. // For each row...
  262. for (uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) {
  263. // Store last value of row prior to reading
  264. matrix_row_t last_row_value = current_matrix[row_index];
  265. // Check row pin state
  266. if (readPin(row_pins[row_index]) == 0) {
  267. // Pin LO, set col bit
  268. current_matrix[row_index] |= (MATRIX_ROW_SHIFTER << current_col);
  269. } else {
  270. // Pin HI, clear col bit
  271. current_matrix[row_index] &= ~(MATRIX_ROW_SHIFTER << current_col);
  272. }
  273. // Determine if the matrix changed state
  274. if ((last_row_value != current_matrix[row_index]) && !(matrix_changed)) {
  275. matrix_changed = true;
  276. }
  277. }
  278. // Unselect col
  279. unselect_col(current_col);
  280. return matrix_changed;
  281. }
  282. #endif
  283. void matrix_init_custom(void) {
  284. // initialize key pins
  285. init_pins();
  286. }
  287. bool matrix_scan_custom(matrix_row_t current_matrix[]) {
  288. bool changed = false;
  289. #if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW)
  290. // Set row, read cols
  291. for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
  292. changed |= read_cols_on_row(current_matrix, current_row);
  293. }
  294. #elif (DIODE_DIRECTION == ROW2COL)
  295. // Set col, read rows
  296. for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
  297. changed |= read_rows_on_col(current_matrix, current_col);
  298. }
  299. #endif
  300. return changed;
  301. }