summaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/ChangeLog/20230528/PR20584.md3
-rw-r--r--docs/_summary.md2
-rw-r--r--docs/cli_commands.md19
-rw-r--r--docs/config_options.md11
-rw-r--r--docs/feature_caps_word.md20
-rw-r--r--docs/feature_combo.md33
-rw-r--r--docs/feature_converters.md8
-rw-r--r--docs/feature_dynamic_macros.md2
-rw-r--r--docs/feature_encoders.md16
-rw-r--r--docs/feature_layers.md48
-rw-r--r--docs/feature_led_matrix.md8
-rw-r--r--docs/feature_oled_driver.md119
-rw-r--r--docs/feature_pointing_device.md26
-rw-r--r--docs/feature_repeat_key.md457
-rw-r--r--docs/feature_rgb_matrix.md100
-rw-r--r--docs/feature_rgblight.md13
-rw-r--r--docs/feature_split_keyboard.md6
-rw-r--r--docs/feature_stenography.md2
-rw-r--r--docs/feature_swap_hands.md11
-rw-r--r--docs/getting_started_vagrant.md56
-rw-r--r--docs/ja/_summary.md2
-rw-r--r--docs/ja/config_options.md5
-rw-r--r--docs/ja/feature_combo.md6
-rw-r--r--docs/ja/feature_dynamic_macros.md2
-rw-r--r--docs/ja/feature_stenography.md2
-rw-r--r--docs/ja/getting_started_vagrant.md61
-rw-r--r--docs/ja/tap_hold.md28
-rw-r--r--docs/keycodes.md9
-rw-r--r--docs/mod_tap.md2
-rw-r--r--docs/newbs_building_firmware_workflow.md2
-rw-r--r--docs/quantum_painter.md24
-rw-r--r--docs/squeezing_avr.md1
-rw-r--r--docs/tap_hold.md89
-rw-r--r--docs/understanding_qmk.md2
-rw-r--r--docs/ws2812_driver.md8
-rw-r--r--docs/zh-cn/_summary.md4
-rw-r--r--docs/zh-cn/getting_started_vagrant.md61
-rw-r--r--docs/zh-cn/mod_tap.md2
38 files changed, 836 insertions, 434 deletions
diff --git a/docs/ChangeLog/20230528/PR20584.md b/docs/ChangeLog/20230528/PR20584.md
new file mode 100644
index 0000000000..e9e49f5730
--- /dev/null
+++ b/docs/ChangeLog/20230528/PR20584.md
@@ -0,0 +1,3 @@
+Two new boolean callback functions, `pre_process_record_kb` and `pre_process_record_user`, are added in this change. They are called at the beginning of `process_record`, right before `process_combo`.
+
+Similar to existing `*_kb` and `*_user` callback functions, returning `false` will halt further processing of key events. The `pre_process_record_user` function will allow user space opportunity to handle or capture an input before it undergoes quantum processing. For example, while action tapping is still resolving the tap or hold output of a mod-tap key, `pre_process_record_user` can capture the next key record of an input event that follows. That key record can be used to influence the [decision of the mod-tap](https://docs.qmk.fm/#/tap_hold) key that is currently undergoing quantum processing.
diff --git a/docs/_summary.md b/docs/_summary.md
index 01808bd675..3d9bde6b17 100644
--- a/docs/_summary.md
+++ b/docs/_summary.md
@@ -41,7 +41,6 @@
* [Keymap Overview](keymap.md)
* Development Environments
* [Docker Guide](getting_started_docker.md)
- * [Vagrant Guide](getting_started_vagrant.md)
* Flashing
* [Flashing](flashing.md)
* [Flashing ATmega32A (ps2avrgb)](flashing_bootloadhid.md)
@@ -71,6 +70,7 @@
* [Macros](feature_macros.md)
* [Mouse Keys](feature_mouse_keys.md)
* [Programmable Button](feature_programmable_button.md)
+ * [Repeat Key](feature_repeat_key.md)
* [Space Cadet Shift](feature_space_cadet.md)
* [US ANSI Shifted Keys](keycodes_us_ansi_shifted.md)
diff --git a/docs/cli_commands.md b/docs/cli_commands.md
index d759c9c35a..79fd9de575 100644
--- a/docs/cli_commands.md
+++ b/docs/cli_commands.md
@@ -165,16 +165,31 @@ qmk find -f 'processor=STM32F411'
qmk find -f 'processor=STM32F411' -f 'features.rgb_matrix=true'
```
+The following filter expressions are also supported:
+
+ - `exists(key)`: Match targets where `key` is present.
+ - `absent(key)`: Match targets where `key` is not present.
+ - `contains(key, value)`: Match targets where `key` contains `value`. Can be used for strings, arrays and object keys.
+ - `length(key, value)`: Match targets where the length of `key` is `value`. Can be used for strings, arrays and objects.
+
+You can also list arbitrary values for each matched target with `--print`:
+
+```
+qmk find -f 'processor=STM32F411' -p 'keyboard_name' -p 'features.rgb_matrix'
+```
+
**Usage**:
```
-qmk find [-h] [-km KEYMAP] [-f FILTER]
+qmk find [-h] [-km KEYMAP] [-p PRINT] [-f FILTER]
options:
-km KEYMAP, --keymap KEYMAP
The keymap name to build. Default is 'default'.
+ -p PRINT, --print PRINT
+ For each matched target, print the value of the supplied info.json key. May be passed multiple times.
-f FILTER, --filter FILTER
- Filter the list of keyboards based on the supplied value in rules.mk. Matches info.json structure, and accepts the formats 'features.rgblight=true' or 'exists(matrix_pins.direct)'. May be passed multiple times, all filters need to match. Value may include wildcards such as '*' and '?'.
+ Filter the list of keyboards based on their info.json data. Accepts the formats key=value, function(key), or function(key,value), eg. 'features.rgblight=true'. Valid functions are 'absent', 'contains', 'exists' and 'length'. May be passed multiple times; all filters need to match. Value may include wildcards such as '*' and '?'.
```
## `qmk console`
diff --git a/docs/config_options.md b/docs/config_options.md
index 5bfb7c5d58..4698260118 100644
--- a/docs/config_options.md
+++ b/docs/config_options.md
@@ -150,7 +150,7 @@ If you define these options you will enable the associated feature, which may in
* `#define TAPPING_TERM_PER_KEY`
* enables handling for per key `TAPPING_TERM` settings
* `#define RETRO_TAPPING`
- * tap anyway, even after TAPPING_TERM, if there was no other key interruption between press and release
+ * tap anyway, even after `TAPPING_TERM`, if there was no other key interruption between press and release
* See [Retro Tapping](tap_hold.md#retro-tapping) for details
* `#define RETRO_TAPPING_PER_KEY`
* enables handling for per key `RETRO_TAPPING` settings
@@ -161,9 +161,6 @@ If you define these options you will enable the associated feature, which may in
* See [Permissive Hold](tap_hold.md#permissive-hold) for details
* `#define PERMISSIVE_HOLD_PER_KEY`
* enabled handling for per key `PERMISSIVE_HOLD` settings
-* `#define IGNORE_MOD_TAP_INTERRUPT`
- * makes it possible to do rolling combos (zx) with keys that convert to other keys on hold, by enforcing the `TAPPING_TERM` for both keys.
- * See [Ignore Mod Tap Interrupt](tap_hold.md#ignore-mod-tap-interrupt) for details
* `#define QUICK_TAP_TERM 100`
* tap-then-hold timing to use a dual role key to repeat keycode
* See [Quick Tap Term](tap_hold.md#quick-tap-term)
@@ -189,8 +186,6 @@ If you define these options you will enable the associated feature, which may in
* how long before oneshot times out
* `#define ONESHOT_TAP_TOGGLE 2`
* how many taps before oneshot toggle is triggered
-* `#define COMBO_COUNT 2`
- * Set this to the number of combos that you're using in the [Combo](feature_combo.md) feature. Or leave it undefined and programmatically set the count.
* `#define COMBO_TERM 200`
* how long for the Combo keys to be detected. Defaults to `TAPPING_TERM` if not defined.
* `#define COMBO_MUST_HOLD_MODS`
@@ -217,7 +212,7 @@ If you define these options you will enable the associated feature, which may in
## RGB Light Configuration
-* `#define RGB_DI_PIN D7`
+* `#define WS2812_DI_PIN D7`
* pin the DI on the WS2812 is hooked-up to
* `#define RGBLIGHT_LAYERS`
* Lets you define [lighting layers](feature_rgblight.md?id=lighting-layers) that can be toggled on or off. Great for showing the current keyboard layer or caps lock state.
@@ -233,7 +228,7 @@ If you define these options you will enable the associated feature, which may in
* `#define RGBLIGHT_SPLIT`
* Needed if both halves of the board have RGB LEDs wired directly to the RGB output pin on the controllers instead of passing the output of the left half to the input of the right half
* `#define RGBLED_SPLIT { 6, 6 }`
- * number of LEDs connected that are directly wired to `RGB_DI_PIN` on each half of a split keyboard
+ * number of LEDs connected that are directly wired to the RGB pin on each half of a split keyboard
* First value indicates number of LEDs for left half, second value is for the right half
* When RGBLED_SPLIT is defined, RGBLIGHT_SPLIT is implicitly defined.
* `#define RGBLIGHT_HUE_STEP 12`
diff --git a/docs/feature_caps_word.md b/docs/feature_caps_word.md
index c58d1a56e2..7f726b059d 100644
--- a/docs/feature_caps_word.md
+++ b/docs/feature_caps_word.md
@@ -90,6 +90,26 @@ by defining `IS_COMMAND()` in config.h:
## Customizing Caps Word :id=customizing-caps-word
+### Invert on shift :id=invert-on-shift
+
+By default, Caps Word turns off when Shift keys are pressed, considering them as
+word-breaking. Alternatively with the `CAPS_WORD_INVERT_ON_SHIFT` option,
+pressing the Shift key continues Caps Word and inverts the shift state. This
+is convenient for uncapitalizing one or a few letters within a word, for
+example with Caps Word on, typing "D, B, Shift+A, Shift+A, S" produces "DBaaS",
+or typing "P, D, F, Shift+S" produces "PDFs".
+
+Enable it by adding in config.h
+
+```c
+#define CAPS_WORD_INVERT_ON_SHIFT
+```
+
+This option works with regular Shift keys `KC_LSFT` and `KC_RSFT`, mod-tap Shift
+keys, and one-shot Shift keys. Note that while Caps Word is on, one-shot Shift
+keys behave like regular Shift keys, and have effect only while they are held.
+
+
### Idle timeout :id=idle-timeout
Caps Word turns off automatically if no keys are pressed for
diff --git a/docs/feature_combo.md b/docs/feature_combo.md
index 075fe252ae..fd241061fb 100644
--- a/docs/feature_combo.md
+++ b/docs/feature_combo.md
@@ -4,15 +4,12 @@ The Combo feature is a chording type solution for adding custom actions. It lets
To enable this feature, you need to add `COMBO_ENABLE = yes` to your `rules.mk`.
-Additionally, in your `config.h`, you'll need to specify the number of combos that you'll be using, by adding `#define COMBO_COUNT 1` (replacing 1 with the number that you're using). It is also possible to not define this and instead set the variable `COMBO_LEN` yourself. There's a trick where we don't need to think about this variable at all. More on this later.
-
-
Then, in your `keymap.c` file, you'll need to define a sequence of keys, terminated with `COMBO_END`, and a structure to list the combination of keys, and its resulting action.
```c
const uint16_t PROGMEM test_combo1[] = {KC_A, KC_B, COMBO_END};
const uint16_t PROGMEM test_combo2[] = {KC_C, KC_D, COMBO_END};
-combo_t key_combos[COMBO_COUNT] = {
+combo_t key_combos[] = {
COMBO(test_combo1, KC_ESC),
COMBO(test_combo2, LCTL(KC_Z)), // keycodes with modifiers are possible too!
};
@@ -33,7 +30,7 @@ It is possible to overlap combos. Before, with the example below both combos wou
```c
const uint16_t PROGMEM test_combo1[] = {LSFT_T(KC_A), LT(1, KC_B), COMBO_END};
const uint16_t PROGMEM test_combo2[] = {LSFT_T(KC_A), LT(1, KC_B), KC_C, COMBO_END};
-combo_t key_combos[COMBO_COUNT] = {
+combo_t key_combos[] = {
COMBO(test_combo1, KC_ESC)
COMBO(test_combo2, KC_TAB)
};
@@ -41,17 +38,15 @@ combo_t key_combos[COMBO_COUNT] = {
## Examples
-A long list of combos can be defined in an `enum` list that ends with `COMBO_LENGTH` and you can leave `COMBO_COUNT` undefined:
+A long list of combos can be defined in an `enum` list:
```c
enum combos {
AB_ESC,
JK_TAB,
QW_SFT,
- SD_LAYER,
- COMBO_LENGTH
+ SD_LAYER
};
-uint16_t COMBO_LEN = COMBO_LENGTH; // remove the COMBO_COUNT define and use this instead!
const uint16_t PROGMEM ab_combo[] = {KC_A, KC_B, COMBO_END};
const uint16_t PROGMEM jk_combo[] = {KC_J, KC_K, COMBO_END};
@@ -72,9 +67,7 @@ For a more complicated implementation, you can use the `process_combo_event` fun
enum combo_events {
EM_EMAIL,
BSPC_LSFT_CLEAR,
- COMBO_LENGTH
};
-uint16_t COMBO_LEN = COMBO_LENGTH; // remove the COMBO_COUNT define and use this instead!
const uint16_t PROGMEM email_combo[] = {KC_E, KC_M, COMBO_END};
const uint16_t PROGMEM clear_line_combo[] = {KC_BSPC, KC_LSFT, COMBO_END};
@@ -259,18 +252,6 @@ bool combo_should_trigger(uint16_t combo_index, combo_t *combo, uint16_t keycode
}
```
-### Variable Length Combos
-If you leave `COMBO_COUNT` undefined in `config.h`, it allows you to programmatically declare the size of the Combo data structure and avoid updating `COMBO_COUNT`. Instead a variable called `COMBO_LEN` has to be set. It can be set with something similar to the following in `keymap.c`: `uint16_t COMBO_LEN = ARRAY_SIZE(key_combos);` or by adding `COMBO_LENGTH` as the *last* entry in the combo enum and then `uint16_t COMBO_LEN = COMBO_LENGTH;` as such:
-```c
-enum myCombos {
- ...,
- COMBO_LENGTH
-};
-uint16_t COMBO_LEN = COMBO_LENGTH;
-```
-Regardless of the method used to declare `COMBO_LEN`, this also requires to convert the `combo_t key_combos[COMBO_COUNT] = {...};` line to `combo_t key_combos[] = {...};`.
-
-
### Combo timer
Normally, the timer is started on the first key press and then reset on every subsequent key press within the `COMBO_TERM`.
@@ -300,10 +281,8 @@ Here's an example where a combo resolves to two modifiers, and on key releases t
```c
enum combos {
- AB_MODS,
- COMBO_LENGTH
+ AB_MODS
};
-uint16_t COMBO_LEN = COMBO_LENGTH;
const uint16_t PROGMEM ab_combo[] = {KC_A, KC_B, COMBO_END};
@@ -415,6 +394,4 @@ SUBS(TH_THE, "the", KC_T, KC_H) // SUBS uses SEND_STRING to output the give
...
```
-Now, you can update only one place to add or alter combos. You don't even need to remember to update the `COMBO_COUNT` or the `COMBO_LEN` variables at all. Everything is taken care of. Magic!
-
For small to huge ready made dictionaries of combos, you can check out http://combos.gboards.ca/.
diff --git a/docs/feature_converters.md b/docs/feature_converters.md
index ec1f3915ee..b1abfa373a 100644
--- a/docs/feature_converters.md
+++ b/docs/feature_converters.md
@@ -20,11 +20,13 @@ Currently the following converters are available:
| `promicro` | `rp2040_ce` |
| `promicro` | `elite_pi` |
| `promicro` | `helios` |
+| `promicro` | `liatris` |
| `promicro` | `michi` |
| `elite_c` | `stemcell` |
| `elite_c` | `rp2040_ce` |
| `elite_c` | `elite_pi` |
| `elite_c` | `helios` |
+| `elite_c` | `liatris` |
See below for more in depth information on each converter.
@@ -87,6 +89,7 @@ If a board currently supported in QMK uses a [Pro Micro](https://www.sparkfun.co
| [customMK Bonsai C4](https://shop.custommk.com/products/bonsai-c4-microcontroller-board) | `bonsai_c4` |
| [Elite-Pi](https://keeb.io/products/elite-pi-usb-c-pro-micro-replacement-rp2040) | `elite_pi` |
| [0xCB Helios](https://keeb.supply/products/0xcb-helios) | `helios` |
+| [Liatris](https://splitkb.com/products/liatris) | `liatris` |
| [Michi](https://github.com/ci-bus/michi-promicro-rp2040) | `michi` |
Converter summary:
@@ -103,6 +106,7 @@ Converter summary:
| `rp2040_ce` | `-e CONVERT_TO=rp2040_ce` | `CONVERT_TO=rp2040_ce` | `#ifdef CONVERT_TO_RP2040_CE` |
| `elite_pi` | `-e CONVERT_TO=elite_pi` | `CONVERT_TO=elite_pi` | `#ifdef CONVERT_TO_ELITE_PI` |
| `helios` | `-e CONVERT_TO=helios` | `CONVERT_TO=helios` | `#ifdef CONVERT_TO_HELIOS` |
+| `liatris` | `-e CONVERT_TO=liatris` | `CONVERT_TO=liatris` | `#ifdef CONVERT_TO_LIATRIS` |
| `michi` | `-e CONVERT_TO=michi` | `CONVERT_TO=michi` | `#ifdef CONVERT_TO_MICHI` |
### Proton C :id=proton_c
@@ -167,7 +171,7 @@ The Bonsai C4 only has one on-board LED (B2), and by default, both the Pro Micro
#define B0 PAL_LINE(GPIOA, 9)
```
-### RP2040 Community Edition - Elite-Pi and Helios :id=rp2040_ce
+### RP2040 Community Edition - Elite-Pi, Helios, and Liatris :id=rp2040_ce
Feature set currently identical to [Adafruit KB2040](#kb2040).
@@ -184,6 +188,7 @@ If a board currently supported in QMK uses an [Elite-C](https://keeb.io/products
| [STeMCell](https://github.com/megamind4089/STeMCell) | `stemcell` |
| [Elite-Pi](https://keeb.io/products/elite-pi-usb-c-pro-micro-replacement-rp2040) | `elite_pi` |
| [0xCB Helios](https://keeb.supply/products/0xcb-helios) | `helios` |
+| [Liatris](https://splitkb.com/products/liatris) | `liatris` |
Converter summary:
@@ -193,6 +198,7 @@ Converter summary:
| `rp2040_ce` | `-e CONVERT_TO=rp2040_ce` | `CONVERT_TO=rp2040_ce` | `#ifdef CONVERT_TO_RP2040_CE` |
| `elite_pi` | `-e CONVERT_TO=elite_pi` | `CONVERT_TO=elite_pi` | `#ifdef CONVERT_TO_ELITE_PI` |
| `helios` | `-e CONVERT_TO=helios` | `CONVERT_TO=helios` | `#ifdef CONVERT_TO_HELIOS` |
+| `liatris` | `-e CONVERT_TO=liatris` | `CONVERT_TO=liatris` | `#ifdef CONVERT_TO_LIATRIS` |
### STeMCell :id=stemcell_elite
diff --git a/docs/feature_dynamic_macros.md b/docs/feature_dynamic_macros.md
index f5a6952b6b..8ab1bad61c 100644
--- a/docs/feature_dynamic_macros.md
+++ b/docs/feature_dynamic_macros.md
@@ -59,7 +59,7 @@ There are a number of hooks that you can use to add custom functionality and fee
Note, that direction indicates which macro it is, with `1` being Macro 1, `-1` being Macro 2, and 0 being no macro.
-* `dynamic_macro_record_start_user(void)` - Triggered when you start recording a macro.
+* `dynamic_macro_record_start_user(int8_t direction)` - Triggered when you start recording a macro.
* `dynamic_macro_play_user(int8_t direction)` - Triggered when you play back a macro.
* `dynamic_macro_record_key_user(int8_t direction, keyrecord_t *record)` - Triggered on each keypress while recording a macro.
* `dynamic_macro_record_end_user(int8_t direction)` - Triggered when the macro recording is stopped.
diff --git a/docs/feature_encoders.md b/docs/feature_encoders.md
index 1c521a4eff..891baeefa1 100644
--- a/docs/feature_encoders.md
+++ b/docs/feature_encoders.md
@@ -81,7 +81,7 @@ Your `keymap.c` will then need an encoder mapping defined (for four layers and t
```c
#if defined(ENCODER_MAP_ENABLE)
-const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = {
+const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][NUM_DIRECTIONS] = {
[_BASE] = { ENCODER_CCW_CW(KC_MS_WH_UP, KC_MS_WH_DOWN), ENCODER_CCW_CW(KC_VOLD, KC_VOLU) },
[_LOWER] = { ENCODER_CCW_CW(RGB_HUD, RGB_HUI), ENCODER_CCW_CW(RGB_SAD, RGB_SAI) },
[_RAISE] = { ENCODER_CCW_CW(RGB_VAD, RGB_VAI), ENCODER_CCW_CW(RGB_SPD, RGB_SPI) },
@@ -102,9 +102,9 @@ Using encoder mapping pumps events through the normal QMK keycode processing pip
## Callbacks
-When not using `ENCODER_MAP_ENABLE = yes`, the callback functions can be inserted into your `<keyboard>.c`:
+?> [**Default Behaviour**](https://github.com/qmk/qmk_firmware/blob/master/quantum/encoder.c#L79-#L98): all encoders installed will function as volume up (`KC_VOLU`) on clockwise rotation and volume down (`KC_VOLD`) on counter-clockwise rotation. If you do not wish to override this, no further configuration is necessary.
-?> Those who are adding new keyboard support where encoders are enabled at the keyboard level should include basic encoder functionality at the keyboard level (`<keyboard>.c`) using the `encoder_update_kb()` function, that way it works for QMK Configuator users and exists in general.
+If you would like the alter the default behaviour, and are not using `ENCODER_MAP_ENABLE = yes`, the callback functions can be inserted into your `<keyboard>.c`:
```c
bool encoder_update_kb(uint8_t index, bool clockwise) {
@@ -113,9 +113,9 @@ bool encoder_update_kb(uint8_t index, bool clockwise) {
}
if (index == 0) { /* First encoder */
if (clockwise) {
- tap_code_delay(KC_VOLU, 10);
+ tap_code(KC_PGDN);
} else {
- tap_code_delay(KC_VOLD, 10);
+ tap_code(KC_PGUP);
}
} else if (index == 1) { /* Second encoder */
if (clockwise) {
@@ -134,9 +134,9 @@ or `keymap.c`:
bool encoder_update_user(uint8_t index, bool clockwise) {
if (index == 0) { /* First encoder */
if (clockwise) {
- tap_code_delay(KC_VOLU, 10);
+ tap_code(KC_PGDN);
} else {
- tap_code_delay(KC_VOLD, 10);
+ tap_code(KC_PGUP);
}
} else if (index == 1) { /* Second encoder */
if (clockwise) {
@@ -149,7 +149,7 @@ bool encoder_update_user(uint8_t index, bool clockwise) {
}
```
-!> If you return `true` in the keymap level `_user` function, it will allow the keyboard level encoder code to run on top of your own. Returning `false` will override the keyboard level function, if setup correctly. This is generally the safest option to avoid confusion.
+!> If you return `true` in the keymap level `_user` function, it will allow the keyboard/core level encoder code to run on top of your own. Returning `false` will override the keyboard level function, if setup correctly. This is generally the safest option to avoid confusion.
## Hardware
diff --git a/docs/feature_layers.md b/docs/feature_layers.md
index f8cb53eda4..8503603ffe 100644
--- a/docs/feature_layers.md
+++ b/docs/feature_layers.md
@@ -127,6 +127,54 @@ layer_state_t layer_state_set_user(layer_state_t state) {
}
```
+### Example: Keycode to cycle through layers
+
+This example shows how to implement a custom keycode to cycle through a range of layers.
+
+```c
+// Define the keycode, `QK_USER` avoids collisions with existing keycodes
+enum keycodes {
+ KC_CYCLE_LAYERS = QK_USER,
+};
+
+// 1st layer on the cycle
+#define LAYER_CYCLE_START 0
+// Last layer on the cycle
+#define LAYER_CYCLE_END 4
+
+// Add the behaviour of this new keycode
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case KC_CYCLE_LAYERS:
+ // Our logic will happen on presses, nothing is done on releases
+ if (!record->event.pressed) {
+ // We've already handled the keycode (doing nothing), let QMK know so no further code is run unnecessarily
+ return false;
+ }
+
+ uint8_t current_layer = get_highest_layer(layer_state);
+
+ // Check if we are within the range, if not quit
+ if (curent_layer > LAYER_CYCLE_END || current_layer < LAYER_CYCLE_START) {
+ return false;
+ }
+
+ uint8_t next_layer = current_layer + 1;
+ if (next_layer > LAYER_CYCLE_END) {
+ next_layer = LAYER_CYCLE_START;
+ }
+ layer_move(next_layer);
+ return false;
+
+ // Process other keycodes normally
+ default:
+ return true;
+ }
+}
+
+// Place `KC_CYCLE_LAYERS` as a keycode in your keymap
+```
+
Use the `IS_LAYER_ON_STATE(state, layer)` and `IS_LAYER_OFF_STATE(state, layer)` macros to check the status of a particular layer.
Outside of `layer_state_set_*` functions, you can use the `IS_LAYER_ON(layer)` and `IS_LAYER_OFF(layer)` macros to check global layer state.
diff --git a/docs/feature_led_matrix.md b/docs/feature_led_matrix.md
index 1cde9b66e1..bc86099f1f 100644
--- a/docs/feature_led_matrix.md
+++ b/docs/feature_led_matrix.md
@@ -378,13 +378,7 @@ For inspiration and examples, check out the built-in effects under `quantum/led_
## EEPROM storage :id=eeprom-storage
-The EEPROM for it is currently shared with the RGB Matrix system (it's generally assumed only one feature would be used at a time), but could be configured to use its own 32bit address with:
-
-```c
-#define EECONFIG_LED_MATRIX (uint32_t *)28
-```
-
-Where `28` is an unused index from `eeconfig.h`.
+The EEPROM for it is currently shared with the RGB Matrix system (it's generally assumed only one feature would be used at a time).
### Direct Operation :id=direct-operation
|Function |Description |
diff --git a/docs/feature_oled_driver.md b/docs/feature_oled_driver.md
index dea9cb8074..a62294b23a 100644
--- a/docs/feature_oled_driver.md
+++ b/docs/feature_oled_driver.md
@@ -2,15 +2,18 @@
## Supported Hardware
-OLED modules using SSD1306 or SH1106 driver ICs, communicating over I2C.
+OLED modules using SSD1306, SH1106 or SH1107 driver ICs, communicating over I2C or SPI.
Tested combinations:
-|IC |Size |Platform|Notes |
-|---------|------|--------|------------------------|
-|SSD1306 |128x32|AVR |Primary support |
-|SSD1306 |128x64|AVR |Verified working |
-|SSD1306 |128x32|Arm | |
-|SH1106 |128x64|AVR |No rotation or scrolling|
+|IC |Size |Platform|Notes |
+|---------|-------|--------|------------------------|
+|SSD1306 |128x32 |AVR |Primary support |
+|SSD1306 |128x64 |AVR |Verified working |
+|SSD1306 |128x32 |Arm | |
+|SH1106 |128x64 |AVR |No scrolling |
+|SH1107 |64x128 |AVR |No scrolling |
+|SH1107 |64x128 |Arm |No scrolling |
+|SH1107 |128x128|Arm |No scrolling |
Hardware configurations using Arm-based microcontrollers or different sizes of OLED modules may be compatible, but are untested.
@@ -23,15 +26,26 @@ OLED_ENABLE = yes
```
## OLED type
-|OLED Driver |Supported Device |
-|-------------------|---------------------------|
-|SSD1306 (default) |For both SSD1306 and SH1106|
+
+|OLED Driver |Supported Device |
+|-------------------|------------------------------------|
+|SSD1306 (default) |For both SSD1306, SH1106, and SH1107|
e.g.
```make
OLED_DRIVER = SSD1306
```
+|OLED Transport | |
+|---------------|------------------------------------------------|
+|i2c (default) | Uses I2C for communication with the OLED panel |
+|spi | Uses SPI for communication with the OLED panel |
+
+e.g.
+```make
+OLED_TRANSPORT = i2c
+```
+
Then in your `keymap.c` file, implement the OLED task call. This example assumes your keymap has three layers named `_QWERTY`, `_FN` and `_ADJ`:
```c
@@ -159,32 +173,57 @@ These configuration options should be placed in `config.h`. Example:
#define OLED_BRIGHTNESS 128
```
+|Define |Default |Description |
+|---------------------------|-------------------------------|---------------------------------------------------------------------------------------------------------------------|
+|`OLED_BRIGHTNESS` |`255` |The default brightness level of the OLED, from 0 to 255. |
+|`OLED_COLUMN_OFFSET` |`0` |Shift output to the right this many pixels.<br />Useful for 128x64 displays centered on a 132x64 SH1106 IC. |
+|`OLED_DISPLAY_CLOCK` |`0x80` |Set the display clock divide ratio/oscillator frequency. |
+|`OLED_FONT_H` |`"glcdfont.c"` |The font code file to use for custom fonts |
+|`OLED_FONT_START` |`0` |The starting character index for custom fonts |
+|`OLED_FONT_END` |`223` |The ending character index for custom fonts |
+|`OLED_FONT_WIDTH` |`6` |The font width |
+|`OLED_FONT_HEIGHT` |`8` |The font height (untested) |
+|`OLED_IC` |`OLED_IC_SSD1306` |Set to `OLED_IC_SH1106` or `OLED_IC_SH1107` if the corresponding controller chip is used. |
+|`OLED_FADE_OUT` |*Not defined* |Enables fade out animation. Use together with `OLED_TIMEOUT`. |
+|`OLED_FADE_OUT_INTERVAL` |`0` |The speed of fade out animation, from 0 to 15. Larger values are slower. |
+|`OLED_SCROLL_TIMEOUT` |`0` |Scrolls the OLED screen after 0ms of OLED inactivity. Helps reduce OLED Burn-in. Set to 0 to disable. |
+|`OLED_SCROLL_TIMEOUT_RIGHT`|*Not defined* |Scroll timeout direction is right when defined, left when undefined. |
+|`OLED_TIMEOUT` |`60000` |Turns off the OLED screen after 60000ms of screen update inactivity. Helps reduce OLED Burn-in. Set to 0 to disable. |
+|`OLED_UPDATE_INTERVAL` |`0` (`50` for split keyboards) |Set the time interval for updating the OLED display in ms. This will improve the matrix scan rate. |
+|`OLED_UPDATE_PROCESS_LIMIT'|`1` |Set the number of dirty blocks to render per loop. Increasing may degrade performance. |
+
+### I2C Configuration
|Define |Default |Description |
|---------------------------|-----------------|--------------------------------------------------------------------------------------------------------------------------|
|`OLED_DISPLAY_ADDRESS` |`0x3C` |The i2c address of the OLED Display |
-|`OLED_FONT_H` |`"glcdfont.c"` |The font code file to use for custom fonts |
-|`OLED_FONT_START` |`0` |The starting character index for custom fonts |
-|`OLED_FONT_END` |`223` |Th