keymap.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. // this is the style you want to emulate.
  2. // This is the canonical layout file for the Quantum project. If you want to add another keyboard,
  3. #include QMK_KEYBOARD_H
  4. // Each layer gets a name for readability, which is then used in the keymap matrix below.
  5. // The underscores don't mean anything - you can have a layer called STUFF or any other name.
  6. // Layer names don't all need to be of the same length, obviously, and you can also skip them
  7. // entirely and just use numbers.
  8. enum dichotomy_layers {
  9. _BS,
  10. _SF,
  11. _NM,
  12. _NS,
  13. _MS
  14. };
  15. #define LONGPRESS_COUNT 4
  16. enum dichotomy_keycodes
  17. {
  18. CK_1G = SAFE_RANGE,
  19. CK_BSPE,
  20. CK_QE,
  21. CK_TE, //these 4 CK_XXXX keys are special "alternate long-press" keys controlled with unique timers. Make sure you understand them before you mess with them.
  22. NS_HYPH,
  23. NS_EQU,
  24. NUMKEY,
  25. SFTKEY,
  26. MOUKEY,
  27. MS_BTN1,
  28. MS_BTN2,
  29. MS_BTN3
  30. };
  31. #define CUSTOM_LONGPRESS 150
  32. #define CUSTOM_TOGGLE_TIME 300
  33. #define RED_BRIGHTNESS 3
  34. #define GREEN_BRIGHTNESS 2
  35. #define BLUE_BRIGHTNESS 2
  36. const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
  37. [_BS] = LAYOUT( /* Base layout, nearly qwerty but with modifications because it's not a full keyboard. Obviously. */
  38. CK_TE, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC,
  39. NUMKEY, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, CK_QE,
  40. SFTKEY, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, MOUKEY,
  41. KC_LCTL, KC_LALT, KC_LGUI, KC_RGUI, KC_RALT, KC_RCTL,
  42. MS_BTN3, KC_LBRC, KC_LPRN, KC_SPC, KC_SPC, KC_RPRN, KC_RBRC, MS_BTN3
  43. ),
  44. [_SF] = LAYOUT( /* Shifted layout, small changes (because angle brackets have been moved to thumb cluster buttons) */
  45. _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
  46. _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
  47. _______, _______, _______, _______, _______, _______, _______, _______, NS_HYPH, KC_UNDS, _______, _______,
  48. _______, _______, _______, _______, _______, _______,
  49. _______, _______, KC_LABK, _______, _______, KC_RABK, _______, _______
  50. ),
  51. [_NM] = LAYOUT( /* Number layout, basically the main function layer */
  52. _______, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, _______,
  53. _______, CK_1G, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, CK_BSPE,
  54. _______, KC_F11, KC_F12, KC_F13, KC_F14, KC_F15, KC_F16, KC_F17, KC_F18, KC_F19, KC_F20, _______,
  55. _______, _______, _______, _______, _______, _______,
  56. _______, _______, _______, _______, _______, _______, _______, _______
  57. ),
  58. [_NS] = LAYOUT( /* Shifted number/function layout, for per-key control. Only active when shift is held, and number is toggled or held */
  59. _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
  60. _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_PLUS, NS_EQU, _______,
  61. _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
  62. _______, _______, _______, _______, _______, _______,
  63. _______, _______, _______, _______, _______, _______, _______, _______
  64. ),
  65. [_MS] = LAYOUT( /* Mouse layer, including buttons for clicking. */
  66. _______, _______, _______, _______, _______, _______, KC_VOLU, KC_HOME, KC_PGUP, _______, _______, _______,
  67. _______, _______, _______, _______, _______, _______, _______, MS_BTN1, MS_BTN2, _______, _______, _______,
  68. _______, _______, _______, _______, _______, _______, KC_VOLD, KC_END, KC_PGDN, _______, _______, _______,
  69. _______, _______, _______, _______, KC_UP, _______,
  70. _______, _______, _______, _______, KC_LEFT, KC_DOWN, KC_RGHT, _______
  71. )
  72. };
  73. static uint16_t special_timers[LONGPRESS_COUNT] = {0xFFFF,0xFFFF,0xFFFF,0xFFFF};
  74. static bool special_key_states[LONGPRESS_COUNT] = {0,0,0,0};
  75. static bool special_key_pressed[LONGPRESS_COUNT] = {0,0,0,0};
  76. static uint16_t shift_timer;
  77. static uint16_t num_timer;
  78. static uint16_t mouse_timer;
  79. static uint8_t red_timer;
  80. static uint8_t green_timer;
  81. static uint8_t blue_timer;
  82. static bool shift_singular_key = false;
  83. static bool number_singular_key = false;
  84. static bool mouse_singular_key = false;
  85. static bool capsLED = false;
  86. static bool shiftLED = false;
  87. static bool numLED = false;
  88. static bool mouseLED = false;
  89. static bool shift_held = false;
  90. static bool shift_suspended = false;
  91. report_mouse_t currentReport = {};
  92. bool process_record_user(uint16_t keycode, keyrecord_t *record) {
  93. //uint8_t layer;
  94. //layer = get_highest_layer(layer_state); // get the current layer //Or don't, I didn't use it.
  95. bool returnVal = true; //this is to determine if more key processing is needed.
  96. //custom layer handling for tri_layer,
  97. switch (keycode) {
  98. case NUMKEY:
  99. if (record->event.pressed) {
  100. num_timer = timer_read();
  101. number_singular_key = true;
  102. layer_invert(_NM);
  103. numLED = !numLED;
  104. } else {
  105. if (timer_elapsed(num_timer) < CUSTOM_TOGGLE_TIME && number_singular_key) {
  106. //do nothing, the layer has already been inverted
  107. } else {
  108. layer_invert(_NM);
  109. numLED = !numLED;
  110. }
  111. }
  112. update_tri_layer(_NM, _SF, _NS);
  113. returnVal = false;
  114. break;
  115. //SHIFT is handled as LSHIFT in the general case - 'toggle' shoudl activate caps, while the layer is only active when shift is held.
  116. case SFTKEY:
  117. if (record->event.pressed) {
  118. shift_held = true;
  119. shiftLED = true;
  120. shift_suspended = false;
  121. shift_timer = timer_read();
  122. shift_singular_key = true;
  123. layer_on(_SF);
  124. register_code(KC_LSFT);
  125. } else {
  126. shift_held = false;
  127. shiftLED = false;
  128. if (timer_elapsed(shift_timer) < CUSTOM_TOGGLE_TIME && shift_singular_key) {
  129. //this was basically a toggle, so activate/deactivate caps lock.
  130. SEND_STRING(SS_TAP(X_CAPS_LOCK));
  131. capsLED = !capsLED;
  132. }
  133. layer_off(_SF);
  134. unregister_code(KC_LSFT);
  135. }
  136. update_tri_layer(_NM, _SF, _NS);
  137. returnVal = false;
  138. break;
  139. //MOUSE layer needs to be handled the same way as NUMKEY, but differently from shift
  140. case MOUKEY:
  141. if (record->event.pressed) {
  142. mouse_timer = timer_read();
  143. mouse_singular_key = true;
  144. layer_invert(_MS);
  145. mouseLED = !mouseLED;
  146. } else {
  147. if (timer_elapsed(mouse_timer) < CUSTOM_TOGGLE_TIME && mouse_singular_key){
  148. //do nothing, it was a toggle (and it's already been toggled)
  149. } else {
  150. layer_invert(_MS);
  151. mouseLED = !mouseLED;
  152. }
  153. }
  154. returnVal = false;
  155. break;
  156. //Custom macros for strange keys with different long-tap behavior
  157. case CK_1G:
  158. if (shift_held && shift_suspended){
  159. register_code(KC_LSFT);
  160. shift_suspended = false;
  161. }
  162. if (record->event.pressed) {
  163. special_timers[CK_1G-SAFE_RANGE] = timer_read();
  164. special_key_pressed[CK_1G-SAFE_RANGE] = 1;
  165. } else {
  166. if (special_key_states[CK_1G-SAFE_RANGE]){
  167. //key was activated after custom_longpress, need to close those keycodes
  168. special_key_states[CK_1G-SAFE_RANGE] = 0;
  169. unregister_code(KC_GRAVE);
  170. } else {
  171. if (special_key_pressed[CK_1G-SAFE_RANGE]){
  172. //key was not activated, return macro activating proper, pre-long-tap key
  173. SEND_STRING(SS_TAP(X_1));
  174. special_key_pressed[CK_1G-SAFE_RANGE] = 0;
  175. } else {
  176. //the short key was already sent, because another key was pressed.
  177. //Do nothing.
  178. }
  179. }
  180. }
  181. returnVal = false;
  182. break;
  183. case CK_BSPE:
  184. if (shift_held && shift_suspended){
  185. register_code(KC_LSFT);
  186. shift_suspended = false;
  187. }
  188. if (record->event.pressed) {
  189. special_timers[CK_BSPE-SAFE_RANGE] = timer_read();
  190. special_key_pressed[CK_BSPE-SAFE_RANGE] = 1;
  191. } else {
  192. if (special_key_states[CK_BSPE-SAFE_RANGE]){
  193. //key was activated after custom_longpress, need to close those keycodes
  194. special_key_states[CK_BSPE-SAFE_RANGE] = 0;
  195. unregister_code(KC_ENTER);
  196. } else {
  197. if (special_key_pressed[CK_BSPE-SAFE_RANGE]){
  198. //key was not activated, return macro activating proper, pre-long-tap key
  199. SEND_STRING(SS_TAP(X_BACKSLASH));
  200. special_key_pressed[CK_BSPE-SAFE_RANGE] = 0;
  201. } else {
  202. //the short key was already sent, because another key was pressed.
  203. //Do nothing.
  204. }
  205. }
  206. }
  207. returnVal = false;
  208. break;
  209. case CK_QE:
  210. if (shift_held && shift_suspended){
  211. register_code(KC_LSFT);
  212. shift_suspended = false;
  213. }
  214. if (record->event.pressed) {
  215. special_timers[CK_QE-SAFE_RANGE] = timer_read();
  216. special_key_pressed[CK_QE-SAFE_RANGE] = 1;
  217. } else {
  218. if (special_key_states[CK_QE-SAFE_RANGE]){
  219. //key was activated after custom_longpress, need to close those keycodes
  220. special_key_states[CK_QE-SAFE_RANGE] = 0;
  221. unregister_code(KC_ENTER);
  222. } else {
  223. if (special_key_pressed[CK_QE-SAFE_RANGE]){
  224. //the long-press key was not activated, return macro activating proper, pre-long-tap key
  225. SEND_STRING(SS_TAP(X_QUOTE));
  226. special_key_pressed[CK_QE-SAFE_RANGE] = 0;
  227. } else {
  228. //the short key was already sent, because another key was pressed.
  229. //Do nothing.
  230. }
  231. }
  232. }
  233. returnVal = false;
  234. break;
  235. case CK_TE:
  236. if (shift_held && shift_suspended){
  237. register_code(KC_LSFT);
  238. shift_suspended = false;
  239. }
  240. if (record->event.pressed) {
  241. special_timers[CK_TE-SAFE_RANGE] = timer_read();
  242. special_key_pressed[CK_TE-SAFE_RANGE] = 1;
  243. } else {
  244. if (special_key_states[CK_TE-SAFE_RANGE]){
  245. //key was activated after custom_longpress, need to close those keycodes
  246. special_key_states[CK_TE-SAFE_RANGE] = 0;
  247. unregister_code(KC_ESCAPE);
  248. } else {
  249. if (special_key_pressed[CK_TE-SAFE_RANGE]){
  250. //the long-press key was not activated, return macro activating proper, pre-long-tap key
  251. SEND_STRING(SS_TAP(X_TAB));
  252. special_key_pressed[CK_TE-SAFE_RANGE] = 0;
  253. } else {
  254. //the short key was already sent, because another key was pressed.
  255. //Do nothing.
  256. }
  257. }
  258. }
  259. returnVal = false;
  260. break;
  261. //No-shift keys, they unregister the KC_LSFT code so they can send
  262. //unshifted values - but they don't change the bool. if any other
  263. //key is pressed and the bool is set, KC_LSFT is registered again.
  264. case NS_HYPH:
  265. if (record->event.pressed) {
  266. shift_suspended = true;
  267. unregister_code(KC_LSFT);
  268. register_code(KC_MINS);
  269. } else {
  270. unregister_code(KC_MINS);
  271. if (shift_held && shift_suspended){
  272. register_code(KC_LSFT);
  273. shift_suspended = false;
  274. }
  275. }
  276. returnVal = false;
  277. break;
  278. case NS_EQU:
  279. if (record->event.pressed) {
  280. shift_suspended = true;
  281. unregister_code(KC_LSFT);
  282. register_code(KC_EQUAL);
  283. } else {
  284. unregister_code(KC_EQUAL);
  285. if (shift_held && shift_suspended){
  286. register_code(KC_LSFT);
  287. shift_suspended = false;
  288. }
  289. }
  290. returnVal = false;
  291. break;
  292. //mouse buttons, for 1-3, to update the mouse report:
  293. case MS_BTN1:
  294. currentReport = pointing_device_get_report();
  295. if (record->event.pressed) {
  296. if (shift_held && shift_suspended){
  297. register_code(KC_LSFT);
  298. shift_suspended = false;
  299. }
  300. //update mouse report here
  301. currentReport.buttons |= MOUSE_BTN1; //MOUSE_BTN1 is a const defined in report.h
  302. } else {
  303. //update mouse report here
  304. currentReport.buttons &= ~MOUSE_BTN1;
  305. }
  306. pointing_device_set_report(currentReport);
  307. returnVal = false;
  308. break;
  309. case MS_BTN2:
  310. currentReport = pointing_device_get_report();
  311. if (record->event.pressed) {
  312. if (shift_held && shift_suspended){
  313. register_code(KC_LSFT);
  314. shift_suspended = false;
  315. }
  316. //update mouse report here
  317. currentReport.buttons |= MOUSE_BTN2; //MOUSE_BTN2 is a const defined in report.h
  318. } else {
  319. //update mouse report here
  320. currentReport.buttons &= ~MOUSE_BTN2;
  321. }
  322. pointing_device_set_report(currentReport);
  323. returnVal = false;
  324. break;
  325. case MS_BTN3:
  326. currentReport = pointing_device_get_report();
  327. if (record->event.pressed) {
  328. if (shift_held && shift_suspended){
  329. register_code(KC_LSFT);
  330. shift_suspended = false;
  331. }
  332. //update mouse report here
  333. currentReport.buttons |= MOUSE_BTN3; //MOUSE_BTN3 is a const defined in report.h
  334. } else {
  335. //update mouse report here
  336. currentReport.buttons &= ~MOUSE_BTN3;
  337. }
  338. pointing_device_set_report(currentReport);
  339. returnVal = false;
  340. break;
  341. //Additionally, if NS_ keys are in use, then shift may be held (but is
  342. //disabled for the unshifted keycodes to be send. Check the bool and
  343. //register shift as necessary.
  344. default:
  345. if (shift_held){
  346. register_code(KC_LSFT);
  347. }
  348. break;
  349. }
  350. switch (keycode){
  351. case KC_BSPC:
  352. case KC_NO:
  353. case NUMKEY:
  354. case SFTKEY:
  355. case MOUKEY:
  356. //don't want to reset single key variables
  357. break;
  358. default:
  359. //If any other key was pressed during the layer mod hold period,
  360. //then the layer mod was used momentarily, and should block latching
  361. shift_singular_key = false;
  362. number_singular_key = false;
  363. mouse_singular_key = false;
  364. break;
  365. }
  366. switch (keycode){
  367. case KC_BSPC:
  368. case KC_NO:
  369. case NUMKEY:
  370. case SFTKEY:
  371. case MOUKEY:
  372. case MOUSE_BTN1:
  373. case MOUSE_BTN2:
  374. case MOUSE_BTN3:
  375. case KC_LCTL:
  376. case KC_LALT:
  377. case KC_LGUI:
  378. case KC_RCTL:
  379. case KC_RALT:
  380. case KC_RGUI:
  381. case CK_1G:
  382. case CK_BSPE:
  383. case CK_QE:
  384. case CK_TE:
  385. //Do nothing, don't want to trigger the timer key rollover
  386. break;
  387. default:
  388. //Now we're checking to see if any of the special timer keys are pressed
  389. //if so, we need to activate their short-press features
  390. if (record->event.pressed) {
  391. for (uint8_t i = 0; i<LONGPRESS_COUNT; i++){
  392. if ((!special_key_states[i]) && special_key_pressed[i]){
  393. switch (i + SAFE_RANGE){
  394. case CK_1G:
  395. SEND_STRING(SS_TAP(X_1));
  396. break;
  397. case CK_BSPE:
  398. SEND_STRING(SS_TAP(X_BACKSLASH));
  399. break;
  400. case CK_QE:
  401. SEND_STRING(SS_TAP(X_QUOTE));
  402. break;
  403. case CK_TE:
  404. SEND_STRING(SS_TAP(X_TAB));
  405. break;
  406. }
  407. special_key_pressed[i] = 0;
  408. }
  409. }
  410. } else {
  411. //do nothing, we don't want to trigger short presses on key releases.
  412. }
  413. break;
  414. }
  415. return returnVal;
  416. };
  417. void matrix_scan_user(void) {
  418. //uint8_t layer = get_highest_layer(layer_state);
  419. for (uint8_t i = 0; i<LONGPRESS_COUNT; i++){
  420. if ((timer_elapsed(special_timers[i]) >= CUSTOM_LONGPRESS) && (!special_key_states[i]) && special_key_pressed[i]){
  421. switch (i + SAFE_RANGE){
  422. case CK_1G:
  423. register_code(KC_GRAVE);
  424. break;
  425. case CK_BSPE:
  426. register_code(KC_ENTER);
  427. break;
  428. case CK_QE:
  429. register_code(KC_ENTER);
  430. break;
  431. case CK_TE:
  432. register_code(KC_ESCAPE);
  433. break;
  434. }
  435. special_key_pressed[i] = 0;
  436. special_key_states[i] = 1;
  437. }
  438. }
  439. if (shiftLED || capsLED){
  440. red_timer++;
  441. if (red_timer < RED_BRIGHTNESS){
  442. red_led_on();
  443. } else {
  444. red_timer = 0;
  445. red_led_off();
  446. }
  447. } else {
  448. red_timer = 0;
  449. red_led_off();
  450. }
  451. if (numLED){
  452. green_timer++;
  453. if (green_timer < GREEN_BRIGHTNESS){
  454. grn_led_on();
  455. } else {
  456. green_timer = 0;
  457. grn_led_off();
  458. }
  459. } else {
  460. green_timer = 0;
  461. grn_led_off();
  462. }
  463. if (mouseLED){
  464. blue_timer++;
  465. if (blue_timer < BLUE_BRIGHTNESS){
  466. blu_led_on();
  467. } else {
  468. blue_timer = 0;
  469. blu_led_off();
  470. }
  471. } else {
  472. blue_timer = 0;
  473. blu_led_off();
  474. }
  475. };