Skip to content

Commit 75c716b

Browse files
authored
Add implementation for Mod-Tap and Modifier Keys (#61)
1 parent 9d02bba commit 75c716b

File tree

3 files changed

+213
-6
lines changed

3 files changed

+213
-6
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ The following are supported.
2222
* [Layers](https://get.vial.today/manual/layers.html) (MO(x), TO(x))
2323
* Matrix testers
2424
* [Macros](https://get.vial.today/manual/macros.html)
25+
* [Mod-Tap](https://docs.qmk.fm/mod_tap)
26+
* [Modifier Keys](https://docs.qmk.fm/feature_advanced_keycodes#modifier-keys)
2527
* [Combos](https://get.vial.today/manual/combos.html)
2628

2729
## Microcontrollers

keyboard.go

Lines changed: 187 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ type Device struct {
4040
combosKey uint32
4141
combosFounds []Keycode
4242

43+
tapOrHold map[uint32]time.Time
44+
4345
pressToReleaseBuf []uint32
4446
noneToPressBuf []uint32
4547
}
@@ -87,6 +89,8 @@ func New() *Device {
8789
combosKey: 0xFFFFFFFF,
8890
combosFounds: make([]Keycode, 10),
8991

92+
tapOrHold: map[uint32]time.Time{},
93+
9094
pressToReleaseBuf: make([]uint32, 0, 20),
9195
noneToPressBuf: make([]uint32, 0, 20),
9296
}
@@ -344,6 +348,104 @@ func (d *Device) Tick() error {
344348
}
345349
}
346350

351+
for _, xx := range noneToPress {
352+
kbidx, layer, index := decKey(xx)
353+
x := d.kb[kbidx].Key(layer, index)
354+
switch x & keycodes.QuantumMask {
355+
case keycodes.TypeLxxxT, keycodes.TypeRxxxT:
356+
d.tapOrHold[xx] = time.Now().Add(200 * time.Millisecond)
357+
}
358+
}
359+
360+
for xx, tt := range d.tapOrHold {
361+
if tt.IsZero() {
362+
// hold release
363+
for _, yy := range pressToRelease {
364+
if xx == yy {
365+
kbidx, layer, index := decKey(xx)
366+
x := d.kb[kbidx].Key(layer, index)
367+
switch x & keycodes.QuantumMask {
368+
case keycodes.TypeLxxxT:
369+
if x&keycodes.TypeXCtl > 0 {
370+
pressToRelease = append(pressToRelease, uint32(0xFF000000)|uint32(keycodes.KeyLeftCtrl))
371+
}
372+
if x&keycodes.TypeXSft > 0 {
373+
pressToRelease = append(pressToRelease, uint32(0xFF000000)|uint32(keycodes.KeyLeftShift))
374+
}
375+
if x&keycodes.TypeXAlt > 0 {
376+
pressToRelease = append(pressToRelease, uint32(0xFF000000)|uint32(keycodes.KeyLeftAlt))
377+
}
378+
if x&keycodes.TypeXGui > 0 {
379+
pressToRelease = append(pressToRelease, uint32(0xFF000000)|uint32(keycodes.KeyWindows))
380+
}
381+
case keycodes.TypeRxxxT:
382+
if x&keycodes.TypeXCtl > 0 {
383+
pressToRelease = append(pressToRelease, uint32(0xFF000000)|uint32(keycodes.KeyRightCtrl))
384+
}
385+
if x&keycodes.TypeXSft > 0 {
386+
pressToRelease = append(pressToRelease, uint32(0xFF000000)|uint32(keycodes.KeyRightShift))
387+
}
388+
if x&keycodes.TypeXAlt > 0 {
389+
pressToRelease = append(pressToRelease, uint32(0xFF000000)|uint32(keycodes.KeyLeftAlt))
390+
}
391+
if x&keycodes.TypeXGui > 0 {
392+
pressToRelease = append(pressToRelease, uint32(0xFF000000)|uint32(keycodes.KeyWindows))
393+
}
394+
}
395+
delete(d.tapOrHold, xx)
396+
}
397+
}
398+
} else if time.Now().Before(tt) {
399+
// tap
400+
for _, yy := range pressToRelease {
401+
if xx == yy {
402+
kbidx, layer, index := decKey(xx)
403+
x := d.kb[kbidx].Key(layer, index)
404+
switch x & keycodes.QuantumMask {
405+
case keycodes.TypeLxxxT, keycodes.TypeRxxxT:
406+
kc := uint32(0xFF000000) | uint32(keycodeViaToTGK(x&0x00FF))
407+
noneToPress = append(noneToPress, kc)
408+
pressToRelease = append(pressToRelease, kc)
409+
}
410+
delete(d.tapOrHold, xx)
411+
}
412+
}
413+
} else {
414+
// hold
415+
kbidx, layer, index := decKey(xx)
416+
x := d.kb[kbidx].Key(layer, index)
417+
switch x & keycodes.QuantumMask {
418+
case keycodes.TypeLxxxT:
419+
if x&keycodes.TypeXCtl > 0 {
420+
noneToPress = append(noneToPress, uint32(0xFF000000)|uint32(keycodes.KeyLeftCtrl))
421+
}
422+
if x&keycodes.TypeXSft > 0 {
423+
noneToPress = append(noneToPress, uint32(0xFF000000)|uint32(keycodes.KeyLeftShift))
424+
}
425+
if x&keycodes.TypeXAlt > 0 {
426+
noneToPress = append(noneToPress, uint32(0xFF000000)|uint32(keycodes.KeyLeftAlt))
427+
}
428+
if x&keycodes.TypeXGui > 0 {
429+
noneToPress = append(noneToPress, uint32(0xFF000000)|uint32(keycodes.KeyWindows))
430+
}
431+
case keycodes.TypeRxxxT:
432+
if x&keycodes.TypeXCtl > 0 {
433+
noneToPress = append(noneToPress, uint32(0xFF000000)|uint32(keycodes.KeyRightCtrl))
434+
}
435+
if x&keycodes.TypeXSft > 0 {
436+
noneToPress = append(noneToPress, uint32(0xFF000000)|uint32(keycodes.KeyRightShift))
437+
}
438+
if x&keycodes.TypeXAlt > 0 {
439+
noneToPress = append(noneToPress, uint32(0xFF000000)|uint32(keycodes.KeyLeftAlt))
440+
}
441+
if x&keycodes.TypeXGui > 0 {
442+
noneToPress = append(noneToPress, uint32(0xFF000000)|uint32(keycodes.KeyWindows))
443+
}
444+
}
445+
d.tapOrHold[xx] = time.Time{}
446+
}
447+
}
448+
347449
for _, xx := range noneToPress {
348450
kbidx, layer, index := decKey(xx)
349451
var x Keycode
@@ -362,6 +464,36 @@ func (d *Device) Tick() error {
362464
} else {
363465
d.layerStack = append(d.layerStack, d.layer)
364466
}
467+
} else if x&keycodes.QuantumMask == keycodes.TypeLxxx && x&keycodes.QuantumTypeMask != 0 {
468+
// TypeLxxx
469+
if x&keycodes.TypeXCtl > 0 {
470+
d.Keyboard.Down(keycodes.KeyLeftCtrl)
471+
}
472+
if x&keycodes.TypeXSft > 0 {
473+
d.Keyboard.Down(keycodes.KeyLeftShift)
474+
}
475+
if x&keycodes.TypeXAlt > 0 {
476+
d.Keyboard.Down(keycodes.KeyLeftAlt)
477+
}
478+
if x&keycodes.TypeXGui > 0 {
479+
d.Keyboard.Down(keycodes.KeyWindows)
480+
}
481+
d.Keyboard.Down(k.Keycode(x&0x00FF | keycodes.TypeNormal))
482+
} else if x&keycodes.QuantumMask == keycodes.TypeRxxx && x&keycodes.QuantumTypeMask != 0 {
483+
// TypeRxxx
484+
if x&keycodes.TypeXCtl > 0 {
485+
d.Keyboard.Down(keycodes.KeyRightCtrl)
486+
}
487+
if x&keycodes.TypeXSft > 0 {
488+
d.Keyboard.Down(keycodes.KeyRightShift)
489+
}
490+
if x&keycodes.TypeXAlt > 0 {
491+
d.Keyboard.Down(keycodes.KeyLeftAlt)
492+
}
493+
if x&keycodes.TypeXGui > 0 {
494+
d.Keyboard.Down(keycodes.KeyWindows)
495+
}
496+
d.Keyboard.Down(k.Keycode(x&0x00FF | keycodes.TypeNormal))
365497
} else if x == keycodes.KeyRestoreDefaultKeymap {
366498
// restore default keymap for QMK
367499
machine.Flash.EraseBlocks(0, 1)
@@ -438,6 +570,36 @@ func (d *Device) Tick() error {
438570
d.layer = d.layerStack[len(d.layerStack)-1]
439571
}
440572
}
573+
} else if x&keycodes.QuantumMask == keycodes.TypeLxxx && x&keycodes.QuantumTypeMask != 0 {
574+
// TypeLxxx
575+
if x&keycodes.TypeXCtl > 0 {
576+
d.Keyboard.Up(keycodes.KeyLeftCtrl)
577+
}
578+
if x&keycodes.TypeXSft > 0 {
579+
d.Keyboard.Up(keycodes.KeyLeftShift)
580+
}
581+
if x&keycodes.TypeXAlt > 0 {
582+
d.Keyboard.Up(keycodes.KeyLeftAlt)
583+
}
584+
if x&keycodes.TypeXGui > 0 {
585+
d.Keyboard.Up(keycodes.KeyWindows)
586+
}
587+
d.Keyboard.Up(k.Keycode(x&0x00FF | keycodes.TypeNormal))
588+
} else if x&keycodes.QuantumMask == keycodes.TypeRxxx && x&keycodes.QuantumTypeMask != 0 {
589+
// TypeRxxx
590+
if x&keycodes.TypeXCtl > 0 {
591+
d.Keyboard.Up(keycodes.KeyRightCtrl)
592+
}
593+
if x&keycodes.TypeXSft > 0 {
594+
d.Keyboard.Up(keycodes.KeyRightShift)
595+
}
596+
if x&keycodes.TypeXAlt > 0 {
597+
d.Keyboard.Up(keycodes.KeyLeftAlt)
598+
}
599+
if x&keycodes.TypeXGui > 0 {
600+
d.Keyboard.Up(keycodes.KeyWindows)
601+
}
602+
d.Keyboard.Up(k.Keycode(x&0x00FF | keycodes.TypeNormal))
441603
} else if x&0xF000 == 0xD000 {
442604
switch x & 0x00FF {
443605
case 0x01, 0x02, 0x04, 0x08, 0x10:
@@ -613,10 +775,20 @@ func (d *Device) KeyVia(layer, kbIndex, index int) Keycode {
613775
// restore default keymap for QMK
614776
kc = keycodes.KeyRestoreDefaultKeymap
615777
default:
616-
if kc&0xFF00 == keycodes.TypeMacroKey {
778+
switch kc & keycodes.QuantumMask {
779+
case keycodes.TypeRxxx, keycodes.TypeLxxxT, keycodes.TypeRxxxT:
617780
// skip
618-
} else {
619-
kc = kc & 0x0FFF
781+
default:
782+
if kc&keycodes.QuantumMask == 0 && kc&keycodes.QuantumTypeMask != 0 {
783+
// skip (keycodes.TpeLxxx)
784+
} else {
785+
switch kc & keycodes.ModKeyMask {
786+
case keycodes.TypeMacroKey:
787+
// skip
788+
default:
789+
kc = kc & 0x0FFF
790+
}
791+
}
620792
}
621793
}
622794
return kc
@@ -680,8 +852,19 @@ func keycodeViaToTGK(key Keycode) Keycode {
680852
case keycodes.KeyRestoreDefaultKeymap:
681853
kc = keycodes.KeyRestoreDefaultKeymap
682854
default:
683-
if key&0xFF00 == keycodes.TypeMacroKey {
855+
switch key & keycodes.QuantumMask {
856+
case keycodes.TypeRxxx, keycodes.TypeLxxxT, keycodes.TypeRxxxT:
684857
kc = key
858+
default:
859+
if key&keycodes.QuantumMask == 0 && key&keycodes.QuantumTypeMask != 0 {
860+
// keycodes.TpeLxxx
861+
kc = key
862+
} else {
863+
switch key & 0xFF00 {
864+
case keycodes.TypeMacroKey:
865+
kc = key
866+
}
867+
}
685868
}
686869
}
687870
return kc

keycodes/keycodes.go

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ import (
55
)
66

77
const (
8-
ModKeyMask = 0xFF00
9-
ToKeyMask = 0x0010
8+
ModKeyMask = 0xFF00
9+
QuantumMask = 0xF000
10+
QuantumTypeMask = 0x0F00
11+
ToKeyMask = 0x0010
1012
)
1113

1214
const (
@@ -16,6 +18,26 @@ const (
1618
TypeModKey = 0xFF00
1719
TypeToKey = 0xFF10
1820
TypeMacroKey = 0x7700
21+
TypeLxxx = 0x0000
22+
TypeRxxx = 0x1000
23+
TypeLxxxT = 0x2000
24+
TypeRxxxT = 0x3000
25+
)
26+
27+
const (
28+
TypeXCtl = 0x0100
29+
TypeXSft = 0x0200
30+
TypeXAlt = 0x0400
31+
TypeXGui = 0x0800
32+
33+
TypeLCtlT = TypeLxxxT | TypeXCtl
34+
TypeLSftT = TypeLxxxT | TypeXSft
35+
TypeLAltT = TypeLxxxT | TypeXAlt
36+
TypeLGuiT = TypeLxxxT | TypeXGui
37+
TypeRCtlT = TypeRxxxT | TypeXCtl
38+
TypeRSftT = TypeRxxxT | TypeXSft
39+
TypeRAltT = TypeRxxxT | TypeXAlt
40+
TypeRGuiT = TypeRxxxT | TypeXGui
1941
)
2042

2143
const (

0 commit comments

Comments
 (0)