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_GET_KEYCODE = 0x04
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_BUFFER_SIZE = 0x0D
CMD_VIA_MACRO_GET_BUFFER = 0x0E
@ -28,6 +31,14 @@ CMD_VIA_VIAL_PREFIX = 0xFE
VIA_LAYOUT_OPTIONS = 0x02
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_SIZE = 0x01
CMD_VIAL_GET_DEFINITION = 0x02
@ -145,6 +156,7 @@ class Keyboard:
def __init__(self, dev, usb_send=hid_send):
self.dev = dev
self.usb_send = usb_send
self.definition = None
# n.b. using OrderedDict here to make order of layout requests consistent for tests
self.rowcol = OrderedDict()
@ -163,6 +175,10 @@ class Keyboard:
self.vibl = False
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
def reload(self, sideload_json=None):
@ -177,6 +193,7 @@ class Keyboard:
self.reload_layers()
self.reload_keymap()
self.reload_macros()
self.reload_rgb()
def reload_layers(self):
""" Get how many layers the keyboard has """
@ -217,6 +234,8 @@ class Keyboard:
payload = json.loads(lzma.decompress(payload))
self.definition = payload
if "vial" in payload:
vial = payload["vial"]
self.vibl = vial.get("vibl", False)
@ -313,6 +332,23 @@ class Keyboard:
macros = self.macro.split(b"\x00") + [b""] * self.macro_count
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):
if code < 0:
return
@ -354,6 +390,24 @@ class Keyboard:
retries=20)
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):
""" Serializes current layout to a binary """

View File

@ -14,6 +14,7 @@ from keymap_editor import KeymapEditor
from keymaps import KEYMAPS
from layout_editor import LayoutEditor
from macro_recorder import MacroRecorder
from rgb_configurator import RGBConfigurator
from unlocker import Unlocker
from util import tr, find_vial_devices, EXAMPLE_KEYBOARDS
from vial_device import VialKeyboard
@ -54,9 +55,12 @@ class MainWindow(QMainWindow):
self.firmware_flasher = FirmwareFlasher(self)
self.macro_recorder = MacroRecorder()
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.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
self.tabs = QTabWidget()
@ -238,7 +242,7 @@ class MainWindow(QMainWindow):
self.current_device.keyboard.reload()
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)
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)