1646c0f26c
* Add Per Key functionality for AutoShift (#11536) * LED Matrix: Reactive effect buffers & advanced indicators (#12588) * [Keyboard] kint36: switch to sym_eager_pk debouncing (#12626) * [Keyboard] kint2pp: reduce input latency by ≈10ms (#12625) * LED Matrix: Split (#12633) * [CI] Format code according to conventions (#12650) * feat: infinite timeout for leader key (#6580) * feat: implement leader_no_timeout logic * docs(leader_key): infinite leader timeout docs * Format code according to conventions (#12680) * Update ADC driver for STM32F1xx, STM32F3xx, STM32F4xx (#12403) * Fix default ADC_RESOLUTION for ADCv3 (and ADCv4) Recent ChibiOS update removed ADC_CFGR1_RES_10BIT from the ADCv3 headers (that macro should not have been there, because ADCv3 has CFGR instead of CFGR1). Fix the default value for ADC_RESOLUTION to use ADC_CFGR_RES_10BITS if it is defined (that name is used for ADCv3 and ADCv4). * Update ADC docs to match the actually used resolution ADC driver for ChibiOS actually uses the 10-bit resolution by default (probably to match AVR); fix the documentation accordingly. Also add both ADC_CFGR_RES_10BITS and ADC_CFGR1_RES_10BIT constants (these names differ according to the ADC implementation in the particular MCU). * Fix pinToMux() for B12 and B13 on STM32F3xx Testing on STM32F303CCT6 revealed that the ADC mux values for B12 and B13 pins were wrong. * Add support for all possible analog pins on STM32F1xx Added ADC mux values for pins A0...A7, B0, B1, C0...C5 on STM32F1xx (they are the same at least for STM32F103x8 and larger F103 devices, and also F102, F105, F107 families). Actually tested on STM32F103C8T6 (therefore pins C0...C5 were not tested). Pins F6...F10, which are present on STM32F103x[C-G] in 144-pin packages, cannot be supported at the moment, because those pins are connected only to ADC3, but the ChibiOS ADC driver for STM32F1xx supports only ADC1. * Add support for all possible analog pins on STM32F4xx Added ADC mux values for pins A0...A7, B0, B1, C0...C5 and optionally F3...F10 (if STM32_ADC_USE_ADC3 is enabled). These mux values are apparently the same for all F4xx devices, except some smaller devices may not have ADC3. Actually tested on STM32F401CCU6, STM32F401CEU6, STM32F411CEU6 (using various WeAct “Blackpill” boards); only pins A0...A7, B0, B1 were tested. Pins F3...F10 are inside `#if STM32_ADC_USE_ADC3` because some devices which don't have ADC3 also don't have the GPIOF port, therefore the code which refers to Fx pins does not compile. * Fix STM32F3xx ADC mux table in documentation The ADC driver documentation had some errors in the mux table for STM32F3xx. Fix this table to match the datasheet and the actual code (mux settings for B12 and B13 were also tested on a real STM32F303CCT6 chip). * Add STM32F1xx ADC pins to the documentation * Add STM32F4xx ADC pins to the documentation * Add initial support for tinyuf2 bootloader (when hosted on F411 blackpill) (#12600) * Add support for jumping to tinyuf2 bootloader. Adds blackpill UF2 example. * Update flashing.md * Update chconf.h * Update config.h * Update halconf.h * Update mcuconf.h * eeprom driver: Refactor where eeprom driver initialisation (and EEPROM emulation initialisation) occurs to make it non-target-specific. (#12671) * Add support for MCU = STM32F446 (#12619) * Add support for MCU = STM32F446 * Update platforms/chibios/GENERIC_STM32_F446XE/configs/config.h * Restore mcuconf.h to the one used by RT-STM32F446RE-NUCLEO64 * stm32f446: update mcuconf.h and board.h for 16MHz operation, with USB enabled, and other peripherals disabled. * Format code according to conventions (#12682) * Format code according to conventions (#12687) * Add STM32L433 and L443 support (#12063) * initial L433 commit * change to XC * fix L433 * disable all peripherals * update system and peripheral clocks * 433 change * use its own board files * revert its own board files * l433 specific change * fix stm32l432xx define * remove duplicate #define * fix bootloader jump * move to L443xx and add i2c2, spi2, usart3 to mcuconf.h * move to L443 * move to L443 * fix sdmmc in mcuconf.h * include STM32L443 * add L443 * Include L443 in compatible microcontrollers * Include L443 in compatible microcontrollers * Update config bootloader jump description * Update ChibiOS define reasoning * Update quantum/mcu_selection.mk * fix git conflict * Updated Function96 with V2 files and removed chconf.h and halconf.h (#12613) * Fix bad PR merge for #6580. (#12721) * Change RGB/LED Matrix to use a simple define for USB suspend (#12697) * [CI] Format code according to conventions (#12731) * Fixing transport's led/rgb matrix suspend state logic (#12770) * [CI] Format code according to conventions (#12772) * Fix comment parsing (#12750) * Added OLED fade out support (#12086) * fix some references to bin/qmk that slipped in (#12832) * Resolve a number of warnings in `qmk generate-api` (#12833) * New command: qmk console (#12828) * stash poc * stash * tidy up implementation * Tidy up slightly for review * Tidy up slightly for review * Bodge environment to make tests pass * Refactor away from asyncio due to windows issues * Filter devices * align vid/pid printing * Add hidapi to the installers * start preparing for multiple hid_listeners * udev rules for hid_listen * refactor to move closer to end state * very basic implementation of the threaded model * refactor how vid/pid/index are supplied and parsed * windows improvements * read the report directly when usage page isn't available * add per-device colors, the choice to show names or numbers, and refactor * add timestamps * Add support for showing bootloaders * tweak the color for bootloaders * Align bootloader disconnect with connect color * add support for showing all bootloaders * fix the pyusb check * tweaks * fix exception * hide a stack trace behind -v * add --no-bootloaders option * add documentation for qmk console * Apply suggestions from code review * pyformat * clean up and flesh out KNOWN_BOOTLOADERS * Remove pointless SERIAL_LINK_ENABLE rules (#12846) * Make Swap Hands use PROGMEM (#12284) This converts the array that the Swap Hands feature uses to use PROGMEM, and to read from that array, as such. Since this array never changes at runtime, there is no reason to keep it in memory. Especially for AVR boards, as memory is a precious resource. * Fix another bin/qmk reference (#12856) * [Keymap] Turn OLED off on suspend in soundmonster keymap (#10419) * Fixup build errors on `develop` branch. (#12723) * LED Matrix: Effects! (#12651) * Fix syntax error when compiling for ARM (#12866) * Remove KEYMAP and LAYOUT_kc (#12160) * alias KEYMAP to LAYOUT * remove KEYMAP and LAYOUT_kc * Add setup, clone, and env to the list of commands we allow even with broken modules (#12868) * Rename `point_t` -> `led_point_t` (#12864) * [Keyboard] updated a vendor name / fixed minor keymap issues (#12881) * Add missing LED Matrix suspend code to suspend.c (#12878) * LED Matrix: Documentation (#12685) * Deprecate `send_unicode_hex_string()` (#12602) * Fix spelling mistake regarding LED Matrix in split_common. (#12888) * [Keymap] Fix QWERTY/DVORAK status output for kzar keymap (#12895) * Use milc.subcommand.config instead of qmk.cli.config (#12915) * Use milc.subcommand.config instead * pyformat * remove the config test * Add function to allow repeated blinking of one layer (#12237) * Implement function rgblight_blink_layer_repeat to allow repeated blinking of one layer at a time * Update doc * Rework rgblight blinking according to requested change * optimize storage * Fixup housekeeping from being invoked twice per loop. (#12933) * matrix: wait for row signal to go HIGH for every row (#12945) I noticed this discrepancy (last row of the matrix treated differently than the others) when optimizing the input latency of my keyboard controller, see also https://michael.stapelberg.ch/posts/2021-05-08-keyboard-input-latency-qmk-kinesis/ Before this commit, when tuning the delays I noticed ghost key presses when pressing the F2 key, which is on the last row of the keyboard matrix: the dead_grave key, which is on the first row of the keyboard matrix, would be incorrectly detected as pressed. After this commit, all keyboard matrix rows are interpreted correctly. I suspect that my setup is more susceptible to this nuance than others because I use GPIO_INPUT_PIN_DELAY=0 and hence don’t have another delay that might mask the problem. * ensure we do not conflict with existing keymap aliases (#12976) * Add support for up to 4 IS31FL3733 drivers (#12342) * Convert Encoder callbacks to be boolean functions (#12805) * [Keyboard] Fix Terrazzo build failure (#12977) * Do not hard set config in CPTC files (#11864) * [Keyboard] Corne - Remove legacy revision support (#12226) * [Keymap] Update to Drashna keymap and user code (based on develop) (#12936) * Add Full-duplex serial driver for ARM boards (#9842) * Document LED_MATRIX_FRAMEBUFFER_EFFECTS (#12987) * Backlight: add defines for default level and breathing state (#12560) * Add dire message about LUFA mass storage bootloader (#13014) * [Keyboard] Remove redundant legacy and common headers for crkbd (#13023) Was causing compiler errors on some systems. * Fix keyboards/keymaps for boolean encoder callback changes (#12985) * `backlight.c`: include `eeprom.h` (#13024) * Add changelog for 2021-05-29 Breaking Changes merge (#12939) * Add ChangeLog for 2021-05-29 Breaking Changes Merge: initial version * Add recent develop changes * Sort recent develop changes * Remove sections for ChibiOS changes per tzarc No ChibiOS changes this round. * Add and sort recent develop changes * add notes about keyboard moves/deletions * import changelog for PR 12172 Documents the change to BOOTMAGIC_ENABLE. * update section headings * re-sort changelog * add additional note regarding Bootmagic changes * remove changelog timestamp * update dates in main Breaking Changes docs * fix broken section anchors in previous changelogs * add link to backlight/eeprom patch to changelog * highlight some more changes * link PRs from section headers * Restore standard readme * run: qmk cformat --core-only
560 lines
34 KiB
Markdown
560 lines
34 KiB
Markdown
# RGB Lighting
|
|
|
|
QMK has the ability to control RGB LEDs attached to your keyboard. This is commonly called *underglow*, due to the LEDs often being mounted on the bottom of the keyboard, producing a nice diffused effect when combined with a translucent case.
|
|
|
|
![Planck with RGB Underglow](https://raw.githubusercontent.com/qmk/qmk_firmware/3774a7fcdab5544fc787f4c200be05fcd417e31f/keyboards/planck/keymaps/yang/planck-with-rgb-underglow.jpg)
|
|
|
|
Some keyboards come with RGB LEDs preinstalled. Others must have them installed after the fact. See the [Hardware Modification](#hardware-modification) section for information on adding RGB lighting to your keyboard.
|
|
|
|
Currently QMK supports the following addressable LEDs (however, the white LED in RGBW variants is not supported):
|
|
|
|
* WS2811, WS2812, WS2812B, WS2812C, etc.
|
|
* SK6812, SK6812MINI, SK6805
|
|
* APA102
|
|
|
|
These LEDs are called "addressable" because instead of using a wire per color, each LED contains a small microchip that understands a special protocol sent over a single wire. The chip passes on the remaining data to the next LED, allowing them to be chained together. In this way, you can easily control the color of the individual LEDs.
|
|
|
|
## Usage
|
|
|
|
On keyboards with onboard RGB LEDs, it is usually enabled by default. If it is not working for you, check that your `rules.mk` includes the following:
|
|
|
|
```make
|
|
RGBLIGHT_ENABLE = yes
|
|
```
|
|
|
|
For APA102 LEDs, add the following to your `rules.mk`:
|
|
|
|
```make
|
|
RGBLIGHT_ENABLE = yes
|
|
RGBLIGHT_DRIVER = APA102
|
|
```
|
|
|
|
At minimum you must define the data pin your LED strip is connected to, and the number of LEDs in the strip, in your `config.h`. For APA102 LEDs, you must also define the clock pin. If your keyboard has onboard RGB LEDs, and you are simply creating a keymap, you usually won't need to modify these.
|
|
|
|
|Define |Description |
|
|
|---------------|---------------------------------------------------------------------------------------------------------|
|
|
|`RGB_DI_PIN` |The pin connected to the data pin of the LEDs |
|
|
|`RGB_CI_PIN` |The pin connected to the clock pin of the LEDs (APA102 only) |
|
|
|`RGBLED_NUM` |The number of LEDs connected |
|
|
|`RGBLED_SPLIT` |(Optional) For split keyboards, the number of LEDs connected on each half directly wired to `RGB_DI_PIN` |
|
|
|
|
Then you should be able to use the keycodes below to change the RGB lighting to your liking.
|
|
|
|
### Color Selection
|
|
|
|
QMK uses [Hue, Saturation, and Value](https://en.wikipedia.org/wiki/HSL_and_HSV) to select colors rather than RGB. The color wheel below demonstrates how this works.
|
|
|
|
<img src="gitbook/images/color-wheel.svg" alt="HSV Color Wheel" width="250"/>
|
|
|
|
Changing the **Hue** cycles around the circle.<br>
|
|
Changing the **Saturation** moves between the inner and outer sections of the wheel, affecting the intensity of the color.<br>
|
|
Changing the **Value** sets the overall brightness.<br>
|
|
|
|
![QMK Color Wheel with HSV Values](https://i.imgur.com/vkYVo66.jpg)
|
|
|
|
## Keycodes
|
|
|
|
|Key |Aliases |Description |
|
|
|-------------------|----------|--------------------------------------------------------------------|
|
|
|`RGB_TOG` | |Toggle RGB lighting on or off |
|
|
|`RGB_MODE_FORWARD` |`RGB_MOD` |Cycle through modes, reverse direction when Shift is held |
|
|
|`RGB_MODE_REVERSE` |`RGB_RMOD`|Cycle through modes in reverse, forward direction when Shift is held|
|
|
|`RGB_HUI` | |Increase hue, decrease hue when Shift is held |
|
|
|`RGB_HUD` | |Decrease hue, increase hue when Shift is held |
|
|
|`RGB_SAI` | |Increase saturation, decrease saturation when Shift is held |
|
|
|`RGB_SAD` | |Decrease saturation, increase saturation when Shift is held |
|
|
|`RGB_VAI` | |Increase value (brightness), decrease value when Shift is held |
|
|
|`RGB_VAD` | |Decrease value (brightness), increase value when Shift is held |
|
|
|`RGB_MODE_PLAIN` |`RGB_M_P `|Static (no animation) mode |
|
|
|`RGB_MODE_BREATHE` |`RGB_M_B` |Breathing animation mode |
|
|
|`RGB_MODE_RAINBOW` |`RGB_M_R` |Rainbow animation mode |
|
|
|`RGB_MODE_SWIRL` |`RGB_M_SW`|Swirl animation mode |
|
|
|`RGB_MODE_SNAKE` |`RGB_M_SN`|Snake animation mode |
|
|
|`RGB_MODE_KNIGHT` |`RGB_M_K` |"Knight Rider" animation mode |
|
|
|`RGB_MODE_XMAS` |`RGB_M_X` |Christmas animation mode |
|
|
|`RGB_MODE_GRADIENT`|`RGB_M_G` |Static gradient animation mode |
|
|
|`RGB_MODE_RGBTEST` |`RGB_M_T` |Red, Green, Blue test animation mode |
|
|
|`RGB_MODE_TWINKLE` |`RGB_M_TW`|Twinkle animation mode |
|
|
|
|
!> By default, if you have both the RGB Light and the [RGB Matrix](feature_rgb_matrix.md) feature enabled, these keycodes will work for both features, at the same time. You can disable the keycode functionality by defining the `*_DISABLE_KEYCODES` option for the specific feature.
|
|
|
|
|
|
## Configuration
|
|
|
|
Your RGB lighting can be configured by placing these `#define`s in your `config.h`:
|
|
|
|
|Define |Default |Description |
|
|
|---------------------------|----------------------------|---------------------------------------------------------------------------------------------------------------------------|
|
|
|`RGBLIGHT_HUE_STEP` |`10` |The number of steps to cycle through the hue by |
|
|
|`RGBLIGHT_SAT_STEP` |`17` |The number of steps to increment the saturation by |
|
|
|`RGBLIGHT_VAL_STEP` |`17` |The number of steps to increment the brightness by |
|
|
|`RGBLIGHT_LIMIT_VAL` |`255` |The maximum brightness level |
|
|
|`RGBLIGHT_SLEEP` |*Not defined* |If defined, the RGB lighting will be switched off when the host goes to sleep |
|
|
|`RGBLIGHT_SPLIT` |*Not defined* |If defined, synchronization functionality for split keyboards is added |
|
|
|`RGBLIGHT_DISABLE_KEYCODES`|*Not defined* |If defined, disables the ability to control RGB Light from the keycodes. You must use code functions to control the feature|
|
|
|`RGBLIGHT_DEFAULT_MODE` |`RGBLIGHT_MODE_STATIC_LIGHT`|The default mode to use upon clearing the EEPROM |
|
|
|`RGBLIGHT_DEFAULT_HUE` |`0` (red) |The default hue to use upon clearing the EEPROM |
|
|
|`RGBLIGHT_DEFAULT_SAT` |`UINT8_MAX` (255) |The default saturation to use upon clearing the EEPROM |
|
|
|`RGBLIGHT_DEFAULT_VAL` |`RGBLIGHT_LIMIT_VAL` |The default value (brightness) to use upon clearing the EEPROM |
|
|
|`RGBLIGHT_DEFAULT_SPD` |`0` |The default speed to use upon clearing the EEPROM |
|
|
|
|
## Effects and Animations
|
|
|
|
Not only can this lighting be whatever color you want,
|
|
if `RGBLIGHT_EFFECT_xxxx` or `RGBLIGHT_ANIMATIONS` is defined, you also have a number of animation modes at your disposal:
|
|
|
|
|Mode number symbol |Additional number |Description |
|
|
|-----------------------------|-------------------|---------------------------------------|
|
|
|`RGBLIGHT_MODE_STATIC_LIGHT` | *None* |Solid color (this mode is always enabled) |
|
|
|`RGBLIGHT_MODE_BREATHING` | 0,1,2,3 |Solid color breathing |
|
|
|`RGBLIGHT_MODE_RAINBOW_MOOD` | 0,1,2 |Cycling rainbow |
|
|
|`RGBLIGHT_MODE_RAINBOW_SWIRL`| 0,1,2,3,4,5 |Swirling rainbow |
|
|
|`RGBLIGHT_MODE_SNAKE` | 0,1,2,3,4,5 |Snake |
|
|
|`RGBLIGHT_MODE_KNIGHT` | 0,1,2 |Knight |
|
|
|`RGBLIGHT_MODE_CHRISTMAS` | *None* |Christmas |
|
|
|`RGBLIGHT_MODE_STATIC_GRADIENT`| 0,1,..,9 |Static gradient |
|
|
|`RGBLIGHT_MODE_RGB_TEST` | *None* |RGB Test |
|
|
|`RGBLIGHT_MODE_ALTERNATING` | *None* |Alternating |
|
|
|`RGBLIGHT_MODE_TWINKLE` | 0,1,2,3,4,5 |Twinkle |
|
|
|
|
Check out [this video](https://youtube.com/watch?v=VKrpPAHlisY) for a demonstration.
|
|
|
|
Note: For versions older than 0.6.117, The mode numbers were written directly. In `quantum/rgblight.h` there is a contrast table between the old mode number and the current symbol.
|
|
|
|
### Effect and Animation Toggles
|
|
|
|
Use these defines to add or remove animations from the firmware. When you are running low on flash space, it can be helpful to disable animations you are not using.
|
|
|
|
|Define |Default |Description |
|
|
|------------------------------------|-------------|-------------------------------------------------------------------------|
|
|
|`RGBLIGHT_ANIMATIONS` |*Not defined*|Enable all additional animation modes. |
|
|
|`RGBLIGHT_EFFECT_ALTERNATING` |*Not defined*|Enable alternating animation mode. |
|
|
|`RGBLIGHT_EFFECT_BREATHING` |*Not defined*|Enable breathing animation mode. |
|
|
|`RGBLIGHT_EFFECT_CHRISTMAS` |*Not defined*|Enable christmas animation mode. |
|
|
|`RGBLIGHT_EFFECT_KNIGHT` |*Not defined*|Enable knight animation mode. |
|
|
|`RGBLIGHT_EFFECT_RAINBOW_MOOD` |*Not defined*|Enable rainbow mood animation mode. |
|
|
|`RGBLIGHT_EFFECT_RAINBOW_SWIRL` |*Not defined*|Enable rainbow swirl animation mode. |
|
|
|`RGBLIGHT_EFFECT_RGB_TEST` |*Not defined*|Enable RGB test animation mode. |
|
|
|`RGBLIGHT_EFFECT_SNAKE` |*Not defined*|Enable snake animation mode. |
|
|
|`RGBLIGHT_EFFECT_STATIC_GRADIENT` |*Not defined*|Enable static gradient mode. |
|
|
|`RGBLIGHT_EFFECT_TWINKLE` |*Not defined*|Enable twinkle animation mode. |
|
|
|
|
### Effect and Animation Settings
|
|
|
|
The following options are used to tweak the various animations:
|
|
|
|
|Define |Default |Description |
|
|
|------------------------------------|-------------|-----------------------------------------------------------------------------------------------|
|
|
|`RGBLIGHT_EFFECT_BREATHE_CENTER` |*Not defined*|If defined, used to calculate the curve for the breathing animation. Valid values are 1.0 to 2.7 |
|
|
|`RGBLIGHT_EFFECT_BREATHE_MAX` |`255` |The maximum brightness for the breathing mode. Valid values are 1 to 255 |
|
|
|`RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL`|`40` |How long (in milliseconds) to wait between animation steps for the "Christmas" animation |
|
|
|`RGBLIGHT_EFFECT_CHRISTMAS_STEP` |`2` |The number of LEDs to group the red/green colors by for the "Christmas" animation |
|
|
|`RGBLIGHT_EFFECT_KNIGHT_LED_NUM` |`RGBLED_NUM` |The number of LEDs to have the "Knight" animation travel |
|
|
|`RGBLIGHT_EFFECT_KNIGHT_LENGTH` |`3` |The number of LEDs to light up for the "Knight" animation |
|
|
|`RGBLIGHT_EFFECT_KNIGHT_OFFSET` |`0` |The number of LEDs to start the "Knight" animation from the start of the strip by |
|
|
|`RGBLIGHT_RAINBOW_SWIRL_RANGE` |`255` |Range adjustment for the rainbow swirl effect to get different swirls |
|
|
|`RGBLIGHT_EFFECT_SNAKE_LENGTH` |`4` |The number of LEDs to light up for the "Snake" animation |
|
|
|`RGBLIGHT_EFFECT_TWINKLE_LIFE` |`200` |Adjusts how quickly each LED brightens and dims when twinkling (in animation steps) |
|
|
|`RGBLIGHT_EFFECT_TWINKLE_PROBABILITY`|`1/127` |Adjusts how likely each LED is to twinkle (on each animation step) |
|
|
|
|
### Example Usage to Reduce Memory Footprint
|
|
1. Remove `RGBLIGHT_ANIMATIONS` from `config.h`.
|
|
1. Selectively add the animations you want to enable. The following would enable two animations and save about 4KiB:
|
|
|
|
```diff
|
|
#undef RGBLED_NUM
|
|
-#define RGBLIGHT_ANIMATIONS
|
|
+#define RGBLIGHT_EFFECT_STATIC_GRADIENT
|
|
+#define RGBLIGHT_EFFECT_RAINBOW_SWIRL
|
|
#define RGBLED_NUM 12
|
|
#define RGBLIGHT_HUE_STEP 8
|
|
#define RGBLIGHT_SAT_STEP 8
|
|
```
|
|
|
|
### Animation Speed
|
|
|
|
You can also modify the speeds that the different modes animate at:
|
|
|
|
Here is a quick demo on Youtube (with NPKC KC60) (https://www.youtube.com/watch?v=VKrpPAHlisY).
|
|
|
|
```c
|
|
// How long (in milliseconds) to wait between animation steps for each of the "Solid color breathing" animations
|
|
const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5};
|
|
|
|
// How long (in milliseconds) to wait between animation steps for each of the "Cycling rainbow" animations
|
|
const uint8_t RGBLED_RAINBOW_MOOD_INTERVALS[] PROGMEM = {120, 60, 30};
|
|
|
|
// How long (in milliseconds) to wait between animation steps for each of the "Swirling rainbow" animations
|
|
const uint8_t RGBLED_RAINBOW_SWIRL_INTERVALS[] PROGMEM = {100, 50, 20};
|
|
|
|
// How long (in milliseconds) to wait between animation steps for each of the "Snake" animations
|
|
const uint8_t RGBLED_SNAKE_INTERVALS[] PROGMEM = {100, 50, 20};
|
|
|
|
// How long (in milliseconds) to wait between animation steps for each of the "Knight" animations
|
|
const uint8_t RGBLED_KNIGHT_INTERVALS[] PROGMEM = {127, 63, 31};
|
|
|
|
// How long (in milliseconds) to wait between animation steps for each of the "Twinkle" animations
|
|
const uint8_t RGBLED_TWINKLE_INTERVALS[] PROGMEM = {50, 25, 10};
|
|
|
|
// These control which hues are selected for each of the "Static gradient" modes
|
|
const uint8_t RGBLED_GRADIENT_RANGES[] PROGMEM = {255, 170, 127, 85, 64};
|
|
```
|
|
|
|
## Lighting Layers
|
|
|
|
?> **Note:** Lighting Layers is an RGB Light feature, it will not work for RGB Matrix. See [RGB Matrix Indicators](feature_rgb_matrix.md?indicators) for details on how to do so.
|
|
|
|
By including `#define RGBLIGHT_LAYERS` in your `config.h` file you can enable lighting layers. These make
|
|
it easy to use your underglow LEDs as status indicators to show which keyboard layer is currently active, or the state of caps lock, all without disrupting any animations. [Here's a video](https://youtu.be/uLGE1epbmdY) showing an example of what you can do.
|
|
|
|
### Defining Lighting Layers :id=defining-lighting-layers
|
|
|
|
By default, 8 layers are possible. This can be expanded to as many as 32 by overriding the definition of `RGBLIGHT_MAX_LAYERS` in `config.h` (e.g. `#define RGBLIGHT_MAX_LAYERS 32`). Please note, if you use a split keyboard, you will need to flash both sides of the split after changing this. Also, increasing the maximum will increase the firmware size, and will slow sync on split keyboards.
|
|
|
|
To define a layer, we modify `keymap.c` to list the LED ranges and the colors we want to overlay on them using an array of `rgblight_segment_t` using the `RGBLIGHT_LAYER_SEGMENTS` macro. We can define multiple layers and enable/disable them independently:
|
|
|
|
```c
|
|
// Light LEDs 6 to 9 and 12 to 15 red when caps lock is active. Hard to ignore!
|
|
const rgblight_segment_t PROGMEM my_capslock_layer[] = RGBLIGHT_LAYER_SEGMENTS(
|
|
{6, 4, HSV_RED}, // Light 4 LEDs, starting with LED 6
|
|
{12, 4, HSV_RED} // Light 4 LEDs, starting with LED 12
|
|
);
|
|
// Light LEDs 9 & 10 in cyan when keyboard layer 1 is active
|
|
const rgblight_segment_t PROGMEM my_layer1_layer[] = RGBLIGHT_LAYER_SEGMENTS(
|
|
{9, 2, HSV_CYAN}
|
|
);
|
|
// Light LEDs 11 & 12 in purple when keyboard layer 2 is active
|
|
const rgblight_segment_t PROGMEM my_layer2_layer[] = RGBLIGHT_LAYER_SEGMENTS(
|
|
{11, 2, HSV_PURPLE}
|
|
);
|
|
// Light LEDs 13 & 14 in green when keyboard layer 3 is active
|
|
const rgblight_segment_t PROGMEM my_layer3_layer[] = RGBLIGHT_LAYER_SEGMENTS(
|
|
{13, 2, HSV_GREEN}
|
|
);
|
|
// etc..
|
|
```
|
|
|
|
We combine these layers into an array using the `RGBLIGHT_LAYERS_LIST` macro, and assign it to the `rgblight_layers` variable during keyboard setup. Note that you can only define up to 8 lighting layers. Any extra layers will be ignored. Since the different lighting layers overlap, the order matters in the array, with later layers taking precedence:
|
|
|
|
```c
|
|
// Now define the array of layers. Later layers take precedence
|
|
const rgblight_segment_t* const PROGMEM my_rgb_layers[] = RGBLIGHT_LAYERS_LIST(
|
|
my_capslock_layer,
|
|
my_layer1_layer, // Overrides caps lock layer
|
|
my_layer2_layer, // Overrides other layers
|
|
my_layer3_layer // Overrides other layers
|
|
);
|
|
|
|
void keyboard_post_init_user(void) {
|
|
// Enable the LED layers
|
|
rgblight_layers = my_rgb_layers;
|
|
}
|
|
```
|
|
Note: For split keyboards with two controllers, both sides need to be flashed when updating the contents of rgblight_layers.
|
|
|
|
### Enabling and disabling lighting layers :id=enabling-lighting-layers
|
|
|
|
Everything above just configured the definition of each lighting layer.
|
|
We can now enable and disable the lighting layers whenever the state of the keyboard changes:
|
|
|
|
```c
|
|
bool led_update_user(led_t led_state) {
|
|
rgblight_set_layer_state(0, led_state.caps_lock);
|
|
return true;
|
|
}
|
|
|
|
layer_state_t default_layer_state_set_user(layer_state_t state) {
|
|
rgblight_set_layer_state(1, layer_state_cmp(state, _DVORAK));
|
|
return state;
|
|
}
|
|
|
|
layer_state_t layer_state_set_user(layer_state_t state) {
|
|
rgblight_set_layer_state(2, layer_state_cmp(state, _FN));
|
|
rgblight_set_layer_state(3, layer_state_cmp(state, _ADJUST));
|
|
return state;
|
|
}
|
|
```
|
|
|
|
### Lighting layer blink :id=lighting-layer-blink
|
|
|
|
By including `#define RGBLIGHT_LAYER_BLINK` in your `config.h` file you can turn a lighting
|
|
layer on for a specified duration. Once the specified number of milliseconds has elapsed
|
|
the layer will be turned off. This is useful, e.g., if you want to acknowledge some
|
|
action (e.g. toggling some setting):
|
|
|
|
```c
|
|
const rgblight_segment_t PROGMEM _yes_layer[] = RGBLIGHT_LAYER_SEGMENTS( {9, 6, HSV_GREEN} );
|
|
const rgblight_segment_t PROGMEM _no_layer[] = RGBLIGHT_LAYER_SEGMENTS( {9, 6, HSV_RED} );
|
|
|
|
const rgblight_segment_t* const PROGMEM _rgb_layers[] =
|
|
RGBLIGHT_LAYERS_LIST( _yes_layer, _no_layer );
|
|
|
|
void keyboard_post_init_user(void) {
|
|
rgblight_layers = _rgb_layers;
|
|
}
|
|
|
|
// Note we user post_process_record_user because we want the state
|
|
// after the flag has been flipped...
|
|
void post_process_record_user(uint16_t keycode, keyrecord_t *record) {
|
|
switch (keycode) {
|
|
case DEBUG:
|
|
rgblight_blink_layer(debug_enable ? 0 : 1, 500);
|
|
break;
|
|
|
|
case NK_TOGG:
|
|
case NK_ON:
|
|
case NK_OFF:
|
|
rgblight_blink_layer(keymap_config.nkro ? 0 : 1, 500);
|
|
break;
|
|
}
|
|
}
|
|
```
|
|
|
|
You can also use `rgblight_blink_layer_repeat` to specify the amount of times the layer is supposed to blink. Using the layers from above,
|
|
```c
|
|
void post_process_record_user(uint16_t keycode, keyrecord_t *record) {
|
|
switch (keycode) {
|
|
case DEBUG:
|
|
rgblight_blink_layer_repeat(debug_enable ? 0 : 1, 200, 3);
|
|
break;
|
|
}
|
|
}
|
|
```
|
|
would turn the layer 0 (or 1) on and off again three times when `DEBUG` is pressed.
|
|
|
|
### Overriding RGB Lighting on/off status
|
|
|
|
Normally lighting layers are not shown when RGB Lighting is disabled (e.g. with `RGB_TOG` keycode). If you would like lighting layers to work even when the RGB Lighting is otherwise off, add `#define RGBLIGHT_LAYERS_OVERRIDE_RGB_OFF` to your `config.h`.
|
|
|
|
## Functions
|
|
|
|
If you need to change your RGB lighting in code, for example in a macro to change the color whenever you switch layers, QMK provides a set of functions to assist you. See [`rgblight.h`](https://github.com/qmk/qmk_firmware/blob/master/quantum/rgblight.h) for the full list, but the most commonly used functions include:
|
|
|
|
### Utility Functions
|
|
|Function |Description |
|
|
|--------------------------------------------|-------------------------------------------------------------------|
|
|
|`sethsv(hue, sat, val, ledbuf)` |Set ledbuf to the given HSV value |
|
|
|`sethsv_raw(hue, sat, val, ledbuf)` |Set ledbuf to the given HSV value without RGBLIGHT_LIMIT_VAL check |
|
|
|`setrgb(r, g, b, ledbuf)` |Set ledbuf to the given RGB value where `r`/`g`/`b` |
|
|
|
|
### Low level Functions
|
|
|Function |Description |
|
|
|--------------------------------------------|-------------------------------------------|
|
|
|`rgblight_set()` |Flash out led buffers to LEDs |
|
|
|`rgblight_set_clipping_range(pos, num)` |Set clipping Range. see [Clipping Range](#clipping-range) |
|
|
|
|
Example:
|
|
```c
|
|
sethsv(HSV_WHITE, (LED_TYPE *)&led[0]); // led 0
|
|
sethsv(HSV_RED, (LED_TYPE *)&led[1]); // led 1
|
|
sethsv(HSV_GREEN, (LED_TYPE *)&led[2]); // led 2
|
|
rgblight_set(); // Utility functions do not call rgblight_set() automatically, so they need to be called explicitly.
|
|
```
|
|
|
|
### Effects and Animations Functions
|
|
#### effect range setting
|
|
|Function |Description |
|
|
|--------------------------------------------|------------------|
|
|
|`rgblight_set_effect_range(pos, num)` |Set Effects Range |
|
|
|
|
#### direct operation
|
|
|Function |Description |
|
|
|--------------------------------------------|-------------|
|
|
|`rgblight_setrgb_at(r, g, b, index)` |Set a single LED to the given RGB value, where `r`/`g`/`b` are between 0 and 255 and `index` is between 0 and `RGBLED_NUM` (not written to EEPROM) |
|
|
|`rgblight_sethsv_at(h, s, v, index)` |Set a single LED to the given HSV value, where `h`/`s`/`v` are between 0 and 255, and `index` is between 0 and `RGBLED_NUM` (not written to EEPROM) |
|
|
|`rgblight_setrgb_range(r, g, b, start, end)`|Set a continuous range of LEDs to the given RGB value, where `r`/`g`/`b` are between 0 and 255 and `start`(included) and `stop`(excluded) are between 0 and `RGBLED_NUM` (not written to EEPROM)|
|
|
|`rgblight_sethsv_range(h, s, v, start, end)`|Set a continuous range of LEDs to the given HSV value, where `h`/`s`/`v` are between 0 and 255, and `start`(included) and `stop`(excluded) are between 0 and `RGBLED_NUM` (not written to EEPROM)|
|
|
|`rgblight_setrgb(r, g, b)` |Set effect range LEDs to the given RGB value where `r`/`g`/`b` are between 0 and 255 (not written to EEPROM) |
|
|
|`rgblight_setrgb_master(r, g, b)` |Set the LEDs on the master side to the given RGB value, where `r`/`g`/`b` are between 0 and 255 (not written to EEPROM) |
|
|
|`rgblight_setrgb_slave(r, g, b)` |Set the LEDs on the slave side to the given RGB value, where `r`/`g`/`b` are between 0 and 255 (not written to EEPROM) |
|
|
|`rgblight_sethsv_master(h, s, v)` |Set the LEDs on the master side to the given HSV value, where `h`/`s`/`v` are between 0 and 255 (not written to EEPROM) |
|
|
|`rgblight_sethsv_slave(h, s, v)` |Set the LEDs on the slave side to the given HSV value, where `h`/`s`/`v` are between 0 and 255 (not written to EEPROM) |
|
|
|
|
Example:
|
|
```c
|
|
rgblight_sethsv_at(HSV_WHITE, 0); // led 0
|
|
rgblight_sethsv_at(HSV_RED, 1); // led 1
|
|
rgblight_sethsv_at(HSV_GREEN, 2); // led 2
|
|
// The above functions automatically calls rgblight_set(), so there is no need to call it explicitly.
|
|
// Note that it is inefficient to call repeatedly.
|
|
```
|
|
|
|
#### effect mode change
|
|
|Function |Description |
|
|
|--------------------------------------------|-------------|
|
|
|`rgblight_mode(x)` |Set the mode, if RGB animations are enabled |
|
|
|`rgblight_mode_noeeprom(x)` |Set the mode, if RGB animations are enabled (not written to EEPROM) |
|
|
|`rgblight_step()` |Change the mode to the next RGB animation in the list of enabled RGB animations |
|
|
|`rgblight_step_noeeprom()` |Change the mode to the next RGB animation in the list of enabled RGB animations (not written to EEPROM) |
|
|
|`rgblight_step_reverse()` |Change the mode to the previous RGB animation in the list of enabled RGB animations |
|
|
|`rgblight_step_reverse_noeeprom()` |Change the mode to the previous RGB animation in the list of enabled RGB animations (not written to EEPROM) |
|
|
|`rgblight_reload_from_eeprom()` |Reload the effect configuration (enabled, mode and color) from EEPROM |
|
|
|
|
#### effects mode disable/enable
|
|
|Function |Description |
|
|
|--------------------------------------------|-------------|
|
|
|`rgblight_toggle()` |Toggle effect range LEDs between on and off |
|
|
|`rgblight_toggle_noeeprom()` |Toggle effect range LEDs between on and off (not written to EEPROM) |
|
|
|`rgblight_enable()` |Turn effect range LEDs on, based on their previous state |
|
|
|`rgblight_enable_noeeprom()` |Turn effect range LEDs on, based on their previous state (not written to EEPROM) |
|
|
|`rgblight_disable()` |Turn effect range LEDs off |
|
|
|`rgblight_disable_noeeprom()` |Turn effect range LEDs off (not written to EEPROM) |
|
|
|
|
#### hue, sat, val change
|
|
|Function |Description |
|
|
|--------------------------------------------|-------------|
|
|
|`rgblight_increase_hue()` |Increase the hue for effect range LEDs. This wraps around at maximum hue |
|
|
|`rgblight_increase_hue_noeeprom()` |Increase the hue for effect range LEDs. This wraps around at maximum hue (not written to EEPROM) |
|
|
|`rgblight_decrease_hue()` |Decrease the hue for effect range LEDs. This wraps around at minimum hue |
|
|
|`rgblight_decrease_hue_noeeprom()` |Decrease the hue for effect range LEDs. This wraps around at minimum hue (not written to EEPROM) |
|
|
|`rgblight_increase_sat()` |Increase the saturation for effect range LEDs. This stops at maximum saturation |
|
|
|`rgblight_increase_sat_noeeprom()` |Increase the saturation for effect range LEDs. This stops at maximum saturation (not written to EEPROM) |
|
|
|`rgblight_decrease_sat()` |Decrease the saturation for effect range LEDs. This stops at minimum saturation |
|
|
|`rgblight_decrease_sat_noeeprom()` |Decrease the saturation for effect range LEDs. This stops at minimum saturation (not written to EEPROM) |
|
|
|`rgblight_increase_val()` |Increase the value for effect range LEDs. This stops at maximum value |
|
|
|`rgblight_increase_val_noeeprom()` |Increase the value for effect range LEDs. This stops at maximum value (not written to EEPROM) |
|
|
|`rgblight_decrease_val()` |Decrease the value for effect range LEDs. This stops at minimum value |
|
|
|`rgblight_decrease_val_noeeprom()` |Decrease the value for effect range LEDs. This stops at minimum value (not written to EEPROM) |
|
|
|`rgblight_sethsv(h, s, v)` |Set effect range LEDs to the given HSV value where `h`/`s`/`v` are between 0 and 255 |
|
|
|`rgblight_sethsv_noeeprom(h, s, v)` |Set effect range LEDs to the given HSV value where `h`/`s`/`v` are between 0 and 255 (not written to EEPROM) |
|
|
|
|
#### Speed functions
|
|
|Function |Description |
|
|
|--------------------------------------------|-------------|
|
|
|`rgblight_increase_speed()` |Increases the animation speed |
|
|
|`rgblight_increase_speed_noeeprom()` |Increases the animation speed (not written to EEPROM) |
|
|
|`rgblight_decrease_speed()` |Decreases the animation speed |
|
|
|`rgblight_decrease_speed_noeeprom()` |Decreases the animation speed (not written to EEPROM) |
|
|
|`rgblight_set_speed()` |Sets the speed. Value is between 0 and 255 |
|
|
|`rgblight_set_speed_noeeprom()` |Sets the speed. Value is between 0 and 255 (not written to EEPROM) |
|
|
|
|
|
|
#### layer functions
|
|
|Function |Description |
|
|
|--------------------------------------------|-------------|
|
|
|`rgblight_get_layer_state(i)` |Returns `true` if lighting layer `i` is enabled |
|
|
|`rgblight_set_layer_state(i, is_on)` |Enable or disable lighting layer `i` based on value of `bool is_on` |
|
|
|
|
#### query
|
|
|Function |Description |
|
|
|-----------------------|---------------------------|
|
|
|`rgblight_is_enabled()`|Gets current on/off status |
|
|
|`rgblight_get_mode()` |Gets current mode |
|
|
|`rgblight_get_hue()` |Gets current hue |
|
|
|`rgblight_get_sat()` |Gets current sat |
|
|
|`rgblight_get_val()` |Gets current val |
|
|
|`rgblight_get_speed()` |Gets current speed |
|
|
|
|
## Colors
|
|
|
|
These are shorthands to popular colors. The `RGB` ones can be passed to the `setrgb` functions, while the `HSV` ones to the `sethsv` functions.
|
|
|
|
|RGB |HSV |
|
|
|-------------------|-------------------|
|
|
|`RGB_WHITE` |`HSV_WHITE` |
|
|
|`RGB_RED` |`HSV_RED` |
|
|
|`RGB_CORAL` |`HSV_CORAL` |
|
|
|`RGB_ORANGE` |`HSV_ORANGE` |
|
|
|`RGB_GOLDENROD` |`HSV_GOLDENROD` |
|
|
|`RGB_GOLD` |`HSV_GOLD` |
|
|
|`RGB_YELLOW` |`HSV_YELLOW` |
|
|
|`RGB_CHARTREUSE` |`HSV_CHARTREUSE` |
|
|
|`RGB_GREEN` |`HSV_GREEN` |
|
|
|`RGB_SPRINGGREEN` |`HSV_SPRINGGREEN` |
|
|
|`RGB_TURQUOISE` |`HSV_TURQUOISE` |
|
|
|`RGB_TEAL` |`HSV_TEAL` |
|
|
|`RGB_CYAN` |`HSV_CYAN` |
|
|
|`RGB_AZURE` |`HSV_AZURE` |
|
|
|`RGB_BLUE` |`HSV_BLUE` |
|
|
|`RGB_PURPLE` |`HSV_PURPLE` |
|
|
|`RGB_MAGENTA` |`HSV_MAGENTA` |
|
|
|`RGB_PINK` |`HSV_PINK` |
|
|
|
|
```c
|
|
rgblight_setrgb(RGB_ORANGE);
|
|
rgblight_sethsv_noeeprom(HSV_GREEN);
|
|
rgblight_setrgb_at(RGB_GOLD, 3);
|
|
rgblight_sethsv_range(HSV_WHITE, 0, 6);
|
|
```
|
|
|
|
These are defined in [`rgblight_list.h`](https://github.com/qmk/qmk_firmware/blob/master/quantum/rgblight_list.h). Feel free to add to this list!
|
|
|
|
|
|
## Changing the order of the LEDs
|
|
|
|
If you want to make the logical order of LEDs different from the electrical connection order, you can do this by defining the `RGBLIGHT_LED_MAP` macro in your `config.h`.
|
|
|
|
Normally, the contents of the LED buffer are output to the LEDs in the same order.
|
|
<img src="https://user-images.githubusercontent.com/2170248/55743718-01866c80-5a6e-11e9-8134-25419928327a.JPG" alt="simple dicrect" width="50%"/>
|
|
|
|
By defining `RGBLIGHT_LED_MAP` as in the example below, you can specify the LED with addressing in reverse order of the electrical connection order.
|
|
|
|
```c
|
|
// config.h
|
|
|
|
#define RGBLED_NUM 4
|
|
#define RGBLIGHT_LED_MAP { 3, 2, 1, 0 }
|
|
|
|
```
|
|
<img src="https://user-images.githubusercontent.com/2170248/55743725-08ad7a80-5a6e-11e9-83ed-126a2b0209fc.JPG" alt="simple mapped" width="50%"/>
|
|
|
|
For keyboards that use the RGB LEDs as a backlight for each key, you can also define it as in the example below.
|
|
|
|
```c
|
|
// config.h
|
|
|
|
#define RGBLED_NUM 30
|
|
|
|
/* RGB LED Conversion macro from physical array to electric array */
|
|
#define LED_LAYOUT( \
|
|
L00, L01, L02, L03, L04, L05, \
|
|
L10, L11, L12, L13, L14, L15, \
|
|
L20, L21, L22, L23, L24, L25, \
|
|
L30, L31, L32, L33, L34, L35, \
|
|
L40, L41, L42, L43, L44, L45 ) \
|
|
{ \
|
|
L05, L04, L03, L02, L01, L00, \
|
|
L10, L11, L12, L13, L14, L15, \
|
|
L25, L24, L23, L22, L21, L20, \
|
|
L30, L31, L32, L33, L34, L35, \
|
|
L46, L45, L44, L43, L42, L41 \
|
|
}
|
|
|
|
/* RGB LED logical order map */
|
|
/* Top->Bottom, Right->Left */
|
|
#define RGBLIGHT_LED_MAP LED_LAYOUT( \
|
|
25, 20, 15, 10, 5, 0, \
|
|
26, 21, 16, 11, 6, 1, \
|
|
27, 22, 17, 12, 7, 2, \
|
|
28, 23, 18, 13, 8, 3, \
|
|
29, 24, 19, 14, 9, 4 )
|
|
|
|
```
|
|
## Clipping Range
|
|
|
|
Using the `rgblight_set_clipping_range()` function, you can prepare more buffers than the actual number of LEDs, and output some of the buffers to the LEDs. This is useful if you want the split keyboard to treat left and right LEDs as logically contiguous.
|
|
|
|
You can set the Clipping Range by executing the following code.
|
|
|
|
```c
|
|
// some source
|
|
rgblight_set_clipping_range(3, 4);
|
|
```
|
|
<img src="https://user-images.githubusercontent.com/2170248/55743785-2bd82a00-5a6e-11e9-9d4b-1b4ffaf4932b.JPG" alt="clip direct" width="70%"/>
|
|
|
|
In addition to setting the Clipping Range, you can use `RGBLIGHT_LED_MAP` together.
|
|
|
|
```c
|
|
// config.h
|
|
#define RGBLED_NUM 8
|
|
#define RGBLIGHT_LED_MAP { 7, 6, 5, 4, 3, 2, 1, 0 }
|
|
|
|
// some soruce
|
|
rgblight_set_clipping_range(3, 4);
|
|
```
|
|
<img src="https://user-images.githubusercontent.com/2170248/55743747-119e4c00-5a6e-11e9-91e5-013203ffae8a.JPG" alt="clip mapped" width="70%"/>
|
|
|
|
## Hardware Modification
|
|
|
|
If your keyboard lacks onboard underglow LEDs, you may often be able to solder on an RGB LED strip yourself. You will need to find an unused pin to wire to the data pin of your LED strip. Some keyboards may break out unused pins from the MCU to make soldering easier. The other two pins, VCC and GND, must also be connected to the appropriate power pins.
|