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 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
преди 13 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. /*
  2. * scan matrix
  3. */
  4. #include <stdint.h>
  5. #include <stdbool.h>
  6. #include <avr/io.h>
  7. #include <util/delay.h>
  8. #include "print.h"
  9. #include "util.h"
  10. #include "debug.h"
  11. #include "ps2.h"
  12. #include "usb_keyboard.h"
  13. #include "matrix_skel.h"
  14. #if (MATRIX_COLS > 16)
  15. # error "MATRIX_COLS must not exceed 16"
  16. #endif
  17. #if (MATRIX_ROWS > 255)
  18. # error "MATRIX_ROWS must not exceed 255"
  19. #endif
  20. /*
  21. * Matrix usage:
  22. * "PS/2 Scan Codes Set 2" is assigned to 256(32x8)cells matrix.
  23. * Hmm, It is very sparse and not efficient :(
  24. *
  25. * 8bit
  26. * ---------
  27. * 0| |
  28. * :| XX | 00-7F for normal codes(without E0-prefix)
  29. * f|_________|
  30. * 10| |
  31. * :| E0 XX | 80-FF for E0-prefix codes(use (XX|0x80) as code)
  32. * 1f| |
  33. * ---------
  34. * exceptions:
  35. * 83: F8[0x83](normal codes but > 0x7F)
  36. * FC: PrintScreen[E0 7C or 84]
  37. * FE: Puause
  38. */
  39. #define F8 (0x83)
  40. #define PRINT_SCREEN (0xFC)
  41. #define PAUSE (0xFE)
  42. #define ROW(code) (code>>3)
  43. #define COL(code) (code&0x07)
  44. static bool is_modified = false;
  45. // matrix state buffer(1:on, 0:off)
  46. #if (MATRIX_COLS <= 8)
  47. static uint8_t matrix[MATRIX_ROWS];
  48. #else
  49. static uint16_t matrix[MATRIX_ROWS];
  50. #endif
  51. #ifdef MATRIX_HAS_GHOST
  52. static bool matrix_has_ghost_in_row(uint8_t row);
  53. #endif
  54. static void matrix_make(uint8_t code);
  55. static void matrix_break(uint8_t code);
  56. static void ps2_reset(void);
  57. static void ps2_set_leds(uint8_t leds);
  58. inline
  59. uint8_t matrix_rows(void)
  60. {
  61. return MATRIX_ROWS;
  62. }
  63. inline
  64. uint8_t matrix_cols(void)
  65. {
  66. return MATRIX_COLS;
  67. }
  68. void matrix_init(void)
  69. {
  70. print_enable = true;
  71. ps2_host_init();
  72. ps2_reset();
  73. // flush LEDs
  74. ps2_set_leds(1<<PS2_LED_NUM_LOCK);
  75. _delay_ms(100);
  76. ps2_set_leds(1<<PS2_LED_NUM_LOCK|1<<PS2_LED_CAPS_LOCK);
  77. _delay_ms(100);
  78. ps2_set_leds(1<<PS2_LED_NUM_LOCK|1<<PS2_LED_CAPS_LOCK|1<<PS2_LED_SCROLL_LOCK);
  79. _delay_ms(300);
  80. ps2_set_leds(0x00);
  81. // initialize matrix state: all keys off
  82. for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
  83. return;
  84. }
  85. /*
  86. * PS/2 Scan Code Set 2: Exceptional Handling
  87. *
  88. * There are several keys to be handled exceptionally.
  89. * The scan code for these keys are varied or prefix/postfix'd
  90. * depending on modifier key state.
  91. *
  92. * References:
  93. * http://www.microsoft.com/whdc/archive/scancode.mspx
  94. * http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/scancode.doc
  95. *
  96. *
  97. * Insert, Delete, Home, End, PageUp, PageDown, Up, Down, Right, Left:
  98. * Num Lock: off
  99. * modifiers | make | break
  100. * ----------+---------------------------+----------------------
  101. * Ohter | <make> | <break>
  102. * LShift | E0 F0 12 <make> | <break> E0 12
  103. * RShift | E0 F0 59 <make> | <break> E0 59
  104. * L+RShift | E0 F0 12 E0 F0 59 <make> | <break> E0 59 E0 12
  105. *
  106. * Num Lock: on
  107. * modifiers | make | break
  108. * ----------+---------------------------+----------------------
  109. * Other | E0 12 <make> | <break> E0 F0 12
  110. * Shift'd | <make> | <break>
  111. *
  112. * Handling: ignore these prefix/postfix codes
  113. *
  114. *
  115. * Keypad-/:
  116. * modifiers | make | break
  117. * ----------+---------------------------+----------------------
  118. * Ohter | <make> | <break>
  119. * LShift | E0 F0 12 <make> | <break> E0 12
  120. * RShift | E0 F0 59 <make> | <break> E0 59
  121. * L+RShift | E0 F0 12 E0 F0 59 <make> | <break> E0 59 E0 12
  122. *
  123. * Handling: ignore these prefix/postfix codes
  124. *
  125. *
  126. * PrintScreen:
  127. * With hoding down modifiers, the scan code is sent as following:
  128. *
  129. * modifiers | make | break
  130. * ----------+--------------+-----------------------------------
  131. * Other | E0 12 E0 7C | E0 F0 7C E0 F0 12
  132. * Shift'd | E0 7C | E0 F0 7C
  133. * Control'd | E0 7C | E0 F0 7C
  134. * Alt'd | 84 | F0 84
  135. *
  136. * Handling: ignore prefix/postfix codes and treat both scan code
  137. * E0 7C and 84 as PrintScreen.
  138. *
  139. * Pause:
  140. * With hoding down modifiers, the scan code is sent as following:
  141. *
  142. * modifiers | make(no break code)
  143. * ----------+--------------------------------------------------
  144. * no mods | E1 14 77 E1 F0 14 F0 77
  145. * Control'd | E0 7E E0 F0 7E
  146. *
  147. * Handling: treat these two code sequence as Pause
  148. *
  149. */
  150. uint8_t matrix_scan(void)
  151. {
  152. static enum {
  153. INIT,
  154. F0,
  155. E0,
  156. E0_F0,
  157. // states for Pause/Break
  158. E1,
  159. E1_14,
  160. E1_14_77,
  161. E1_14_77_E1,
  162. E1_14_77_E1_F0,
  163. E1_14_77_E1_F0_14,
  164. E1_14_77_E1_F0_14_F0,
  165. } state = INIT;
  166. is_modified = false;
  167. // Pause/Break off(PS/2 has no break for this key)
  168. if (matrix_is_on(ROW(PAUSE), COL(PAUSE))) {
  169. matrix_break(PAUSE);
  170. }
  171. uint8_t code;
  172. while ((code = ps2_host_recv())) {
  173. debug_hex(code); debug(" ");
  174. switch (state) {
  175. case INIT:
  176. switch (code) {
  177. case 0xE0: // 2byte make
  178. state = E0;
  179. break;
  180. case 0xF0: // break code
  181. state = F0;
  182. break;
  183. case 0xE1: // Pause/Break
  184. state = E1;
  185. break;
  186. case 0x83: // F8
  187. matrix_make(F8);
  188. state = INIT;
  189. break;
  190. case 0x84: // PrintScreen
  191. matrix_make(PRINT_SCREEN);
  192. state = INIT;
  193. break;
  194. default: // normal key make
  195. if (code < 0x80) {
  196. matrix_make(code);
  197. } else {
  198. debug("unexpected scan code at INIT: "); debug_hex(code); debug("\n");
  199. }
  200. state = INIT;
  201. }
  202. break;
  203. case E0:
  204. switch (code) {
  205. case 0x12: // postfix/postfix code for exceptional keys
  206. case 0x59: // postfix/postfix code for exceptional keys
  207. // ignore
  208. state = INIT;
  209. break;
  210. case 0x7E: // former part of Control-Pause[E0 7E E0 F0 7E]
  211. matrix_make(PAUSE);
  212. state = INIT;
  213. break;
  214. case 0xF0: // E0 break
  215. state = E0_F0;
  216. break;
  217. default: // E0 make
  218. if (code < 0x80) {
  219. matrix_make(code|0x80);
  220. } else {
  221. debug("unexpected scan code at E0: "); debug_hex(code); debug("\n");
  222. }
  223. state = INIT;
  224. }
  225. break;
  226. case F0:
  227. switch (code) {
  228. case 0x83:
  229. matrix_break(F8);
  230. state = INIT;
  231. break;
  232. case 0x84:
  233. matrix_break(PRINT_SCREEN);
  234. state = INIT;
  235. break;
  236. default:
  237. if (code < 0x80) {
  238. matrix_break(code);
  239. } else {
  240. debug("unexpected scan code at F0: "); debug_hex(code); debug("\n");
  241. }
  242. state = INIT;
  243. }
  244. break;
  245. case E0_F0: // E0 break
  246. switch (code) {
  247. case 0x12: // postfix/postfix code for exceptional keys
  248. case 0x59: // postfix/postfix code for exceptional keys
  249. case 0x7E: // latter part of Control-Pause[E0 7E E0 F0 7E]
  250. // ignore
  251. state = INIT;
  252. break;
  253. default:
  254. if (code < 0x80) {
  255. matrix_break(code|0x80);
  256. } else {
  257. debug("unexpected scan code at E0_F0: "); debug_hex(code); debug("\n");
  258. }
  259. state = INIT;
  260. }
  261. break;
  262. /* Pause */
  263. case E1:
  264. switch (code) {
  265. case 0x14:
  266. state = E1_14;
  267. break;
  268. default:
  269. state = INIT;
  270. }
  271. break;
  272. case E1_14:
  273. switch (code) {
  274. case 0x77:
  275. state = E1_14_77;
  276. break;
  277. default:
  278. state = INIT;
  279. }
  280. break;
  281. case E1_14_77:
  282. switch (code) {
  283. case 0xE1:
  284. state = E1_14_77_E1;
  285. break;
  286. default:
  287. state = INIT;
  288. }
  289. break;
  290. case E1_14_77_E1:
  291. switch (code) {
  292. case 0xF0:
  293. state = E1_14_77_E1_F0;
  294. break;
  295. default:
  296. state = INIT;
  297. }
  298. break;
  299. case E1_14_77_E1_F0:
  300. switch (code) {
  301. case 0x14:
  302. state = E1_14_77_E1_F0_14;
  303. break;
  304. default:
  305. state = INIT;
  306. }
  307. break;
  308. case E1_14_77_E1_F0_14:
  309. switch (code) {
  310. case 0xF0:
  311. state = E1_14_77_E1_F0_14_F0;
  312. break;
  313. default:
  314. state = INIT;
  315. }
  316. break;
  317. case E1_14_77_E1_F0_14_F0:
  318. switch (code) {
  319. case 0x77:
  320. matrix_make(PAUSE);
  321. state = INIT;
  322. break;
  323. default:
  324. state = INIT;
  325. }
  326. break;
  327. default:
  328. state = INIT;
  329. }
  330. }
  331. // handle LED indicators
  332. static uint8_t prev_leds = 0;
  333. if (prev_leds != usb_keyboard_leds) {
  334. uint8_t leds = 0;
  335. if (usb_keyboard_leds&(1<<USB_LED_SCROLL_LOCK))
  336. leds |= (1<<PS2_LED_SCROLL_LOCK);
  337. if (usb_keyboard_leds&(1<<USB_LED_NUM_LOCK))
  338. leds |= (1<<PS2_LED_NUM_LOCK);
  339. if (usb_keyboard_leds&(1<<USB_LED_CAPS_LOCK))
  340. leds |= (1<<PS2_LED_CAPS_LOCK);
  341. ps2_set_leds(leds);
  342. prev_leds = usb_keyboard_leds;
  343. }
  344. return 1;
  345. }
  346. bool matrix_is_modified(void)
  347. {
  348. return is_modified;
  349. }
  350. inline
  351. bool matrix_has_ghost(void)
  352. {
  353. #ifdef MATRIX_HAS_GHOST
  354. for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
  355. if (matrix_has_ghost_in_row(i))
  356. return true;
  357. }
  358. #endif
  359. return false;
  360. }
  361. inline
  362. bool matrix_is_on(uint8_t row, uint8_t col)
  363. {
  364. return (matrix[row] & (1<<col));
  365. }
  366. inline
  367. #if (MATRIX_COLS <= 8)
  368. uint8_t matrix_get_row(uint8_t row)
  369. #else
  370. uint16_t matrix_get_row(uint8_t row)
  371. #endif
  372. {
  373. return matrix[row];
  374. }
  375. void matrix_print(void)
  376. {
  377. #if (MATRIX_COLS <= 8)
  378. print("\nr/c 01234567\n");
  379. #else
  380. print("\nr/c 0123456789ABCDEF\n");
  381. #endif
  382. for (uint8_t row = 0; row < matrix_rows(); row++) {
  383. phex(row); print(": ");
  384. #if (MATRIX_COLS <= 8)
  385. pbin_reverse(matrix_get_row(row));
  386. #else
  387. pbin_reverse16(matrix_get_row(row));
  388. #endif
  389. #ifdef MATRIX_HAS_GHOST
  390. if (matrix_has_ghost_in_row(row)) {
  391. print(" <ghost");
  392. }
  393. #endif
  394. print("\n");
  395. }
  396. }
  397. uint8_t matrix_key_count(void)
  398. {
  399. uint8_t count = 0;
  400. for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
  401. #if (MATRIX_COLS <= 8)
  402. count += bitpop(matrix[i]);
  403. #else
  404. count += bitpop16(matrix[i]);
  405. #endif
  406. }
  407. return count;
  408. }
  409. #ifdef MATRIX_HAS_GHOST
  410. inline
  411. static bool matrix_has_ghost_in_row(uint8_t row)
  412. {
  413. // no ghost exists in case less than 2 keys on
  414. if (((matrix[row] - 1) & matrix[row]) == 0)
  415. return false;
  416. // ghost exists in case same state as other row
  417. for (uint8_t i=0; i < MATRIX_ROWS; i++) {
  418. if (i != row && (matrix[i] & matrix[row]) == matrix[row])
  419. return true;
  420. }
  421. return false;
  422. }
  423. #endif
  424. inline
  425. static void matrix_make(uint8_t code)
  426. {
  427. if (!matrix_is_on(ROW(code), COL(code))) {
  428. matrix[ROW(code)] |= 1<<COL(code);
  429. is_modified = true;
  430. }
  431. }
  432. inline
  433. static void matrix_break(uint8_t code)
  434. {
  435. if (matrix_is_on(ROW(code), COL(code))) {
  436. matrix[ROW(code)] &= ~(1<<COL(code));
  437. is_modified = true;
  438. }
  439. }
  440. static void ps2_reset(void)
  441. {
  442. ps2_host_send(0xFF);
  443. ps2_host_recv(); // 0xFA
  444. ps2_host_recv(); // 0xAA
  445. _delay_ms(1000);
  446. }
  447. static void ps2_set_leds(uint8_t leds)
  448. {
  449. ps2_host_send(0xED);
  450. ps2_host_recv(); // 0xFA
  451. ps2_host_send(leds);
  452. ps2_host_recv(); // 0xFA
  453. }