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. static matrix_row_t debouncing_matrix[MATRIX_ROWS];
  35. #else
  36. static matrix_col_t matrix[MATRIX_COLS];
  37. static matrix_col_t debouncing_matrix[MATRIX_COLS];
  38. #endif
  39. static int8_t debouncing_delay = -1;
  40. #if DIODE_DIRECTION == COL2ROW
  41. static void toggle_row(uint8_t row);
  42. static matrix_row_t read_cols(void);
  43. #else
  44. static void toggle_col(uint8_t col);
  45. static matrix_col_t read_rows(void);
  46. #endif
  47. __attribute__ ((weak))
  48. void matrix_init_quantum(void) {
  49. }
  50. __attribute__ ((weak))
  51. void matrix_scan_quantum(void) {
  52. }
  53. uint8_t matrix_rows(void) {
  54. return MATRIX_ROWS;
  55. }
  56. uint8_t matrix_cols(void) {
  57. return MATRIX_COLS;
  58. }
  59. void matrix_init(void) {
  60. /* frees PORTF by setting the JTD bit twice within four cycles */
  61. MCUCR |= _BV(JTD);
  62. MCUCR |= _BV(JTD);
  63. /* initializes the I/O pins */
  64. #if DIODE_DIRECTION == COL2ROW
  65. for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
  66. /* DDRxn */
  67. _SFR_IO8(row_pins[r].input_addr + 1) |= _BV(row_pins[r].bit);
  68. toggle_row(r);
  69. }
  70. for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
  71. /* PORTxn */
  72. _SFR_IO8(col_pins[c].input_addr + 2) |= _BV(col_pins[c].bit);
  73. }
  74. #else
  75. for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
  76. /* DDRxn */
  77. _SFR_IO8(col_pins[c].input_addr + 1) |= _BV(col_pins[c].bit);
  78. toggle_col(c);
  79. }
  80. for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
  81. /* PORTxn */
  82. _SFR_IO8(row_pins[r].input_addr + 2) |= _BV(row_pins[r].bit);
  83. }
  84. #endif
  85. matrix_init_quantum();
  86. }
  87. #if DIODE_DIRECTION == COL2ROW
  88. uint8_t matrix_scan(void) {
  89. for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
  90. toggle_row(r);
  91. matrix_row_t state = read_cols();
  92. if (debouncing_matrix[r] != state) {
  93. debouncing_matrix[r] = state;
  94. debouncing_delay = DEBOUNCING_DELAY;
  95. }
  96. toggle_row(r);
  97. }
  98. if (debouncing_delay >= 0) {
  99. dprintf("Debouncing delay remaining: %X\n", debouncing_delay);
  100. --debouncing_delay;
  101. if (debouncing_delay >= 0) {
  102. wait_ms(1);
  103. }
  104. else {
  105. for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
  106. matrix[r] = debouncing_matrix[r];
  107. }
  108. }
  109. }
  110. matrix_scan_quantum();
  111. return 1;
  112. }
  113. static void toggle_row(uint8_t row) {
  114. /* PINxn */
  115. _SFR_IO8(row_pins[row].input_addr) = _BV(row_pins[row].bit);
  116. }
  117. static matrix_row_t read_cols(void) {
  118. matrix_row_t state = 0;
  119. for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
  120. /* PINxn */
  121. if (!(_SFR_IO8(col_pins[c].input_addr) & _BV(col_pins[c].bit))) {
  122. state |= (matrix_row_t)1 << c;
  123. }
  124. }
  125. return state;
  126. }
  127. matrix_row_t matrix_get_row(uint8_t row) {
  128. return matrix[row];
  129. }
  130. #else
  131. uint8_t matrix_scan(void) {
  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. }