bb-encoder.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. /* Copyright 2021 Batuhan Başerdem
  2. * <baserdem.batuhan@gmail.com> @bbaserdem
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include "bb-encoder.h"
  18. // Need this to call velocikey activation
  19. #ifdef VELOCIKEY_ENABLE
  20. # include "velocikey.h"
  21. #endif // VELOCIKEY_ENABLE
  22. // Need memcpy and memcmp from string.h along with transfer stuff
  23. #ifdef OLED_ENABLE
  24. # include <string.h>
  25. #endif // OLED_ENABLE
  26. /* ROTARY ENCODER
  27. * This contains my general rotary encoder code
  28. * Encoders each have a list of different modes they can be in.
  29. * Each mode also have an on click action as well.
  30. * Modes can be cycled using either shift-click or ctrl-click
  31. * Modes can be reset using OS click
  32. * Some modes are only accessible through some keymap layers
  33. */
  34. // Default state for the encoders
  35. void reset_encoder_state(void) {
  36. userspace_config.e0base = 0;
  37. userspace_config.e0point = 0;
  38. userspace_config.e0rgb = 0;
  39. userspace_config.e1base = 1;
  40. userspace_config.e1point = 1;
  41. userspace_config.e1rgb = 1;
  42. }
  43. // Encoder scroll functionality
  44. bool encoder_update_user(uint8_t index, bool clockwise) {
  45. uint8_t this_number;
  46. // Differentiate layer roles
  47. switch (get_highest_layer(layer_state)) {
  48. # ifdef RGB_MATRIX_ENABLE
  49. case _MEDI:
  50. // Get correct index
  51. if (index == 0) {
  52. this_number = userspace_config.e0rgb;
  53. } else if (index == 1) {
  54. this_number = userspace_config.e1rgb;
  55. } else {
  56. this_number = 128;
  57. }
  58. switch(this_number) {
  59. case 0: // Effect the RGB mode
  60. if (clockwise) {
  61. rgb_matrix_step_noeeprom();
  62. } else {
  63. rgb_matrix_step_reverse_noeeprom();
  64. }
  65. break;
  66. case 1: // Effect the RGB hue
  67. if (clockwise) {
  68. rgb_matrix_increase_hue_noeeprom();
  69. } else {
  70. rgb_matrix_decrease_hue_noeeprom();
  71. }
  72. break;
  73. case 2: // Effect the RGB saturation
  74. if (clockwise) {
  75. rgb_matrix_increase_sat_noeeprom();
  76. } else {
  77. rgb_matrix_decrease_sat_noeeprom();
  78. }
  79. break;
  80. case 3: // Effect the RGB brightness
  81. if (clockwise) {
  82. rgb_matrix_increase_val_noeeprom();
  83. } else {
  84. rgb_matrix_decrease_val_noeeprom();
  85. }
  86. break;
  87. case 4: // Effect the RGB effect speed
  88. if (clockwise) {
  89. rgb_matrix_increase_speed_noeeprom();
  90. } else {
  91. rgb_matrix_decrease_speed_noeeprom();
  92. }
  93. break;
  94. }
  95. break;
  96. # endif // RGB_MATRIX_ENABLE
  97. # ifdef MOUSEKEY_ENABLE
  98. case _MOUS:
  99. // Get correct index
  100. if (index == 0) {
  101. this_number = userspace_config.e0point;
  102. } else if (index == 1) {
  103. this_number = userspace_config.e1point;
  104. } else {
  105. this_number = 128;
  106. }
  107. switch(this_number) {
  108. case 0: // Move mouse on horizontal axis
  109. if (clockwise) {
  110. tap_code(KC_MS_R);
  111. } else {
  112. tap_code(KC_MS_L);
  113. }
  114. break;
  115. case 1: // Move mouse on vertical axis
  116. if (clockwise) {
  117. tap_code(KC_MS_D);
  118. } else {
  119. tap_code(KC_MS_U);
  120. }
  121. break;
  122. case 2: // Move mouse wheel on vertical axis
  123. if (clockwise) {
  124. tap_code(KC_WH_D);
  125. } else {
  126. tap_code(KC_WH_U);
  127. }
  128. break;
  129. case 3: // Move mouse on horizontal axis
  130. if (clockwise) {
  131. tap_code(KC_WH_R);
  132. } else {
  133. tap_code(KC_WH_L);
  134. }
  135. break;
  136. }
  137. break;
  138. # endif // MOUSEKEY_ENABLE
  139. default:
  140. // Get correct index
  141. if (index == 0) {
  142. this_number = userspace_config.e0base;
  143. } else if (index == 1) {
  144. this_number = userspace_config.e1base;
  145. } else {
  146. this_number = 128;
  147. }
  148. switch(this_number) {
  149. case 0: // Volume
  150. if (clockwise) {
  151. tap_code16(KC_VOLU);
  152. } else {
  153. tap_code16(KC_VOLD);
  154. }
  155. break;
  156. case 1: // Song change
  157. if (clockwise) {
  158. tap_code16(KC_MNXT);
  159. } else {
  160. tap_code16(KC_MPRV);
  161. }
  162. break;
  163. case 2: // Move to audio sink
  164. if (clockwise) {
  165. tap_code16(KC_F13);
  166. } else {
  167. tap_code16(S(KC_F13));
  168. }
  169. break;
  170. case 3: // Volume of source
  171. if (clockwise) {
  172. tap_code16(S(KC_VOLU));
  173. } else {
  174. tap_code16(C(KC_VOLD));
  175. }
  176. break;
  177. case 4: // Move to audio source
  178. if (clockwise) {
  179. tap_code16(C(KC_F13));
  180. } else {
  181. tap_code16(C(S(KC_F13)));
  182. }
  183. break;
  184. case 5: // Left-right
  185. if (clockwise) {
  186. tap_code16(KC_RGHT);
  187. } else {
  188. tap_code16(KC_LEFT);
  189. }
  190. break;
  191. case 6: // Up-down
  192. if (clockwise) {
  193. tap_code16(KC_DOWN);
  194. } else {
  195. tap_code16(KC_UP);
  196. }
  197. break;
  198. case 7: // Page Up-down
  199. if (clockwise) {
  200. tap_code16(KC_PGDN);
  201. } else {
  202. tap_code16(KC_PGUP);
  203. }
  204. break;
  205. case 8: // Delete
  206. if (clockwise) {
  207. tap_code16(KC_DEL);
  208. } else {
  209. tap_code16(KC_BSPC);
  210. }
  211. break;
  212. }
  213. break;
  214. }
  215. return false;
  216. }
  217. void encoder_click_action(uint8_t index) {
  218. uint8_t this_number;
  219. // Differentiate layer roles
  220. switch (get_highest_layer(layer_state)) {
  221. # ifdef RGB_MATRIX_ENABLE
  222. case _MEDI:
  223. // Get correct index
  224. if (index == 0) {
  225. this_number = userspace_config.e0rgb;
  226. } else if (index == 1) {
  227. this_number = userspace_config.e1rgb;
  228. } else {
  229. this_number = 128;
  230. }
  231. switch(this_number) {
  232. case 0: // Return to no animation
  233. rgb_matrix_mode_noeeprom(RGB_MATRIX_SOLID_COLOR);
  234. break;
  235. case 1:
  236. case 2:
  237. case 3: // Toggle
  238. rgb_matrix_increase_val_noeeprom();
  239. break;
  240. case 4: // Toggle velocikey
  241. # ifdef VELOCIKEY_ENABLE
  242. velocikey_toggle();
  243. # endif // VELOCIKEY_ENABLE
  244. break;
  245. }
  246. break;
  247. # endif // RGB_MATRIX_ENABLE
  248. # ifdef MOUSEKEY_ENABLE
  249. case _MOUS:
  250. // Get correct index
  251. if (index == 0) {
  252. this_number = userspace_config.e0point;
  253. } else if (index == 1) {
  254. this_number = userspace_config.e1point;
  255. } else {
  256. this_number = 128;
  257. }
  258. switch(this_number) {
  259. case 0: // Left click
  260. tap_code16(KC_BTN1);
  261. break;
  262. case 1: // Right click
  263. tap_code16(KC_BTN2);
  264. break;
  265. case 2:
  266. case 3: // Middle click
  267. tap_code16(KC_BTN2);
  268. break;
  269. }
  270. break;
  271. # endif // MOUSEKEY_ENABLE
  272. default:
  273. // Get correct index
  274. if (index == 0) {
  275. this_number = userspace_config.e0base;
  276. } else if (index == 1) {
  277. this_number = userspace_config.e1base;
  278. } else {
  279. this_number = 128;
  280. }
  281. switch(this_number) {
  282. case 0: // Toggle mute
  283. case 2:
  284. tap_code16(KC_MUTE);
  285. break;
  286. case 1: // Pause
  287. tap_code16(KC_MPLY);
  288. break;
  289. case 3: // Mute source
  290. case 4:
  291. tap_code16(A(KC_MUTE));
  292. break;
  293. case 5: // Insert
  294. tap_code16(KC_INS);
  295. break;
  296. case 6: // Capslock
  297. tap_code16(KC_CAPS);
  298. break;
  299. case 7: // Redo
  300. tap_code16(BB_REDO);
  301. break;
  302. case 8: // Undo
  303. tap_code16(BB_UNDO);
  304. break;
  305. }
  306. break;
  307. }
  308. }
  309. bool process_record_encoder(uint16_t keycode, keyrecord_t *record) {
  310. // Check if and which encoder
  311. int encoder_index = -1;
  312. // Get the pressed encoder
  313. switch (keycode) {
  314. case BB_ENC0:
  315. encoder_index = 0;
  316. break;
  317. case BB_ENC1:
  318. encoder_index = 1;
  319. break;
  320. }
  321. // Activate encoder function of button
  322. if ((encoder_index >= 0) & (!record->event.pressed)) {
  323. // If shifted, move mode one point forward
  324. if (get_mods() & MOD_MASK_SHIFT) {
  325. switch (get_highest_layer(layer_state)) {
  326. # ifdef RGB_MATRIX_ENABLE
  327. case _MEDI:
  328. if (encoder_index == 0) {
  329. userspace_config.e0rgb = (userspace_config.e0rgb + 1) % 5;
  330. } else {
  331. userspace_config.e1rgb = (userspace_config.e1rgb + 1) % 5;
  332. }
  333. break;
  334. # endif // RGB_MATRIX_ENABLE
  335. # ifdef MOUSEKEY_ENABLE
  336. case _MOUS:
  337. if (encoder_index == 0) {
  338. userspace_config.e0point = (userspace_config.e0point + 1) % 4;
  339. } else {
  340. userspace_config.e1point = (userspace_config.e1point + 1) % 4;
  341. }
  342. break;
  343. # endif // MOUSEKEY_ENABLE
  344. default:
  345. if (encoder_index == 0) {
  346. userspace_config.e0base = (userspace_config.e0base + 1) % 9;
  347. } else {
  348. userspace_config.e1base = (userspace_config.e1base + 1) % 9;
  349. }
  350. break;
  351. }
  352. // If ctrl is active, move mode one point backwards
  353. } else if (get_mods() & MOD_MASK_CTRL) {
  354. switch (get_highest_layer(layer_state)) {
  355. # ifdef RGB_MATRIX_ENABLE
  356. case _MEDI:
  357. if (encoder_index == 0) {
  358. userspace_config.e0rgb = (userspace_config.e0rgb + 5 - 1) % 5;
  359. } else {
  360. userspace_config.e1rgb = (userspace_config.e1rgb + 5 - 1) % 5;
  361. }
  362. break;
  363. # endif // RGB_MATRIX_ENABLE
  364. # ifdef MOUSEKEY_ENABLE
  365. case _MOUS:
  366. if (encoder_index == 0) {
  367. userspace_config.e0point = (userspace_config.e0point + 4 - 1) % 4;
  368. } else {
  369. userspace_config.e1point = (userspace_config.e1point + 4 - 1) % 4;
  370. }
  371. break;
  372. # endif // MOUSEKEY_ENABLE
  373. default:
  374. if (encoder_index == 0) {
  375. userspace_config.e0base = (userspace_config.e0base + 9 - 1) % 9;
  376. } else {
  377. userspace_config.e1base = (userspace_config.e1base + 9 - 1) % 9;
  378. }
  379. break;
  380. }
  381. // If meta is active, reset the encoder states
  382. } else if (get_mods() & MOD_MASK_GUI) {
  383. reset_encoder_state();
  384. eeconfig_update_user(userspace_config.raw);
  385. // If nothing else; just perform the click action
  386. } else {
  387. encoder_click_action(encoder_index);
  388. }
  389. }
  390. return true;
  391. }
  392. // For printing status to OLED
  393. #ifdef OLED_ENABLE
  394. void encoder_state_string(uint8_t index, uint8_t layer, char* buffer) {
  395. uint8_t this_number;
  396. // Get the layer straight from the main function
  397. switch (layer) {
  398. // If RGB control mode is enabled
  399. # ifdef RGB_MATRIX_ENABLE
  400. case _MEDI:
  401. // Get correct index
  402. if (index == 0) {
  403. this_number = userspace_config.e0rgb;
  404. } else if (index == 1) {
  405. this_number = userspace_config.e1rgb;
  406. } else {
  407. this_number = 128;
  408. }
  409. switch (this_number) {
  410. case 0:
  411. strcpy(buffer, "ani mode");
  412. break;
  413. case 1:
  414. strcpy(buffer, "hue ");
  415. break;
  416. case 2:
  417. strcpy(buffer, "saturat.");
  418. break;
  419. case 3:
  420. strcpy(buffer, "bright. ");
  421. break;
  422. case 4:
  423. strcpy(buffer, "ani. spd");
  424. break;
  425. default:
  426. strcpy(buffer, " -N/A- ");
  427. break;
  428. }
  429. break;
  430. # endif // RGB_MATRIX_ENABLE
  431. // If pointer control is enabled
  432. # ifdef MOUSEKEY_ENABLE
  433. case _MOUS:
  434. // Get correct index
  435. if (index == 0) {
  436. this_number = userspace_config.e0point;
  437. } else if (index == 1) {
  438. this_number = userspace_config.e1point;
  439. } else {
  440. this_number = 128;
  441. }
  442. switch (this_number) {
  443. case 0:
  444. strcpy(buffer, "Lateral ");
  445. break;
  446. case 1:
  447. strcpy(buffer, "Vertical");
  448. break;
  449. case 2:
  450. strcpy(buffer, "Scr. Ver");
  451. break;
  452. case 3:
  453. strcpy(buffer, "Scr. Lat");
  454. break;
  455. default:
  456. strcpy(buffer, " -N/A- ");
  457. break;
  458. }
  459. break;
  460. # endif // MOUSEKEY_ENABLE
  461. default:
  462. // Get correct index
  463. if (index == 0) {
  464. this_number = userspace_config.e0base;
  465. } else if (index == 1) {
  466. this_number = userspace_config.e1base;
  467. } else {
  468. this_number = 128;
  469. }
  470. switch (this_number) {
  471. case 0:
  472. strcpy(buffer, "Volume ");
  473. break;
  474. case 1:
  475. strcpy(buffer, "Song ");
  476. break;
  477. case 2:
  478. strcpy(buffer, "Sink ");
  479. break;
  480. case 3:
  481. strcpy(buffer, "Src. Vol");
  482. break;
  483. case 4:
  484. strcpy(buffer, "Source ");
  485. break;
  486. case 5:
  487. strcpy(buffer, "Arrow LR");
  488. break;
  489. case 6:
  490. strcpy(buffer, "Arrow UD");
  491. break;
  492. case 7:
  493. strcpy(buffer, "Page U/D");
  494. break;
  495. case 8:
  496. strcpy(buffer, "Erase ");
  497. break;
  498. default:
  499. strcpy(buffer, " -N/A- ");
  500. break;
  501. }
  502. break;
  503. }
  504. }
  505. #endif // OLED_ENABLE