Skip to content

Commit a6c7cd0

Browse files
committed
simplify
1 parent 55f845a commit a6c7cd0

File tree

1 file changed

+94
-93
lines changed

1 file changed

+94
-93
lines changed

keyboard.py

Lines changed: 94 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -32,61 +32,60 @@
3232
(
3333
'`', F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, DEL,
3434
___, ___, UP, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___,
35-
___,LEFT,DOWN,RIGHT,___, ___, ___, ___, ___, ___, ___, ___, ___,
35+
___, LEFT, DOWN, RIGHT, ___, ___, ___, ___, ___, ___, ___, ___, ___,
3636
___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___,
3737
___, ___, ___, ___, ___, ___, ___, ___
3838
),
39-
39+
4040
# layer 2
4141
(
4242
'`', F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, DEL,
4343
___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___,
44-
___, ___, ___, ___, ___, ___,LEFT, UP,DOWN,RIGHT, ___, ___, ___,
44+
___, ___, ___, ___, ___, ___, LEFT, UP, DOWN, RIGHT, ___, ___, ___,
4545
___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___,
4646
___, ___, ___, ___, ___, ___, ___, ___
4747
),
4848
)
4949

5050

51-
5251
ROWS = (P27, P13, P30, P20, P3)
5352
COLS = (P26, P31, P29, P28, P5, P4, P24, P25, P23, P22, P14, P15, P16, P17)
5453

5554

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

6463

6564
class Queue:
6665
def __init__(self, size):
6766
self.size = size
6867
self.queue = bytearray(size)
69-
68+
7069
self.head = 0
7170
self.tail = 0
72-
71+
7372
def put(self, data):
7473
self.queue[self.head] = data
7574
self.head += 1
7675
if self.head >= self.size:
7776
self.head = 0
78-
77+
7978
def get(self):
8079
data = self.queue[self.tail]
8180
self.tail += 1
8281
if self.tail >= self.size:
8382
self.tail = 0
84-
83+
8584
return data
86-
85+
8786
def preview(self, n=0):
8887
return self.queue[(self.tail + n) % self.size]
89-
88+
9089
def __len__(self):
9190
length = self.head - self.tail
9291
return length if length >= 0 else length + self.size
@@ -99,39 +98,42 @@ def __init__(self, keymap=KEYMAP, rows=ROWS, cols=COLS, coords=COORDS, row2col=T
9998
self.cols = cols
10099
self.coords = coords
101100
self.row2col = row2col
102-
self.pressed_keys = []
103101
self.layers = 1
102+
self.scan_time = 0
103+
self.pair_keys = {}
104104
self.pressed_mask = 0
105+
self.pressed_count = 0
105106
self.queue = Queue(128)
106-
self.t = 0
107-
self.pair_keys = {}
108107

109108
def setup(self):
110109
n = len(self.rows) * len(self.cols)
111-
self.t_keydown = [0] * n
110+
self.pressed_time = [0] * n
112111
self.keys = [0] * n
113-
114-
def f(x):
112+
113+
# convert pykey to pycode (unicode string)
114+
def pykeycode(x):
115115
if type(x) is int:
116116
return chr(x) if x > 9 else ASCII_TO_KEYCODE[ord(str(x))]
117117
if type(x) is str and len(x) == 1:
118118
return ASCII_TO_KEYCODE[ord(str(x))]
119119
raise ValueError('Invalid keycode or keyname {}'.format(x))
120120

121-
convert = lambda *args: ''.join((f(x) for x in args))
121+
concat = lambda *a: ''.join((pykeycode(x) for x in a))
122+
123+
self._keymap = tuple(concat(*layer) for layer in self.keymap)
124+
125+
self.pair_keys_code = tuple(
126+
map(lambda x: ord(pykeycode(x)), self.pair_keys.keys()))
127+
128+
def get_coord(x): return self.coords[self.keymap[0].index(x)]
122129

123-
self._keymap = tuple(convert(*layer) for layer in self.keymap)
124-
125-
self.pair_keys_code = list(map(lambda x: ord(f(x)), self.pair_keys.keys()))
126-
127-
get_coord = lambda x: self.coords[self.keymap[0].index(x)]
128130
def get_mask(x):
129131
keys = self.pair_keys[x]
130132
return 1 << get_coord(keys[0]) | 1 << get_coord(keys[1])
131133

132-
self.pair_keys_mask = list(map(get_mask, self.pair_keys))
134+
self.pair_keys_mask = tuple(map(get_mask, self.pair_keys))
133135
# print([hex(x) for x in self.pair_keys_mask])
134-
136+
135137
self.ro = [] # row as output
136138
for pin in self.rows:
137139
io = digitalio.DigitalInOut(pin)
@@ -151,26 +153,36 @@ def get_mask(x):
151153
self.selected_value = bool(self.row2col)
152154

153155
def scan(self):
154-
self.t = time.monotonic_ns()
156+
self.scan_time = time.monotonic_ns()
155157
pressed_mask = 0
156-
n_pressed_keys = 0
158+
n_pressed = 0
157159
for r, o in enumerate(self.ro):
158160
o.value = self.selected_value # select row
159161
for c, i in enumerate(self.ci):
160162
key_index = r * len(self.ci) + c
161163
key_mask = 1 << key_index
162164
if i.value == self.selected_value:
163165
pressed_mask |= key_mask
164-
n_pressed_keys += 1
166+
n_pressed += 1
165167
if not (self.pressed_mask & (1 << key_index)):
166-
self.t_keydown[key_index] = self.t
168+
self.pressed_time[key_index] = self.scan_time
167169
self.queue.put(key_index)
168170
elif self.pressed_mask & (1 << key_index):
169171
self.queue.put(0x80 | key_index)
170-
172+
171173
o.value = not self.selected_value
172174
self.pressed_mask = pressed_mask
173-
return n_pressed_keys
175+
self.pressed_count = n_pressed
176+
177+
return len(self.queue)
178+
179+
def wait(self, n_events=1, until=None):
180+
while True:
181+
n = len(self.queue)
182+
if n >= n_events or (until and self.scan_time > until):
183+
return n
184+
185+
self.scan()
174186

175187
def keycode(self, position):
176188
position = self.coords[position]
@@ -195,66 +207,58 @@ def run(self):
195207
ble.advertising = True
196208
ble_keyboard = _Keyboard(hid.devices)
197209
usb_keyboard = _Keyboard(usb_hid.devices)
198-
210+
199211
def send(code):
200212
usb_keyboard.press(code)
201213
usb_keyboard.release(code)
202214
if ble.connected:
203215
ble.advertising = False
204216
ble_keyboard.press(code)
205217
ble_keyboard.release(code)
206-
218+
207219
def press(code):
208220
usb_keyboard.press(code)
209221
if ble.connected:
210222
ble.advertising = False
211223
ble_keyboard.press(code)
212-
224+
213225
def release(code):
214226
usb_keyboard.release(code)
215227
if ble.connected:
216228
ble.advertising = False
217229
ble_keyboard.release(code)
218230

219231
self.setup()
220-
221-
pair_keys_state = 0
222-
# pending_key = 0xFF
223232
while True:
224-
n_pressed_keys = self.scan()
225-
n_events = len(self.queue)
226-
if not n_events:
233+
n_events = self.scan()
234+
if n_events == 0:
227235
continue
228236

229237
# detecting pair keys
230-
if n_pressed_keys == 1 and n_events == 1:
231-
if pair_keys_state == 0:
232-
for mask in self.pair_keys_mask:
233-
if self.pressed_mask & mask == self.pressed_mask:
234-
pair_keys_state = 1
235-
break
236-
else:
237-
pair_keys_state = -1
238-
239-
240-
if pair_keys_state > 0:
241-
event = self.queue.preview()
242-
dt = time.monotonic_ns() - self.t_keydown[event & 0x7F]
243-
if dt < 25000000:
244-
# wait for a more event
245-
continue
246-
elif n_pressed_keys == 2 and n_events == 2:
247-
if self.pressed_mask in self.pair_keys_mask:
248-
multi_hit_index = self.pair_keys_mask.index(self.pressed_mask)
249-
keycode = self.pair_keys_code[multi_hit_index]
250-
print('multi hit {}'.format(multi_hit_index))
251-
key = self.queue.get()
252-
self.keys[key] = keycode
253-
238+
if n_events == 1 and self.pressed_count == 1:
239+
for mask in self.pair_keys_mask:
240+
if self.pressed_mask & mask == self.pressed_mask:
241+
n_events = self.wait(2, self.scan_time + 25000000)
242+
break
243+
244+
if n_events >= 2:
245+
mask = 1 << self.queue.preview(0) | 1 << self.queue.preview(1)
246+
if mask in self.pair_keys_mask:
247+
pair_keys_index = self.pair_keys_mask.index(mask)
248+
keycode = self.pair_keys_code[pair_keys_index]
249+
key1 = self.queue.get()
250+
key2 = self.queue.get()
251+
dt = self.pressed_time[key2] - self.pressed_time[key1]
252+
print('pair keys {} ({}, {}), dt = {}'.format(
253+
pair_keys_index,
254+
key1,
255+
key2,
256+
dt // 1000000))
257+
254258
# only one action
255-
key = self.queue.get()
256-
self.keys[key] = 0
257-
259+
self.keys[key1] = keycode
260+
self.keys[key2] = 0
261+
258262
if keycode < 2:
259263
pass
260264
elif keycode < 0xFF:
@@ -268,44 +272,41 @@ def release(code):
268272
elif kind == ACT_LAYER_TAP:
269273
self.layers |= 1 << layer
270274
print('layers {}'.format(self.layers))
271-
272-
pair_keys_state = 0
275+
273276
while len(self.queue):
274277
event = self.queue.get()
275278
key = event & 0x7F
276-
if event & 0x80:
277-
print('{} \\'.format(key))
278-
keycode = self.keys[key]
279-
dt = (self.t - self.t_keydown[key]) // 1000000
280-
print('dt({}) = {}'.format(key, dt))
279+
if event & 0x80 == 0:
280+
keycode = self.keycode(key)
281+
self.keys[key] = keycode
282+
print('{} / keycode = {}'.format(key, keycode))
281283
if keycode < 2:
282284
pass
283-
if keycode < 0xFF:
284-
release(keycode)
285+
elif keycode < 0xFF:
286+
press(keycode)
285287
else:
286288
kind = keycode >> 12
287289
layer = ((keycode >> 8) & 0xF)
288290
if kind == ACT_LAYER_TAP:
289-
self.layers &= ~(1 << layer)
291+
self.layers |= 1 << layer
290292
print('layers {}'.format(self.layers))
291-
code = keycode & 0xFF
292-
if dt < 500 and code:
293-
send(code)
294293
else:
295-
print('/ {}'.format(key))
296-
keycode = self.keycode(key)
297-
self.keys[key] = keycode
298-
print('keycode {}'.format(keycode))
294+
keycode = self.keys[key]
295+
dt = (self.scan_time - self.pressed_time[key]) // 1000000
296+
print('{} \\ keycode = {}, dt = {}'.format(key, keycode, dt))
299297
if keycode < 2:
300298
pass
301-
elif keycode < 0xFF:
302-
press(keycode)
299+
if keycode < 0xFF:
300+
release(keycode)
303301
else:
304302
kind = keycode >> 12
305303
layer = ((keycode >> 8) & 0xF)
306304
if kind == ACT_LAYER_TAP:
307-
self.layers |= 1 << layer
305+
self.layers &= ~(1 << layer)
308306
print('layers {}'.format(self.layers))
307+
code = keycode & 0xFF
308+
if dt < 500 and code:
309+
send(code)
309310

310311
if not ble.connected and not ble.advertising:
311312
ble.start_advertising(advertisement)
@@ -316,7 +317,7 @@ def release(code):
316317

317318
def main():
318319
kbd = Keyboard()
319-
kbd.pair_keys = { L2: (S, D), L1: (J, K) }
320+
kbd.pair_keys = {L2: (S, D), L1: (J, K)}
320321
kbd.run()
321322

322323

0 commit comments

Comments
 (0)