keyboard stuff
at master 229 lines 14 kB view raw view rendered
1# Stenography in QMK {#stenography-in-qmk} 2 3[Stenography](https://en.wikipedia.org/wiki/Stenotype) is a method of writing most often used by court reports, closed-captioning, and real-time transcription for the deaf. In stenography words are chorded syllable by syllable with a mixture of spelling, phonetic, and shortcut (briefs) strokes. Professional stenographers can reach 200-300 WPM without any of the strain usually found in standard typing and with far fewer errors (>99.9% accuracy). 4 5The [Open Steno Project](https://www.openstenoproject.org/) has built an open-source program called Plover that provides real-time translation of steno strokes into words and commands. It has an established dictionary and supports 6 7## Steno Support in QMK 8 9There are three ways that QMK keyboards can support steno, with varying degrees of configuration required: 10 111. Plover with [Arpeggiation](https://plover.wiki/index.php/Glossary#Arpeggiate) requires no changes to any keyboard and is supported by QMK as well as any other QWERTY keyboard. 122. Plover with [NKRO](https://plover.wiki/index.php/Using_a_standard_keyboard_with_Plover#NKRO). If your keyboard supports NKRO in hardware and you have NKRO enabled as a USB endpoint, you can chord with the keyboard. Many devices will arrive stock like this and will require no changes. 133. Steno Machine Protocols. This requires the most configuration, but this has the advantage of allowing you to use your keyboard keys normally (either on another layer or another piece of hardware) without enabling and disabling your steno software. 14 15## Plover with QWERTY Keyboard {#plover-with-qwerty-keyboard} 16 17Plover can work with any standard QWERTY keyboard, although it is more efficient if the keyboard supports NKRO (n-key rollover) to allow Plover to see all the pressed keys at once. An example keymap for Plover can be found in `planck/keymaps/default`. Switching to the `PLOVER` layer adjusts the position of the keyboard to support the number bar. 18 19To enable NKRO, add `NKRO_ENABLE = yes` in your `rules.mk` and make sure to press `NK_ON` to turn it on because `NKRO_ENABLE = yes` merely adds the possibility of switching to NKRO mode but it doesn't automatically switch to it. If you want to automatically switch, add `#define NKRO_DEFAULT_ON true` in your `config.h`. 20 21You may also need to adjust your layout, either in QMK or in Plover, if you have anything other than a standard layout. You may also want to purchase some steno-friendly keycaps to make it easier to hit multiple keys. 22 23## Plover with Steno Protocol {#plover-with-steno-protocol} 24 25Plover also understands the language of several steno machines. QMK can speak a couple of these languages: TX Bolt and GeminiPR. An example layout can be found in `splitography/keymaps/default`. 26 27When QMK speaks to Plover over a steno protocol, Plover will not use the keyboard as input. This means that you can switch back and forth between a standard keyboard and your steno keyboard, or even switch layers from Plover to standard and back without needing to activate/deactivate Plover. 28 29In this mode, Plover expects to speak with a steno machine over a serial port so QMK will present itself to the operating system as a virtual serial port in addition to a keyboard. 30 31::: info 32Due to hardware limitations, you might not be able to run both a virtual serial port and other features (mouse keys, NKRO, or MIDI support) at the same time. You will likely encounter a compile time error if this is the case. Disable those other features as necessary. 33::: 34 35::: warning 36Serial stenography protocols are not supported on [V-USB keyboards](../compatible_microcontrollers#atmel-avr). 37::: 38 39To enable stenography protocols, add the following lines to your `rules.mk`: 40```make 41STENO_ENABLE = yes 42``` 43 44### TX Bolt {#tx-bolt} 45 46TX Bolt communicates the status of 24 keys over a simple protocol in variable-sized (1–4 bytes) packets. 47 48To select TX Bolt, add the following lines to your `rules.mk`: 49```make 50STENO_ENABLE = yes 51STENO_PROTOCOL = txbolt 52``` 53 54Each byte of the packet represents a different group of steno keys. Determining the group of a certain byte of the packet is done by checking the first two bits, the remaining bits are set if the corresponding steno key was pressed for the stroke. The last set of keys (as indicated by leading `11`) needs to keep track of less keys than there are bits so one of the bits is constantly 0. 55 56The start of a new packet can be detected by comparing the group “ID” (the two MSBs) of the current byte to that of the previously received byte. If the group “ID” of the current byte is smaller or equal to that of the previous byte, it means that the current byte is the beginning of a new packet. 57 58The format of TX Bolt packets is shown below. 59``` 6000HWPKTS 01UE*OAR 10GLBPRF 110#ZDST 61``` 62 63Examples of steno strokes and the associated packet: 64- `EUBG` = `01110000 10101000` 65- `WAZ` = `00010000 01000010 11001000` 66- `PHAPBGS` = `00101000 01000010 10101100 11000010` 67 68### GeminiPR {#geminipr} 69 70GeminiPR encodes 42 keys into a 6-byte packet. While TX Bolt contains everything that is necessary for standard stenography, GeminiPR opens up many more options, including differentiating between top and bottom `S-`, and supporting non-English theories. 71 72To select GeminiPR, add the following lines to your `rules.mk`: 73```make 74STENO_ENABLE = yes 75STENO_PROTOCOL = geminipr 76``` 77 78All packets in the GeminiPR protocol consist of exactly six bytes, used as bit-arrays for different groups of keys. The beginning of a packet is indicated by setting the most significant bit (MSB) to 1 while setting the MSB of the remaining five bytes to 0. 79 80The format of GeminiPR packets is shown below. 81``` 821 Fn #1 #2 #3 #4 #5 #6 830 S1- S2- T- K- P- W- H- 840 R- A- O- *1 *2 res1 res2 850 pwr *3 *4 -E -U -F -R 860 -P -B -L -G -T -S -D 870 #7 #8 #9 #A #B #C -Z 88``` 89 90Examples of steno strokes and the associated packet: 91- `EUBG` = `10000000 00000000 00000000 00001100 00101000 00000000` 92- `WAZ` = `10000000 00000010 00100000 00000000 00000000 00000001` 93- `PHAPBGS` = `10000000 00000101 00100000 00000000 01101010 00000000` 94 95### Switching protocols on the fly {#switching-protocols-on-the-fly} 96 97If you wish to switch the serial protocol used to transfer the steno chords without having to recompile your keyboard firmware every time, you can press the `QK_STENO_BOLT` and `QK_STENO_GEMINI` keycodes in order to switch protocols on the fly. 98 99To enable these special keycodes, add the following lines to your `rules.mk`: 100```make 101STENO_ENABLE = yes 102STENO_PROTOCOL = all 103``` 104 105If you want to switch protocols programmatically, as part of a custom macro for example, don't use `tap_code(QK_STENO_*)`, as `tap_code` only supports [basic keycodes](../keycodes_basic). Instead, you should use `steno_set_mode(STENO_MODE_*)`, whose valid arguments are `STENO_MODE_BOLT` and `STENO_MODE_GEMINI`. 106 107The default protocol is Gemini PR but the last protocol used is stored in non-volatile memory so QMK will remember your choice between reboots of your keyboard — assuming that your keyboard features (emulated) EEPROM. 108 109Naturally, this option takes the most amount of firmware space as it needs to compile the code for all the available stenography protocols. In most cases, compiling a single stenography protocol is sufficient. 110 111The default value for `STENO_PROTOCOL` is `all`. 112 113## Configuring QMK for Steno {#configuring-qmk-for-steno} 114 115After enabling stenography and optionally selecting a protocol, you may also need disable mouse keys, extra keys, or another USB endpoint to prevent conflicts. The builtin USB stack for some processors only supports a certain number of USB endpoints and the virtual serial port needed for steno fills 3 of them. 116 117::: warning 118If you had *explicitly* set `VIRSTER_ENABLE = no`, none of the serial stenography protocols (GeminiPR, TX Bolt) will work properly. You are expected to either set it to `yes`, remove the line from your `rules.mk` or send the steno chords yourself in an alternative way using the [provided interceptable hooks](#interfacing-with-the-code). 119::: 120 121In your keymap, create a new layer for Plover, that you can fill in with the [steno keycodes](#keycode-reference). Remember to create a key to switch to the layer as well as a key for exiting the layer. 122 123Once you have your keyboard flashed, launch Plover. Click the 'Configure...' button. In the 'Machine' tab, select the Stenotype Machine that corresponds to your desired protocol. Click the 'Configure...' button on this tab and enter the serial port or click 'Scan'. Baud rate is fine at 9600 (although you should be able to set as high as 115200 with no issues). Use the default settings for everything else (Data Bits: 8, Stop Bits: 1, Parity: N, no flow control). 124 125To test your keymap, you can chord keys on your keyboard and either look at the output of the 'paper tape' (Tools > Paper Tape) or that of the 'layout display' (Tools > Layout Display). If your strokes correctly show up, you are now ready to steno! 126 127## Learning Stenography {#learning-stenography} 128 129* [Learn Plover!](https://sites.google.com/site/learnplover/) 130* [Steno Jig](https://joshuagrams.github.io/steno-jig/) 131* More resources at the Plover [Learning Stenography](https://github.com/openstenoproject/plover/wiki/Learning-Stenography) wiki 132 133## Interfacing with the code {#interfacing-with-the-code} 134 135The steno code has three interceptable hooks. If you define these functions, they will be called at certain points in processing; if they return true, processing continues, otherwise it's assumed you handled things. 136 137```c 138bool send_steno_chord_user(steno_mode_t mode, uint8_t chord[MAX_STROKE_SIZE]); 139``` 140 141This function is called when a chord is about to be sent. Mode will be one of `STENO_MODE_BOLT` or `STENO_MODE_GEMINI`. This represents the actual chord that would be sent via whichever protocol. You can modify the chord provided to alter what gets sent. Remember to return true if you want the regular sending process to happen. 142 143```c 144bool process_steno_user(uint16_t keycode, keyrecord_t *record) { return true; } 145``` 146 147This function is called when a keypress has come in, before it is processed. The keycode should be one of `QK_STENO_BOLT`, `QK_STENO_GEMINI`, or one of the `STN_*` key values. 148 149```c 150bool post_process_steno_user(uint16_t keycode, keyrecord_t *record, steno_mode_t mode, uint8_t chord[MAX_STROKE_SIZE], int8_t n_pressed_keys); 151``` 152 153This function is called after a key has been processed, but before any decision about whether or not to send a chord. This is where to put hooks for things like, say, live displays of steno chords or keys. 154 155If `record->event.pressed` is false, and `n_pressed_keys` is 0 or 1, the chord will be sent shortly, but has not yet been sent. This relieves you of the need of keeping track of where a packet ends and another begins. 156 157The `chord` argument contains the packet of the current chord as specified by the protocol in use. This is *NOT* simply a list of chorded steno keys of the form `[STN_E, STN_U, STN_BR, STN_GR]`. Refer to the appropriate protocol section of this document to learn more about the format of the packets in your steno protocol/mode of choice. 158 159The `n_pressed_keys` argument is the number of physical keys actually being held down. 160This is not always equal to the number of bits set to 1 (aka the [Hamming weight](https://en.wikipedia.org/wiki/Hamming_weight)) in `chord` because it is possible to simultaneously press down four keys, then release three of those four keys and then press yet another key while the fourth finger is still holding down its key. 161At the end of this scenario given as an example, `chord` would have five bits set to 1 but 162`n_pressed_keys` would be set to 2 because there are only two keys currently being pressed down. 163 164## Keycode Reference {#keycode-reference} 165 166::: info 167TX Bolt does not support the full set of keys. The TX Bolt implementation in QMK will map the GeminiPR keys to the nearest TX Bolt key so that one key map will work for both. 168::: 169 170|GeminiPR|TX Bolt|Steno Key| 171|--------|-------|-----------| 172|`STN_N1`|`STN_NUM`|Number bar #1| 173|`STN_N2`|`STN_NUM`|Number bar #2| 174|`STN_N3`|`STN_NUM`|Number bar #3| 175|`STN_N4`|`STN_NUM`|Number bar #4| 176|`STN_N5`|`STN_NUM`|Number bar #5| 177|`STN_N6`|`STN_NUM`|Number bar #6| 178|`STN_N7`|`STN_NUM`|Number bar #7| 179|`STN_N8`|`STN_NUM`|Number bar #8| 180|`STN_N9`|`STN_NUM`|Number bar #9| 181|`STN_NA`|`STN_NUM`|Number bar #A| 182|`STN_NB`|`STN_NUM`|Number bar #B| 183|`STN_NC`|`STN_NUM`|Number bar #C| 184|`STN_S1`|`STN_SL`| `S-` upper| 185|`STN_S2`|`STN_SL`| `S-` lower| 186|`STN_TL`|`STN_TL`| `T-`| 187|`STN_KL`|`STN_KL`| `K-`| 188|`STN_PL`|`STN_PL`| `P-`| 189|`STN_WL`|`STN_WL`| `W-`| 190|`STN_HL`|`STN_HL`| `H-`| 191|`STN_RL`|`STN_RL`| `R-`| 192|`STN_A`|`STN_A`| `A` vowel| 193|`STN_O`|`STN_O`| `O` vowel| 194|`STN_ST1`|`STN_STR`| `*` upper-left | 195|`STN_ST2`|`STN_STR`| `*` lower-left| 196|`STN_ST3`|`STN_STR`| `*` upper-right| 197|`STN_ST4`|`STN_STR`| `*` lower-right| 198|`STN_E`|`STN_E`| `E` vowel| 199|`STN_U`|`STN_U`| `U` vowel| 200|`STN_FR`|`STN_FR`| `-F`| 201|`STN_RR`|`STN_RR`| `-R`| 202|`STN_PR`|`STN_PR`| `-P`| 203|`STN_BR`|`STN_BR`| `-B`| 204|`STN_LR`|`STN_LR`| `-L`| 205|`STN_GR`|`STN_GR`| `-G`| 206|`STN_TR`|`STN_TR`| `-T`| 207|`STN_SR`|`STN_SR`| `-S`| 208|`STN_DR`|`STN_DR`| `-D`| 209|`STN_ZR`|`STN_ZR`| `-Z`| 210|`STN_FN`|| (Function)| 211|`STN_RES1`||(Reset 1)| 212|`STN_RES2`||(Reset 2)| 213|`STN_PWR`||(Power)| 214 215If you do not want to hit two keys with one finger combined keycodes can be used. These cause both keys to be reported as pressed or released. To use these keycodes define `STENO_COMBINEDMAP` in your `config.h` file. 216 217|Combined key | Key1 | Key 2 | 218|---------------|--------|----------| 219|STN_S3 | STN_S1 | STN_S2 | 220|STN_TKL | STN_TL | STN_KL | 221|STN_PWL | STN_PL | STN_WL | 222|STN_HRL | STN_HL | STN_RL | 223|STN_FRR | STN_FR | STN_RR | 224|STN_PBR | STN_PR | STN_BR | 225|STN_LGR | STN_LR | STN_GR | 226|STN_TSR | STN_TR | STN_SR | 227|STN_DZR | STN_DR | STN_ZR | 228|STN_AO | STN_A | STN_O | 229|STN_EU | STN_E | STN_U |