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 3.9KB

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