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.

336 lines
12 KiB

  1. /* Copyright 2022 @daliusd
  2. *
  3. * This program is free software: you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation, either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include "flow.h"
  17. extern const uint16_t flow_config[FLOW_COUNT][2];
  18. extern const uint16_t flow_layers_config[FLOW_LAYERS_COUNT][2];
  19. // Represents the states a flow key can be in
  20. typedef enum {
  21. flow_up_unqueued,
  22. flow_up_queued,
  23. flow_up_queued_used,
  24. flow_down_unused,
  25. flow_down_used,
  26. } flow_state_t;
  27. #ifdef FLOW_ONESHOT_TERM
  28. const int g_flow_oneshot_term = FLOW_ONESHOT_TERM;
  29. #else
  30. const int g_flow_oneshot_term = 500;
  31. #endif
  32. #ifdef FLOW_ONESHOT_WAIT_TERM
  33. const int g_flow_oneshot_wait_term = FLOW_ONESHOT_WAIT_TERM;
  34. #else
  35. const int g_flow_oneshot_wait_term = 500;
  36. #endif
  37. flow_state_t flow_state[FLOW_COUNT] = { [0 ... FLOW_COUNT - 1] = flow_up_unqueued };
  38. bool flow_pressed[FLOW_COUNT][2] = { [0 ... FLOW_COUNT - 1] = {false, false} };
  39. uint16_t flow_timers[FLOW_COUNT] = { [0 ... FLOW_COUNT - 1] = 0 };
  40. bool flow_timeout_timers_active[FLOW_COUNT] = { [0 ... FLOW_COUNT - 1] = false };
  41. uint16_t flow_timeout_timers_value[FLOW_COUNT] = { [0 ... FLOW_COUNT - 1] = 0 };
  42. uint16_t flow_timeout_wait_timers_value[FLOW_COUNT] = { [0 ... FLOW_COUNT - 1] = 0 };
  43. flow_state_t flow_layers_state[FLOW_LAYERS_COUNT] = {
  44. [0 ... FLOW_LAYERS_COUNT - 1] = flow_up_unqueued
  45. };
  46. bool flow_layer_timeout_timers_active[FLOW_LAYERS_COUNT] = { [0 ... FLOW_LAYERS_COUNT - 1] = false };
  47. uint16_t flow_layer_timeout_timers_value[FLOW_LAYERS_COUNT] = { [0 ... FLOW_LAYERS_COUNT - 1] = 0 };
  48. uint16_t flow_layer_timeout_wait_timers_value[FLOW_LAYERS_COUNT] = { [0 ... FLOW_LAYERS_COUNT - 1] = 0 };
  49. bool is_flow_ignored_key(uint16_t keycode) {
  50. for (int i = 0; i < FLOW_COUNT; i++) {
  51. if (flow_config[i][0] == keycode) {
  52. return true;
  53. }
  54. }
  55. for (int i = 0; i < FLOW_LAYERS_COUNT; i++) {
  56. if (flow_layers_config[i][0] == keycode) {
  57. return true;
  58. }
  59. }
  60. if (keycode == KC_LSFT || keycode == KC_RSFT
  61. || keycode == KC_LCTL || keycode == KC_RCTL
  62. || keycode == KC_LALT || keycode == KC_RALT
  63. || keycode == KC_LGUI || keycode == KC_RGUI) {
  64. return true;
  65. }
  66. return false;
  67. }
  68. bool update_flow_mods(
  69. uint16_t keycode,
  70. bool pressed
  71. ) {
  72. bool pass = true;
  73. bool flow_key_list_triggered[FLOW_COUNT] = { [0 ... FLOW_COUNT - 1] = false };
  74. bool flow_key_list_pressed[FLOW_COUNT] = { [0 ... FLOW_COUNT - 1] = false };
  75. bool flow_triggered = false;
  76. for (uint8_t i = 0; i < FLOW_COUNT; i++) {
  77. // Layer key
  78. if (keycode == flow_config[i][0]) {
  79. if (pressed) {
  80. flow_pressed[i][0] = true;
  81. } else {
  82. flow_pressed[i][0] = false;
  83. }
  84. // KC mod key
  85. } else if (keycode == flow_config[i][1]) {
  86. if (pressed) {
  87. if (flow_pressed[i][0]) {
  88. flow_pressed[i][1] = true;
  89. flow_key_list_triggered[i] = true;
  90. flow_triggered = true;
  91. flow_key_list_pressed[i] = true;
  92. pass = false;
  93. }
  94. } else if (flow_pressed[i][1]) {
  95. flow_pressed[i][1] = false;
  96. if (flow_pressed[i][0]) {
  97. flow_key_list_triggered[i] = true;
  98. flow_triggered = true;
  99. pass = false;
  100. } else if ((flow_state[i] == flow_down_unused)
  101. || (flow_state[i] == flow_down_used)) {
  102. flow_key_list_triggered[i] = true;
  103. flow_triggered = true;
  104. pass = false;
  105. }
  106. }
  107. }
  108. }
  109. for (uint8_t i = 0; i < FLOW_COUNT; i++) {
  110. if (flow_key_list_triggered[i]) {
  111. if (flow_key_list_pressed[i]) {
  112. if (flow_state[i] == flow_up_unqueued) {
  113. register_code(flow_config[i][1]);
  114. }
  115. flow_timeout_wait_timers_value[i] = timer_read();
  116. flow_state[i] = flow_down_unused;
  117. } else {
  118. // Trigger keyup
  119. switch (flow_state[i]) {
  120. case flow_down_unused:
  121. if (!flow_pressed[i][1]) {
  122. if (timer_elapsed(flow_timeout_wait_timers_value[i]) > g_flow_oneshot_wait_term) {
  123. flow_state[i] = flow_up_unqueued;
  124. unregister_code(flow_config[i][1]);
  125. } else {
  126. // If we didn't use the mod while trigger was held, queue it.
  127. flow_state[i] = flow_up_queued;
  128. flow_timeout_timers_active[i] = true;
  129. flow_timeout_timers_value[i] = timer_read();
  130. }
  131. }
  132. break;
  133. case flow_down_used:
  134. // If we did use the mod while trigger was held, unregister it.
  135. if (!flow_pressed[i][1]) {
  136. flow_state[i] = flow_up_unqueued;
  137. unregister_code(flow_config[i][1]);
  138. }
  139. break;
  140. default:
  141. break;
  142. }
  143. }
  144. } else if (!flow_triggered) {
  145. if (pressed) {
  146. if (!is_flow_ignored_key(keycode)) {
  147. switch (flow_state[i]) {
  148. case flow_up_queued:
  149. flow_state[i] = flow_up_queued_used;
  150. flow_timeout_timers_active[i] = false;
  151. break;
  152. case flow_up_queued_used:
  153. flow_state[i] = flow_up_unqueued;
  154. unregister_code(flow_config[i][1]);
  155. break;
  156. default:
  157. break;
  158. }
  159. }
  160. } else {
  161. if (!is_flow_ignored_key(keycode)) {
  162. // On non-ignored keyup, consider the oneshot used.
  163. switch (flow_state[i]) {
  164. case flow_down_unused:
  165. flow_state[i] = flow_down_used;
  166. break;
  167. case flow_up_queued:
  168. flow_state[i] = flow_up_unqueued;
  169. unregister_code(flow_config[i][1]);
  170. break;
  171. case flow_up_queued_used:
  172. flow_state[i] = flow_up_unqueued;
  173. unregister_code(flow_config[i][1]);
  174. break;
  175. default:
  176. break;
  177. }
  178. }
  179. }
  180. }
  181. }
  182. return pass;
  183. }
  184. void change_pressed_status(uint16_t keycode, bool pressed) {
  185. for (int i = 0; i < FLOW_COUNT; i++) {
  186. if (flow_config[i][0] == keycode) {
  187. flow_pressed[i][0] = pressed;
  188. }
  189. }
  190. }
  191. bool update_flow_layers(
  192. uint16_t keycode,
  193. bool pressed,
  194. keypos_t key_position
  195. ) {
  196. uint8_t key_layer = read_source_layers_cache(key_position);
  197. bool pass = true;
  198. for (int i = 0; i < FLOW_LAYERS_COUNT; i++) {
  199. uint16_t trigger = flow_layers_config[i][0];
  200. uint16_t layer = flow_layers_config[i][1];
  201. if (keycode == trigger) {
  202. if (pressed) {
  203. // Trigger keydown
  204. if (flow_layers_state[i] == flow_up_unqueued) {
  205. layer_on(layer);
  206. change_pressed_status(trigger, true);
  207. }
  208. flow_layer_timeout_wait_timers_value[i] = timer_read();
  209. flow_layers_state[i] = flow_down_unused;
  210. pass = false;
  211. } else {
  212. // Trigger keyup
  213. switch (flow_layers_state[i]) {
  214. case flow_down_unused:
  215. if (timer_elapsed(flow_layer_timeout_wait_timers_value[i]) > g_flow_oneshot_wait_term) {
  216. flow_layers_state[i] = flow_up_unqueued;
  217. layer_off(layer);
  218. change_pressed_status(trigger, false);
  219. pass = false;
  220. } else {
  221. // If we didn't use the layer while trigger was held, queue it.
  222. flow_layers_state[i] = flow_up_queued;
  223. flow_layer_timeout_timers_active[i] = true;
  224. flow_layer_timeout_timers_value[i] = timer_read();
  225. pass = false;
  226. change_pressed_status(trigger, true);
  227. }
  228. break;
  229. case flow_down_used:
  230. // If we did use the layer while trigger was held, turn off it.
  231. flow_layers_state[i] = flow_up_unqueued;
  232. layer_off(layer);
  233. change_pressed_status(trigger, false);
  234. pass = false;
  235. break;
  236. default:
  237. break;
  238. }
  239. }
  240. } else {
  241. if (pressed) {
  242. if (key_layer == layer) {
  243. // On non-ignored keyup, consider the oneshot used.
  244. switch (flow_layers_state[i]) {
  245. case flow_down_unused:
  246. flow_layers_state[i] = flow_down_used;
  247. break;
  248. case flow_up_queued:
  249. flow_layers_state[i] = flow_up_queued_used;
  250. flow_layer_timeout_timers_active[i] = false;
  251. break;
  252. case flow_up_queued_used:
  253. flow_layers_state[i] = flow_up_unqueued;
  254. layer_off(layer);
  255. change_pressed_status(trigger, false);
  256. pass = false;
  257. break;
  258. default:
  259. break;
  260. }
  261. }
  262. } else {
  263. // Ignore key ups from other layers
  264. if (key_layer == layer) {
  265. // On non-ignored keyup, consider the oneshot used.
  266. switch (flow_layers_state[i]) {
  267. case flow_up_queued:
  268. flow_layers_state[i] = flow_up_unqueued;
  269. layer_off(layer);
  270. change_pressed_status(trigger, false);
  271. break;
  272. case flow_up_queued_used:
  273. flow_layers_state[i] = flow_up_unqueued;
  274. layer_off(layer);
  275. change_pressed_status(trigger, false);
  276. break;
  277. default:
  278. break;
  279. }
  280. }
  281. }
  282. }
  283. }
  284. return pass;
  285. }
  286. bool update_flow(
  287. uint16_t keycode,
  288. bool pressed,
  289. keypos_t key_position
  290. ) {
  291. bool pass = update_flow_mods(keycode, pressed);
  292. pass = update_flow_layers(keycode, pressed, key_position) & pass;
  293. return pass;
  294. }
  295. void flow_matrix_scan(void) {
  296. for (int i = 0; i < FLOW_COUNT; i++) {
  297. if (flow_timeout_timers_active[i]
  298. && timer_elapsed(flow_timeout_timers_value[i]) > g_flow_oneshot_term) {
  299. flow_timeout_timers_active[i] = false;
  300. flow_state[i] = flow_up_unqueued;
  301. unregister_code(flow_config[i][1]);
  302. }
  303. }
  304. for (int i = 0; i < FLOW_LAYERS_COUNT; i++) {
  305. if (flow_layer_timeout_timers_active[i]
  306. && timer_elapsed(flow_layer_timeout_timers_value[i]) > g_flow_oneshot_term) {
  307. flow_layer_timeout_timers_active[i] = false;
  308. flow_layers_state[i] = flow_up_unqueued;
  309. layer_off(flow_layers_config[i][1]);
  310. change_pressed_status(flow_layers_config[i][0], false);
  311. }
  312. }
  313. }