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.

matrix.c 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  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
  29. * f|_________|
  30. * 10| |
  31. * :| E0 XX | 80-FF for E0-prefix codes(use (XX|0x80) as code)
  32. * 1f| |
  33. * ---------
  34. * exceptions:
  35. * 0x83: F8(normal code placed beyond 0x7F)
  36. * 0xFE: PrintScreen
  37. * 0xFF: Puause/Break
  38. */
  39. #define _PRINT_SCREEN (0xFE)
  40. #define _PAUSE_BREAK (0xFF)
  41. #define _ROW(code) (code>>3)
  42. #define _COL(code) (code&0x07)
  43. static bool _matrix_is_modified = false;
  44. // matrix state buffer(1:on, 0:off)
  45. #if (MATRIX_COLS <= 8)
  46. static uint8_t *matrix;
  47. static uint8_t _matrix0[MATRIX_ROWS];
  48. #else
  49. static uint16_t *matrix;
  50. static uint16_t _matrix0[MATRIX_ROWS];
  51. #endif
  52. #ifdef MATRIX_HAS_GHOST
  53. static bool matrix_has_ghost_in_row(uint8_t row);
  54. #endif
  55. static void _matrix_make(uint8_t code);
  56. static void _matrix_break(uint8_t code);
  57. static void _ps2_reset(void);
  58. static void _ps2_set_leds(uint8_t leds);
  59. inline
  60. uint8_t matrix_rows(void)
  61. {
  62. return MATRIX_ROWS;
  63. }
  64. inline
  65. uint8_t matrix_cols(void)
  66. {
  67. return MATRIX_COLS;
  68. }
  69. void matrix_init(void)
  70. {
  71. print_enable = true;
  72. ps2_host_init();
  73. _ps2_reset();
  74. // flush LEDs
  75. _ps2_set_leds(1<<PS2_LED_NUM_LOCK);
  76. _delay_ms(100);
  77. _ps2_set_leds(1<<PS2_LED_NUM_LOCK|1<<PS2_LED_CAPS_LOCK);
  78. _delay_ms(100);
  79. _ps2_set_leds(1<<PS2_LED_NUM_LOCK|1<<PS2_LED_CAPS_LOCK|1<<PS2_LED_SCROLL_LOCK);
  80. _delay_ms(300);
  81. _ps2_set_leds(0x00);
  82. // initialize matrix state: all keys off
  83. for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00;
  84. matrix = _matrix0;
  85. return;
  86. }
  87. uint8_t matrix_scan(void)
  88. {
  89. static enum {
  90. INIT,
  91. BREAK,
  92. E0,
  93. E0_F0,
  94. // states for PrintScreen
  95. E0_12,
  96. E0_12_E0,
  97. E0_F0_7C,
  98. E0_F0_7C_E0,
  99. E0_F0_7C_E0_F0,
  100. // states for Pause/Break
  101. E1,
  102. E1_14,
  103. E1_14_77,
  104. E1_14_77_E1,
  105. E1_14_77_E1_F0,
  106. E1_14_77_E1_F0_14,
  107. E1_14_77_E1_F0_14_F0,
  108. } state = INIT;
  109. _matrix_is_modified = false;
  110. // Pause/Break off(PS/2 has no break for this key)
  111. if (matrix_is_on(_ROW(_PAUSE_BREAK), _COL(_PAUSE_BREAK))) {
  112. _matrix_break(_PAUSE_BREAK);
  113. }
  114. uint8_t code;
  115. while ((code = ps2_host_recv())) {
  116. switch (state) {
  117. case INIT:
  118. switch (code) {
  119. case 0xE0: // 2byte make
  120. state = E0;
  121. break;
  122. case 0xF0: // break code
  123. state = BREAK;
  124. break;
  125. case 0xE1: // Pause/Break
  126. state = E1;
  127. break;
  128. default: // normal key make
  129. if (code < 0x80) {
  130. _matrix_make(code);
  131. } else {
  132. debug("ps/2 unknow code: "); debug_hex(code); debug("\n");
  133. }
  134. state = INIT;
  135. }
  136. break;
  137. case E0:
  138. switch (code) {
  139. case 0x12: // PrintScreen(make)
  140. state = E0_12;
  141. break;
  142. case 0x7C: // PrintScreen(typematic)
  143. // ignore
  144. state = INIT;
  145. break;
  146. case 0xF0: // E0 break
  147. state = E0_F0;
  148. break;
  149. default: // E0 make
  150. if (code < 0x80) {
  151. _matrix_make(code|0x80);
  152. } else {
  153. debug("ps/2 unknow code: "); debug_hex(code); debug("\n");
  154. }
  155. state = INIT;
  156. }
  157. break;
  158. case BREAK:
  159. if (code < 0x80) {
  160. _matrix_break(code);
  161. } else {
  162. debug("ps/2 unknow code: "); debug_hex(code); debug("\n");
  163. }
  164. state = INIT;
  165. break;
  166. case E0_F0: // E0 break
  167. switch (code) {
  168. case 0x7C:
  169. state = E0_F0_7C;
  170. break;
  171. default:
  172. if (code < 0x80) {
  173. _matrix_break(code|0x80);
  174. } else {
  175. debug("ps/2 unknow code: "); debug_hex(code); debug("\n");
  176. }
  177. state = INIT;
  178. }
  179. break;
  180. /* PrintScreen(make) */
  181. case E0_12:
  182. switch (code) {
  183. case 0xE0:
  184. state = E0_12_E0;
  185. break;
  186. default:
  187. state = INIT;
  188. }
  189. break;
  190. case E0_12_E0:
  191. switch (code) {
  192. case 0x7C:
  193. _matrix_make(_PRINT_SCREEN);
  194. state = INIT;
  195. break;
  196. default:
  197. state = INIT;
  198. }
  199. break;
  200. /* PrintScreen(break) */
  201. case E0_F0_7C:
  202. switch (code) {
  203. case 0xE0:
  204. state = E0_F0_7C_E0;
  205. break;
  206. default:
  207. state = INIT;
  208. }
  209. break;
  210. case E0_F0_7C_E0:
  211. switch (code) {
  212. case 0xF0:
  213. state = E0_F0_7C_E0_F0;
  214. break;
  215. default:
  216. state = INIT;
  217. }
  218. break;
  219. case E0_F0_7C_E0_F0:
  220. switch (code) {
  221. case 0x12:
  222. _matrix_break(_PRINT_SCREEN);
  223. state = INIT;
  224. break;
  225. default:
  226. state = INIT;
  227. }
  228. break;
  229. /* Pause/Break */
  230. case E1:
  231. switch (code) {
  232. case 0x14:
  233. state = E1_14;
  234. break;
  235. default:
  236. state = INIT;
  237. }
  238. break;
  239. case E1_14:
  240. switch (code) {
  241. case 0x77:
  242. state = E1_14_77;
  243. break;
  244. default:
  245. state = INIT;
  246. }
  247. break;
  248. case E1_14_77:
  249. switch (code) {
  250. case 0xE1:
  251. state = E1_14_77_E1;
  252. break;
  253. default:
  254. state = INIT;
  255. }
  256. break;
  257. case E1_14_77_E1:
  258. switch (code) {
  259. case 0xF0:
  260. state = E1_14_77_E1_F0;
  261. break;
  262. default:
  263. state = INIT;
  264. }
  265. break;
  266. case E1_14_77_E1_F0:
  267. switch (code) {
  268. case 0x14:
  269. state = E1_14_77_E1_F0_14;
  270. break;
  271. default:
  272. state = INIT;
  273. }
  274. break;
  275. case E1_14_77_E1_F0_14:
  276. switch (code) {
  277. case 0xF0:
  278. state = E1_14_77_E1_F0_14_F0;
  279. break;
  280. default:
  281. state = INIT;
  282. }
  283. break;
  284. case E1_14_77_E1_F0_14_F0:
  285. switch (code) {
  286. case 0x77:
  287. _matrix_make(_PAUSE_BREAK);
  288. state = INIT;
  289. break;
  290. default:
  291. state = INIT;
  292. }
  293. break;
  294. default:
  295. state = INIT;
  296. }
  297. }
  298. static uint8_t prev_leds = 0;
  299. if (prev_leds != usb_keyboard_leds) {
  300. uint8_t leds = 0;
  301. if (usb_keyboard_leds&(1<<USB_LED_SCROLL_LOCK))
  302. leds |= (1<<PS2_LED_SCROLL_LOCK);
  303. if (usb_keyboard_leds&(1<<USB_LED_NUM_LOCK))
  304. leds |= (1<<PS2_LED_NUM_LOCK);
  305. if (usb_keyboard_leds&(1<<USB_LED_CAPS_LOCK))
  306. leds |= (1<<PS2_LED_CAPS_LOCK);
  307. _ps2_set_leds(leds);
  308. prev_leds = usb_keyboard_leds;
  309. }
  310. return 1;
  311. }
  312. bool matrix_is_modified(void)
  313. {
  314. return _matrix_is_modified;
  315. }
  316. inline
  317. bool matrix_has_ghost(void)
  318. {
  319. #ifdef MATRIX_HAS_GHOST
  320. for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
  321. if (matrix_has_ghost_in_row(i))
  322. return true;
  323. }
  324. #endif
  325. return false;
  326. }
  327. inline
  328. bool matrix_is_on(uint8_t row, uint8_t col)
  329. {
  330. return (matrix[row] & (1<<col));
  331. }
  332. inline
  333. #if (MATRIX_COLS <= 8)
  334. uint8_t matrix_get_row(uint8_t row)
  335. #else
  336. uint16_t matrix_get_row(uint8_t row)
  337. #endif
  338. {
  339. return matrix[row];
  340. }
  341. void matrix_print(void)
  342. {
  343. #if (MATRIX_COLS <= 8)
  344. print("\nr/c 01234567\n");
  345. #else
  346. print("\nr/c 0123456789ABCDEF\n");
  347. #endif
  348. for (uint8_t row = 0; row < matrix_rows(); row++) {
  349. phex(row); print(": ");
  350. #if (MATRIX_COLS <= 8)
  351. pbin_reverse(matrix_get_row(row));
  352. #else
  353. pbin_reverse16(matrix_get_row(row));
  354. #endif
  355. #ifdef MATRIX_HAS_GHOST
  356. if (matrix_has_ghost_in_row(row)) {
  357. print(" <ghost");
  358. }
  359. #endif
  360. print("\n");
  361. }
  362. }
  363. uint8_t matrix_key_count(void)
  364. {
  365. uint8_t count = 0;
  366. for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
  367. #if (MATRIX_COLS <= 8)
  368. count += bitpop(matrix[i]);
  369. #else
  370. count += bitpop16(matrix[i]);
  371. #endif
  372. }
  373. return count;
  374. }
  375. #ifdef MATRIX_HAS_GHOST
  376. inline
  377. static bool matrix_has_ghost_in_row(uint8_t row)
  378. {
  379. // no ghost exists in case less than 2 keys on
  380. if (((matrix[row] - 1) & matrix[row]) == 0)
  381. return false;
  382. // ghost exists in case same state as other row
  383. for (uint8_t i=0; i < MATRIX_ROWS; i++) {
  384. if (i != row && (matrix[i] & matrix[row]) == matrix[row])
  385. return true;
  386. }
  387. return false;
  388. }
  389. #endif
  390. inline
  391. static void _matrix_make(uint8_t code)
  392. {
  393. if (!matrix_is_on(_ROW(code), _COL(code))) {
  394. matrix[_ROW(code)] |= 1<<_COL(code);
  395. _matrix_is_modified = true;
  396. }
  397. }
  398. inline
  399. static void _matrix_break(uint8_t code)
  400. {
  401. if (matrix_is_on(_ROW(code), _COL(code))) {
  402. matrix[_ROW(code)] &= ~(1<<_COL(code));
  403. _matrix_is_modified = true;
  404. }
  405. }
  406. static void _ps2_reset(void)
  407. {
  408. ps2_host_send(0xFF);
  409. ps2_host_recv(); // 0xFA
  410. ps2_host_recv(); // 0xAA
  411. _delay_ms(1000);
  412. }
  413. static void _ps2_set_leds(uint8_t leds)
  414. {
  415. ps2_host_send(0xED);
  416. ps2_host_recv(); // 0xFA
  417. ps2_host_send(leds);
  418. ps2_host_recv(); // 0xFA
  419. }