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