matrix.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /*
  2. Copyright 2012 Jun Wako
  3. Copyright 2014 Jack Humbert
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #include <stdint.h>
  16. #include <stdbool.h>
  17. #include <avr/io.h>
  18. #include "wait.h"
  19. #include "print.h"
  20. #include "debug.h"
  21. #include "util.h"
  22. #include "matrix.h"
  23. #ifdef MATRIX_HAS_GHOST
  24. # error "The universal matrix.c file cannot be used for this keyboard."
  25. #endif
  26. #ifndef DEBOUNCING_DELAY
  27. # define DEBOUNCING_DELAY 5
  28. #endif
  29. static const io_pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
  30. static const io_pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
  31. /* matrix state */
  32. #if DIODE_DIRECTION == COL2ROW
  33. static matrix_row_t matrix[MATRIX_ROWS];
  34. #else
  35. static matrix_col_t matrix[MATRIX_COLS];
  36. #endif
  37. static int8_t debouncing_delay = -1;
  38. #if DIODE_DIRECTION == COL2ROW
  39. static void toggle_row(uint8_t row);
  40. static matrix_row_t read_cols(void);
  41. #else
  42. static void toggle_col(uint8_t col);
  43. static matrix_col_t read_rows(void);
  44. #endif
  45. __attribute__ ((weak))
  46. void matrix_init_quantum(void) {
  47. }
  48. __attribute__ ((weak))
  49. void matrix_scan_quantum(void) {
  50. }
  51. uint8_t matrix_rows(void) {
  52. return MATRIX_ROWS;
  53. }
  54. uint8_t matrix_cols(void) {
  55. return MATRIX_COLS;
  56. }
  57. void matrix_power_up(void) {
  58. #if DIODE_DIRECTION == COL2ROW
  59. for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
  60. /* DDRxn */
  61. _SFR_IO8(row_pins[r].input_addr + 1) |= _BV(row_pins[r].bit);
  62. toggle_row(r);
  63. }
  64. for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
  65. /* PORTxn */
  66. _SFR_IO8(col_pins[c].input_addr + 2) |= _BV(col_pins[c].bit);
  67. }
  68. #else
  69. for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
  70. /* DDRxn */
  71. _SFR_IO8(col_pins[c].input_addr + 1) |= _BV(col_pins[c].bit);
  72. toggle_col(c);
  73. }
  74. for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
  75. /* PORTxn */
  76. _SFR_IO8(row_pins[r].input_addr + 2) |= _BV(row_pins[r].bit);
  77. }
  78. #endif
  79. }
  80. void matrix_init(void) {
  81. /* frees PORTF by setting the JTD bit twice within four cycles */
  82. #ifdef __AVR_ATmega32U4__
  83. MCUCR |= _BV(JTD);
  84. MCUCR |= _BV(JTD);
  85. #endif
  86. /* initializes the I/O pins */
  87. #if DIODE_DIRECTION == COL2ROW
  88. for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
  89. /* DDRxn */
  90. _SFR_IO8(row_pins[r].input_addr + 1) |= _BV(row_pins[r].bit);
  91. toggle_row(r);
  92. }
  93. for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
  94. /* PORTxn */
  95. _SFR_IO8(col_pins[c].input_addr + 2) |= _BV(col_pins[c].bit);
  96. }
  97. #else
  98. for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
  99. /* DDRxn */
  100. _SFR_IO8(col_pins[c].input_addr + 1) |= _BV(col_pins[c].bit);
  101. toggle_col(c);
  102. }
  103. for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
  104. /* PORTxn */
  105. _SFR_IO8(row_pins[r].input_addr + 2) |= _BV(row_pins[r].bit);
  106. }
  107. #endif
  108. matrix_init_quantum();
  109. }
  110. #if DIODE_DIRECTION == COL2ROW
  111. uint8_t matrix_scan(void) {
  112. static matrix_row_t debouncing_matrix[MATRIX_ROWS];
  113. for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
  114. toggle_row(r);
  115. matrix_row_t state = read_cols();
  116. if (debouncing_matrix[r] != state) {
  117. debouncing_matrix[r] = state;
  118. debouncing_delay = DEBOUNCING_DELAY;
  119. }
  120. toggle_row(r);
  121. }
  122. if (debouncing_delay >= 0) {
  123. dprintf("Debouncing delay remaining: %X\n", debouncing_delay);
  124. --debouncing_delay;
  125. if (debouncing_delay >= 0) {
  126. wait_ms(1);
  127. }
  128. else {
  129. for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
  130. matrix[r] = debouncing_matrix[r];
  131. }
  132. }
  133. }
  134. matrix_scan_quantum();
  135. return 1;
  136. }
  137. static void toggle_row(uint8_t row) {
  138. /* PINxn */
  139. _SFR_IO8(row_pins[row].input_addr) = _BV(row_pins[row].bit);
  140. }
  141. static matrix_row_t read_cols(void) {
  142. matrix_row_t state = 0;
  143. for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
  144. /* PINxn */
  145. if (!(_SFR_IO8(col_pins[c].input_addr) & _BV(col_pins[c].bit))) {
  146. state |= (matrix_row_t)1 << c;
  147. }
  148. }
  149. return state;
  150. }
  151. matrix_row_t matrix_get_row(uint8_t row) {
  152. return matrix[row];
  153. }
  154. #else
  155. uint8_t matrix_scan(void) {
  156. static matrix_col_t debouncing_matrix[MATRIX_COLS];
  157. for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
  158. toggle_col(c);
  159. matrix_col_t state = read_rows();
  160. if (debouncing_matrix[c] != state) {
  161. debouncing_matrix[c] = state;
  162. debouncing_delay = DEBOUNCING_DELAY;
  163. }
  164. toggle_col(c);
  165. }
  166. if (debouncing_delay >= 0) {
  167. dprintf("Debouncing delay remaining: %X\n", debouncing_delay);
  168. --debouncing_delay;
  169. if (debouncing_delay >= 0) {
  170. wait_ms(1);
  171. }
  172. else {
  173. for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
  174. matrix[c] = debouncing_matrix[c];
  175. }
  176. }
  177. }
  178. matrix_scan_quantum();
  179. return 1;
  180. }
  181. static void toggle_col(uint8_t col) {
  182. /* PINxn */
  183. _SFR_IO8(col_pins[col].input_addr) = _BV(col_pins[col].bit);
  184. }
  185. static matrix_col_t read_rows(void) {
  186. matrix_col_t state = 0;
  187. for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
  188. /* PINxn */
  189. if (!(_SFR_IO8(row_pins[r].input_addr) & _BV(row_pins[r].bit))) {
  190. state |= (matrix_col_t)1 << r;
  191. }
  192. }
  193. return state;
  194. }
  195. matrix_row_t matrix_get_row(uint8_t row) {
  196. matrix_row_t state = 0;
  197. matrix_col_t mask = (matrix_col_t)1 << row;
  198. for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
  199. if (matrix[c] & mask) {
  200. state |= (matrix_row_t)1 << c;
  201. }
  202. }
  203. return state;
  204. }
  205. #endif
  206. bool matrix_is_modified(void) {
  207. if (debouncing_delay >= 0) return false;
  208. return true;
  209. }
  210. bool matrix_is_on(uint8_t row, uint8_t col) {
  211. return matrix_get_row(row) & (matrix_row_t)1 << col;
  212. }
  213. void matrix_print(void) {
  214. dprintln("Human-readable matrix state:");
  215. for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
  216. dprintf("State of row %X: %016b\n", r, bitrev16(matrix_get_row(r)));
  217. }
  218. }
  219. uint8_t matrix_key_count(void) {
  220. uint8_t count = 0;
  221. for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
  222. count += bitpop16(matrix_get_row(r));
  223. }
  224. return count;
  225. }