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.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

action_tapping.c 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. #include <stdint.h>
  2. #include <stdbool.h>
  3. #include "action.h"
  4. #include "action_tapping.h"
  5. #include "timer.h"
  6. #ifdef DEBUG_ACTION
  7. #include "debug.h"
  8. #else
  9. #include "nodebug.h"
  10. #endif
  11. #ifndef NO_ACTION_TAPPING
  12. #define IS_TAPPING() !IS_NOEVENT(tapping_key.event)
  13. #define IS_TAPPING_PRESSED() (IS_TAPPING() && tapping_key.event.pressed)
  14. #define IS_TAPPING_RELEASED() (IS_TAPPING() && !tapping_key.event.pressed)
  15. #define IS_TAPPING_KEY(k) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (k)))
  16. #define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < TAPPING_TERM)
  17. static keyrecord_t tapping_key = {};
  18. static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {};
  19. static uint8_t waiting_buffer_head = 0;
  20. static uint8_t waiting_buffer_tail = 0;
  21. static bool process_tapping(keyrecord_t *record);
  22. static bool waiting_buffer_enq(keyrecord_t record);
  23. static void waiting_buffer_clear(void);
  24. static bool waiting_buffer_typed(keyevent_t event);
  25. static bool waiting_buffer_has_anykey_pressed(void);
  26. static void waiting_buffer_scan_tap(void);
  27. static void debug_tapping_key(void);
  28. static void debug_waiting_buffer(void);
  29. void action_tapping_process(keyrecord_t record)
  30. {
  31. if (process_tapping(&record)) {
  32. if (!IS_NOEVENT(record.event)) {
  33. debug("processed: "); debug_record(record); debug("\n");
  34. }
  35. } else {
  36. if (!waiting_buffer_enq(record)) {
  37. // clear all in case of overflow.
  38. debug("OVERFLOW: CLEAR ALL STATES\n");
  39. clear_keyboard();
  40. waiting_buffer_clear();
  41. tapping_key = (keyrecord_t){};
  42. }
  43. }
  44. // process waiting_buffer
  45. if (!IS_NOEVENT(record.event) && waiting_buffer_head != waiting_buffer_tail) {
  46. debug("---- action_exec: process waiting_buffer -----\n");
  47. }
  48. for (; waiting_buffer_tail != waiting_buffer_head; waiting_buffer_tail = (waiting_buffer_tail + 1) % WAITING_BUFFER_SIZE) {
  49. if (process_tapping(&waiting_buffer[waiting_buffer_tail])) {
  50. debug("processed: waiting_buffer["); debug_dec(waiting_buffer_tail); debug("] = ");
  51. debug_record(waiting_buffer[waiting_buffer_tail]); debug("\n\n");
  52. } else {
  53. break;
  54. }
  55. }
  56. if (!IS_NOEVENT(record.event)) {
  57. debug("\n");
  58. }
  59. }
  60. /* Tapping
  61. *
  62. * Rule: Tap key is typed(pressed and released) within TAPPING_TERM.
  63. * (without interfering by typing other key)
  64. */
  65. /* return true when key event is processed or consumed. */
  66. bool process_tapping(keyrecord_t *keyp)
  67. {
  68. keyevent_t event = keyp->event;
  69. // if tapping
  70. if (IS_TAPPING_PRESSED()) {
  71. if (WITHIN_TAPPING_TERM(event)) {
  72. if (tapping_key.tap.count == 0) {
  73. if (IS_TAPPING_KEY(event.key) && !event.pressed) {
  74. // first tap!
  75. debug("Tapping: First tap(0->1).\n");
  76. tapping_key.tap.count = 1;
  77. debug_tapping_key();
  78. process_action(&tapping_key);
  79. // copy tapping state
  80. keyp->tap = tapping_key.tap;
  81. // enqueue
  82. return false;
  83. }
  84. #if TAPPING_TERM >= 500
  85. /* This can settle mod/fn state fast but may prevent from typing fast. */
  86. else if (!event.pressed && waiting_buffer_typed(event)) {
  87. // other key typed. not tap.
  88. debug("Tapping: End. No tap. Interfered by typing key\n");
  89. process_action(&tapping_key);
  90. tapping_key = (keyrecord_t){};
  91. debug_tapping_key();
  92. // enqueue
  93. return false;
  94. }
  95. #endif
  96. /* release a key pressed before tapping */
  97. else if (!event.pressed && !waiting_buffer_typed(event)) {
  98. /* Unexpected repeating occurs unless this event is processed immedately. */
  99. debug("Tapping: release a key pressed before tapping\n");
  100. process_action(keyp);
  101. return true;
  102. }
  103. else {
  104. // set interrupted flag when other key preesed during tapping
  105. if (event.pressed) {
  106. tapping_key.tap.interrupted = true;
  107. }
  108. // enqueue
  109. return false;
  110. }
  111. }
  112. // tap_count > 0
  113. else {
  114. if (IS_TAPPING_KEY(event.key) && !event.pressed) {
  115. debug("Tapping: Tap release("); debug_dec(tapping_key.tap.count); debug(")\n");
  116. keyp->tap = tapping_key.tap;
  117. process_action(keyp);
  118. tapping_key = *keyp;
  119. debug_tapping_key();
  120. return true;
  121. }
  122. else if (is_tap_key(event.key) && event.pressed) {
  123. if (tapping_key.tap.count > 1) {
  124. debug("Tapping: Start new tap with releasing last tap(>1).\n");
  125. // unregister key
  126. process_action(&(keyrecord_t){
  127. .tap = tapping_key.tap,
  128. .event.key = tapping_key.event.key,
  129. .event.time = event.time,
  130. .event.pressed = false
  131. });
  132. } else {
  133. debug("Tapping: Start while last tap(1).\n");
  134. }
  135. tapping_key = *keyp;
  136. waiting_buffer_scan_tap();
  137. debug_tapping_key();
  138. return true;
  139. }
  140. else {
  141. if (!IS_NOEVENT(event)) {
  142. debug("Tapping: key event while last tap(>0).\n");
  143. }
  144. process_action(keyp);
  145. return true;
  146. }
  147. }
  148. }
  149. // after TAPPING_TERM
  150. else {
  151. if (tapping_key.tap.count == 0) {
  152. debug("Tapping: End. Timeout. Not tap(0): ");
  153. debug_event(event); debug("\n");
  154. process_action(&tapping_key);
  155. tapping_key = (keyrecord_t){};
  156. debug_tapping_key();
  157. return false;
  158. } else {
  159. if (IS_TAPPING_KEY(event.key) && !event.pressed) {
  160. debug("Tapping: End. last timeout tap release(>0).");
  161. keyp->tap = tapping_key.tap;
  162. process_action(keyp);
  163. tapping_key = (keyrecord_t){};
  164. return true;
  165. }
  166. else if (is_tap_key(event.key) && event.pressed) {
  167. if (tapping_key.tap.count > 1) {
  168. debug("Tapping: Start new tap with releasing last timeout tap(>1).\n");
  169. // unregister key
  170. process_action(&(keyrecord_t){
  171. .tap = tapping_key.tap,
  172. .event.key = tapping_key.event.key,
  173. .event.time = event.time,
  174. .event.pressed = false
  175. });
  176. } else {
  177. debug("Tapping: Start while last timeout tap(1).\n");
  178. }
  179. tapping_key = *keyp;
  180. waiting_buffer_scan_tap();
  181. debug_tapping_key();
  182. return true;
  183. }
  184. else {
  185. if (!IS_NOEVENT(event)) {
  186. debug("Tapping: key event while last timeout tap(>0).\n");
  187. }
  188. process_action(keyp);
  189. return true;
  190. }
  191. }
  192. }
  193. } else if (IS_TAPPING_RELEASED()) {
  194. if (WITHIN_TAPPING_TERM(event)) {
  195. if (event.pressed) {
  196. if (IS_TAPPING_KEY(event.key)) {
  197. if (!tapping_key.tap.interrupted && tapping_key.tap.count > 0) {
  198. // sequential tap.
  199. keyp->tap = tapping_key.tap;
  200. if (keyp->tap.count < 15) keyp->tap.count += 1;
  201. debug("Tapping: Tap press("); debug_dec(keyp->tap.count); debug(")\n");
  202. process_action(keyp);
  203. tapping_key = *keyp;
  204. debug_tapping_key();
  205. return true;
  206. } else {
  207. // FIX: start new tap again
  208. tapping_key = *keyp;
  209. return true;
  210. }
  211. } else if (is_tap_key(event.key)) {
  212. // Sequential tap can be interfered with other tap key.
  213. debug("Tapping: Start with interfering other tap.\n");
  214. tapping_key = *keyp;
  215. waiting_buffer_scan_tap();
  216. debug_tapping_key();
  217. return true;
  218. } else {
  219. // should none in buffer
  220. // FIX: interrupted when other key is pressed
  221. tapping_key.tap.interrupted = true;
  222. process_action(keyp);
  223. return true;
  224. }
  225. } else {
  226. if (!IS_NOEVENT(event)) debug("Tapping: other key just after tap.\n");
  227. process_action(keyp);
  228. return true;
  229. }
  230. } else {
  231. // FIX: process_aciton here?
  232. // timeout. no sequential tap.
  233. debug("Tapping: End(Timeout after releasing last tap): ");
  234. debug_event(event); debug("\n");
  235. tapping_key = (keyrecord_t){};
  236. debug_tapping_key();
  237. return false;
  238. }
  239. }
  240. // not tapping state
  241. else {
  242. if (event.pressed && is_tap_key(event.key)) {
  243. debug("Tapping: Start(Press tap key).\n");
  244. tapping_key = *keyp;
  245. waiting_buffer_scan_tap();
  246. debug_tapping_key();
  247. return true;
  248. } else {
  249. process_action(keyp);
  250. return true;
  251. }
  252. }
  253. }
  254. /*
  255. * Waiting buffer
  256. */
  257. bool waiting_buffer_enq(keyrecord_t record)
  258. {
  259. if (IS_NOEVENT(record.event)) {
  260. return true;
  261. }
  262. if ((waiting_buffer_head + 1) % WAITING_BUFFER_SIZE == waiting_buffer_tail) {
  263. debug("waiting_buffer_enq: Over flow.\n");
  264. return false;
  265. }
  266. waiting_buffer[waiting_buffer_head] = record;
  267. waiting_buffer_head = (waiting_buffer_head + 1) % WAITING_BUFFER_SIZE;
  268. debug("waiting_buffer_enq: "); debug_waiting_buffer();
  269. return true;
  270. }
  271. void waiting_buffer_clear(void)
  272. {
  273. waiting_buffer_head = 0;
  274. waiting_buffer_tail = 0;
  275. }
  276. bool waiting_buffer_typed(keyevent_t event)
  277. {
  278. for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
  279. if (KEYEQ(event.key, waiting_buffer[i].event.key) && event.pressed != waiting_buffer[i].event.pressed) {
  280. return true;
  281. }
  282. }
  283. return false;
  284. }
  285. bool waiting_buffer_has_anykey_pressed(void)
  286. {
  287. for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
  288. if (waiting_buffer[i].event.pressed) return true;
  289. }
  290. return false;
  291. }
  292. /* scan buffer for tapping */
  293. void waiting_buffer_scan_tap(void)
  294. {
  295. // tapping already is settled
  296. if (tapping_key.tap.count > 0) return;
  297. // invalid state: tapping_key released && tap.count == 0
  298. if (!tapping_key.event.pressed) return;
  299. for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
  300. if (IS_TAPPING_KEY(waiting_buffer[i].event.key) &&
  301. !waiting_buffer[i].event.pressed &&
  302. WITHIN_TAPPING_TERM(waiting_buffer[i].event)) {
  303. tapping_key.tap.count = 1;
  304. waiting_buffer[i].tap.count = 1;
  305. process_action(&tapping_key);
  306. debug("waiting_buffer_scan_tap: found at ["); debug_dec(i); debug("]\n");
  307. debug_waiting_buffer();
  308. return;
  309. }
  310. }
  311. }
  312. /*
  313. * debug print
  314. */
  315. static void debug_tapping_key(void)
  316. {
  317. debug("TAPPING_KEY="); debug_record(tapping_key); debug("\n");
  318. }
  319. static void debug_waiting_buffer(void)
  320. {
  321. debug("{ ");
  322. for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
  323. debug("["); debug_dec(i); debug("]="); debug_record(waiting_buffer[i]); debug(" ");
  324. }
  325. debug("}\n");
  326. }
  327. #endif