Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

13 роки тому
13 роки тому
13 роки тому
13 роки тому
13 роки тому
13 роки тому
13 роки тому
13 роки тому
13 роки тому
13 роки тому
13 роки тому
13 роки тому
13 роки тому
13 роки тому
13 роки тому
13 роки тому
13 роки тому
13 роки тому
13 роки тому
13 роки тому
13 роки тому
13 роки тому
13 роки тому
13 роки тому
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. /*
  2. Copyright 2011 Jun Wako <[email protected]>
  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. */
  14. /*
  15. * scan matrix
  16. */
  17. #include <stdint.h>
  18. #include <stdbool.h>
  19. #include <avr/io.h>
  20. #include <util/delay.h>
  21. #include "print.h"
  22. #include "util.h"
  23. #include "debug.h"
  24. #include "adb.h"
  25. #include "matrix.h"
  26. #include "report.h"
  27. #include "host.h"
  28. #if (MATRIX_COLS > 16)
  29. # error "MATRIX_COLS must not exceed 16"
  30. #endif
  31. #if (MATRIX_ROWS > 255)
  32. # error "MATRIX_ROWS must not exceed 255"
  33. #endif
  34. static bool has_media_keys = false;
  35. static bool is_iso_layout = false;
  36. static bool is_modified = false;
  37. static report_mouse_t mouse_report = {};
  38. // matrix state buffer(1:on, 0:off)
  39. #if (MATRIX_COLS <= 8)
  40. static uint8_t matrix[MATRIX_ROWS];
  41. #else
  42. static uint16_t matrix[MATRIX_ROWS];
  43. #endif
  44. #ifdef MATRIX_HAS_GHOST
  45. static bool matrix_has_ghost_in_row(uint8_t row);
  46. #endif
  47. static void register_key(uint8_t key);
  48. inline
  49. uint8_t matrix_rows(void)
  50. {
  51. return MATRIX_ROWS;
  52. }
  53. inline
  54. uint8_t matrix_cols(void)
  55. {
  56. return MATRIX_COLS;
  57. }
  58. void matrix_init(void)
  59. {
  60. // LED on
  61. DDRD |= (1<<6); PORTD |= (1<<6);
  62. adb_host_init();
  63. // wait for keyboard to boot up and receive command
  64. _delay_ms(2000);
  65. // device scan
  66. xprintf("Before init:\n");
  67. for (uint8_t addr = 1; addr < 16; addr++) {
  68. uint16_t reg3 = adb_host_talk(addr, ADB_REG_3);
  69. if (reg3) {
  70. xprintf("Scan: addr:%d, reg3:%04X\n", addr, reg3);
  71. }
  72. _delay_ms(20);
  73. }
  74. // Determine ISO keyboard by handler id
  75. // http://lxr.free-electrons.com/source/drivers/macintosh/adbhid.c?v=4.4#L815
  76. uint16_t handler_id = adb_host_talk(ADB_ADDR_KEYBOARD, ADB_REG_3);
  77. switch (handler_id) {
  78. case 0x04: case 0x05: case 0x07: case 0x09: case 0x0D:
  79. case 0x11: case 0x14: case 0x19: case 0x1D: case 0xC1:
  80. case 0xC4: case 0xC7:
  81. is_iso_layout = true;
  82. break;
  83. default:
  84. is_iso_layout = false;
  85. break;
  86. }
  87. // Adjustable keyboard media keys: address=0x07 and handlerID=0x02
  88. has_media_keys = (0x02 == (adb_host_talk(ADB_ADDR_APPLIANCE, ADB_REG_3) & 0xff));
  89. if (has_media_keys) {
  90. xprintf("Found: media keys\n");
  91. }
  92. // Enable keyboard left/right modifier distinction
  93. // Listen Register3
  94. // upper byte: reserved bits 0000, keyboard address 0010
  95. // lower byte: device handler 00000011
  96. adb_host_listen(ADB_ADDR_KEYBOARD, ADB_REG_3, ADB_ADDR_KEYBOARD, ADB_HANDLER_EXTENDED_PROTOCOL);
  97. // device scan
  98. xprintf("After init:\n");
  99. for (uint8_t addr = 1; addr < 16; addr++) {
  100. uint16_t reg3 = adb_host_talk(addr, ADB_REG_3);
  101. if (reg3) {
  102. xprintf("Scan: addr:%d, reg3:%04X\n", addr, reg3);
  103. }
  104. _delay_ms(20);
  105. }
  106. // initialize matrix state: all keys off
  107. for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
  108. debug_enable = true;
  109. //debug_matrix = true;
  110. //debug_keyboard = true;
  111. //debug_mouse = true;
  112. print("debug enabled.\n");
  113. // LED off
  114. DDRD |= (1<<6); PORTD &= ~(1<<6);
  115. return;
  116. }
  117. #ifdef ADB_MOUSE_ENABLE
  118. #ifdef MAX
  119. #undef MAX
  120. #endif
  121. #define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
  122. void adb_mouse_task(void)
  123. {
  124. uint16_t codes;
  125. int16_t x, y;
  126. static int8_t mouseacc;
  127. _delay_ms(12); // delay for preventing overload of poor ADB keyboard controller
  128. codes = adb_host_mouse_recv();
  129. // If nothing received reset mouse acceleration, and quit.
  130. if (!codes) {
  131. mouseacc = 1;
  132. return;
  133. };
  134. // Bit sixteen is button.
  135. if (~codes & (1 << 15))
  136. mouse_report.buttons |= MOUSE_BTN1;
  137. if (codes & (1 << 15))
  138. mouse_report.buttons &= ~MOUSE_BTN1;
  139. // lower seven bits are movement, as signed int_7.
  140. // low byte is X-axis, high byte is Y.
  141. y = (codes>>8 & 0x3F);
  142. x = (codes>>0 & 0x3F);
  143. // bit seven and fifteen is negative
  144. // usb does not use int_8, but int_7 (measuring distance) with sign-bit.
  145. if (codes & (1 << 6))
  146. x = (x-0x40);
  147. if (codes & (1 << 14))
  148. y = (y-0x40);
  149. // Accelerate mouse. (They weren't meant to be used on screens larger than 320x200).
  150. x *= mouseacc;
  151. y *= mouseacc;
  152. // Cap our two bytes per axis to one byte.
  153. // Easier with a MIN-function, but since -MAX(-a,-b) = MIN(a,b)...
  154. // I.E. MIN(MAX(x,-127),127) = -MAX(-MAX(x, -127), -127) = MIN(-MIN(-x,127),127)
  155. mouse_report.x = -MAX(-MAX(x, -127), -127);
  156. mouse_report.y = -MAX(-MAX(y, -127), -127);
  157. if (debug_mouse) {
  158. print("adb_host_mouse_recv: "); print_bin16(codes); print("\n");
  159. print("adb_mouse raw: [");
  160. phex(mouseacc); print(" ");
  161. phex(mouse_report.buttons); print("|");
  162. print_decs(mouse_report.x); print(" ");
  163. print_decs(mouse_report.y); print("]\n");
  164. }
  165. // Send result by usb.
  166. host_mouse_send(&mouse_report);
  167. // increase acceleration of mouse
  168. mouseacc += ( mouseacc < ADB_MOUSE_MAXACC ? 1 : 0 );
  169. return;
  170. }
  171. #endif
  172. uint8_t matrix_scan(void)
  173. {
  174. /* extra_key is volatile and more convoluted than necessary because gcc refused
  175. to generate valid code otherwise. Making extra_key uint8_t and constructing codes
  176. here via codes = extra_key<<8 | 0xFF; would consistently fail to even LOAD
  177. extra_key from memory, and leave garbage in the high byte of codes. I tried
  178. dozens of code variations and it kept generating broken assembly output. So
  179. beware if attempting to make extra_key code more logical and efficient. */
  180. static volatile uint16_t extra_key = 0xFFFF;
  181. uint16_t codes;
  182. uint8_t key0, key1;
  183. is_modified = false;
  184. codes = extra_key;
  185. extra_key = 0xFFFF;
  186. if ( codes == 0xFFFF )
  187. {
  188. _delay_ms(12); // delay for preventing overload of poor ADB keyboard controller
  189. codes = adb_host_kbd_recv(ADB_ADDR_KEYBOARD);
  190. // Adjustable keybaord media keys
  191. if (codes == 0 && has_media_keys &&
  192. (codes = adb_host_kbd_recv(ADB_ADDR_APPLIANCE))) {
  193. // key1
  194. switch (codes & 0x7f ) {
  195. case 0x00: // Mic
  196. codes = (codes & ~0x007f) | 0x42;
  197. break;
  198. case 0x01: // Mute
  199. codes = (codes & ~0x007f) | 0x4a;
  200. break;
  201. case 0x02: // Volume down
  202. codes = (codes & ~0x007f) | 0x49;
  203. break;
  204. case 0x03: // Volume Up
  205. codes = (codes & ~0x007f) | 0x48;
  206. break;
  207. case 0x7F: // no code
  208. break;
  209. default:
  210. xprintf("ERROR: media key1\n");
  211. return 0x11;
  212. }
  213. // key0
  214. switch ((codes >> 8) & 0x7f ) {
  215. case 0x00: // Mic
  216. codes = (codes & ~0x7f00) | (0x42 << 8);
  217. break;
  218. case 0x01: // Mute
  219. codes = (codes & ~0x7f00) | (0x4a << 8);
  220. break;
  221. case 0x02: // Volume down
  222. codes = (codes & ~0x7f00) | (0x49 << 8);
  223. break;
  224. case 0x03: // Volume Up
  225. codes = (codes & ~0x7f00) | (0x48 << 8);
  226. break;
  227. default:
  228. xprintf("ERROR: media key0\n");
  229. return 0x10;
  230. }
  231. }
  232. }
  233. key0 = codes>>8;
  234. key1 = codes&0xFF;
  235. if (debug_matrix && codes) {
  236. print("adb_host_kbd_recv: "); phex16(codes); print("\n");
  237. }
  238. if (codes == 0) { // no keys
  239. return 0;
  240. } else if (codes == 0x7F7F) { // power key press
  241. register_key(0x7F);
  242. } else if (codes == 0xFFFF) { // power key release
  243. register_key(0xFF);
  244. } else if (key0 == 0xFF) { // error
  245. xprintf("adb_host_kbd_recv: ERROR(%d)\n", codes);
  246. // something wrong or plug-in
  247. matrix_init();
  248. return key1;
  249. } else {
  250. /* Swap codes for ISO keyboard
  251. * https://github.com/tmk/tmk_keyboard/issues/35
  252. *
  253. * ANSI
  254. * ,----------- ----------.
  255. * | *a| 1| 2 =|Backspa|
  256. * |----------- ----------|
  257. * |Tab | Q| | ]| *c|
  258. * |----------- ----------|
  259. * |CapsLo| A| '|Return |
  260. * |----------- ----------|
  261. * |Shift | Shift |
  262. * `----------- ----------'
  263. *
  264. * ISO
  265. * ,----------- ----------.
  266. * | *a| 1| 2 =|Backspa|
  267. * |----------- ----------|
  268. * |Tab | Q| | ]|Retur|
  269. * |----------- -----` |
  270. * |CapsLo| A| '| *c| |
  271. * |----------- ----------|
  272. * |Shif| *b| Shift |
  273. * `----------- ----------'
  274. *
  275. * ADB scan code USB usage
  276. * ------------- ---------
  277. * Key ANSI ISO ANSI ISO
  278. * ---------------------------------------------
  279. * *a 0x32 0x0A 0x35 0x35
  280. * *b ---- 0x32 ---- 0x64
  281. * *c 0x2A 0x2A 0x31 0x31(or 0x32)
  282. */
  283. if (is_iso_layout) {
  284. if ((key0 & 0x7F) == 0x32) {
  285. key0 = (key0 & 0x80) | 0x0A;
  286. } else if ((key0 & 0x7F) == 0x0A) {
  287. key0 = (key0 & 0x80) | 0x32;
  288. }
  289. }
  290. register_key(key0);
  291. if (key1 != 0xFF) // key1 is 0xFF when no second key.
  292. extra_key = key1<<8 | 0xFF; // process in a separate call
  293. }
  294. return 1;
  295. }
  296. bool matrix_is_modified(void)
  297. {
  298. return is_modified;
  299. }
  300. inline
  301. bool matrix_has_ghost(void)
  302. {
  303. #ifdef MATRIX_HAS_GHOST
  304. for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
  305. if (matrix_has_ghost_in_row(i))
  306. return true;
  307. }
  308. #endif
  309. return false;
  310. }
  311. inline
  312. bool matrix_is_on(uint8_t row, uint8_t col)
  313. {
  314. return (matrix[row] & (1<<col));
  315. }
  316. inline
  317. #if (MATRIX_COLS <= 8)
  318. uint8_t matrix_get_row(uint8_t row)
  319. #else
  320. uint16_t matrix_get_row(uint8_t row)
  321. #endif
  322. {
  323. return matrix[row];
  324. }
  325. void matrix_print(void)
  326. {
  327. if (!debug_matrix) return;
  328. #if (MATRIX_COLS <= 8)
  329. print("r/c 01234567\n");
  330. #else
  331. print("r/c 0123456789ABCDEF\n");
  332. #endif
  333. for (uint8_t row = 0; row < matrix_rows(); row++) {
  334. phex(row); print(": ");
  335. #if (MATRIX_COLS <= 8)
  336. pbin_reverse(matrix_get_row(row));
  337. #else
  338. pbin_reverse16(matrix_get_row(row));
  339. #endif
  340. #ifdef MATRIX_HAS_GHOST
  341. if (matrix_has_ghost_in_row(row)) {
  342. print(" <ghost");
  343. }
  344. #endif
  345. print("\n");
  346. }
  347. }
  348. uint8_t matrix_key_count(void)
  349. {
  350. uint8_t count = 0;
  351. for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
  352. #if (MATRIX_COLS <= 8)
  353. count += bitpop(matrix[i]);
  354. #else
  355. count += bitpop16(matrix[i]);
  356. #endif
  357. }
  358. return count;
  359. }
  360. #ifdef MATRIX_HAS_GHOST
  361. inline
  362. static bool matrix_has_ghost_in_row(uint8_t row)
  363. {
  364. // no ghost exists in case less than 2 keys on
  365. if (((matrix[row] - 1) & matrix[row]) == 0)
  366. return false;
  367. // ghost exists in case same state as other row
  368. for (uint8_t i=0; i < MATRIX_ROWS; i++) {
  369. if (i != row && (matrix[i] & matrix[row]) == matrix[row])
  370. return true;
  371. }
  372. return false;
  373. }
  374. #endif
  375. inline
  376. static void register_key(uint8_t key)
  377. {
  378. uint8_t col, row;
  379. col = key&0x07;
  380. row = (key>>3)&0x0F;
  381. if (key&0x80) {
  382. matrix[row] &= ~(1<<col);
  383. } else {
  384. matrix[row] |= (1<<col);
  385. }
  386. is_modified = true;
  387. }