Поддержка MacOS (проверено в Tahoe)
This commit is contained in:
Executable
+163
@@ -0,0 +1,163 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Карта «LED-индекс → физическая клавиша» для GANSS ARDOR_Katana (0c45:8006).
|
||||
|
||||
Построена экспериментально: группы индексов красились контрастными цветами,
|
||||
пользователь сообщал, какие клавиши загорелись (методика и открытые вопросы —
|
||||
в docs/protocol.md).
|
||||
|
||||
Имена клавиш — позиции US-раскладки.
|
||||
"""
|
||||
|
||||
__all__ = ["KEYMAP", "BLIND", "UNKNOWN", "PROBE_COLORS", "KEY_SYMBOL_ALIASES",
|
||||
"name"]
|
||||
|
||||
# Подтверждённая карта (индекс → имя клавиши)
|
||||
KEYMAP = {
|
||||
0x01: "Esc",
|
||||
0x02: "F1", 0x03: "F2", 0x04: "F3", 0x05: "F4",
|
||||
0x06: "F5", 0x07: "F6", 0x08: "F7", 0x09: "F8",
|
||||
0x0A: "F9", 0x0B: "F10", 0x0C: "F11", 0x0D: "F12",
|
||||
|
||||
0x13: "`(~)", 0x14: "1", 0x15: "2", 0x16: "3", 0x17: "4",
|
||||
0x18: "5", 0x19: "6", 0x1A: "7", 0x1B: "8", 0x1C: "9", 0x1D: "0",
|
||||
0x1E: "-(_)", 0x1F: "=(+)",
|
||||
|
||||
0x20: "NumLock", 0x21: "Num/", 0x22: "Num*",
|
||||
0x25: "Tab", 0x26: "Q", 0x27: "W", 0x28: "E", 0x29: "R",
|
||||
0x2A: "T", 0x2B: "Y", 0x2C: "U", 0x2D: "I", 0x2E: "O", 0x2F: "P",
|
||||
|
||||
0x30: "[({)", 0x31: "](})", 0x32: "Num7", 0x33: "Num8", 0x34: "Num9",
|
||||
0x37: "Caps", 0x38: "A", 0x39: "S", 0x3A: "D", 0x3B: "F",
|
||||
0x3C: "G", 0x3D: "H", 0x3E: "J", 0x3F: "K",
|
||||
|
||||
0x40: "L", 0x41: ";", 0x42: "'", 0x43: "\\",
|
||||
0x44: "Num4", 0x45: "Num5", 0x46: "Num6",
|
||||
|
||||
0x49: "LShift", 0x4A: "Z", 0x4B: "X", 0x4C: "C", 0x4D: "V",
|
||||
0x4E: "B", 0x4F: "N",
|
||||
0x50: "M", 0x51: ",", 0x52: ".", 0x53: "/", 0x54: "RShift",
|
||||
0x55: "Enter", 0x56: "Num1", 0x57: "Num2", 0x58: "Num3",
|
||||
|
||||
0x5B: "LCtrl", 0x5C: "LWin", 0x5D: "LAlt",
|
||||
0x5E: "Space", 0x5F: "RAlt", 0x60: "Fn", 0x61: "Menu", 0x62: "RCtrl",
|
||||
|
||||
0x63: "ArrowLeft", 0x64: "ArrowDown", 0x65: "ArrowUp",
|
||||
0x66: "ArrowRight", 0x67: "Backspace", 0x68: "Num0",
|
||||
0x69: "Num.(Del)", 0x6A: "NumEnter",
|
||||
0x70: "PrtSc", 0x71: "ScrLk", 0x73: "Pause", 0x74: "Insert",
|
||||
0x75: "Home", 0x76: "PgUp", 0x77: "Delete", 0x78: "End",
|
||||
0x79: "PgDown", 0x7A: "Num-", 0x7B: "Num+",
|
||||
}
|
||||
|
||||
# Слоты, которые красились, но не светятся: ни к какому LED не подключены
|
||||
BLIND = {0x00, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x23, 0x24, 0x35, 0x36,
|
||||
0x47, 0x48, 0x59, 0x5A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x72,
|
||||
0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85,
|
||||
0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E}
|
||||
|
||||
# Индексы, не идентифицированные на момент снятия карты
|
||||
UNKNOWN = sorted(set(range(0x00, 0x8F)) - set(KEYMAP) - BLIND)
|
||||
|
||||
# Контрастная палитра для картирования (максимально различимые цвета,
|
||||
# за раз — немного точек)
|
||||
PROBE_COLORS = [
|
||||
(0xFF, 0x00, 0x00), # красный
|
||||
(0x00, 0xFF, 0x00), # зелёный
|
||||
(0x00, 0x00, 0xFF), # синий
|
||||
(0xFF, 0xFF, 0x00), # жёлтый
|
||||
(0xFF, 0x00, 0xFF), # маджента
|
||||
(0x00, 0xFF, 0xFF), # циан
|
||||
(0xFF, 0x80, 0x00), # оранжевый
|
||||
]
|
||||
|
||||
# Дополнительные алиасы клавиш: синоним → каноническое имя из KEYMAP
|
||||
# (в нижнем регистре). Позволяют писать --key tilde=red, --key lbracket=blue.
|
||||
# Символы-псевдонимы ('[', '~', ';') работают напрямую из KEYMAP.
|
||||
KEY_SYMBOL_ALIASES = {
|
||||
# цифровой ряд
|
||||
"tilde": "`", "grave": "`", "backquote": "`", "backtick": "`",
|
||||
"minus": "-", "dash": "-", "hyphen": "-",
|
||||
"equal": "=", "equals": "=",
|
||||
# основной блок
|
||||
"lbracket": "[", "leftbracket": "[", "openbracket": "[",
|
||||
"rbracket": "]", "rightbracket": "]", "closebracket": "]",
|
||||
"semicolon": ";", "colon": ";",
|
||||
"quote": "'", "apostrophe": "'", "singlequote": "'",
|
||||
"backslash": chr(92), "bslash": chr(92),
|
||||
"comma": ",",
|
||||
"period": ".", "dot": ".",
|
||||
"slash": "/", "question": "/",
|
||||
"lessthan": ",", "greaterthan": ".",
|
||||
# пробел и служебные
|
||||
"spacebar": "space",
|
||||
"capslock": "caps",
|
||||
"leftshift": "lshift", "shift": "lshift",
|
||||
"rightshift": "rshift",
|
||||
"leftctrl": "lctrl", "ctrl": "lctrl",
|
||||
"rightctrl": "rctrl",
|
||||
"leftalt": "lalt", "alt": "lalt",
|
||||
"rightalt": "ralt", "altgr": "ralt",
|
||||
"windows": "lwin", "super": "lwin", "meta": "lwin",
|
||||
"menu": "menu", "context": "menu", "apps": "menu",
|
||||
"enter": "enter", "return": "enter", "cr": "enter",
|
||||
"tab": "tab",
|
||||
"escape": "esc",
|
||||
"backspace": "backspace", "bksp": "backspace",
|
||||
"delete": "delete", "del": "delete",
|
||||
"insert": "insert", "ins": "insert",
|
||||
"home": "home", "end": "end",
|
||||
"pageup": "pgup", "pgdn": "pgdown", "pagedown": "pgdown",
|
||||
"printscreen": "prtsc", "prntscr": "prtsc", "pscr": "prtsc",
|
||||
"scrolllock": "scrlk", "slck": "scrlk",
|
||||
"pause": "pause", "break": "pause",
|
||||
"leftarrow": "arrowleft", "rightarrow": "arrowright",
|
||||
"uparrow": "arrowup", "downarrow": "arrowdown",
|
||||
"left": "arrowleft", "right": "arrowright",
|
||||
"up": "arrowup", "down": "arrowdown",
|
||||
# нумпад
|
||||
"numlock": "numlock", "numasterisk": "num*", "numtimes": "num*",
|
||||
"numminus": "num-", "numplus": "num+", "numpoint": "num.",
|
||||
"numdot": "num.", "numdecimal": "num.", "numdel": "num.",
|
||||
"numcomma": "num.", "numperiod": "num.",
|
||||
"numslash": "num/", "numdivide": "num/",
|
||||
"numenter": "numenter",
|
||||
"num0": "num0", "num1": "num1", "num2": "num2", "num3": "num3",
|
||||
"num4": "num4", "num5": "num5", "num6": "num6", "num7": "num7",
|
||||
"num8": "num8", "num9": "num9",
|
||||
}
|
||||
|
||||
|
||||
def name(idx: int) -> str:
|
||||
"""Имя слота: клавиша, «(blind)» для слепых или 0xNN? для неизвестных."""
|
||||
if idx in KEYMAP:
|
||||
return KEYMAP[idx]
|
||||
if idx in BLIND:
|
||||
return "(blind)"
|
||||
return f"0x{idx:02x}?"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("Confirmed keymap:")
|
||||
for i in sorted(KEYMAP):
|
||||
print(f" 0x{i:02x}: {KEYMAP[i]}")
|
||||
print(f"\nBlind slots: {' '.join(f'{i:02x}' for i in sorted(BLIND))}")
|
||||
print(f"Unidentified ({len(UNKNOWN)}): "
|
||||
+ " ".join(f"{i:02x}" for i in UNKNOWN))
|
||||
|
||||
# алиасы, сгруппированные по клавишам в порядке раскладки
|
||||
from collections import defaultdict
|
||||
groups = defaultdict(list)
|
||||
for alias, canonical in KEY_SYMBOL_ALIASES.items():
|
||||
groups[canonical].append(alias)
|
||||
|
||||
def _idx(canonical: str) -> int:
|
||||
"""LED-индекс канонического имени (0xFF — если не найдено)."""
|
||||
for i, lbl in KEYMAP.items():
|
||||
if lbl.lower() == canonical or lbl.split("(")[0].lower() == canonical:
|
||||
return i
|
||||
return 0xFF
|
||||
|
||||
print(f"\nKey aliases ({len(KEY_SYMBOL_ALIASES)}):")
|
||||
for canonical in sorted(groups, key=_idx):
|
||||
aliases = ", ".join(sorted(groups[canonical]))
|
||||
print(f" {canonical:12s} <- {aliases}")
|
||||
Reference in New Issue
Block a user