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.

265 lines
6.7 KiB

  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. // initialize row and col
  149. setup_io_pins();
  150. setup_leds();
  151. // initialize matrix state: all keys off
  152. for (uint8_t i=0; i < MATRIX_ROWS; i++) {
  153. matrix[i] = 0;
  154. matrix_debouncing[i] = 0;
  155. }
  156. matrix_init_quantum();
  157. }
  158. uint8_t matrix_scan(void)
  159. {
  160. for (uint8_t col = 0; col < MATRIX_COLS; col++) { // 0-7
  161. pull_column(col); // output hi on theline
  162. _delay_us(5); // without this wait it won't read stable value.
  163. for (uint8_t row = 0; row < MATRIX_ROWS; row++) { // 0-17
  164. bool prev_bit = matrix_debouncing[row] & (1<<col);
  165. bool curr_bit = *row_pin[row] & row_bit[row];
  166. if (prev_bit != curr_bit) {
  167. matrix_debouncing[row] ^= ((matrix_row_t)1<<col);
  168. if (debouncing) {
  169. dprintf("bounce!: %02X\n", debouncing);
  170. }
  171. debouncing = DEBOUNCE;
  172. }
  173. }
  174. release_column(col);
  175. }
  176. if (debouncing) {
  177. if (--debouncing) {
  178. _delay_ms(1);
  179. } else {
  180. for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
  181. matrix[i] = matrix_debouncing[i];
  182. }
  183. }
  184. }
  185. matrix_scan_quantum();
  186. return 1;
  187. }
  188. bool matrix_is_modified(void)
  189. {
  190. // NOTE: no longer used
  191. return true;
  192. }
  193. inline
  194. bool matrix_has_ghost(void)
  195. {
  196. return false;
  197. }
  198. inline
  199. bool matrix_is_on(uint8_t row, uint8_t col)
  200. {
  201. return (matrix[row] & ((matrix_row_t)1<<col));
  202. }
  203. inline
  204. matrix_row_t matrix_get_row(uint8_t row)
  205. {
  206. return matrix[row];
  207. }
  208. void matrix_print(void)
  209. {
  210. print("\nr/c 01234567\n");
  211. for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
  212. print_hex8(row); print(": ");
  213. print_bin_reverse8(matrix_get_row(row));
  214. print("\n");
  215. }
  216. }
  217. uint8_t matrix_key_count(void)
  218. {
  219. uint8_t count = 0;
  220. for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
  221. for (uint8_t j = 0; j < MATRIX_COLS; j++) {
  222. if (matrix_is_on(i, j))
  223. count++;
  224. }
  225. }
  226. return count;
  227. }