sten.c 9.1 KB

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