Skip to content

Commit a5203da

Browse files
committed
Adding keyBlock capability to support Programmmer's Dvorak
- Useful for partial redefinitions of keys Such as redefining Shift, which, as per the USB spec is handled by the OS This means we have to careful select which USB Codes to send to the OS to simulate Shift not being pressed (while it is) - KLL capabilities only work with numerical arguments (KLL 0.3d) - Each key must be explicitly block for each combination (e.g. LShift and RShift are handled separately) - Adding example configuration for the Infinity 60% - Adding example configuration for the Infinity Ergodox - Requires kll.git 1a078b2 or higher
1 parent 253d96a commit a5203da

File tree

4 files changed

+245
-2
lines changed

4 files changed

+245
-2
lines changed
+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#!/usr/bin/env bash
2+
# This script shows how to use a complex multi-file layout such as Programmer's Dvorak
3+
# Jacob Alexander 2015-2016
4+
5+
6+
7+
#################
8+
# Configuration #
9+
#################
10+
11+
######## Left Side ########
12+
13+
# Feel free to change the variables in this section to configure your keyboard
14+
15+
BuildPath="ICED-L"
16+
17+
## KLL Configuration ##
18+
19+
# Generally shouldn't be changed, this will affect every layer
20+
BaseMap="scancode_map leftHand slave1 rightHand"
21+
22+
# This is the default layer of the keyboard
23+
# NOTE: To combine kll files into a single layout, separate them by spaces
24+
# e.g. DefaultMap="mylayout mylayoutmod"
25+
DefaultMap="programmers_dvorak_default lcdFuncMap"
26+
27+
# This is where you set the additional layers
28+
# NOTE: Indexing starts at 1
29+
# NOTE: Each new layer is another array entry
30+
# e.g. PartialMaps[1]="layer1 layer1mod"
31+
# PartialMaps[2]="layer2"
32+
# PartialMaps[3]="layer3"
33+
PartialMaps[1]="programmers_dvorak_shift"
34+
35+
36+
37+
##########################
38+
# Advanced Configuration #
39+
##########################
40+
41+
# Don't change the variables in this section unless you know what you're doing
42+
# These are useful for completely custom keyboards
43+
# NOTE: Changing any of these variables will require a force build to compile correctly
44+
45+
# Keyboard Module Configuration
46+
ScanModule="Infinity_Ergodox"
47+
MacroModule="PartialMap"
48+
OutputModule="pjrcUSB"
49+
DebugModule="full"
50+
51+
# Microcontroller
52+
Chip="mk20dx256vlh7"
53+
54+
# Compiler Selection
55+
Compiler="gcc"
56+
57+
58+
59+
########################
60+
# Bash Library Include #
61+
########################
62+
63+
# Shouldn't need to touch this section
64+
65+
# Check if the library can be found
66+
if [ ! -f cmake.bash ]; then
67+
echo "ERROR: Cannot find 'cmake.bash'"
68+
exit 1
69+
fi
70+
71+
# Load the library
72+
source cmake.bash
73+
74+
75+
76+
#########################
77+
# Re-run for right side #
78+
#########################
79+
80+
######## Right Side ########
81+
82+
# Feel free to change the variables in this section to configure your keyboard
83+
84+
BuildPath="ICED-R"
85+
86+
## KLL Configuration ##
87+
88+
# Only changing the basemap (everything else is the same)
89+
# Generally shouldn't be changed, this will affect every layer
90+
BaseMap="defaultMap rightHand slave1 leftHand"
91+
92+
# Load the library (starts the build)
93+
source cmake.bash
94+
95+
+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#!/usr/bin/env bash
2+
# This script shows how to use a complex multi-file layout such as Programmer's Dvorak
3+
# Jacob Alexander 2016
4+
5+
6+
7+
#################
8+
# Configuration #
9+
#################
10+
11+
# Feel free to change the variables in this section to configure your keyboard
12+
13+
BuildPath="IC60"
14+
15+
## KLL Configuration ##
16+
17+
# Generally shouldn't be changed, this will affect every layer
18+
BaseMap="scancode_map"
19+
20+
# This is the default layer of the keyboard
21+
# NOTE: To combine kll files into a single layout, separate them by spaces
22+
# e.g. DefaultMap="mylayout mylayoutmod"
23+
DefaultMap="programmers_dvorak_default stdFuncMap"
24+
25+
# This is where you set the additional layers
26+
# NOTE: Indexing starts at 1
27+
# NOTE: Each new layer is another array entry
28+
# e.g. PartialMaps[1]="layer1 layer1mod"
29+
# PartialMaps[2]="layer2"
30+
# PartialMaps[3]="layer3"
31+
PartialMaps[1]="programmers_dvorak_shift"
32+
33+
34+
35+
##########################
36+
# Advanced Configuration #
37+
##########################
38+
39+
# Don't change the variables in this section unless you know what you're doing
40+
# These are useful for completely custom keyboards
41+
# NOTE: Changing any of these variables will require a force build to compile correctly
42+
43+
# Keyboard Module Configuration
44+
ScanModule="Infinity_60%"
45+
MacroModule="PartialMap"
46+
OutputModule="pjrcUSB"
47+
DebugModule="full"
48+
49+
# Microcontroller
50+
Chip="mk20dx128vlf5"
51+
52+
# Compiler Selection
53+
Compiler="gcc"
54+
55+
56+
57+
########################
58+
# Bash Library Include #
59+
########################
60+
61+
# Shouldn't need to touch this section
62+
63+
# Check if the library can be found
64+
if [ ! -f cmake.bash ]; then
65+
echo "ERROR: Cannot find 'cmake.bash'"
66+
exit 1
67+
fi
68+
69+
# Load the library
70+
source cmake.bash
71+

Macro/PartialMap/capabilities.kll

+19-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
Name = PartialMapCapabilities;
2-
Version = 0.3;
2+
Version = 0.4;
33
Author = "HaaTa (Jacob Alexander) 2014-2016";
44
KLL = 0.3d;
55

66
# Modified Date
7-
Date = 2016-04-08;
7+
Date = 2016-08-06;
88

99

1010
# Capabilties available to the PartialMap module
@@ -25,3 +25,20 @@ stateWordSize = 8; # Default for now, increase to 16 or 32 for higher limits
2525
indexWordSize => IndexWordSize_define;
2626
indexWordSize = 16; # Default for now, increase to 32 for higher limits (8 for less resource usage)
2727

28+
# Block Key Capability
29+
# Add this capability as a combo to any key you want to explicitly block another
30+
# For example:
31+
# To turn Shift+1 into q
32+
# U"Shift" + U"1" : U"Q" + blockKey( 0xE1 ) + blockKey( 0x1E );
33+
#
34+
# 0xE1 - Left Shift (0xE5 is Right Shift)
35+
# 0x1E - 1
36+
#
37+
# NOTE: KLL is limited to using numbers for key blocking instead of the symbolic names
38+
# A future version of KLL will address this
39+
blockKey => Macro_blockUSBKey_capability( usbCode : 1 );
40+
41+
# This defines the maximum number of keys that can be blocked in a single processing loop
42+
maxBlockCount => Macro_maxBlockCount_define;
43+
maxBlockCount = 4;
44+

Macro/PartialMap/macro.c

+60
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,10 @@ TriggerGuide macroInterconnectCache[ MaxScanCode ];
131131
uint8_t macroInterconnectCacheSize = 0;
132132
#endif
133133

134+
// Key blocking buffer
135+
uint8_t macroHidBlockList[ Macro_maxBlockCount_define ];
136+
uint8_t macroHidBlockListSize;
137+
134138

135139

136140
// ----- Capabilities -----
@@ -370,6 +374,39 @@ void Macro_layerRotate_capability( uint8_t state, uint8_t stateType, uint8_t *ar
370374
}
371375

372376

377+
// Block USB Key
378+
// During the next processing cycle, queue up a key to be ignored
379+
// e.g. If Shift is assigned to both Shift and Layer 1
380+
// Then if the 1 key on Layer 1 is assigned 2
381+
// Block the Shift key so a USB 2 can be sent via the Output channel
382+
// This works by having a queue of keys to "unset" if they are triggered during the next processing loop
383+
void Macro_blockUSBKey_capability( uint8_t state, uint8_t stateType, uint8_t *args )
384+
{
385+
// Display capability name
386+
if ( stateType == 0xFF && state == 0xFF )
387+
{
388+
print("Macro_blockUSBKey(usbCode)");
389+
return;
390+
}
391+
392+
// Get usb key from arguments
393+
// Access argument directly as it's already uint8_t
394+
uint8_t usbCode = args[0];
395+
396+
// Add to the hid block list
397+
if ( macroHidBlockListSize < Macro_maxBlockCount_define )
398+
{
399+
macroHidBlockList[ macroHidBlockListSize++ ] = usbCode;
400+
}
401+
else
402+
{
403+
warn_print("USB Key Block buffer is full!: ");
404+
printHex( usbCode );
405+
print( NL );
406+
}
407+
}
408+
409+
373410

374411
// ----- Functions -----
375412

@@ -681,6 +718,26 @@ void Macro_appendResultMacroToPendingList( const TriggerMacro *triggerMacro )
681718
}
682719

683720

721+
// Block any of the keys that may be in the buffer
722+
// These keys may not be pressed during the processing loop, but block them anyways
723+
// See Macro_blockUSBKey_capability for more details on usage
724+
inline void Macro_processKeyBlocking()
725+
{
726+
// Iterate over list of USB keys
727+
for ( uint8_t key = 0; key < Macro_maxBlockCount_define; key++ )
728+
{
729+
// This capability will always unset (doesn't toggle)
730+
731+
// First we need to generate the argument
732+
uint8_t args[] = { macroHidBlockList[ key ] };
733+
734+
// XXX Only handles normal keys (no analog, yet)
735+
// 0x03 is release, which always unsets a key from the USB buffer, even if it's not there
736+
Output_usbCodeSend_capability( 0x03, 0x00, args );
737+
}
738+
}
739+
740+
684741
// Macro Procesing Loop
685742
// Called once per USB buffer send
686743
inline void Macro_process()
@@ -758,6 +815,9 @@ inline void Macro_process()
758815
// Process result macros
759816
Result_process();
760817

818+
// Process Key Blocking
819+
Macro_processKeyBlocking();
820+
761821
// Signal buffer that we've used it
762822
Scan_finishedWithMacro( macroTriggerListBufferSize );
763823

0 commit comments

Comments
 (0)