diff --git a/keyboards/planck/keymaps/steno/Makefile b/keyboards/planck/keymaps/steno/Makefile index 3ed9d2db45f..874154af630 100644 --- a/keyboards/planck/keymaps/steno/Makefile +++ b/keyboards/planck/keymaps/steno/Makefile @@ -3,5 +3,5 @@ ifndef QUANTUM_DIR endif MOUSEKEY_ENABLE = no # Mouse keys(+4700) -STENO_ENABLE = yes # Enable TX Bolt protocol for Stenography, requires VIRTSER and may not work with mouse keys - +STENO_ENABLE = yes # Additional protocols for Stenography(+1700), requires VIRTSER +AUDIO_ENABLE = no # Audio output on port C6 diff --git a/keyboards/planck/keymaps/steno/keymap.c b/keyboards/planck/keymaps/steno/keymap.c index b4e30169fb3..38540a26137 100644 --- a/keyboards/planck/keymaps/steno/keymap.c +++ b/keyboards/planck/keymaps/steno/keymap.c @@ -41,6 +41,9 @@ enum planck_keycodes { EXT_PLV }; +#define ST_BOLT QK_STENO_BOLT +#define ST_GEM QK_STENO_GEMINI + const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { /* Qwerty @@ -166,7 +169,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { [_ADJUST] = { {_______, RESET, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_DEL }, {_______, _______, MU_MOD, AU_ON, AU_OFF, AG_NORM, AG_SWAP, QWERTY, COLEMAK, DVORAK, PLOVER, _______}, - {_______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, _______, _______, _______, _______, _______}, + {_______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, _______, _______, _______, ST_BOLT, ST_GEM}, {_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______} } diff --git a/quantum/keymap_extras/keymap_steno.h b/quantum/keymap_extras/keymap_steno.h index 4eb1c7477ad..4ce91cc1352 100644 --- a/quantum/keymap_extras/keymap_steno.h +++ b/quantum/keymap_extras/keymap_steno.h @@ -18,8 +18,12 @@ #include "keymap.h" +// List of keycodes for the steno keyboard. To prevent +// errors, this must be <= 42 total entries in order to +// support the GeminiPR protocol. enum steno_keycodes { - STN_FN = QK_STENO, + STN__MIN = QK_STENO, + STN_FN = STN__MIN, STN_NUM, STN_N1 = STN_NUM, STN_N2, @@ -65,7 +69,8 @@ enum steno_keycodes { STN_NA, STN_NB, STN_NC, - STN_ZR + STN_ZR, + STN__MAX = STN_ZR, // must be less than QK_STENO_BOLT }; #endif diff --git a/quantum/process_keycode/process_steno.c b/quantum/process_keycode/process_steno.c index 211f00a5a2b..a9126866603 100644 --- a/quantum/process_keycode/process_steno.c +++ b/quantum/process_keycode/process_steno.c @@ -1,12 +1,8 @@ -#include "process_steno.h" + #include "process_steno.h" #include "quantum_keycodes.h" #include "keymap_steno.h" #include "virtser.h" -uint8_t state[4] = {0}; -uint8_t pressed = 0; - - // TxBolt Codes #define TXB_NUL 0 #define TXB_S_L 0b00000001 @@ -41,6 +37,13 @@ uint8_t pressed = 0; #define TXB_GET_GROUP(code) ((code & TXB_GRPMASK) >> 6) +#define BOLT_STATE_SIZE 4 +#define GEMINI_STATE_SIZE 6 + +uint8_t state[MAX(BOLT_STATE_SIZE, GEMINI_STATE_SIZE)] = {0}; +uint8_t pressed = 0; +steno_mode_t mode; + uint8_t boltmap[64] = { 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, @@ -52,31 +55,97 @@ uint8_t boltmap[64] = { #define BOLTMAP_MASK (sizeof(boltmap) - 1) -void send_steno_state(void) { - for (uint8_t i = 0; i < 4; ++i) { - if (state[i]) { + +void steno_clear_state(void) { + memset(state, 0, sizeof(state)); +} + +void steno_init() { + if (!eeconfig_is_enabled()) { + eeconfig_init(); + } + mode = eeprom_read_byte(EECONFIG_STENOMODE); +} + +void steno_set_mode(steno_mode_t new_mode) { + steno_clear_state(); + mode = new_mode; + eeprom_update_byte(EECONFIG_STENOMODE, mode); +} + +void send_steno_state(uint8_t size, bool send_empty) { + for (uint8_t i = 0; i < size; ++i) { + if (state[i] || send_empty) { virtser_send(state[i]); - state[i] = 0; } } - virtser_send(0); + steno_clear_state(); +} + +bool update_state_bolt(uint8_t key) { + uint8_t boltcode = boltmap[key]; + state[TXB_GET_GROUP(boltcode)] |= boltcode; + return false; +} + +bool send_state_bolt(void) { + send_steno_state(BOLT_STATE_SIZE, false); + virtser_send(0); // terminating byte + return false; +} + +bool update_state_gemini(uint8_t key) { + state[key / 7] |= 1 << (6 - (key % 7)); + return false; +} + +bool send_state_gemini(void) { + state[0] |= 0x80; // Indicate start of packet + send_steno_state(GEMINI_STATE_SIZE, true); + return false; } bool process_steno(uint16_t keycode, keyrecord_t *record) { - if(keycode >= QK_STENO && keycode <= QK_STENO_MAX) { - if(IS_PRESSED(record->event)) { - uint8_t boltcode = boltmap[keycode & BOLTMAP_MASK]; - ++pressed; - state[TXB_GET_GROUP(boltcode)] |= boltcode; - } else { - --pressed; - if (pressed <= 0) { - pressed = 0; // protect against spurious up keys - send_steno_state(); + switch (keycode) { + case QK_STENO_BOLT: + if (IS_PRESSED(record->event)) { + steno_set_mode(STENO_MODE_BOLT); } - } - return false; - } + return false; + case QK_STENO_GEMINI: + if (IS_PRESSED(record->event)) { + steno_set_mode(STENO_MODE_GEMINI); + } + return false; + + case STN__MIN...STN__MAX: + if (IS_PRESSED(record->event)) { + uint8_t key = keycode - QK_STENO; + ++pressed; + switch(mode) { + case STENO_MODE_BOLT: + return update_state_bolt(key); + case STENO_MODE_GEMINI: + return update_state_gemini(key); + default: + return false; + } + } else { + --pressed; + if (pressed <= 0) { + pressed = 0; + switch(mode) { + case STENO_MODE_BOLT: + return send_state_bolt(); + case STENO_MODE_GEMINI: + return send_state_gemini(); + default: + return false; + } + } + } + + } return true; } diff --git a/quantum/process_keycode/process_steno.h b/quantum/process_keycode/process_steno.h index fb9b8e8adce..abd1d466cc4 100644 --- a/quantum/process_keycode/process_steno.h +++ b/quantum/process_keycode/process_steno.h @@ -7,6 +7,10 @@ #error "must have virtser enabled to use steno" #endif +typedef enum { STENO_MODE_BOLT, STENO_MODE_GEMINI } steno_mode_t; + bool process_steno(uint16_t keycode, keyrecord_t *record); +void steno_init(void); +void steno_set_mode(steno_mode_t mode); #endif \ No newline at end of file diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h index f0937628e87..ee2fac03850 100644 --- a/quantum/quantum_keycodes.h +++ b/quantum/quantum_keycodes.h @@ -73,6 +73,8 @@ enum quantum_keycodes { QK_LAYER_TAP_TOGGLE_MAX = 0x58FF, #ifdef STENO_ENABLE QK_STENO = 0x5900, + QK_STENO_BOLT = 0x5930, + QK_STENO_GEMINI = 0x5931, QK_STENO_MAX = 0x593F, #endif QK_MOD_TAP = 0x6000, diff --git a/tmk_core/common/eeconfig.c b/tmk_core/common/eeconfig.c index 140d2b85bb9..e2eb4a38e3d 100644 --- a/tmk_core/common/eeconfig.c +++ b/tmk_core/common/eeconfig.c @@ -19,6 +19,9 @@ void eeconfig_init(void) #ifdef RGBLIGHT_ENABLE eeprom_update_dword(EECONFIG_RGBLIGHT, 0); #endif +#ifdef STENO_ENABLE + eeprom_update_byte(EECONFIG_STENOMODE, 0); +#endif } void eeconfig_enable(void) diff --git a/tmk_core/common/eeconfig.h b/tmk_core/common/eeconfig.h index 280dc7ab67e..ce60ca86615 100644 --- a/tmk_core/common/eeconfig.h +++ b/tmk_core/common/eeconfig.h @@ -34,6 +34,7 @@ along with this program. If not, see . #define EECONFIG_AUDIO (uint8_t *)7 #define EECONFIG_RGBLIGHT (uint32_t *)8 #define EECONFIG_UNICODEMODE (uint8_t *)12 +#define EECONFIG_STENOMODE (uint8_t *)13 /* debug bit */ diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index 97a8f1cd8c4..9466e10e2d4 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -51,6 +51,9 @@ along with this program. If not, see . #ifdef RGBLIGHT_ENABLE # include "rgblight.h" #endif +#ifdef STENO_ENABLE +# include "process_steno.h" +#endif #ifdef FAUXCLICKY_ENABLE # include "fauxclicky.h" #endif @@ -139,6 +142,9 @@ void keyboard_init(void) { #ifdef RGBLIGHT_ENABLE rgblight_init(); #endif +#ifdef STENO_ENABLE + steno_init(); +#endif #ifdef FAUXCLICKY_ENABLE fauxclicky_init(); #endif