aboutsummaryrefslogtreecommitdiff
path: root/quantum/process_keycode/process_steno.c
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/process_keycode/process_steno.c')
-rw-r--r--quantum/process_keycode/process_steno.c208
1 files changed, 97 insertions, 111 deletions
diff --git a/quantum/process_keycode/process_steno.c b/quantum/process_keycode/process_steno.c
index 50a1ef2fc..e0b33ec86 100644
--- a/quantum/process_keycode/process_steno.c
+++ b/quantum/process_keycode/process_steno.c
@@ -58,150 +58,136 @@
58#define GEMINI_STATE_SIZE 6 58#define GEMINI_STATE_SIZE 6
59#define MAX_STATE_SIZE GEMINI_STATE_SIZE 59#define MAX_STATE_SIZE GEMINI_STATE_SIZE
60 60
61static uint8_t state[MAX_STATE_SIZE] = {0}; 61static uint8_t state[MAX_STATE_SIZE] = {0};
62static uint8_t chord[MAX_STATE_SIZE] = {0}; 62static uint8_t chord[MAX_STATE_SIZE] = {0};
63static int8_t pressed = 0; 63static int8_t pressed = 0;
64static steno_mode_t mode; 64static steno_mode_t mode;
65 65
66static const uint8_t boltmap[64] PROGMEM = { 66static const uint8_t boltmap[64] PROGMEM = {TXB_NUL, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_S_L, TXB_S_L, TXB_T_L, TXB_K_L, TXB_P_L, TXB_W_L, TXB_H_L, TXB_R_L, TXB_A_L, TXB_O_L, TXB_STR, TXB_STR, TXB_NUL, TXB_NUL, TXB_NUL, TXB_STR, TXB_STR, TXB_E_R, TXB_U_R, TXB_F_R, TXB_R_R, TXB_P_R, TXB_B_R, TXB_L_R, TXB_G_R, TXB_T_R, TXB_S_R, TXB_D_R, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_Z_R};
67 TXB_NUL, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM,
68 TXB_S_L, TXB_S_L, TXB_T_L, TXB_K_L, TXB_P_L, TXB_W_L, TXB_H_L,
69 TXB_R_L, TXB_A_L, TXB_O_L, TXB_STR, TXB_STR, TXB_NUL, TXB_NUL,
70 TXB_NUL, TXB_STR, TXB_STR, TXB_E_R, TXB_U_R, TXB_F_R, TXB_R_R,
71 TXB_P_R, TXB_B_R, TXB_L_R, TXB_G_R, TXB_T_R, TXB_S_R, TXB_D_R,
72 TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_Z_R
73};
74 67
75static void steno_clear_state(void) { 68static void steno_clear_state(void) {
76 memset(state, 0, sizeof(state)); 69 memset(state, 0, sizeof(state));
77 memset(chord, 0, sizeof(chord)); 70 memset(chord, 0, sizeof(chord));
78} 71}
79 72
80static void send_steno_state(uint8_t size, bool send_empty) { 73static void send_steno_state(uint8_t size, bool send_empty) {
81 for (uint8_t i = 0; i < size; ++i) { 74 for (uint8_t i = 0; i < size; ++i) {
82 if (chord[i] || send_empty) { 75 if (chord[i] || send_empty) {
83 virtser_send(chord[i]); 76 virtser_send(chord[i]);
77 }
84 } 78 }
85 }
86} 79}
87 80
88void steno_init() { 81void steno_init() {
89 if (!eeconfig_is_enabled()) { 82 if (!eeconfig_is_enabled()) {
90 eeconfig_init(); 83 eeconfig_init();
91 } 84 }
92 mode = eeprom_read_byte(EECONFIG_STENOMODE); 85 mode = eeprom_read_byte(EECONFIG_STENOMODE);
93} 86}
94 87
95void steno_set_mode(steno_mode_t new_mode) { 88void steno_set_mode(steno_mode_t new_mode) {
96 steno_clear_state(); 89 steno_clear_state();
97 mode = new_mode; 90 mode = new_mode;
98 eeprom_update_byte(EECONFIG_STENOMODE, mode); 91 eeprom_update_byte(EECONFIG_STENOMODE, mode);
99} 92}
100 93
101/* override to intercept chords right before they get sent. 94/* override to intercept chords right before they get sent.
102 * return zero to suppress normal sending behavior. 95 * return zero to suppress normal sending behavior.
103 */ 96 */
104__attribute__ ((weak)) 97__attribute__((weak)) bool send_steno_chord_user(steno_mode_t mode, uint8_t chord[6]) { return true; }
105bool send_steno_chord_user(steno_mode_t mode, uint8_t chord[6]) { return true; }
106 98
107__attribute__ ((weak)) 99__attribute__((weak)) bool postprocess_steno_user(uint16_t keycode, keyrecord_t *record, steno_mode_t mode, uint8_t chord[6], int8_t pressed) { return true; }
108bool postprocess_steno_user(uint16_t keycode, keyrecord_t *record, steno_mode_t mode, uint8_t chord[6], int8_t pressed) { return true; }
109 100
110__attribute__ ((weak)) 101__attribute__((weak)) bool process_steno_user(uint16_t keycode, keyrecord_t *record) { return true; }
111bool process_steno_user(uint16_t keycode, keyrecord_t *record) { return true; }
112 102
113static void send_steno_chord(void) { 103static void send_steno_chord(void) {
114 if (send_steno_chord_user(mode, chord)) { 104 if (send_steno_chord_user(mode, chord)) {
115 switch(mode) { 105 switch (mode) {
116 case STENO_MODE_BOLT: 106 case STENO_MODE_BOLT:
117 send_steno_state(BOLT_STATE_SIZE, false); 107 send_steno_state(BOLT_STATE_SIZE, false);
118 virtser_send(0); // terminating byte 108 virtser_send(0); // terminating byte
119 break; 109 break;
120 case STENO_MODE_GEMINI: 110 case STENO_MODE_GEMINI:
121 chord[0] |= 0x80; // Indicate start of packet 111 chord[0] |= 0x80; // Indicate start of packet
122 send_steno_state(GEMINI_STATE_SIZE, true); 112 send_steno_state(GEMINI_STATE_SIZE, true);
123 break; 113 break;
114 }
124 } 115 }
125 } 116 steno_clear_state();
126 steno_clear_state();
127} 117}
128 118
129uint8_t *steno_get_state(void) { 119uint8_t *steno_get_state(void) { return &state[0]; }
130 return &state[0];
131}
132 120
133uint8_t *steno_get_chord(void) { 121uint8_t *steno_get_chord(void) { return &chord[0]; }
134 return &chord[0];
135}
136 122
137static bool update_state_bolt(uint8_t key, bool press) { 123static bool update_state_bolt(uint8_t key, bool press) {
138 uint8_t boltcode = pgm_read_byte(boltmap + key); 124 uint8_t boltcode = pgm_read_byte(boltmap + key);
139 if (press) { 125 if (press) {
140 state[TXB_GET_GROUP(boltcode)] |= boltcode; 126 state[TXB_GET_GROUP(boltcode)] |= boltcode;
141 chord[TXB_GET_GROUP(boltcode)] |= boltcode; 127 chord[TXB_GET_GROUP(boltcode)] |= boltcode;
142 } else { 128 } else {
143 state[TXB_GET_GROUP(boltcode)] &= ~boltcode; 129 state[TXB_GET_GROUP(boltcode)] &= ~boltcode;
144 } 130 }
145 return false; 131 return false;
146} 132}
147 133
148static bool update_state_gemini(uint8_t key, bool press) { 134static bool update_state_gemini(uint8_t key, bool press) {
149 int idx = key / 7; 135 int idx = key / 7;
150 uint8_t bit = 1 << (6 - (key % 7)); 136 uint8_t bit = 1 << (6 - (key % 7));
151 if (press) { 137 if (press) {
152 state[idx] |= bit; 138 state[idx] |= bit;
153 chord[idx] |= bit; 139 chord[idx] |= bit;
154 } else { 140 } else {
155 state[idx] &= ~bit; 141 state[idx] &= ~bit;
156 } 142 }
157 return false; 143 return false;
158} 144}
159 145
160bool process_steno(uint16_t keycode, keyrecord_t *record) { 146bool process_steno(uint16_t keycode, keyrecord_t *record) {
161 switch (keycode) { 147 switch (keycode) {
162 case QK_STENO_BOLT: 148 case QK_STENO_BOLT:
163 if (!process_steno_user(keycode, record)) { 149 if (!process_steno_user(keycode, record)) {
164 return false; 150 return false;
165 } 151 }
166 if (IS_PRESSED(record->event)) { 152 if (IS_PRESSED(record->event)) {
167 steno_set_mode(STENO_MODE_BOLT); 153 steno_set_mode(STENO_MODE_BOLT);
168 } 154 }
169 return false; 155 return false;
170 156
171 case QK_STENO_GEMINI: 157 case QK_STENO_GEMINI:
172 if (!process_steno_user(keycode, record)) { 158 if (!process_steno_user(keycode, record)) {
173 return false; 159 return false;
174 } 160 }
175 if (IS_PRESSED(record->event)) { 161 if (IS_PRESSED(record->event)) {
176 steno_set_mode(STENO_MODE_GEMINI); 162 steno_set_mode(STENO_MODE_GEMINI);
177 } 163 }
178 return false; 164 return false;
179 165
180 case STN__MIN...STN__MAX: 166 case STN__MIN ... STN__MAX:
181 if (!process_steno_user(keycode, record)) { 167 if (!process_steno_user(keycode, record)) {
182 return false; 168 return false;
183 } 169 }
184 switch(mode) { 170 switch (mode) {
185 case STENO_MODE_BOLT: 171 case STENO_MODE_BOLT:
186 update_state_bolt(keycode - QK_STENO, IS_PRESSED(record->event)); 172 update_state_bolt(keycode - QK_STENO, IS_PRESSED(record->event));
187 break; 173 break;
188 case STENO_MODE_GEMINI: 174 case STENO_MODE_GEMINI:
189 update_state_gemini(keycode - QK_STENO, IS_PRESSED(record->event)); 175 update_state_gemini(keycode - QK_STENO, IS_PRESSED(record->event));
190 break; 176 break;
191 } 177 }
192 // allow postprocessing hooks 178 // allow postprocessing hooks
193 if (postprocess_steno_user(keycode, record, mode, chord, pressed)) { 179 if (postprocess_steno_user(keycode, record, mode, chord, pressed)) {
194 if (IS_PRESSED(record->event)) { 180 if (IS_PRESSED(record->event)) {
195 ++pressed; 181 ++pressed;
196 } else { 182 } else {
197 --pressed; 183 --pressed;
198 if (pressed <= 0) { 184 if (pressed <= 0) {
199 pressed = 0; 185 pressed = 0;
200 send_steno_chord(); 186 send_steno_chord();
201 } 187 }
202 } 188 }
203 } 189 }
204 return false; 190 return false;
205 } 191 }
206 return true; 192 return true;
207} 193}