-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathmain.tex
1864 lines (1359 loc) · 68.3 KB
/
main.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
\documentclass{kiibohd-template}
\begin{document}
%% General Notes and Guidelines when editing this document %% XXX <---
% - To say this calmly, ONE SENTENCE PER LINE, no exceptions.
% - If you want to use a table, there is a table macro
% - If you want to include a diagram/figure/picture, there is a macro for that
% - Use \todo and \todo[inline] to indicate TODOs
% - Use LaTex comments to indicate formatting and tricky LaTex usage
% - XXX indicates something to take note of (it highlights in many text editors, as does TODO)
% - FIXME is another highlighting tag :D
\title{KLL Spec v0.5.6}
\titlename{Keyboard Layout Language Spec}
\author{HaaTa - Jacob Alexander}
\email{[email protected]}
\docrev{DRAFT - 0.5.6}
\urlname{kiibohd.com}
%%% Titlepage %%%
\maketitle
%%% Revision History %%%
\begin{versionhistory}
\vhEntry{0.1}{2014-05-10}{HaaTa}{Initial Draft}
\vhEntry{0.2}{2014-05-11}{HaaTa}{Finished trigger section}
\vhEntry{0.2a}{2014-05-15}{HaaTa}{Finished result section}
\vhEntry{0.2b}{2014-05-17}{HaaTa}{Initial pass at USB Code Table}
\vhEntry{0.2c}{2014-05-18}{HaaTa}{Finished USB Code Table}
\vhEntry{0.3}{2014-09-07}{HaaTa}{Initial KLL implementation}
\vhEntry{0.3a}{2014-11-21}{HaaTa}{Adding Defines}
\vhEntry{0.3b}{2015-05-02}{HaaTa}{Adding Media Keys and Null Key}
\vhEntry{0.3c}{2015-09-29}{HaaTa}{Adding soft replacement}
\vhEntry{0.3d}{2015-10-17}{HaaTa}{Adding more consumer control codes}
\vhEntry{0.4}{2015-05-19}{HaaTa}{Adding key state scheduling}
\vhEntry{0.5}{2015-12-02}{HaaTa}{Adding Pixel Output Control}
\vhEntry{0.5a}{2015-12-10}{HaaTa}{Adding array variables}
\vhEntry{0.5b}{2016-04-20}{HaaTa}{Adding trigger macro isolation}
\vhEntry{0.5c}{2016-10-09}{HaaTa}{Adding pixel addressing types}
\vhEntry{0.5.4}{2018-03-24}{HaaTa}{Adding new trigger options}
\vhEntry{0.5.5}{2018-05-03}{HaaTa}{Adding Locale support}
\vhEntry{0.5.6}{2018-08-11}{HaaTa}{Adding rotation trigger}
\vhEntry{0.5.7}{2019-02-03}{HaaTa}{Adding clearactive replace state}
\end{versionhistory}
%%% Tables %%%
\printtables
%%% Summary %%%
\chapter{Summary}
This document outlines a complex keymapping scheme for custom keyboard firmware.
It is based upon the concept of trigger:result pairs and ways to configure both parts of the pair (input and output).
A variety of macros are supported along with analog keyswitches.
In addition, this keymapping scheme supports static and dynamic layering as well as supporting arbitrary keyboard features that may or may not be available on a given keyboard.
%%% Scope %%%
\chapter{Scope}
Hardware keymappings for keyboards traditionally has been cumbersome.
At best, each layer can be defined as a set of predefined trigger:result pairs.
A trigger being a key and a result being a key press (e.g. USB Code).
Some keyboards allow for macros; however, these macros usually have to be custom programmed to the microcontroller (most, if not all custom keyboard firmware), or have very limited scope (Kinesis Advantage Pro and some Cherry POS keyboards such as the G80-8200).
Secondly, keymap layering (e.g. FN Layer) almost universally supports distinct layers (in the firmware that support this).
However, no current firmware support ``partial layering''.
Partial layering is only modifying a part of the current layout, similar to how XKB handles remapping Ctrl and CapsLock.
To reduce size constraints, EEPROM storage of keyboard layouts will not be considered.
It may be possible to do post compilation keymap modifications, but this is considered optional for an implementation.
Finally, as of current (2015-05-10), no keymapping mechanism supports analog keyswitches for use in typing.
This is mostly lack of availability of analog keyboard switches.
%%% Variables %%%
\chapter{Variables}
Variables serve two purposes.
The first, to give information to the compiler both for informational and controlling internal keyboard firmware features.
The second is for keymapping convenience.
In most cases variables will only be used for compiler information.
Variables used for non-compiler purposes must be integers.
The compiler will enforce this.
Variables are defined as follows.
\begin{lstlisting}
<variable name> = <contents>;
\end{lstlisting}
Each command ends with a semi colon, there are no exceptions to this.
Every keymap file will have the following variable.
\begin{lstlisting}
Name = myKeymapFile;
\end{lstlisting}
If spaces are required for either the variable name or variable contents, doubles quotes may be used.
The spaces will be internally converted to underscores if the variable is used for non-informational purposes.
Variable names can only use A-Z, a-z, 0-9 and underscores and must not start with a number.
\begin{lstlisting}
"space containing variable" = "space-ful variable";
mix = "And Match";
\end{lstlisting}
In some cases it's necessary to define an array variable to give the compiler better context of the variables.
Particularily when defining separate buffer locations that need to be combined into a single index range (e.g. Pixel Control).
Arrays can be defined by index or space separated list.
If the compiler is unsure about how to use the array it will default to a space separated list as the output (e.g. Defines).
\begin{lstlisting}
variable[0] = "index 1 info";
variable[1] = 56;
var2[] = item1 item2 "item 3";
\end{lstlisting}
%% Defines %%
\section{Defines}
\label{sec:Defines}
Defines are a special case of variables that are used to influence static configuration options of the keyboard.
This allows information to be given to the keyboard firmware before it is compiled.
For example, defining the word size of the macro definition (i.e.\ using 8 bit instead of 32 bit when only 256 positions are required).
Defines are set the same way as variables are.
However, and additional configuration is required to indicate which variables set defines for the compiled firmware.
This help save the user from not setting critical defines that the firmware requires as warning messages are generated by the compiler when they are missing.
\begin{lstlisting}
<capability name> => <corresponding C/C++ define>;
\end{lstlisting}
Each keyboard will likely have a different set of configurable defines which will be exposed.
By default, they will have set values; however, these values can be overridden.
\begin{lstlisting}
# Define declaration
myDefine => myCDefine;
# Default value
myDefine = 23;
# Override
myDefine = 144;
\end{lstlisting}
In order to pass strings, the desired quotes must be double-quoted.
\begin{lstlisting}
myDefine => myCDefine;
# Correct
myDefine = '"This is a good string"';
# Possibly incorrect
myDefine = "This is an iffy string";
\end{lstlisting}
The second variable assignment will not pass the double quotes to the generated file so the result will not be interpreted as a C-String by the C/C++ compiler.
%%% Capabilities %%%
\chapter{Capabilities}
\label{chpt:Capabilities}
Capabilities define what the keyboard can do.
At basic level, each keyboard has the capability to send USB Codes.
Some keyboards have solenoids that can be fired, others have clickers.
Capabilities are read by the compiler to cross-reference the functions that control that capability to the designated key press.
If a capability is specified as a result to a keypress and is not defined for the specified keyboard, it is ignored and removed from the compiled keyboard mappings (for each of the layers it is defined on).
In general, capabilities specific to each keyboard are defined in the keyboard specific Scan Code to USB Code keymap.
Capabilities such as clickers and solenoids are defined using a standard so that their functionality does not have to be redefined for each keymap (i.e.\ keymaps are transferable between keyboards even with special functionality that does not apply to every keyboard).
Capabilities are defined as follows.
\begin{lstlisting}
<capability name> => <corresponding C/C++ function>;
\end{lstlisting}
The arguments of the C/C++ function must be specified, but not defined.
Capabilities are used to describe to both the compiler and user, what the special functionality is supposed to do.
The argument names themselves should be descriptive names containing no spaces, start with a letter and may use a-z, A-Z, 0-9 and underscore.
The colon after each argument specifies the byte length of the argument.
This number must be an positive integer.
Capabilities have two implied arguments, state and state type.
These arguments are set by the TriggerMacro that signaled this Capability.
\begin{lstlisting}
# Correct
myCapability => myCFunction( arg1:1, arg2:2 );
# Incorrect, defines the arg2 as 25
yourCapability => myCFunction( arg1:1, 25:2 );
\end{lstlisting}
Refer to Section~\ref{chpt:CapabilitiesTable} for a list of common capabilities.
%%% Keymapping %%%
\chapter{Keymapping}
Keymapping is the main purpose of KLL.
KLL is designed to deal with most kinds of macros and layering (in addition to keyboard specific functions).
Keymapping is defined in two parts.
The first part is call the trigger.
The trigger defines what the signal of a keypress (e.g.\ press a) is that will be used to generate a result (e.g.\ send USB Code a).
Triggers can be simple or very complex.
Defined as Scan Codes (non-portable) and USB Codes (portable).
The second part is called a result.
The result is what the keyboard firmware is designated to do once the corresponding trigger is received.
Results vary from sending single USB Codes, to USB Code Macros, to enabling keyboard specific capabilities and toggling other keymapped layers.
Defined as USB Codes and Capabilities.
If an undefined Capability is used it is ignored and the trigger:result pair is removed from the keymap.
As a note, time based key sequences (e.g.\ entering keys within a specified period of time) are not supported for both the trigger and result mechanisms.
These may be added in a future version of KLL if enough demand (and a sensible/scalable implementation is proposed).
The following is the general syntax of the trigger:result pair.
\begin{lstlisting}
<trigger> : <result>;
\end{lstlisting}
There are four variants of the trigger:result pair.
Depending on which variant is used, assignment of the result changes.
\begin{lstlisting}
<trigger> : <result>; # Replaces results on trigger
<trigger> :: <result>; # Soft layer replacement
<trigger> :+ <result>; # Adds results to trigger
<trigger> :- <result>; # Removes result from trigger
\end{lstlisting}
In general, the normal trigger:result pair will be used to replace/change keymapping.
The trigger::result pair is a soft layer replacement which is used to only do replacement if two conditions are met: not the default layer and the trigger being replaced is not the same as defined in the base map.
This is useful for making broad replacement rules for all layers but only come into effect if actually being used.
An adding trigger:+result pair is useful when adding an extra action to a key of macro of keys (e.g.\ solenoid press).
A subtraction trigger:-result pair is useful when compiling in many layouts and there are certain additions that are undesirable.
% Isolation
\subsection{Isolation}
Sometimes it's useful to define macros that are comprised of simple macros already linked to results.
Instead of using the more sophisticated state scheduling in Section~\ref{subsubsec:ScanCodeStateScheduling}, trigger assignment isolation can be used.
For example, say the A and B keys are already assigned to output `A' and `B' respectively.
However, you want A+B together to output `Q', but not `A' or `B'.
Isolation macros, when triggered will cancel any other macros that may be active or may activate during that processing loop.
This means if you pressed A, then B, `A' then `Q' will be displayed.
And if you keep holding down B and A, then `Q' will start repeating.
If A is released, then `B' will output.
So, to just output `Q' both A and B must be pressed then released during the same scan cycle.
\begin{lstlisting}
<trigger> i: <result>; # Replaces results on trigger
<trigger> i:: <result>; # Soft layer replacement
<trigger> i:+ <result>; # Adds results to trigger
<trigger> i:- <result>; # Removes result from trigger
\end{lstlisting}
If more than one isolation trigger is activated at the same time the behaviour is undefined and any one of the isolated triggers may take priority depending on how the firmware processes the inputs.
%% Trigger
\section{Trigger}
The trigger defines the conditions required for a specific keymapping.
These conditions can be as simple as a single key press or as complex as sequences of key combinations.
A trigger is defined for each type of source.
For a keyboard, the source types are Scan Codes and USB Codes.
Other types of source types include axis control (mouse), rotation control (mouse wheel), indicator codes (keyboard lock lights).
Beyond this, it is possible to specify ranges of sources to do the same function.
Require a sequence of sources entered to enable a function.
Use a combination of sources to trigger a capability.
For each type of source a state may be used to control what the trigger of the source is.
With analog switches it's possible to define a percentage value threshold for a key.
Precedence is evaluated as follows: Scan Code/USB Code/Source then range, then combination and finally sequence.
Ranges of combinations does not make sense, nor does combinations of sequences.
% Sources
\subsection{Sources}
A source is a control interface that generates a change in state that, using a measure or threshold that can trigger an event.
For keyboards, Scan Codes are native identifiers to the keyboard firmware.
Whereas USB Codes are the identifiers used to send over USB to the OS.
After compilation, all keymappings are mapped to Scan Codes; however, using Scan Codes in keymap files is not portable between different keyboards so their use is discouraged outside of defining the default Scan Code to USB Code keymap.
Logical mappings are not used for other types of control such as axis control, rotation control and indicator codes.
% Scan Code
\subsection{Scan Code}
\label{subsec:Scan_Code}
Scan Codes are the native identifier for keypresses on keyboard firmware.
In general, Scan Codes should not be used for defining keymaps; however, they are required for defining the initial Scan Code to USB Code mapping for each keyboard.
Each trigger must identify whether it is a Scan Code or USB Code.
For Scan Codes it is prefixed with an S.
\begin{lstlisting}
S<Scan Code> : <result>;
\end{lstlisting}
Scan Codes can be defined as either hex or decimal numbers.
\begin{lstlisting}
S0x2A : <result>;
S124 : <result>;
\end{lstlisting}
The compiler will error if it is specified in the keymap explicitly.
For keyboards that are interconnect capable, it is possible to set the interconnect index for that keyboard.
By default, a scan code is defined as index 0.
This can be changed using the \textbf{ConnectId} variable.
This variable is effective immediately.
\begin{lstlisting}
S0x2A : <result>; # Defaults to index 0
ConnectId = 2;
S0x2A : <result>; # Defaults to index 2
S124 : <result>; # Also defaults to index 2
\end{lstlisting}
% State Scheduling
\subsubsection{State Scheduling}
\label{subsubsec:ScanCodeStateScheduling}
Instead of processing the trigger immediately, as done by default, it is also possible to put additional state conditions on the keypress.
Keyswitch trigger events have 6 different states that can be specified: press (\textbf{P}), hold (\textbf{H}), release (\textbf{R}), off (\textbf{O}), unique press (\textbf{UP}) and unique release (\textbf{UR}).
State conditions are defined using parenthesis after the keyswitch definition.
The press event is the default schedule event for keyswitches.
The release event is useful for signalling an event after the key has been released rather than when it was pressed.
Unique press is a special state that requires no other keyswitch is currently in the press or hold state.
Unique release is another special state requiring no additional keypresses since this key was pressed.
This is often referred to as ``tap'' keys.
\begin{lstlisting}
S100 : <result>;
S100(P) : <result>; # Same as above
S101(UP) : <result>; # Tap key
S102(UR) : <result>; # Single key input
S103(R) : <result>; # Single-shot on release
\end{lstlisting}
Hold and off are non-triggering events so they cannot be used to trigger results alone.
This means they \textbf{must} be part of a combination with a triggering event (see Section~\ref{subsec:Combination}).
\begin{lstlisting}
S104(H) : <result>; # Incorrect
S104(H) + S105(O) : <result>; # Incorrect
S100 + S104(H) : <result>; # Correct, holding a key
S101 + S105(O) : <result>; # Correct, key is not pressed
\end{lstlisting}
% Key Positioning
\subsubsection{Key Positioning}
\label{subsubsec:keypositioning}
It is possible to give a physical location to a particular Scan Code.
This allows for configuration utilities to automatically generate the layout as well as give hints to pixel positioning (i.e. backlight keys).
Key positioning is generally completely optional and needs to be done once for every physical layout configuration of the device.
Each key may be assigned the following options, by default they are set to 0.
\begin{itemize}
\item x, y, z positions (mm)
\item rx, ry, rz rotations (deg)
\end{itemize}
The units are in mm and degrees respectively.
\begin{lstlisting}
# Set the x position 20 mm and x rotation 15 deg
S120 <= x:20,rx:15;
\end{lstlisting}
Currently keycap shape is not supported.
Though suggestions are welcome on how best to support them (especially the odd shaped ones).
% USB Code
\subsection{USB Code}
\label{subsec:USB_Code}
USB Codes define how USB understands keyboard output press/release events and are defined by the USB HID Spec.
USB Codes are the recommend identifier when defining triggers for KLL keymaps.
Each trigger must identify whether it is a Scan Code or USB Code.
For USB Codes it is prefixed with a U.
\begin{lstlisting}
U<USB Code> : <result>;
\end{lstlisting}
USB Codes can be defined in a number of ways.
Like Scan Codes, the USB Code can be defined directly using hex or decimal numbers (not recommended).
The recommended way is to use the descriptive names for the USB Codes.
Descriptive names are always strings, and must be enclosed with double quotes.
\begin{lstlisting}
U0x2A : <result>;
U124 : <result>;
U"A" : <result>;
U"a" : <result>; # Same as previous
\end{lstlisting}
Refer to Section~\ref{chpt:USBCodeTable} for the complete list of standard (US ANSI) USB Codes.
For dealing with non-ANSI keyboard locales and layouts please refer to Section~\ref{sec:locales}.
There is an important difference when using a USB Code as the the Trigger as compared to a Scan Code.
When an assignment is done using a USB Code, a lookup must occur to find the original Scan Code that the USB Code was assigned to.
Since assignment order matters this can become confusing.
\begin{lstlisting}
U"s" : U"r";
U"r" : U"p";
\end{lstlisting}
This has an unintended side-effect.
All R's will be assigned to P.
If the user is aware, the problem isn't too bad to deal with.
However, this is a very tricky problem to deal with for GUI keymap programs as it is not intuitive to enforce order.
Therefore, to resolve this issue, all assignments using a USB Code trigger must be cached until the current kll file has finished parsing.
Then the cached assignments can be applied to the current layer.
This will allow mass assignment of keys without having to worry about the order of assignment.
If re-assignment is needed, use another kll file or a Scan Code trigger.
% State Scheduling
\subsubsection{State Scheduling}
\label{subsubsec:trigusbstateschedule}
All of state schedulers used for Scan Code triggers are applicable for USB Code triggers (see Section~\ref{subsubsec:ScanCodeStateScheduling}).
\begin{lstlisting}
U"A" : <result>;
U"A"(P) : <result>; # Same as above
U"B"(UP) : <result>; # Tap key
U"C"(UR) : <result>; # Single key input
U"D"(R) : <result>; # Single-shot on release
U"A" + U"Q"(H) : <result>; # Correct, holding a key
U"B" + U"W"(O) : <result>; # Correct, key is not pressed
\end{lstlisting}
% Button Code
%\subsubsection{Button Code}
% TODO
% B[<num>]
% Linear Code
%\subsubsection{Linear Code}
% TODO - Use +/- for relative state
% L[<num>]
% Rotation Code
%\subsubsection{Rotation Code}
% TODO - Use +/- for relative state
% R[<num>]
% Analog
\subsubsection{Analog States}
For analog keyboard switches, it is useful to specify a trigger at a press percentage as press/release behaviour needs to be defined.
The expected implementation defines a press when the key stops moving or begins to move back up.
If a stopped key moves further down (past the next trigger), stops or begins to move back up the next trigger is used and the previous on is released.
Again, if the stopped key moves back up going back over a past trigger, stops (or with a slight delay before going back up further) this past trigger will activate, releasing the previous trigger.
Analog triggers are specified using parenthesis.
\begin{lstlisting}
<Code>(<Analog Value>) : <result>;
\end{lstlisting}
Both USB Codes and Scan Codes can be used with analog keyboards signals.
Mapping analog triggers gets more tricky, so it is recommended that they are only used with USB Codes.
Analog triggers are specified from 0 to 100 using integers only.
0 is a special case and is only pulsed when it is reached rather than held.
\begin{lstlisting}
S0x2A(10) : <result>; # 10% press
S0x2A(80) : <result>; # 80% press
U124 (50) : <result>; # 50% press
U"A" (0) : <result>; # 0% pulse
U"a" (52) : <result>; # 52% press
\end{lstlisting}
If the keyboard is not analog, any trigger with an analog trigger will be ignored.
And inversely, if the Scan Code/USB Code maps to an analog key, a normal press/release trigger will be ignored.
% LED Indicator Code
\subsection{LED Indicator Code}
\label{subsec:LED_Indicator_Code}
Instead of using a keypress as the trigger to a macro, it is also possible to use the state of a HID LED Indicator such as Caps Lock.
\begin{lstlisting}
I<Indicator Code> : <result>;
\end{lstlisting}
Indicator codes can be specified using a numeric or string identifier.
\begin{lstlisting}
U"a" + I2 : <result>; # a + CapsLock
U"a" + I0x3 : <result>; # a + ScrollLock
U"a" + I"NumLock" : <result>; # a + NumLock
\end{lstlisting}
Refer to Section~\ref{chpt:LEDIndicatorCodeTable} for the complete list of LED Indicator Codes.
% State Scheduling
\subsubsection{State Scheduling}
Similar to keypresses, indicator codes have four states: activate (\textbf{A}), on (\textbf{On}), deactivate (\textbf{D}) and off (\textbf{Off}).
Also similar to keypresses, on and off cannot be used to trigger a macro.
While activate and deactivate can be used as a trigger to a macro.
The default state for LED Indicator codes is activate.
\begin{lstlisting}
I"NumLock" : <result>;
I"NumLock"(A) : <result>; # Same as above
I"NumLock"(D) : <result>; # NumLock disable
\end{lstlisting}
The on and off states must be specified with another trigger as they are non-trigger conditions.
\begin{lstlisting}
I"NumLock"(On) + U"c" : <result>; # Correct
U"a" + I"NumLock"(Off) : <result>; # Correct
I"NumLock"(Off) : <result>; # Incorrect
I"NumLock"(On), U"d" : <result>; # Incorrect
\end{lstlisting}
Keep in mind that the LED Indicator Codes are controlled by the host OS and not by the keyboard.
There is always the chance that the OS tries to do something strange with the LEDs that may not match what the OS itself is doing (i.e. CapsLock led is off, but all keys are outputing as caps).
In this case there is really nothing the keyboard can do to right itself.
% Layer State
\subsection{Layer State}
\label{subsec:Layer_State}
Layer state may be used as a trigger to a macro.
In most cases using \textbf{Layer} is preferrable as it will trigger using any of: Shift, Latch and Lock.
While using the specific triggers is more restrictive.
\begin{lstlisting}
Layer[1] : <result>; # Layer 1
LayerShift[2] : <result>; # Layer 2 shift
LayerLatch[2] : <result>; # Layer 2 latch
LayerLock[2] : <result>; # Layer 2 lock
\end{lstlisting}
% State Scheduling
\subsubsection{State Scheduling}
Similar to keypresses, layers have four states: activate (\textbf{A}), on (\textbf{On}), deactivate (\textbf{D}) and off (\textbf{Off}).
Also similar to keypresses, on and off cannot be used to trigger a macro.
While activate and deactivate can be used as a trigger to a macro.
The default state for a layer is activate.
\begin{lstlisting}
Layer[1] : <result>;
Layer[1](A) : <result>; # Same as above
Layer[1](D) : <result>; # Layer 1 disable
\end{lstlisting}
As with indicators (Section~\ref{subsec:LED_Indicator_Code}, the on and off states must be specified with another trigger as they are non-trigger conditions.
\begin{lstlisting}
Layer[1](On) + U"c" : <result>; # Correct
U"a" + Layer[1](Off) : <result>; # Correct
Layer[1](Off) : <result>; # Incorrect
Layer[1](On), U"d" : <result>; # Incorrect
\end{lstlisting}
% Animation
\subsection{Animation}
Refer to Section~\ref{sec:Animation_Triggers} on Animation Trigger usage.
% Generic Triggers
\subsection{Generic Triggers}
For custom defined triggers there may not exist KLL syntax yet.
In this case, generic triggers can be used to define the trigger identifier and code directly.
Generally these trigger identifiers shouldn't change; however, don't consider them portable between major firmware versions.
But an effort is made not to change the identifier numbering.
The code is always specified as an 8 bit number.
For codes higher than 255 you'll need to determine the identifier associated with that code.
For example, \textbf{0} is Switch Bank 1 corresponding from 0 to 255 and \textbf{2} is Switch Bank 3 corresponding from 512 to 767.
While it is possible to trigger on the Animation Bank (See Section~\ref{subsubsec:Trigger_Identifiers}) these may be dynamically indexed based on which animations are defined.
So you will almost certainly run into issues using a Generic Trigger.
Generic triggers do not support ranges as seen in Section~\ref{subsection:Range}.
\begin{lstlisting}
S2 : <result>;
T[0,2] : <result>; # Same as S2
S257 : <result>;
T[1,1] : <result>; # Same as S257
I"NumLock" : <result>;
T[4,0] : <result>; # I"NumLock"
Layer[1] : <result>;
T[9,1] : <result>; # Layer[1]
# On host sleep trigger
T[17,0] : <result>;
# 1 minute after host sleep trigger
T[17,1] : <result>;
# After device inactivity
T[19,0] : <result>;
# 2 minutes after device usages stops
T[19,2] : <result>;
# Two rotation triggers, 0 and 1
T[20,0](0) : <resulta1>;
T[20,0](1) : <resulta2>;
T[20,0](2) : <resulta3>;
T[20,1](0) : <resultb1>;
T[20,1](1) : <resultb2>;
# Rotate right rotation 0
<trigger> : rotate(0, 1);
# Rotate left rotation 1
<trigger> : rotate(1, -1);
\end{lstlisting}
% List of Trigger Identifiers
\subsubsection{Trigger Identifiers}
\label{subsubsec:Trigger_Identifiers}
The current list of trigger identifiers and their code ranges.
\begin{ltable}{triggeridentifiers}{ l | r | l }{Table of Trigger Identifiers and Code Ranges}
\textbf{Identifier Value} & \textbf{Name} & \textbf{Code Offset} \\
\hline
\hline
\input{TriggerCodeTable} % See .tex file for data
\end{ltable}
% Range
\subsection{Range}
\label{subsection:Range}
For convenience, it is also possible to define a range of triggers rather than explicitly defining each of the trigger:result pairs.
This is useful for defining things such as using the clicker speaker for every single key or just the letter keys.
Ranges are defined as the numerical range of either USB Codes or Scan Codes (use not recommended).
Fortunately this means ranges such as A-Z will work has USB HID defines the USB Codes in order.
Unfortunately the range 0-9 will not work as the USB Codes are organized: 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 just like on a keyboard.
To assist with this problem, the compiler will warn when this situation occurs.
Forward and reverse ranges are possible.
There is no wrap-around.
Scan Codes and USB Codes cannot be mixed.
To define a range, two additional pieces of syntax are required: square brackets and range specifier.
\begin{lstlisting}
S[0x2A-0x50] : <result>;
S[12-43] : <result>;
S[69] : <result>; # Also a valid definition
U[124-43] : <result>; # Reverse range
U["A"-"Z"] : <result>;
U["0"-"9"] : <result>; # Compiler will warn, only 0 and 9
U["1"-"0"] : <result>; # Correct definition of 0-9
\end{lstlisting}
In addition to a specific range, multiple single keys or ranges may also be specified.
\begin{lstlisting}
S[0x2A-0x50, 0x5] : <result>;
S[12, 43] : <result>;
U["A"-"Z", "Enter"] : <result>;
\end{lstlisting}
When using an analog supporting keyboard, a range is specified to that specific range.
Or the analog trigger can be specified for the entire range.
\begin{lstlisting}
S[0x2A-0x50(20), 0x5(56)] : <result>;
S[12, 43](79) : <result>;
U["A"-"Z"(42),"Tab"](30) : <result>; # 30, unless specified
\end{lstlisting}
% Sequence
\subsection{Sequence}
\label{subsec:Sequence}
Sequences are a type of macro.
A sequence is a set of expected inputs that must happen in order with no extra inputs of non-defined inputs.
If a non-defined input is found, the sequence is reset and waits for the first input in the sequence again.
Sequences cannot mix Scan Codes and USB Codes.
Trigger inputs in the sequence are separated by commas.
The Scan Codes and USB Codes are evaluated/expanded first, then the sequences are evaluated (Codes have higher precedence).
\begin{lstlisting}
S[0x2A-0x50], S[12], U[5] : <result>;
U["Q"-"Y"], U["Enter"] : <result>;
U["A"-"Z"(42),"Tab"](30), U[12](53) : <result>;
\end{lstlisting}
Analog triggers cannot be set across multiple inputs in the sequence.
For convenience, a second sequence syntax is available only for specifying ASCII characters.
This allows for sentences to be inputted rather than the individual USB Codes.
The key difference is the use of single quotes.
If a shift is required for the specific key, it will be added as a combination (see Section~\ref{subsec:Combination}).
\begin{lstlisting}
'abc' : <result>;
U'T' : <result>;
U['Can you type this?'](23) : <result>;
\end{lstlisting}
Single quotes are only used for sentence expansion, they cannot be used for strings.
% Combination
\subsection{Combination}
\label{subsec:Combination}
Combinations are a type of macro.
A combination is a set of inputs pressed at the same time.
For example: Ctrl+Alt+Delete.
In order for a combination trigger to be signalled all of the keys must be pressed.
The combination will not end if a key is missing from the combination (as the user may not have pressed it yet).
Extra keys not part of the combination also do not cancel the combination.
Combinations cannot mix Scan Codes and USB Codes.
Trigger inputs in the combination are separated by pluses.
The Scan Codes and USB Codes are evaluated/expanded first, then sequences are evaluated and finally combinations (Codes have the highest precedence, then sequences, then combinations).
\begin{lstlisting}
U["Q"-"Y"] + U["Enter"] : <result>;
S[0x2A-0x50] + S[12], U[5] : <result>;
U["A"-"Z"(42),"Tab"](30) + U[12](53) : <result>;
'Can you type this?'(23) + 'a'(43) : <result>;
\end{lstlisting}
Analog triggers cannot be set across multiple inputs in the combination.
% Timing
\subsection{Timing}
\label{subsec:trigtiming}
It is possible to assign a time to a given trigger.
This allows for sophisticated time based input sequences.
The granularity of the fundamental time base depends on the hardware.
This time base is advertised by the underlying hardware to the KLL compiler using the \textbf{timeBase} define.
The following are the accepted time units.
\begin{itemize}
\item \textbf{s} - Seconds
\item \textbf{ms} - Milliseconds
\item \textbf{us} - Microseconds
\end{itemize}
Fractional numbers are also valid (e.g. 1.43~s).
If the number will be rounded to the nearest fundamental time unit.
Avoid using the fundamental time unit directly as it will not behave the same way between different keyboards.
The format is as follows.
\begin{lstlisting}
<identifier>([<state scheduler>][:<time>]) : <result>;
\end{lstlisting}
Hold A for at least 300~ms.
\begin{lstlisting}
U"a"(300ms) : <result>;
U"a"(H:300ms) : <result>; # Same
\end{lstlisting}
Hold A for at most 300~ms.
\begin{lstlisting}
U"a"(R:300ms) : <result>;
\end{lstlisting}
More complicated state scheduling is also possible.
Press timers may be used to have combos that require a key pressed first then after a certain amount of time another key must be pressed, which then completes the element in the sequence.
\begin{lstlisting}
U"a" + U"b"(P:1s) : <result>; # Press B after 1s
U"a" + U"b"(H:1s) : <result>; # B must be held for at least 1s
U"a" + U"b"(R:1s) : <result>; # B cannot be held for more than 1s
\end{lstlisting}
Non-trigger events cannot be used with a time specifier.
This includes: \textbf{On}, \textbf{Off} and \textbf{Hold}.
Hold can only be used when using multiple time triggers.
Multiple time triggers may be used to define more complex input sequences.
For example, to press A, require a wait time of 50~ms then hold for at least 100~ms, but no longer than 200~ms.
\begin{lstlisting}
U"a" + U"b"(P:50ms,H:100ms,R:200ms);
\end{lstlisting}
%% Result
\section{Result}
The result is the action, or set of actions, after the conditions for the trigger have been satisfied.
The result can be as simple as a single USB Code output or as complex as signalling a keyboard specific clicker and outputting a combinational macro.
A Scan Code cannot be used as a result.
Like triggers, there are two basic types of results: keyboard specific functionality and USB Codes.
Both of these results are referred to as capabilities.
A basic capability of every keyboard is to send USB Codes, while other keyboards may have other capabilities such FN layers or clickers.
When a trigger is satisfied each of the results assigned to this trigger are signalled.
Much of the syntax is the same as with triggers.
The major difference being, no analog qualifiers and no ranges.
Some state scheduling qualifiers also may not apply in all situations, if at all.
% USB Code
\subsection{USB Code}
USB Codes are the primary use of the result part of the trigger:result pairs.
Result USB Codes are defined the same way as trigger USB Codes (Section~\ref{subsec:USB_Code}).
\begin{lstlisting}
<trigger> : U0x2A;
<trigger> : U124;
<trigger> : U"A";
<trigger> : U"a"; # Same as previous
\end{lstlisting}
Refer to Section~\ref{chpt:USBCodeTable} for the complete list of standard (US ANSI) USB Codes.
For dealing with non-ANSI keyboard locales and layouts please refer to Section~\ref{sec:locales}.
% State Scheduling
\subsubsection{State Scheduling}
\label{subsubsec:resultusbcodestateschedule}
It is also possible to schedule output sequences just as with USB Code triggers (see Section~\ref{subsubsec:trigusbstateschedule}).
Result USB Codes have three scheduling types: press (\textbf{P}), hold (\textbf{H}) and release (\textbf{R}).
Off, unique press and unique release have no meaning for output and therefore are not available.
The hold state can only be used with a timing specifier (see Section~\ref{subsec:resulttiming}).
By default, the press specifier is used and the key is released before the next sequence element and/or the end of the sequence.
\begin{lstlisting}
<trigger> : U"A";
<trigger> : U"A"(P,R); # Same as previous
<trigger> : U"A"(P), U"A"(R);
<trigger> : U"A"(P); # Does not release a
<trigger> : U"A"(R); # Only releases a if active/pressed
\end{lstlisting}
% None
\subsection{None}
Sometimes it is useful to block the fall-through to a previous layer and have the key do nothing.
The \textbf{None} keyword is case sensitive.
\begin{lstlisting}
<trigger> : None;
\end{lstlisting}
% Consumer Control Code
\subsection{Consumer Control Code}
Consumer Control Codes, or Media Keys are a USB HID control type that allows you to control media functions.
These include global hotkeys such as Play, Next and Previous.
Similar to USB Codes (Section~\ref{subsec:USB_Code}), Consumer Control Codes can be defined as numbers or by its symbolic name.
It is important to note that there is no support for sequences, combinations or ranges of Consumer Control Codes.
\begin{lstlisting}
<trigger> : CON0xB0;
<trigger> : CON176;
<trigger> : CON"Play";
<trigger> : CON"play"; # Same as previous
\end{lstlisting}
Refer to Section~\ref{chpt:ConsCodeTable} for the complete list of Consumer Control Codes.
Consumer Control Codes may also use state scheduling. See Section~\ref{subsubsec:resultusbcodestateschedule} for usage details.
% System Control Code
\subsection{System Control Code}
System Control Codes are a USB HID control type that allows you to system level functions.
These include global hotkeys such as Power, Sleep and Eject.
Similar to USB Codes (Section~\ref{subsec:USB_Code}), System Control Codes can be defined as numbers or by its symbolic name.
It is important to note that there is no support for sequences, combinations or ranges of System Control Codes.
\begin{lstlisting}
<trigger> : SYS0x82;
<trigger> : SYS130;
<trigger> : SYS"Sleep";
<trigger> : SYS"sleep"; # Same as previous
\end{lstlisting}
Refer to Section~\ref{chpt:SysCodeTable} for the complete list of System Control Codes.
System Control Codes may also use state scheduling. See Section~\ref{subsubsec:resultusbcodestateschedule} for usage details.
% Sequence
\subsection{Sequence}
A result sequence is a series of outputted USB Codes which are split between each USB output buffer refresh.
This is similar to a trigger input sequence.
The syntax is the same as trigger sequences (Section~\ref{subsec:Sequence}.
\begin{lstlisting}
<trigger> : U["Q"-"Y"], U["Enter"];
<trigger> : U["A"-"Z","Tab"], U[12];
\end{lstlisting}
Single quoted strings will be literally evaluated.
Any characters requiring a Shift key will have it added as a combination as part of the result.
\begin{lstlisting}
<trigger> : 'abc';
<trigger> : U'T';
<trigger> : U['Can you type this?'];
\end{lstlisting}
% Combination
\subsection{Combination}
A result combination is a set of keys sent out during the same USB output buffer.
The syntax is the same as trigger combinations (Section~\ref{subsec:Combination}.
Keep in mind, if the keyboard does not support NKRO then some result combinations will not be possible.
\begin{lstlisting}
<trigger> : U["Q"-"Y"] + U["Enter"];
<trigger> : U["A"-"Z","Tab"] + U[12];
<trigger> : 'Can you type this?' + 'a';
\end{lstlisting}
% Capability
\subsection{Capability}
In addition to outputting USB Codes, capabilities can be triggered.
Technically, outputting USB Codes is a capability of the keyboard, but it is always considered to exist.