diff options
Diffstat (limited to 'quantum/process_keycode/process_steno.c')
-rw-r--r-- | quantum/process_keycode/process_steno.c | 208 |
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 | ||
61 | static uint8_t state[MAX_STATE_SIZE] = {0}; | 61 | static uint8_t state[MAX_STATE_SIZE] = {0}; |
62 | static uint8_t chord[MAX_STATE_SIZE] = {0}; | 62 | static uint8_t chord[MAX_STATE_SIZE] = {0}; |
63 | static int8_t pressed = 0; | 63 | static int8_t pressed = 0; |
64 | static steno_mode_t mode; | 64 | static steno_mode_t mode; |
65 | 65 | ||
66 | static const uint8_t boltmap[64] PROGMEM = { | 66 | static 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 | ||
75 | static void steno_clear_state(void) { | 68 | static 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 | ||
80 | static void send_steno_state(uint8_t size, bool send_empty) { | 73 | static 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 | ||
88 | void steno_init() { | 81 | void 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 | ||
95 | void steno_set_mode(steno_mode_t new_mode) { | 88 | void 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; } |
105 | bool 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; } |
108 | bool 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; } |
111 | bool process_steno_user(uint16_t keycode, keyrecord_t *record) { return true; } | ||
112 | 102 | ||
113 | static void send_steno_chord(void) { | 103 | static 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 | ||
129 | uint8_t *steno_get_state(void) { | 119 | uint8_t *steno_get_state(void) { return &state[0]; } |
130 | return &state[0]; | ||
131 | } | ||
132 | 120 | ||
133 | uint8_t *steno_get_chord(void) { | 121 | uint8_t *steno_get_chord(void) { return &chord[0]; } |
134 | return &chord[0]; | ||
135 | } | ||
136 | 122 | ||
137 | static bool update_state_bolt(uint8_t key, bool press) { | 123 | static 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 | ||
148 | static bool update_state_gemini(uint8_t key, bool press) { | 134 | static 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 | ||
160 | bool process_steno(uint16_t keycode, keyrecord_t *record) { | 146 | bool 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 | } |