send_string.c (11103B)
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 32 float 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 149 void send_string(const char *string) { 150 send_string_with_delay(string, TAP_CODE_DELAY); 151 } 152 153 void send_string_with_delay_impl(char (*getter)(void *), void *arg, uint8_t interval) { 154 while (1) { 155 char ascii_code = getter(arg); 156 if (!ascii_code) break; 157 if (ascii_code == SS_QMK_PREFIX) { 158 ascii_code = getter(arg); 159 160 if (ascii_code == SS_TAP_CODE) { 161 // tap 162 uint8_t keycode = getter(arg); 163 tap_code(keycode); 164 } else if (ascii_code == SS_DOWN_CODE) { 165 // down 166 uint8_t keycode = getter(arg); 167 register_code(keycode); 168 } else if (ascii_code == SS_UP_CODE) { 169 // up 170 uint8_t keycode = getter(arg); 171 unregister_code(keycode); 172 } else if (ascii_code == SS_DELAY_CODE) { 173 // delay 174 int ms = 0; 175 ascii_code = getter(arg); 176 177 while (isdigit(ascii_code)) { 178 ms *= 10; 179 ms += ascii_code - '0'; 180 ascii_code = getter(arg); 181 } 182 183 wait_ms(ms); 184 } 185 186 wait_ms(interval); 187 188 // if we had a delay that terminated with a null, we're done 189 if (ascii_code == 0) break; 190 } else { 191 send_char_with_delay(ascii_code, interval); 192 } 193 } 194 } 195 196 typedef struct send_string_memory_state_t { 197 const char *string; 198 } send_string_memory_state_t; 199 200 char send_string_get_next_ram(void *arg) { 201 send_string_memory_state_t *state = (send_string_memory_state_t *)arg; 202 char ret = *state->string; 203 state->string++; 204 return ret; 205 } 206 207 void send_string_with_delay(const char *string, uint8_t interval) { 208 send_string_memory_state_t state = {string}; 209 send_string_with_delay_impl(send_string_get_next_ram, &state, interval); 210 } 211 212 void send_char(char ascii_code) { 213 send_char_with_delay(ascii_code, TAP_CODE_DELAY); 214 } 215 216 void send_char_with_delay(char ascii_code, uint8_t interval) { 217 #if defined(AUDIO_ENABLE) && defined(SENDSTRING_BELL) 218 if (ascii_code == '\a') { // BEL 219 PLAY_SONG(bell_song); 220 return; 221 } 222 #endif 223 224 uint8_t keycode = pgm_read_byte(&ascii_to_keycode_lut[(uint8_t)ascii_code]); 225 bool is_shifted = PGM_LOADBIT(ascii_to_shift_lut, (uint8_t)ascii_code); 226 bool is_altgred = PGM_LOADBIT(ascii_to_altgr_lut, (uint8_t)ascii_code); 227 bool is_dead = PGM_LOADBIT(ascii_to_dead_lut, (uint8_t)ascii_code); 228 229 if (is_shifted) { 230 register_code(KC_LEFT_SHIFT); 231 wait_ms(interval); 232 } 233 234 if (is_altgred) { 235 register_code(KC_RIGHT_ALT); 236 wait_ms(interval); 237 } 238 239 tap_code_delay(keycode, interval); 240 wait_ms(interval); 241 242 if (is_altgred) { 243 unregister_code(KC_RIGHT_ALT); 244 wait_ms(interval); 245 } 246 247 if (is_shifted) { 248 unregister_code(KC_LEFT_SHIFT); 249 wait_ms(interval); 250 } 251 252 if (is_dead) { 253 tap_code(KC_SPACE); 254 wait_ms(interval); 255 } 256 } 257 258 void send_dword(uint32_t number) { 259 send_word(number >> 16); 260 send_word(number & 0xFFFFUL); 261 } 262 263 void send_word(uint16_t number) { 264 send_byte(number >> 8); 265 send_byte(number & 0xFF); 266 } 267 268 void send_byte(uint8_t number) { 269 send_nibble(number >> 4); 270 send_nibble(number & 0xF); 271 } 272 273 void send_nibble(uint8_t number) { 274 switch (number & 0xF) { 275 case 0 ... 9: 276 send_char(number + '0'); 277 break; 278 case 10 ... 15: 279 send_char(number - 10 + 'a'); 280 break; 281 } 282 } 283 284 #if defined(__AVR_ATmega32U4__) 285 # include <avr/io.h> 286 #endif 287 288 void tap_random_base64(void) { 289 #if defined(__AVR_ATmega32U4__) 290 uint8_t key = (TCNT0 + TCNT1 + TCNT3 + TCNT4) % 64; 291 #else 292 uint8_t key = rand() % 64; 293 #endif 294 switch (key) { 295 case 0 ... 25: 296 send_char(key + 'A'); 297 break; 298 case 26 ... 51: 299 send_char(key - 26 + 'a'); 300 break; 301 case 52: 302 send_char('0'); 303 break; 304 case 53 ... 61: 305 send_char(key - 53 + '1'); 306 break; 307 case 62: 308 send_char('+'); 309 break; 310 case 63: 311 send_char('/'); 312 break; 313 } 314 } 315 316 #if defined(__AVR__) 317 void send_string_P(const char *string) { 318 send_string_with_delay_P(string, TAP_CODE_DELAY); 319 } 320 321 char send_string_get_next_progmem(void *arg) { 322 send_string_memory_state_t *state = (send_string_memory_state_t *)arg; 323 char ret = pgm_read_byte(state->string); 324 state->string++; 325 return ret; 326 } 327 328 void send_string_with_delay_P(const char *string, uint8_t interval) { 329 send_string_memory_state_t state = {string}; 330 send_string_with_delay_impl(send_string_get_next_progmem, &state, interval); 331 } 332 #endif