Corne CherryでレイヤーごとにLEDを切り替える
QMKを使って、Corne Cherry(crkbd)のバックライトLEDを制御しようとしてハマったことを記録します。
やりたいこと
crkbdでレイヤーごとに点灯するLEDを切り替える。
はじめに
VIAではLEDの細かい制御はできないので、QMK Firmwareを使います。基になるキーマップは、crkbd/keymaps/defaultをコピーしたものとします。
QMKによるLED制御
QMKには、4種類のLED制御方法がありますが、今回は、RGB Lighting、RGB Matrixを試しました。どちらも、やりたいことは実現できますが、RGB Matrix
の方が、LEDアニメーションが充実しています。
共通の設定
LED制御を有効にするとファームウェアサイズを消費するので、必須ではないですが、ファームウェアサイズを削減するオプションをrules.mk
に追加しておきます。
OLED_ENABLE = yes
OLED_DRIVER = SSD1306
+ MOUSEKEY_ENABLE = no
+ EXTRAKEY_ENABLE = no
+ LTO_ENABLE = yes
この設定は、crkbd/rules.mkを上書きする設定になります。
crkbdのバックライトLED配置
0-5、27-32はアンダーグローで、バックライトLEDは以下の配置になっています。
{ 24, 23, 18, 17, 10, 9 }, { 36, 37, 44, 45, 50, 51 },
{ 25, 22, 19, 16, 11, 8 }, { 35, 38, 43, 46, 49, 52 },
{ 26, 21, 20, 15, 12, 7 }, { 34, 39, 42, 47, 48, 53 },
{ NO_LED, NO_LED, NO_LED, 14, 13, 6 }, { 33, 40, 41, NO_LED, NO_LED, NO_LED }
RGB Lightingの場合
まず、RGB Lighting
を有効化します。
+ RGBLIGHT_ENABLE = yes
+ RGB_MATRIX_ENABLE = no
RGB Lighting
には、まさにレイヤーごとにLEDを切り替えるLighting Layersが準備されているのでこれを使う設定をします。
#ifdef RGBLIGHT_ENABLE
+ #define RGBLIGHT_LAYERS
- #define RGBLIGHT_ANIMATIONS // ファームウェアサイズ削減
#undef RGBLED_NUM
- #define RGBLED_NUM 27
+ #define RGBLED_NUM 54 // 左右でユニークな番号を使って制御
+ #undef RGBLED_SPLIT
+ #define RGBLED_SPLIT { 27, 27 } // defaultだと{6, 6}バックライトLEDのみになっている
#define RGBLIGHT_LIMIT_VAL 120
#define RGBLIGHT_HUE_STEP 10
#define RGBLIGHT_SAT_STEP 17
#define RGBLIGHT_VAL_STEP 17
#endif
デフォルト設定がおかしい気がしたので、PR出してみました。
2022-01-22 追記:マージ待ちのIssue #15779がありました。RGBLED_NUM
とRGBLED_SPLIT
の設定は不要になります。
あとは、ドキュメント通り、以下のような設定をするだけです。
const rgblight_segment_t PROGMEM raise_layer[] = RGBLIGHT_LAYER_SEGMENTS(
// undergrow
{0, 6, HSV_OFF},
{27, 6, HSV_OFF},
// backlight
{6, 21, HSV_GOLD},
{33, 21, HSV_GOLD}
);
const rgblight_segment_t PROGMEM lower_layer[] = RGBLIGHT_LAYER_SEGMENTS(
// 略
);
const rgblight_segment_t* const PROGMEM my_rgb_layers[] = RGBLIGHT_LAYERS_LIST(
raise_layer,
lower_layer
);
void keyboard_post_init_user(void) {
rgblight_layers = my_rgb_layers;
}
layer_state_t layer_state_set_user(layer_state_t state) {
rgblight_set_layer_state(0, layer_state_cmp(state, _RAISE));
rgblight_set_layer_state(1, layer_state_cmp(state, _LOWER));
return state;
}
RGB Matrixの場合
keyboards/crkbdに説明がありますが、一部修正の必要があります。
まず、RGB Matrix
を有効化します。
+ RGBLIGHT_ENABLE = no
+ RGB_MATRIX_ENABLE = yes
次に、マスターのレイヤー情報をスレーブに共有する設定をします。
#ifdef RGB_MATRIX_ENABLE
+ # define SPLIT_LAYER_STATE_ENABLE
# define RGB_MATRIX_KEYPRESSES // reacts to keypresses
// 略
#endif
RGB Matrix
には、レイヤーごとにLEDを切り替える機能はないので、rgb_matrix_indicators_advanced_user
を使います。色の指定にはドキュメントにならい、RGBではなくHSVを使います。
#ifdef RGB_MATRIX_ENABLE
// 明度の上限を抑える
void set_color(int index, uint8_t hsvred, uint8_t hsvgreen, uint8_t hsvblue) {
HSV hsv = (HSV){hsvred, hsvgreen, hsvblue};
if (hsv.v > rgb_matrix_get_val()) {
hsv.v = rgb_matrix_get_val();
}
RGB rgb = hsv_to_rgb(hsv);
rgb_matrix_set_color(index, rgb.r, rgb.g, rgb.b);
}
void rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) {
// RGB_MATRIX_SOLID_COLOR(1)のときに、自作LEDロジックが動くようにする
if (rgb_matrix_get_mode() != 1) {
return;
}
// 一度全消灯
rgb_matrix_set_color_all(RGB_OFF);
// レイヤーごとにLEDを切り替える
switch (get_highest_layer(layer_state | default_layer_state)) {
case _RAISE:
if (is_keyboard_left()) {
// left
set_color(8, HSV_YELLOW);
set_color(11, HSV_YELLOW);
// ・・・
}else{
// right
set_color(37, HSV_BLUE);
set_color(44, HSV_BLUE);
// ・・・
}
break;
case _LOWER:
// 略
break;
default:
break;
}
}
#endif // RGB_MATRIX_ENABLE
以上で、レイヤーごとに点灯するLEDを切り替えることができました。
Discussion