arkag.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. #include "arkag.h"
  2. /*
  3. Current Layout and Keeb:
  4. https://github.com/arkag/qmk_firmware/blob/master/keyboards/mechmini/v2/keymaps/arkag/keymap.c
  5. */
  6. // Start: Written by konstantin: vomindoraan
  7. #include <ctype.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. void send_unicode_hex_string(const char *str) {
  11. if (!str) { return; } // Saftey net
  12. while (*str) {
  13. // Find the next code point (token) in the string
  14. for (; *str == ' '; str++);
  15. size_t n = strcspn(str, " "); // Length of the current token
  16. char code_point[n+1];
  17. strncpy(code_point, str, n);
  18. code_point[n] = '\0'; // Make sure it's null-terminated
  19. // Normalize the code point: make all hex digits lowercase
  20. for (char *p = code_point; *p; p++) {
  21. *p = tolower(*p);
  22. }
  23. // Send the code point as a Unicode input string
  24. unicode_input_start();
  25. send_string(code_point);
  26. unicode_input_finish();
  27. str += n; // Move to the first ' ' (or '\0') after the current token
  28. }
  29. }
  30. // End: Written by konstantin: vomindoraan
  31. // Start: Written by Chris Lewis
  32. #ifndef MIN
  33. #define MIN(a,b) (((a)<(b))?(a):(b))
  34. #endif
  35. #ifndef MAX
  36. #define MAX(a,b) (((a)>(b))?(a):(b))
  37. #endif
  38. #define TYPING_SPEED_MAX_VALUE 200
  39. uint8_t typing_speed = 0;
  40. void velocikey_accelerate() {
  41. if (typing_speed < TYPING_SPEED_MAX_VALUE) typing_speed += (TYPING_SPEED_MAX_VALUE / 50);
  42. }
  43. void velocikey_decelerate() {
  44. static uint16_t decay_timer = 0;
  45. if (timer_elapsed(decay_timer) > 500 || decay_timer == 0) {
  46. if (typing_speed > 0) typing_speed -= 1;
  47. //Decay a little faster at half of max speed
  48. if (typing_speed > TYPING_SPEED_MAX_VALUE / 2) typing_speed -= 1;
  49. //Decay even faster at 3/4 of max speed
  50. if (typing_speed > TYPING_SPEED_MAX_VALUE / 4 * 3) typing_speed -= 3;
  51. decay_timer = timer_read();
  52. }
  53. }
  54. uint8_t velocikey_match_speed(uint8_t minValue, uint8_t maxValue) {
  55. return MAX(minValue, maxValue - (maxValue - minValue) * ((float)typing_speed / TYPING_SPEED_MAX_VALUE));
  56. }
  57. // End: Written by Chris Lewis
  58. uint8_t current_os,
  59. mod_primary_mask,
  60. fade_interval,
  61. num_extra_flashes_off = 0;
  62. Color underglow,
  63. flash_color,
  64. saved_color,
  65. hsv_none = {0,0,0};
  66. flashState flash_state = no_flash;
  67. fadeState fade_state = add_fade;
  68. activityState state = boot;
  69. void set_color (Color new, bool update) {
  70. rgblight_sethsv_eeprom_helper(new.h, new.s, new.v, update);
  71. }
  72. void save_color(Color to_save) {
  73. saved_color = to_save;
  74. }
  75. void reset_color(void) {
  76. underglow = saved_color;
  77. }
  78. Color mod_color(Color current_color, bool should_add, uint8_t change_amount) {
  79. save_color(underglow);
  80. int addlim = 359 - change_amount;
  81. int sublim = change_amount;
  82. int leftovers;
  83. if (should_add) {
  84. if (current_color.h <= addlim) {
  85. current_color.h += change_amount;
  86. } else {
  87. leftovers = (359 + change_amount) % 359;
  88. current_color.h = 0 + leftovers;
  89. }
  90. } else {
  91. if (current_color.h >= sublim) {
  92. current_color.h -= change_amount;
  93. } else {
  94. leftovers = change_amount - current_color.h;
  95. current_color.h = 359 - leftovers;
  96. }
  97. }
  98. return current_color;
  99. }
  100. void check_state (void) {
  101. static uint16_t active_timer;
  102. if (!active_timer) {active_timer = timer_read();}
  103. static bool activated, deactivated, slept;
  104. switch (state) {
  105. case active:
  106. if (!activated) {
  107. if (slept) {rgblight_mode_noeeprom(1);}
  108. activated = true;
  109. deactivated = false;
  110. slept = false;
  111. }
  112. fade_interval = velocikey_match_speed(1, 25);
  113. if (timer_elapsed(active_timer) < INACTIVE_DELAY) {return;}
  114. active_timer = timer_read();
  115. state = inactive;
  116. return;
  117. case inactive:
  118. if (!deactivated) {
  119. deactivated = true;
  120. activated = false;
  121. slept = false;
  122. }
  123. velocikey_decelerate();
  124. fade_interval = velocikey_match_speed(1, 25);
  125. if (timer_elapsed(active_timer) < SLEEP_DELAY) {return;}
  126. state = sleeping;
  127. return;
  128. case sleeping:
  129. if (!slept) {
  130. rgblight_mode_noeeprom(4);
  131. slept = true;
  132. activated = false;
  133. deactivated = false;
  134. }
  135. return;
  136. case boot:
  137. return;
  138. }
  139. }
  140. void fade_rgb (void) {
  141. static uint16_t fade_timer;
  142. if (state == boot) {return;}
  143. if (!fade_timer) {fade_timer = timer_read();}
  144. if (timer_elapsed(fade_timer) < fade_interval) {return;}
  145. switch (fade_state) {
  146. case add_fade:
  147. if (underglow.h == 359) {
  148. fade_state = sub_fade;
  149. return;
  150. }
  151. underglow.h = underglow.h + 1;
  152. break;
  153. case sub_fade:
  154. if (underglow.h == 0) {
  155. fade_state = add_fade;
  156. return;
  157. }
  158. underglow.h = underglow.h - 1;
  159. break;
  160. }
  161. fade_timer = timer_read();
  162. if (flash_state == no_flash) {
  163. set_color(underglow, false);
  164. }
  165. }
  166. void flash_rgb (void) {
  167. static uint16_t flash_timer;
  168. switch(flash_state) {
  169. case no_flash:
  170. return;
  171. case flash_off:
  172. if (!flash_timer) {flash_timer = timer_read();}
  173. if (timer_elapsed(flash_timer) >= LED_FLASH_DELAY) {
  174. set_color(hsv_none, false);
  175. flash_timer = timer_read();
  176. flash_state = flash_on;
  177. }
  178. return;
  179. case flash_on:
  180. if (timer_elapsed(flash_timer) >= LED_FLASH_DELAY) {
  181. set_color(flash_color, false);
  182. flash_timer = timer_read();
  183. if (num_extra_flashes_off > 0) {
  184. flash_state = flash_off;
  185. num_extra_flashes_off--;
  186. } else {
  187. set_color(underglow, false);
  188. flash_state = no_flash;
  189. }
  190. }
  191. return;
  192. }
  193. }
  194. void set_os (uint8_t os, bool update) {
  195. current_os = os;
  196. if (update) {
  197. eeprom_update_byte(EECONFIG_USERSPACE, current_os);
  198. }
  199. switch (os) {
  200. case OS_MAC:
  201. set_unicode_input_mode(UC_OSX);
  202. underglow = (Color){ 300, 255, 255 };
  203. mod_primary_mask = MOD_GUI_MASK;
  204. break;
  205. case OS_WIN:
  206. set_unicode_input_mode(UC_WINC);
  207. underglow = (Color){ 180, 255, 255 };
  208. mod_primary_mask = MOD_CTL_MASK;
  209. break;
  210. case OS_NIX:
  211. set_unicode_input_mode(UC_LNX);
  212. underglow = (Color){ 60, 255, 255 };
  213. mod_primary_mask = MOD_CTL_MASK;
  214. break;
  215. default:
  216. underglow = (Color){ 0, 0, 255 };
  217. mod_primary_mask = MOD_CTL_MASK;
  218. }
  219. set_color(underglow, update);
  220. flash_color = underglow;
  221. flash_state = flash_off;
  222. state = boot;
  223. num_extra_flashes_off = 1;
  224. }
  225. void tap_key(uint8_t keycode) {
  226. register_code(keycode);
  227. unregister_code(keycode);
  228. }
  229. // register GUI if Mac or Ctrl if other
  230. void pri_mod(bool press) {
  231. if (press) {
  232. if (current_os == OS_MAC) {
  233. register_code(KC_LGUI);
  234. } else {
  235. register_code(KC_LCTL);
  236. }
  237. } else {
  238. if (current_os == OS_MAC) {
  239. unregister_code(KC_LGUI);
  240. } else {
  241. unregister_code(KC_LCTL);
  242. }
  243. }
  244. }
  245. // register Ctrl if Mac or GUI if other
  246. void sec_mod(bool press) {
  247. if (press) {
  248. if (current_os == OS_MAC) {
  249. register_code(KC_LCTL);
  250. } else {
  251. register_code(KC_LGUI);
  252. }
  253. } else {
  254. if (current_os == OS_MAC) {
  255. unregister_code(KC_LCTL);
  256. } else {
  257. unregister_code(KC_LGUI);
  258. }
  259. }
  260. }
  261. void surround_type(uint8_t num_of_chars, uint16_t keycode, bool use_shift) {
  262. if (use_shift) {
  263. register_code(KC_LSFT);
  264. }
  265. for (int i = 0; i < num_of_chars; i++) {
  266. tap_key(keycode);
  267. }
  268. if (use_shift) {
  269. unregister_code(KC_LSFT);
  270. }
  271. for (int i = 0; i < (num_of_chars/2); i++) {
  272. tap_key(KC_LEFT);
  273. }
  274. }
  275. void long_keystroke(size_t num_of_keys, uint16_t keys[]) {
  276. for (int i = 0; i < num_of_keys-1; i++) {
  277. register_code(keys[i]);
  278. }
  279. tap_key(keys[num_of_keys-1]);
  280. for (int i = 0; i < num_of_keys-1; i++) {
  281. unregister_code(keys[i]);
  282. }
  283. }
  284. void dance_grv (qk_tap_dance_state_t *state, void *user_data) {
  285. if (state->count == 1) {
  286. tap_key(KC_GRV);
  287. } else if (state->count == 2) {
  288. surround_type(2, KC_GRAVE, false);
  289. } else {
  290. surround_type(6, KC_GRAVE, false);
  291. }
  292. }
  293. void dance_quot (qk_tap_dance_state_t *state, void *user_data) {
  294. if (state->count == 1) {
  295. tap_key(KC_QUOT);
  296. } else if (state->count == 2) {
  297. surround_type(2, KC_QUOTE, false);
  298. } else if (state->count == 3) {
  299. surround_type(2, KC_QUOTE, true);
  300. }
  301. }
  302. void dance_strk (qk_tap_dance_state_t *state, void *user_data) {
  303. if (state->count == 1) {
  304. surround_type(4, KC_TILDE, true);
  305. } else if (state->count == 2) {
  306. if (current_os == OS_MAC) {
  307. long_keystroke(3, (uint16_t[]){KC_LGUI, KC_LSFT, KC_4});
  308. } else if (current_os == OS_WIN) {
  309. long_keystroke(3, (uint16_t[]){KC_LGUI, KC_LSFT, KC_S});
  310. } else {
  311. return;
  312. }
  313. }
  314. }
  315. void dance_3 (qk_tap_dance_state_t *state, void *user_data) {
  316. if (state->count == 1) {
  317. tap_key(KC_3);
  318. } else if (state->count == 2) {
  319. send_unicode_hex_string("00E8");
  320. } else if (state->count == 3) {
  321. send_unicode_hex_string("00E9");
  322. }
  323. }
  324. void dance_c (qk_tap_dance_state_t *state, void *user_data) {
  325. if (state->count == 1) {
  326. tap_key(KC_C);
  327. } else if (state->count == 2) {
  328. send_unicode_hex_string("00E7");
  329. }
  330. }
  331. void matrix_init_user(void) {
  332. current_os = eeprom_read_byte(EECONFIG_USERSPACE);
  333. set_os(current_os, false);
  334. }
  335. LEADER_EXTERNS();
  336. void matrix_scan_user(void) {
  337. check_state();
  338. flash_rgb();
  339. fade_rgb();
  340. LEADER_DICTIONARY() {
  341. leading = false;
  342. leader_end();
  343. // begin OS functions
  344. SEQ_TWO_KEYS(KC_P, KC_B) {
  345. if (current_os == OS_WIN) {
  346. SEND_STRING(SS_DOWN(X_LGUI) SS_TAP(X_PAUSE) SS_UP(X_LGUI));
  347. } else {
  348. }
  349. }
  350. SEQ_THREE_KEYS(KC_C, KC_A, KC_D) {
  351. if (current_os == OS_WIN) {
  352. SEND_STRING(SS_DOWN(X_LCTRL) SS_DOWN(X_LALT) SS_TAP(X_DELETE) SS_UP(X_LALT) SS_UP(X_LCTRL));
  353. } else {
  354. }
  355. }
  356. SEQ_FOUR_KEYS(KC_C, KC_A, KC_L, KC_C) {
  357. if (current_os == OS_WIN) {
  358. SEND_STRING(SS_TAP(X_CALCULATOR));
  359. } else if (current_os == OS_MAC) {
  360. SEND_STRING(SS_DOWN(X_LGUI) SS_TAP(X_SPACE) SS_UP(X_LGUI) "calculator" SS_TAP(X_ENTER));
  361. }
  362. }
  363. // end OS functions
  364. // begin format functions
  365. SEQ_ONE_KEY(KC_B) {
  366. surround_type(4, KC_8, true);
  367. }
  368. SEQ_ONE_KEY(KC_I) {
  369. surround_type(2, KC_8, true);
  370. }
  371. SEQ_ONE_KEY(KC_U) {
  372. surround_type(4, KC_MINS, true);
  373. }
  374. SEQ_ONE_KEY(KC_S) {
  375. surround_type(4, KC_GRAVE, true);
  376. }
  377. SEQ_TWO_KEYS(KC_S, KC_S) {
  378. if (current_os == OS_MAC) {
  379. long_keystroke(3, (uint16_t[]){KC_LGUI, KC_LSFT, KC_4});
  380. } else if (current_os == OS_WIN) {
  381. long_keystroke(3, (uint16_t[]){KC_LGUI, KC_LSFT, KC_S});
  382. } else {
  383. return;
  384. }
  385. }
  386. SEQ_ONE_KEY(KC_C) {
  387. surround_type(2, KC_GRAVE, false);
  388. }
  389. SEQ_TWO_KEYS(KC_C, KC_C) {
  390. surround_type(6, KC_GRAVE, false);
  391. }
  392. // end format functions
  393. // start fancy functions
  394. SEQ_THREE_KEYS(KC_C, KC_C, KC_C) {
  395. surround_type(6, KC_GRAVE, false);
  396. pri_mod(true);
  397. tap_key(KC_V);
  398. pri_mod(false);
  399. tap_key(KC_RGHT);
  400. tap_key(KC_RGHT);
  401. tap_key(KC_RGHT);
  402. tap_key(KC_ENTER);
  403. }
  404. // end fancy functions
  405. // start typing functions
  406. SEQ_TWO_KEYS(KC_T, KC_M) {
  407. // ™
  408. send_unicode_hex_string("2122");
  409. }
  410. SEQ_THREE_KEYS(KC_G, KC_G, KC_T) {
  411. SEND_STRING("@GrahamGoldenTech.com");
  412. }
  413. SEQ_THREE_KEYS(KC_L, KC_O, KC_D) {
  414. // ಠ__ಠ
  415. send_unicode_hex_string("0CA0 005F 005F 0CA0");
  416. }
  417. SEQ_FOUR_KEYS(KC_R, KC_E, KC_P, KC_O) {
  418. SEND_STRING("https://github.com/qmk/qmk_firmware/tree/master/users/arkag");
  419. }
  420. SEQ_FOUR_KEYS(KC_F, KC_L, KC_I, KC_P) {
  421. // (╯‵Д′)╯彡┻━┻
  422. send_unicode_hex_string("0028 256F 2035 0414 2032 0029 256F 5F61 253B 2501 253B");
  423. }
  424. SEQ_FIVE_KEYS(KC_U, KC_F, KC_L, KC_I, KC_P) {
  425. // ┬─┬ノ( º _ º ノ)
  426. send_unicode_hex_string("252C 2500 252C 30CE 0028 0020 00BA 0020 005F 0020 00BA 0020 30CE 0029");
  427. }
  428. SEQ_FIVE_KEYS(KC_L, KC_E, KC_N, KC_N, KC_Y) {
  429. // ( ͡° ͜ʖ ͡°)
  430. send_unicode_hex_string("0028 0020 0361 00B0 0020 035C 0296 0020 0361 00B0 0029");
  431. }
  432. SEQ_FIVE_KEYS(KC_S, KC_H, KC_R, KC_U, KC_G) {
  433. // ¯\_(ツ)_/¯
  434. send_unicode_hex_string("00AF 005C 005F 0028 30C4 0029 005F 002F 00AF");
  435. }
  436. // end typing functions
  437. }
  438. }
  439. bool process_record_user(uint16_t keycode, keyrecord_t *record) {
  440. switch (keycode) {
  441. case M_PMOD:
  442. if (record->event.pressed) {
  443. pri_mod(true);
  444. } else {
  445. pri_mod(false);
  446. }
  447. return false;
  448. case M_SMOD:
  449. if (record->event.pressed) {
  450. sec_mod(true);
  451. } else {
  452. sec_mod(false);
  453. }
  454. return false;
  455. case M_OS:
  456. if (record->event.pressed) {
  457. set_os((current_os+1) % _OS_COUNT, true);
  458. }
  459. return false;
  460. default:
  461. if (record->event.pressed) {
  462. state = active;
  463. velocikey_accelerate();
  464. }
  465. return true;
  466. }
  467. }
  468. //Tap Dance Definitions
  469. qk_tap_dance_action_t tap_dance_actions[] = {
  470. [TD_3_GRV_ACT] = ACTION_TAP_DANCE_FN (dance_3),
  471. [TD_C_CED] = ACTION_TAP_DANCE_FN (dance_c),
  472. [TD_GRV_3GRV] = ACTION_TAP_DANCE_FN (dance_grv),
  473. [TD_SING_DOUB] = ACTION_TAP_DANCE_FN (dance_quot),
  474. [TD_STRK_SHOT] = ACTION_TAP_DANCE_FN (dance_strk),
  475. [TD_HYPH_UNDR] = ACTION_TAP_DANCE_DOUBLE (KC_MINS, LSFT(KC_MINS)),
  476. [TD_BRCK_PARN_O] = ACTION_TAP_DANCE_DOUBLE (KC_LBRC, LSFT(KC_9)),
  477. [TD_BRCK_PARN_C] = ACTION_TAP_DANCE_DOUBLE (KC_RBRC, LSFT(KC_0)),
  478. [TD_LALT_RALT] = ACTION_TAP_DANCE_DOUBLE (KC_LALT, KC_RALT),
  479. };