164 lines
7.0 KiB
Python
Executable File
164 lines
7.0 KiB
Python
Executable File
#!/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}")
|