Keyboard firmwares for Atmel AVR and Cortex-M
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.

matrix.c 4.0KB

13 jaren geleden
13 jaren geleden
13 jaren geleden
13 jaren geleden
13 jaren geleden
13 jaren geleden
13 jaren geleden
13 jaren geleden
13 jaren geleden
13 jaren geleden
13 jaren geleden
13 jaren geleden
13 jaren geleden
13 jaren geleden
13 jaren geleden
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*
  2. * scan matrix
  3. */
  4. #include <stdint.h>
  5. #include <stdbool.h>
  6. #include <avr/io.h>
  7. #include <util/delay.h>
  8. #include "print.h"
  9. #include "util.h"
  10. #include "matrix_skel.h"
  11. // matrix state buffer (key on: 1/key off: 0)
  12. static uint8_t *matrix;
  13. static uint8_t *matrix_prev;
  14. static uint8_t _matrix0[MATRIX_ROWS];
  15. static uint8_t _matrix1[MATRIX_ROWS];
  16. static bool matrix_has_ghost_in_row(uint8_t row);
  17. static uint8_t read_col(void);
  18. static void unselect_rows(void);
  19. static void select_row(uint8_t row);
  20. inline
  21. int matrix_rows(void)
  22. {
  23. return MATRIX_ROWS;
  24. }
  25. inline
  26. int matrix_cols(void)
  27. {
  28. return MATRIX_COLS;
  29. }
  30. // this must be called once before matrix_scan.
  31. void matrix_init(void)
  32. {
  33. // initialize row and col
  34. unselect_rows();
  35. // Input with pull-up(DDR:0, PORT:1)
  36. DDRB = 0x00;
  37. PORTB = 0xFF;
  38. // initialize matrix state: all keys off
  39. for (int i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00;
  40. for (int i=0; i < MATRIX_ROWS; i++) _matrix1[i] = 0x00;
  41. matrix = _matrix0;
  42. matrix_prev = _matrix1;
  43. }
  44. int matrix_scan(void)
  45. {
  46. uint8_t *tmp;
  47. tmp = matrix_prev;
  48. matrix_prev = matrix;
  49. matrix = tmp;
  50. for (int i = 0; i < MATRIX_ROWS; i++) {
  51. unselect_rows();
  52. select_row(i);
  53. _delay_us(30); // without this wait read unstable value.
  54. matrix[i] = ~read_col();
  55. }
  56. unselect_rows();
  57. return 1;
  58. }
  59. bool matrix_is_modified(void)
  60. {
  61. for (int i = 0; i < MATRIX_ROWS; i++) {
  62. if (matrix[i] != matrix_prev[i])
  63. return true;
  64. }
  65. return false;
  66. }
  67. bool matrix_has_ghost(void)
  68. {
  69. for (int i = 0; i < MATRIX_ROWS; i++) {
  70. if (matrix_has_ghost_in_row(i))
  71. return true;
  72. }
  73. return false;
  74. }
  75. inline
  76. bool matrix_is_on(int row, int col)
  77. {
  78. return (matrix[row] & (1<<col));
  79. }
  80. inline
  81. uint16_t matrix_get_row(int row)
  82. {
  83. return matrix[row];
  84. }
  85. void matrix_print(void)
  86. {
  87. print("\nr/c 01234567\n");
  88. for (int row = 0; row < matrix_rows(); row++) {
  89. phex(row); print(": ");
  90. pbin_reverse(matrix_get_row(row));
  91. if (matrix_has_ghost_in_row(row)) {
  92. print(" <ghost");
  93. }
  94. print("\n");
  95. }
  96. }
  97. int matrix_key_count(void)
  98. {
  99. int count = 0;
  100. for (int i = 0; i < MATRIX_ROWS; i++) {
  101. count += bitpop(matrix[i]);
  102. }
  103. return count;
  104. }
  105. static bool matrix_has_ghost_in_row(uint8_t row)
  106. {
  107. // no ghost exists in case less than 2 keys on
  108. if (((matrix[row] - 1) & matrix[row]) == 0)
  109. return false;
  110. // ghost exists in case same state as other row
  111. for (int i=0; i < MATRIX_ROWS; i++) {
  112. if (i != row && (matrix[i] & matrix[row]) == matrix[row])
  113. return true;
  114. }
  115. return false;
  116. }
  117. static uint8_t read_col(void)
  118. {
  119. return PINB;
  120. }
  121. static void unselect_rows(void)
  122. {
  123. // Hi-Z(DDR:0, PORT:0) to unselect
  124. DDRC &= ~0b11000000; // PC: 7,6
  125. PORTC &= ~0b11000000;
  126. DDRD &= ~0b11000111; // PD: 7,6,2,1,0
  127. PORTD &= ~0b11000111;
  128. DDRF &= ~0b11000000; // PF: 7,6
  129. PORTF &= ~0b11000000;
  130. }
  131. static void select_row(uint8_t row)
  132. {
  133. // Output low(DDR:1, PORT:0) to select
  134. // row: 0 1 2 3 4 5 6 7 8
  135. // pin: PD0, PC7, PD7, PF6, PD6, PD1, PD2, PC6, PF7
  136. switch (row) {
  137. case 0:
  138. DDRD |= (1<<0);
  139. PORTD &= ~(1<<0);
  140. break;
  141. case 1:
  142. DDRC |= (1<<7);
  143. PORTC &= ~(1<<7);
  144. break;
  145. case 2:
  146. DDRD |= (1<<7);
  147. PORTD &= ~(1<<7);
  148. break;
  149. case 3:
  150. DDRF |= (1<<6);
  151. PORTF &= ~(1<<6);
  152. break;
  153. case 4:
  154. DDRD |= (1<<6);
  155. PORTD &= ~(1<<6);
  156. break;
  157. case 5:
  158. DDRD |= (1<<1);
  159. PORTD &= ~(1<<1);
  160. break;
  161. case 6:
  162. DDRD |= (1<<2);
  163. PORTD &= ~(1<<2);
  164. break;
  165. case 7:
  166. DDRC |= (1<<6);
  167. PORTC &= ~(1<<6);
  168. break;
  169. case 8:
  170. DDRF |= (1<<7);
  171. PORTF &= ~(1<<7);
  172. break;
  173. }
  174. }