]> git.donarmstrong.com Git - qmk_firmware.git/blob - keyboards/georgi/sten.h
[Keyboard] Georgi Support (#5384)
[qmk_firmware.git] / keyboards / georgi / sten.h
1 // 2019, g Heavy Industries
2
3 #include QMK_KEYBOARD_H
4 #include "mousekey.h"
5 #include "keymap.h"
6 #include "keymap_steno.h"
7
8 // Bitfield representing the current chord
9 uint32_t cChord = 0;
10
11 // See if a given chord is pressed. 
12 // P will return 
13 // PJ will continue processing, removing the found chord 
14 #define P(chord, act)  if (cChord == (chord)) { act; return true; }
15 #define PJ(chord, act) if ((cChord & (chord)) == (chord)) { cChord ^= chord; act; }
16
17 // All Steno Codes
18 // Shift to internal representation
19 #define STN(n) (1L<<n)
20
21 //i.e) S(teno)R(ight)F
22 enum ORDER { 
23                 SFN = 0, SPWR, SST1, SST2, SST3, SST4, SNUM,
24                 SLSU, SLSD, SLT, SLK, SLP, SLW, SLH, SLR, SLA, SLO, 
25                 SRE, SRU, SRF, SRR, SRP, SRB, SRL, SRG, SRT, SRS, SRD, SRZ
26 };
27
28 // Break it all out
29 #define FN      STN(SFN)
30 #define PWR     STN(SPWR)
31 #define ST1 STN(SST1)
32 #define ST2 STN(SST2)
33 #define ST3 STN(SST3)
34 #define ST4 STN(SST4)
35 #define NUM STN(SNUM) // No distinction between left and right
36
37 #define LSU STN(SLSU)
38 #define LSD STN(SLSD)
39 #define LFT STN(SLT)  // (L)e(F)t (T), preprocessor conflict
40 #define LK  STN(SLK)
41 #define LP  STN(SLP)
42 #define LW  STN(SLW)
43 #define LH  STN(SLH)
44 #define LR  STN(SLR)
45 #define LA  STN(SLA)
46 #define LO  STN(SLO)
47
48 #define RE  STN(SRE)
49 #define RU  STN(SRU)
50 #define RF  STN(SRF)
51 #define RR  STN(SRR)
52 #define RP  STN(SRP)
53 #define RB  STN(SRB)
54 #define RL  STN(SRL)
55 #define RG  STN(SRG)
56 #define RT  STN(SRT)
57 #define RS  STN(SRS)
58 #define RD  STN(SRD)
59 #define RZ  STN(SRZ)
60
61 bool            processQwerty(void);
62 bool            processFakeSteno(void);
63 void            clickMouse(uint8_t kc);
64 void            SEND(uint8_t kc);
65 extern int      getKeymapCount(void);
66
67 // Mode state
68 enum MODE { STENO = 0, QWERTY, COMMAND };
69 enum MODE cMode = STENO;
70 enum MODE pMode;
71 bool QWERSTENO = false;
72
73 // Command State
74 #define MAX_CMD_BUF 20
75 uint8_t CMDBUF[MAX_CMD_BUF];
76 uint8_t CMDLEN = 0;
77
78 // Key Repeat state
79 bool     inChord  = false;
80 uint16_t repTimer = 0;
81 #define  REP_DELAY 300
82
83 // Mousekeys state
84 bool    inMouse = false;
85 int8_t  mousePress;
86
87 // All processing done at chordUp goes through here
88 bool send_steno_chord_user(steno_mode_t mode, uint8_t chord[6]) { 
89         // Check for mousekeys, this is release
90 #ifdef MOUSEKEY_ENABLE
91         if (inMouse) {
92                 inMouse = false;
93                 mousekey_off(mousePress);
94                 mousekey_send();
95         }
96 #endif
97
98         // Toggle Serial/QWERTY steno
99         if (cChord == (PWR | FN | ST1 | ST2)) {
100                 uprintf("Fallback Toggle\n");
101                 QWERSTENO = !QWERSTENO;
102                 
103                 goto out;
104         }
105
106         // handle command mode
107         if (cChord == (PWR | FN | RD | RZ)) {
108                 uprintf("COMMAND Toggle\n");
109                 if (cMode != COMMAND) {   // Entering Command Mode
110                         CMDLEN = 0;
111                         pMode = cMode;
112                         cMode = COMMAND;
113                 } else {                  // Exiting Command Mode
114                         cMode = pMode;
115
116                         // Press all and release all
117                         for (int i = 0; i < CMDLEN; i++) {
118                                 register_code(CMDBUF[i]);
119                         }
120                         clear_keyboard();
121                 }
122
123                 goto out;
124         }
125
126         // Handle Gaming Toggle,
127         if (cChord == (PWR | FN | ST2 | ST3) && getKeymapCount() > 1) {
128                 uprintf("Switching to QMK\n");
129                 layer_on(1);
130                 goto out;
131         }
132
133         // Lone FN press, toggle QWERTY
134         if (cChord == FN) {
135                 (cMode == STENO) ? (cMode = QWERTY) : (cMode = STENO);
136                 goto out;
137         }
138
139         // Check for Plover momentary
140         if (cMode == QWERTY && (cChord & FN)) {
141                 cChord ^= FN;
142                 goto steno;
143         }
144
145         // Do QWERTY and Momentary QWERTY
146         if (cMode == QWERTY || (cMode == COMMAND) || (cChord & (FN | PWR))) {
147                 if (cChord & FN)  cChord ^= FN;
148                 processQwerty();
149                 goto out;
150         }
151
152         // Fallback NKRO Steno
153         if (cMode == STENO && QWERSTENO) {
154                 processFakeSteno();
155                 goto out;
156         }
157
158 steno:
159         // Hey that's a steno chord!
160         inChord = false;
161         cChord = 0;
162         return true; 
163
164 out:
165         inChord = false;
166         clear_keyboard();
167         cChord = 0;
168         return false;
169 }
170
171 // Update Chord State 
172 bool process_steno_user(uint16_t keycode, keyrecord_t *record) { 
173         // Everything happens in here when steno keys come in.
174         // Bail on keyup
175         if (!record->event.pressed) return true;
176
177         // Update key repeat timers
178         repTimer = timer_read();
179         inChord  = true;
180
181         // Switch on the press adding to chord
182         bool pr = record->event.pressed;
183         switch (keycode) {
184                         // Mods and stuff
185                         case STN_ST1:                   pr ? (cChord |= (ST1)): (cChord &= ~(ST1)); break;
186                         case STN_ST2:                   pr ? (cChord |= (ST2)): (cChord &= ~(ST2)); break;
187                         case STN_ST3:                   pr ? (cChord |= (ST3)): (cChord &= ~(ST3)); break;
188                         case STN_ST4:                   pr ? (cChord |= (ST4)): (cChord &= ~(ST4)); break;
189                         case STN_FN:                    pr ? (cChord |= (FN)) : (cChord &= ~(FN)); break;
190                         case STN_PWR:                   pr ? (cChord |= (PWR)): (cChord &= ~(PWR)); break;
191                         case STN_N1...STN_N6: 
192                         case STN_N7...STN_NC:   pr ? (cChord |= (NUM)): (cChord &= ~(NUM)); break;
193
194                         // All the letter keys
195                         case STN_S1:                    pr ? (cChord |= (LSU)) : (cChord &= ~(LSU));  break;
196                         case STN_S2:                    pr ? (cChord |= (LSD)) : (cChord &= ~(LSD));  break;
197                         case STN_TL:                    pr ? (cChord |= (LFT)) : (cChord &= ~(LFT)); break;
198                         case STN_KL:                    pr ? (cChord |= (LK)) : (cChord &= ~(LK)); break;
199                         case STN_PL:                    pr ? (cChord |= (LP)) : (cChord &= ~(LP)); break;
200                         case STN_WL:                    pr ? (cChord |= (LW)) : (cChord &= ~(LW)); break;
201                         case STN_HL:                    pr ? (cChord |= (LH)) : (cChord &= ~(LH)); break;
202                         case STN_RL:                    pr ? (cChord |= (LR)) : (cChord &= ~(LR)); break;
203                         case STN_A:                             pr ? (cChord |= (LA)) : (cChord &= ~(LA)); break;
204                         case STN_O:                             pr ? (cChord |= (LO)) : (cChord &= ~(LO)); break;
205                         case STN_E:                             pr ? (cChord |= (RE)) : (cChord &= ~(RE)); break;
206                         case STN_U:                             pr ? (cChord |= (RU)) : (cChord &= ~(RU)); break;
207                         case STN_FR:                    pr ? (cChord |= (RF)) : (cChord &= ~(RF)); break;
208                         case STN_RR:                    pr ? (cChord |= (RR)) : (cChord &= ~(RR)); break;
209                         case STN_PR:                    pr ? (cChord |= (RP)) : (cChord &= ~(RP)); break;
210                         case STN_BR:                    pr ? (cChord |= (RB)) : (cChord &= ~(RB)); break;
211                         case STN_LR:                    pr ? (cChord |= (RL)) : (cChord &= ~(RL)); break;
212                         case STN_GR:                    pr ? (cChord |= (RG)) : (cChord &= ~(RG)); break;
213                         case STN_TR:                    pr ? (cChord |= (RT)) : (cChord &= ~(RT)); break;
214                         case STN_SR:                    pr ? (cChord |= (RS)) : (cChord &= ~(RS)); break;
215                         case STN_DR:                    pr ? (cChord |= (RD)) : (cChord &= ~(RD)); break;
216                         case STN_ZR:                    pr ? (cChord |= (RZ)) : (cChord &= ~(RZ)); break;
217         }
218
219         // Check for key repeat in QWERTY mode
220         return true; 
221 }
222 void matrix_scan_user(void) {
223         // We abuse this for early sending of key
224         // Key repeat only on QWER/SYMB layers
225         if (cMode != QWERTY) return;
226
227         // Check timers
228         if (timer_elapsed(repTimer) > REP_DELAY) {
229                 // Process Key for report
230                 processQwerty();
231
232                 // Send report to host
233                 send_keyboard_report();
234                 repTimer = timer_read();
235         }
236 };
237
238 // Helpers
239 bool processFakeSteno(void) {
240         PJ( LSU,                        SEND(KC_Q););
241         PJ( LSD,                        SEND(KC_A););
242         PJ( LFT,                        SEND(KC_W););
243         PJ( LP,                         SEND(KC_E););
244         PJ( LH,                         SEND(KC_R););
245         PJ( LK,                         SEND(KC_S););
246         PJ( LW,                         SEND(KC_D););
247         PJ( LR,                         SEND(KC_F););
248         PJ( ST1,                        SEND(KC_T););
249         PJ( ST2,                        SEND(KC_G););
250         PJ( LA,                         SEND(KC_C););
251         PJ( LO,                         SEND(KC_V););
252         PJ( RE,                         SEND(KC_N););
253         PJ( RU,                         SEND(KC_M););
254         PJ( ST3,                        SEND(KC_Y););
255         PJ( ST4,                        SEND(KC_H););
256         PJ( RF,                         SEND(KC_U););
257         PJ( RP,                         SEND(KC_I););
258         PJ( RL,                         SEND(KC_O););
259         PJ( RT,                         SEND(KC_P););
260         PJ( RD,                         SEND(KC_LBRC););
261         PJ( RR,                         SEND(KC_J););
262         PJ( RB,                         SEND(KC_K););
263         PJ( RG,                         SEND(KC_L););
264         PJ( RS,                         SEND(KC_SCLN););
265         PJ( RZ,                         SEND(KC_COMM););
266         PJ( NUM,                        SEND(KC_1););
267
268         return false;
269 }
270 void clickMouse(uint8_t kc) {
271 #ifdef MOUSEKEY_ENABLE
272         mousekey_on(kc);
273         mousekey_send();
274
275         // Store state for later use
276         inMouse = true;
277         mousePress = kc;
278 #endif
279 }
280 void SEND(uint8_t kc) {
281         // Send Keycode, Does not work for Quantum Codes
282         if (cMode == COMMAND && CMDLEN < MAX_CMD_BUF) {
283                 uprintf("CMD LEN: %d BUF: %d\n", CMDLEN, MAX_CMD_BUF);
284                 CMDBUF[CMDLEN] = kc;
285                 CMDLEN++;
286         } 
287
288         if (cMode != COMMAND) register_code(kc);
289         return;
290 }