matrix.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  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_init(void) {
  58. /* frees PORTF by setting the JTD bit twice within four cycles */
  59. MCUCR |= _BV(JTD);
  60. MCUCR |= _BV(JTD);
  61. /* initializes the I/O pins */
  62. #if DIODE_DIRECTION == COL2ROW
  63. for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
  64. /* DDRxn */
  65. _SFR_IO8(row_pins[r].input_addr + 1) |= _BV(row_pins[r].bit);
  66. toggle_row(r);
  67. }
  68. for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
  69. /* PORTxn */
  70. _SFR_IO8(col_pins[c].input_addr + 2) |= _BV(col_pins[c].bit);
  71. }
  72. #else
  73. for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
  74. /* DDRxn */
  75. _SFR_IO8(col_pins[c].input_addr + 1) |= _BV(col_pins[c].bit);
  76. toggle_col(c);
  77. }
  78. for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
  79. /* PORTxn */
  80. _SFR_IO8(row_pins[r].input_addr + 2) |= _BV(row_pins[r].bit);
  81. }
  82. #endif
  83. matrix_init_quantum();
  84. }
  85. #if DIODE_DIRECTION == COL2ROW
  86. uint8_t matrix_scan(void) {
  87. static matrix_row_t debouncing_matrix[MATRIX_ROWS];
  88. for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
  89. toggle_row(r);
  90. matrix_row_t state = read_cols();
  91. if (debouncing_matrix[r] != state) {
  92. debouncing_matrix[r] = state;
  93. debouncing_delay = DEBOUNCING_DELAY;
  94. }
  95. toggle_row(r);
  96. }
  97. if (debouncing_delay >= 0) {
  98. dprintf("Debouncing delay remaining: %X\n", debouncing_delay);
  99. --debouncing_delay;
  100. if (debouncing_delay >= 0) {
  101. wait_ms(1);
  102. }
  103. else {
  104. for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
  105. matrix[r] = debouncing_matrix[r];
  106. }
  107. }
  108. }
  109. matrix_scan_quantum();
  110. return 1;
  111. }
  112. static void toggle_row(uint8_t row) {
  113. /* PINxn */
  114. _SFR_IO8(row_pins[row].input_addr) = _BV(row_pins[row].bit);
  115. }
  116. static matrix_row_t read_cols(void) {
  117. matrix_row_t state = 0;
  118. for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
  119. /* PINxn */
  120. if (!(_SFR_IO8(col_pins[c].input_addr) & _BV(col_pins[c].bit))) {
  121. state |= (matrix_row_t)1 << c;
  122. }
  123. }
  124. return state;
  125. }
  126. matrix_row_t matrix_get_row(uint8_t row) {
  127. return matrix[row];
  128. }
  129. #else
  130. uint8_t matrix_scan(void) {
  131. static matrix_col_t debouncing_matrix[MATRIX_COLS];
  132. for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
  133. toggle_col(c);
  134. matrix_col_t state = read_rows();
  135. if (debouncing_matrix[c] != state) {
  136. debouncing_matrix[c] = state;
  137. debouncing_delay = DEBOUNCING_DELAY;
  138. }
  139. toggle_col(c);
  140. }
  141. if (debouncing_delay >= 0) {
  142. dprintf("Debouncing delay remaining: %X\n", debouncing_delay);
  143. --debouncing_delay;
  144. if (debouncing_delay >= 0) {
  145. wait_ms(1);
  146. }
  147. else {
  148. for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
  149. matrix[c] = debouncing_matrix[c];
  150. }
  151. }
  152. }
  153. matrix_scan_quantum();
  154. return 1;
  155. }
  156. static void toggle_col(uint8_t col) {
  157. /* PINxn */
  158. _SFR_IO8(col_pins[col].input_addr) = _BV(col_pins[col].bit);
  159. }
  160. static matrix_col_t read_rows(void) {
  161. matrix_col_t state = 0;
  162. for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
  163. /* PINxn */
  164. if (!(_SFR_IO8(row_pins[r].input_addr) & _BV(row_pins[r].bit))) {
  165. state |= (matrix_col_t)1 << r;
  166. }
  167. }
  168. return state;
  169. }
  170. matrix_row_t matrix_get_row(uint8_t row) {
  171. matrix_row_t state = 0;
  172. matrix_col_t mask = (matrix_col_t)1 << row;
  173. for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
  174. if (matrix[c] & mask) {
  175. state |= (matrix_row_t)1 << c;
  176. }
  177. }
  178. return state;
  179. }
  180. #endif
  181. bool matrix_is_modified(void) {
  182. if (debouncing_delay >= 0) return false;
  183. return true;
  184. }
  185. bool matrix_is_on(uint8_t row, uint8_t col) {
  186. return matrix_get_row(row) & (matrix_row_t)1 << col;
  187. }
  188. void matrix_print(void) {
  189. dprintln("Human-readable matrix state:");
  190. for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
  191. dprintf("State of row %X: %016b\n", r, bitrev16(matrix_get_row(r)));
  192. }
  193. }
  194. uint8_t matrix_key_count(void) {
  195. uint8_t count = 0;
  196. for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
  197. count += bitpop16(matrix_get_row(r));
  198. }
  199. return count;
  200. }