matrix.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /* Copyright 2012 Jun Wako <wakojun@gmail.com>: TMK Matrix
  2. * Copyright 2018 bakageta <amo@bakageta.com>
  3. *
  4. * This is heavily based on hid_liber/board.{c|h}.
  5. * https://github.com/BathroomEpiphanies/AVR-Keyboard
  6. *
  7. * Copyright (c) 2012 Fredrik Atmer, Bathroom Epiphanies Inc
  8. * http://bathroomepiphanies.com
  9. *
  10. * This program is free software: you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation, either version 2 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. */
  23. #include <stdint.h>
  24. #include <stdbool.h>
  25. #if defined(__AVR__)
  26. #include <avr/io.h>
  27. #endif
  28. #include <util/delay.h>
  29. #include "wait.h"
  30. #include "print.h"
  31. #include "debug.h"
  32. #include "util.h"
  33. #include "matrix.h"
  34. #include "timer.h"
  35. #ifndef DEBOUNCE
  36. # define DEBOUNCE 5
  37. #endif
  38. static uint8_t debouncing = DEBOUNCE;
  39. // bit array of key state(1:on, 0:off)
  40. static matrix_row_t matrix[MATRIX_ROWS];
  41. static matrix_row_t matrix_debouncing[MATRIX_ROWS];
  42. #define _DDRA (uint8_t *const)&DDRA
  43. #define _DDRB (uint8_t *const)&DDRB
  44. #define _DDRC (uint8_t *const)&DDRC
  45. #define _DDRD (uint8_t *const)&DDRD
  46. #define _DDRE (uint8_t *const)&DDRE
  47. #define _DDRF (uint8_t *const)&DDRF
  48. #define _PINA (uint8_t *const)&PINA
  49. #define _PINB (uint8_t *const)&PINB
  50. #define _PINC (uint8_t *const)&PINC
  51. #define _PIND (uint8_t *const)&PIND
  52. #define _PINE (uint8_t *const)&PINE
  53. #define _PINF (uint8_t *const)&PINF
  54. #define _PORTA (uint8_t *const)&PORTA
  55. #define _PORTB (uint8_t *const)&PORTB
  56. #define _PORTC (uint8_t *const)&PORTC
  57. #define _PORTD (uint8_t *const)&PORTD
  58. #define _PORTE (uint8_t *const)&PORTE
  59. #define _PORTF (uint8_t *const)&PORTF
  60. #define _BIT0 0x01
  61. #define _BIT1 0x02
  62. #define _BIT2 0x04
  63. #define _BIT3 0x08
  64. #define _BIT4 0x10
  65. #define _BIT5 0x20
  66. #define _BIT6 0x40
  67. #define _BIT7 0x80
  68. /* Specifies the ports and pin numbers for the rows */
  69. static
  70. uint8_t *const row_ddr[MATRIX_ROWS] = {
  71. _DDRB, _DDRB,
  72. _DDRC, _DDRC,
  73. _DDRD, _DDRD, _DDRD, _DDRD, _DDRD, _DDRD, _DDRD, _DDRD,
  74. _DDRF, _DDRF, _DDRF, _DDRF, _DDRF, _DDRF};
  75. static
  76. uint8_t *const row_port[MATRIX_ROWS] = {
  77. _PORTB, _PORTB,
  78. _PORTC, _PORTC,
  79. _PORTD, _PORTD, _PORTD, _PORTD, _PORTD, _PORTD, _PORTD, _PORTD,
  80. _PORTF, _PORTF, _PORTF, _PORTF, _PORTF, _PORTF};
  81. static
  82. uint8_t *const row_pin[MATRIX_ROWS] = {
  83. _PINB, _PINB,
  84. _PINC, _PINC,
  85. _PIND, _PIND, _PIND, _PIND, _PIND, _PIND, _PIND, _PIND,
  86. _PINF, _PINF, _PINF, _PINF, _PINF, _PINF};
  87. static
  88. const uint8_t row_bit[MATRIX_ROWS] = {
  89. _BIT4, _BIT7,
  90. _BIT6, _BIT7,
  91. _BIT0, _BIT1, _BIT2, _BIT3, _BIT4, _BIT5, _BIT6, _BIT7,
  92. _BIT0, _BIT1, _BIT4, _BIT5, _BIT6, _BIT7};
  93. static
  94. const uint8_t mask = 0x0E;
  95. /* Specifies the ports and pin numbers for the columns */
  96. static
  97. const uint8_t col_bit[MATRIX_COLS] = { 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E};
  98. __attribute__ ((weak))
  99. void matrix_init_kb(void) {
  100. matrix_init_user();
  101. }
  102. __attribute__ ((weak))
  103. void matrix_scan_kb(void) {
  104. matrix_scan_user();
  105. }
  106. __attribute__ ((weak))
  107. void matrix_init_user(void) {
  108. }
  109. __attribute__ ((weak))
  110. void matrix_scan_user(void) {
  111. }
  112. static
  113. inline void pull_column(int col) {
  114. PORTB = col_bit[col] | (PORTB & ~mask);
  115. }
  116. static
  117. inline void release_column(int col) {
  118. }
  119. /* PORTB is set as input with pull-up resistors
  120. PORTC,D,E,F are set to high output */
  121. static
  122. void setup_io_pins(void) {
  123. uint8_t row;
  124. DDRB |= 0x0E;
  125. PORTB &= ~0x0E;
  126. for(row = 0; row < MATRIX_ROWS; row++) {
  127. *row_ddr[row] &= ~row_bit[row];
  128. *row_port[row] &= ~row_bit[row];
  129. }
  130. }
  131. static
  132. void setup_leds(void) {
  133. DDRB |= 0x60;
  134. PORTB |= 0x60;
  135. }
  136. inline
  137. uint8_t matrix_rows(void)
  138. {
  139. return MATRIX_ROWS;
  140. }
  141. inline
  142. uint8_t matrix_cols(void)
  143. {
  144. return MATRIX_COLS;
  145. }
  146. void matrix_init(void)
  147. {
  148. // To use PORTF disable JTAG with writing JTD bit twice within four cycles.
  149. MCUCR |= (1<<JTD);
  150. MCUCR |= (1<<JTD);
  151. // initialize row and col
  152. setup_io_pins();
  153. setup_leds();
  154. // initialize matrix state: all keys off
  155. for (uint8_t i=0; i < MATRIX_ROWS; i++) {
  156. matrix[i] = 0;
  157. matrix_debouncing[i] = 0;
  158. }
  159. matrix_init_quantum();
  160. }
  161. uint8_t matrix_scan(void)
  162. {
  163. for (uint8_t col = 0; col < MATRIX_COLS; col++) { // 0-7
  164. pull_column(col); // output hi on theline
  165. _delay_us(5); // without this wait it won't read stable value.
  166. for (uint8_t row = 0; row < MATRIX_ROWS; row++) { // 0-17
  167. bool prev_bit = matrix_debouncing[row] & (1<<col);
  168. bool curr_bit = *row_pin[row] & row_bit[row];
  169. if (prev_bit != curr_bit) {
  170. matrix_debouncing[row] ^= ((matrix_row_t)1<<col);
  171. if (debouncing) {
  172. dprintf("bounce!: %02X\n", debouncing);
  173. }
  174. debouncing = DEBOUNCE;
  175. }
  176. }
  177. release_column(col);
  178. }
  179. if (debouncing) {
  180. if (--debouncing) {
  181. _delay_ms(1);
  182. } else {
  183. for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
  184. matrix[i] = matrix_debouncing[i];
  185. }
  186. }
  187. }
  188. matrix_scan_quantum();
  189. return 1;
  190. }
  191. bool matrix_is_modified(void)
  192. {
  193. // NOTE: no longer used
  194. return true;
  195. }
  196. inline
  197. bool matrix_has_ghost(void)
  198. {
  199. return false;
  200. }
  201. inline
  202. bool matrix_is_on(uint8_t row, uint8_t col)
  203. {
  204. return (matrix[row] & ((matrix_row_t)1<<col));
  205. }
  206. inline
  207. matrix_row_t matrix_get_row(uint8_t row)
  208. {
  209. return matrix[row];
  210. }
  211. void matrix_print(void)
  212. {
  213. print("\nr/c 01234567\n");
  214. for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
  215. phex(row); print(": ");
  216. pbin_reverse(matrix_get_row(row));
  217. print("\n");
  218. }
  219. }
  220. uint8_t matrix_key_count(void)
  221. {
  222. uint8_t count = 0;
  223. for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
  224. for (uint8_t j = 0; j < MATRIX_COLS; j++) {
  225. if (matrix_is_on(i, j))
  226. count++;
  227. }
  228. }
  229. return count;
  230. }