bring over old posts
This commit is contained in:
parent
ba252d7d6a
commit
51c0a6b30e
20 changed files with 870 additions and 12 deletions
211
content/blog/keyboard-lighting.md
Normal file
211
content/blog/keyboard-lighting.md
Normal file
|
@ -0,0 +1,211 @@
|
|||
+++
|
||||
title = "Keyboard Lighting"
|
||||
date = 2024-04-10
|
||||
updated = 2024-07-30
|
||||
+++
|
||||
{% note() %}
|
||||
**I am not a keyboard nerd**. Full respect to any of you out there, but I am not one, nor do I plan to become one anytime soon.
|
||||
Don't take this as a "definitive guide" to anything, it was just me messing around.
|
||||
{% end %}
|
||||
|
||||
# Introduction
|
||||
Yesterday, I started using a new keyboard.
|
||||
Well, it was yesterday as of when I started writing this - it certainly isn't yesterday anymore.
|
||||
|
||||
Previously, I'd been using a super mushy-feeling Incredibly Generic Office Supply Keyboard from Dell, which honestly sucked.
|
||||
After a few years of heavy use it had gotten kinda nasty, and was basically uncleanable.
|
||||
|
||||
Considering how much time I spend typing, I figured it was worth getting an upgrade, so I ordered a
|
||||
[Keychron C1 Pro](https://www.keychron.com/products/keychron-c1-pro-qmk-via-wired-mechanical-keyboard?variant=40615805583449)
|
||||
(the variant with hot-swappable switches, and therefore also RGB lighting).
|
||||
I'm not going to say it's the best keyboard ever and that you should go out and buy it immediately,
|
||||
or conversely that it's the *worst* keyboard and you should avoid it at all costs.
|
||||
It's fine for my purposes, and is a huge improvement over my old keyboard, but that's beside the point.
|
||||
|
||||
I didn't buy it for the RGB effects.
|
||||
To be honest, I don't even *like* RGB lighting most of the time. I find it kind of distracting,
|
||||
and I usually try to avoid "gamer-branded" products stuffed to the brim with multicolored lights like the plague.
|
||||
But, being me, and being told "yeah this keyboard has an ARM chip inside it" (a `STM32F402RC` to be precise) I had to see if I could customize it.
|
||||
|
||||
Aaaand so began an afternoon-long dive down a keyboard rabbit-hole.
|
||||
|
||||
# VIA
|
||||
{% important() %}
|
||||
I started writing this before [Keychron Launcher](https://launcher.keychron.com) came out.
|
||||
I haven't tried to use it, and don't really know what it's capable of, but it's possible that
|
||||
if it had existed at the time I wouldn't have gone down this rabbit hole at all.
|
||||
{% end %}
|
||||
|
||||
From poking around on Keychron's website it looked like the simplest route to customize the lighting was to use [VIA](https://www.caniusevia.com/).
|
||||
Firefox doesn't support [webhid](https://caniuse.com/?search=webhid), but Chromium-based browsers do, so I opened up Chromium...
|
||||
and what's this? An error? Already? I haven't even *done* anything yet.
|
||||
|
||||
{{ image(src="/assets/keyboard/keyboard-via-error.png", alt="Screenshot of VIA displaying an error", caption="Extremely useful error message") }}
|
||||
|
||||
Ooookay?
|
||||
|
||||
Apparently you need to dig up a keyboard-specific config file (in my case [this json](/assets/keyboard/c1_pro_v2_ansi_rgb.json)) and load it.
|
||||
Don't really know how I missed that.
|
||||
|
||||
In any case, it seemed to be working, and I could cycle through the various RGB modes, as well as customize the static color.
|
||||
But, come on, that's *so dreadfully boring*. I wasn't interested in customizing keymaps or anything like that, and I felt... unsatisfied... with the lighting options.
|
||||
Apparently their definition of "customizable" lighting doesn't quite align with mine.
|
||||
There's a little computer inside there, there's bound to be *something* more I can do with it...
|
||||
|
||||
# Screwing around with a Windows VM
|
||||
After googling around for a while, I stumbled upon [this reddit post](https://www.reddit.com/r/Keychron/comments/lbk2fk/a_very_odd_workaround_for_the_rgb_software/)
|
||||
advertising a supposed way to program the lighting using somewhat sketchy-seeming third-party software.
|
||||
|
||||
Soo... (not knowing any better), I guess it's Windows VM time!
|
||||
|
||||
{{ image(src="/assets/keyboard/keyboard-windont.png", alt="Windows installation screen inside of QEMU", caption="Ah shit, here we go again") }}
|
||||
|
||||
Maybe it had something to do with the keyboard itself being unsupported, maybe it was the software,
|
||||
maybe it was USB device passthrough being weird, but the app always quit with a "no gaming device found" popup and no other useful information.
|
||||
I also tried VIA again and some other software, and had no real success with any of it.
|
||||
|
||||
Solid waste of an hour.
|
||||
|
||||
It felt like I was digging too deep into solutions for *my specific keyboard*, but how do people do this more generally?
|
||||
|
||||
# QMK Firmware
|
||||
> Your computer keyboard has a processor inside of it, similar to the one inside your computer.
|
||||
> This processor runs software that is responsible for detecting button presses and informing the computer when keys are pressed.
|
||||
> QMK Firmware fills the role of that software, detecting button presses and passing that information on to the host computer. [...]
|
||||
> QMK tries to put a lot of power into your hands by making easy things easy, and hard things possible.
|
||||
>
|
||||
> \- [QMK documentation](https://docs.qmk.fm/newbs)
|
||||
|
||||
Well, this certainly sounds more promising.
|
||||
I'm kind of upset I didn't find this earlier, to be honest.
|
||||
|
||||
Apparently putting custom firmware on a keyboard is a perfectly normal thing? Having not looked into any of this before, it felt a little daunting.
|
||||
|
||||
> Open your `keymap.c` file in your text editor.
|
||||
|
||||
Wait what?
|
||||
I need C?
|
||||
I don't... I don't do C...
|
||||
What am I even doing at this point?
|
||||
How did I get here?
|
||||
Help??? Anyone???
|
||||
|
||||
|
||||
At least the [QMK Documentation](https://docs.qmk.fm/newbs) is fairly comprehensive, and flashing custom firmware isn't *that* much of a pain, all things considered.
|
||||
They have it set up to be fairly friendly toward clueless people like me who have no idea what they're doing.
|
||||
|
||||
I wasn't interested in a custom keymap, I'm just here for the [RGB matrix effects](https://docs.qmk.fm/features/rgb_matrix#custom-rgb-matrix-effects).
|
||||
|
||||
The basic examples were pretty easy to follow, and it wasn't that hard to display a static pattern of lights.
|
||||
Doing something dynamic sounded cool, but also like a project for The Distant Future(tm).
|
||||
|
||||
## HID Communication
|
||||
Somehow, the VIA app was communicating with the keyboard to set the static color without flashing new firmware,
|
||||
so I wanted to see if I could imitate that myself.
|
||||
|
||||
Turns out QMK makes it quite easy to [send data back and forth](https://docs.qmk.fm/features/rawhid)
|
||||
between the computer and the keyboard, and after a little fiddling around, I had something promising.
|
||||
|
||||
## Final Code
|
||||
```c,linenos
|
||||
RGB_MATRIX_EFFECT(custom_colors)
|
||||
RGB_MATRIX_EFFECT(pride_flag)
|
||||
|
||||
#ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
|
||||
// yes I *know* these could be packed but no
|
||||
static uint8_t color_r = 0xFF;
|
||||
static uint8_t color_g = 0xFF;
|
||||
static uint8_t color_b = 0xFF;
|
||||
|
||||
// I'm almost positive you're not *supposed* to have this in your rgb effect definitions,
|
||||
// but uhh... it works... so, I'm not complaining
|
||||
#include "raw_hid.h"
|
||||
void raw_hid_receive(uint8_t* data, uint8_t length) {
|
||||
// this probably isn't proper idiomatic C, but whatever
|
||||
color_r = data[0];
|
||||
color_g = data[1];
|
||||
color_b = data[2];
|
||||
}
|
||||
|
||||
static bool custom_colors(effect_params_t* params) {
|
||||
RGB_MATRIX_USE_LIMITS(led_min, led_max)
|
||||
for (uint8_t i = led_min; i < led_max; i++) {
|
||||
rgb_matrix_set_color(i,
|
||||
color_r,
|
||||
color_g,
|
||||
color_b
|
||||
);
|
||||
}
|
||||
return rgb_matrix_check_finished_leds(led_max);
|
||||
}
|
||||
|
||||
|
||||
// simple static effect, just for fun
|
||||
static bool pride_flag(effect_params_t* params) {
|
||||
RGB_MATRIX_USE_LIMITS(led_min, led_max);
|
||||
for (uint8_t i = led_min; i < led_max; i++) {
|
||||
int16_t y = g_led_config.point[i].y;
|
||||
// hardcoded y values found through trial and error,
|
||||
// and are probably specific to my particular keyboard model
|
||||
// there's almost certainly a better way, but this Works(tm)
|
||||
//
|
||||
// tbe colors are more or less completely eyeballed since the
|
||||
// color accuracy of this keyboard is garbage
|
||||
if (y <= 13) rgb_matrix_set_color(i, 0x00, 0x00, 0x00);
|
||||
else if (y <= 26) rgb_matrix_set_color(i, 0x2B, 0x9E, 0xFA);
|
||||
else if (y <= 38) rgb_matrix_set_color(i, 0xF0, 0x19, 0x18);
|
||||
else if (y <= 51) rgb_matrix_set_color(i, 0xFF, 0xFF, 0xFF);
|
||||
else if (y <= 63) rgb_matrix_set_color(i, 0xF5, 0x19, 0x18);
|
||||
else rgb_matrix_set_color(i, 0x2B, 0x9E, 0xFA);
|
||||
}
|
||||
return rgb_matrix_check_finished_leds(led_max);
|
||||
}
|
||||
|
||||
#endif
|
||||
```
|
||||
|
||||
I then wrote this little command-line thing to let me change the keyboard color on the fly.
|
||||
|
||||
```rs,linenos
|
||||
use hidapi::HidApi;
|
||||
use std::env;
|
||||
|
||||
fn main() {
|
||||
let color = u32::from_str_radix(&env::args().nth(1).expect("specify a color"), 16)
|
||||
.expect("failed to parse color");
|
||||
|
||||
let api = HidApi::new().unwrap();
|
||||
let device = api
|
||||
.device_list()
|
||||
.find(|device|
|
||||
// this is... less than great
|
||||
device.vendor_id() == 0x3434 &&
|
||||
device.product_id() == 0x0510 &&
|
||||
device.usage_page() == 0xFF60 &&
|
||||
device.usage() == 0x61
|
||||
).expect("failed to find keyboard")
|
||||
.open_device(&api)
|
||||
.expect("failed to open device");
|
||||
|
||||
let mut data = [0u8; 32]; // must be 32 bytes
|
||||
data[1..4].copy_from_slice(&color.to_be_bytes()[1..4]);
|
||||
device.write(&data).expect("failed to set color");
|
||||
}
|
||||
```
|
||||
|
||||
It works! Yay!
|
||||
|
||||
I'm actually surprised it was that straightforward; when the QMK docs first mentioned using C and flashing
|
||||
custom firmware on the keyboard I expected it to be a *lot* worse than it actually ended up being.
|
||||
|
||||
# Conclusion
|
||||
This was a bit of an adventure.
|
||||
I only barely scratched the surface when it comes to QMK, but it's still super cool to see something like this actually *work*.
|
||||
|
||||
There's clearly a lot more you can do with custom firmware, especially considering HID communication.
|
||||
I can imagine someone doing all sorts of cool things with different keys lighting up to signal different things.
|
||||
Maybe a push-to-talk key (for e.g. Discord) with a colorful status indicator?
|
||||
|
||||
I'm curious what kind of crazy stuff people have come up with.
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue