* [style] refactor keymaps
- use four-space indent
- grid-align keycodes
- use QMK-native keycode aliases
* [style] friendly-format info.json
* [chore] remove key overlaps in layout data
* [chore] correct key sequence
* [chore] add key labels
Add `label` keys to the JSON layout data to disambiguate which keys each
object is meant to represent.
Based on the original key sizes and positions as submitted by the
maintainer.
* [docs] add layout/matrix diagram
* [refactor] rename LAYOUT to LAYOUT_all
* [enhancement] add LAYOUT_tkl_ansi_split_bs_rshift
* [enhancement] add LAYOUT_tkl_iso_split_bs_rshift
* [enhancement] enable Community Layout support
* [style] friendly-format info.json
- sort JSON keys in layouts object
- remove instances of `w: 1`
* [chore] correct layout data
* [refactor] rename LAYOUT to LAYOUT_60_tsangan_hhkb
* [enhancement] add LAYOUT_60_ansi_tsangan_split_rshift
* [enhancement] enable Community Layout support
* [bugfix] write appropropriate keymaps
Neither the `default` nor `via` keymaps were written appropriately for
this keyboard.
This commit modifies both keymaps to be appropriate for
`60_tsangan_hhkb` layout.
* [refactor] rename LAYOUT to LAYOUT_planck_mit
* [style] friendly-format info.json
* [style] refactor keymaps
- grid-align keycodes
- use four-space indent
- remove trailing whitespace
* [chore] tidy-up keyboard data in info.json
- spell-check `manufacturer` value
- use valid `url`
- reference GitHub username for `maintainer`
* [chore] tidy-up readme
- link to maintainer's GitHub account
- add Hardware Availability link
- break-out Hardware Specs into its own section
* [enhancement] enable Community Layout support
* [chore] replace product image in readme
Source repository for previous URL seems to have been deleted.
* [enhancement] remove redundant layout data
Remove the redundant layout data from the keyboard-level `info.json`.
* [enhancement] correct JSON syntax in rev1/info.json
* [enhancement] friendly-format rev1/info.json
* [enhancement] correct layout data
* fix non-default keymap compiling, initial matrix state, watchdog options
* fix: allow planck/rev7 to be used with ENCODER_ENABLE = no
* chore: update function name on all cases.
* remove old midi tone option
Co-authored-by: Ryan <fauxpark@gmail.com>
* fixes abhixec's planck keymap
* add audio enable condition to abhixec's planck keymap
* add audio enable condition to all muse includes
* Revert "add audio enable condition to all muse includes"
This reverts commit 9779e90897.
* Revert "add audio enable condition to abhixec's planck keymap"
This reverts commit 24c742a5e8.
* Revert "fixes abhixec's planck keymap"
This reverts commit 4bb085d1ff.
---------
Co-authored-by: Peter.Falken <luis@bitjester.com>
Co-authored-by: Ryan <fauxpark@gmail.com>
* [refactor] friendly-format info.json
* [enhancement] remove key overlap
Fix a key overlap in the Configurator rendering between LCtrl and Fn2.
* [enhancement] replace store links with product links
Replace URLs that point to the vendor's shop with URLs to the vendor's
product listing.
Apparently layouts with 2u keys were not correctly converted into the
`info.json` format (the old C layout macros used the arguments for such
keys multiple times to cover all possible 1u locations; this is not
supported in `info.json`, and the single matrix location for 2u keys was
chosen incorrectly in some cases). Fix the layout definitions to match
the real PCB wiring.
* refactor keymaps
- remove extra blank lines
- convert tabs to spaces
- use four-space indent
- grid-align keycodes
- use QMK-native keycode aliases
* info.json: correct layout data
* add readme.md
* info.json: correct maintainer field
Updates the value to reference the maintainer's GitHub username.
* Fork Rev. 3 to 4
* Update RGB LED positions
* Adjust RGB positions
* Enable more RGB modes
* Update copyrights
* Add license headers to keymaps
* Use same type of license header
Co-authored-by: Joel Challis <git@zvecr.com>
* Fix I2C pins
---------
Co-authored-by: Joel Challis <git@zvecr.com>
* Add an emphasis on QMK MSYS terminal
Not using MSYS terminal is a frequent user error. This change
adds an additional statement to guide users to run the first
command in MSYS itself. Edited the same statement for consistency
in the other OSes.
* Update instructions for the other operating systems
Functions in filters did not work properly except when used in the last
(or only) filter. The problem was caused by the peculiarity of the
`lambda` behavior in Python — any variables from the outer scope are
captured only by reference, therefore any subsequent reassignment of
those variables is propagated to all lambdas created earlier in the same
scope. Together with the laziness of `filter()` (it returns an iterator
which performs filtering on demand) this resulted in all function
filters using the values of the `key` and `value` variables which
correspond to the last filter in the sequence, therefore the result of
filtering was wrong if some filter with a function was not the last one
in the sequence.
Apparently the shortest way to make a Python lambda capture some
variables by value is to add arguments with default values for such
variables (default values are evaluated when the lambda is created, and
any subsequent reassignments in the outer scope no longer changes them).
This makes filters with functions work properly even when such filters
are not at the last position in the sequence.
* Add missing layout data for a handful of boards
* typo
* Add missing layouts for stoutgat
* Add missing layout for j80
* Replace missing layout with alias for wraith
* Add missing layout for matrix/me
* Add missing layout for satisfaction75/prototype
* Apply suggestions from code review
* Rename wt80-a layouts
* Rename rosa layouts
* Add missing layouts for naked48
* Add missing layouts for naked60
* Add missing layouts for uma
* Remove unused and pointless `LAYOUT_stack` for buzzard
* Add missing layout for keyboardio/model01
* Add missing layout for smk65 revf
* Fix via keymap for h60
* Add missing layout for jabberwocky/v1
* Apply suggestions from code review
* Add missing layout for m3n3van
* Add missing layout for giabalanai
* Add missing layouts for treadstone48/rev1
* Add missing layouts for squiggle
* Update keyboards/marksard/treadstone48/rev1/info.json
* add matrix_diagram.md
* info.json: apply friendly formatting
* info.json: correct layout data
Moves the position representing the Rotary Encoder to the top of the layout.
* refactor keymaps
Applies the following changes to the `default` and `via` keymaps:
- four-space indent
- use of QMK-native keycode aliases
- numerically-indexed keymap layers
- updated grid alignment of keycodes
* add LAYOUT_ansi_blocker_tsangan_wkl_split_bs
* add LAYOUT_ansi_blocker_tsangan_wkl
* add LAYOUT_iso_blocker_tsangan_wkl_split_bs
* add LAYOUT_iso_blocker_tsangan_wkl
* info.json: apply friendly formatting
* rename LAYOUT_all to LAYOUT_ortho_2x4
* info.json: update maintainer field
Use the maintainer's GitHub username instead of their display name.
* Add keyevent for combo keyrecord
* Fix formatting
* Update quantum/process_keycode/process_combo.c
Co-authored-by: Sergey Vlasov <sigprof@gmail.com>
* Add combo unit-tests and hot-fix process_record_tap_hint
...as this function tries to lookup the combo keys passed in. This will
be refactored in a later pr.
---------
Co-authored-by: Sergey Vlasov <sigprof@gmail.com>
Co-authored-by: Stefan Kerkmann <karlk90@pm.me>
* info.json: apply friendly formatting
* info.json: correct layout data
Update layout data to my best guess of the actual layout. Seems this product never went into production.
* rename LAYOUT_all to LAYOUT_ansi_split_bs_rshift
* add LAYOUT_ansi
* add matrix_diagram.md
* Apply suggestions from code review
* add matrix_diagram.md
* info.json: apply friendly formatting
* info.json: fix key overlap
Fixes the Numpad Enter key overlapping the second Numpad 0 key (bottom right of numpad).
* info.json: add matrix position [7, 1]
Adds matrix position [7, 1] to the layout data (bottom half of split Numpad Plus).
* add LAYOUT_2u_bs_275u_rshift
* add matrix_diagram.md
* info.json: apply friendly formatting
* info.json: correct layout data
* info.json: alias LAYOUT to LAYOUT_all
The PCB supports multiple layouts, but I have not been able to discover how the additional layouts are wired.
* update matrix_diagram.md (thanks yulei)
* add LAYOUT_2u_numpad_plus_enter_zero with reference keymap
* add matrix_diagram.md
* info.json: apply friendly formatting
* remove matrix position K3B
Based on photos of the keyboard and renders of the PCB, I'm not convinced it exists.
* add LAYOUT_625u_space
* add matrix_diagram.md
* info.json: apply friendly formatting
* add LAYOUT_66_ansi_split_space
* add LAYOUT_66_iso_split_space
* refactor default keymap
- use four-space indent
- use QMK-native keycode aliases directly
- use `enum` statement for layer names
- grid-align keycodes
* refactor ansi keymap
- use four-space indent
- use QMK-native keycode aliases directly
- use `enum` statement for layer names
- grid-align keycodes
* refactor iso keymap
- use four-space indent
- use QMK-native keycode aliases directly
- use `enum` statement for layer names
- grid-align keycodes
* change layout macro for ansi keymap
Refactors the `ansi` keymap to use the `LAYOUT_66_ansi_split_space` macro, and renames the keymap to `default_ansi_split_space`.
* change layout macro for iso keymap
Refactors the `iso` keymap to use the `LAYOUT_66_iso_split_space` macro, and renames the keymap to `default_iso_split_space`.
* add LAYOUT_66_ansi
The column for the spacebar key may be wrong; I was unable to find high-resolution images of the PCB.
* add LAYOUT_66_iso
The column for the spacebar key may be wrong; I was unable to find high-resolution images of the PCB.
* enable Community Layout support
* add matrix_diagram.md
* info.json: apply friendly formatting
* add matrix position [5, 2] to LAYOUT_all
The PCB supports four 1u mod keys to the left of the Spacebar, but this was not implemented in the original submission to QMK.
* add LAYOUT_ansi_split_bs
* add LAYOUT_ansi
* add LAYOUT_ansi_blocker_split_bs
* add LAYOUT_ansi_blocker
* add LAYOUT_ansi_blocker_tsangan_split_bs
* add LAYOUT_ansi_blocker_tsangan
* add LAYOUT_iso_split_bs
* add LAYOUT_iso
* add LAYOUT_iso_blocker_split_bs
* add LAYOUT_iso_blocker
* add LAYOUT_iso_blocker_tsangan_split_bs
* add LAYOUT_iso_blocker_tsangan
* info.json: correct layout data
* info.json: apply friendly formatting
* rename LAYOUT_all to LAYOUT
Only one layout is supported. Alias is maintained for backward compatibility.
* add matrix_diagram.md
* info.json: apply friendly formatting
* rename LAYOUT_all to LAYOUT_ansi_blocker
Existing codebase only supports the Hotswap version, but there is a Soldered version that supports additional layouts.
* refactor keymaps
- use four-space indent
- update grid-alignment of keycodes
- remove trailing spaces
* flesh-out keyboard readme
* add matrix_diagram.md
* refactor keymaps
* fix Configurator implementation
The original C-based code had an off-by-one error in the key sequence, that was then converted in data-driven configurator without being corrected.
* info.json: apply friendly formatting
* rename LAYOUT_all to LAYOUT_60_ansi_split_bs_rshift
* add LAYOUT_60_ansi
* add LAYOUT_60_tsangan_hhkb
* add LAYOUT_60_ansi_tsangan
* add LAYOUT_60_ansi_wkl_split_bs_rshift
* add LAYOUT_60_ansi_wkl
* enable Community Layout support
* edit listed maintainer (reference GitHub username)
* add matrix_diagram.md
* refactor keymaps
* fix Configurator implementation
The original C-based code had an off-by-one error in the key sequence, that was then converted in data-driven configurator without being corrected.
* info.json: apply friendly formatting
* add LAYOUT_60_ansi_split_bs_rshift
* add LAYOUT_60_ansi
* add LAYOUT_60_tsangan_hhkb
* add LAYOUT_60_ansi_tsangan
* add LAYOUT_60_iso_split_bs_rshift
* add LAYOUT_60_iso
* add LAYOUT_60_iso_tsangan_split_bs_rshift
* add LAYOUT_60_iso_tsangan
* enable Community Layout support
* edit keyboard maintainer
* rename LAYOUT_all to LAYOUT_60_tsangan_hhkb
* refactor keymaps
- use four-space indent
- grid-align keycodes
* copy via keymap to default
The default keymap had some keycodes that aren't appropriate for this board, and the function layer was wonky.
* enable Community Layout support
* add matrix_diagram.md
* info.json: apply friendly formatting
* rename LAYOUT_all to LAYOUT_60_tsangan_hhkb
* add LAYOUT_60_ansi_tsangan_split_rshift
* refactor default and via keymaps
- use four-space indent
- grid-align keycodes
* copy via keymap to default
The default keymap didn't make sense to me - it included keycodes for features that aren't supported, and the arrow key alignment on the function layer was wonky.
* enable Community Layout support
* add matrix_diagram.md
* refactor default and via keymaps
- use four-space indent
- grid-align keycodes
* info.json: apply friendly formatting
* standardize default and via keymaps
Place the `KC_NUHS` and `KC_NUBS` keycodes on the correct keys.
* add LAYOUT_ansi with reference keymap
* add LAYOUT_ansi_split_bs with reference keymap
* add LAYOUT_iso with reference keymap
* add LAYOUT_iso_split_bs with reference keymap
* info.json: apply friendly formatting
* add matrix_diagram.md
* add LAYOUT_ansi with reference keymap
* add LAYOUT_iso with reference keymap
* correct url value in info.json
The URL didn't load for me with the `www.` included. *shrug*
* add matrix_diagram.md
* refactor default keymap
- use four-space indent
- grid-align keycodes
- use QMK-native keycode alias for `RGB_MODE_RGBTEST`
* refactor default_iso keymap
- use four-space indent
- grid-align keycodes
* refactor via keymap
- use four-space indent
- grid-align keycodes
- use QMK-native keycode alias for `KC_TRNS`
* info.json: apply friendly formatting
* add maintainer and url keys to info.json
* add LAYOUT_ansi with reference keymap
* add LAYOUT_iso; refactor default_iso keymap
* standardize default and via keymaps
- use `QK_GESC` at top left
- use `KC_DEL` for right half of Split Backspace
- use `KC_NUHS` for Non-US Hash position
- use `KC_NUBS` for Non-Us Backslash position
- use `KC_RGUI` for middle right mod
* add RGB Underglow keycodes to all keymap Function layers
* add matrix_diagram.md
* info.json: apply friendly formatting
* grid align keycodes in keymaps
* physically arrange layout macro
The switch positions available for matrix position [3, 13] are both to the left of the only position present for matrix position [4, 7]. This commit switches the two locations physically and in the keymaps.
* add LAYOUT_60_ansi_split_bs_rshift
* add LAYOUT_60_ansi_arrow
* add LAYOUT_60_tsangan_hhkb
* add LAYOUT_60_iso_split_bs_rshift
* add LAYOUT_60_iso_arrow
* add LAYOUT_60_tsangan_hhkb_iso
* add matrix_diagram.md
Adds `matrix_diagram.md` to the `4pplet/aekiso60` directory, and removes the diagrams from the keyboard revision header files.
* info.json: apply friendly formatting
* move matrix data to info.json
* create keyboard-level info.json
* add LAYOUT_60_iso_tsangan
* enable Community Layout support
* fixup: improve AVR detection for 60_iso/unxmaal
* fixup: moved TAP_CODE_DELAY to mechmerlin/config.h
* fixup: move talljoe.c to INTROSPECTION_KEYMAP_C
* fixup: AVR/RGBLIGHT criteria for 60_iso/unxmaal
As per last breaking changes cycle, there has been _a lot_ of emphasis on behind-the-scenes changes, mainly around migration of configurables into `info.json` files, cleanup of `info.json` files, additional layout definitions for keyboards, adding support for general community layouts to keyboards, as well as addressing technical debt.
Of note for keyboard designers:
* Layout and matrix definitions in `info.json` are now _mandatory_ for merge into QMK.
* Layout macros in `<yourkeyboard>.h` are no longer accepted into QMK Firmware.
* Existing keyboards have been meticulously converted by the QMK collaborators
* Layouts missing from keyboard definitions have been added in the process
* Keys within layouts should not specify `"w":1` or `"h":1` if the key size is 1 -- `w`/`h` should only be present for sizes other than 1
*`config_common.h` has been removed and should not be present anywhere in your keyboard code.
*`RGB_DI_PIN` will now cause an error during build:
* For WS2812-like LEDs, this should be moved to `info.json`: `"ws2812": { "pin": "xxx" }`
* For APA102 LEDs, this should be moved to `info.json`: `"apa102": { "data_pin": "xxx" }`
* Other mandatory data-driven changes should be automatically flagged during build
* Keymaps with `encoder_map` should now have the following change made:
* Users assumed the `2` referred to the number of encoders, rather than the number of directions (which is always 2)
### Repeat last key ([#19700](https://github.com/qmk/qmk_firmware/pull/19700)) :id=repeat-last-key
A new pair of keys has been added to QMK -- namely `QK_REPEAT_KEY` and `QK_ALT_REPEAT_KEY` (shortened: `QK_REP`/`QK_AREP`). These allow you to repeat the last key pressed, or in the case of the alternate key, press the "opposite" of the last key. For example, if you press `KC_LEFT`, pressing `QK_REPEAT_KEY` afterwards repeats `KC_LEFT`, but pressing `QK_ALT_REPEAT_KEY` instead sends `KC_RIGHT`.
The full list of default alternate keys is available on the [Repeat Key](feature_repeat_key.md) documentation.
To enable these keys, in your keymap's `rules.mk`, add:
```make
REPEAT_KEY_ENABLE= yes
```
...and add them to your keymap.
### User callback for pre process record ([#20584](https://github.com/qmk/qmk_firmware/pull/20584)) :id=user-callback-for-pre-process-record
Two new boolean callback functions, `pre_process_record_kb` and `pre_process_record_user`, have been added. 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.
Several build targets for the IBM Model M were cluttered in different folders. The maintainers of several Model M replacement controller projects agreed to consolidate them under one common folder.
The list of all moved keyboard locations is listed [below](20230528.md#updated-keyboard-codebases).
## Changes Requiring User Action :id=changes-requiring-user-action
Following up from the last breaking changes cycle, `IGNORE_MOD_TAP_INTERRUPT` has been removed and if present in keymap code, will now fail to build. The previous functionality for `IGNORE_MOD_TAP_INTERRUPT` is now default, and should you wish to revert to the old behaviour, you can use `HOLD_ON_OTHER_KEY_PRESS` instead.
For more information, you are invited to read the section on [HOLD_ON_OTHER_KEY_PRESS](tap_hold.md#hold-on-other-key-press) in the page on [Tap-Hold configuration options](tap_hold.md).
For keyboards who have not yet been migrated to encoder map, a default set of encoder functionality is now enabled, gracefully degrading functionality depending on which flags are enabled by the keyboard:
* If `EXTRAKEY_ENABLE` is enabled by the keyboard, the encoder will be mapped to `KC_VOLU`/`KC_VOLD`
* If `MOUSEKEY_ENABLE` is enabled by the keyboard, the encoder will be mapped to `KC_MS_WH_UP`/`KC_MS_WH_DOWN`
* Otherwise, `KC_PGDN`/`KC_PGUP` will be used
Additionally, this ensures that builds on QMK Configurator produce some sort of usable encoder mapping.
* Fix rgblight layers when animations aren't enabled ([#20097](https://github.com/qmk/qmk_firmware/pull/20097))
* Fixed split keyboard issue where custom LED indicators could activate incorrect LEDs (#20203) ([#20204](https://github.com/qmk/qmk_firmware/pull/20204))
@@ -23,14 +23,6 @@ If it is determined that your submission is a breaking change, there are a few t
If you are contributing core code, and the only reason it needs to go through breaking changes is that you are updating keymaps to match your change, consider whether you can submit your feature in a way that the old keymaps continue to work. Then submit a separate PR that goes through the breaking changes process to remove the old code.
### Contribute a ChangeLog Entry
We require submissions that go through the Breaking Change process to include a changelog entry. The entry should be a short summary of the changes your pull request makes – [each section here started as a changelog](ChangeLog/20190830.md "n.b. This should link to the 2019 Aug 30 Breaking Changes doc - @noroadsleft").
Your changelog should be located at `docs/ChangeLog/YYYYMMDD/PR####.md`, where `YYYYMMDD` is the date on which QMK's breaking change branch – usually named `develop`– will be merged into the `master` branch, and `####` is the number of your pull request.
If your submission requires action on the part of users, your changelog should instruct users what action(s) must be taken, or link to a location that does so.
### Document Your Changes
Understanding the purpose for your submission, and possible implications or actions it will require can make the review process more straightforward. A changelog may suffice for this purpose, but more extensive changes may require a level of detail that is ill-suited for a changelog.
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 '?'.
@@ -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.
@@ -37,9 +37,9 @@ For more information on bitwise operators in C, click [here](https://en.wikipedi
In practice, this means that you can check whether a given modifier is active with `get_mods() & MOD_BIT(KC_<modifier>)` (see the [list of modifier keycodes](keycodes_basic.md#modifiers)) or with `get_mods() & MOD_MASK_<modifier>` if the difference between left and right hand modifiers is not important and you want to match both. Same thing can be done for one-shot modifiers if you replace `get_mods()` with `get_oneshot_mods()`.
To check that *only* a specific set of mods is active at a time, AND the modifier state and your desired mod mask as explained above and compare the result to the mod mask itself: `get_mods() & <mod mask> == <mod mask>`.
To check that *only* a specific set of mods is active at a time, use a simple equality operator: `get_mods() == <mod mask>`.
For example, let's say you want to trigger a piece of custom code if one-shot left control and one-shot left shift are on but every other one-shot mods are off. To do so, you can compose the desired mod mask by combining the mod bits for left control and shift with `(MOD_BIT(KC_LCTL) | MOD_BIT(KC_LSFT))` and then plug it in: `get_oneshot_mods() & (MOD_BIT(KC_LCTL) | MOD_BIT(KC_LSFT)) == (MOD_BIT(KC_LCTL) | MOD_BIT(KC_LSFT))`. Using `MOD_MASK_CS` instead for the mod bitmask would have forced you to press four modifier keys (both versions of control and shift) to fulfill the condition.
For example, let's say you want to trigger a piece of custom code if one-shot left control and one-shot left shift are on but every other one-shot mods are off. To do so, you can compose the desired mod mask by combining the mod bits for left control and shift with `(MOD_BIT(KC_LCTL) | MOD_BIT(KC_LSFT))` and then plug it in: `get_oneshot_mods() == (MOD_BIT(KC_LCTL) | MOD_BIT(KC_LSFT))`. Using `MOD_MASK_CS` instead for the mod bitmask would have forced you to press four modifier keys (both versions of control and shift) to fulfill the condition.
@@ -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.
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
enummyCombos{
...,
COMBO_LENGTH
};
uint16_tCOMBO_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
@@ -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/.
| Not defined | Use the default algorithm, currently sym_defer_g | Nothing |
| custom | Use your own debounce code | ```SRC += debounce.c``` add your own debounce.c and implement necessary functions |
| Anything Else | Use another algorithm from quantum/debounce/* | Nothing |
Default debounce time is 5 milliseconds and it can be changed with the following line in `config.h`:
```
#define DEBOUNCE 10
```
?> Setting `DEBOUNCE` to `0` will disable this feature.
**Regarding split keyboards**:
The debounce code is compatible with split keyboards.
### Debounce Method
### Selecting an included debouncing method
Keyboards may select one of the already implemented debounce methods, by adding to ```rules.mk``` the following line:
Keyboards may select one of the core debounce methods by adding the following line into `rules.mk`:
```
DEBOUNCE_TYPE = <name of algorithm>
```
Where name of algorithm is one of:
* ```sym_defer_g``` - debouncing per keyboard. On any state change, a global timer is set. When ```DEBOUNCE``` milliseconds of no changes has occurred, all input changes are pushed.
* This is the current default algorithm. This is the highest performance algorithm with lowest memory usage, and it's also noise-resistant.
* ```sym_eager_pr``` - debouncing per row. On any state change, response is immediate, followed by locking the row ```DEBOUNCE``` milliseconds of no further input for that row.
For use in keyboards where refreshing ```NUM_KEYS``` 8-bit counters is computationally expensive / low scan rate, and fingers usually only hit one row at a time. This could be
appropriate for the ErgoDox models; the matrix is rotated 90°, and hence its "rows" are really columns, and each finger only hits a single "row" at a time in normal use.
* ```sym_eager_pk``` - debouncing per key. On any state change, response is immediate, followed by ```DEBOUNCE``` milliseconds of no further input for that key
* ```sym_defer_pr``` - debouncing per row. On any state change, a per-row timer is set. When ```DEBOUNCE``` milliseconds of no changes have occurred on that row, the entire row is pushed. Can improve responsiveness over `sym_defer_g` while being less susceptible than per-key debouncers to noise.
* ```sym_defer_pk``` - debouncing per key. On any state change, a per-key timer is set. When ```DEBOUNCE``` milliseconds of no changes have occurred on that key, the key status change is pushed.
* ```asym_eager_defer_pk``` - debouncing per key. On a key-down state change, response is immediate, followed by ```DEBOUNCE``` milliseconds of no further input for that key. On a key-up state change, a per-key timer is set. When ```DEBOUNCE``` milliseconds of no changes have occurred on that key, the key-up status change is pushed.
Name of algorithm is one of:
### A couple algorithms that could be implemented in the future:
* ```sym_defer_pr```
* ```sym_eager_g```
| Algorithm | Description |
| --------------------- | ----------- |
| `sym_defer_g` | Debouncing per keyboard. On any state change, a global timer is set. When `DEBOUNCE` milliseconds of no changes has occurred, all input changes are pushed. This is the highest performance algorithm with lowest memory usage and is noise-resistant. |
| `sym_defer_pr` | Debouncing per row. On any state change, a per-row timer is set. When `DEBOUNCE` milliseconds of no changes have occurred on that row, the entire row is pushed. This can improve responsiveness over `sym_defer_g` while being less susceptible to noise than per-key algorithm. |
| `sym_defer_pk` | Debouncing per key. On any state change, a per-key timer is set. When `DEBOUNCE` milliseconds of no changes have occurred on that key, the key status change is pushed. |
| `sym_eager_pr` | Debouncing per row. On any state change, response is immediate, followed by `DEBOUNCE` milliseconds of no further input for that row. |
| `sym_eager_pk` | Debouncing per key. On any state change, response is immediate, followed by `DEBOUNCE` milliseconds of no further input for that key. |
| `asym_eager_defer_pk` | Debouncing per key. On a key-down state change, response is immediate, followed by `DEBOUNCE` milliseconds of no further input for that key. On a key-up state change, a per-key timer is set. When `DEBOUNCE` milliseconds of no changes have occurred on that key, the key-up status change is pushed. |
### Use your own debouncing code
You have the option to implement you own debouncing algorithm. To do this:
* Set ```DEBOUNCE_TYPE = custom``` in ```rules.mk```.
* Add ```SRC += debounce.c``` in ```rules.mk```
* Add your own ```debounce.c```. Look at current implementations in ```quantum/debounce``` for examples.
?> `sym_defer_g` is the default if `DEBOUNCE_TYPE` is undefined.
?> `sym_eager_pr` is suitable for use in keyboards where refreshing `NUM_KEYS` 8-bit counters is computationally expensive or has low scan rate while fingers usually hit one row at a time. This could be appropriate for the ErgoDox models where the matrix is rotated 90°. Hence its "rows" are really columns and each finger only hits a single "row" at a time with normal usage.
### Implementing your own debouncing code
You have the option to implement you own debouncing algorithm with the following steps:
* Set `DEBOUNCE_TYPE = custom` in `rules.mk`.
* Add `SRC += debounce.c` in `rules.mk`
* Implement your own `debounce.c`. See `quantum/debounce` for examples.
* Debouncing occurs after every raw matrix scan.
* Use num_rows rather than MATRIX_ROWS, so that split keyboards are supported correctly.
* If the algorithm might be applicable to other keyboards, please consider adding it to ```quantum/debounce```
* Use num_rows instead of MATRIX_ROWS to support split keyboards correctly.
* If your custom algorithm is applicable to other keyboards, please consider making a pull request.
@@ -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`:
!> 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.
@@ -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).
|`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. |
|`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` |The ending character index for custom fonts |
|`OLED_FONT_WIDTH` |`6` |The font width |
|`OLED_FONT_HEIGHT` |`8` |The font height (untested) |
|`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_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_IC` |`OLED_IC_SSD1306`|Set to `OLED_IC_SH1106` if you're using the SH1106 OLED controller. |
|`OLED_COLUMN_OFFSET` |`0` |(SH1106 only.) Shift output to the right this many pixels.<br/>Useful for 128x64 displays centered on a 132x64 SH1106 IC.|
|`OLED_BRIGHTNESS` |`255` |The default brightness level of the OLED, from 0 to 255. |
|`OLED_UPDATE_INTERVAL` |`0` |Set the time interval for updating the OLED display in ms. This will improve the matrix scan rate. |
## 128x64 & Custom sized OLED Displays
### SPI Configuration
The default display size for this feature is 128x32 and all necessary defines are precalculated with that in mind. We have added a define, `OLED_DISPLAY_128X64`, to switch all the values to be used in a 128x64 display, as well as added a custom define, `OLED_DISPLAY_CUSTOM`, that allows you to provide the necessary values to the driver.
|`OLED_DC_PIN` | Required |The pin used for the DC connection of the OLED Display. |
|`OLED_CS_PIN` | Required |The pin used for the CS connection of the OLED Display. |
|`OLED_RST_PIN` | *Not defined* |The pin used for the RST connection of the OLED Display (may be left undefined if the RST pin is not connected). |
|`OLED_SPI_MODE` |`3` (default) |The SPI Mode for the OLED Display (not typically changed). |
|`OLED_SPI_DIVISOR` |`2` (default) |The SPI Multiplier to use for the OLED Display. |
## 128x64 & Custom sized OLED Displays
The default display size for this feature is 128x32, and the defaults are set with that in mind. However, there are a number of additional presets for common sizes that we have added. You can define one of these values to use the presets. If your display doesn't match one of these presets, you can define `OLED_DISPLAY_CUSTOM` to manually specify all of the values.
|`OLED_DISPLAY_WIDTH` |`128` |The width of the OLED display. |
|`OLED_DISPLAY_HEIGHT`|`32` |The height of the OLED display. |
|`OLED_MATRIX_SIZE` |`512` |The local buffer size to allocate.<br>`(OLED_DISPLAY_HEIGHT / 8 * OLED_DISPLAY_WIDTH)`. |
@@ -192,14 +231,13 @@ These configuration options should be placed in `config.h`. Example:
|`OLED_BLOCK_COUNT` |`16` |The number of blocks the display is divided into for dirty rendering.<br>`(sizeof(OLED_BLOCK_TYPE) * 8)`. |
|`OLED_BLOCK_SIZE` |`32` |The size of each block for dirty rendering<br>`(OLED_MATRIX_SIZE / OLED_BLOCK_COUNT)`. |
|`OLED_COM_PINS` |`COM_PINS_SEQ` |How the SSD1306 chip maps it's memory to display.<br>Options are `COM_PINS_SEQ`, `COM_PINS_ALT`, `COM_PINS_SEQ_LR`, & `COM_PINS_ALT_LR`.|
|`OLED_COM_PIN_COUNT` |*Not defined* |Number of COM pins supported by the controller.<br>If not defined, the value appropriate for the defined `OLED_IC` is used. |
|`OLED_COM_PIN_OFFSET`|`0` |Number of the first COM pin used by the OLED matrix. |
|`OLED_SOURCE_MAP` |`{ 0, ... N }` |Precalculated source array to use for mapping source buffer to target OLED memory in 90 degree rendering. |
|`OLED_TARGET_MAP` |`{ 24, ... N }`|Precalculated target array to use for mapping source buffer to target OLED memory in 90 degree rendering. |
### 90 Degree Rotation - Technical Mumbo Jumbo
!> Rotation is unsupported on the SH1106.
```c
// OLED Rotation enum values are flags
typedef enum {
@@ -210,7 +248,7 @@ typedef enum {
} oled_rotation_t;
```
OLED displays driven by SSD1306 drivers only natively support in hardware 0 degree and 180 degree rendering. This feature is done in software and not free. Using this feature will increase the time to calculate what data to send over i2c to the OLED. If you are strapped for cycles, this can cause keycodes to not register. In testing however, the rendering time on an ATmega32U4 board only went from 2ms to 5ms and keycodes not registering was only noticed once we hit 15ms.
OLED displays driven by SSD1306, SH1106 or SH1107 drivers only natively support in hardware 0 degree and 180 degree rendering. This feature is done in software and not free. Using this feature will increase the time to calculate what data to send over i2c to the OLED. If you are strapped for cycles, this can cause keycodes to not register. In testing however, the rendering time on an ATmega32U4 board only went from 2ms to 5ms and keycodes not registering was only noticed once we hit 15ms.
90 degree rotation is achieved by using bitwise operations to rotate each 8 block of memory and uses two precalculated arrays to remap buffer memory to OLED memory. The memory map defines are precalculated for remap performance and are calculated based on the display height, width, and block size. For example, in the 128x32 implementation with a `uint8_t` block type, we have a 64 byte block size. This gives us eight 8 byte blocks that need to be rotated and rendered. The OLED renders horizontally two 8 byte blocks before moving down a page, e.g:
@@ -232,6 +270,8 @@ However the local buffer is stored as if it was Height x Width display instead o
So those precalculated arrays just index the memory offsets in the order in which each one iterates its data.
Rotation on SH1106 and SH1107 is noticeably less efficient than on SSD1306, because these controllers do not support the “horizontal addressing mode”, which allows transferring the data for the whole rotated block at once; instead, separate address setup commands for every page in the block are required. The screen refresh time for SH1107 is therefore about 45% higher than for a same size screen with SSD1306 when using STM32 MCUs (on AVR the slowdown is about 20%, because the code which actually rotates the bitmap consumes more time).
@@ -197,6 +197,24 @@ The Pimoroni Trackball module is a I2C based breakout board with an RGB enable t
| `PIMORONI_TRACKBALL_DEBOUNCE_CYCLES` | (Optional) The number of scan cycles used for debouncing on the ball press. | `20` |
| `PIMORONI_TRACKBALL_ERROR_COUNT` | (Optional) Specifies the number of read/write errors until the sensor is disabled. | `10` |
### PMW3320 Sensor
To use the PMW3320 sensor, add this to your `rules.mk`
```make
POINTING_DEVICE_DRIVER= pmw3320
```
The PMW3320 sensor uses a serial type protocol for communication, and requires an additional light source (it could work without one, but expect it to be out of service early).
| `PMW3320_SCLK_PIN` | (Required) The pin connected to the clock pin of the sensor. | `POINTING_DEVICE_SCLK_PIN` |
| `PMW3320_SDIO_PIN` | (Required) The pin connected to the data pin of the sensor. | `POINTING_DEVICE_SDIO_PIN` |
| `PMW3320_CS_PIN` | (Required) The pin connected to the cable select pin of the sensor. | `POINTING_DEVICE_CS_PIN` |
The CPI range is 500-3500, in increments of 250. Defaults to 1000 CPI.
### PMW 3360 and PMW 3389 Sensor
This drivers supports both the PMW 3360 and PMW 3389 sensor as well as multiple sensors of the same type _per_ controller, so 2 can be attached at the same side for split keyboards (or unsplit keyboards).
This allows you to toggle between scrolling and cursor movement by pressing the DRAG_SCROLL key.
### Advanced Drag Scroll
Sometimes, like with the Cirque trackpad, you will run into issues where the scrolling may be too fast.
Here is a slightly more advanced example of drag scrolling. You will be able to change the scroll speed based on the values in set in `SCROLL_DIVISOR_H` and `SCROLL_DIVISOR_V`. This bit of code is also set up so that instead of toggling the scrolling state with set_scrolling = !set_scrolling, the set_scrolling variable is set directly to record->event.pressed. This way, the drag scrolling will only be active while the DRAG_SCROLL button is held down.
```c
enumcustom_keycodes{
DRAG_SCROLL=SAFE_RANGE,
};
boolset_scrolling=false;
// Modify these values to adjust the scrolling speed
#define SCROLL_DIVISOR_H 8.0
#define SCROLL_DIVISOR_V 8.0
// Variables to store accumulated scroll values
floatscroll_accumulated_h=0;
floatscroll_accumulated_v=0;
// Function to handle mouse reports and perform drag scrolling
The following examples make use the `SPLIT_POINTING_ENABLE` functionality and show how to manipulate the mouse report for a scrolling mode.
@@ -602,6 +689,10 @@ There are several functions that allow for more advanced interaction with the au
| `auto_mouse_layer_off(void)` | Disable target layer if appropriate will call (makes call to `layer_state_set`) | | `void`(None) |
| `auto_mouse_toggle(void)` | Toggle on/off target toggle state (disables layer deactivation when true) | | `void`(None) |
| `get_auto_mouse_toggle(void)` | Return value of toggling state variable | | `bool` |
| `set_auto_mouse_timeout(uint16_t timeout)` | Change/set the timeout for turing off the layer | | `void`(None) |
| `get_auto_mouse_timeout(void)` | Return the current timeout for turing off the layer | | `uint16_t` |
| `set_auto_mouse_debounce(uint16_t timeout)` | Change/set the debounce for preventing layer activation | | `void`(None) |
| `get_auto_mouse_debounce(void)` | Return the current debounce for preventing layer activation | | `uint8_t` |
_NOTES:_
- _Due to the nature of how some functions work, the `auto_mouse_trigger_reset`, and `auto_mouse_layer_off` functions should never be called in the `layer_state_set_*` stack as this can cause indefinite loops._
@@ -713,7 +804,7 @@ _Note: The Cirque pinnacle track pad already implements a custom activation func
When using a custom pointing device (overwriting `pointing_device_task`) the following code should be somewhere in the `pointing_device_task_*` stack:
```c
voidpointing_device_task(void){
boolpointing_device_task(void){
//...Custom pointing device task code
// handle automatic mouse layer (needs report_mouse_t as input)
Where `X_Y` is the location of the LED in the matrix defined by [the datasheet](https://www.issi.com/WW/pdf/31FL3733.pdf) and the header file `drivers/led/issi/is31fl3733.h`. The `driver` is the index of the driver you defined in your `config.h` (`0`, `1`, `2`, or `3` for now).
---
### IS31FL3736 :id=is31fl3736
There is basic support for addressable RGB matrix lighting with the I2C IS31FL3736 RGB controller. To enable it, add this to your `rules.mk`:
```make
RGB_MATRIX_ENABLE= yes
RGB_MATRIX_DRIVER= IS31FL3736
```
You can use between 1 and 4 IS31FL3736 IC's. Do not specify `DRIVER_ADDR_<N>` defines for IC's that are not present on your keyboard.
Configure the hardware via your `config.h`:
| Variable | Description | Default |
|----------|-------------|---------|
| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
| `ISSI_PWM_FREQUENCY` | (Optional) PWM Frequency Setting - IS31FL3736B only | 0 |
| `ISSI_GLOBALCURRENT` | (Optional) Configuration for the Global Current Register | 0xFF |
| `ISSI_SWPULLUP` | (Optional) Set the value of the SWx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
| `ISSI_CSPULLUP` | (Optional) Set the value of the CSx lines on-chip de-ghosting resistors | PUR_0R (Disabled) |
| `DRIVER_COUNT` | (Required) How many RGB driver IC's are present | |
| `RGB_MATRIX_LED_COUNT` | (Required) How many RGB lights are present across all drivers | |
| `DRIVER_ADDR_1` | (Required) Address for the first RGB driver | |
| `DRIVER_ADDR_2` | (Optional) Address for the second RGB driver | |
| `DRIVER_ADDR_3` | (Optional) Address for the third RGB driver | |
| `DRIVER_ADDR_4` | (Optional) Address for the fourth RGB driver | |
The IS31FL3736 IC's have on-chip resistors that can be enabled to allow for de-ghosting of the RGB matrix. By default these resistors are not enabled (`ISSI_SWPULLUP`/`ISSI_CSPULLUP` are given the value of`PUR_0R`), the values that can be set to enable de-ghosting are as follows:
| `ISSI_SWPULLUP/ISSI_CSPULLUP` | Description |
|----------------------|-------------|
| `PUR_0R` | (default) Do not use the on-chip resistors/enable de-ghosting |
| `PUR_05KR` | The 0.5k Ohm resistor used during blanking period (t_NOL) |
| `PUR_1KR` | The 1k Ohm resistor used during blanking period (t_NOL) |
| `PUR_2KR` | The 2k Ohm resistor used during blanking period (t_NOL) |
| `PUR_4KR` | The 4k Ohm resistor used during blanking period (t_NOL) |
| `PUR_8KR` | The 8k Ohm resistor during blanking period (t_NOL) |
| `PUR_16KR` | The 16k Ohm resistor during blanking period (t_NOL) |
| `PUR_32KR` | The 32k Ohm resistor used during blanking period (t_NOL) |
Here is an example using 2 drivers.
```c
// This is a 7-bit address, that gets left-shifted and bit 0
// set to 0 for write, 1 for read (as per I2C protocol)
// The address will vary depending on your wiring:
!> Note the parentheses, this is so when `RGB_MATRIX_LED_COUNT` is used in code and expanded, the values are added together before any additional math is applied to them. As an example, `rand() % (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)` will give very different results than `rand() % DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL`.
Define these arrays listing all the LEDs in your `<keyboard>.c`:
There is basic support for addressable RGB matrix lighting with the I2C IS31FL3737 RGB controller. To enable it, add this to your `rules.mk`:
@@ -218,8 +294,6 @@ Here is an example using 2 drivers.
```
!> Note the parentheses, this is so when `RGB_MATRIX_LED_COUNT` is used in code and expanded, the values are added together before any additional math is applied to them. As an example, `rand() % (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)` will give very different results than `rand() % DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL`.
Currently only 2 drivers are supported, but it would be trivial to support all 4 combinations.
Define these arrays listing all the LEDs in your `<keyboard>.c`:
```c
@@ -361,7 +435,7 @@ Configure the hardware via your `config.h`:
```c
// The pin connected to the data pin of the LEDs
#define RGB_DI_PIN D7
#define WS2812_DI_PIN D7
// The number of LEDs connected
#define RGB_MATRIX_LED_COUNT 70
```
@@ -383,9 +457,9 @@ Configure the hardware via your `config.h`:
```c
// The pin connected to the data pin of the LEDs
#define RGB_DI_PIN D7
#define APA102_DI_PIN D7
// The pin connected to the clock pin of the LEDs
#define RGB_CI_PIN D6
#define APA102_CI_PIN D6
// The number of LEDs connected
#define RGB_MATRIX_LED_COUNT 70
```
@@ -690,6 +764,14 @@ Remove the spread effect entirely.
#define RGB_MATRIX_TYPING_HEATMAP_SLIM
```
It's also possible to adjust the tempo of *heating up*. It's defined as the number of shades that are
increased on the [HSV scale](https://en.wikipedia.org/wiki/HSL_and_HSV). Decreasing this value increases
the number of keystrokes needed to fully heat up the key.
Solid reactive effects will pulse RGB light on key presses with user configurable hues. To enable gradient mode that will automatically change reactive color, add the following define:
@@ -811,13 +893,7 @@ These are defined in [`color.h`](https://github.com/qmk/qmk_firmware/blob/master
## EEPROM storage :id=eeprom-storage
The EEPROM for it is currently shared with the LED 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_RGB_MATRIX (uint32_t *)28
```
Where `28` is an unused index from `eeconfig.h`.
The EEPROM for it is currently shared with the LED Matrix system (it's generally assumed only one feature would be used at a time).
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.
Steve Losh described the [Space Cadet Shift](https://stevelosh.com/blog/2012/10/a-modern-space-cadet/) quite well. Essentially, when you tap Left Shift on its own, you get an opening parenthesis; tap Right Shift on its own and you get the closing one. When held, the Shift keys function as normal. Yes, it's as cool as it sounds, and now even cooler supporting Control and Alt as well!
Steve Losh described the [Space Cadet Shift](https://web.archive.org/web/20230330090938/https://stevelosh.com/blog/2012/10/a-modern-space-cadet/) quite well. Essentially, when you tap Left Shift on its own, you get an opening parenthesis; tap Right Shift on its own and you get the closing one. When held, the Shift keys function as normal. Yes, it's as cool as it sounds, and now even cooler supporting Control and Alt as well!
@@ -300,6 +300,12 @@ This enables transmitting the pointing device status to the master side of the s
This enables triggering of haptic feedback on the slave side of the split keyboard. For DRV2605L this will send the mode, but for solenoids it is expected that the desired mode is already set up on the slave.
```c
#define SPLIT_ACTIVITY_ENABLE
```
This synchronizes the activity timestamps between sides of the split keyboard, allowing for activity timeouts to occur.
### Custom data sync between sides :id=custom-data-sync
QMK's split transport allows for arbitrary data transactions at both the keyboard and user levels. This is modelled on a remote procedure call, with the master invoking a function on the slave side, with the ability to send data from master to slave, process it slave side, and send data back from slave to master.
This function is called after a key has been processed, but before any decision about whether or not to send a chord. This is where to put hooks for things like, say, live displays of steno chords or keys.
If `IS_PRESSED(record->event)` is false, and `n_pressed_keys` is 0 or 1, the chord will be sent shortly, but has not yet been sent. This relieves you of the need of keeping track of where a packet ends and another begins.
If `record->event.pressed` is false, and `n_pressed_keys` is 0 or 1, the chord will be sent shortly, but has not yet been sent. This relieves you of the need of keeping track of where a packet ends and another begins.
The `chord` argument contains the packet of the current chord as specified by the protocol in use. This is *NOT* simply a list of chorded steno keys of the form `[STN_E, STN_U, STN_BR, STN_GR]`. Refer to the appropriate protocol section of this document to learn more about the format of the packets in your steno protocol/mode of choice.
This project includes a `Vagrantfile` that will allow you to build a new firmware for your keyboard very easily without major changes to your primary operating system. This also ensures that when you clone the project and perform a build, you have the exact same environment as anyone else using the Vagrantfile to build. This makes it much easier for people to help you troubleshoot any issues you encounter.
## Requirements
Using the `Vagrantfile` in this repository requires you have [Vagrant](https://www.vagrantup.com/) as well as a supported provider installed:
* [VirtualBox](https://www.virtualbox.org/) (Version at least 5.0.12)
* Sold as 'the most accessible platform to use Vagrant'
* [VMware Workstation](https://www.vmware.com/products/workstation) and [Vagrant VMware plugin](https://www.vagrantup.com/vmware)
* The (paid) VMware plugin requires a licensed copy of VMware Workstation/Fusion
* [Docker](https://www.docker.com/)
Other than having Vagrant, a suitable provider installed and possibly a restart of your computer afterwards, you can simple run a 'vagrant up' anywhere inside the folder where you checked out this project and it will start an environment (either a virtual machine or container) that contains all the tools required to build this project. There is a post Vagrant startup hint that will get you off on the right foot, otherwise you can also reference the build documentation below.
## Flashing the Firmware
The "easy" way to flash the firmware is using a tool from your host OS:
If you want to program via the command line you can uncomment the ['modifyvm'] lines in the Vagrantfile to enable the USB passthrough into Linux and then program using the command line tools like dfu-util/dfu-programmer or you can install the Teensy CLI version.
## Vagrantfile Overview
The development environment is configured to run the QMK Docker image, `qmkfm/qmk_cli`. This not only ensures predictability between systems, it also mirrors the CI environment.
## FAQ
### Why am I seeing issues under Virtualbox?
Certain versions of Virtualbox 5 appear to have an incompatibility with the Virtualbox extensions installed in the boxes in this Vagrantfile. If you encounter any issues with the /vagrant mount not succeeding, please upgrade your version of Virtualbox to at least 5.0.12. **Alternately, you can try running the following command:**
```
vagrant plugin install vagrant-vbguest
```
### How do I remove an existing environment?
Finished with your environment? From anywhere inside the folder where you checked out this project, Execute:
```
vagrant destroy
```
### What if I want to use Docker directly?
Want to benefit from the Vagrant workflow without a virtual machine? The Vagrantfile is configured to bypass running a virtual machine, and run the container directly. Execute the following when bringing up the environment to force the use of Docker:
```
vagrant up --provider=docker
```
### How do I access the virtual machine instead of the Docker container?
Execute the following to bypass the `vagrant` user booting directly to the official qmk builder image:
@@ -35,6 +35,40 @@ To use a 5V/16MHz Pro Micro as an ISP flashing tool, you will first need to load
!> Note that the `10` pin on the Pro Micro should be wired to the `RESET` pin on the keyboard's controller. ***DO NOT*** connect the `RESET` pin on the Pro Micro to the `RESET` on the keyboard.
A standard Uno or Micro can be used as an ISP flashing tool using the [example "ArduinoISP" sketch](https://docs.arduino.cc/built-in-examples/arduino-isp/ArduinoISP#load-the-sketch) to emulate an STK500 ISP. Also works with Sparkfun Pro Micros and clones.
**AVRDUDE Programmer**: `stk500v1`
**AVRDUDE Port**: Serial
#### Wiring
|Uno |Keyboard|
|-----------|--------|
|`5V` |`VCC` |
|`GND` |`GND` |
|`10` (`B2`)|`RESET` |
|`13` (`B5`)|`SCLK` |
|`11` (`B3`)|`MOSI` |
|`12` (`B4`)|`MISO` |
|Micro |Keyboard|
|-----------|--------|
|`5V` |`VCC` |
|`GND` |`GND` |
|`10` (`B6`)|`RESET` |
|`15` (`B1`)|`SCLK` |
|`16` (`B2`)|`MOSI` |
|`14` (`B3`)|`MISO` |
!> Note that the `10` pin on the Uno/Micro should be wired to the `RESET` pin on the keyboard's controller. ***DO NOT*** connect the `RESET` pin on the Uno/Micro to the `RESET` on the keyboard.
@@ -57,6 +91,7 @@ To use a Teensy 2.0 as an ISP flashing tool, you will first need to load a [spec
!> Note that the `B0` pin on the Teensy should be wired to the `RESET` pin on the keyboard's controller. ***DO NOT*** connect the `RESET` pin on the Teensy to the `RESET` on the keyboard.
Enabling `IGNORE_MOD_TAP_INTERRUPT` is recommended when using Mod-Tap on alphanumeric keys to avoid hold function taking precendence when the next key is pressed quickly. See [Ignore Mod Tap Interrupt](tap_hold.md#ignore-mod-tap-interrupt) for more details.
### Changing both tap and hold
This last example implements custom tap and hold function with `LT(0,KC_NO)` to create a single copy-on-tap, paste-on-hold key:
The [QMK Configurator](https://config.qmk.fm) is an online graphical user interface that generates QMK Firmware `.hex` or `.bin` files.
It should be noted that Configurator cannot produce firmwares for keyboards using a different controller than they were designed for, i.e. an RP2040 controller on a board designed for pro micro. You will have to use the command line [converters](https://docs.qmk.fm/#/feature_converters?id=supported-converters) for this.
Watch the [Video Tutorial](https://www.youtube.com/watch?v=-imgglzDMdY). Many people find that is enough information to start programming their own keyboard.
The QMK Configurator works best with Chrome or Firefox.
@@ -85,6 +85,8 @@ Visit the [QMK Configurator](https://config.qmk.fm/#/) to create a keymap file:
3. Customise the key layout according to your preference.
4. Select download next to **KEYMAP.JSON** and save the JSON file into the `~/qmk_keymap/` folder.
!> **Important:** Make sure that the GitHub username you use in step 2 is correct. If it is not, the build process will fail to locate your files in the right folder.
### Add a GitHub Action workflow
Open the file `~/qmk_keymap/.github/workflows/build.yml` with your favorite [text editor](newbs_learn_more_resources.md#text-editor-resources), paste the following workflow content, and save it:
@@ -15,7 +15,7 @@ Different keyboards have different ways to enter this special mode. If your PCB
* Press the physical `RESET` button, usually located on the underside of the PCB
* Locate header pins on the PCB labeled `RESET` and `GND`, and short them together while plugging your PCB in
If you've attempted all of the above to no avail, and the main chip on the board says `STM32` on it, this may be a bit more complicated. Generally your best bet is to ask on [Discord](https://discord.gg/Uq7gcHh) for assistance. It's likely some photos of the board will be asked for -- if you can get them ready beforehand it'll help move things along!
If you've attempted all of the above to no avail, and the main chip on the board says `STM32` or `RP2-B1` on it, this may be a bit more complicated. Generally your best bet is to ask on [Discord](https://discord.gg/Uq7gcHh) for assistance. It's likely some photos of the board will be asked for -- if you can get them ready beforehand it'll help move things along!
Otherwise, you should see a message in yellow, similar to this in QMK Toolbox:
@@ -31,6 +31,8 @@ The simplest way to flash your keyboard will be with the [QMK Toolbox](https://g
However, the Toolbox is currently only available for Windows and macOS. If you're using Linux (or just wish to flash the firmware from the command line), skip to the [Flash your Keyboard from the Command Line](#flash-your-keyboard-from-the-command-line) section.
?> QMK Toolbox is not necessary for flashing [RP2040 devices](https://docs.qmk.fm/#/flashing?id=raspberry-pi-rp2040-uf2).
### Load the File into QMK Toolbox
Begin by opening the QMK Toolbox application. You'll want to locate the firmware file in Finder or Explorer. Your keyboard firmware may be in one of two formats- `.hex` or `.bin`. QMK tries to copy the appropriate one for your keyboard into the root `qmk_firmware` directory.
@@ -120,7 +120,7 @@ NOTE: remember to follow the instructions printed at the end of installation (us
### ** Windows **
After installing QMK you can set it up with this command:
Open QMK MSYS and run the following command:
qmk setup
@@ -128,7 +128,7 @@ In most situations you will want to answer `y` to all of the prompts.
### ** macOS **
Afterinstalling QMK you can set it up with this command:
Open Terminal and run the following command:
qmk setup
@@ -136,7 +136,7 @@ In most situations you will want to answer `y` to all of the prompts.
### ** Linux/WSL **
After installing QMK you can set it up with this command:
Open your preferred terminal app and run the following command:
qmk setup
@@ -150,7 +150,7 @@ Luckily, the fix is easy. Run this as your user: `echo 'PATH="$HOME/.local/bin:$
### ** FreeBSD **
After installing QMK you can set it up with this command:
Open your preferred terminal app and run the following command:
qmk setup
@@ -172,6 +172,8 @@ For example, to build a firmware for a Clueboard 66% you would use:
qmk compile -kb clueboard/66/rev3 -km default
?> The keyboard option is the path relative to the keyboard directory, the above example would be found in `qmk_firmware/keyboards/clueboard/66/rev3`. If you're unsure you can view a full list of supported keyboards with `qmk list-keyboards`.
When it is done you should have a lot of output that ends similar to this:
This installs a bunch of Git related tools that may make using Git with QMK Firmware easier.
* [Git Extension Pack](https://marketplace.visualstudio.com/items?itemName=donjayamanne.git-extension-pack) - This installs a bunch of Git related tools that may make using Git with QMK Firmware easier.
* [clangd](https://marketplace.visualstudio.com/items?itemName=llvm-vs-code-extensions.vscode-clangd) - _[Optional]_ - This is the language server for C/C++ that VS Code uses. It provides IntelliSense and other features.
* [EditorConfig for VS Code](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig) - _[Optional]_ - Helps to keep the code to the QMK Coding Conventions.
* [GitHub Markdown Preview](https://marketplace.visualstudio.com/items?itemName=bierner.github-markdown-preview) - _[Optional]_ - Makes the markdown preview in VS Code more like GitHub's.
* [VS Live Share Extension Pack](https://marketplace.visualstudio.com/items?itemName=MS-vsliveshare.vsliveshare-pack) - _[Optional]_ - This extension allows somebody else to access your workspace (or you to access somebody else's workspace) and help out. This is great if you're having issues and need some help from somebody.
Using the [standard `compile_commands.json` database](https://clang.llvm.org/docs/JSONCompilationDatabase.html), we can get VS code C/C++ extension to use the exact same includes and defines used for your keyboard and keymap.
Using the [standard `compile_commands.json` database](https://clang.llvm.org/docs/JSONCompilationDatabase.html), we can get the VS code _clangd_ extension to use the correct includes and defines used for your keyboard and keymap.
1. Run `qmk generate-compilation-database -kb <keyboard> -km <keymap>` to generate the `compile_commands.json`.
1. Create `.vscode/c_cpp_properties.json` with the following content:
1. Inside VS code, press <kbd><kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd></kbd> (macOS: <kbd><kbd>Command</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd></kbd>) to open the command palette.
1. Start typing `clangd: Download Language Server` and select it when it appears. Note that this only needs to be done once on clangd extension installation, if it didn't already ask to do so.
1. Inside VS code, press <kbd><kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd></kbd> (macOS: <kbd><kbd>Command</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd></kbd>) to open the command palette.
1. Start typing `clangd: Restart Language Server` and select it when it appears.
Change values in `.vscode/c_cpp_properties.json` for your environment:
1. Copy the `-mmcu` argument from `compile_commands.json` into your `compilerArgs`. This is to work around a [bug in vscode c/c++ extension](https://github.com/microsoft/vscode-cpptools/issues/6478).
1. Use the `compilerPath` from `compile_commands.json`.
1. Modify `cStandard`, `cppStandard` and `intelliSenseMode` values to the correct values for your platform. See [this section](https://code.visualstudio.com/docs/cpp/c-cpp-properties-schema-reference#_configuration-properties) for reference. For WSL, it should still be gcc-x64.
And now you're ready to code QMK Firmware in VS Code
## Troubleshooting VSCode C/C++ extension
If the defines are not matching what you expect, open the source code and run action `C/C++: Log Diagnostics`. This will list the exact list of defines and include paths defined in `compile_commands.json`, and if it's not part of your compilation database, it will tell you so.
- keyboard moves within the repository *must* go through the `develop` branch instead of `master`, so as to ensure compatibility for users
-`data/mappings/keyboard_aliases.hjson` must be updated to reflect the move, so users with pre-created configurator keymap.json files continue to detect the correct keyboard
- keyboard updates and refactors (eg. to data driven) *must* go through `develop` to reduce `master` -> `develop` merge conflicts
- PR submissions from a `kbfirmware` export (or equivalent) will not be accepted unless converted to new QMK standards -- try `qmk import-kbfirmware` first
-`info.json`
- With the move to [data driven](https://docs.qmk.fm/#/data_driven_config) keyboard configuration, we encourage contributors to utilise as many features as possible of the info.json [schema](https://github.com/qmk/qmk_firmware/blob/master/data/schemas/keyboard.jsonschema).
- hardware that's enabled at the keyboard level and requires configuration such as OLED displays or encoders should have basic functionality implemented here
-`<keyboard>.h`
-`#include "quantum.h"` appears at the top
-`LAYOUT` macros should be moved to `info.json`
-`LAYOUT` macros are no longer accepted and should instead be moved to `info.json`
- keymap `config.h`
- no duplication of `rules.mk` or `config.h` from keyboard
- if using `MO(1)` and `MO(2)` keycodes together to access a third layer, the [Tri Layer](https://docs.qmk.fm/#/feature_tri_layer) feature should be used, rather than manually implementing this using `layer_on/off()` and `update_tri_layer()` functions in the keymap's `process_record_user()`.
- default (and via) keymaps should be "pristine"
- bare minimum to be used as a "clean slate" for another user to develop their own user-specific keymap
- what does pristine mean? no custom keycodes. no advanced features like tap dance or macros. basic mod taps and home row mods would be acceptable where their use is necessary
- standard layouts preferred in these keymaps, if possible
- should use [encoder map feature](https://docs.qmk.fm/#/feature_encoders?id=encoder-map), rather than `encoder_update_user()`
- default keymap should not enable VIA -- the VIA integration documentation requires a keymap called `via`
@@ -15,3 +15,5 @@ On this page we have documented keycodes between `0x00FF` and `0xFFFF` which are
|`QK_CLEAR_EEPROM`|`EE_CLR` |Reinitializes the keyboard's EEPROM (persistent memory) |
|`QK_MAKE` | |Sends `qmk compile -kb (keyboard) -km (keymap)`, or `qmk flash` if shift is held. Puts keyboard into bootloader mode if shift & control are held |
|`QK_REBOOT` |`QK_RBT` |Resets the keyboard. Does not load the bootloader |
!> Note: `QK_MAKE` requires `#define ENABLE_COMPILE_KEYCODE` in your config.h to function.
| `QUANTUM_PAINTER_NUM_IMAGES` | `8` | The maximum number of images/animations that can be loaded at any one time. |
| `QUANTUM_PAINTER_NUM_FONTS` | `4` | The maximum number of fonts that can be loaded at any one time. |
| `QUANTUM_PAINTER_CONCURRENT_ANIMATIONS` | `4` | The maximum number of animations that can be executed at the same time. |
| `QUANTUM_PAINTER_LOAD_FONTS_TO_RAM` | `FALSE` | Whether or not fonts should be loaded to RAM. Relevant for fonts stored in off-chip persistent storage, such as external flash. |
| `QUANTUM_PAINTER_PIXDATA_BUFFER_SIZE` | `32` | The limit of the amount of pixel data that can be transmitted in one transaction to the display. Higher values require more RAM on the MCU. |
| `QUANTUM_PAINTER_SUPPORTS_256_PALETTE` | `FALSE` | If 256-color palettes are supported. Requires significantly more RAM on the MCU. |
| `QUANTUM_PAINTER_SUPPORTS_NATIVE_COLORS` | `FALSE` | If native color range is supported. Requires significantly more RAM on the MCU. |
| `QUANTUM_PAINTER_DEBUG` | _unset_ | Prints out significant amounts of debugging information to CONSOLE output. Significant performance degradation, use only for debugging. |
| `QUANTUM_PAINTER_DISPLAY_TIMEOUT` | `30000` | This controls the amount of time (in milliseconds) that all displays will remain on after the last user input. If set to `0`, the display will remain on indefinitely. |
| `QUANTUM_PAINTER_TASK_THROTTLE`| `1` | This controls the amount of time (in milliseconds) that the Quantum Painter internal task will wait between each execution. Affects animations, display timeout, and LVGL timing if enabled. |
| `QUANTUM_PAINTER_NUM_IMAGES` | `8` | The maximum number of images/animations that can be loaded at any one time. |
| `QUANTUM_PAINTER_NUM_FONTS` | `4` | The maximum number of fonts that can be loaded at any one time. |
| `QUANTUM_PAINTER_CONCURRENT_ANIMATIONS` | `4` | The maximum number of animations that can be executed at the same time. |
| `QUANTUM_PAINTER_LOAD_FONTS_TO_RAM` | `FALSE` | Whether or not fonts should be loaded to RAM. Relevant for fonts stored in off-chip persistent storage, such as external flash. |
| `QUANTUM_PAINTER_PIXDATA_BUFFER_SIZE` | `1024` | The limit of the amount of pixel data that can be transmitted in one transaction to the display. Higher values require more RAM on the MCU. |
| `QUANTUM_PAINTER_SUPPORTS_256_PALETTE` | `FALSE` | If 256-color palettes are supported. Requires significantly more RAM on the MCU. |
| `QUANTUM_PAINTER_SUPPORTS_NATIVE_COLORS` | `FALSE` | If native color range is supported. Requires significantly more RAM on the MCU. |
| `QUANTUM_PAINTER_DEBUG` | _unset_ | Prints out significant amounts of debugging information to CONSOLE output. Significant performance degradation, use only for debugging. |
| `QUANTUM_PAINTER_DEBUG_ENABLE_FLUSH_TASK_OUTPUT` | _unset_ | By default, debug output is disabled while the internal task is flushing the display(s). If you want to keep it enabled, add this to your `config.h`. Note: Console will get clogged. |
Drivers have their own set of configurable options, and are described in their respective sections.
@@ -130,20 +130,18 @@ Note that until the tap-or-hold decision completes (which happens when either th
To better illustrate the tap-or-hold decision modes, let us compare the expected output of each decision mode in a handful of tapping scenarios involving a mod-tap key (`LSFT_T(KC_A)`) and a regular key (`KC_B`) with the `TAPPING_TERM` set to 200ms.
By default, mod-taps behave like `HOLD_ON_OTHER_KEY_PRESS`, while layer-taps behave like "Ignore Interrupt" out of the box. If you want "Ignore Interrupt"-like behaviour for mod-taps, you must enable `IGNORE_MOD_TAP_INTERRUPT`, or return `false` in the `get_hold_on_other_key_press` function for all mod-taps.
Note: "`kc` held" in the "Physical key event" column means that the key wasn't physically released yet at this point in time.
@@ -241,10 +239,8 @@ Example sequence 3 (Mod Tap):
| +--------------+ | |
+---------------------------|--------+
```
Based on previous examples, you might have expected the output of the above sequence to be `KC_A``KC_X`
since `SFT_T(KC_A)` is NOT held longer than the `TAPPING_TERM`.
However, the actual output would be capital `X` (`SHIFT` + `x`) due to reasons
explained under [Ignore Mod Tap Interrupt](#ignore-mod-tap-interrupt).
In the above sequence, `SFT_T(KC_A)` has been released before the end of its `TAPPING_TERM` and as such will be interpreted as`KC_A`,
followed by any key event that happened after the initial press of `SFT_T(KC_A)`. In this instance, the output would be `KC_A``KC_X`.
### Permissive Hold
@@ -300,7 +296,7 @@ However, this slightly different sequence will not be affected by the “permiss
In the sequence above the dual-role key is released before the other key is released, and if that happens within the tapping term, the “permissive hold” mode will still choose the tap action for the dual-role key, and the sequence will be registered as `al` by the host. We could describe this as a “rolling press” (the two keys' key down and key up events behave as if you were rolling a ball across the two keys, first pressing each key down in sequence and then releasing them in the same order).
?> The `PERMISSIVE_HOLD` option is not noticeable if you also enable `HOLD_ON_OTHER_KEY_PRESS` because the latter option considers both the “nested tap” and “rolling press” sequences like shown above as a hold action, not the tap action. `HOLD_ON_OTHER_KEY_PRESS` makes the Tap-Or-Hold decision earlier in the chain of key events, thus taking a precedence over `PERMISSIVE_HOLD`. This remark also applies to default mod-taps.
?> The `PERMISSIVE_HOLD` option is not noticeable if you also enable `HOLD_ON_OTHER_KEY_PRESS` because the latter option considers both the “nested tap” and “rolling press” sequences like shown above as a hold action, not the tap action. `HOLD_ON_OTHER_KEY_PRESS` makes the Tap-Or-Hold decision earlier in the chain of key events, thus taking a precedence over `PERMISSIVE_HOLD`.
For more granular control of this feature, you can add the following to your `config.h`:
@@ -356,8 +352,6 @@ An example of a sequence that is affected by the “hold on other key press” m
Normally, if you do all this within the `TAPPING_TERM` (default: 200ms), this will be registered as `al` by the firmware and host system. With the `HOLD_ON_OTHER_KEY_PRESS` option enabled, the Layer Tap key is considered as a layer switch if another key is pressed, and the above sequence would be registered as `KC_RGHT` (the mapping of `L` on layer 2).
?> The `HOLD_ON_OTHER_KEY_PRESS` option is essentially redundant with the default mod-tap behaviour. The only notable difference is that `HOLD_ON_OTHER_KEY_PRESS` reduces the delay before the key events are made visible to the host.
For more granular control of this feature, you can add the following to your `config.h`:
To enable this setting, add this to your `config.h`:
```c
#define IGNORE_MOD_TAP_INTERRUPT
```
?> This option affects only the Mod Tap keys; it does not affect other dual-role keys such as Layer Tap.
By default, the tap-or-hold decision for Mod Tap keys strongly prefers the hold action. If you press a Mod Tap key, then press another key while still holding the Mod Tap key down, the Mod Tap press will be handled as a modifier hold even if the Mod Tap key is then released within the tapping term, and irrespective of the order in which those keys are released. Using options such as `PERMISSIVE_HOLD` or `HOLD_ON_OTHER_KEY_PRESS` will not affect the functionality of Mod Tap keys in a major way (these options would still affect the delay until the common code for dual-role keys finishes its tap-or-hold decision, but then the special code for Mod Tap keys will override the result of that decision and choose the hold action if another key was pressed). In fact, by default, the tap-or-hold decision for Mod Tap keys is done in the same way as if the `HOLD_ON_OTHER_KEY_PRESS` option was enabled, but without the decreased delay provided by `HOLD_ON_OTHER_KEY_PRESS`.
If the `IGNORE_MOD_TAP_INTERRUPT` option is enabled, Mod Tap keys are no longer treated as a special case, and their behavior will match the behavior of other dual-role keys such as Layer Tap. Then the behavior of Mod Tap keys can be further tuned using other options such as `PERMISSIVE_HOLD` or `HOLD_ON_OTHER_KEY_PRESS`.
An example of a sequence that will be affected by the `IGNORE_MOD_TAP_INTERRUPT` option (assuming that options like `PERMISSIVE_HOLD` or `HOLD_ON_OTHER_KEY_PRESS` are not enabled):
-`SFT_T(KC_A)` Down
-`KC_X` Down
-`SFT_T(KC_A)` Up
-`KC_X` Up
```
TAPPING_TERM
+---------------------------|--------+
| +-------------+ | |
| | SFT_T(KC_A) | | |
| +-------------+ | |
| +--------------+ | |
| | KC_X | | |
| +--------------+ | |
+---------------------------|--------+
```
Normally, this would send a capital `X` (`SHIFT`+`x`), even if the sequence is performed faster than the `TAPPING_TERM`. However, if the `IGNORE_MOD_TAP_INTERRUPT` option is enabled, the `SFT_T(KC_A)` key must be held longer than the `TAPPING_TERM` to register the hold action. A quick tap will output `ax` in this case, while a hold will still output a capital `X` (`SHIFT`+`x`).
However, if the `HOLD_ON_OTHER_KEY_PRESS` option is enabled in addition to `IGNORE_MOD_TAP_INTERRUPT`, the above sequence will again send a capital `X` (`SHIFT`+`x`) even if performed faster than the `TAPPING_TERM`. The difference from the default configuration is that by default the host will receive the key events only after the `SFT_T(KC_A)` key is released, but with the `HOLD_ON_OTHER_KEY_PRESS` option, the host will start receiving key events when the `KC_X` key is pressed.
For more granular control of this feature, you can add the following to your `config.h`:
```c
#define HOLD_ON_OTHER_KEY_PRESS_PER_KEY
```
?> This option affects *all* dual-role keys.
You can then add the following function to your keymap:
// Do not force the mod-tap key press to be handled as a modifier
// if any other key was pressed while the mod-tap key is held down.
returnfalse;
default:
// Force the dual-role key press to be handled as a modifier if any
// other key was pressed while the mod-tap key is held down.
returntrue;
}
}
```
Note that you must return `false` in `get_hold_on_other_key_press` in order to apply `IGNORE_MOD_TAP_INTERRUPT` for a certain mod-tap key.
?> `IGNORE_MOD_TAP_INTERRUPT[_PER_KEY]` is being progressively phased out to align the (default) behavior and configuration of mod-taps with the rest of dual-role keys.
## Quick Tap Term
When the user holds a key after tapping it, the tapping function is repeated by default, rather than activating the hold function. This allows keeping the ability to auto-repeat the tapping function of a dual-role key. `QUICK_TAP_TERM` enables fine tuning of that ability. If set to `0`, it will remove the auto-repeat ability and activate the hold function instead.
Targeting STM32 boards where WS2812 support is offloaded to an SPI hardware device. The advantage is that the use of DMA offloads processing of the WS2812 protocol from the MCU. `RGB_DI_PIN` for this driver is the configured SPI MOSI pin. Due to the nature of repurposing SPI to drive the LEDs, the other SPI pins, MISO and SCK, **must** remain unused. To configure it, add this to your rules.mk:
Targeting STM32 boards where WS2812 support is offloaded to an SPI hardware device. The advantage is that the use of DMA offloads processing of the WS2812 protocol from the MCU. `WS2812_DI_PIN` for this driver is the configured SPI MOSI pin. Due to the nature of repurposing SPI to drive the LEDs, the other SPI pins, MISO and SCK, **must** remain unused. To configure it, add this to your rules.mk:
```make
WS2812_DRIVER= spi
@@ -183,7 +183,7 @@ This can be configured for bitbang, PWM and SPI.
Note: This only applies to STM32 boards.
To configure the `RGB_DI_PIN` to open drain configuration add this to your config.h file:
To configure the `WS2812_DI_PIN` to open drain configuration add this to your config.h file:
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.