Skip to content

Commit d2398c4

Browse files
committed
use Fn+Ctrl to toggle arrow keys layer
1 parent 18244c6 commit d2398c4

File tree

2 files changed

+103
-33
lines changed

2 files changed

+103
-33
lines changed

action_code.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,20 @@
478478
ACT_FUNCTION = 0b1111
479479

480480

481+
OP_BIT_AND = 0
482+
OP_BIT_OR = 1
483+
OP_BIT_XOR = 2
484+
OP_BIT_SET = 3
485+
486+
ON_PRESS = 1
487+
ON_RELEASE = 2
488+
ON_BOTH = 3
489+
490+
491+
OP_TAP_TOGGLE = 0xF0
492+
493+
494+
481495
# convert keyname to action code
482496
def get_action_code(x):
483497
if type(x) is int:
@@ -501,7 +515,14 @@ def MODS(*args):
501515
MODS_KEY = lambda mods, key: ACTION(ACT_MODS, (mods << 8) | get_action_code(key))
502516
MODS_TAP = lambda mods, key: ACTION(ACT_MODS_TAP, (mods << 8) | get_action_code(key))
503517
MOUSEKEY = lambda key: ACTION(ACT_MOUSEKEY, key)
518+
519+
LAYER_BITOP = lambda op, part, bits, on: ACTION(ACT_LAYER, op<<10|on<<8|part<<5|(bits&0x1f))
520+
LAYER_BIT_XOR = lambda part, bits, on: LAYER_BITOP(OP_BIT_XOR, part, bits, on)
521+
LAYER_INVERT = lambda layer, on: LAYER_BIT_XOR(layer/4, 1<<(layer%4), on)
522+
LAYER_TOGGLE = lambda layer: LAYER_INVERT(layer, ON_RELEASE)
523+
504524
LAYER_TAP = lambda layer, key=NO: ACTION(ACT_LAYER_TAP, (layer << 8) | get_action_code(key))
525+
LAYER_TAP_TOGGLE = lambda layer: LAYER_TAP(layer, OP_TAP_TOGGLE)
505526
LAYER_MODS = lambda layer, mods: LAYER_TAP(layer, 0xC0 | mods)
506527

507528
COMMAND = lambda id, opt: ACTION(ACT_COMMAND, opt << 8 | id)

keyboard.py

Lines changed: 82 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,12 @@
1515

1616

1717
___ = TRANSPARENT
18+
BOOT = BOOTLOADER
1819
L1 = LAYER_TAP(1)
1920
L2 = LAYER_TAP(2)
2021
L2D = LAYER_TAP(2, D)
22+
L3 = LAYER_TAP(3)
23+
T3 = LAYER_TAP_TOGGLE(3)
2124

2225

2326
KEYMAP = (
@@ -35,7 +38,7 @@
3538
'`', F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, DEL,
3639
___, ___, UP, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___,
3740
___,LEFT,DOWN,RIGHT,___, ___, ___, ___, ___, ___, ___, ___, ___,
38-
___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___,
41+
___, ___, ___, ___, ___,BOOT, ___, ___, ___, ___, ___, ___,
3942
___, ___, ___, ___, ___, ___, ___, ___
4043
),
4144

@@ -47,20 +50,29 @@
4750
___, ___, ___, ___, ___, ___,PGDN, ___, ___, ___, ___, ___,
4851
___, ___, ___, ___, ___, ___, ___, ___
4952
),
53+
54+
# layer 3
55+
(
56+
___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___,
57+
___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___,
58+
___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___,
59+
___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, UP,
60+
___, ___, ___, ___, ___,LEFT,DOWN,RIGHT
61+
),
5062
)
5163

5264

5365
ROWS = (P27, P13, P30, P20, P3)
5466
COLS = (P26, P31, P29, P28, P5, P4, P24, P25, P23, P22, P14, P15, P16, P17)
5567

5668

57-
COORDS = bytearray((
69+
COORDS = (
5870
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
5971
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
6072
28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 0, 40,
6173
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 52, 0,
6274
53, 55, 54, 0, 0, 56, 0, 0, 57, 58, 59, 60, 0, 0
63-
))
75+
)
6476

6577

6678
def reset_into_bootloader():
@@ -128,11 +140,14 @@ def setup(self):
128140
self.pair_keys_code = tuple(
129141
map(lambda x: get_action_code(x), self.pair_keys.keys()))
130142

131-
def get_coord(x): return self.coords[self.keymap[0].index(x)]
143+
def get_coord(x): return self.coords.index(self.keymap[0].index(x))
132144

133145
def get_mask(x):
134146
keys = self.pair_keys[x]
135-
return 1 << get_coord(keys[0]) | 1 << get_coord(keys[1])
147+
mask = 0
148+
for key in keys:
149+
mask |= 1 << get_coord(key)
150+
return mask
136151

137152
self.pair_keys_mask = tuple(map(get_mask, self.pair_keys))
138153
# print([hex(x) for x in self.pair_keys_mask])
@@ -188,13 +203,19 @@ def wait(self, n_events=1, end_time=None):
188203
if n >= n_events or (end_time and self.scan_time > end_time):
189204
return n
190205

206+
def wait_for_mask(self, mask, end_time=None):
207+
while True:
208+
n = self.scan()
209+
if mask == self.pressed_mask or (self.pressed_mask & mask != self.pressed_mask) or (end_time and self.scan_time > end_time):
210+
return n
211+
191212
def action_code(self, position):
192213
position = self.coords[position]
193214

194215
for layer in range(len(self.actonmap) - 1, -1, -1):
195216
if (self.layers >> layer) & 1:
196217
code = self.actonmap[layer][position]
197-
if code == TRANSPARENT:
218+
if code == get_action_code(TRANSPARENT):
198219
continue
199220
return code
200221
return 0
@@ -242,39 +263,53 @@ def release(code):
242263
if n_events == 1 and self.pressed_count == 1:
243264
for mask in self.pair_keys_mask:
244265
if self.pressed_mask & mask == self.pressed_mask:
245-
n_events = self.wait(2, self.scan_time + 25000000)
266+
n_events = self.wait_for_mask(mask, self.scan_time + 30000000)
246267
break
247268

248-
if n_events >= 2:
249-
mask = 1 << self.queue.preview(0) | 1 << self.queue.preview(1)
269+
if n_events >= 2 and n_events == self.pressed_count:
270+
mask = 0
271+
for i in range(n_events):
272+
mask |= 1 << self.queue.preview(i)
250273
if mask in self.pair_keys_mask:
251274
pair_keys_index = self.pair_keys_mask.index(mask)
252275
action_code = self.pair_keys_code[pair_keys_index]
253-
key1 = self.queue.get()
254-
key2 = self.queue.get()
255-
dt = self.pressed_time[key2] - self.pressed_time[key1]
256-
print('pair keys {} ({}, {}), dt = {}'.format(
276+
keys = []
277+
for _ in range(n_events):
278+
key = self.queue.get()
279+
self.keys[key] = 0
280+
keys.append(key)
281+
282+
dt = self.pressed_time[keys[-1]] - self.pressed_time[keys[0]]
283+
print('pair keys {} {}, dt = {}'.format(
257284
pair_keys_index,
258-
key1,
259-
key2,
285+
keys,
260286
dt // 1000000))
261-
262-
# only one action
263-
self.keys[key1] = action_code
264-
self.keys[key2] = 0
287+
288+
self.keys[keys[0]] = action_code
265289

266290
if action_code < 2:
267291
pass
268292
elif action_code < 0xFF:
269293
press(action_code)
270294
else:
271295
kind = action_code >> 12
272-
layer = ((action_code >> 8) & 0xF)
273-
if kind < (ACT_MODS_TAP + 1):
274-
# todo
275-
mods = (action_code >> 8) & 0x1F
276-
elif kind == ACT_LAYER_TAP:
277-
self.layers |= 1 << layer
296+
if kind == ACT_LAYER_TAP:
297+
layer = ((action_code >> 8) & 0xF)
298+
mask = 1 << layer
299+
keycode = action_code & 0xFF
300+
print((keycode, OP_TAP_TOGGLE))
301+
if keycode != OP_TAP_TOGGLE:
302+
n_events = self.wait(1, self.pressed_time[key] + 500000000)
303+
if n_events > 0 and self.queue.preview() == (key | 0x80):
304+
print('press & release quickly')
305+
self.keys[key] = keycode
306+
press(keycode)
307+
else:
308+
self.layers |= mask
309+
else:
310+
print('toggle {}'.format(self.layers))
311+
self.layers = (self.layers & ~mask) | (mask & ~self.layers)
312+
278313
print('layers {}'.format(self.layers))
279314

280315
while len(self.queue):
@@ -290,9 +325,22 @@ def release(code):
290325
press(action_code)
291326
else:
292327
kind = action_code >> 12
293-
layer = ((action_code >> 8) & 0xF)
294328
if kind == ACT_LAYER_TAP:
295-
self.layers |= 1 << layer
329+
layer = ((action_code >> 8) & 0xF)
330+
mask = 1 << layer
331+
keycode = action_code & 0xFF
332+
if keycode != OP_TAP_TOGGLE:
333+
n_events = self.wait(1, self.pressed_time[key] + 500000000)
334+
if n_events > 0 and self.queue.preview() == (key | 0x80):
335+
print('press & release quickly')
336+
self.keys[key] = keycode
337+
press(keycode)
338+
else:
339+
self.layers |= mask
340+
else:
341+
print('toggle {}'.format(self.layers))
342+
self.layers = (self.layers & ~mask) | (mask & ~self.layers)
343+
296344
print('layers {}'.format(self.layers))
297345
elif action_code == BOOTLOADER:
298346
reset_into_bootloader()
@@ -306,13 +354,14 @@ def release(code):
306354
release(action_code)
307355
else:
308356
kind = action_code >> 12
309-
layer = ((action_code >> 8) & 0xF)
310357
if kind == ACT_LAYER_TAP:
311-
self.layers &= ~(1 << layer)
312-
print('layers {}'.format(self.layers))
358+
layer = ((action_code >> 8) & 0xF)
313359
keycode = action_code & 0xFF
314-
if dt < 500 and keycode:
315-
send(keycode)
360+
if keycode != OP_TAP_TOGGLE:
361+
self.layers &= ~(1 << layer)
362+
print('layers {}'.format(self.layers))
363+
# if dt < 500 and keycode:
364+
# send(keycode)
316365

317366
if not ble.connected and not ble.advertising:
318367
ble.start_advertising(advertisement)
@@ -323,7 +372,7 @@ def release(code):
323372

324373
def main():
325374
kbd = Keyboard()
326-
kbd.pair_keys = {L2: (S, D), L1: (J, K)}
375+
kbd.pair_keys = {T3: (L1, RCTRL)}
327376
kbd.run()
328377

329378

0 commit comments

Comments
 (0)