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.

264 lines
5.6 KiB

  1. /**
  2. * matrix.c
  3. *
  4. Copyright 2020 astro <yuleiz@gmail.com>
  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. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include "quantum.h"
  17. #ifndef DEBOUNCE
  18. # define DEBOUNCE 5
  19. #endif
  20. static uint8_t debouncing = DEBOUNCE;
  21. static matrix_row_t matrix[MATRIX_ROWS];
  22. static matrix_row_t matrix_debouncing[MATRIX_ROWS];
  23. static uint8_t read_rows(void);
  24. static void init_rows(void);
  25. static void init_cols(void);
  26. static void unselect_cols(void);
  27. static void select_col(uint8_t col);
  28. __attribute__ ((weak))
  29. void matrix_init_kb(void)
  30. {
  31. matrix_init_user();
  32. }
  33. __attribute__ ((weak))
  34. void matrix_scan_kb(void)
  35. {
  36. matrix_scan_user();
  37. }
  38. __attribute__ ((weak))
  39. void matrix_init_user(void) {}
  40. __attribute__ ((weak))
  41. void matrix_scan_user(void) {}
  42. void matrix_init(void)
  43. {
  44. //setPinOutput(F0);
  45. //writePinHigh(F0);
  46. setPinOutput(B4);
  47. writePinLow(B4);
  48. init_cols();
  49. init_rows();
  50. for (uint8_t i=0; i < MATRIX_ROWS; i++) {
  51. matrix[i] = 0;
  52. matrix_debouncing[i] = 0;
  53. }
  54. matrix_init_kb();
  55. }
  56. uint8_t matrix_scan(void)
  57. {
  58. for (uint8_t col = 0; col < MATRIX_COLS; col++) {
  59. select_col(col);
  60. _delay_us(3);
  61. uint8_t rows = read_rows();
  62. for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
  63. bool prev_bit = matrix_debouncing[row] & ((matrix_row_t)1<<col);
  64. bool curr_bit = rows & (1<<row);
  65. if (prev_bit != curr_bit) {
  66. matrix_debouncing[row] ^= ((matrix_row_t)1<<col);
  67. debouncing = DEBOUNCE;
  68. }
  69. }
  70. unselect_cols();
  71. }
  72. if (debouncing) {
  73. if (--debouncing) {
  74. _delay_ms(1);
  75. } else {
  76. for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
  77. matrix[i] = matrix_debouncing[i];
  78. }
  79. }
  80. }
  81. matrix_scan_kb();
  82. return 1;
  83. }
  84. inline matrix_row_t matrix_get_row(uint8_t row)
  85. {
  86. return matrix[row];
  87. }
  88. void matrix_print(void)
  89. {
  90. print("\nr/c 0123456789ABCDEF\n");
  91. for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
  92. xprintf("%02X: %032lb\n", row, bitrev32(matrix_get_row(row)));
  93. }
  94. }
  95. /*
  96. * Row pin configuration
  97. * row: 0 1 2 3 4
  98. * pin: PE6 PF6 PF7 PB7 PD4
  99. */
  100. static void init_rows(void)
  101. {
  102. setPinInputHigh(E6);
  103. setPinInputHigh(F6);
  104. setPinInputHigh(F7);
  105. setPinInputHigh(B7);
  106. setPinInputHigh(D4);
  107. }
  108. static uint8_t read_rows(void)
  109. {
  110. return ((readPin(E6) ? 0 : (1 << 0)) |
  111. (readPin(F6) ? 0 : (1 << 1)) |
  112. (readPin(F7) ? 0 : (1 << 2)) |
  113. (readPin(B7) ? 0 : (1 << 3)) |
  114. (readPin(D4) ? 0 : (1 << 4)));
  115. }
  116. /*
  117. * Columns 0 - 13
  118. * These columns uses two 74LVC138 3 to 8 bit demultiplexers.
  119. * EN Pin, PF5, PD6
  120. *
  121. * col / pin: PF0 PF1 PF4
  122. * 0: 0 0 0
  123. * 1: 1 0 0
  124. * 2: 0 1 0
  125. * 3: 1 1 0
  126. * 4: 0 0 1
  127. * 5: 1 0 1
  128. * 6: 0 1 1
  129. * PD2 PD3 PD5
  130. * 7: 0 0 0
  131. * 8: 1 0 0
  132. * 9: 0 1 0
  133. * 10: 1 1 0
  134. * 11: 0 0 1
  135. * 12: 1 0 1
  136. * 13: 0 1 1
  137. *
  138. */
  139. static void init_cols(void)
  140. {
  141. setPinOutput(F0);
  142. setPinOutput(F1);
  143. setPinOutput(F4);
  144. setPinOutput(F5);
  145. setPinOutput(D2);
  146. setPinOutput(D3);
  147. setPinOutput(D5);
  148. setPinOutput(D6);
  149. unselect_cols();
  150. }
  151. static void unselect_cols(void)
  152. {
  153. writePinHigh(F0);
  154. writePinHigh(F1);
  155. writePinHigh(F4);
  156. writePinHigh(F5);
  157. writePinHigh(D2);
  158. writePinHigh(D3);
  159. writePinHigh(D5);
  160. writePinHigh(D6);
  161. }
  162. static void select_col(uint8_t col) {
  163. switch (col) {
  164. case 0:
  165. writePinLow(F0);
  166. writePinLow(F1);
  167. writePinLow(F4);
  168. break;
  169. case 1:
  170. writePinHigh(F0);
  171. writePinLow(F1);
  172. writePinLow(F4);
  173. break;
  174. case 2:
  175. writePinLow(F0);
  176. writePinHigh(F1);
  177. writePinLow(F4);
  178. break;
  179. case 3:
  180. writePinHigh(F0);
  181. writePinHigh(F1);
  182. writePinLow(F4);
  183. break;
  184. case 4:
  185. writePinLow(F0);
  186. writePinLow(F1);
  187. writePinHigh(F4);
  188. break;
  189. case 5:
  190. writePinHigh(F0);
  191. writePinLow(F1);
  192. writePinHigh(F4);
  193. break;
  194. case 6:
  195. writePinLow(F0);
  196. writePinHigh(F1);
  197. writePinHigh(F4);
  198. break;
  199. case 7:
  200. writePinLow(D2);
  201. writePinLow(D3);
  202. writePinLow(D5);
  203. break;
  204. case 8:
  205. writePinHigh(D2);
  206. writePinLow(D3);
  207. writePinLow(D5);
  208. break;
  209. case 9:
  210. writePinLow(D2);
  211. writePinHigh(D3);
  212. writePinLow(D5);
  213. break;
  214. case 10:
  215. writePinHigh(D2);
  216. writePinHigh(D3);
  217. writePinLow(D5);
  218. break;
  219. case 11:
  220. writePinLow(D2);
  221. writePinLow(D3);
  222. writePinHigh(D5);
  223. break;
  224. case 12:
  225. writePinHigh(D2);
  226. writePinLow(D3);
  227. writePinHigh(D5);
  228. break;
  229. case 13:
  230. writePinLow(D2);
  231. writePinHigh(D3);
  232. writePinHigh(D5);
  233. break;
  234. }
  235. }