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.

пре 13 година
пре 13 година
пре 13 година
пре 12 година
пре 13 година
пре 12 година
пре 13 година
пре 12 година
пре 13 година
пре 13 година
пре 12 година
пре 13 година
пре 12 година
пре 13 година
пре 12 година
пре 13 година
пре 12 година
пре 13 година
пре 10 година
пре 13 година
пре 13 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 13 година
пре 12 година
пре 13 година
пре 13 година
пре 12 година
пре 13 година
пре 12 година
пре 13 година
пре 13 година
пре 12 година
пре 13 година
пре 10 година
пре 13 година
пре 12 година
пре 13 година
пре 12 година
пре 13 година
пре 12 година
пре 13 година
пре 12 година
пре 12 година
пре 10 година
пре 10 година
пре 13 година
пре 13 година
пре 10 година
пре 10 година
пре 13 година
пре 12 година
пре 13 година
пре 12 година
пре 13 година
пре 12 година
пре 12 година
пре 13 година
пре 12 година
пре 13 година
пре 13 година
пре 10 година
пре 10 година
пре 13 година
пре 12 година
пре 13 година
пре 12 година
пре 13 година
пре 12 година
пре 13 година
пре 10 година
пре 13 година
пре 10 година
пре 10 година
пре 13 година
пре 12 година
пре 13 година
пре 12 година
пре 13 година
пре 10 година
пре 10 година
пре 13 година
пре 12 година
пре 13 година
пре 13 година
пре 12 година
пре 13 година
пре 10 година
пре 10 година
пре 13 година
пре 10 година
пре 13 година
пре 13 година
пре 13 година
пре 13 година
пре 13 година
пре 10 година
пре 10 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  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. #include <stdint.h>
  15. #include <stdbool.h>
  16. #include "action.h"
  17. #include "print.h"
  18. #include "util.h"
  19. #include "debug.h"
  20. #include "ps2.h"
  21. #include "host.h"
  22. #include "led.h"
  23. #include "matrix.h"
  24. static void matrix_make(uint8_t code);
  25. static void matrix_break(uint8_t code);
  26. /*
  27. * Matrix Array usage:
  28. * 'Scan Code Set 2' is assigned into 256(32x8)cell matrix.
  29. * Hmm, it is very sparse and not efficient :(
  30. *
  31. * Notes:
  32. * Both 'Hanguel/English'(F1) and 'Hanja'(F2) collide with 'Delete'(E0 71) and 'Down'(E0 72).
  33. * These two Korean keys need exceptional handling and are not supported for now. Sorry.
  34. *
  35. * 8bit wide
  36. * +---------+
  37. * 0| |
  38. * :| XX | 00-7F for normal codes(without E0-prefix)
  39. * f|_________|
  40. * 10| |
  41. * :| E0 YY | 80-FF for E0-prefixed codes
  42. * 1f| | (<YY>|0x80) is used as matrix position.
  43. * +---------+
  44. *
  45. * Exceptions:
  46. * 0x83: F7(0x83) This is a normal code but beyond 0x7F.
  47. * 0xFC: PrintScreen
  48. * 0xFE: Pause
  49. */
  50. static uint8_t matrix[MATRIX_ROWS];
  51. #define ROW(code) (code>>3)
  52. #define COL(code) (code&0x07)
  53. // matrix positions for exceptional keys
  54. #define F7 (0x83)
  55. #define PRINT_SCREEN (0xFC)
  56. #define PAUSE (0xFE)
  57. static bool is_modified = false;
  58. void matrix_init(void)
  59. {
  60. debug_enable = true;
  61. ps2_host_init();
  62. // initialize matrix state: all keys off
  63. for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
  64. return;
  65. }
  66. /*
  67. * PS/2 Scan Code Set 2: Exceptional Handling
  68. *
  69. * There are several keys to be handled exceptionally.
  70. * The scan code for these keys are varied or prefix/postfix'd
  71. * depending on modifier key state.
  72. *
  73. * Keyboard Scan Code Specification:
  74. * http://www.microsoft.com/whdc/archive/scancode.mspx
  75. * http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/scancode.doc
  76. *
  77. *
  78. * 1) Insert, Delete, Home, End, PageUp, PageDown, Up, Down, Right, Left
  79. * a) when Num Lock is off
  80. * modifiers | make | break
  81. * ----------+---------------------------+----------------------
  82. * Ohter | <make> | <break>
  83. * LShift | E0 F0 12 <make> | <break> E0 12
  84. * RShift | E0 F0 59 <make> | <break> E0 59
  85. * L+RShift | E0 F0 12 E0 F0 59 <make> | <break> E0 59 E0 12
  86. *
  87. * b) when Num Lock is on
  88. * modifiers | make | break
  89. * ----------+---------------------------+----------------------
  90. * Other | E0 12 <make> | <break> E0 F0 12
  91. * Shift'd | <make> | <break>
  92. *
  93. * Handling: These prefix/postfix codes are ignored.
  94. *
  95. *
  96. * 2) Keypad /
  97. * modifiers | make | break
  98. * ----------+---------------------------+----------------------
  99. * Ohter | <make> | <break>
  100. * LShift | E0 F0 12 <make> | <break> E0 12
  101. * RShift | E0 F0 59 <make> | <break> E0 59
  102. * L+RShift | E0 F0 12 E0 F0 59 <make> | <break> E0 59 E0 12
  103. *
  104. * Handling: These prefix/postfix codes are ignored.
  105. *
  106. *
  107. * 3) PrintScreen
  108. * modifiers | make | break
  109. * ----------+--------------+-----------------------------------
  110. * Other | E0 12 E0 7C | E0 F0 7C E0 F0 12
  111. * Shift'd | E0 7C | E0 F0 7C
  112. * Control'd | E0 7C | E0 F0 7C
  113. * Alt'd | 84 | F0 84
  114. *
  115. * Handling: These prefix/postfix codes are ignored, and both scan codes
  116. * 'E0 7C' and 84 are seen as PrintScreen.
  117. *
  118. * 4) Pause
  119. * modifiers | make(no break code)
  120. * ----------+--------------------------------------------------
  121. * Other | E1 14 77 E1 F0 14 F0 77
  122. * Control'd | E0 7E E0 F0 7E
  123. *
  124. * Handling: Both code sequences are treated as a whole.
  125. * And we need a ad hoc 'pseudo break code' hack to get the key off
  126. * because it has no break code.
  127. *
  128. */
  129. uint8_t matrix_scan(void)
  130. {
  131. // scan code reading states
  132. static enum {
  133. INIT,
  134. F0,
  135. E0,
  136. E0_F0,
  137. // Pause
  138. E1,
  139. E1_14,
  140. E1_14_77,
  141. E1_14_77_E1,
  142. E1_14_77_E1_F0,
  143. E1_14_77_E1_F0_14,
  144. E1_14_77_E1_F0_14_F0,
  145. // Control'd Pause
  146. E0_7E,
  147. E0_7E_E0,
  148. E0_7E_E0_F0,
  149. } state = INIT;
  150. is_modified = false;
  151. // 'pseudo break code' hack
  152. if (matrix_is_on(ROW(PAUSE), COL(PAUSE))) {
  153. matrix_break(PAUSE);
  154. }
  155. uint8_t code = ps2_host_recv();
  156. if (code) xprintf("%i\r\n", code);
  157. if (!ps2_error) {
  158. switch (state) {
  159. case INIT:
  160. switch (code) {
  161. case 0xE0:
  162. state = E0;
  163. break;
  164. case 0xF0:
  165. state = F0;
  166. break;
  167. case 0xE1:
  168. state = E1;
  169. break;
  170. case 0x83: // F7
  171. matrix_make(F7);
  172. state = INIT;
  173. break;
  174. case 0x84: // Alt'd PrintScreen
  175. matrix_make(PRINT_SCREEN);
  176. state = INIT;
  177. break;
  178. case 0x00: // Overrun [3]p.25
  179. matrix_clear();
  180. clear_keyboard();
  181. print("Overrun\n");
  182. state = INIT;
  183. break;
  184. case 0xAA: // Self-test passed
  185. case 0xFC: // Self-test failed
  186. printf("BAT %s\n", (code == 0xAA) ? "OK" : "NG");
  187. led_set(host_keyboard_leds());
  188. state = INIT;
  189. break;
  190. default: // normal key make
  191. if (code < 0x80) {
  192. matrix_make(code);
  193. } else {
  194. matrix_clear();
  195. clear_keyboard();
  196. xprintf("unexpected scan code at INIT: %02X\n", code);
  197. }
  198. state = INIT;
  199. }
  200. break;
  201. case E0: // E0-Prefixed
  202. switch (code) {
  203. case 0x12: // to be ignored
  204. case 0x59: // to be ignored
  205. state = INIT;
  206. break;
  207. case 0x7E: // Control'd Pause
  208. state = E0_7E;
  209. break;
  210. case 0xF0:
  211. state = E0_F0;
  212. break;
  213. default:
  214. if (code < 0x80) {
  215. matrix_make(code|0x80);
  216. } else {
  217. matrix_clear();
  218. clear_keyboard();
  219. xprintf("unexpected scan code at E0: %02X\n", code);
  220. }
  221. state = INIT;
  222. }
  223. break;
  224. case F0: // Break code
  225. switch (code) {
  226. case 0x83: // F7
  227. matrix_break(F7);
  228. state = INIT;
  229. break;
  230. case 0x84: // Alt'd PrintScreen
  231. matrix_break(PRINT_SCREEN);
  232. state = INIT;
  233. break;
  234. case 0xF0:
  235. matrix_clear();
  236. clear_keyboard();
  237. xprintf("unexpected scan code at F0: F0(clear and cont.)\n");
  238. break;
  239. default:
  240. if (code < 0x80) {
  241. matrix_break(code);
  242. } else {
  243. matrix_clear();
  244. clear_keyboard();
  245. xprintf("unexpected scan code at F0: %02X\n", code);
  246. }
  247. state = INIT;
  248. }
  249. break;
  250. case E0_F0: // Break code of E0-prefixed
  251. switch (code) {
  252. case 0x12: // to be ignored
  253. case 0x59: // to be ignored
  254. state = INIT;
  255. break;
  256. default:
  257. if (code < 0x80) {
  258. matrix_break(code|0x80);
  259. } else {
  260. matrix_clear();
  261. clear_keyboard();
  262. xprintf("unexpected scan code at E0_F0: %02X\n", code);
  263. }
  264. state = INIT;
  265. }
  266. break;
  267. // following are states of Pause
  268. case E1:
  269. switch (code) {
  270. case 0x14:
  271. state = E1_14;
  272. break;
  273. default:
  274. state = INIT;
  275. }
  276. break;
  277. case E1_14:
  278. switch (code) {
  279. case 0x77:
  280. state = E1_14_77;
  281. break;
  282. default:
  283. state = INIT;
  284. }
  285. break;
  286. case E1_14_77:
  287. switch (code) {
  288. case 0xE1:
  289. state = E1_14_77_E1;
  290. break;
  291. default:
  292. state = INIT;
  293. }
  294. break;
  295. case E1_14_77_E1:
  296. switch (code) {
  297. case 0xF0:
  298. state = E1_14_77_E1_F0;
  299. break;
  300. default:
  301. state = INIT;
  302. }
  303. break;
  304. case E1_14_77_E1_F0:
  305. switch (code) {
  306. case 0x14:
  307. state = E1_14_77_E1_F0_14;
  308. break;
  309. default:
  310. state = INIT;
  311. }
  312. break;
  313. case E1_14_77_E1_F0_14:
  314. switch (code) {
  315. case 0xF0:
  316. state = E1_14_77_E1_F0_14_F0;
  317. break;
  318. default:
  319. state = INIT;
  320. }
  321. break;
  322. case E1_14_77_E1_F0_14_F0:
  323. switch (code) {
  324. case 0x77:
  325. matrix_make(PAUSE);
  326. state = INIT;
  327. break;
  328. default:
  329. state = INIT;
  330. }
  331. break;
  332. // Following are states of Control'd Pause
  333. case E0_7E:
  334. if (code == 0xE0)
  335. state = E0_7E_E0;
  336. else
  337. state = INIT;
  338. break;
  339. case E0_7E_E0:
  340. if (code == 0xF0)
  341. state = E0_7E_E0_F0;
  342. else
  343. state = INIT;
  344. break;
  345. case E0_7E_E0_F0:
  346. if (code == 0x7E)
  347. matrix_make(PAUSE);
  348. state = INIT;
  349. break;
  350. default:
  351. state = INIT;
  352. }
  353. }
  354. // TODO: request RESEND when error occurs?
  355. /*
  356. if (PS2_IS_FAILED(ps2_error)) {
  357. uint8_t ret = ps2_host_send(PS2_RESEND);
  358. xprintf("Resend: %02X\n", ret);
  359. }
  360. */
  361. return 1;
  362. }
  363. inline
  364. bool matrix_is_on(uint8_t row, uint8_t col)
  365. {
  366. return (matrix[row] & (1<<col));
  367. }
  368. inline
  369. uint8_t matrix_get_row(uint8_t row)
  370. {
  371. return matrix[row];
  372. }
  373. uint8_t matrix_key_count(void)
  374. {
  375. uint8_t count = 0;
  376. for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
  377. count += bitpop(matrix[i]);
  378. }
  379. return count;
  380. }
  381. inline
  382. static void matrix_make(uint8_t code)
  383. {
  384. if (!matrix_is_on(ROW(code), COL(code))) {
  385. matrix[ROW(code)] |= 1<<COL(code);
  386. is_modified = true;
  387. }
  388. }
  389. inline
  390. static void matrix_break(uint8_t code)
  391. {
  392. if (matrix_is_on(ROW(code), COL(code))) {
  393. matrix[ROW(code)] &= ~(1<<COL(code));
  394. is_modified = true;
  395. }
  396. }
  397. void matrix_clear(void)
  398. {
  399. for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
  400. }