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