QMK RGB 饱和度见底

问题描述 投票:0回答:2

RGB 键码

RGB_HUI
RGB_HUD
RGB_SAI
RGB_SAD
RGB_VAI
RGB_VAD
》允许我增加或减少 RGB 底光灯的色调、饱和度和值。但我希望能够按住一个键来连续更改颜色。所以我做了这些改变:

config.h

#ifdef RGBLIGHT_ENABLE
  #define RGBLIGHT_HUE_STEP 1
  #define RGBLIGHT_SAT_STEP 1
  #define RGBLIGHT_VAL_STEP 1
#endif

然后在

keymap.c
我制作了自定义键码:

enum custom_keycodes {
    KC_HUI = SAFE_RANGE,
    KC_HUD,
    KC_SAI,
    KC_SAD,
    KC_VAI,
    KC_VAD
};

并定义了一些变量:

// flags. 0 = no change, 1 = increment, -1 = decrement.
int8_t change_hue = 0;
int8_t change_saturation = 0;
int8_t change_value = 0;

// timers to control color change speed
uint16_t hue_timer = 0;
uint16_t saturation_timer = 0;
uint16_t value_timer = 0;

// seconds it takes to cycle through 0-255 or back
// technically 1 = 1.024 seconds, yielding even multiples of 4ms per tick (1024 / 256).
const int8_t hue_seconds = 5;
const int8_t saturation_seconds = 5;
const int8_t value_seconds = 5;

然后我使用键码来设置标志和计时器:

bool process_record_user(uint16_t keycode, keyrecord_t *record) {
    switch (keycode) {
        case KC_HUI:
            if (record->event.pressed) {
                hue_timer = timer_read();
                change_hue = 1;
            } else {
                change_hue = 0;
            }
            break;
        case KC_HUD:
            if (record->event.pressed) {
                hue_timer = timer_read();
                change_hue = -1;
            } else {
                change_hue = 0;
            }
            break;
        case KC_SAI:
            if (record->event.pressed) {
                saturation_timer = timer_read();
                change_saturation = 1;
            } else {
                change_saturation = 0;
            }
            break;
        case KC_SAD:
            if (record->event.pressed) {
                saturation_timer = timer_read();
                change_saturation = -1;
            } else {
                change_saturation = 0;
            }
            break;
        case KC_VAI:
            if (record->event.pressed) {
                value_timer = timer_read();
                change_value = 1;
            } else {
                change_value = 0;
            }
            break;
        case KC_VAD:
            if (record->event.pressed) {
                value_timer = timer_read();
                change_value = -1;
            } else {
                change_value = 0;
            }
            break;
    }
    return true;
}

然后我使用矩阵扫描来使用这些标志和计时器来更改颜色:

void matrix_scan_user(void) {
    switch (change_hue) {
        case 0:
            break;
        case 1:
            if (timer_elapsed(hue_timer) > (hue_seconds * 4)) {
                hue_timer = timer_read();
                rgblight_increase_hue();
            }
            break;
        case -1:
            if (timer_elapsed(hue_timer) > (hue_seconds * 4)) {
                hue_timer = timer_read();
                rgblight_decrease_hue();
            }
            break;
    }
    switch (change_saturation) {
        case 0:
            break;
        case 1:
            if (timer_elapsed(saturation_timer) > (saturation_seconds * 4)) {
                saturation_timer = timer_read();
                rgblight_increase_sat();
            }
            break;
        case -1:
            if (timer_elapsed(saturation_timer) > (saturation_seconds * 4)) {
                saturation_timer = timer_read();
                rgblight_decrease_sat();
            }
            break;
    }
    switch (change_value) {
        case 0:
            break;
        case 1:
            if (timer_elapsed(value_timer) > (value_seconds * 4)) {
                value_timer = timer_read();
                rgblight_increase_val();
            }
            break;
        case -1:
            if (timer_elapsed(value_timer) > (value_seconds * 4)) {
                value_timer = timer_read();
                rgblight_decrease_val();
            }
            break;
    }
}

根据文档,每个都应分别围绕最大/最小色调/饱和度/值。

  • 这似乎与
    KC_HUI
    KC_HUD
    的预期完全一样:如果我按住按键足够长的时间,它会绕过弯曲,并且色调会继续循环。
  • KC_SAI
    KC_VAI
    KC_VAD
    至少可以正常工作。我可以将饱和度或值增加到最大值,它就会停在那里,同样,如果我减少值,它就会停在零。
  • KC_SAD
    就是问题所在。当我按住它足够长的时间(刚刚过去白色)时,键盘就会爆炸。它变成了奇怪的橙色,没有任何作用。

作为参考,这里是 GitHub 提交,我在其中进行了所有更改,当然还有我的其余代码。

  1. 知道为什么
    KC_SAD
    会爆炸而不是停下来或绕过去吗?
  2. 知道为什么饱和度和价值都停止了,而不是像我根据阅读的文档所期望的那样回绕吗?
  3. 我是否可以更好地以不同的方式尝试整个事情(向更有经验的用户提问)?
c keyboard qmk
2个回答
1
投票

我对此进行了更多实验,并提出了一种不同的实现,该实现在添加到固件大小的代码行和字节方面更加有效。请注意,它不是定义新的自定义键码,而是劫持现有的 RGB_... 来实现新的和改进的目的:

#include <lib/lib8tion/lib8tion.h>

// flags. 0 = no change, 1 = increment, -1 = decrement.
int8_t change_hue = 0;
int8_t change_sat = 0;
int8_t change_val = 0;

// timer to control color change speed
uint16_t change_timer = 0;
const uint16_t change_tick  = 15;

void matrix_scan_user(void) {
    if (change_hue != 0 || change_val != 0 || change_sat != 0) {
        if (timer_elapsed(change_timer) > change_tick) {
            HSV hsv = rgblight_get_hsv();
            hsv.h += change_hue;
            hsv.s = change_sat > 0 ? qadd8(hsv.s, (uint8_t) change_sat) : qsub8(hsv.s, (uint8_t) -change_sat);
            hsv.v = change_val > 0 ? qadd8(hsv.v, (uint8_t) change_val) : qsub8(hsv.v, (uint8_t) -change_val);
            rgblight_sethsv_noeeprom(hsv.h, hsv.s, hsv.v);
            change_timer = timer_read();
        }
    }
}

bool process_record_user(uint16_t keycode, keyrecord_t *record) {
    if (record->event.pressed) {
        switch (keycode) {

                // clang-format off
            case RGB_HUI: change_timer = timer_read(); change_hue =  1; return false;
            case RGB_HUD: change_timer = timer_read(); change_hue = -1; return false;
            case RGB_SAI: change_timer = timer_read(); change_sat =  1; return false;
            case RGB_SAD: change_timer = timer_read(); change_sat = -1; return false;
            case RGB_VAI: change_timer = timer_read(); change_val =  1; return false;
            case RGB_VAD: change_timer = timer_read(); change_val = -1; return false;
                // clang-format on
        }
    } else {
        bool rgb_done = false;
        switch (keycode) {
            case RGB_HUI:
            case RGB_HUD:
                change_hue = 0;
                rgb_done   = true;
                break;
            case RGB_SAI:
            case RGB_SAD:
                change_sat = 0;
                rgb_done   = true;
                break;
            case RGB_VAI:
            case RGB_VAD:
                change_val = 0;
                rgb_done   = true;
                break;
        }

        if (rgb_done) {
            HSV final = rgblight_get_hsv();
            rgblight_sethsv(final.h, final.s, final.v);
        }
    }

    return true;
}


0
投票

这是一个非常好的功能!

  1. 我将您的代码复制到我的一个键盘中,但无法重现您在
    "bomb out"
    上看到的
    KC_SAD
    行为。
  2. 文档不正确。饱和度和价值的增加/减少函数不会回绕,据我所知,它们并不打算回绕。它们的最大值为 255,底部限制为 0。我将提交 PR 来修复文档。
  3. 我在您的实现中看到的唯一重大问题是,它会导致对 eeprom 进行大量写入,这是不健康的(它们会随着时间的推移而磨损)。例如,您应该使用
    rgblight_increase_sat_noeeprom()
    来调整饱和度(及其对应的色调/饱和度和减少)。然后当您松开按键时,才可以将当前的 HSV 设置写入 eeprom(使用
    rgblight_sethsv()
    将最终值设置到 eeprom 中。
© www.soinside.com 2019 - 2024. All rights reserved.