matrix.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /*
  2. Copyright 2011 Jun Wako <wakojun@gmail.com>
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. Ported to QMK by Peter Roe <pete@13bit.me>
  14. */
  15. #include <stdint.h>
  16. #include <stdbool.h>
  17. #include <avr/io.h>
  18. #include <util/delay.h>
  19. #include "print.h"
  20. #include "util.h"
  21. #include "debug.h"
  22. #include "adb.h"
  23. #include "matrix.h"
  24. #include "report.h"
  25. #include "host.h"
  26. #include "led.h"
  27. #include "timer.h"
  28. static bool is_iso_layout = false;
  29. // matrix state buffer(1:on, 0:off)
  30. static matrix_row_t matrix[MATRIX_ROWS];
  31. static void register_key(uint8_t key);
  32. __attribute__ ((weak))
  33. void matrix_init_kb(void) {
  34. matrix_init_user();
  35. }
  36. __attribute__ ((weak))
  37. void matrix_scan_kb(void) {
  38. matrix_scan_user();
  39. }
  40. __attribute__ ((weak))
  41. void matrix_init_user(void) {
  42. }
  43. __attribute__ ((weak))
  44. void matrix_scan_user(void) {
  45. }
  46. void matrix_init(void)
  47. {
  48. // LED on
  49. DDRD |= (1<<6); PORTD |= (1<<6);
  50. adb_host_init();
  51. // wait for keyboard to boot up and receive command
  52. _delay_ms(2000);
  53. // initialize matrix state: all keys off
  54. for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
  55. led_set(host_keyboard_leds());
  56. // debug_enable = false;
  57. // debug_matrix = true;
  58. // debug_keyboard = true;
  59. // debug_mouse = true;
  60. // print("debug enabled.\n");
  61. // LED off
  62. DDRD |= (1<<6); PORTD &= ~(1<<6);
  63. matrix_init_quantum();
  64. }
  65. #ifdef ADB_MOUSE_ENABLE
  66. #ifdef MAX
  67. #undef MAX
  68. #endif
  69. #define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
  70. static report_mouse_t mouse_report = {};
  71. void adb_mouse_task(void)
  72. {
  73. uint16_t codes;
  74. int16_t x, y;
  75. static int8_t mouseacc;
  76. /* tick of last polling */
  77. static uint16_t tick_ms;
  78. // polling with 12ms interval
  79. if (timer_elapsed(tick_ms) < 12) return;
  80. tick_ms = timer_read();
  81. codes = adb_host_mouse_recv();
  82. // If nothing received reset mouse acceleration, and quit.
  83. if (!codes) {
  84. mouseacc = 1;
  85. return;
  86. };
  87. // Bit sixteen is button.
  88. if (~codes & (1 << 15))
  89. mouse_report.buttons |= MOUSE_BTN1;
  90. if (codes & (1 << 15))
  91. mouse_report.buttons &= ~MOUSE_BTN1;
  92. // lower seven bits are movement, as signed int_7.
  93. // low byte is X-axis, high byte is Y.
  94. y = (codes>>8 & 0x3F);
  95. x = (codes>>0 & 0x3F);
  96. // bit seven and fifteen is negative
  97. // usb does not use int_8, but int_7 (measuring distance) with sign-bit.
  98. if (codes & (1 << 6))
  99. x = (x-0x40);
  100. if (codes & (1 << 14))
  101. y = (y-0x40);
  102. // Accelerate mouse. (They weren't meant to be used on screens larger than 320x200).
  103. x *= mouseacc;
  104. y *= mouseacc;
  105. // Cap our two bytes per axis to one byte.
  106. // Easier with a MIN-function, but since -MAX(-a,-b) = MIN(a,b)...
  107. // I.E. MIN(MAX(x,-127),127) = -MAX(-MAX(x, -127), -127) = MIN(-MIN(-x,127),127)
  108. mouse_report.x = -MAX(-MAX(x, -127), -127);
  109. mouse_report.y = -MAX(-MAX(y, -127), -127);
  110. if (debug_mouse) {
  111. print("adb_host_mouse_recv: "); print_bin16(codes); print("\n");
  112. print("adb_mouse raw: [");
  113. phex(mouseacc); print(" ");
  114. phex(mouse_report.buttons); print("|");
  115. print_decs(mouse_report.x); print(" ");
  116. print_decs(mouse_report.y); print("]\n");
  117. }
  118. // Send result by usb.
  119. host_mouse_send(&mouse_report);
  120. // increase acceleration of mouse
  121. mouseacc += ( mouseacc < ADB_MOUSE_MAXACC ? 1 : 0 );
  122. return;
  123. }
  124. #endif
  125. uint8_t matrix_scan(void)
  126. {
  127. /* extra_key is volatile and more convoluted than necessary because gcc refused
  128. to generate valid code otherwise. Making extra_key uint8_t and constructing codes
  129. here via codes = extra_key<<8 | 0xFF; would consistently fail to even LOAD
  130. extra_key from memory, and leave garbage in the high byte of codes. I tried
  131. dozens of code variations and it kept generating broken assembly output. So
  132. beware if attempting to make extra_key code more logical and efficient. */
  133. static volatile uint16_t extra_key = 0xFFFF;
  134. uint16_t codes;
  135. uint8_t key0, key1;
  136. /* tick of last polling */
  137. static uint16_t tick_ms;
  138. codes = extra_key;
  139. extra_key = 0xFFFF;
  140. if ( codes == 0xFFFF )
  141. {
  142. // polling with 12ms interval
  143. if (timer_elapsed(tick_ms) < 12) return 0;
  144. tick_ms = timer_read();
  145. codes = adb_host_kbd_recv();
  146. }
  147. key0 = codes>>8;
  148. key1 = codes&0xFF;
  149. if (debug_matrix && codes) {
  150. print("adb_host_kbd_recv: "); phex16(codes); print("\n");
  151. }
  152. if (codes == 0) { // no keys
  153. return 0;
  154. } else if (codes == 0x7F7F) { // power key press
  155. register_key(0x7F);
  156. } else if (codes == 0xFFFF) { // power key release
  157. register_key(0xFF);
  158. } else if (key0 == 0xFF) { // error
  159. xprintf("adb_host_kbd_recv: ERROR(%d)\n", codes);
  160. // something wrong or plug-in
  161. matrix_init();
  162. return key1;
  163. } else {
  164. /* Swap codes for ISO keyboard
  165. * https://github.com/tmk/tmk_keyboard/issues/35
  166. *
  167. * ANSI
  168. * ,----------- ----------.
  169. * | *a| 1| 2 =|Backspa|
  170. * |----------- ----------|
  171. * |Tab | Q| | ]| *c|
  172. * |----------- ----------|
  173. * |CapsLo| A| '|Return |
  174. * |----------- ----------|
  175. * |Shift | Shift |
  176. * `----------- ----------'
  177. *
  178. * ISO
  179. * ,----------- ----------.
  180. * | *a| 1| 2 =|Backspa|
  181. * |----------- ----------|
  182. * |Tab | Q| | ]|Retur|
  183. * |----------- -----` |
  184. * |CapsLo| A| '| *c| |
  185. * |----------- ----------|
  186. * |Shif| *b| Shift |
  187. * `----------- ----------'
  188. *
  189. * ADB scan code USB usage
  190. * ------------- ---------
  191. * Key ANSI ISO ANSI ISO
  192. * ---------------------------------------------
  193. * *a 0x32 0x0A 0x35 0x35
  194. * *b ---- 0x32 ---- 0x64
  195. * *c 0x2A 0x2A 0x31 0x31(or 0x32)
  196. */
  197. if (is_iso_layout) {
  198. if ((key0 & 0x7F) == 0x32) {
  199. key0 = (key0 & 0x80) | 0x0A;
  200. } else if ((key0 & 0x7F) == 0x0A) {
  201. key0 = (key0 & 0x80) | 0x32;
  202. }
  203. }
  204. register_key(key0);
  205. if (key1 != 0xFF) // key1 is 0xFF when no second key.
  206. extra_key = key1<<8 | 0xFF; // process in a separate call
  207. }
  208. matrix_scan_quantum();
  209. return 1;
  210. }
  211. void matrix_print(void){
  212. }
  213. inline
  214. matrix_row_t matrix_get_row(uint8_t row)
  215. {
  216. return matrix[row];
  217. }
  218. inline
  219. static void register_key(uint8_t key)
  220. {
  221. uint8_t col, row;
  222. col = key&0x07;
  223. row = (key>>3)&0x0F;
  224. if (key&0x80) {
  225. matrix[row] &= ~(1<<col);
  226. } else {
  227. matrix[row] |= (1<<col);
  228. }
  229. }