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.6KB

13 lat temu
13 lat temu
13 lat temu
13 lat temu
13 lat temu
13 lat temu
13 lat temu
13 lat temu
13 lat temu
13 lat temu
13 lat temu
13 lat temu
13 lat temu
13 lat temu
13 lat temu
13 lat temu
13 lat temu
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  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. #if (MATRIX_COLS > 16)
  12. # error "MATRIX_COLS must not exceed 16"
  13. #endif
  14. #if (MATRIX_ROWS > 255)
  15. # error "MATRIX_ROWS must not exceed 255"
  16. #endif
  17. // matrix state buffer(1:on, 0:off)
  18. #if (MATRIX_COLS <= 8)
  19. static uint8_t *matrix;
  20. static uint8_t *matrix_prev;
  21. static uint8_t _matrix0[MATRIX_ROWS];
  22. static uint8_t _matrix1[MATRIX_ROWS];
  23. #else
  24. static uint16_t *matrix;
  25. static uint16_t *matrix_prev;
  26. static uint16_t _matrix0[MATRIX_ROWS];
  27. static uint16_t _matrix1[MATRIX_ROWS];
  28. #endif
  29. #ifdef MATRIX_HAS_GHOST
  30. static bool matrix_has_ghost_in_row(uint8_t row);
  31. #endif
  32. // matrix is active low. (key on: 0/key off: 1)
  33. //
  34. // HHKB has no ghost and no bounce.
  35. // row: HC4051 select input channel(0-8)
  36. // PB0, PB1, PB2(A, B, C)
  37. // col: LS145 select low output line(0-8)
  38. // PB3, PB4, PB5, PB6(A, B, C, D)
  39. // use D as ENABLE: (enable: 0/unenable: 1)
  40. // key: KEY: (on: 0/ off:1)
  41. // KEY_PREV: (on: 1/ off: 0)
  42. // PE6,PE7(KEY, KEY_PREV)
  43. #define COL_ENABLE (1<<6)
  44. #define KEY_SELELCT(ROW, COL) (PORTB = (PORTB&(1<<7))|COL_ENABLE|(((COL)&0x07)<<3)|((ROW)&0x07))
  45. #define KEY_ENABLE (PORTB &= ~COL_ENABLE)
  46. #define KEY_UNABLE (PORTB |= COL_ENABLE)
  47. #define KEY_STATE (PINE&(1<<6))
  48. #define KEY_PREV_ON (PORTE |= (1<<7))
  49. #define KEY_PREV_OFF (PORTE &= ~(1<<7))
  50. inline
  51. uint8_t matrix_rows(void)
  52. {
  53. return MATRIX_ROWS;
  54. }
  55. inline
  56. uint8_t matrix_cols(void)
  57. {
  58. return MATRIX_COLS;
  59. }
  60. void matrix_init(void)
  61. {
  62. // row & col output(PB0-6)
  63. DDRB = 0xFF;
  64. KEY_SELELCT(0, 0);
  65. // KEY: input with pullup(PE6)
  66. // KEY_PREV: output(PE7)
  67. DDRE = 0xBF;
  68. PORTE = 0x40;
  69. // initialize matrix state: all keys off
  70. for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00;
  71. for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix1[i] = 0x00;
  72. matrix = _matrix0;
  73. matrix_prev = _matrix1;
  74. }
  75. uint8_t matrix_scan(void)
  76. {
  77. uint8_t *tmp;
  78. tmp = matrix_prev;
  79. matrix_prev = matrix;
  80. matrix = tmp;
  81. for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
  82. for (uint8_t col = 0; col < MATRIX_COLS; col++) {
  83. KEY_SELELCT(row, col);
  84. _delay_us(40); // from logic analyzer chart
  85. if (matrix_prev[row] & (1<<col)) {
  86. KEY_PREV_ON;
  87. }
  88. _delay_us(7); // from logic analyzer chart
  89. KEY_ENABLE;
  90. _delay_us(10); // from logic analyzer chart
  91. if (KEY_STATE) {
  92. matrix[row] &= ~(1<<col);
  93. } else {
  94. matrix[row] |= (1<<col);
  95. }
  96. KEY_PREV_OFF;
  97. KEY_UNABLE;
  98. _delay_us(150); // from logic analyzer chart
  99. }
  100. }
  101. return 1;
  102. }
  103. bool matrix_is_modified(void)
  104. {
  105. for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
  106. if (matrix[i] != matrix_prev[i])
  107. return true;
  108. }
  109. return false;
  110. }
  111. inline
  112. bool matrix_has_ghost(void)
  113. {
  114. #ifdef MATRIX_HAS_GHOST
  115. for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
  116. if (matrix_has_ghost_in_row(i))
  117. return true;
  118. }
  119. #endif
  120. return false;
  121. }
  122. inline
  123. bool matrix_is_on(uint8_t row, uint8_t col)
  124. {
  125. return (matrix[row] & (1<<col));
  126. }
  127. inline
  128. #if (MATRIX_COLS <= 8)
  129. uint8_t matrix_get_row(uint8_t row)
  130. #else
  131. uint16_t matrix_get_row(uint8_t row)
  132. #endif
  133. {
  134. return matrix[row];
  135. }
  136. void matrix_print(void)
  137. {
  138. #if (MATRIX_COLS <= 8)
  139. print("\nr/c 01234567\n");
  140. #else
  141. print("\nr/c 0123456789ABCDEF\n");
  142. #endif
  143. for (uint8_t row = 0; row < matrix_rows(); row++) {
  144. phex(row); print(": ");
  145. #if (MATRIX_COLS <= 8)
  146. pbin_reverse(matrix_get_row(row));
  147. #else
  148. pbin_reverse16(matrix_get_row(row));
  149. #endif
  150. #ifdef MATRIX_HAS_GHOST
  151. if (matrix_has_ghost_in_row(row)) {
  152. print(" <ghost");
  153. }
  154. #endif
  155. print("\n");
  156. }
  157. }
  158. uint8_t matrix_key_count(void)
  159. {
  160. uint8_t count = 0;
  161. for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
  162. #if (MATRIX_COLS <= 8)
  163. count += bitpop(matrix[i]);
  164. #else
  165. count += bitpop16(matrix[i]);
  166. #endif
  167. }
  168. return count;
  169. }
  170. #ifdef MATRIX_HAS_GHOST
  171. inline
  172. static bool matrix_has_ghost_in_row(uint8_t row)
  173. {
  174. // no ghost exists in case less than 2 keys on
  175. if (((matrix[row] - 1) & matrix[row]) == 0)
  176. return false;
  177. // ghost exists in case same state as other row
  178. for (uint8_t i=0; i < MATRIX_ROWS; i++) {
  179. if (i != row && (matrix[i] & matrix[row]) == matrix[row])
  180. return true;
  181. }
  182. return false;
  183. }
  184. #endif