send_string.c
11266 bytes
1/* Copyright 2021
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "send_string.h"
18
19#include <ctype.h>
20#include <stdlib.h>
21
22#include "quantum_keycodes.h"
23#include "keycode.h"
24#include "action.h"
25#include "wait.h"
26
27#if defined(AUDIO_ENABLE) && defined(SENDSTRING_BELL)
28# include "audio.h"
29# ifndef BELL_SOUND
30# define BELL_SOUND TERMINAL_SOUND
31# endif
32float bell_song[][2] = SONG(BELL_SOUND);
33#endif
34
35// clang-format off
36
37/* Bit-Packed look-up table to convert an ASCII character to whether
38 * [Shift] needs to be sent with the keycode.
39 */
40__attribute__((weak)) const uint8_t ascii_to_shift_lut[16] PROGMEM = {
41 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
42 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
43 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
44 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
45
46 KCLUT_ENTRY(0, 1, 1, 1, 1, 1, 1, 0),
47 KCLUT_ENTRY(1, 1, 1, 1, 0, 0, 0, 0),
48 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
49 KCLUT_ENTRY(0, 0, 1, 0, 1, 0, 1, 1),
50 KCLUT_ENTRY(1, 1, 1, 1, 1, 1, 1, 1),
51 KCLUT_ENTRY(1, 1, 1, 1, 1, 1, 1, 1),
52 KCLUT_ENTRY(1, 1, 1, 1, 1, 1, 1, 1),
53 KCLUT_ENTRY(1, 1, 1, 0, 0, 0, 1, 1),
54 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
55 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
56 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
57 KCLUT_ENTRY(0, 0, 0, 1, 1, 1, 1, 0)
58};
59
60/* Bit-Packed look-up table to convert an ASCII character to whether
61 * [AltGr] needs to be sent with the keycode.
62 */
63__attribute__((weak)) const uint8_t ascii_to_altgr_lut[16] PROGMEM = {
64 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
65 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
66 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
67 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
68
69 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
70 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
71 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
72 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
73 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
74 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
75 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
76 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
77 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
78 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
79 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
80 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0)
81};
82
83/* Bit-Packed look-up table to convert an ASCII character to whether
84 * [Space] needs to be sent after the keycode
85 */
86__attribute__((weak)) const uint8_t ascii_to_dead_lut[16] PROGMEM = {
87 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
88 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
89 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
90 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
91
92 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
93 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
94 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
95 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
96 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
97 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
98 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
99 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
100 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
101 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
102 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
103 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0)
104};
105
106/* Look-up table to convert an ASCII character to a keycode.
107 */
108__attribute__((weak)) const uint8_t ascii_to_keycode_lut[128] PROGMEM = {
109 // NUL SOH STX ETX EOT ENQ ACK BEL
110 XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
111 // BS TAB LF VT FF CR SO SI
112 KC_BSPC, KC_TAB, KC_ENT, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
113 // DLE DC1 DC2 DC3 DC4 NAK SYN ETB
114 XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
115 // CAN EM SUB ESC FS GS RS US
116 XXXXXXX, XXXXXXX, XXXXXXX, KC_ESC, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
117
118 // ! " # $ % & '
119 KC_SPC, KC_1, KC_QUOT, KC_3, KC_4, KC_5, KC_7, KC_QUOT,
120 // ( ) * + , - . /
121 KC_9, KC_0, KC_8, KC_EQL, KC_COMM, KC_MINS, KC_DOT, KC_SLSH,
122 // 0 1 2 3 4 5 6 7
123 KC_0, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7,
124 // 8 9 : ; < = > ?
125 KC_8, KC_9, KC_SCLN, KC_SCLN, KC_COMM, KC_EQL, KC_DOT, KC_SLSH,
126 // @ A B C D E F G
127 KC_2, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G,
128 // H I J K L M N O
129 KC_H, KC_I, KC_J, KC_K, KC_L, KC_M, KC_N, KC_O,
130 // P Q R S T U V W
131 KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W,
132 // X Y Z [ \ ] ^ _
133 KC_X, KC_Y, KC_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_6, KC_MINS,
134 // ` a b c d e f g
135 KC_GRV, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G,
136 // h i j k l m n o
137 KC_H, KC_I, KC_J, KC_K, KC_L, KC_M, KC_N, KC_O,
138 // p q r s t u v w
139 KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W,
140 // x y z { | } ~ DEL
141 KC_X, KC_Y, KC_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_GRV, KC_DEL
142};
143
144// clang-format on
145
146// Note: we bit-pack in "reverse" order to optimize loading
147#define PGM_LOADBIT(mem, pos) ((pgm_read_byte(&((mem)[(pos) / 8])) >> ((pos) % 8)) & 0x01)
148
149void send_string(const char *string) {
150 send_string_with_delay(string, TAP_CODE_DELAY);
151}
152
153void send_string_with_delay(const char *string, uint8_t interval) {
154 while (1) {
155 char ascii_code = *string;
156 if (!ascii_code) break;
157 if (ascii_code == SS_QMK_PREFIX) {
158 ascii_code = *(++string);
159
160 if (ascii_code == SS_TAP_CODE) {
161 // tap
162 uint8_t keycode = *(++string);
163 tap_code(keycode);
164 } else if (ascii_code == SS_DOWN_CODE) {
165 // down
166 uint8_t keycode = *(++string);
167 register_code(keycode);
168 } else if (ascii_code == SS_UP_CODE) {
169 // up
170 uint8_t keycode = *(++string);
171 unregister_code(keycode);
172 } else if (ascii_code == SS_DELAY_CODE) {
173 // delay
174 int ms = 0;
175 uint8_t keycode = *(++string);
176
177 while (isdigit(keycode)) {
178 ms *= 10;
179 ms += keycode - '0';
180 keycode = *(++string);
181 }
182
183 wait_ms(ms);
184 }
185
186 wait_ms(interval);
187 } else {
188 send_char_with_delay(ascii_code, interval);
189 }
190
191 ++string;
192 }
193}
194
195void send_char(char ascii_code) {
196 send_char_with_delay(ascii_code, TAP_CODE_DELAY);
197}
198
199void send_char_with_delay(char ascii_code, uint8_t interval) {
200#if defined(AUDIO_ENABLE) && defined(SENDSTRING_BELL)
201 if (ascii_code == '\a') { // BEL
202 PLAY_SONG(bell_song);
203 return;
204 }
205#endif
206
207 uint8_t keycode = pgm_read_byte(&ascii_to_keycode_lut[(uint8_t)ascii_code]);
208 bool is_shifted = PGM_LOADBIT(ascii_to_shift_lut, (uint8_t)ascii_code);
209 bool is_altgred = PGM_LOADBIT(ascii_to_altgr_lut, (uint8_t)ascii_code);
210 bool is_dead = PGM_LOADBIT(ascii_to_dead_lut, (uint8_t)ascii_code);
211
212 if (is_shifted) {
213 register_code(KC_LEFT_SHIFT);
214 wait_ms(interval);
215 }
216
217 if (is_altgred) {
218 register_code(KC_RIGHT_ALT);
219 wait_ms(interval);
220 }
221
222 tap_code_delay(keycode, interval);
223 wait_ms(interval);
224
225 if (is_altgred) {
226 unregister_code(KC_RIGHT_ALT);
227 wait_ms(interval);
228 }
229
230 if (is_shifted) {
231 unregister_code(KC_LEFT_SHIFT);
232 wait_ms(interval);
233 }
234
235 if (is_dead) {
236 tap_code(KC_SPACE);
237 wait_ms(interval);
238 }
239}
240
241void send_dword(uint32_t number) {
242 send_word(number >> 16);
243 send_word(number & 0xFFFFUL);
244}
245
246void send_word(uint16_t number) {
247 send_byte(number >> 8);
248 send_byte(number & 0xFF);
249}
250
251void send_byte(uint8_t number) {
252 send_nibble(number >> 4);
253 send_nibble(number & 0xF);
254}
255
256void send_nibble(uint8_t number) {
257 switch (number & 0xF) {
258 case 0 ... 9:
259 send_char(number + '0');
260 break;
261 case 10 ... 15:
262 send_char(number - 10 + 'a');
263 break;
264 }
265}
266
267void tap_random_base64(void) {
268#if defined(__AVR_ATmega32U4__)
269 uint8_t key = (TCNT0 + TCNT1 + TCNT3 + TCNT4) % 64;
270#else
271 uint8_t key = rand() % 64;
272#endif
273 switch (key) {
274 case 0 ... 25:
275 send_char(key + 'A');
276 break;
277 case 26 ... 51:
278 send_char(key - 26 + 'a');
279 break;
280 case 52:
281 send_char('0');
282 break;
283 case 53 ... 61:
284 send_char(key - 53 + '1');
285 break;
286 case 62:
287 send_char('+');
288 break;
289 case 63:
290 send_char('/');
291 break;
292 }
293}
294
295#if defined(__AVR__)
296void send_string_P(const char *string) {
297 send_string_with_delay_P(string, TAP_CODE_DELAY);
298}
299
300void send_string_with_delay_P(const char *string, uint8_t interval) {
301 while (1) {
302 char ascii_code = pgm_read_byte(string);
303 if (!ascii_code) break;
304 if (ascii_code == SS_QMK_PREFIX) {
305 ascii_code = pgm_read_byte(++string);
306
307 if (ascii_code == SS_TAP_CODE) {
308 // tap
309 uint8_t keycode = pgm_read_byte(++string);
310 tap_code(keycode);
311 } else if (ascii_code == SS_DOWN_CODE) {
312 // down
313 uint8_t keycode = pgm_read_byte(++string);
314 register_code(keycode);
315 } else if (ascii_code == SS_UP_CODE) {
316 // up
317 uint8_t keycode = pgm_read_byte(++string);
318 unregister_code(keycode);
319 } else if (ascii_code == SS_DELAY_CODE) {
320 // delay
321 int ms = 0;
322 uint8_t keycode = pgm_read_byte(++string);
323
324 while (isdigit(keycode)) {
325 ms *= 10;
326 ms += keycode - '0';
327 keycode = pgm_read_byte(++string);
328 }
329 wait_ms(ms);
330 }
331 } else {
332 send_char_with_delay(ascii_code, interval);
333 }
334
335 ++string;
336 }
337}
338#endif