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.

256 lines
5.3 KiB

  1. #include <stdint.h>
  2. #include <stdbool.h>
  3. #include <avr/io.h>
  4. #include "wait.h"
  5. #include "action_layer.h"
  6. #include "print.h"
  7. #include "debug.h"
  8. #include "util.h"
  9. #include "matrix.h"
  10. #include "ergodone.h"
  11. #include "expander.h"
  12. /*
  13. * This constant define not debouncing time in msecs, but amount of matrix
  14. * scan loops which should be made to get stable debounced results.
  15. *
  16. * On Ergodox matrix scan rate is relatively low, because of slow I2C.
  17. * Now it's only 317 scans/second, or about 3.15 msec/scan.
  18. * According to Cherry specs, debouncing time is 5 msec.
  19. *
  20. * And so, there is no sense to have DEBOUNCE higher than 2.
  21. */
  22. #ifndef DEBOUNCE
  23. # define DEBOUNCE 5
  24. #endif
  25. /* matrix state(1:on, 0:off) */
  26. static matrix_row_t matrix[MATRIX_ROWS];
  27. // Debouncing: store for each key the number of scans until it's eligible to
  28. // change. When scanning the matrix, ignore any changes in keys that have
  29. // already changed in the last DEBOUNCE scans.
  30. static uint8_t debounce_matrix[MATRIX_ROWS * MATRIX_COLS];
  31. static matrix_row_t read_cols(uint8_t row);
  32. static void init_cols(void);
  33. static void unselect_rows(void);
  34. static void select_row(uint8_t row);
  35. __attribute__ ((weak))
  36. void matrix_init_user(void) {}
  37. __attribute__ ((weak))
  38. void matrix_scan_user(void) {}
  39. __attribute__ ((weak))
  40. void matrix_init_kb(void) {
  41. matrix_init_user();
  42. }
  43. __attribute__ ((weak))
  44. void matrix_scan_kb(void) {
  45. matrix_scan_user();
  46. }
  47. inline
  48. uint8_t matrix_rows(void)
  49. {
  50. return MATRIX_ROWS;
  51. }
  52. inline
  53. uint8_t matrix_cols(void)
  54. {
  55. return MATRIX_COLS;
  56. }
  57. void matrix_init(void)
  58. {
  59. unselect_rows();
  60. init_cols();
  61. // initialize matrix state: all keys off
  62. for (uint8_t i=0; i < MATRIX_ROWS; i++) {
  63. matrix[i] = 0;
  64. for (uint8_t j=0; j < MATRIX_COLS; ++j) {
  65. debounce_matrix[i * MATRIX_COLS + j] = 0;
  66. }
  67. }
  68. matrix_init_quantum();
  69. }
  70. void matrix_power_up(void) {
  71. unselect_rows();
  72. init_cols();
  73. // initialize matrix state: all keys off
  74. for (uint8_t i=0; i < MATRIX_ROWS; i++) {
  75. matrix[i] = 0;
  76. }
  77. }
  78. // Returns a matrix_row_t whose bits are set if the corresponding key should be
  79. // eligible to change in this scan.
  80. matrix_row_t debounce_mask(uint8_t row) {
  81. matrix_row_t result = 0;
  82. for (uint8_t j=0; j < MATRIX_COLS; ++j) {
  83. if (debounce_matrix[row * MATRIX_COLS + j]) {
  84. --debounce_matrix[row * MATRIX_COLS + j];
  85. } else {
  86. result |= (1 << j);
  87. }
  88. }
  89. return result;
  90. }
  91. // Report changed keys in the given row. Resets the debounce countdowns
  92. // corresponding to each set bit in 'change' to DEBOUNCE.
  93. void debounce_report(matrix_row_t change, uint8_t row) {
  94. for (uint8_t i = 0; i < MATRIX_COLS; ++i) {
  95. if (change & (1 << i)) {
  96. debounce_matrix[row * MATRIX_COLS + i] = DEBOUNCE;
  97. }
  98. }
  99. }
  100. uint8_t matrix_scan(void)
  101. {
  102. expander_scan();
  103. for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
  104. select_row(i);
  105. wait_us(30); // without this wait read unstable value.
  106. matrix_row_t mask = debounce_mask(i);
  107. matrix_row_t cols = (read_cols(i) & mask) | (matrix[i] & ~mask);
  108. debounce_report(cols ^ matrix[i], i);
  109. matrix[i] = cols;
  110. unselect_rows();
  111. }
  112. matrix_scan_quantum();
  113. return 1;
  114. }
  115. inline
  116. bool matrix_is_on(uint8_t row, uint8_t col)
  117. {
  118. return (matrix[row] & ((matrix_row_t)1<<col));
  119. }
  120. inline
  121. matrix_row_t matrix_get_row(uint8_t row)
  122. {
  123. return matrix[row];
  124. }
  125. void matrix_print(void)
  126. {
  127. print("\nr/c 0123456789ABCDEF\n");
  128. for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
  129. phex(row); print(": ");
  130. pbin_reverse16(matrix_get_row(row));
  131. print("\n");
  132. }
  133. }
  134. uint8_t matrix_key_count(void)
  135. {
  136. uint8_t count = 0;
  137. for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
  138. count += bitpop16(matrix[i]);
  139. }
  140. return count;
  141. }
  142. /* Column pin configuration
  143. *
  144. * Pro Micro: 6 5 4 3 2 1 0
  145. * PD3 PD2 PD4 PC6 PD7 PE6 PB4
  146. *
  147. * Expander: 13 12 11 10 9 8 7
  148. */
  149. static void init_cols(void)
  150. {
  151. // Pro Micro
  152. DDRE &= ~(1<<PE6);
  153. PORTE |= (1<<PE6);
  154. DDRD &= ~(1<<PD2 | 1<<PD3 | 1<<PD4 | 1<<PD7);
  155. PORTD |= (1<<PD2 | 1<<PD3 | 1<<PD4 | 1<<PD7);
  156. DDRC &= ~(1<<PC6);
  157. PORTC |= (1<<PC6);
  158. DDRB &= ~(1<<PB4);
  159. PORTB |= (1<<PB4);
  160. // MCP23017
  161. expander_init();
  162. }
  163. static matrix_row_t read_cols(uint8_t row)
  164. {
  165. return expander_read_row() |
  166. (PIND&(1<<PD3) ? 0 : (1<<6)) |
  167. (PIND&(1<<PD2) ? 0 : (1<<5)) |
  168. (PIND&(1<<PD4) ? 0 : (1<<4)) |
  169. (PINC&(1<<PC6) ? 0 : (1<<3)) |
  170. (PIND&(1<<PD7) ? 0 : (1<<2)) |
  171. (PINE&(1<<PE6) ? 0 : (1<<1)) |
  172. (PINB&(1<<PB4) ? 0 : (1<<0)) ;
  173. }
  174. /* Row pin configuration
  175. *
  176. * Pro Micro: 0 1 2 3 4 5
  177. * F4 F5 F6 F7 B1 B2
  178. *
  179. * Expander: 0 1 2 3 4 5
  180. */
  181. static void unselect_rows(void)
  182. {
  183. // Pro Micro
  184. DDRF &= ~(1<<PF4 | 1<<PF5 | 1<<PF6 | 1<<PF7);
  185. PORTF &= ~(1<<PF4 | 1<<PF5 | 1<<PF6 | 1<<PF7);
  186. DDRB &= ~(1<<PB1 | 1<<PB2);
  187. PORTB &= ~(1<<PB1 | 1<<PB2);
  188. // Expander
  189. expander_unselect_rows();
  190. }
  191. static void select_row(uint8_t row)
  192. {
  193. // Pro Micro
  194. switch (row) {
  195. case 0:
  196. DDRF |= (1<<PF4);
  197. PORTF &= ~(1<<PF4);
  198. break;
  199. case 1:
  200. DDRF |= (1<<PF5);
  201. PORTF &= ~(1<<PF5);
  202. break;
  203. case 2:
  204. DDRF |= (1<<PF6);
  205. PORTF &= ~(1<<PF6);
  206. break;
  207. case 3:
  208. DDRF |= (1<<PF7);
  209. PORTF &= ~(1<<PF7);
  210. break;
  211. case 4:
  212. DDRB |= (1<<PB1);
  213. PORTB &= ~(1<<PB1);
  214. break;
  215. case 5:
  216. DDRB |= (1<<PB2);
  217. PORTB &= ~(1<<PB2);
  218. break;
  219. }
  220. expander_select_row(row);
  221. }