sten.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. #include "sten.h"
  2. // Chord state
  3. uint32_t cChord = 0; // Current Chord
  4. int chordIndex = 0; // Keys in previousachord
  5. int32_t chordState[32]; // Full Chord history
  6. #define QWERBUF 24 // Size of chords to buffer for output
  7. bool repeatFlag = false; // Should we repeat?
  8. uint32_t pChord = 0; // Previous Chord
  9. int pChordIndex = 0; // Keys in previousachord
  10. uint32_t pChordState[32]; // Previous chord sate
  11. uint32_t stickyBits = 0; // Or'd with every incoming press
  12. // Mode state
  13. enum MODE { STENO = 0, QWERTY, COMMAND };
  14. enum MODE pMode;
  15. bool QWERSTENO = false;
  16. #ifdef ONLYQWERTY
  17. enum MODE cMode = QWERTY;
  18. #else
  19. enum MODE cMode = STENO;
  20. #endif
  21. // Command State
  22. #define MAX_CMD_BUF 20
  23. uint8_t CMDLEN = 0;
  24. uint8_t CMDBUF[MAX_CMD_BUF];
  25. // Key Repeat state
  26. bool inChord = false;
  27. bool repEngaged = false;
  28. uint16_t repTimer = 0;
  29. #define REP_INIT_DELAY 750
  30. #define REP_DELAY 25
  31. // Mousekeys state
  32. bool inMouse = false;
  33. int8_t mousePress;
  34. // All processing done at chordUp goes through here
  35. bool send_steno_chord_user(steno_mode_t mode, uint8_t chord[6]) {
  36. // Check for mousekeys, this is release
  37. #ifdef MOUSEKEY_ENABLE
  38. if (inMouse) {
  39. inMouse = false;
  40. mousekey_off(mousePress);
  41. mousekey_send();
  42. }
  43. #endif
  44. // Toggle Serial/QWERTY steno
  45. if (cChord == (PWR | FN | ST1 | ST2)) {
  46. #ifndef NO_DEBUG
  47. uprintf("Fallback Toggle\n");
  48. #endif
  49. QWERSTENO = !QWERSTENO;
  50. goto out;
  51. }
  52. // handle command mode
  53. if (cChord == (PWR | FN | RD | RZ)) {
  54. #ifndef NO_DEBUG
  55. uprintf("COMMAND Toggle\n");
  56. #endif
  57. if (cMode != COMMAND) { // Entering Command Mode
  58. CMDLEN = 0;
  59. pMode = cMode;
  60. cMode = COMMAND;
  61. } else { // Exiting Command Mode
  62. cMode = pMode;
  63. // Press all and release all
  64. for (int i = 0; i < CMDLEN; i++) {
  65. register_code(CMDBUF[i]);
  66. }
  67. clear_keyboard();
  68. }
  69. goto out;
  70. }
  71. // Handle Gaming Toggle,
  72. if (cChord == (PWR | FN | ST4 | ST3) && keymapsCount > 1) {
  73. #ifndef NO_DEBUG
  74. uprintf("Switching to QMK\n");
  75. #endif
  76. layer_on(1);
  77. goto out;
  78. }
  79. // Lone FN press, toggle QWERTY
  80. #ifndef ONLYQWERTY
  81. if (cChord == FN) {
  82. (cMode == STENO) ? (cMode = QWERTY) : (cMode = STENO);
  83. goto out;
  84. }
  85. #endif
  86. // Check for Plover momentary
  87. if (cMode == QWERTY && (cChord & FN)) {
  88. cChord ^= FN;
  89. goto steno;
  90. }
  91. // Do QWERTY and Momentary QWERTY
  92. if (cMode == QWERTY || (cMode == COMMAND) || (cChord & (FN | PWR))) {
  93. processChord(false);
  94. goto out;
  95. }
  96. // Fallback NKRO Steno
  97. if (cMode == STENO && QWERSTENO) {
  98. processChord(true);
  99. goto out;
  100. }
  101. steno:
  102. // Hey that's a steno chord!
  103. inChord = false;
  104. chordIndex = 0;
  105. cChord = 0;
  106. return true;
  107. out:
  108. cChord = 0;
  109. inChord = false;
  110. chordIndex = 0;
  111. clear_keyboard();
  112. repEngaged = false;
  113. for (int i = 0; i < 32; i++)
  114. chordState[i] = 0xFFFF;
  115. return false;
  116. }
  117. // Update Chord State
  118. bool process_steno_user(uint16_t keycode, keyrecord_t *record) {
  119. // Everything happens in here when steno keys come in.
  120. // Bail on keyup
  121. if (!record->event.pressed) return true;
  122. // Update key repeat timers
  123. repTimer = timer_read();
  124. inChord = true;
  125. // Switch on the press adding to chord
  126. bool pr = record->event.pressed;
  127. switch (keycode) {
  128. // Mods and stuff
  129. case STN_ST1: pr ? (cChord |= (ST1)): (cChord &= ~(ST1)); break;
  130. case STN_ST2: pr ? (cChord |= (ST2)): (cChord &= ~(ST2)); break;
  131. case STN_ST3: pr ? (cChord |= (ST3)): (cChord &= ~(ST3)); break;
  132. case STN_ST4: pr ? (cChord |= (ST4)): (cChord &= ~(ST4)); break;
  133. case STN_FN: pr ? (cChord |= (FN)) : (cChord &= ~(FN)); break;
  134. case STN_PWR: pr ? (cChord |= (PWR)): (cChord &= ~(PWR)); break;
  135. case STN_N1...STN_N6: pr ? (cChord |= (LNO)): (cChord &= ~(LNO)); break;
  136. case STN_N7...STN_NC: pr ? (cChord |= (RNO)): (cChord &= ~(RNO)); break;
  137. // All the letter keys
  138. case STN_S1: pr ? (cChord |= (LSU)) : (cChord &= ~(LSU)); break;
  139. case STN_S2: pr ? (cChord |= (LSD)) : (cChord &= ~(LSD)); break;
  140. case STN_TL: pr ? (cChord |= (LFT)) : (cChord &= ~(LFT)); break;
  141. case STN_KL: pr ? (cChord |= (LK)) : (cChord &= ~(LK)); break;
  142. case STN_PL: pr ? (cChord |= (LP)) : (cChord &= ~(LP)); break;
  143. case STN_WL: pr ? (cChord |= (LW)) : (cChord &= ~(LW)); break;
  144. case STN_HL: pr ? (cChord |= (LH)) : (cChord &= ~(LH)); break;
  145. case STN_RL: pr ? (cChord |= (LR)) : (cChord &= ~(LR)); break;
  146. case STN_A: pr ? (cChord |= (LA)) : (cChord &= ~(LA)); break;
  147. case STN_O: pr ? (cChord |= (LO)) : (cChord &= ~(LO)); break;
  148. case STN_E: pr ? (cChord |= (RE)) : (cChord &= ~(RE)); break;
  149. case STN_U: pr ? (cChord |= (RU)) : (cChord &= ~(RU)); break;
  150. case STN_FR: pr ? (cChord |= (RF)) : (cChord &= ~(RF)); break;
  151. case STN_RR: pr ? (cChord |= (RR)) : (cChord &= ~(RR)); break;
  152. case STN_PR: pr ? (cChord |= (RP)) : (cChord &= ~(RP)); break;
  153. case STN_BR: pr ? (cChord |= (RB)) : (cChord &= ~(RB)); break;
  154. case STN_LR: pr ? (cChord |= (RL)) : (cChord &= ~(RL)); break;
  155. case STN_GR: pr ? (cChord |= (RG)) : (cChord &= ~(RG)); break;
  156. case STN_TR: pr ? (cChord |= (RT)) : (cChord &= ~(RT)); break;
  157. case STN_SR: pr ? (cChord |= (RS)) : (cChord &= ~(RS)); break;
  158. case STN_DR: pr ? (cChord |= (RD)) : (cChord &= ~(RD)); break;
  159. case STN_ZR: pr ? (cChord |= (RZ)) : (cChord &= ~(RZ)); break;
  160. }
  161. // Store previous state for fastQWER
  162. if (pr) {
  163. chordState[chordIndex] = cChord;
  164. chordIndex++;
  165. }
  166. return true;
  167. }
  168. void matrix_scan_user(void) {
  169. // We abuse this for early sending of key
  170. // Key repeat only on QWER/SYMB layers
  171. if (cMode != QWERTY || !inChord) return;
  172. // Check timers
  173. #ifndef NO_REPEAT
  174. if (repEngaged && timer_elapsed(repTimer) > REP_DELAY) {
  175. // Process Key for report
  176. processChord(false);
  177. // Send report to host
  178. send_keyboard_report();
  179. clear_keyboard();
  180. repTimer = timer_read();
  181. }
  182. if (!repEngaged && timer_elapsed(repTimer) > REP_INIT_DELAY) {
  183. repEngaged = true;
  184. }
  185. #endif
  186. };
  187. // For Plover NKRO
  188. uint32_t processFakeSteno(bool lookup) {
  189. P( LSU, SEND(KC_Q););
  190. P( LSD, SEND(KC_A););
  191. P( LFT, SEND(KC_W););
  192. P( LP, SEND(KC_E););
  193. P( LH, SEND(KC_R););
  194. P( LK, SEND(KC_S););
  195. P( LW, SEND(KC_D););
  196. P( LR, SEND(KC_F););
  197. P( ST1, SEND(KC_T););
  198. P( ST2, SEND(KC_G););
  199. P( LA, SEND(KC_C););
  200. P( LO, SEND(KC_V););
  201. P( RE, SEND(KC_N););
  202. P( RU, SEND(KC_M););
  203. P( ST3, SEND(KC_Y););
  204. P( ST4, SEND(KC_H););
  205. P( RF, SEND(KC_U););
  206. P( RP, SEND(KC_I););
  207. P( RL, SEND(KC_O););
  208. P( RT, SEND(KC_P););
  209. P( RD, SEND(KC_LBRC););
  210. P( RR, SEND(KC_J););
  211. P( RB, SEND(KC_K););
  212. P( RG, SEND(KC_L););
  213. P( RS, SEND(KC_SCLN););
  214. P( RZ, SEND(KC_COMM););
  215. P( LNO, SEND(KC_1););
  216. P( RNO, SEND(KC_1););
  217. return 0;
  218. }
  219. // Traverse the chord history to a given point
  220. // Returns the mask to use
  221. void processChord(bool useFakeSteno) {
  222. // Save the clean chord state
  223. uint32_t savedChord = cChord;
  224. // Apply Stick Bits if needed
  225. if (stickyBits != 0) {
  226. cChord |= stickyBits;
  227. for (int i = 0; i <= chordIndex; i++)
  228. chordState[i] |= stickyBits;
  229. }
  230. // Strip FN
  231. if (cChord & FN) cChord ^= FN;
  232. // First we test if a whole chord was passsed
  233. // If so we just run it handling repeat logic
  234. if (useFakeSteno && processFakeSteno(true) == cChord) {
  235. processFakeSteno(false);
  236. return;
  237. } else if (processQwerty(true) == cChord) {
  238. processQwerty(false);
  239. // Repeat logic
  240. if (repeatFlag) {
  241. restoreState();
  242. repeatFlag = false;
  243. processChord(false);
  244. } else {
  245. saveState(cChord);
  246. }
  247. return;
  248. }
  249. // Iterate through chord picking out the individual
  250. // and longest chords
  251. uint32_t bufChords[QWERBUF];
  252. int bufLen = 0;
  253. uint32_t mask = 0;
  254. // We iterate over it multiple times to catch the longest
  255. // chord. Then that gets addded to the mask and re run.
  256. while (savedChord != mask) {
  257. uint32_t test = 0;
  258. uint32_t longestChord = 0;
  259. for (int i = 0; i <= chordIndex; i++) {
  260. cChord = chordState[i] & ~mask;
  261. if (cChord == 0)
  262. continue;
  263. // Assume mid parse Sym is new chord
  264. if (i != 0 && test != 0 && (cChord ^ test) == PWR) {
  265. longestChord = test;
  266. break;
  267. }
  268. // Lock SYM layer in once detected
  269. if (mask & PWR)
  270. cChord |= PWR;
  271. // Testing for keycodes
  272. if (useFakeSteno) {
  273. test = processFakeSteno(true);
  274. } else {
  275. test = processQwerty(true);
  276. }
  277. if (test != 0) {
  278. longestChord = test;
  279. }
  280. }
  281. mask |= longestChord;
  282. bufChords[bufLen] = longestChord;
  283. bufLen++;
  284. // That's a loop of sorts, halt processing
  285. if (bufLen >= QWERBUF) {
  286. return;
  287. }
  288. }
  289. // Now that the buffer is populated, we run it
  290. for (int i = 0; i < bufLen ; i++) {
  291. cChord = bufChords[i];
  292. if (useFakeSteno) {
  293. processFakeSteno(false);
  294. } else {
  295. processQwerty(false);
  296. }
  297. }
  298. // Save state in case of repeat
  299. if (!repeatFlag) {
  300. saveState(savedChord);
  301. }
  302. // Restore cChord for held repeat
  303. cChord = savedChord;
  304. return;
  305. }
  306. void saveState(uint32_t cleanChord) {
  307. pChord = cleanChord;
  308. pChordIndex = chordIndex;
  309. for (int i = 0; i < 32; i++)
  310. pChordState[i] = chordState[i];
  311. }
  312. void restoreState() {
  313. cChord = pChord;
  314. chordIndex = pChordIndex;
  315. for (int i = 0; i < 32; i++)
  316. chordState[i] = pChordState[i];
  317. }
  318. // Macros for calling from keymap.c
  319. void SEND(uint8_t kc) {
  320. // Send Keycode, Does not work for Quantum Codes
  321. if (cMode == COMMAND && CMDLEN < MAX_CMD_BUF) {
  322. #ifndef NO_DEBUG
  323. uprintf("CMD LEN: %d BUF: %d\n", CMDLEN, MAX_CMD_BUF);
  324. #endif
  325. CMDBUF[CMDLEN] = kc;
  326. CMDLEN++;
  327. }
  328. if (cMode != COMMAND) register_code(kc);
  329. return;
  330. }
  331. void REPEAT(void) {
  332. if (cMode != QWERTY)
  333. return;
  334. repeatFlag = true;
  335. return;
  336. }
  337. void SET_STICKY(uint32_t stick) {
  338. stickyBits = stick;
  339. return;
  340. }
  341. void SWITCH_LAYER(int layer) {
  342. if (keymapsCount >= layer)
  343. layer_on(layer);
  344. }
  345. void CLICK_MOUSE(uint8_t kc) {
  346. #ifdef MOUSEKEY_ENABLE
  347. mousekey_on(kc);
  348. mousekey_send();
  349. // Store state for later use
  350. inMouse = true;
  351. mousePress = kc;
  352. #endif
  353. }