rgb_configurator: initial implementation

main
Ilya Zhuravlev 2021-04-03 19:47:29 -04:00
parent 6ddbce17ec
commit 8aa8e0dab3
3 changed files with 202 additions and 2 deletions

View File

@ -17,6 +17,9 @@ CMD_VIA_GET_KEYBOARD_VALUE = 0x02
CMD_VIA_SET_KEYBOARD_VALUE = 0x03 CMD_VIA_SET_KEYBOARD_VALUE = 0x03
CMD_VIA_GET_KEYCODE = 0x04 CMD_VIA_GET_KEYCODE = 0x04
CMD_VIA_SET_KEYCODE = 0x05 CMD_VIA_SET_KEYCODE = 0x05
CMD_VIA_LIGHTING_SET_VALUE = 0x07
CMD_VIA_LIGHTING_GET_VALUE = 0x08
CMD_VIA_LIGHTING_SAVE = 0x09
CMD_VIA_MACRO_GET_COUNT = 0x0C CMD_VIA_MACRO_GET_COUNT = 0x0C
CMD_VIA_MACRO_GET_BUFFER_SIZE = 0x0D CMD_VIA_MACRO_GET_BUFFER_SIZE = 0x0D
CMD_VIA_MACRO_GET_BUFFER = 0x0E CMD_VIA_MACRO_GET_BUFFER = 0x0E
@ -28,6 +31,14 @@ CMD_VIA_VIAL_PREFIX = 0xFE
VIA_LAYOUT_OPTIONS = 0x02 VIA_LAYOUT_OPTIONS = 0x02
VIA_SWITCH_MATRIX_STATE = 0x03 VIA_SWITCH_MATRIX_STATE = 0x03
QMK_BACKLIGHT_BRIGHTNESS = 0x09
QMK_BACKLIGHT_EFFECT = 0x0A
QMK_RGBLIGHT_BRIGHTNESS = 0x80
QMK_RGBLIGHT_EFFECT = 0x81
QMK_RGBLIGHT_EFFECT_SPEED = 0x82
QMK_RGBLIGHT_COLOR = 0x83
CMD_VIAL_GET_KEYBOARD_ID = 0x00 CMD_VIAL_GET_KEYBOARD_ID = 0x00
CMD_VIAL_GET_SIZE = 0x01 CMD_VIAL_GET_SIZE = 0x01
CMD_VIAL_GET_DEFINITION = 0x02 CMD_VIAL_GET_DEFINITION = 0x02
@ -145,6 +156,7 @@ class Keyboard:
def __init__(self, dev, usb_send=hid_send): def __init__(self, dev, usb_send=hid_send):
self.dev = dev self.dev = dev
self.usb_send = usb_send self.usb_send = usb_send
self.definition = None
# n.b. using OrderedDict here to make order of layout requests consistent for tests # n.b. using OrderedDict here to make order of layout requests consistent for tests
self.rowcol = OrderedDict() self.rowcol = OrderedDict()
@ -163,6 +175,10 @@ class Keyboard:
self.vibl = False self.vibl = False
self.custom_keycodes = None self.custom_keycodes = None
self.lighting_qmk_rgblight = self.lighting_qmk_backlight = False
self.underglow_brightness = self.underglow_effect = self.underglow_effect_speed = -1
self.underglow_color = (0, 0)
self.via_protocol = self.vial_protocol = self.keyboard_id = -1 self.via_protocol = self.vial_protocol = self.keyboard_id = -1
def reload(self, sideload_json=None): def reload(self, sideload_json=None):
@ -177,6 +193,7 @@ class Keyboard:
self.reload_layers() self.reload_layers()
self.reload_keymap() self.reload_keymap()
self.reload_macros() self.reload_macros()
self.reload_rgb()
def reload_layers(self): def reload_layers(self):
""" Get how many layers the keyboard has """ """ Get how many layers the keyboard has """
@ -217,6 +234,8 @@ class Keyboard:
payload = json.loads(lzma.decompress(payload)) payload = json.loads(lzma.decompress(payload))
self.definition = payload
if "vial" in payload: if "vial" in payload:
vial = payload["vial"] vial = payload["vial"]
self.vibl = vial.get("vibl", False) self.vibl = vial.get("vibl", False)
@ -313,6 +332,23 @@ class Keyboard:
macros = self.macro.split(b"\x00") + [b""] * self.macro_count macros = self.macro.split(b"\x00") + [b""] * self.macro_count
self.macro = b"\x00".join(macros[:self.macro_count]) + b"\x00" self.macro = b"\x00".join(macros[:self.macro_count]) + b"\x00"
def reload_rgb(self):
if "lighting" in self.definition:
self.lighting_qmk_rgblight = self.definition["lighting"] in ["qmk_rgblight", "qmk_backlight_rgblight"]
self.lighting_qmk_backlight = self.definition["lighting"] in ["qmk_backlight", "qmk_backlight_rgblight"]
if self.lighting_qmk_rgblight:
self.underglow_brightness = self.usb_send(
self.dev, struct.pack(">BB", CMD_VIA_LIGHTING_GET_VALUE, QMK_RGBLIGHT_BRIGHTNESS), retries=20)[2]
self.underglow_effect = self.usb_send(
self.dev, struct.pack(">BB", CMD_VIA_LIGHTING_GET_VALUE, QMK_RGBLIGHT_EFFECT), retries=20)[2]
self.underglow_effect_speed = self.usb_send(
self.dev, struct.pack(">BB", CMD_VIA_LIGHTING_GET_VALUE, QMK_RGBLIGHT_EFFECT_SPEED), retries=20)[2]
color = self.usb_send(
self.dev, struct.pack(">BB", CMD_VIA_LIGHTING_GET_VALUE, QMK_RGBLIGHT_COLOR), retries=20)[2:4]
# hue, sat
self.underglow_color = (color[0], color[1])
def set_key(self, layer, row, col, code): def set_key(self, layer, row, col, code):
if code < 0: if code < 0:
return return
@ -354,6 +390,24 @@ class Keyboard:
retries=20) retries=20)
self.macro = data self.macro = data
def set_qmk_rgblight_brightness(self, value):
self.underglow_brightness = value
self.usb_send(self.dev, struct.pack(">BBB", CMD_VIA_LIGHTING_SET_VALUE, QMK_RGBLIGHT_BRIGHTNESS, value),
retries=20)
def set_qmk_rgblight_effect(self, index):
self.underglow_effect = index
self.usb_send(self.dev, struct.pack(">BBB", CMD_VIA_LIGHTING_SET_VALUE, QMK_RGBLIGHT_EFFECT, index),
retries=20)
def set_qmk_rgblight_effect_speed(self, value):
self.underglow_effect_speed = value
self.usb_send(self.dev, struct.pack(">BBB", CMD_VIA_LIGHTING_SET_VALUE, QMK_RGBLIGHT_EFFECT_SPEED, value),
retries=20)
def save_rgb(self):
self.usb_send(self.dev, struct.pack(">B", CMD_VIA_LIGHTING_SAVE), retries=20)
def save_layout(self): def save_layout(self):
""" Serializes current layout to a binary """ """ Serializes current layout to a binary """

View File

@ -14,6 +14,7 @@ from keymap_editor import KeymapEditor
from keymaps import KEYMAPS from keymaps import KEYMAPS
from layout_editor import LayoutEditor from layout_editor import LayoutEditor
from macro_recorder import MacroRecorder from macro_recorder import MacroRecorder
from rgb_configurator import RGBConfigurator
from unlocker import Unlocker from unlocker import Unlocker
from util import tr, find_vial_devices, EXAMPLE_KEYBOARDS from util import tr, find_vial_devices, EXAMPLE_KEYBOARDS
from vial_device import VialKeyboard from vial_device import VialKeyboard
@ -54,9 +55,12 @@ class MainWindow(QMainWindow):
self.firmware_flasher = FirmwareFlasher(self) self.firmware_flasher = FirmwareFlasher(self)
self.macro_recorder = MacroRecorder() self.macro_recorder = MacroRecorder()
self.matrix_tester = MatrixTest(self.layout_editor) self.matrix_tester = MatrixTest(self.layout_editor)
self.rgb_configurator = RGBConfigurator()
self.editors = [(self.keymap_editor, "Keymap"), (self.layout_editor, "Layout"), (self.macro_recorder, "Macros"), self.editors = [(self.keymap_editor, "Keymap"), (self.layout_editor, "Layout"), (self.macro_recorder, "Macros"),
(self.matrix_tester, "Matrix tester"), (self.firmware_flasher, "Firmware updater")] (self.matrix_tester, "Matrix tester"), (self.rgb_configurator, "Lighting"),
(self.firmware_flasher, "Firmware updater")]
Unlocker.global_layout_editor = self.layout_editor Unlocker.global_layout_editor = self.layout_editor
self.tabs = QTabWidget() self.tabs = QTabWidget()
@ -238,7 +242,7 @@ class MainWindow(QMainWindow):
self.current_device.keyboard.reload() self.current_device.keyboard.reload()
for e in [self.layout_editor, self.keymap_editor, self.firmware_flasher, self.macro_recorder, for e in [self.layout_editor, self.keymap_editor, self.firmware_flasher, self.macro_recorder,
self.matrix_tester]: self.matrix_tester, self.rgb_configurator]:
e.rebuild(self.current_device) e.rebuild(self.current_device)
def refresh_tabs(self): def refresh_tabs(self):

View File

@ -0,0 +1,142 @@
# SPDX-License-Identifier: GPL-2.0-or-later
from PyQt5 import QtCore
from PyQt5.QtWidgets import QVBoxLayout, QWidget, QPushButton, QHBoxLayout, QSizePolicy, QGridLayout, QLabel, QSlider, \
QComboBox
from basic_editor import BasicEditor
from util import tr
from vial_device import VialKeyboard
class QmkRgblightEffect:
def __init__(self, idx, name, color_picker):
self.idx = idx
self.name = name
self.color_picker = color_picker
QMK_RGBLIGHT_EFFECTS = [
QmkRgblightEffect(0, "All Off", False),
QmkRgblightEffect(1, "Solid Color", True),
QmkRgblightEffect(2, "Breathing 1", True),
QmkRgblightEffect(3, "Breathing 2", True),
QmkRgblightEffect(4, "Breathing 3", True),
QmkRgblightEffect(5, "Breathing 4", True),
QmkRgblightEffect(6, "Rainbow Mood 1", False),
QmkRgblightEffect(7, "Rainbow Mood 2", False),
QmkRgblightEffect(8, "Rainbow Mood 3", False),
QmkRgblightEffect(9, "Rainbow Swirl 1", False),
QmkRgblightEffect(10, "Rainbow Swirl 2", False),
QmkRgblightEffect(11, "Rainbow Swirl 3", False),
QmkRgblightEffect(12, "Rainbow Swirl 4", False),
QmkRgblightEffect(13, "Rainbow Swirl 5", False),
QmkRgblightEffect(14, "Rainbow Swirl 6", False),
QmkRgblightEffect(15, "Snake 1", True),
QmkRgblightEffect(16, "Snake 2", True),
QmkRgblightEffect(17, "Snake 3", True),
QmkRgblightEffect(18, "Snake 4", True),
QmkRgblightEffect(19, "Snake 5", True),
QmkRgblightEffect(20, "Snake 6", True),
QmkRgblightEffect(21, "Knight 1", True),
QmkRgblightEffect(22, "Knight 2", True),
QmkRgblightEffect(23, "Knight 3", True),
QmkRgblightEffect(24, "Christmas", True),
QmkRgblightEffect(25, "Gradient 1", True),
QmkRgblightEffect(26, "Gradient 2", True),
QmkRgblightEffect(27, "Gradient 3", True),
QmkRgblightEffect(28, "Gradient 4", True),
QmkRgblightEffect(29, "Gradient 5", True),
QmkRgblightEffect(30, "Gradient 6", True),
QmkRgblightEffect(31, "Gradient 7", True),
QmkRgblightEffect(32, "Gradient 8", True),
QmkRgblightEffect(33, "Gradient 9", True),
QmkRgblightEffect(34, "Gradient 10", True),
QmkRgblightEffect(35, "RGB Test", True),
QmkRgblightEffect(36, "Alternating", True),
]
class RGBConfigurator(BasicEditor):
def __init__(self):
super().__init__()
self.addStretch()
w = QWidget()
w.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
self.container = QGridLayout()
w.setLayout(self.container)
self.addWidget(w)
self.setAlignment(w, QtCore.Qt.AlignHCenter)
self.container.addWidget(QLabel(tr("RGBConfigurator", "Underglow Effect")), 0, 0)
self.underglow_effect = QComboBox()
for ef in QMK_RGBLIGHT_EFFECTS:
self.underglow_effect.addItem(ef.name)
self.container.addWidget(self.underglow_effect, 0, 1)
self.container.addWidget(QLabel(tr("RGBConfigurator", "Underglow Brightness")), 1, 0)
self.underglow_brightness = QSlider(QtCore.Qt.Horizontal)
self.underglow_brightness.setMinimum(0)
self.underglow_brightness.setMaximum(255)
self.underglow_brightness.valueChanged.connect(self.on_underglow_brightness_changed)
self.container.addWidget(self.underglow_brightness, 1, 1)
# XXX: qmk speed setting does nothing
# self.container.addWidget(QLabel(tr("RGBConfigurator", "Underglow Effect Speed")), 2, 0)
# self.underglow_effect_speed = QSlider(QtCore.Qt.Horizontal)
# self.underglow_effect_speed.setMinimum(0)
# self.underglow_effect_speed.setMaximum(3)
# self.underglow_effect_speed.valueChanged.connect(self.on_underglow_effect_speed_changed)
# self.container.addWidget(self.underglow_effect_speed, 2, 1)
self.lbl_underglow_color = QLabel(tr("RGBConfigurator", "Underglow Color"))
self.container.addWidget(self.lbl_underglow_color, 3, 0)
self.underglow_color = QLabel("x")
self.container.addWidget(self.underglow_color, 3, 1)
self.underglow_effect.currentIndexChanged.connect(self.on_underglow_effect_changed)
self.addStretch()
buttons = QHBoxLayout()
buttons.addStretch()
save_btn = QPushButton(tr("RGBConfigurator", "Save"))
buttons.addWidget(save_btn)
save_btn.clicked.connect(self.on_save)
self.addLayout(buttons)
def on_underglow_brightness_changed(self, value):
self.device.keyboard.set_qmk_rgblight_brightness(value)
def on_underglow_effect_changed(self, index):
self.lbl_underglow_color.setVisible(QMK_RGBLIGHT_EFFECTS[index].color_picker)
self.underglow_color.setVisible(QMK_RGBLIGHT_EFFECTS[index].color_picker)
self.device.keyboard.set_qmk_rgblight_effect(index)
def on_underglow_effect_speed_changed(self, value):
self.device.keyboard.set_qmk_rgblight_effect_speed(value)
def on_save(self):
self.device.keyboard.save_rgb()
def valid(self):
return isinstance(self.device, VialKeyboard) and self.device.keyboard.lighting_qmk_rgblight
def rebuild(self, device):
super().rebuild(device)
if not self.valid():
return
# TODO: this should block signals from the actual combobox/etc sending them
# self.blockSignals(True)
self.underglow_brightness.setValue(device.keyboard.underglow_brightness)
self.underglow_effect.setCurrentIndex(device.keyboard.underglow_effect)
# self.underglow_effect_speed.setValue(device.keyboard.underglow_effect_speed)
# TODO: as above
# self.blockSignals(False)