-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcode.py
More file actions
107 lines (91 loc) · 3.8 KB
/
code.py
File metadata and controls
107 lines (91 loc) · 3.8 KB
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
import board, keypad, usb_hid, usb_cdc, json
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
from adafruit_hid.keycode import Keycode
rowPins = (board.GP6, board.GP8, board.GP11)
colPins = (board.GP0, board.GP2, board.GP4)
keyMatrix = keypad.KeyMatrix(rowPins, colPins, columns_to_anodes=True)
layKey = keypad.Keys([board.GP13], value_when_pressed=False)
kbd = Keyboard(usb_hid.devices)
kbdLayout = KeyboardLayoutUS(kbd)
serialPort = usb_cdc.data
def loadKeymaps():
try:
with open("keymaps.json", "r") as f:
rawKeymaps = json.load(f)
parsed = {}
for layerStr, keyDict in rawKeymaps.items():
parsed[int(layerStr)] = {int(k): v for k, v in keyDict.items()}
return parsed
except Exception:
safe = {}
for l in range(9):
safe[l] = {k: {"type": "empty", "value": ""} for k in range(9)}
return safe
allKeymaps = loadKeymaps()
activeLayer = 0
layMode = False
def handleIncomingSerial():
global allKeymaps
if not serialPort or not serialPort.in_waiting:
return
# Use native readline! Fast and buffer-safe.
line = serialPort.readline().decode("utf-8", "ignore").strip()
if line == "LAYOUT_DATA_START":
layout_data = []
while True:
# Wait inside this loop until the transfer is done
if serialPort.in_waiting:
chunk = serialPort.readline().decode("utf-8", "ignore").strip()
if chunk == "LAYOUT_DATA_END":
try:
with open("keymaps.json", "w") as f:
f.write("".join(layout_data))
allKeymaps = loadKeymaps()
serialPort.write(b"LAYOUT_OK\n")
except Exception:
serialPort.write(b"LAYOUT_ERR\n")
return
elif chunk:
layout_data.append(chunk)
def fireKey(entry):
actionType = entry.get("type", "empty")
actionValue = entry.get("value", "")
if actionType == "empty" or not actionValue: return
if actionType == "key":
keycode = getattr(Keycode, actionValue, None)
if keycode: kbd.press(keycode)
elif actionType == "combo":
comboKeycodes = [getattr(Keycode, k, None) for k in actionValue]
comboKeycodes = [k for k in comboKeycodes if k is not None]
if comboKeycodes: kbd.press(*comboKeycodes)
elif actionType == "print":
kbdLayout.write(actionValue)
elif actionType == "app":
if serialPort:
serialPort.write(("LAUNCH_APP:" + actionValue + "\n").encode("utf-8"))
def releaseKey(entry):
actionType = entry.get("type", "empty")
actionValue = entry.get("value", "")
if actionType == "empty" or not actionValue: return
if actionType == "key":
keycode = getattr(Keycode, actionValue, None)
if keycode: kbd.release(keycode)
elif actionType == "combo":
comboKeycodes = [getattr(Keycode, k, None) for k in actionValue]
comboKeycodes = [k for k in comboKeycodes if k is not None]
if comboKeycodes: kbd.release(*comboKeycodes)
while True:
handleIncomingSerial()
keyPress = keyMatrix.events.get()
layPress = layKey.events.get()
if layPress is not None and layPress.pressed: layMode = not layMode
if layMode and keyPress is not None and keyPress.pressed:
chosenLayer = keyPress.key_number
if chosenLayer in allKeymaps: activeLayer = chosenLayer
layMode = False
continue
if keyPress is not None and not layMode:
keyEntry = allKeymaps[activeLayer].get(keyPress.key_number, {"type":"empty", "value":""})
if keyPress.pressed: fireKey(keyEntry)
elif keyPress.released: releaseKey(keyEntry)