Compare commits

...
118 Commits
Author SHA1 Message Date
Joel Challis 08c662f286 Remove shebang from MSYS workaround in bootstrap script (#26442) 2026-09-05 17:30:51 +01:00
Joel Challis 570401148e Implement UV installer path workaround for Msys (#26441) 2026-09-05 12:25:07 +01:00
2a5dd4317a Add keyboard Orbiter (#26311)
* Initial commit orbiter

Left side support. Need to look into split support next.

* Start adding split configurations

* Not really working but it compiles

* WORKING CONFIG

* Add via support

remove via json file later

* added oled driver and i2c configuration

* update to correct driver block macros

* fix faulty configuration for i2c

* remove via support

* enable console by default

* rework layout slightly

* fix default keymap

* cleanup

* fix comment

* update readme

* add copyright headers to pass lint check

* apply clang-formatter

* refactor folder structure slightly

* quickfix name

* bump readme

* rework for data driven conf

* apply formatter json and update naming

* forgot one

* slight adjustment

* use smaller copyright

* minor change to name

* Apply suggestions from code review

Co-authored-by: Joel Challis <git@zvecr.com>

* remove .mk file and rename oled.c

* apply formatter

* git-format text

* Use DMA offloading

* add dma config

* remove lto

* Update keyboards/supercrisp/orbiter/readme.md

Co-authored-by: Joel Challis <git@zvecr.com>

---------

Co-authored-by: rasmus <rasmus_lindy@hotmail.com>
Co-authored-by: Joel Challis <git@zvecr.com>
2026-09-05 00:03:33 -07:00
JubakubaandJoel Challis 967b5932bf Add Aftermarket Keycult (Per Key RGB) PCB Support (#26409)
* Add Aftermarket Keycult (Per Key RGB) PCB Support

* Well since local lint and the real lint argue...I'm keeping to what I know and removing rules.mk.  I'll fix C formatting later...again local lint thinks it's great.

* literally lowercased already locally and git has it cached...I hate working with git.

* c fix

* c fix2

* c...sure would be nice to see the errors so I'm not just guessing...

* magic?

* Suggestions

* Update keyboards/jubakuba/aftermarket_keycult_tkl/keymaps/default/keymap.c

Co-authored-by: Joel Challis <git@zvecr.com>

* Update keyboards/jubakuba/aftermarket_keycult_tkl/keyboard.json

Co-authored-by: Joel Challis <git@zvecr.com>

---------

Co-authored-by: Joel Challis <git@zvecr.com>
2026-09-04 23:51:31 -07:00
leyew e6a31e474a Add Stinga keyboard (#26411) 2026-09-04 23:34:41 +01:00
Joel Challis f07f83fd45 Fix UnicodeDecodeError in git_check_deviation (#26439)
Fix UnicodeDecodeError in git_check_deviation

Decode git log output to bytes to prevent Unicode errors.
2026-09-04 09:50:06 +08:00
Nick Brassel 3c73e928ab Bootstrap: environmental sanitisation, package install robustness (#26433)
* Sanitise more.

* Let's brute-force Gentoo prep.

* Quiet, Gentoo.

* Intel macOS, `brew` unsupported.

* Intel macOS, `brew` unsupported.

* Throttle.

* Apparently there's a free `macos-26-intel` runner.

* More safety.

* More safety.
2026-09-03 09:22:27 +10:00
veypatch 4e67c28c17 Fix RGB matrix layout for Splitkb Halcyon/Aurora corne (#26424) 2026-09-02 09:06:42 -06:00
zvecr 193078f3ea Merge branch 'develop' 2026-08-31 23:04:36 +01:00
zvecr 7f5cd5db14 Merge point for 2026q3 breaking changes 2026-08-31 23:04:07 +01:00
zvecr e35948097f Add changelog 2026-08-31 04:28:22 +01:00
Drashna Jaelre 1c729db989 Update LED Matrix documentation to include JSON config (#26425) 2026-08-31 02:59:52 +01:00
Joel Challis 698894aef0 Fix 'qmk generate-develop-pr-list' for ghapi v2 (#26428) 2026-08-30 23:45:18 +01:00
Joel Challis 4b16b5e520 Rework Plover HID to use Steno keycodes (#26421) 2026-08-27 02:13:00 +01:00
Drashna Jaelreandフィルターペーパー 0db4603acb Update RGB Matrix documentation to include JSON config (#26187)
* Update RGB Matrix documentation to include JSON config

* Update docs/features/rgb_matrix.md

Co-authored-by: フィルターペーパー <76888457+filterpaper@users.noreply.github.com>

* Fixup

---------

Co-authored-by: フィルターペーパー <76888457+filterpaper@users.noreply.github.com>
2026-08-26 15:25:26 +08:00
Joel Challis 4dfef5c638 Initial rework of steno feature (#26273) 2026-08-25 17:15:01 +01:00
4b2c8b31b1 Update encoder documents for json config (#26188)
* Update encoder documents for json config

* encoder map

* Apply suggestions from code review

Co-authored-by: フィルターペーパー <76888457+filterpaper@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Fix sentence to be correct

---------

Co-authored-by: フィルターペーパー <76888457+filterpaper@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-08-25 07:40:13 +08:00
Joel Challis 8b783cad10 Align USB endpoint buffers to fix RP2040 Plover HID issues (#26417) 2026-08-25 00:19:22 +01:00
Joel Challis 19b72554f8 Fix EECONFIG_MODULE_DATA_SIZE for modules with zero provisioned eeconfig (#26414) 2026-08-21 21:38:36 +01:00
Joel Challis b0fd02bd21 Update satisfaction75 to only use keyboard datablock (#26320) 2026-08-20 00:36:09 +01:00
Joel Challis 37142b6b8f Migrate remaining VIA_EEPROM_CUSTOM_CONFIG_SIZE to EECONFIG_KB_DATA_SIZE (#26321) 2026-08-20 00:35:50 +01:00
Joel Challis 65315a8315 Resolve recursive keyboard aliases when locating userspace keymaps (#26402) 2026-08-20 00:35:07 +01:00
Joel Challis a625d49dcb Convert novelkeys/nk87 to use RGB Matrix (#26349) 2026-08-19 20:41:23 +01:00
QMK Bot 7b7044830e Merge remote-tracking branch 'origin/master' into develop 2026-08-17 23:12:05 +00:00
Jacek Królikowski 3f26a9232a Add Revolt (rev2) keyboard (#26180) 2026-08-18 00:11:26 +01:00
yiancarandJoel Challis ecdac18043 Keycult TKL Updates (#26385)
* Keycult TKL Updates

* Update keyboards/keycult/keycult_tkl/keyboard.json

Co-authored-by: Joel Challis <git@zvecr.com>

---------

Co-authored-by: Joel Challis <git@zvecr.com>
2026-08-13 11:19:51 -07:00
bc744bbcaa Fix ChibiOS virtual serial short packet receive (#26356)
* Core: fix ChibiOS virtual serial short packet receive

Signed-off-by: Giridhar <giridharpavan593@gmail.com>

* Add handwired/onekey virtser test keymap

---------

Signed-off-by: Giridhar <giridharpavan593@gmail.com>
Co-authored-by: Giridhar <giridharpavan593@gmail.com>
Co-authored-by: zvecr <git@zvecr.com>
2026-08-12 23:52:49 -07:00
Pascal Getreuer d7ad3bf8aa [Core] Fix to make Repeat Key QK_REP work with Key Overrides. (#26312) 2026-08-12 21:06:14 +01:00
QMK Bot bd823862c1 Merge remote-tracking branch 'origin/master' into develop 2026-08-11 23:04:36 +00:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 96c3e85e59 Bump JamesIves/github-pages-deploy-action from 4.8.0 to 4.9.0 (#26398)
Bumps [JamesIves/github-pages-deploy-action](https://github.com/jamesives/github-pages-deploy-action) from 4.8.0 to 4.9.0.
- [Release notes](https://github.com/jamesives/github-pages-deploy-action/releases)
- [Commits](https://github.com/jamesives/github-pages-deploy-action/compare/v4.8.0...v4.9.0)

---
updated-dependencies:
- dependency-name: JamesIves/github-pages-deploy-action
  dependency-version: 4.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-12 00:03:56 +01:00
QMK Bot 4742ea9ac5 Merge remote-tracking branch 'origin/master' into develop 2026-08-10 18:29:41 +00:00
14774c8482 Add license headers to splitkb/aurora glcdfont.c files (#26382)
* Add license headers to splitkb/aurora glcdfont.c files

`qmk lint` requires a license header on every code file in a keyboard's
directory tree, but the three Aurora glcdfont.c files have none. Since
lint walks each parent directory of the target, this makes
`qmk lint -kb splitkb/aurora/{corne,lily58,sweep}/rev1` fail for every
user of those boards, including on keymaps they have no control over.

The three files are byte-identical copies of a Corne font, so use the
same `Copyright <year> QMK` attribution already used for the comparable
file in keyboards/helix/glcdfont.c rather than assigning authorship.

Lint now passes for all three boards.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Update keyboards/splitkb/aurora/corne/glcdfont.c

Co-authored-by: Joel Challis <git@zvecr.com>

* Update keyboards/splitkb/aurora/lily58/glcdfont.c

Co-authored-by: Joel Challis <git@zvecr.com>

* Update keyboards/splitkb/aurora/sweep/glcdfont.c

Co-authored-by: Joel Challis <git@zvecr.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Joel Challis <git@zvecr.com>
2026-08-10 11:28:50 -07:00
Joel Challis c7d8bdfce5 Update keyboards to implement led_update_kb instead of led_set (#26388) 2026-08-08 23:06:15 +01:00
QMK Bot a3658c1f09 Merge remote-tracking branch 'origin/master' into develop 2026-08-08 10:19:39 +00:00
Benoit Brummer 9caa5f871d [ploopyco/trackball_thumb] Update readme.md with correct flashing instructions (#26287)
Flashing is currently set to the middle click, not button 4 (per https://github.com/qmk/qmk_firmware/blob/master/keyboards/ploopyco/trackball_thumb/info.json )
2026-08-08 03:18:55 -07:00
Joel Challis 68c82976cd Update magic_force/mf17 to WS2812 PWM driver (#26384) 2026-08-05 19:39:13 +01:00
Arca Artem beb57311cb qp_lvgl: always signal flush ready even with no display (#26275)
qp_lvgl_flush() called lv_disp_flush_ready() only inside the
`if (selected_display)` block. When LVGL invokes the flush callback while
selected_display is NULL, the callback returns without ever signalling
completion, so LVGL keeps the flush marked "in progress" and stalls all
further rendering.

Move lv_disp_flush_ready() out of the conditional so it is always called,
per LVGL's contract that every flush_cb must signal ready exactly once.
2026-08-05 19:36:31 +01:00
QMK Bot af6115e215 Merge remote-tracking branch 'origin/master' into develop 2026-08-05 09:25:47 +00:00
Hannah Kemplin 0456ffb38e Update inaccessible external links in contributing documentation (#26374) 2026-08-05 19:25:07 +10:00
QMK Bot 827bd363f9 Merge remote-tracking branch 'origin/master' into develop 2026-08-05 05:46:59 +00:00
437025dcb1 Add HEER S1 macropad (#26373)
* Add HEER S1 macropad

* Address review feedback for HEER S1

- readme: add product image, correct maintainer link and availability URL
- config.h: drop OLED_DISPLAY_ADDRESS, already the driver default
- keyboard.json: drop the i2c block, which only feeds split transport
- move the OLED to heer_s1.c as oled_task_kb
- default keymap reduced to keymaps[] and encoder_map[]

The default keymap also configured GP16/GP17 as GPIO inputs at boot. Those are
the OLED's I2C SDA/SCL lines, so it tore down the display bus on every start.
The encoder switches are on GP2/GP14. Removed along with the rest of the code.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Update keyboards/heer_s1/keymaps/default/keymap.c

Co-authored-by: Joel Challis <git@zvecr.com>

* Update keyboards/heer_s1/keymaps/default/keymap.c

Co-authored-by: Joel Challis <git@zvecr.com>

* Update keyboards/heer_s1/keymaps/default/keymap.c

Co-authored-by: Joel Challis <git@zvecr.com>

* Update keyboards/heer_s1/keymaps/default/keymap.c

Co-authored-by: Joel Challis <git@zvecr.com>

* Update keyboards/heer_s1/keyboard.json

Co-authored-by: Joel Challis <git@zvecr.com>

* Update keyboards/heer_s1/readme.md

Co-authored-by: Joel Challis <git@zvecr.com>

* Update keyboards/heer_s1/keymaps/default/keymap.c

Co-authored-by: Joel Challis <git@zvecr.com>

* Update keyboards/heer_s1/keyboard.json

Co-authored-by: Joel Challis <git@zvecr.com>

* Update keyboards/heer_s1/keyboard.json

Co-authored-by: Joel Challis <git@zvecr.com>

* Fix duplicated enumerators in default keymap

The suggested enum replacement was applied alongside the original entries
rather than in place of them, leaving L_BASE, L_MEDIA and L_EDIT declared
twice.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Update keyboards/heer_s1/readme.md

Co-authored-by: Joel Challis <git@zvecr.com>

* Update keyboards/heer_s1/keyboard.json

Co-authored-by: Joel Challis <git@zvecr.com>

---------

Co-authored-by: HEER <heerelectronix@gmail.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Joel Challis <git@zvecr.com>
2026-08-04 22:46:16 -07:00
QMK Bot 0a1ecc7e05 Merge remote-tracking branch 'origin/master' into develop 2026-08-05 05:46:06 +00:00
Kento LauzonandJoel Challis a2dab6d6bd add keotl/11squares keyboard (#26359)
* add 11squares

* fix keyboard.json

* clang-format

* fix license attribution

* Apply suggestions from code review

Co-authored-by: Joel Challis <git@zvecr.com>

---------

Co-authored-by: Joel Challis <git@zvecr.com>
2026-08-04 22:45:23 -07:00
QMK Bot fe19d07c82 Merge remote-tracking branch 'origin/master' into develop 2026-08-03 05:12:38 +00:00
yiancar 54881c6845 Stratum 80 (#26372) 2026-08-03 06:12:09 +01:00
Feags 54df1890f6 [Keyboard] Add Krado Industries Promenade RP24HS (#26172) 2026-08-03 06:11:52 +01:00
QMK Bot 009efa8620 Merge remote-tracking branch 'origin/master' into develop 2026-08-03 01:02:46 +00:00
Joel Challis 332fa30e17 Update more broken LUFA links (#26383) 2026-08-03 02:02:07 +01:00
Joel Challis 2787ebb7ac Make framebuffer effects honour rgb_matrix_map_row_column_to_led (#26294) 2026-08-02 20:10:52 +01:00
Joel Challis ae0aaa50dc Port typing_heatmap animation to LED Matrix (#26300) 2026-08-02 20:10:35 +01:00
Joel Challis 5351ac6c66 Use core spi_init implementation for gmmk/gmmk2/p96 (#26344) 2026-08-02 20:10:06 +01:00
Cipulot a000551018 Change preprocessor directive for random solenoid firing (#26377)
Fix define verification
2026-08-01 19:39:32 -07:00
QMK Bot 4699895f73 Merge remote-tracking branch 'origin/master' into develop 2026-08-02 02:01:13 +00:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> d6235b9627 Bump postcss from 8.5.15 to 8.5.25 in /builddefs/docsgen (#26380)
Bumps [postcss](https://github.com/postcss/postcss) from 8.5.15 to 8.5.25.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.5.15...8.5.25)

---
updated-dependencies:
- dependency-name: postcss
  dependency-version: 8.5.25
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-02 03:00:30 +01:00
Drashna Jaelre 74800d0cdf Add STM32_USB_USE_OTG2 to USB_ENDPOINTS_ARE_REORDERABLE (#26369) 2026-07-31 11:48:45 +10:00
QMK Bot ac62ad57ec Merge remote-tracking branch 'origin/master' into develop 2026-07-28 01:19:47 +00:00
Álvaro A. VolpatoandJoel Challis 4ffb1ab16c Adds support for mode M65V2 (#26049)
Co-authored-by: Joel Challis <git@zvecr.com>
2026-07-28 11:19:04 +10:00
QMK Bot de06b15a68 Merge remote-tracking branch 'origin/master' into develop 2026-07-24 20:48:35 +00:00
Javier San Félix a53ce75641 [Keyboard] Add Mithril (#26212) 2026-07-24 21:32:16 +01:00
Christian C. Berclaz b75ec7d85a Addition of the Ymdk Oni Tsangan/HHKB-like pcb (#25230) 2026-07-24 21:25:14 +01:00
QMK Bot d5582b3e9d Merge remote-tracking branch 'origin/master' into develop 2026-07-24 01:31:15 +00:00
Linn f0e090f67a Update emerge-webrsync to emaint sync (#26352)
Gentoo users using git to sync cannot use `emerge-webrsync` command, but it seems like `emaint sync` still works with the webrsync method. Furthermore, running the version with `emerge-webrsync` on my Gentoo computer, which syncs with git, seemed to break syncing until manually fixed (by deleting and reinstalling the gentoo repository)
2026-07-24 02:30:34 +01:00
QMK Bot d720540949 Merge remote-tracking branch 'origin/master' into develop 2026-07-21 23:42:35 +00:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 3ef9860ee1 Bump actions/labeler from 6 to 7 (#26351)
Bumps [actions/labeler](https://github.com/actions/labeler) from 6 to 7.
- [Release notes](https://github.com/actions/labeler/releases)
- [Commits](https://github.com/actions/labeler/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/labeler
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-22 00:41:55 +01:00
QMK Bot 86ac91f73e Merge remote-tracking branch 'origin/master' into develop 2026-07-19 20:56:01 +00:00
Joel Challis 95b9016a3b Fix STM32G0B1 not booting after ChibiOS update (#26342) 2026-07-19 21:55:20 +01:00
QMK Bot e2fd609ebf Merge remote-tracking branch 'origin/master' into develop 2026-07-19 03:55:10 +00:00
dbd9b0a379 NK65 Gen2 Keyboard (#26334)
* Initial commit

* Cleanup

* Update keyboards/novelkeys/nk65_gen2/keymaps/default/keymap.c

Co-authored-by: Joel Challis <git@zvecr.com>

* Update keyboards/novelkeys/nk65_gen2/config.h

Co-authored-by: Joel Challis <git@zvecr.com>

* Update keyboards/novelkeys/nk65_gen2/mcuconf.h

Co-authored-by: Joel Challis <git@zvecr.com>

* Update keyboards/novelkeys/nk65_gen2/readme.md

Co-authored-by: Joel Challis <git@zvecr.com>

* Update keyboards/novelkeys/nk65_gen2/halconf.h

Co-authored-by: Joel Challis <git@zvecr.com>

* Update keyboards/novelkeys/nk65_gen2/keymaps/default/keymap.c

Co-authored-by: Joel Challis <git@zvecr.com>

* Simplify RGB matrix color settings in keymap.c

* Update keyboards/novelkeys/nk65_gen2/readme.md

Co-authored-by: Joel Challis <git@zvecr.com>

* Update keyboards/novelkeys/nk65_gen2/readme.md

Co-authored-by: Joel Challis <git@zvecr.com>

---------

Co-authored-by: yiancar <yiancar@gmail.com>
Co-authored-by: Joel Challis <git@zvecr.com>
2026-07-18 20:54:32 -07:00
Joel Challis b0a6e8e281 Be lazier in loading keyboard schema for new-keyboard (#26340) 2026-07-18 22:47:05 +01:00
Joel Challis cf01e22447 First pass of ruff check fixes (#26257) 2026-07-18 04:06:19 +01:00
QMK Bot bea6a83a12 Merge remote-tracking branch 'origin/master' into develop 2026-07-18 00:07:20 +00:00
Joel Challis b8bf40eb96 Avoid computing _get_default_distrib_path when QMK_DISTRIB_DIR is set (#26339) 2026-07-18 10:06:00 +10:00
Iuri RibeiroandJoel Challis 2649ec02c9 Fix SEQUENCER_ENABLE so the sequencer feature builds again (#26322)
* Make the sequencer feature build again

SEQUENCER_ENABLE only set MUSIC_ENABLE, so -DSEQUENCER_ENABLE was never
defined and neither sequencer.c nor process_sequencer.c were compiled;
process_sequencer.c also lost the includes it depends on. Wire the make
target up like the other features and add the missing includes.

* Include sequencer.h in keyboard.c for sequencer_task()

* Update builddefs/common_features.mk

Co-authored-by: Joel Challis <git@zvecr.com>

---------

Co-authored-by: Joel Challis <git@zvecr.com>
2026-07-13 17:38:42 -07:00
Nick Brassel a5fb55b99a Add _noeeprom variants of backlight enable/disable. (#26328) 2026-07-13 10:58:12 +01:00
QMK Bot 556bb7e020 Merge remote-tracking branch 'origin/master' into develop 2026-07-11 05:33:19 +00:00
yi chen a738fad372 [Docs] Clarify Python HID package name in Raw HID docs (#26318)
The PyPI package for the Python HID library used here is called `hid`
(https://pypi.org/project/hid/), but the docs called it "pyhidapi" while
linking to the `hid` package page. There is also a separate, unrelated,
unmaintained package literally named `pyhidapi` on PyPI, so a reader
following the doc text as written can end up installing the wrong package.

Update the library list and prose to say `hid`, and add a short tip
covering the install/import command and calling out the package to avoid.

Fixes #26047
2026-07-11 06:32:34 +01:00
QMK Bot 470a81235a Merge remote-tracking branch 'origin/master' into develop 2026-07-11 05:20:01 +00:00
Assem Mohamed 99b8f3bf4e Add handwired keyboard "handwired/tnx_corne_f401" (#26032) 2026-07-11 06:19:17 +01:00
Joel Challis f533c6113d Fix use of via.h (#26316) 2026-07-08 11:43:31 +01:00
Joel Challis 59188e616b Tidy sawnsprojects/satxri6key (#26317) 2026-07-08 11:43:14 +01:00
Joel Challis 12139903ce Require --keyboard for some CLI subcommands (#26308) 2026-07-08 01:41:47 +01:00
QMK Bot 817bbaa5f9 Merge remote-tracking branch 'origin/master' into develop 2026-07-07 22:15:29 +00:00
Alexis "Horgix" Chotard 2dc5e39798 docs(features): Add missing inline code syntax for KC_ESC (#26314) 2026-07-07 23:14:50 +01:00
QMK Bot da481f5cc4 Merge remote-tracking branch 'origin/master' into develop 2026-07-06 20:09:23 +00:00
Harry CuttsandJoel Challis 7a15cd2482 Add "handwired" TwentyPad macro pad (#26264)
* Add "handwired" TwentyPad macro pad

TwentyPad is 20-key macro pad I created as a hobby project. Its
configuration is based on ez_maker/directpins/teensy_2, with the
bootloader and layout changed.

* Host the image on Imgur

Co-authored-by: Joel Challis <git@zvecr.com>

---------

Co-authored-by: Joel Challis <git@zvecr.com>
2026-07-06 13:08:39 -07:00
Harrison 428b1cd568 Use memmove for overlapping copies in RGB/LED matrix last-hit tracker (#26306)
Use memmove for overlapping copies in RGB/LED matrix last-hit tracker
2026-07-06 12:30:13 -07:00
QMK Bot e38f3097cb Merge remote-tracking branch 'origin/master' into develop 2026-07-03 03:49:08 +00:00
Pascal GetreuerandDrashna Jaelre cf93bbb78f [Docs] Tap-hold doc improvements and suggest an HRMs starter recipe (#26284)
* Enhance tap-hold docs.

* Minor edits.

* Move note on Quick Tap to a sub bullet for visibility.

Co-authored-by: Drashna Jaelre <drashna@live.com>

---------

Co-authored-by: Drashna Jaelre <drashna@live.com>
2026-07-03 11:48:28 +08:00
QMK Bot 9f75ab2c92 Merge remote-tracking branch 'origin/master' into develop 2026-06-26 13:20:50 +00:00
Nick Brassel 5734360a86 Restrict the EXTRAKEY_ENABLE System Control HID usage range. (#26295) 2026-06-25 16:29:47 +10:00
Joel Challis 0ec0cdde81 Consistently handle datablock init (#26282) 2026-06-24 20:36:51 +01:00
QMK Bot ee9354d36e Merge remote-tracking branch 'origin/master' into develop 2026-06-23 20:31:27 +00:00
Joel Challis dd905c9531 Split ducky/one2sf/1967st into ansi/iso variants (#26277) 2026-06-23 15:31:31 +01:00
Joel Challis 963986c475 Automatically handle duplicate matrix LED mappings (#26278) 2026-06-22 18:31:14 +01:00
QMK Bot aae4189aa4 Merge remote-tracking branch 'origin/master' into develop 2026-06-22 17:28:58 +00:00
Joel Challis fd624d016b Fix nifty_numpad issues (#26283)
* eeconfig_init_kb_datablock should not call eeconfig_init_user_datablock

* Fix lint warnings
2026-06-21 10:49:42 +01:00
gitaen 6741f9dc26 Add converter/thinkpad_t6x/pico_t61 keyboard (#26266)
This adds support for Frank Adams pico_t61 board which is similar to
the currently supported converter/thinkpad_t6x/rpi_pico one.

Common options and shared default keymap have been moved to the upper
directory (keyboards/converter/thinkpad_t6x).
2026-06-19 19:40:51 +01:00
QMK Bot f8910d3a60 Merge remote-tracking branch 'origin/master' into develop 2026-06-19 16:32:31 +00:00
Arca Artem 1d2f52e407 process_key_lock: clear entire key state in cancel_key_lock() (#26269)
cancel_key_lock() called UNSET_KEY_STATE(0x0), which expands to clearing
only bit 0 of key_state[0]. The lock state is a 256-bit map spread across
key_state[0..3], so every locked key other than keycode 0x00 stayed
latched after a cancel.

Zero all four words so cancel_key_lock() releases every locked key, as
its name and its public declaration in process_key_lock.h imply.
2026-06-19 17:24:11 +01:00
Jack Sangdahl 746eff22db Add additional layouts for mkh_studio/bully (#26271)
* Add extra spacebar layouts

- Rename LAYOUT -> LAYOUT_all
  - Resize keys to not be 0.5u tall
- Add layout alias for the above
- Add LAYOUT_split_space
- Add LAYOUT_full_space

* Remove whitepsace
2026-06-18 15:59:10 -07:00
Joel Challis d36397fdd4 Implement Plover HID for VUSB (#26267) 2026-06-19 06:55:21 +10:00
Joel Challis 8522bb342d Enable modules to persist data (#26201) 2026-06-18 18:43:32 +01:00
precondition 721affff7b repeat_key.c: add implementation for get_last_record (#26263)
The `get_last_record` signature was present in repeat_key.h but without
any implementation in repeat_key.c which caused compilation errors for
any user of `get_last_record`.
2026-06-18 18:41:12 +01:00
gitaen 4f6c5d2745 Remove pin ordering restriction in RP2040 ps2 driver (#26256) 2026-06-15 09:36:02 +10:00
Nick Brassel 92dc82ae08 Plover HID cleanup. (#26262) 2026-06-15 08:33:35 +10:00
b64014d5df Custom plover HID report type (#26018)
Co-authored-by: Nick Brassel <nick@tzarc.org>
Co-authored-by: dnaq <dnaq@users.noreply.github.com>
2026-06-14 12:38:34 +10:00
Puneet DixitandDeepak kudi 0d401d1182 Preserve Azoteq mouse buttons (#26248)
Co-authored-by: Deepak kudi <deepakkudi23@adsl-172-10-9-116.dsl.sndg02.sbcglobal.net>
2026-06-14 09:04:01 +10:00
QMK Bot 6ada0933db Merge remote-tracking branch 'origin/master' into develop 2026-06-13 21:20:24 +00:00
QMK Bot 0515002e7d Merge remote-tracking branch 'origin/master' into develop 2026-06-13 12:29:41 +00:00
QMK Bot 7f702d2262 Merge remote-tracking branch 'origin/master' into develop 2026-06-13 12:06:29 +00:00
QMK Bot 6a0e2a8868 Merge remote-tracking branch 'origin/master' into develop 2026-06-13 11:30:00 +00:00
QMK Bot 90082403de Merge remote-tracking branch 'origin/master' into develop 2026-06-10 23:54:21 +00:00
QMK Bot cffafbbdc7 Merge remote-tracking branch 'origin/master' into develop 2026-06-09 18:27:28 +00:00
QMK Bot 55be8f2c2b Merge remote-tracking branch 'origin/master' into develop 2026-06-08 00:37:23 +00:00
QMK Bot df94ffcc66 Merge remote-tracking branch 'origin/master' into develop 2026-06-03 21:49:34 +00:00
QMK Bot ee74da3a4d Merge remote-tracking branch 'origin/master' into develop 2026-06-01 11:34:14 +00:00
QMK Bot 480d808683 Merge remote-tracking branch 'origin/master' into develop 2026-06-01 08:08:15 +00:00
zvecr 62a8db33a3 Branch point for 2026q3 Breaking Change 2026-06-01 07:59:12 +01:00
337 changed files with 11051 additions and 2542 deletions
+22 -9
View File
@@ -83,32 +83,34 @@ jobs:
- name: Install base dependencies
run: |
# Attempt to run the package installation up to 10 times to mitigate transient network issues
ok=''
for n in $(seq 1 10); do
{
echo "Attempt #$n of 10 to install base dependencies:"
case "${{ matrix.distribution }}" in
*ubuntu*|*debian*)
apt-get update
apt-get install -y sudo git passwd
apt-get update &&
apt-get install -y sudo git passwd
;;
*fedora*|*rockylinux*|*almalinux*)
dnf install -y sudo git passwd findutils # findutils=xargs
;;
*suse*)
zypper --non-interactive refresh
zypper --non-interactive install sudo git shadow findutils tar # findutils=xargs
zypper --non-interactive refresh &&
zypper --non-interactive install sudo git shadow findutils tar # findutils=xargs
;;
*gentoo*)
emerge-webrsync
emerge --noreplace --ask=n sudo dev-vcs/git shadow findutils # findutils=xargs
{ emaint sync -a || emerge --sync --quiet || emerge-webrsync -q ; } &&
emerge --noreplace --ask=n sudo dev-vcs/git shadow findutils # findutils=xargs
;;
*archlinux*|*cachyos*|*manjaro*)
pacman -Syu --noconfirm
pacman -S --noconfirm sudo git
pacman -Syu --noconfirm &&
pacman -S --noconfirm sudo git
;;
esac
} && break || sleep 10
} && { ok=1; break ; } || sleep 10
done
[ -n "$ok" ] || exit 1
# Fix PAM configuration for sudo in containers
# Fix /etc/shadow permissions - common issue in container environments
@@ -196,10 +198,21 @@ jobs:
- macos-15 # Apple Silicon ARM64
- macos-15-intel # Intel x64
- macos-26 # Apple Silicon ARM64
- macos-26-intel # Intel x64
runs-on: ${{ matrix.os }}
steps:
- name: Install base dependencies
run: |
# Attempt to run the brew update up to 10 times to mitigate transient issues
for n in $(seq 1 10); do
brew update && exit 0
brew update-reset || true
sleep 10
done
exit 1
- name: Checkout repository
uses: actions/checkout@v7
with:
+1 -1
View File
@@ -57,7 +57,7 @@ jobs:
- name: Deploy
if: ${{ github.event_name == 'push' && github.repository == 'qmk/qmk_firmware' }}
uses: JamesIves/github-pages-deploy-action@v4.8.0
uses: JamesIves/github-pages-deploy-action@v4.9.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
branch: gh-pages
+1 -1
View File
@@ -10,4 +10,4 @@ jobs:
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v6
- uses: actions/labeler@v7
+8 -8
View File
@@ -187,9 +187,9 @@ include $(COMMUNITY_RULES_MK)
ifneq ($(COMMUNITY_MODULES),)
$(INTERMEDIATE_OUTPUT)/src/community_config.h: $(KEYMAP_JSON) $(DD_CONFIG_FILES)
$(INTERMEDIATE_OUTPUT)/src/community_post_config.h: $(KEYMAP_JSON) $(DD_CONFIG_FILES)
@$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
$(eval CMD=$(QMK_BIN) generate-community-config-h -kb $(KEYBOARD) --quiet --output $(INTERMEDIATE_OUTPUT)/src/community_config.h $(KEYMAP_JSON))
$(eval CMD=$(QMK_BIN) generate-community-post-config-h -kb $(KEYBOARD) --quiet --output $(INTERMEDIATE_OUTPUT)/src/community_post_config.h $(KEYMAP_JSON))
@$(BUILD_CMD)
$(INTERMEDIATE_OUTPUT)/src/community_modules.h: $(KEYMAP_JSON) $(DD_CONFIG_FILES)
@@ -227,10 +227,10 @@ $(INTERMEDIATE_OUTPUT)/src/split_transaction_id_community_modules.inc: $(KEYMAP_
$(eval CMD=$(QMK_BIN) generate-split-transaction-id-community-modules-inc -kb $(KEYBOARD) --quiet --output $(INTERMEDIATE_OUTPUT)/src/split_transaction_id_community_modules.inc $(KEYMAP_JSON))
@$(BUILD_CMD)
COMMUNITY_CONFIG_H = $(INTERMEDIATE_OUTPUT)/src/community_config.h
COMMUNITY_POST_CONFIG_H = $(INTERMEDIATE_OUTPUT)/src/community_post_config.h
SRC += $(INTERMEDIATE_OUTPUT)/src/community_modules.c
generated-files: $(INTERMEDIATE_OUTPUT)/src/community_config.h $(INTERMEDIATE_OUTPUT)/src/community_modules.h $(INTERMEDIATE_OUTPUT)/src/community_modules.c $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.c $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.h $(INTERMEDIATE_OUTPUT)/src/led_matrix_community_modules.inc $(INTERMEDIATE_OUTPUT)/src/rgb_matrix_community_modules.inc $(INTERMEDIATE_OUTPUT)/src/split_transaction_id_community_modules.inc
generated-files: $(INTERMEDIATE_OUTPUT)/src/community_post_config.h $(INTERMEDIATE_OUTPUT)/src/community_modules.h $(INTERMEDIATE_OUTPUT)/src/community_modules.c $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.c $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.h $(INTERMEDIATE_OUTPUT)/src/led_matrix_community_modules.inc $(INTERMEDIATE_OUTPUT)/src/rgb_matrix_community_modules.inc $(INTERMEDIATE_OUTPUT)/src/split_transaction_id_community_modules.inc
endif
@@ -331,10 +331,6 @@ define config_h_community_module_appender
endef
$(foreach module,$(COMMUNITY_MODULE_PATHS),$(eval $(call config_h_community_module_appender,$(module))))
ifneq ($(COMMUNITY_CONFIG_H),)
CONFIG_H += $(COMMUNITY_CONFIG_H)
endif
ifneq ("$(wildcard $(KEYBOARD_PATH_5)/config.h)","")
CONFIG_H += $(KEYBOARD_PATH_5)/config.h
endif
@@ -376,6 +372,10 @@ ifneq ("$(wildcard $(KEYBOARD_PATH_5)/post_config.h)","")
POST_CONFIG_H += $(KEYBOARD_PATH_5)/post_config.h
endif
ifneq ($(COMMUNITY_POST_CONFIG_H),)
POST_CONFIG_H += $(COMMUNITY_POST_CONFIG_H)
endif
CONFIG_H += $(INTERMEDIATE_OUTPUT)/src/info_config.h
KEYBOARD_SRC += $(INTERMEDIATE_OUTPUT)/src/default_keyboard.c
+24 -16
View File
@@ -98,26 +98,34 @@ endif
VALID_STENO_PROTOCOL_TYPES := geminipr txbolt all
STENO_PROTOCOL ?= all
ifeq ($(strip $(STENO_ENABLE)), yes)
ifeq ($(filter $(STENO_PROTOCOL),$(VALID_STENO_PROTOCOL_TYPES)),)
$(call CATASTROPHIC_ERROR,Invalid STENO_PROTOCOL,STENO_PROTOCOL="$(STENO_PROTOCOL)" is not a valid stenography protocol)
else
OPT_DEFS += -DSTENO_ENABLE
endif
ifeq ($(strip $(PLOVER_HID_ENABLE)), yes)
$(call WARNING_MESSAGE, PLOVER_HID_ENABLE is mutually exclusive with STENO_ENABLE and will be disabled)
override PLOVER_HID_ENABLE = no
endif
ifeq ($(strip $(STENO_PROTOCOL)), all)
override STENO_PROTOCOL := $(filter-out all,$(VALID_STENO_PROTOCOL_TYPES))
OPT_DEFS += -DSTENO_ENABLE_ALL
endif
OPT_DEFS += -DNUM_STENO_PROTOCOLS=$(words $(sort $(STENO_PROTOCOL)))
# for each supported protocol -> add deps
ifneq ($(filter $(STENO_PROTOCOL),geminipr),)
OPT_DEFS += -DSTENO_ENABLE_GEMINI
SRC += $(QUANTUM_DIR)/steno/steno_gemini.c
VIRTSER_ENABLE ?= yes
endif
ifneq ($(filter $(STENO_PROTOCOL),txbolt),)
OPT_DEFS += -DSTENO_ENABLE_BOLT
SRC += $(QUANTUM_DIR)/steno/steno_bolt.c
VIRTSER_ENABLE ?= yes
ifeq ($(strip $(STENO_PROTOCOL)), geminipr)
OPT_DEFS += -DSTENO_ENABLE_GEMINI
endif
ifeq ($(strip $(STENO_PROTOCOL)), txbolt)
OPT_DEFS += -DSTENO_ENABLE_BOLT
endif
ifeq ($(strip $(STENO_PROTOCOL)), all)
OPT_DEFS += -DSTENO_ENABLE_ALL
OPT_DEFS += -DSTENO_ENABLE_GEMINI
OPT_DEFS += -DSTENO_ENABLE_BOLT
endif
SRC += $(QUANTUM_DIR)/process_keycode/process_steno.c
endif
endif
+8 -8
View File
@@ -952,10 +952,10 @@ mitt@^3.0.1:
resolved "https://registry.yarnpkg.com/mitt/-/mitt-3.0.1.tgz#ea36cf0cc30403601ae074c8f77b7092cdab36d1"
integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==
nanoid@^3.3.12:
version "3.3.12"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.12.tgz#ab3d912e217a6d0a514f00a72a16543a28982c05"
integrity sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==
nanoid@^3.3.16:
version "3.3.16"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.16.tgz#a04d8ec4b1f10009d2d533947aefe4293737816c"
integrity sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==
oniguruma-to-es@^3.1.0:
version "3.1.1"
@@ -977,11 +977,11 @@ picocolors@^1.1.1:
integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==
postcss@^8.4.43, postcss@^8.5.8:
version "8.5.15"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.15.tgz#d1eaf677a324e9ec02196da2d3fecf4a0b9a735c"
integrity sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==
version "8.5.25"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.25.tgz#5012a598eaaa897f21bbe8553be3cb7bd2bd78cb"
integrity sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==
dependencies:
nanoid "^3.3.12"
nanoid "^3.3.16"
picocolors "^1.1.1"
source-map-js "^1.2.1"
+2
View File
@@ -45,12 +45,14 @@ GENERIC_FEATURES = \
MOUSEKEY \
MUSIC \
OS_DETECTION \
PLOVER_HID \
PROGRAMMABLE_BUTTON \
REPEAT_KEY \
SECURE \
SEND_STRING \
SEQUENCER \
SPACE_CADET \
STENO \
SWAP_HANDS \
TAP_DANCE \
TRI_LAYER \
+1
View File
@@ -63,6 +63,7 @@ OTHER_OPTION_NAMES = \
LCD_BACKLIGHT_ENABLE \
MACROS_ENABLED \
PS2_ENABLE \
PLOVER_HID_ENABLE \
PS2_MOUSE_ENABLE \
PS2_DRIVER \
RAW_ENABLE \
@@ -0,0 +1,8 @@
{
"ranges": {
"0x74C0/0x003F": "!delete!", // Old QK_STENO
"0x74C0/0x005F": {
"define": "QK_STENO"
}
}
}
@@ -0,0 +1,609 @@
{
"keycodes": {
"!reset!":0,
"0x74C0": {
"group": "steno",
"key": "QK_STENO_FUNCTION",
"aliases": [
"ST_FN"
]
},
"0x74C1": {
"group": "steno",
"key": "QK_STENO_N1",
"aliases": [
"ST_N1",
"ST_NUM"
]
},
"0x74C2": {
"group": "steno",
"key": "QK_STENO_N2",
"aliases": [
"ST_N2"
]
},
"0x74C3": {
"group": "steno",
"key": "QK_STENO_N3",
"aliases": [
"ST_N3"
]
},
"0x74C4": {
"group": "steno",
"key": "QK_STENO_N4",
"aliases": [
"ST_N4"
]
},
"0x74C5": {
"group": "steno",
"key": "QK_STENO_N5",
"aliases": [
"ST_N5"
]
},
"0x74C6": {
"group": "steno",
"key": "QK_STENO_N6",
"aliases": [
"ST_N6"
]
},
"0x74C7": {
"group": "steno",
"key": "QK_STENO_S1",
"aliases": [
"ST_S1",
"ST_SL"
]
},
"0x74C8": {
"group": "steno",
"key": "QK_STENO_S2",
"aliases": [
"ST_S2"
]
},
"0x74C9": {
"group": "steno",
"key": "QK_STENO_TL",
"aliases": [
"ST_TL"
]
},
"0x74CA": {
"group": "steno",
"key": "QK_STENO_KL",
"aliases": [
"ST_KL"
]
},
"0x74CB": {
"group": "steno",
"key": "QK_STENO_PL",
"aliases": [
"ST_PL"
]
},
"0x74CC": {
"group": "steno",
"key": "QK_STENO_WL",
"aliases": [
"ST_WL"
]
},
"0x74CD": {
"group": "steno",
"key": "QK_STENO_HL",
"aliases": [
"ST_HL"
]
},
"0x74CE": {
"group": "steno",
"key": "QK_STENO_RL",
"aliases": [
"ST_RL"
]
},
"0x74CF": {
"group": "steno",
"key": "QK_STENO_A",
"aliases": [
"ST_A"
]
},
"0x74D0": {
"group": "steno",
"key": "QK_STENO_O",
"aliases": [
"ST_O"
]
},
"0x74D1": {
"group": "steno",
"key": "QK_STENO_ST1",
"aliases": [
"ST_ST1",
"ST_STR"
]
},
"0x74D2": {
"group": "steno",
"key": "QK_STENO_ST2",
"aliases": [
"ST_ST2"
]
},
"0x74D3": {
"group": "steno",
"key": "QK_STENO_RESET1",
"aliases": [
"ST_RE1",
"ST_RES1"
]
},
"0x74D4": {
"group": "steno",
"key": "QK_STENO_RESET2",
"aliases": [
"ST_RE2",
"ST_RES2"
]
},
"0x74D5": {
"group": "steno",
"key": "QK_STENO_POWER",
"aliases": [
"ST_PWR"
]
},
"0x74D6": {
"group": "steno",
"key": "QK_STENO_ST3",
"aliases": [
"ST_ST3"
]
},
"0x74D7": {
"group": "steno",
"key": "QK_STENO_ST4",
"aliases": [
"ST_ST4"
]
},
"0x74D8": {
"group": "steno",
"key": "QK_STENO_E",
"aliases": [
"ST_E"
]
},
"0x74D9": {
"group": "steno",
"key": "QK_STENO_U",
"aliases": [
"ST_U"
]
},
"0x74DA": {
"group": "steno",
"key": "QK_STENO_FR",
"aliases": [
"ST_FR"
]
},
"0x74DB": {
"group": "steno",
"key": "QK_STENO_RR",
"aliases": [
"ST_RR"
]
},
"0x74DC": {
"group": "steno",
"key": "QK_STENO_PR",
"aliases": [
"ST_PR"
]
},
"0x74DD": {
"group": "steno",
"key": "QK_STENO_BR",
"aliases": [
"ST_BR"
]
},
"0x74DE": {
"group": "steno",
"key": "QK_STENO_LR",
"aliases": [
"ST_LR"
]
},
"0x74DF": {
"group": "steno",
"key": "QK_STENO_GR",
"aliases": [
"ST_GR"
]
},
"0x74E0": {
"group": "steno",
"key": "QK_STENO_TR",
"aliases": [
"ST_TR"
]
},
"0x74E1": {
"group": "steno",
"key": "QK_STENO_SR",
"aliases": [
"ST_SR"
]
},
"0x74E2": {
"group": "steno",
"key": "QK_STENO_DR",
"aliases": [
"ST_DR"
]
},
"0x74E3": {
"group": "steno",
"key": "QK_STENO_N7",
"aliases": [
"ST_N7"
]
},
"0x74E4": {
"group": "steno",
"key": "QK_STENO_N8",
"aliases": [
"ST_N8"
]
},
"0x74E5": {
"group": "steno",
"key": "QK_STENO_N9",
"aliases": [
"ST_N9"
]
},
"0x74E6": {
"group": "steno",
"key": "QK_STENO_NA",
"aliases": [
"ST_NA"
]
},
"0x74E7": {
"group": "steno",
"key": "QK_STENO_NB",
"aliases": [
"ST_NB"
]
},
"0x74E8": {
"group": "steno",
"key": "QK_STENO_NC",
"aliases": [
"ST_NC"
]
},
"0x74E9": {
"group": "steno",
"key": "QK_STENO_ZR",
"aliases": [
"ST_ZR"
]
},
"0x74EA": {
"group": "steno",
"key": "QK_STENO_X1",
"aliases": [
"ST_X1"
]
},
"0x74EB": {
"group": "steno",
"key": "QK_STENO_X2",
"aliases": [
"ST_X2"
]
},
"0x74EC": {
"group": "steno",
"key": "QK_STENO_X3",
"aliases": [
"ST_X3"
]
},
"0x74ED": {
"group": "steno",
"key": "QK_STENO_X4",
"aliases": [
"ST_X4"
]
},
"0x74EE": {
"group": "steno",
"key": "QK_STENO_X5",
"aliases": [
"ST_X5"
]
},
"0x74EF": {
"group": "steno",
"key": "QK_STENO_X6",
"aliases": [
"ST_X6"
]
},
"0x74F0": {
"group": "steno",
"key": "QK_STENO_X7",
"aliases": [
"ST_X7"
]
},
"0x74F1": {
"group": "steno",
"key": "QK_STENO_X8",
"aliases": [
"ST_X8"
]
},
"0x74F2": {
"group": "steno",
"key": "QK_STENO_X9",
"aliases": [
"ST_X9"
]
},
"0x74F3": {
"group": "steno",
"key": "QK_STENO_X10",
"aliases": [
"ST_X10"
]
},
"0x74F4": {
"group": "steno",
"key": "QK_STENO_X11",
"aliases": [
"ST_X11"
]
},
"0x74F5": {
"group": "steno",
"key": "QK_STENO_X12",
"aliases": [
"ST_X12"
]
},
"0x74F6": {
"group": "steno",
"key": "QK_STENO_X13",
"aliases": [
"ST_X13"
]
},
"0x74F7": {
"group": "steno",
"key": "QK_STENO_X14",
"aliases": [
"ST_X14"
]
},
"0x74F8": {
"group": "steno",
"key": "QK_STENO_X15",
"aliases": [
"ST_X15"
]
},
"0x74F9": {
"group": "steno",
"key": "QK_STENO_X16",
"aliases": [
"ST_X16"
]
},
"0x74FA": {
"group": "steno",
"key": "QK_STENO_X17",
"aliases": [
"ST_X17"
]
},
"0x74FB": {
"group": "steno",
"key": "QK_STENO_X18",
"aliases": [
"ST_X18"
]
},
"0x74FC": {
"group": "steno",
"key": "QK_STENO_X19",
"aliases": [
"ST_X19"
]
},
"0x74FD": {
"group": "steno",
"key": "QK_STENO_X20",
"aliases": [
"ST_X20"
]
},
"0x74FE": {
"group": "steno",
"key": "QK_STENO_X21",
"aliases": [
"ST_X21"
]
},
"0x74FF": {
"group": "steno",
"key": "QK_STENO_X22",
"aliases": [
"ST_X22"
]
},
"0x7500": {
"group": "steno",
"key": "QK_STENO_X23",
"aliases": [
"ST_X23"
]
},
"0x7501": {
"group": "steno",
"key": "QK_STENO_X24",
"aliases": [
"ST_X24"
]
},
"0x7502": {
"group": "steno",
"key": "QK_STENO_X25",
"aliases": [
"ST_X25"
]
},
"0x7503": {
"group": "steno",
"key": "QK_STENO_X26",
"aliases": [
"ST_X26"
]
},
// 0x7504
// 0x7505
// 0x7506
// 0x7507
// 0x7508
// 0x7509
// 0x750A
"0x750B": {
"group": "steno",
"key": "QK_STENO_S3",
"aliases": [
"ST_S3"
]
},
"0x750C": {
"group": "steno",
"key": "QK_STENO_TKL",
"aliases": [
"ST_TKL"
]
},
"0x750D": {
"group": "steno",
"key": "QK_STENO_PWL",
"aliases": [
"ST_PWL"
]
},
"0x750E": {
"group": "steno",
"key": "QK_STENO_HRL",
"aliases": [
"ST_HRL"
]
},
"0x750F": {
"group": "steno",
"key": "QK_STENO_FRR",
"aliases": [
"ST_FRR"
]
},
"0x7510": {
"group": "steno",
"key": "QK_STENO_PBR",
"aliases": [
"ST_PBR"
]
},
"0x7511": {
"group": "steno",
"key": "QK_STENO_LGR",
"aliases": [
"ST_LGR"
]
},
"0x7512": {
"group": "steno",
"key": "QK_STENO_TSR",
"aliases": [
"ST_TSR"
]
},
"0x7513": {
"group": "steno",
"key": "QK_STENO_DZR",
"aliases": [
"ST_DZR"
]
},
"0x7514": {
"group": "steno",
"key": "QK_STENO_AO",
"aliases": [
"ST_AO"
]
},
"0x7515": {
"group": "steno",
"key": "QK_STENO_EU",
"aliases": [
"ST_EU"
]
},
// 0x7516
// 0x7517
// 0x7518
// 0x7519
// 0x751A
// 0x751B
"0x751C": {
"group": "steno",
"key": "QK_STENO_MODE_BOLT",
"label": "Steno Mode TX Bolt",
"aliases": [
"ST_BOLT"
]
},
"0x751D": {
"group": "steno",
"key": "QK_STENO_MODE_GEMINI",
"label": "Steno Mode GeminiPR",
"aliases": [
"ST_GEMI"
]
},
"0x751E": {
"group": "steno",
"key": "QK_STENO_MODE_NEXT",
"label": "Steno Mode Next",
"aliases": [
"ST_NEXT"
]
},
"0x751F": {
"group": "steno",
"key": "QK_STENO_MODE_PREVIOUS",
"label": "Steno Mode Previous",
"aliases": [
"ST_PREV"
]
}
}
}
+3
View File
@@ -0,0 +1,3 @@
{
// This version exists to signify addition of eeconfig support.
}
+3
View File
@@ -217,6 +217,9 @@
"SPLIT_ST7565_ENABLE": {"info_key": "split.transport.sync.st7565", "value_type": "flag"},
"SPLIT_WPM_ENABLE": {"info_key": "split.transport.sync.wpm", "value_type": "flag"},
// Stenography
"STENO_COMBINEDMAP": {"info_key": "stenography.combined_map", "value_type": "flag"},
// Tapping
"CHORDAL_HOLD": {"info_key": "tapping.chordal_hold", "value_type": "flag"},
"FLOW_TAP_TERM": {"info_key": "tapping.flow_tap_term", "value_type": "int"},
+4 -1
View File
@@ -1741,7 +1741,10 @@
"target": "ducky/one2mini/1861st"
},
"ducky/one2sf": {
"target": "ducky/one2sf/1967st"
"target": "ducky/one2sf/1967st/ansi"
},
"ducky/one2sf/1967st": {
"target": "ducky/one2sf/1967st/ansi"
},
"dumbpad": {
"target": "dumbpad/v0x"
+11
View File
@@ -815,6 +815,17 @@
"additionalProperties": false,
"properties": {
"enabled": {"type": "boolean"},
"combined_map": {"type": "boolean"},
"default": {
"type": "object",
"additionalProperties": false,
"properties": {
"mode": {
"type": "string",
"enum": ["geminipr", "txbolt"]
}
}
},
"protocol": {
"type": "string",
"enum": ["all", "geminipr", "txbolt"]
+189
View File
@@ -0,0 +1,189 @@
# QMK Breaking Changes - 2026 August 30 Changelog
## Notable Changes {#notable-changes}
### Community Modules `1.1.3` ([#26201](https://github.com/qmk/qmk_firmware/pull/26201)) {#community-modules}
Version 1.1.3 adds support for persistent data in community modules. Modules can now store and restore their own state across restarts, enabling more stateful behavior without relying on keyboard-level EEPROM handling. A reference example can be located at [modules/qmk/nvm_test](https://github.com/qmk/qmk_firmware/tree/develop/modules/qmk/nvm_test).
See the [Community Modules documentation](../features/community_modules) for more information, including the full list of available hooks.
### Steno Feature Updates ([#26273](https://github.com/qmk/qmk_firmware/pull/26273), [#26018](https://github.com/qmk/qmk_firmware/pull/26018)) {#steno}
The steno feature has been reworked around a clearer integration, including a more consistent keycode naming scheme.
Users should migrate old `STN_*` and legacy mode names to the new `QK_STENO_*`/`ST_*` naming scheme.
::: warning
Keycode aliases have been put in place in most cases to cater for "old names" being mapped to "new names" -- the documentation already reflects all the new naming of keys.
:::
<details>
<summary>Full list of updated keycodes</summary>
| Old Keycode | New Keycode | Aliases |
|----------------------|------------------------|--------------------|
| `STN_FN` | `QK_STENO_FUNCTION` | `ST_FN` |
| `STN_N1`/`STN_NUM` | `QK_STENO_N1` | `ST_N1`/`ST_NUM` |
| `STN_N2` | `QK_STENO_N2` | `ST_N2` |
| `STN_N3` | `QK_STENO_N3` | `ST_N3` |
| `STN_N4` | `QK_STENO_N4` | `ST_N4` |
| `STN_N5` | `QK_STENO_N5` | `ST_N5` |
| `STN_N6` | `QK_STENO_N6` | `ST_N6` |
| `STN_S1`/`STN_SL` | `QK_STENO_S1` | `ST_S1`/`ST_SL` |
| `STN_S2` | `QK_STENO_S2` | `ST_S2` |
| `STN_TL` | `QK_STENO_TL` | `ST_TL` |
| `STN_KL` | `QK_STENO_KL` | `ST_KL` |
| `STN_PL` | `QK_STENO_PL` | `ST_PL` |
| `STN_WL` | `QK_STENO_WL` | `ST_WL` |
| `STN_HL` | `QK_STENO_HL` | `ST_HL` |
| `STN_RL` | `QK_STENO_RL` | `ST_RL` |
| `STN_A` | `QK_STENO_A` | `ST_A` |
| `STN_O` | `QK_STENO_O` | `ST_O` |
| `STN_ST1`/`STN_STR` | `QK_STENO_ST1` | `ST_ST1`/`ST_STR` |
| `STN_ST2` | `QK_STENO_ST2` | `ST_ST2` |
| `STN_RE1`/`STN_RES1` | `QK_STENO_RESET1` | `ST_RES1`/`ST_RE1` |
| `STN_RE2`/`STN_RES2` | `QK_STENO_RESET2` | `ST_RES2`/`ST_RE2` |
| `STN_PWR` | `QK_STENO_POWER` | `ST_PWR` |
| `STN_ST3` | `QK_STENO_ST3` | `ST_ST3` |
| `STN_ST4` | `QK_STENO_ST4` | `ST_ST4` |
| `STN_E` | `QK_STENO_E` | `ST_E` |
| `STN_U` | `QK_STENO_U` | `ST_U` |
| `STN_FR` | `QK_STENO_FR` | `ST_FR` |
| `STN_RR` | `QK_STENO_RR` | `ST_RR` |
| `STN_PR` | `QK_STENO_PR` | `ST_PR` |
| `STN_BR` | `QK_STENO_BR` | `ST_BR` |
| `STN_LR` | `QK_STENO_LR` | `ST_LR` |
| `STN_GR` | `QK_STENO_GR` | `ST_GR` |
| `STN_TR` | `QK_STENO_TR` | `ST_TR` |
| `STN_SR` | `QK_STENO_SR` | `ST_SR` |
| `STN_DR` | `QK_STENO_DR` | `ST_DR` |
| `STN_N7` | `QK_STENO_N7` | `ST_N7` |
| `STN_N8` | `QK_STENO_N8` | `ST_N8` |
| `STN_N9` | `QK_STENO_N9` | `ST_N9` |
| `STN_NA` | `QK_STENO_NA` | `ST_NA` |
| `STN_NB` | `QK_STENO_NB` | `ST_NB` |
| `STN_NC` | `QK_STENO_NC` | `ST_NC` |
| `STN_ZR` | `QK_STENO_ZR` | `ST_ZR` |
| `STN_SL` | `QK_STENO_S1` | `ST_S1` |
| `STN_STR` | `QK_STENO_ST1` | `ST_ST1` |
| `STN_S3` | `QK_STENO_S3` | `ST_S3` |
| `STN_TKL` | `QK_STENO_TKL` | `ST_TKL` |
| `STN_PWL` | `QK_STENO_PWL` | `ST_PWL` |
| `STN_HRL` | `QK_STENO_HRL` | `ST_HRL` |
| `STN_FRR` | `QK_STENO_FRR` | `ST_FRR` |
| `STN_PBR` | `QK_STENO_PBR` | `ST_PBR` |
| `STN_LGR` | `QK_STENO_LGR` | `ST_LGR` |
| `STN_TSR` | `QK_STENO_TSR` | `ST_TSR` |
| `STN_DZR` | `QK_STENO_DZR` | `ST_DZR` |
| `STN_AO` | `QK_STENO_AO` | `ST_AO` |
| `STN_EU` | `QK_STENO_EU` | `ST_EU` |
| `QK_STENO_BOLT` | `QK_STENO_MODE_BOLT` | `ST_BOLT` |
| `QK_STENO_GEMINI` | `QK_STENO_MODE_GEMINI` | `ST_GEMI` |
</details>
Support for the [Plover custom HID protocol](https://github.com/opensteno/plover/releases/tag/v5.1.0) has also been integrated. This provides an alternative to the COM port based Gemini and Bolt protocols, and extends steno support to VUSB based devices.
::: info Note
A tighter integration of the Plover HID protocol into the steno feature is planned for a future release.
:::
See the [Stenography Feature](../features/stenography) documentation for more information.
### Remove pin ordering restriction in RP2040 ps2 driver ([#26256](https://github.com/qmk/qmk_firmware/pull/26256)) {#rp2040-ps2}
The RP2040 PS/2 driver no longer requires a strict clock/data pin ordering. This removes an unnecessary wiring restriction for RP2040-based keyboards and allows more valid PS/2 layouts to work without needing to match a specific pin sequence.
### Restrict the EXTRAKEY_ENABLE System Control HID usage range. ([#26295](https://github.com/qmk/qmk_firmware/pull/26295)) {#extrakey-gamepad}
QMK now limits the default System Control HID range exposed by `EXTRAKEY_ENABLE` to the safe subset it actually uses. This prevents issues where some hosts to misidentify the device as a gamepad.
To widen the range to the old behavior, the following can be added to a `config.h`:
```c
#define SYSTEM_CONTROL_USAGE_MINIMUM 0x0001
#define SYSTEM_CONTROL_USAGE_MAXIMUM 0x00B7
```
::: warning
Only widen it if you need the extra usages and know your host handles them.
:::
### Updated Keyboard Codebases {#updated-keyboard-codebases}
| Old Keyboard Name | New Keyboard Name |
|---------------------|--------------------------|
| ducky/one2sf/1967st | ducky/one2sf/1967st/ansi |
## Deprecation Notices
In line with the [notice period](../support_deprecation_policy#how-much-advance-notice-will-be-given), deprecation notices for larger items are listed here.
### VIA Feature Migration ([#26315](https://github.com/qmk/qmk_firmware/pull/26315)) {#via-module}
As part of long-term goal to progressively reduce the maintenance burden on the project, upkeep of the VIA integration will transition to the VIA team.
This allows the VIA team to support many more custom keyboard configurations, as well as reduces the turnaround time for any changes to the VIA protocol they wish to make.
Backwards compatibility will remain for a transition period and in a future release, the old VIA feature-based implementation is expected to be removed.
## Full changelist
Core:
* Custom plover HID report type ([#26018](https://github.com/qmk/qmk_firmware/pull/26018))
* Enable modules to persist data ([#26201](https://github.com/qmk/qmk_firmware/pull/26201))
* Preserve Azoteq mouse buttons ([#26248](https://github.com/qmk/qmk_firmware/pull/26248))
* Remove pin ordering restriction in RP2040 ps2 driver ([#26256](https://github.com/qmk/qmk_firmware/pull/26256))
* Plover HID cleanup. ([#26262](https://github.com/qmk/qmk_firmware/pull/26262))
* repeat_key.c: add implementation for get_last_record ([#26263](https://github.com/qmk/qmk_firmware/pull/26263))
* Implement Plover HID for VUSB ([#26267](https://github.com/qmk/qmk_firmware/pull/26267))
* process_key_lock: clear entire key state in cancel_key_lock() ([#26269](https://github.com/qmk/qmk_firmware/pull/26269))
* Initial rework of steno feature ([#26273](https://github.com/qmk/qmk_firmware/pull/26273))
* qp_lvgl: always signal flush ready even with no display ([#26275](https://github.com/qmk/qmk_firmware/pull/26275))
* Consistently handle datablock init ([#26282](https://github.com/qmk/qmk_firmware/pull/26282))
* Make framebuffer effects honour `rgb_matrix_map_row_column_to_led` ([#26294](https://github.com/qmk/qmk_firmware/pull/26294))
* Restrict the EXTRAKEY_ENABLE System Control HID usage range. ([#26295](https://github.com/qmk/qmk_firmware/pull/26295))
* Port typing_heatmap animation to LED Matrix ([#26300](https://github.com/qmk/qmk_firmware/pull/26300))
* Add `_noeeprom` variants of backlight enable/disable. ([#26328](https://github.com/qmk/qmk_firmware/pull/26328))
* Add STM32_USB_USE_OTG2 to USB_ENDPOINTS_ARE_REORDERABLE ([#26369](https://github.com/qmk/qmk_firmware/pull/26369))
* Change preprocessor directive for random solenoid firing ([#26377](https://github.com/qmk/qmk_firmware/pull/26377))
* Rework Plover HID to use Steno keycodes ([#26421](https://github.com/qmk/qmk_firmware/pull/26421))
CLI:
* Require `--keyboard` for some CLI subcommands ([#26308](https://github.com/qmk/qmk_firmware/pull/26308))
* Be lazier in loading keyboard schema for new-keyboard ([#26340](https://github.com/qmk/qmk_firmware/pull/26340))
Keyboards:
* Addition of the Ymdk Oni Tsangan/HHKB-like pcb ([#25230](https://github.com/qmk/qmk_firmware/pull/25230))
* Add converter/thinkpad_t6x/pico_t61 keyboard ([#26266](https://github.com/qmk/qmk_firmware/pull/26266))
* Add additional layouts for `mkh_studio/bully` ([#26271](https://github.com/qmk/qmk_firmware/pull/26271))
* Split `ducky/one2sf/1967st` into `ansi`/`iso` variants ([#26277](https://github.com/qmk/qmk_firmware/pull/26277))
* Automatically handle duplicate matrix LED mappings ([#26278](https://github.com/qmk/qmk_firmware/pull/26278))
* Tidy sawnsprojects/satxri6key ([#26317](https://github.com/qmk/qmk_firmware/pull/26317))
* Update satisfaction75 to only use keyboard datablock ([#26320](https://github.com/qmk/qmk_firmware/pull/26320))
* Migrate remaining `VIA_EEPROM_CUSTOM_CONFIG_SIZE` to `EECONFIG_KB_DATA_SIZE` ([#26321](https://github.com/qmk/qmk_firmware/pull/26321))
* Use core `spi_init` implementation for gmmk/gmmk2/p96 ([#26344](https://github.com/qmk/qmk_firmware/pull/26344))
* Convert `novelkeys/nk87` to use RGB Matrix ([#26349](https://github.com/qmk/qmk_firmware/pull/26349))
* Update magic_force/mf17 to WS2812 PWM driver ([#26384](https://github.com/qmk/qmk_firmware/pull/26384))
* Keycult TKL Updates ([#26385](https://github.com/qmk/qmk_firmware/pull/26385))
* Update keyboards to implement `led_update_kb` instead of `led_set` ([#26388](https://github.com/qmk/qmk_firmware/pull/26388))
Keyboard fixes:
* Fix nifty_numpad issues ([#26283](https://github.com/qmk/qmk_firmware/pull/26283))
* Fix use of `via.h` ([#26316](https://github.com/qmk/qmk_firmware/pull/26316))
Others:
* Update RGB Matrix documentation to include JSON config ([#26187](https://github.com/qmk/qmk_firmware/pull/26187))
* Update encoder documents for json config ([#26188](https://github.com/qmk/qmk_firmware/pull/26188))
* Update LED Matrix documentation to include JSON config ([#26425](https://github.com/qmk/qmk_firmware/pull/26425))
Bugs:
* First pass of ruff check fixes ([#26257](https://github.com/qmk/qmk_firmware/pull/26257))
* Use `memmove` for overlapping copies in RGB/LED matrix last-hit tracker ([#26306](https://github.com/qmk/qmk_firmware/pull/26306))
* Fix to make Repeat Key QK_REP work with Key Overrides. ([#26312](https://github.com/qmk/qmk_firmware/pull/26312))
* Fix SEQUENCER_ENABLE so the sequencer feature builds again ([#26322](https://github.com/qmk/qmk_firmware/pull/26322))
* Fix ChibiOS virtual serial short packet receive ([#26356](https://github.com/qmk/qmk_firmware/pull/26356))
* Resolve recursive keyboard aliases when locating userspace keymaps ([#26402](https://github.com/qmk/qmk_firmware/pull/26402))
* Fix `EECONFIG_MODULE_DATA_SIZE` for modules with zero provisioned eeconfig ([#26414](https://github.com/qmk/qmk_firmware/pull/26414))
* Align USB endpoint buffers to fix RP2040 Plover HID issues ([#26417](https://github.com/qmk/qmk_firmware/pull/26417))
* Fix 'qmk generate-develop-pr-list' for ghapi v2 ([#26428](https://github.com/qmk/qmk_firmware/pull/26428))
+1 -1
View File
@@ -214,7 +214,7 @@
{ "text": "My Pull Request Was Flagged", "link": "/breaking_changes_instructions" },
{
"text": "Most Recent ChangeLog",
"link": "/ChangeLog/20260531"
"link": "/ChangeLog/20260830"
},
{ "text": "Past Breaking Changes", "link": "/breaking_changes_history" },
{ "text": "Deprecation Policy", "link": "/support_deprecation_policy" }
+10 -10
View File
@@ -10,25 +10,25 @@ Practically, this means QMK merges the `develop` branch into the `master` branch
## What has been included in past Breaking Changes?
* [2026 Aug 30](ChangeLog/20260830)
* [2026 May 31](ChangeLog/20260531)
* [2026 Feb 22](ChangeLog/20260222)
* [2025 Nov 30](ChangeLog/20251130)
* [Older Breaking Changes](breaking_changes_history)
## When is the next Breaking Change?
The next Breaking Change is scheduled for Aug 30, 2026.
The next Breaking Change is scheduled for November 29, 2026.
### Important Dates
* 2025 May 31 - `develop` is tagged with a new release version. Each push to `master` is subsequently merged to `develop` by GitHub actions.
* 2026 Aug 2 - `develop` closed to new PRs.
* 2026 Aug 2 - Call for testers.
* 2026 Aug 16 - Last day for merges -- after this point `develop` is locked for testing and accepts only bugfixes
* 2026 Aug 23 - `develop` is locked, only critical bugfix PRs merged.
* 2026 Aug 28 - `master` is locked, no PRs merged.
* 2026 Aug 30 - Merge `develop` to `master`.
* 2026 Aug 30 - `master` is unlocked. PRs can be merged again.
* 2025 Aug 30 - `develop` is tagged with a new release version. Each push to `master` is subsequently merged to `develop` by GitHub actions.
* 2026 Nov 1 - `develop` closed to new PRs.
* 2026 Nov 1 - Call for testers.
* 2026 Nov 15 - Last day for merges -- after this point `develop` is locked for testing and accepts only bugfixes
* 2026 Nov 22 - `develop` is locked, only critical bugfix PRs merged.
* 2026 Nov 27 - `master` is locked, no PRs merged.
* 2026 Nov 29 - Merge `develop` to `master`.
* 2026 Nov 29 - `master` is unlocked. PRs can be merged again.
## What changes will be included?
+1
View File
@@ -2,6 +2,7 @@
This page links to all previous changelogs from the QMK Breaking Changes process.
* [2026 Aug 30](ChangeLog/20260830) - version 0.34.0
* [2026 May 31](ChangeLog/20260531) - version 0.33.0
* [2026 Feb 22](ChangeLog/20260222) - version 0.32.0
* [2025 Nov 30](ChangeLog/20251130) - version 0.31.0
+1 -1
View File
@@ -214,7 +214,7 @@ options:
-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 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 '?'.
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`
+1 -1
View File
@@ -6,7 +6,7 @@ Features within QMK may or may not be compatible with every microcontroller.
## Atmel AVR
The following use [LUFA](https://www.fourwalledcubicle.com/LUFA.php) as the USB stack:
The following use [LUFA](https://github.com/abcminiuser/lufa) as the USB stack:
* [ATmega16U2](https://www.microchip.com/wwwproducts/en/ATmega16U2) / [ATmega32U2](https://www.microchip.com/wwwproducts/en/ATmega32U2)
* [ATmega16U4](https://www.microchip.com/wwwproducts/en/ATmega16U4) / [ATmega32U4](https://www.microchip.com/wwwproducts/en/ATmega32U4)
+4
View File
@@ -340,6 +340,10 @@ There are a few different ways to set handedness for split keyboards (listed in
* `#define SPLIT_TRANSACTION_IDS_USER .....`
* Allows for custom data sync with the slave when using the QMK-provided split transport. See [custom data sync between sides](features/split_keyboard#custom-data-sync) for more information.
* `#define SYSTEM_CONTROL_USAGE_MINIMUM 0x0081`
* `#define SYSTEM_CONTROL_USAGE_MAXIMUM 0x008F`
* Sets the usage range reported by the System Control collection that `EXTRAKEY_ENABLE` adds. The default range covers the System Control usages QMK can send and stops below the Generic Desktop D-pad usages (`0x90` and up). Raising the maximum into that range makes some hosts detect the keyboard as a gamepad, so only widen it if you need the extra usages and know your host handles them. The minimum must not be greater than the maximum.
# The `rules.mk` File
This is a [make](https://www.gnu.org/software/make/manual/make.html) file that is included by the top-level `Makefile`. It is used to set some information about the MCU that we will be compiling for as well as enabling and disabling certain features.
+2 -2
View File
@@ -19,11 +19,11 @@ Please keep these things in mind:
* Everyone involved with QMK is donating their time and energy. We don't get paid to work on or answer questions about QMK.
* Try to ask your question so it's as easy to answer as possible. If you're not sure how to do that these are some good guides:
* https://opensource.com/life/16/10/how-ask-technical-questions
* http://www.catb.org/esr/faqs/smart-questions.html
* <http://www.catb.org/esr/faqs/smart-questions.html> ([mirror](https://github.com/selfteaching/How-To-Ask-Questions-The-Smart-Way))
# Project Overview
QMK is largely written in C, with specific features and parts written in C++. It targets embedded processors found in keyboards, particularly AVR ([LUFA](https://www.fourwalledcubicle.com/LUFA.php)) and ARM ([ChibiOS](https://www.chibios.org)). If you are already well versed in Arduino programming you'll find a lot of the concepts and limitations familiar. Prior experience with Arduino is not required to successfully contribute to QMK.
QMK is largely written in C, with specific features and parts written in C++. It targets embedded processors found in keyboards, particularly AVR ([LUFA](https://github.com/abcminiuser/lufa)) and ARM ([ChibiOS](https://www.chibios.org)). If you are already well versed in Arduino programming you'll find a lot of the concepts and limitations familiar. Prior experience with Arduino is not required to successfully contribute to QMK.
<!-- FIXME: We should include a list of resources for learning C here. -->
+20 -5
View File
@@ -191,7 +191,9 @@ void eeconfig_init_user_datablock(void);
:::::
### Example
### Examples
#### Basic
This is an example of how to add settings, and read and write it. We're using the user keymap for the example here.
@@ -215,10 +217,6 @@ typedef struct my_config_t {
static my_config_t config;
void keyboard_post_init_user(void) {
if (!eeconfig_is_user_datablock_valid()) {
eeconfig_init_user_datablock();
}
eeconfig_read_user_datablock(&config, 0, sizeof(my_config_t));
}
@@ -240,3 +238,20 @@ void housekeeping_task_user(void) {
}
}
```
#### Default Values
Extending the above example, a default value for the datablock can be configured as follows:
```c
void eeconfig_init_user_datablock(void) {
my_config_t default_config = {
.data = 42,
};
eeconfig_update_user_datablock(&default_config, 0, sizeof(my_config_t));
}
```
::: tip
For large datablocks, you might need to manually update in chunks to avoid memory issues.
:::
+2 -1
View File
@@ -16,7 +16,8 @@ These functions allow you to activate layers in various ways. Note that layers a
* `OSL(layer)` - momentarily activates *layer* until the next key is pressed. See [One Shot Keys](one_shot_keys) for details and additional functionality.
* `TG(layer)` - toggles *layer*, activating it if it's inactive and vice versa
* `TO(layer)` - activates *layer* and de-activates all other layers (except your default layer). This function is special, because instead of just adding/removing one layer to your active layer stack, it will completely replace your current active layers, uniquely allowing you to replace higher layers with a lower one. This is activated on keydown (as soon as the key is pressed).
* `TT(layer)` - Layer Tap-Toggle. If you hold the key down, *layer* is activated, and then is de-activated when you let go (like `MO`). If you repeatedly tap it, the layer will be toggled on or off (like `TG`). It needs 5 taps by default, but you can change this by defining `TAPPING_TOGGLE` -- for example, `#define TAPPING_TOGGLE 2` to toggle on just two taps.
* `TT(layer)` - Layer Tap-Toggle. If you hold the key down, *layer* is activated, and then is de-activated when you let go (like `MO`). If you repeatedly tap it, the layer will be toggled on or off (like `TG`). It needs 5 taps by default, but you can change this by defining `TAPPING_TOGGLE` -- for example, `#define TAPPING_TOGGLE 2` to toggle on just two taps.
* Note: toggling behavior requires that [Quick Tap](tap_hold#quick-tap-term) is enabled (`QUICK_TAP_TERM` not set to `0`), or if `QUICK_TAP_TERM_PER_KEY` is defined, that `get_quick_tap_term()` returns a non-zero value for the `TT` key.
See also the [Layer Lock key](features/layer_lock), which locks the highest
active layer until pressed again.
+33 -17
View File
@@ -135,28 +135,45 @@ This file defines LED matrix effects in the same form as used with `led_matrix_k
This file defines RGB matrix effects in the same form as used with `rgb_matrix_kb.inc` and `rgb_matrix_user.inc` (see [Custom RGB Matrix Effects](rgb_matrix#custom-rgb-matrix-effects)). Effect mode names are prepended with `RGB_MATRIX_COMMUNITY_MODULE_`.
### Custom split keyboard data sync
### Additional Customization
Defines follow the convention, `SPLIT_TRANSACTION_IDS_MODULE_<MODULE>` (see [Custom data sync](split_keyboard#custom-data-sync)).
#### Split Keyboard Data Sync
Defines follow the convention, `SPLIT_TRANSACTION_IDS_MODULE_<MODULE>` (see [Custom data sync](split_keyboard#custom-data-sync)).
#### Persistent Configuration
Defines follow the convention, `EECONFIG_MODULE_<MODULE>_DATA_SIZE` and `EECONFIG_MODULE_<MODULE>_DATA_VERSION` (see [Custom Persistent Configuration](../feature_eeprom#datablock)).
When configured, the following APIs are available:
| API Format | Example (`hello_world` module) | API Version |
|--------------------------------------------|-----------------------------------------------|-------------|
| `eeconfig_is_<module>_datablock_valid` | `eeconfig_is_hello_world_datablock_valid` | `1.1.3` |
| `eeconfig_read_<module>_datablock` | `eeconfig_read_hello_world_datablock` | `1.1.3` |
| `eeconfig_update_<module>_datablock` | `eeconfig_update_hello_world_datablock` | `1.1.3` |
| `eeconfig_init_<module>_datablock` | `eeconfig_init_hello_world_datablock` | `1.1.3` |
| `eeconfig_read_<module>_datablock_field` | `eeconfig_read_hello_world_datablock_field` | `1.1.3` |
| `eeconfig_update_<module>_datablock_field` | `eeconfig_update_hello_world_datablock_field` | `1.1.3` |
### Compatible APIs
Community Modules may provide specializations for the following APIs:
| Base API | API Format | Example (`hello_world` module) | API Version |
|----------------------------------|-------------------------------------------|---------------------------------------------|-------------|
| `keyboard_pre_init` | `keyboard_pre_init_<module>` | `keyboard_pre_init_hello_world` | `0.1.0` |
| `keyboard_post_init` | `keyboard_post_init_<module>` | `keyboard_post_init_hello_world` | `0.1.0` |
| `pre_process_record` | `pre_process_record_<module>` | `pre_process_record_hello_world` | `0.1.0` |
| `process_record` | `process_record_<module>` | `process_record_hello_world` | `0.1.0` |
| `post_process_record` | `post_process_record_<module>` | `post_process_record_hello_world` | `0.1.0` |
| `housekeeping_task` | `housekeeping_task_<module>` | `housekeeping_task_hello_world` | `1.0.0` |
| `suspend_power_down` | `suspend_power_down_<module>` | `suspend_power_down_hello_world` | `1.0.0` |
| `suspend_wakeup_init` | `suspend_wakeup_init_<module>` | `suspend_wakeup_init_hello_world` | `1.0.0` |
| `shutdown` | `shutdown_<module>` | `shutdown_hello_world` | `1.0.0` |
| `process_detected_host_os` | `process_detected_host_os_<module>` | `process_detected_host_os_hello_world` | `1.0.0` |
| `default_layer_state_set` | `default_layer_state_set_<module>` | `default_layer_state_set_hello_world` | `1.1.0` |
| `layer_state_set` | `layer_state_set_<module>` | `layer_state_set_hello_world` | `1.1.0` |
| Base API | API Format | Example (`hello_world` module) | API Version |
|----------------------------------|-------------------------------------------|----------------------------------------------|-------------|
| `keyboard_pre_init` | `keyboard_pre_init_<module>` | `keyboard_pre_init_hello_world` | `0.1.0` |
| `keyboard_post_init` | `keyboard_post_init_<module>` | `keyboard_post_init_hello_world` | `0.1.0` |
| `pre_process_record` | `pre_process_record_<module>` | `pre_process_record_hello_world` | `0.1.0` |
| `process_record` | `process_record_<module>` | `process_record_hello_world` | `0.1.0` |
| `post_process_record` | `post_process_record_<module>` | `post_process_record_hello_world` | `0.1.0` |
| `housekeeping_task` | `housekeeping_task_<module>` | `housekeeping_task_hello_world` | `1.0.0` |
| `suspend_power_down` | `suspend_power_down_<module>` | `suspend_power_down_hello_world` | `1.0.0` |
| `suspend_wakeup_init` | `suspend_wakeup_init_<module>` | `suspend_wakeup_init_hello_world` | `1.0.0` |
| `shutdown` | `shutdown_<module>` | `shutdown_hello_world` | `1.0.0` |
| `process_detected_host_os` | `process_detected_host_os_<module>` | `process_detected_host_os_hello_world` | `1.0.0` |
| `default_layer_state_set` | `default_layer_state_set_<module>` | `default_layer_state_set_hello_world` | `1.1.0` |
| `layer_state_set` | `layer_state_set_<module>` | `layer_state_set_hello_world` | `1.1.0` |
| `led_matrix_indicators` | `led_matrix_indicators_<module>` | `led_matrix_indicators_hello_world` | `1.1.0` |
| `led_matrix_indicators_advanced` | `led_matrix_indicators_advanced_<module>` | `led_matrix_indicators_advanced_hello_world` | `1.1.0` |
| `rgb_matrix_indicators` | `rgb_matrix_indicators_<module>` | `rgb_matrix_indicators_hello_world` | `1.1.0` |
@@ -164,7 +181,6 @@ Community Modules may provide specializations for the following APIs:
| `pointing_device_init` | `pointing_device_init_<module>` | `pointing_device_init_hello_world` | `1.1.0` |
| `pointing_device_task` | `pointing_device_task_<module>` | `pointing_device_task_hello_world` | `1.1.0` |
::: info
An unspecified API is disregarded if a Community Module does not provide a specialization for it.
:::
+123 -8
View File
@@ -1,5 +1,25 @@
# Encoders
:::::tabs
==== JSON
Basic (EC11 compatible) encoders are supported by adding this to your keyboard's json config:
```json
"features": {
"encoder": true
},
"encoder": {
"rotary": [
{"pin_a": "B5", "pin_b": "B6"},
{"pin_a": "B7", "pin_b": "B8", "resolution": 2}
]
}
```
==== Legacy
Basic (EC11 compatible) encoders are supported by adding this to your `rules.mk`:
```make
@@ -20,11 +40,6 @@ Each PAD_A/B variable defines an array so multiple encoders can be defined, e.g.
#define ENCODER_B_PINS { encoder1b, encoder2b }
```
If your encoder's clockwise directions are incorrect, you can swap the A & B pad definitions. They can also be flipped with a define:
```c
#define ENCODER_DIRECTION_FLIP
```
Additionally, the resolution, which defines how many pulses the encoder registers between each detent, can be defined with:
@@ -38,6 +53,14 @@ It can also be defined per-encoder, by instead defining:
#define ENCODER_RESOLUTIONS { 4, 2 }
```
:::::
If your encoder's clockwise directions are incorrect, you can swap the A & B pad definitions. They can also be flipped with a define:
```c
#define ENCODER_DIRECTION_FLIP
```
For 4× encoders you also can assign default position if encoder skips pulses when it changes direction. For example, if your encoder send high level on both pins by default, define this:
```c
@@ -46,6 +69,50 @@ For 4× encoders you also can assign default position if encoder skips pulses wh
## Split Keyboards
:::::tabs
==== JSON
If you are using different pinouts for the encoders on each half of a split keyboard, you can define the pinout (and optionally, resolutions) for the right half like this:
```json
"encoder": {
"rotary": [
{"pin_a": "B4", "pin_b": "B3"}
]
},
"split": {
"encoder": {
"right": {
"rotary": [
{"pin_a": "D4", "pin_b": "D2", "resolution": 2}
]
}
}
}
```
If the `"right"` definitions are not specified, then the non-right version will be applied to both sides of the split.
Additionally, if one side does not have an encoder, you can specify no encoder for the pins/resolution -- for example, a split keyboard with only a right-side encoder:
```json
"encoder": {
"rotary": []
},
"split": {
"encoder": {
"right": {
"rotary": [
{"pin_a": "D4", "pin_b": "D2", "resolution": 2}
]
}
}
}
```
==== Legacy
If you are using different pinouts for the encoders on each half of a split keyboard, you can define the pinout (and optionally, resolutions) for the right half like this:
```c
@@ -66,6 +133,7 @@ Additionally, if one side does not have an encoder, you can specify `{}` for the
#define ENCODER_B_PINS_RIGHT { B13 }
#define ENCODER_RESOLUTIONS_RIGHT { 4 }
```
:::::
::: warning
Keep in mind that whenever you change the encoder resolution, you will need to reflash the half that has the encoder affected by the change.
@@ -73,11 +141,26 @@ Keep in mind that whenever you change the encoder resolution, you will need to r
## Encoder map {#encoder-map}
Encoder mapping may be added to your `keymap.c`, which replicates the normal keyswitch layer handling functionality, but with encoders. Add this to your keymap's `rules.mk`:
Encoder mapping may be added to your `keymap.c`, which replicates the normal keyswitch layer handling functionality, but with encoders. Add this to your keymap's config:
:::::tabs
==== keymap.json
```json
"config": {
"features": {
"encoder_map": true
}
}
```
==== rules.mk
```make
ENCODER_MAP_ENABLE = yes
```
:::::
Your `keymap.c` will then need an encoder mapping defined (for four layers and two encoders):
@@ -103,7 +186,7 @@ Using encoder mapping pumps events through the normal QMK keycode processing pip
```
::: tip
By default, the encoder map delay matches the value of `TAP_CODE_DELAY`.
By default, the encoder map delay matches the value of `qmk.tap_keycode_delay` (or `TAP_CODE_DELAY`).
:::
## Callbacks
@@ -172,15 +255,47 @@ Multiple encoders may share pins so long as each encoder has a distinct pair of
- pads must be high at the detent stability point which is called 'default position' in QMK
- no more than two encoders sharing a pin can be turned at the same time
For example you can support two encoders using only 3 pins like this
For example you can support two encoders using only 3 pins like this:
:::::tabs
==== JSON
```json
"encoder": {
"rotary": [
{"pin_a": "B1", "pin_b": "B2"},
{"pin_a": "B1", "pin_b": "B3"}
]
}
```
==== Legacy
```c
#define ENCODER_A_PINS { B1, B1 }
#define ENCODER_B_PINS { B2, B3 }
```
:::::
You could even support three encoders using only three pins (one per encoder) however in this configuration, rotating two encoders which share pins simultaneously will often generate incorrect output. For example:
:::::tabs
==== JSON
```json
"encoder": {
"rotary": [
{"pin_a": "B1", "pin_b": "B2"},
{"pin_a": "B1", "pin_b": "B3"},
{"pin_a": "B2", "pin_b": "B3"}
]
}
```
==== Legacy
```c
#define ENCODER_A_PINS { B1, B1, B2 }
#define ENCODER_B_PINS { B2, B3, B3 }
```
:::::
Here rotating Encoder 0 `B1 B2` and Encoder 1 `B1 B3` could be interpreted as rotating Encoder 2 `B2 B3` or `B3 B2` depending on the timing. This may still be a useful configuration depending on your use case
+1 -1
View File
@@ -8,7 +8,7 @@ Replace the `KC_GRV` key in your keymap (usually to the left of the `1` key) wit
## What Your OS Sees
If Mary presses `QK_GESC` on her keyboard, the OS will see an KC_ESC character. Now if Mary holds Shift down and presses `QK_GESC` it will output `~`, or a shifted backtick. Now if she holds GUI/CMD/WIN, it will output a simple <code>&#96;</code> character.
If Mary presses `QK_GESC` on her keyboard, the OS will see an `KC_ESC` character. Now if Mary holds Shift down and presses `QK_GESC` it will output `~`, or a shifted backtick. Now if she holds GUI/CMD/WIN, it will output a simple <code>&#96;</code> character.
## Keycodes
+215 -4
View File
@@ -24,16 +24,64 @@ LED Matrix is an abstraction layer on top of an underlying LED driver API. The l
|[IS31FL3746A](../drivers/is31fl3746a)|72 |
|[SNLED27351](../drivers/snled27351) |192 |
To assign the LED Matrix driver, add the following to your `rules.mk`, for example:
To assign the LED Matrix driver, add the following to your keyboard config, for example:
:::::tabs
==== `JSON`
```json
"led_matrix": {
"driver": "is31fl3218"
}
```
==== `rules.mk`
```make
LED_MATRIX_DRIVER = is31fl3218
```
:::::
## Common Configuration {#common-configuration}
From this point forward the configuration is the same for all the drivers. The `led_config_t` struct provides a key electrical matrix to led index lookup table, what the physical position of each LED is on the board, and what type of key or usage the LED if the LED represents. Here is a brief example:
:::::tabs
==== `JSON`
```json
"led_matrix": {
"layout": [
{"matrix": [0, 3], "x": 188, "y": 16, "flags": 1},
{"matrix": [1, 3], "x": 187, "y": 48, "flags": 4},
{"matrix": [2, 3], "x": 147, "y": 64, "flags": 4},
{"matrix": [2, 0], "x": 112, "y": 64, "flags": 4},
{"matrix": [1, 0], "x": 37, "y": 48, "flags": 4},
{"matrix": [0, 0], "x": 38, "y": 16, "flags": 1}
]
}
```
The first part, `matrix`, tells the system what key this LED represents using the key's electrical matrix row & col. This part is optional, if the LED doesn't correspond to a switch (such as underglow leds).
The second and third parts represents the LED's physical `x, y` position on the keyboard. The default expected range of values for `x` is `0-224`, and the default expected range of values for `y` is `0-64`. This default expected range is due to effects that calculate the center of the keyboard for their animations. The easiest way to calculate these positions is imagine your keyboard is a grid, and the top left of the keyboard represents `{ x, y }` coordinate `{ 0, 0 }` and the bottom right of your keyboard represents `{ 224, 64 }`. Using this as a basis, you can use the following formula to calculate the physical position:
```c
x = 224 / (NUMBER_OF_COLS - 1) * COL_POSITION
y = 64 / (NUMBER_OF_ROWS - 1) * ROW_POSITION
```
Where NUMBER_OF_COLS, NUMBER_OF_ROWS, COL_POSITION, & ROW_POSITION are all based on the physical layout of your keyboard, not the electrical layout.
As mentioned earlier, the center of the keyboard by default is expected to be `{ 112, 32 }`, but this can be changed if you want to more accurately calculate the LED's physical `{ x, y }` positions. Keyboard designers can implement `led_matrix.center_point = [ 112, 32 ]` in their json with the new center point of the keyboard, or where they want it to be allowing more possibilities for the `x, y` values. Do note that the maximum value for x or y is 255, and the recommended maximum is 224 as this gives animations runoff room before they reset.
The last value `flags` is a bitmask, whether or not a certain LEDs is of a certain type. It is recommended that LEDs are set to only 1 type.
==== `<keyboard>.c`
```c
led_config_t g_led_config = { {
// Key Matrix to LED Index
@@ -63,6 +111,8 @@ As mentioned earlier, the center of the keyboard by default is expected to be `{
`// LED Index to Flag` is a bitmask, whether or not a certain LEDs is of a certain type. It is recommended that LEDs are set to only 1 type.
:::::
## Flags {#flags}
|Define |Value |Description |
@@ -119,12 +169,75 @@ enum led_matrix_effects {
LED_MATRIX_SOLID_MULTISPLASH, // Value pulses away from multiple key hits then fades out
LED_MATRIX_WAVE_LEFT_RIGHT, // Sine wave scrolling from left to right
LED_MATRIX_WAVE_UP_DOWN, // Sine wave scrolling from up to down
LED_MATRIX_TYPING_HEATMAP, // How hot is your WPM!
LED_MATRIX_EFFECT_MAX
};
```
You can enable a single effect by defining `ENABLE_[EFFECT_NAME]` in your `config.h`:
:::::tabs
==== `JSON`
You can enable a single effect by setting it true in the `led_matrix.animations` section in your json:
```json
"led_matrix": {
"animations": {
"alphas_mods": true,
"breathing": true,
"band": true,
"band_pinwheel": true,
"band_spiral": true,
"cycle_left_right": true,
"cycle_up_down": true,
"cycle_out_in": true,
"dual_beacon": true,
"wave_left_right": true,
"wave_up_down": true,
}
},
```
**Framebuffer effects**
```json
"led_matrix": {
"animations": {
"typing_heatmap": true,
}
}
```
::: tip
These modes introduce additional logic that can increase firmware size.
:::
**Reactive effects**
```json
"led_matrix": {
"animations": {
"solid_reactive_simple": true,
"solid_reactive": true,
"solid_reactive_wide": true,
"solid_reactive_multiwide": true,
"solid_reactive_cross": true,
"solid_reactive_multicross": true,
"solid_reactive_nexus": true,
"solid_reactive_multinexus": true,
"splash": true,
"multisplash": true,
}
}
```
::: tip
These modes introduce additional logic that can increase firmware size.
:::
==== `config.h`
You can enable a single effect by defining `ENABLE_[EFFECT_NAME]` in your `config.h`:
|Define |Description |
|-------------------------------------------------------|----------------------------------------------|
@@ -140,6 +253,14 @@ You can enable a single effect by defining `ENABLE_[EFFECT_NAME]` in your `confi
|`#define ENABLE_LED_MATRIX_WAVE_LEFT_RIGHT` |Enables `LED_MATRIX_WAVE_LEFT_RIGHT` |
|`#define ENABLE_LED_MATRIX_WAVE_UP_DOWN` |Enables `LED_MATRIX_WAVE_UP_DOWN` |
|Framebuffer Defines |Description |
|------------------------------------------------------|-----------------------------------------------|
|`#define ENABLE_LED_MATRIX_TYPING_HEATMAP` |Enables `LED_MATRIX_TYPING_HEATMAP` |
::: tip
These modes introduce additional logic that can increase firmware size.
:::
|Reactive Defines |Description |
|-------------------------------------------------------|----------------------------------------------|
|`#define ENABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE` |Enables `LED_MATRIX_SOLID_REACTIVE_SIMPLE` |
@@ -156,6 +277,44 @@ You can enable a single effect by defining `ENABLE_[EFFECT_NAME]` in your `confi
These modes introduce additional logic that can increase firmware size.
:::
:::::
### LED Matrix Effect Typing Heatmap {#led-matrix-effect-typing-heatmap}
This effect will scale the LED matrix brightness according to a heatmap of recently pressed keys. Whenever a key is pressed its "temperature" increases as well as that of its neighboring keys. The temperature of each key is then decreased automatically every 25 milliseconds by default.
In order to change the delay of temperature decrease define `LED_MATRIX_TYPING_HEATMAP_DECREASE_DELAY_MS`:
```c
#define LED_MATRIX_TYPING_HEATMAP_DECREASE_DELAY_MS 50
```
As heatmap uses the physical position of the leds set in the g_led_config, you may need to tweak the following options to get the best effect for your keyboard. Note the size of this grid is `224x64`.
Limit the distance the effect spreads to surrounding keys.
```c
#define LED_MATRIX_TYPING_HEATMAP_SPREAD 40
```
Limit how hot surrounding keys get from each press.
```c
#define LED_MATRIX_TYPING_HEATMAP_AREA_LIMIT 16
```
Remove the spread effect entirely.
```c
#define LED_MATRIX_TYPING_HEATMAP_SLIM
```
It's also possible to adjust the tempo of *heating up*. It's defined as the number of steps by which to increment the brightness. Decreasing this value increases the number of keystrokes needed to fully heat up the key.
```c
#define LED_MATRIX_TYPING_HEATMAP_INCREASE_STEP 32
```
## Custom LED Matrix Effects {#custom-led-matrix-effects}
By setting `LED_MATRIX_CUSTOM_USER = yes` in `rules.mk`, new effects can be defined directly from your keymap or userspace, without having to edit any QMK core files. To declare new effects, create a `led_matrix_user.inc` file in the user keymap directory or userspace folder.
@@ -235,11 +394,61 @@ const char* effect_name = led_matrix_get_mode_name(led_matrix_get_mode());
`led_matrix_get_mode_name()` is not enabled by default as it increases the amount of flash memory used by the firmware based on the number of effects enabled.
:::
## Additional `config.h` Options {#additional-configh-options}
## Additional Configuration Options {#additional-configh-options}
```c
#define LED_MATRIX_MODE_NAME_ENABLE // enables led_matrix_get_mode_name()
```
:::::tabs
==== `JSON`
```json
"led_matrix": {
"default": {
// Sets the default enabled state, if none has been set
"on": true,
// Sets the default mode, if none has been set
"animation": "solid",
// Sets the default brightness value, if none has been set
"val": 127,
// Sets the default speed, if none has been set
"speed": 127,
// Sets the default flag, if none has been set
"flags": 255
},
// Sets the flags which can be cycled through
"flag_steps": [
// LED_FLAG_ALL, LED_FLAG_KEYLIGHT | LED_FLAG_MODIFIER, LED_FLAG_NONE
255, 5, 0
],
// limits max brightness of leds
"max_brightness": 255,
// number of milliseconds to wait until led automatically turns off
"timeout": 0,
// The value by which to increment the brightness per adjustment action
"val_steps": 16,
// The value by which to increment the animation speed per adjustment action
"speed_steps": 16,
// limits in milliseconds how frequently an animation will update the LEDs.
// 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
"led_flush_limit": 16,
// limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
"led_process_limit": 15,
// reactive effects respond to keyreleases (instead of keypresses)
"react_on_keyup": true,
// turn off effects when suspended
"sleep": true,
// (Optional) For split keyboards, the number of LEDs connected on each half. X = left, Y = Right.
// If reactive effects are enabled, you also will want to enable split.transport.sync.matrix_state
"split_count": [X, Y],
}
```
==== `config.h`
```c
#define LED_MATRIX_KEYRELEASES // reactive effects respond to keyreleases (instead of keypresses)
#define LED_MATRIX_TIMEOUT 0 // number of milliseconds to wait until led automatically turns off
#define LED_MATRIX_SLEEP // turn off effects when suspended
@@ -258,6 +467,8 @@ const char* effect_name = led_matrix_get_mode_name(led_matrix_get_mode());
#define LED_MATRIX_FLAG_STEPS { LED_FLAG_ALL, LED_FLAG_KEYLIGHT | LED_FLAG_MODIFIER, LED_FLAG_NONE } // Sets the flags which can be cycled through.
```
:::::
## EEPROM storage {#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).
+1 -1
View File
@@ -166,7 +166,7 @@ In your keyboard config.h:
The `PIO` subsystem is a Raspberry Pi RP2040 specific implementation, using the integrated PIO peripheral and is therefore only available on this MCU.
There are strict requirements for pin ordering but any pair of GPIO pins can be used. The GPIO used for clock must be directly after data, see the included info.json snippet for an example of correct order.
The GPIOs used for clock and data must be consecutive (in either order).
You may optionally switch the PIO peripheral used with the following define in config.h:
```c
+6 -2
View File
@@ -28,10 +28,14 @@ To send data to the keyboard, you must first find a library for communicating wi
* **Node.js:** [node-hid](https://github.com/node-hid/node-hid)
* **C/C++:** [hidapi](https://github.com/libusb/hidapi)
* **Java:** [purejavahidapi](https://github.com/nyholku/purejavahidapi) and [hid4java](https://github.com/gary-rowe/hid4java)
* **Python:** [pyhidapi](https://pypi.org/project/hid/) and [pywinusb](https://pypi.org/project/pywinusb)
* **Python:** [hid](https://pypi.org/project/hid/) and [pywinusb](https://pypi.org/project/pywinusb)
Please refer to these libraries' own documentation for instructions on usage. Remember to close the device once you are finished with it!
::: tip
The `hid` package is installed with `pip install hid` and imported as `import hid`. Avoid installing the unrelated `pyhidapi` package from PyPI, which is a different, unmaintained project despite the similar name.
:::
Next, you will need to know the USB Vendor and Product IDs of the device. These can easily be found by looking at your keyboard's `info.json`, under the `usb` object (alternatively, you can also use Device Manager on Windows, System Information on macOS, or `lsusb` on Linux). For example, the Vendor ID for the Planck Rev 6 is `0x03A8`, and the Product ID is `0xA4F9`.
It's also a good idea to narrow down the list of potential HID devices the library may give you by filtering on the usage page and usage ID, to avoid accidentally opening the interface on the same device for the keyboard, or mouse, or media keys, etc.
@@ -72,7 +76,7 @@ void raw_hid_receive(uint8_t *data, uint8_t length) {
}
```
On the host side (here we are using Python and the `pyhidapi` library), the HID device is opened by enumerating the interfaces on the USB device, then filtering on the usage page and usage ID. Then, a report containing a single ASCII "A" (hex `0x41`) is constructed and sent.
On the host side (here we are using Python and the `hid` package), the HID device is opened by enumerating the interfaces on the USB device, then filtering on the usage page and usage ID. Then, a report containing a single ASCII "A" (hex `0x41`) is constructed and sent.
For demonstration purposes, the manufacturer and product strings of the device, along with the request and response, are also printed.
+221 -4
View File
@@ -27,16 +27,64 @@ RGB Matrix is an abstraction layer on top of an underlying LED driver API. The l
|[SNLED27351](../drivers/snled27351) |64 |
|[WS2812](../drivers/ws2812) |? |
To assign the RGB Matrix driver, add the following to your `rules.mk`, for example:
To assign the RGB Matrix driver, add the following to your keyboard config, for example:
:::::tabs
==== `JSON`
```json
"rgb_matrix": {
"driver": "is31fl3218"
}
```
==== `rules.mk`
```make
RGB_MATRIX_DRIVER = is31fl3218
```
:::::
## Common Configuration {#common-configuration}
From this point forward the configuration is the same for all the drivers. The `led_config_t` struct provides a key electrical matrix to led index lookup table, what the physical position of each LED is on the board, and what type of key or usage the LED if the LED represents. Here is a brief example:
:::::tabs
==== `JSON`
```json
"rgb_matrix": {
"layout": [
{"matrix": [0, 3], "x": 188, "y": 16, "flags": 1},
{"matrix": [1, 3], "x": 187, "y": 48, "flags": 4},
{"matrix": [2, 3], "x": 147, "y": 64, "flags": 4},
{"matrix": [2, 0], "x": 112, "y": 64, "flags": 4},
{"matrix": [1, 0], "x": 37, "y": 48, "flags": 4},
{"matrix": [0, 0], "x": 38, "y": 16, "flags": 1}
]
}
```
The first part, `matrix`, tells the system what key this LED represents using the key's electrical matrix row & col. This part is optional, if the LED doesn't correspond to a switch (such as underglow leds).
The second and third parts represents the LED's physical `x, y` position on the keyboard. The default expected range of values for `x` is `0-224`, and the default expected range of values for `y` is `0-64`. This default expected range is due to effects that calculate the center of the keyboard for their animations. The easiest way to calculate these positions is imagine your keyboard is a grid, and the top left of the keyboard represents `{ x, y }` coordinate `{ 0, 0 }` and the bottom right of your keyboard represents `{ 224, 64 }`. Using this as a basis, you can use the following formula to calculate the physical position:
```c
x = 224 / (NUMBER_OF_COLS - 1) * COL_POSITION
y = 64 / (NUMBER_OF_ROWS - 1) * ROW_POSITION
```
Where NUMBER_OF_COLS, NUMBER_OF_ROWS, COL_POSITION, & ROW_POSITION are all based on the physical layout of your keyboard, not the electrical layout.
As mentioned earlier, the center of the keyboard by default is expected to be `{ 112, 32 }`, but this can be changed if you want to more accurately calculate the LED's physical `{ x, y }` positions. Keyboard designers can implement `rgb_matrix.center_point = [ 112, 32 ]` in their json with the new center point of the keyboard, or where they want it to be allowing more possibilities for the `x, y` values. Do note that the maximum value for x or y is 255, and the recommended maximum is 224 as this gives animations runoff room before they reset.
The last value `flags` is a bitmask, whether or not a certain LEDs is of a certain type. It is recommended that LEDs are set to only 1 type.
==== `<keyboard>.c`
```c
led_config_t g_led_config = { {
// Key Matrix to LED Index
@@ -62,10 +110,12 @@ y = 64 / (NUMBER_OF_ROWS - 1) * ROW_POSITION
Where NUMBER_OF_COLS, NUMBER_OF_ROWS, COL_POSITION, & ROW_POSITION are all based on the physical layout of your keyboard, not the electrical layout.
As mentioned earlier, the center of the keyboard by default is expected to be `{ 112, 32 }`, but this can be changed if you want to more accurately calculate the LED's physical `{ x, y }` positions. Keyboard designers can implement `#define RGB_MATRIX_CENTER { 112, 32 }` in their config.h file with the new center point of the keyboard, or where they want it to be allowing more possibilities for the `{ x, y }` values. Do note that the maximum value for x or y is 255, and the recommended maximum is 224 as this gives animations runoff room before they reset.
As mentioned earlier, the center of the keyboard by default is expected to be `{ 112, 32 }`, but this can be changed if you want to more accurately calculate the LED's physical `{ x, y }` positions. Keyboard designers can implement `rgb_matrix.center_point = [ 112, 32]` in their json (or `#define RGB_MATRIX_CENTER {112, 32}` in their config.h file) with the new center point of the keyboard, or where they want it to be allowing more possibilities for the `x, y` values. Do note that the maximum value for x or y is 255, and the recommended maximum is 224 as this gives animations runoff room before they reset.
`// LED Index to Flag` is a bitmask, whether or not a certain LEDs is of a certain type. It is recommended that LEDs are set to only 1 type.
:::::
## Flags {#flags}
|Define |Value |Description |
@@ -160,8 +210,113 @@ enum rgb_matrix_effects {
};
```
You can enable a single effect by defining `ENABLE_[EFFECT_NAME]` in your `config.h`:
:::::tabs
==== `JSON`
You can enable a single effect by setting it true in the `rgb_matrix.animations` section in your json:
```json
"rgb_matrix": {
"animations": {
"alphas_mods": true,
"gradient_up_down": true,
"gradient_left_right": true,
"breathing": true,
"band_sat": true,
"band_val": true,
"band_pinwheel_sat": true,
"band_pinwheel_val": true,
"band_spiral_sat": true,
"band_spiral_val": true,
"cycle_all": true,
"cycle_left_right": true,
"cycle_up_down": true,
"rainbow_moving_chevron": true,
"cycle_out_in": true,
"cycle_out_in_dual": true,
"cycle_pinwheel": true,
"cycle_spiral": true,
"dual_beacon": true,
"rainbow_beacon": true,
"rainbow_pinwheels": true,
"raindrops": true,
"jellybean_raindrops": true,
"hue_breathing": true,
"hue_pendulum": true,
"hue_wave": true,
"pixel_rain": true,
"pixel_flow": true,
"pixel_fractal": true,
"typing_heatmap": true,
"digital_rain": true,
"solid_reactive_simple": true,
"solid_reactive": true,
"solid_reactive_wide": true,
"solid_reactive_multiwide": true,
"solid_reactive_cross": true,
"solid_reactive_multicross": true,
"solid_reactive_nexus": true,
"solid_reactive_multinexus": true,
"splash": true,
"multispash": true,
"solid_splash": true,
"solid_multisplash": true,
"starlight": true,
"starlight_smooth": true,
"starlight_dual_hue": true,
"starlight_dual_sat": true,
"riverflow": true
}
},
```
**Framebuffer effects**
```json
"rgb_matrix": {
"animations": {
"typing_heatmap": true,
"digital_rain": true,
}
}
```
::: tip
These modes introduce additional logic that can increase firmware size.
:::
**Reactive effects**
```json
"rgb_matrix": {
"animations": {
"solid_reactive_simple": true,
"solid_reactive": true,
"solid_reactive_wide": true,
"solid_reactive_multiwide": true,
"solid_reactive_cross": true,
"solid_reactive_multicross": true,
"solid_reactive_nexus": true,
"solid_reactive_multinexus": true,
"splash": true,
"multisplash": true,
"solid_splash": true,
"solid_multisplash": true
}
}
```
::: tip
These modes introduce additional logic that can increase firmware size.
:::
==== `config.h`
You can enable a single effect by defining `ENABLE_[EFFECT_NAME]` in your `config.h`:
|Define |Description |
|------------------------------------------------------|----------------------------------------------|
@@ -229,6 +384,7 @@ These modes introduce additional logic that can increase firmware size.
These modes introduce additional logic that can increase firmware size.
:::
:::::
### RGB Matrix Effect Typing Heatmap {#rgb-matrix-effect-typing-heatmap}
@@ -387,10 +543,69 @@ const char* effect_name = rgb_matrix_get_mode_name(rgb_matrix_get_mode());
:::
## Additional `config.h` Options {#additional-configh-options}
## Additional Configuration Options {#additional-configh-options}
```c
#define RGB_MATRIX_MODE_NAME_ENABLE // enables rgb_matrix_get_mode_name()
```
:::::tabs
==== `JSON`
```json
"rgb_matrix": {
"default": {
// Sets the default enabled state, if none has been set
"on": true,
// Sets the default mode, if none has been set
"animation": "cycle_left_right",
// Sets the default hue value, if none has been set
"hue": 0,
// Sets the default saturation value, if none has been set
"sat": 255,
// Sets the default brightness value, if none has been set
"val": 127,
// Sets the default speed, if none has been set
"speed": 127,
// Sets the default flag, if none has been set
"flags": 255
},
// Sets the flags which can be cycled through
"flag_steps": [
// LED_FLAG_ALL, LED_FLAG_KEYLIGHT | LED_FLAG_MODIFIER, LED_FLAG_UNDERGLOW, LED_FLAG_NONE
255, 5, 2, 0
],
// limits max brightness of leds
"max_brightness": 255,
// number of milliseconds to wait until rgb automatically turns off
"timeout": 0,
// The value by which to increment the hue per adjustment action
"hue_steps": 8,
// The value by which to increment the saturation per adjustment action
"sat_steps": 16,
// The value by which to increment the brightness per adjustment action
"val_steps": 16,
// The value by which to increment the animation speed per adjustment action
"speed_steps": 16,
// limits in milliseconds how frequently an animation will update the LEDs.
// 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
"led_flush_limit": 16,
// limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
"led_process_limit": 15,
// reactive effects respond to keyreleases (instead of keypresses)
"react_on_keyup": true,
// turn off effects when suspended
"sleep": true,
// (Optional) For split keyboards, the number of LEDs connected on each half. X = left, Y = Right.
// If reactive effects are enabled, you also will want to enable split.transport.sync.matrix_state
"split_count": [X, Y],
}
```
==== `config.h`
```c
#define RGB_MATRIX_KEYRELEASES // reactive effects respond to keyreleases (instead of keypresses)
#define RGB_MATRIX_TIMEOUT 0 // number of milliseconds to wait until rgb automatically turns off
#define RGB_MATRIX_SLEEP // turn off effects when suspended
@@ -414,6 +629,8 @@ const char* effect_name = rgb_matrix_get_mode_name(rgb_matrix_get_mode());
#define RGB_MATRIX_FLAG_STEPS { LED_FLAG_ALL, LED_FLAG_KEYLIGHT | LED_FLAG_MODIFIER, LED_FLAG_UNDERGLOW, LED_FLAG_NONE } // Sets the flags which can be cycled through.
```
:::::
## EEPROM storage {#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).
+139 -63
View File
@@ -6,11 +6,12 @@ The [Open Steno Project](https://www.openstenoproject.org/) has built an open-so
## Steno Support in QMK
There are three ways that QMK keyboards can support steno, with varying degrees of configuration required:
There are four ways that QMK keyboards can support steno, with varying degrees of configuration required:
1. Plover with [Arpeggiation](https://plover.wiki/index.php/Glossary#Arpeggiate) requires no changes to any keyboard and is supported by QMK as well as any other QWERTY keyboard.
2. Plover with [NKRO](https://plover.wiki/index.php/Using_a_standard_keyboard_with_Plover#NKRO). If your keyboard supports NKRO in hardware and you have NKRO enabled as a USB endpoint, you can chord with the keyboard. Many devices will arrive stock like this and will require no changes.
3. Steno Machine Protocols. This requires the most configuration, but this has the advantage of allowing you to use your keyboard keys normally (either on another layer or another piece of hardware) without enabling and disabling your steno software.
4. Plover HID Protocol. This is a custom HID protocol that Plover can understand, but does not require a COM port. It is robust to device disconnects and saves an interface over the COM-based alternatives.
## Plover with QWERTY Keyboard {#plover-with-qwerty-keyboard}
@@ -92,9 +93,27 @@ Examples of steno strokes and the associated packet:
- `WAZ` = `10000000 00000010 00100000 00000000 00000000 00000001`
- `PHAPBGS` = `10000000 00000101 00100000 00000000 01101010 00000000`
### Switching protocols on the fly {#switching-protocols-on-the-fly}
## Plover HID Protocol {#plover-hid-protocol}
If you wish to switch the serial protocol used to transfer the steno chords without having to recompile your keyboard firmware every time, you can press the `QK_STENO_BOLT` and `QK_STENO_GEMINI` keycodes in order to switch protocols on the fly.
This mode operates independently of the other Steno "official" machine protocols. Like any other mouse or keyboard, it uses the USB HID protocol to communicate with Plover by sending an 8 byte (64 bit) packet representing a bitfield for all the possible keys on a steno machine plus a number of additional general purpose keys for custom use. This protocol is only understood by Plover as of [5.1.0](https://github.com/opensteno/plover/releases/tag/v5.1.0).
To enable this functionality, add the following lines to your `rules.mk`:
```make
PLOVER_HID_ENABLE = yes
```
::: warning
The Plover HID Protocol is currently mutually exclusive with the other steno protocols and will be disabled when `STENO_ENABLE` is set.
:::
All of the possible keycodes are defined with the `ST_` prefix and are available without any additional includes.
More details can be found here: https://github.com/dnaq/plover-machine-hid
## Switching protocols on the fly {#switching-protocols-on-the-fly}
If you wish to switch the serial protocol used to transfer the steno chords without having to recompile your keyboard firmware every time, you can press one of the [mode keycodes](#keycode-reference-mode) in order to switch protocols on the fly.
To enable these special keycodes, add the following lines to your `rules.mk`:
```make
@@ -106,6 +125,13 @@ If you want to switch protocols programmatically, as part of a custom macro for
The default protocol is Gemini PR but the last protocol used is stored in non-volatile memory so QMK will remember your choice between reboots of your keyboard &mdash; assuming that your keyboard features (emulated) EEPROM.
To configure the default, add one of the following lines to your `config.h`:
```c
#define STENO_DEFAULT_MODE STENO_MODE_GEMINI
#define STENO_DEFAULT_MODE STENO_MODE_BOLT
```
Naturally, this option takes the most amount of firmware space as it needs to compile the code for all the available stenography protocols. In most cases, compiling a single stenography protocol is sufficient.
The default value for `STENO_PROTOCOL` is `all`.
@@ -126,7 +152,7 @@ To test your keymap, you can chord keys on your keyboard and either look at the
## Learning Stenography {#learning-stenography}
* [Learn Plover!](https://sites.google.com/site/learnplover/)
* [Learn Plover!](https://opensteno.org/learn-plover/)
* [Steno Jig](https://joshuagrams.github.io/steno-jig/)
* More resources at the Plover [Learning Stenography](https://github.com/openstenoproject/plover/wiki/Learning-Stenography) wiki
@@ -144,7 +170,7 @@ This function is called when a chord is about to be sent. Mode will be one of `S
bool process_steno_user(uint16_t keycode, keyrecord_t *record) { return true; }
```
This function is called when a keypress has come in, before it is processed. The keycode should be one of `QK_STENO_BOLT`, `QK_STENO_GEMINI`, or one of the `STN_*` key values.
This function is called when a keypress has come in, before it is processed. The keycode should be one of `QK_STENO_MODE_BOLT`, `QK_STENO_MODE_GEMINI`, or one of the `ST_*` key values.
```c
bool post_process_steno_user(uint16_t keycode, keyrecord_t *record, steno_mode_t mode, uint8_t chord[MAX_STROKE_SIZE], int8_t n_pressed_keys);
@@ -154,7 +180,7 @@ This function is called after a key has been processed, but before any decision
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.
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 `[ST_E, ST_U, ST_BR, ST_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.
The `n_pressed_keys` argument is the number of physical keys actually being held down.
This is not always equal to the number of bits set to 1 (aka the [Hamming weight](https://en.wikipedia.org/wiki/Hamming_weight)) in `chord` because it is possible to simultaneously press down four keys, then release three of those four keys and then press yet another key while the fourth finger is still holding down its key.
@@ -163,67 +189,117 @@ At the end of this scenario given as an example, `chord` would have five bits se
## Keycode Reference {#keycode-reference}
### Mode {#keycode-reference-mode}
When more than one protocol is enabled, the following keycodes are available:
| Key | Aliases | Description |
|---------------------------|---------|---------------------------------------------------------------------------|
|`QK_STENO_MODE_BOLT` |`ST_BOLT`| Set mode to `STENO_MODE_BOLT` (when multiple protocols are enabled) |
|`QK_STENO_MODE_GEMINI` |`ST_GEMI`| Set mode to `STENO_MODE_GEMINI` (when multiple protocols are enabled) |
|`QK_STENO_MODE_NEXT` |`ST_NEXT`| Cycle through modes (when multiple protocols are enabled) |
|`QK_STENO_MODE_PREVIOUS` |`ST_PREV`| Cycle through modes in reverse (when multiple protocols are enabled) |
### General {#keycode-reference-general}
::: info
TX Bolt does not support the full set of keys. The TX Bolt implementation in QMK will map the GeminiPR keys to the nearest TX Bolt key so that one key map will work for both.
:::
|GeminiPR|TX Bolt|Steno Key|
|--------|-------|-----------|
|`STN_N1`|`STN_NUM`|Number bar #1|
|`STN_N2`|`STN_NUM`|Number bar #2|
|`STN_N3`|`STN_NUM`|Number bar #3|
|`STN_N4`|`STN_NUM`|Number bar #4|
|`STN_N5`|`STN_NUM`|Number bar #5|
|`STN_N6`|`STN_NUM`|Number bar #6|
|`STN_N7`|`STN_NUM`|Number bar #7|
|`STN_N8`|`STN_NUM`|Number bar #8|
|`STN_N9`|`STN_NUM`|Number bar #9|
|`STN_NA`|`STN_NUM`|Number bar #A|
|`STN_NB`|`STN_NUM`|Number bar #B|
|`STN_NC`|`STN_NUM`|Number bar #C|
|`STN_S1`|`STN_SL`| `S-` upper|
|`STN_S2`|`STN_SL`| `S-` lower|
|`STN_TL`|`STN_TL`| `T-`|
|`STN_KL`|`STN_KL`| `K-`|
|`STN_PL`|`STN_PL`| `P-`|
|`STN_WL`|`STN_WL`| `W-`|
|`STN_HL`|`STN_HL`| `H-`|
|`STN_RL`|`STN_RL`| `R-`|
|`STN_A`|`STN_A`| `A` vowel|
|`STN_O`|`STN_O`| `O` vowel|
|`STN_ST1`|`STN_STR`| `*` upper-left |
|`STN_ST2`|`STN_STR`| `*` lower-left|
|`STN_ST3`|`STN_STR`| `*` upper-right|
|`STN_ST4`|`STN_STR`| `*` lower-right|
|`STN_E`|`STN_E`| `E` vowel|
|`STN_U`|`STN_U`| `U` vowel|
|`STN_FR`|`STN_FR`| `-F`|
|`STN_RR`|`STN_RR`| `-R`|
|`STN_PR`|`STN_PR`| `-P`|
|`STN_BR`|`STN_BR`| `-B`|
|`STN_LR`|`STN_LR`| `-L`|
|`STN_GR`|`STN_GR`| `-G`|
|`STN_TR`|`STN_TR`| `-T`|
|`STN_SR`|`STN_SR`| `-S`|
|`STN_DR`|`STN_DR`| `-D`|
|`STN_ZR`|`STN_ZR`| `-Z`|
|`STN_FN`|| (Function)|
|`STN_RES1`||(Reset 1)|
|`STN_RES2`||(Reset 2)|
|`STN_PWR`||(Power)|
| Key | GeminiPR | TX Bolt | Description |
|---------------------|-----------|----------|-----------------|
| `QK_STENO_N1` | `ST_N1` | `ST_NUM` | Number bar #1 |
| `QK_STENO_N2` | `ST_N2` | `ST_NUM` | Number bar #2 |
| `QK_STENO_N3` | `ST_N3` | `ST_NUM` | Number bar #3 |
| `QK_STENO_N4` | `ST_N4` | `ST_NUM` | Number bar #4 |
| `QK_STENO_N5` | `ST_N5` | `ST_NUM` | Number bar #5 |
| `QK_STENO_N6` | `ST_N6` | `ST_NUM` | Number bar #6 |
| `QK_STENO_N7` | `ST_N7` | `ST_NUM` | Number bar #7 |
| `QK_STENO_N8` | `ST_N8` | `ST_NUM` | Number bar #8 |
| `QK_STENO_N9` | `ST_N9` | `ST_NUM` | Number bar #9 |
| `QK_STENO_NA` | `ST_NA` | `ST_NUM` | Number bar #A |
| `QK_STENO_NB` | `ST_NB` | `ST_NUM` | Number bar #B |
| `QK_STENO_NC` | `ST_NC` | `ST_NUM` | Number bar #C |
| `QK_STENO_S1` | `ST_S1` | `ST_SL` | `S-` upper |
| `QK_STENO_S2` | `ST_S2` | `ST_SL` | `S-` lower |
| `QK_STENO_TL` | `ST_TL` | `ST_TL` | `T-` |
| `QK_STENO_KL` | `ST_KL` | `ST_KL` | `K-` |
| `QK_STENO_PL` | `ST_PL` | `ST_PL` | `P-` |
| `QK_STENO_WL` | `ST_WL` | `ST_WL` | `W-` |
| `QK_STENO_HL` | `ST_HL` | `ST_HL` | `H-` |
| `QK_STENO_RL` | `ST_RL` | `ST_RL` | `R-` |
| `QK_STENO_A` | `ST_A` | `ST_A` | `A` vowel |
| `QK_STENO_O` | `ST_O` | `ST_O` | `O` vowel |
| `QK_STENO_ST1` | `ST_ST1` | `ST_STR` | `*` upper-left |
| `QK_STENO_ST2` | `ST_ST2` | `ST_STR` | `*` lower-left |
| `QK_STENO_ST3` | `ST_ST3` | `ST_STR` | `*` upper-right |
| `QK_STENO_ST4` | `ST_ST4` | `ST_STR` | `*` lower-right |
| `QK_STENO_E` | `ST_E` | `ST_E` | `E` vowel |
| `QK_STENO_U` | `ST_U` | `ST_U` | `U` vowel |
| `QK_STENO_FR` | `ST_FR` | `ST_FR` | `-F` |
| `QK_STENO_RR` | `ST_RR` | `ST_RR` | `-R` |
| `QK_STENO_PR` | `ST_PR` | `ST_PR` | `-P` |
| `QK_STENO_BR` | `ST_BR` | `ST_BR` | `-B` |
| `QK_STENO_LR` | `ST_LR` | `ST_LR` | `-L` |
| `QK_STENO_GR` | `ST_GR` | `ST_GR` | `-G` |
| `QK_STENO_TR` | `ST_TR` | `ST_TR` | `-T` |
| `QK_STENO_SR` | `ST_SR` | `ST_SR` | `-S` |
| `QK_STENO_DR` | `ST_DR` | `ST_DR` | `-D` |
| `QK_STENO_ZR` | `ST_ZR` | `ST_ZR` | `-Z` |
| `QK_STENO_FUNCTION` | `ST_FN` | | (Function) |
| `QK_STENO_RESET1` | `ST_RES1` | | (Reset 1) |
| `QK_STENO_RESET2` | `ST_RES2` | | (Reset 2) |
| `QK_STENO_POWER` | `ST_PWR` | | (Power) |
### Protocol Specific {#keycode-reference-protocol-specific}
#### Plover HID {#keycode-reference-plover-hid}
Additional keycodes available for the [Plover HID Protocol](#plover-hid-protocol):
| Key | Aliases | Description |
|----------------|----------|-------------------------------------|
| `QK_STENO_X1` | `ST_X1` | Extra button 1 (Protocol specific) |
| `QK_STENO_X2` | `ST_X2` | Extra button 2 (Protocol specific) |
| `QK_STENO_X3` | `ST_X3` | Extra button 3 (Protocol specific) |
| `QK_STENO_X4` | `ST_X4` | Extra button 4 (Protocol specific) |
| `QK_STENO_X5` | `ST_X5` | Extra button 5 (Protocol specific) |
| `QK_STENO_X6` | `ST_X6` | Extra button 6 (Protocol specific) |
| `QK_STENO_X7` | `ST_X7` | Extra button 7 (Protocol specific) |
| `QK_STENO_X8` | `ST_X8` | Extra button 8 (Protocol specific) |
| `QK_STENO_X9` | `ST_X9` | Extra button 9 (Protocol specific) |
| `QK_STENO_X10` | `ST_X10` | Extra button 10 (Protocol specific) |
| `QK_STENO_X11` | `ST_X11` | Extra button 11 (Protocol specific) |
| `QK_STENO_X12` | `ST_X12` | Extra button 12 (Protocol specific) |
| `QK_STENO_X13` | `ST_X13` | Extra button 13 (Protocol specific) |
| `QK_STENO_X14` | `ST_X14` | Extra button 14 (Protocol specific) |
| `QK_STENO_X15` | `ST_X15` | Extra button 15 (Protocol specific) |
| `QK_STENO_X16` | `ST_X16` | Extra button 16 (Protocol specific) |
| `QK_STENO_X17` | `ST_X17` | Extra button 17 (Protocol specific) |
| `QK_STENO_X18` | `ST_X18` | Extra button 18 (Protocol specific) |
| `QK_STENO_X19` | `ST_X19` | Extra button 19 (Protocol specific) |
| `QK_STENO_X20` | `ST_X20` | Extra button 20 (Protocol specific) |
| `QK_STENO_X21` | `ST_X21` | Extra button 21 (Protocol specific) |
| `QK_STENO_X22` | `ST_X22` | Extra button 22 (Protocol specific) |
| `QK_STENO_X23` | `ST_X23` | Extra button 23 (Protocol specific) |
| `QK_STENO_X24` | `ST_X24` | Extra button 24 (Protocol specific) |
| `QK_STENO_X25` | `ST_X25` | Extra button 25 (Protocol specific) |
| `QK_STENO_X26` | `ST_X26` | Extra button 26 (Protocol specific) |
### Combined Map {#keycode-reference-combinedmap}
If you do not want to hit two keys with one finger combined keycodes can be used. These cause both keys to be reported as pressed or released. To use these keycodes define `STENO_COMBINEDMAP` in your `config.h` file.
|Combined key | Key1 | Key 2 |
|---------------|--------|----------|
|STN_S3 | STN_S1 | STN_S2 |
|STN_TKL | STN_TL | STN_KL |
|STN_PWL | STN_PL | STN_WL |
|STN_HRL | STN_HL | STN_RL |
|STN_FRR | STN_FR | STN_RR |
|STN_PBR | STN_PR | STN_BR |
|STN_LGR | STN_LR | STN_GR |
|STN_TSR | STN_TR | STN_SR |
|STN_DZR | STN_DR | STN_ZR |
|STN_AO | STN_A | STN_O |
|STN_EU | STN_E | STN_U |
| Combined key | Aliases | Key 1 | Key 2 |
|----------------|----------|---------|---------|
| `QK_STENO_S3` | `ST_S3` | `ST_S1` | `ST_S2` |
| `QK_STENO_TKL` | `ST_TKL` | `ST_TL` | `ST_KL` |
| `QK_STENO_PWL` | `ST_PWL` | `ST_PL` | `ST_WL` |
| `QK_STENO_HRL` | `ST_HRL` | `ST_HL` | `ST_RL` |
| `QK_STENO_FRR` | `ST_FRR` | `ST_FR` | `ST_RR` |
| `QK_STENO_PBR` | `ST_PBR` | `ST_PR` | `ST_BR` |
| `QK_STENO_LGR` | `ST_LGR` | `ST_LR` | `ST_GR` |
| `QK_STENO_TSR` | `ST_TSR` | `ST_TR` | `ST_SR` |
| `QK_STENO_DZR` | `ST_DZR` | `ST_DR` | `ST_ZR` |
| `QK_STENO_AO` | `ST_AO` | `ST_A` | `ST_O` |
| `QK_STENO_EU` | `ST_EU` | `ST_E` | `ST_U` |
+4
View File
@@ -375,6 +375,10 @@ In this configuration "hold" takes place **after** tap dance timeout. To achieve
Tap dance can be used to emulate `MT()` and `LT()` behavior when the tapped code is not a basic keycode. This is useful to send tapped keycodes that normally require `Shift`, such as parentheses or curly braces—or other modified keycodes, such as `Control + X`.
::: tip
For simply sending a non-basic keycode on tap while functioning as a modifier or layer switch on hold, a simpler (and often superior) alternative is to use a Mod-Tap or Layer-Tap key and intercept its tap function in `process_record_user()`. This avoids the complexity of Tap Dance, and allows the key to benefit from advanced Tap-Hold options. See [Intercepting Mod-Taps](../mod_tap#intercepting-mod-taps) for details.
:::
Below your layers and custom keycodes, add the following:
```c
+90
View File
@@ -728,6 +728,96 @@ See also: [Mod-Tap](mod_tap)
|`MEH_T(kc)` | |Left Control, Left Shift and Left Alt when held, `kc` when tapped |
|`HYPR_T(kc)` | |Left Control, Left Shift, Left Alt and Left GUI when held, `kc` when tapped|
## Stenography {#stenography}
See also: [Stenography](features/stenography)
|Key |Aliases |Description |
|------------------------|-------------------|---------------------------------------------------------------------|
|`QK_STENO_FUNCTION` |`ST_FN` |(Function) |
|`QK_STENO_N1` |`ST_N1`, `ST_NUM` |Number bar #1 |
|`QK_STENO_N2` |`ST_N2` |Number bar #2 |
|`QK_STENO_N3` |`ST_N3` |Number bar #3 |
|`QK_STENO_N4` |`ST_N4` |Number bar #4 |
|`QK_STENO_N5` |`ST_N5` |Number bar #5 |
|`QK_STENO_N6` |`ST_N6` |Number bar #6 |
|`QK_STENO_S1` |`ST_S1`, `ST_SL` |`S-` upper |
|`QK_STENO_S2` |`ST_S2` |`S-` lower |
|`QK_STENO_TL` |`ST_TL` |`T-` |
|`QK_STENO_KL` |`ST_KL` |`K-` |
|`QK_STENO_PL` |`ST_PL` |`P-` |
|`QK_STENO_WL` |`ST_WL` |`W-` |
|`QK_STENO_HL` |`ST_HL` |`H-` |
|`QK_STENO_RL` |`ST_RL` |`R-` |
|`QK_STENO_A` |`ST_A` |`A` vowel |
|`QK_STENO_O` |`ST_O` |`O` vowel |
|`QK_STENO_ST1` |`ST_ST1`, `ST_STR` |`*` upper-left |
|`QK_STENO_ST2` |`ST_ST2` |`*` lower-left |
|`QK_STENO_RESET1` |`ST_RE1`, `ST_RES1`|(Reset 1) |
|`QK_STENO_RESET2` |`ST_RE2`, `ST_RES2`|(Reset 2) |
|`QK_STENO_POWER` |`ST_PWR` |(Power) |
|`QK_STENO_ST3` |`ST_ST3` |`*` upper-right |
|`QK_STENO_ST4` |`ST_ST4` |`*` lower-right |
|`QK_STENO_E` |`ST_E` |`E` vowel |
|`QK_STENO_U` |`ST_U` |`U` vowel |
|`QK_STENO_FR` |`ST_FR` |`-F` |
|`QK_STENO_RR` |`ST_RR` |`-R` |
|`QK_STENO_PR` |`ST_PR` |`-P` |
|`QK_STENO_BR` |`ST_BR` |`-B` |
|`QK_STENO_LR` |`ST_LR` |`-L` |
|`QK_STENO_GR` |`ST_GR` |`-G` |
|`QK_STENO_TR` |`ST_TR` |`-T` |
|`QK_STENO_SR` |`ST_SR` |`-S` |
|`QK_STENO_DR` |`ST_DR` |`-D` |
|`QK_STENO_N7` |`ST_N7` |Number bar #7 |
|`QK_STENO_N8` |`ST_N8` |Number bar #8 |
|`QK_STENO_N9` |`ST_N9` |Number bar #9 |
|`QK_STENO_NA` |`ST_NA` |Number bar #A |
|`QK_STENO_NB` |`ST_NB` |Number bar #B |
|`QK_STENO_NC` |`ST_NC` |Number bar #C |
|`QK_STENO_ZR` |`ST_ZR` |`-Z` |
|`QK_STENO_X1` |`ST_X1` |Extra button 1 (Protocol specific) |
|`QK_STENO_X2` |`ST_X2` |Extra button 2 (Protocol specific) |
|`QK_STENO_X3` |`ST_X3` |Extra button 3 (Protocol specific) |
|`QK_STENO_X4` |`ST_X4` |Extra button 4 (Protocol specific) |
|`QK_STENO_X5` |`ST_X5` |Extra button 5 (Protocol specific) |
|`QK_STENO_X6` |`ST_X6` |Extra button 6 (Protocol specific) |
|`QK_STENO_X7` |`ST_X7` |Extra button 7 (Protocol specific) |
|`QK_STENO_X8` |`ST_X8` |Extra button 8 (Protocol specific) |
|`QK_STENO_X9` |`ST_X9` |Extra button 9 (Protocol specific) |
|`QK_STENO_X10` |`ST_X10` |Extra button 10 (Protocol specific) |
|`QK_STENO_X11` |`ST_X11` |Extra button 11 (Protocol specific) |
|`QK_STENO_X12` |`ST_X12` |Extra button 12 (Protocol specific) |
|`QK_STENO_X13` |`ST_X13` |Extra button 13 (Protocol specific) |
|`QK_STENO_X14` |`ST_X14` |Extra button 14 (Protocol specific) |
|`QK_STENO_X15` |`ST_X15` |Extra button 15 (Protocol specific) |
|`QK_STENO_X16` |`ST_X16` |Extra button 16 (Protocol specific) |
|`QK_STENO_X17` |`ST_X17` |Extra button 17 (Protocol specific) |
|`QK_STENO_X18` |`ST_X18` |Extra button 18 (Protocol specific) |
|`QK_STENO_X19` |`ST_X19` |Extra button 19 (Protocol specific) |
|`QK_STENO_X20` |`ST_X20` |Extra button 20 (Protocol specific) |
|`QK_STENO_X21` |`ST_X21` |Extra button 21 (Protocol specific) |
|`QK_STENO_X22` |`ST_X22` |Extra button 22 (Protocol specific) |
|`QK_STENO_X23` |`ST_X23` |Extra button 23 (Protocol specific) |
|`QK_STENO_X24` |`ST_X24` |Extra button 24 (Protocol specific) |
|`QK_STENO_X25` |`ST_X25` |Extra button 25 (Protocol specific) |
|`QK_STENO_X26` |`ST_X26` |Extra button 26 (Protocol specific) |
|`QK_STENO_S3` |`ST_S3` |Trigger `ST_S1` and `ST_S2` (when *Combined Map* is enabled) |
|`QK_STENO_TKL` |`ST_TKL` |Trigger `ST_TL` and `ST_KL` (when *Combined Map* is enabled) |
|`QK_STENO_PWL` |`ST_PWL` |Trigger `ST_PL` and `ST_WL` (when *Combined Map* is enabled) |
|`QK_STENO_HRL` |`ST_HRL` |Trigger `ST_HL` and `ST_RL` (when *Combined Map* is enabled) |
|`QK_STENO_FRR` |`ST_FRR` |Trigger `ST_FR` and `ST_RR` (when *Combined Map* is enabled) |
|`QK_STENO_PBR` |`ST_PBR` |Trigger `ST_PR` and `ST_BR` (when *Combined Map* is enabled) |
|`QK_STENO_LGR` |`ST_LGR` |Trigger `ST_LR` and `ST_GR` (when *Combined Map* is enabled) |
|`QK_STENO_TSR` |`ST_TSR` |Trigger `ST_TR` and `ST_SR` (when *Combined Map* is enabled) |
|`QK_STENO_DZR` |`ST_DZR` |Trigger `ST_DR` and `ST_ZR` (when *Combined Map* is enabled) |
|`QK_STENO_AO` |`ST_AO` |Trigger `ST_A` and `ST_O` (when *Combined Map* is enabled) |
|`QK_STENO_EU` |`ST_EU` |Trigger `ST_E` and `ST_U` (when *Combined Map* is enabled) |
|`QK_STENO_MODE_BOLT` |`ST_BOLT` |Set mode to `STENO_MODE_BOLT` (when multiple protocols are enabled) |
|`QK_STENO_MODE_GEMINI` |`ST_GEMI` |Set mode to `STENO_MODE_GEMINI` (when multiple protocols are enabled)|
|`QK_STENO_MODE_NEXT` |`ST_NEXT` |Cycle through modes (when multiple protocols are enabled) |
|`QK_STENO_MODE_PREVIOUS`|`ST_PREV` |Cycle through modes in reverse (when multiple protocols are enabled) |
## Tapping Term Keys {#tapping-term-keys}
See also: [Dynamic Tapping Term](tap_hold#dynamic-tapping-term)
+3 -1
View File
@@ -72,9 +72,11 @@ It can also be mitigated by increasing [`TAP_CODE_DELAY`](config_options#behavio
## Intercepting Mod-Taps
This technique works for both Mod-Tap (`MT`) and Layer-Tap (`LT`) keys.
### Changing tap function
The basic keycode limitation with Mod-Tap can be worked around by intercepting it in `process_record_user`. For example, shifted keycode `KC_DQUO` cannot be used with `MT()` because it is a 16-bit keycode alias of `LSFT(KC_QUOT)`. Modifiers on `KC_DQUO` will be masked by `MT()`. But the following custom code can be used to intercept the "tap" function to manually send `KC_DQUO`:
The basic keycode limitation with Mod-Tap and Layer-Tap can be worked around by intercepting it in `process_record_user`. For example, shifted keycode `KC_DQUO` cannot be used with `MT()` because it is a 16-bit keycode alias of `LSFT(KC_QUOT)`. Modifiers on `KC_DQUO` will be masked by `MT()`. But the following custom code can be used to intercept the "tap" function to manually send `KC_DQUO`:
```c
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+7
View File
@@ -866,6 +866,13 @@ Configures the [Stenography](features/stenography) feature.
* `enabled` <Badge type="info">Boolean</Badge>
* Enable the Stenography feature.
* Default: `false`
* `combined_map` <Badge type="info">Boolean</Badge>
* Enable the Stenography Combined Map sub-feature.
* Default: `false`
* `default`
* `mode` <Badge type="info">String</Badge>
* The default mode. Must be one of `geminipr`, `txbolt`.
* Default: `"geminipr"` when available, otherwise `"txbolt"`
* `protocol` <Badge type="info">String</Badge>
* The Steno protocol to use. Must be one of `all`, `geminipr`, `txbolt`.
* Default: `"all"`
+25 -2
View File
@@ -1,8 +1,12 @@
# Tap-Hold Configuration Options
These options let you modify the behavior of the tap-hold keys, applying primarily to Mod-Tap `MT` and Layer-Tap `LT` keys. They also affect layer tap-toggle `TT`, one-shot `OSM`, `OSL`, and Swap Hands `SH_T`, `SH_TT` keys.
While Tap-Hold options are fantastic, they are not without their issues. We have tried to configure them with reasonable defaults, but that may still cause issues for some people.
These options let you modify the behavior of the tap-hold keys.
::: info
Besides the tapping term, tap-hold options do **not** apply to Tap Dance keys. Tap Dance implements a separate, simpler decision logic to track when keys are tapped vs. held, and it does not support advanced tap-hold configurations like Permissive Hold, Chordal Hold, etc.
:::
## Tapping Term
@@ -148,6 +152,25 @@ uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) {
The reason is that `TAPPING_TERM` is a macro that expands to a constant integer and thus cannot be changed at runtime, whereas `g_tapping_term` is a variable whose value can be changed at runtime. If you want, you can temporarily enable `DYNAMIC_TAPPING_TERM_ENABLE` to find a suitable tapping term value and then disable that feature and revert back to using the classic syntax for per-key tapping term settings. In case you need to access the tapping term from elsewhere in your code, you can use the `GET_TAPPING_TERM(keycode, record)` macro. This macro will expand to whatever is the appropriate access pattern given the current configuration.
## Configuring Home Row Mods
"Home row mods" (HRMs) is a popular layout technique where modifiers are placed as Mod-Tap keys on the home row (<kbd>A</kbd>, <kbd>S</kbd>, <kbd>D</kbd>, <kbd>F</kbd> and <kbd>J</kbd>, <kbd>K</kbd>, <kbd>L</kbd>, <kbd>;</kbd>, supposing QWERTY layout). This reduces hand movement and can increase comfort. However, because these keys are also used for fast typing, they are prone to accidental modifier triggers (when rolling keys) or accidental typed letters (when trying to use a modifier).
There is no single perfect configuration for home row mods, as it depends heavily on your typing speed and habits. However, a good starting point in QMK is (added in your `config.h`):
```c
#define TAPPING_TERM 250
#define PERMISSIVE_HOLD // Triggers mod if you tap another key while holding.
#define CHORDAL_HOLD // Constrains holds to opposite-hand combinations.
// Consider also:
// #define FLOW_TAP_TERM 150 // Disables holds when typing quickly.
```
See [Permissive Hold](#permissive-hold), [Chordal Hold](#chordal-hold), and [Flow Tap](#flow-tap) below for details on what they do and how to fine-tune them.
Additionally, [Speculative Hold](#speculative-hold) is useful to eliminate lag when combining a home row mod with mouse clicks (e.g., Shift + Click), as standard mod-tap keys do not send the modifier until the tap-hold decision is finalized.
## Tap-Or-Hold Decision Modes
The code which decides between the tap and hold actions of dual-role keys supports three different modes, in increasing order of preference for the hold action:
@@ -824,7 +847,7 @@ bool get_speculative_hold(uint16_t keycode, keyrecord_t* record) {
}
```
Some operating systems or applications assign actions to tapping a modifier key by itself, e.g., tapping GUI to open a start menu. Because Speculative Hold sometimes sends a lone modifier key press, it can falsely trigger these actions (known as the "flashing mods" problem). How such an input is handled depends on the OS and application, so unfortunately, there is no universal solution.
Some operating systems or applications assign actions to tapping a modifier key by itself, e.g., tapping GUI to open a start menu. Because Speculative Hold sends a lone modifier key press in some cases, it can falsely trigger these actions (known as the "flashing mods" problem). How such an input is handled depends on the OS and application, so unfortunately, there is no universal solution.
To mitigate this issue, you can set `DUMMY_MOD_NEUTRALIZER_KEYCODE` (and optionally `MODS_TO_NEUTRALIZE`) in your `config.h`, as described above for [Retro Tapping](#retro-tapping).
+1 -1
View File
@@ -86,7 +86,7 @@ void solenoid_fire(uint8_t index) {
*
*/
void solenoid_fire_handler(void) {
#ifndef SOLENOID_RANDOM_FIRE
#ifdef SOLENOID_RANDOM_FIRE
if (NUMBER_OF_SOLENOIDS > 1) {
uint8_t i = rand() % NUMBER_OF_SOLENOIDS;
if (!solenoid_on[i]) {
+1 -1
View File
@@ -354,7 +354,7 @@ bool azoteq_iqs5xx_init(void) {
};
report_mouse_t azoteq_iqs5xx_get_report(report_mouse_t mouse_report) {
report_mouse_t temp_report = {0};
report_mouse_t temp_report = {.buttons = mouse_report.buttons};
azoteq_iqs5xx_base_data_t base_data = {0};
i2c_status_t status = azoteq_iqs5xx_get_base_data(&base_data);
+9
View File
@@ -0,0 +1,9 @@
// Copyright 2026 Yiancar
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
/* RGB Light */
#define WS2812_PWM_DRIVER PWMD1
#define WS2812_PWM_DMA_STREAM STM32_DMA1_STREAM5
#define WS2812_PWM_DMA_CHANNEL 5
+8
View File
@@ -0,0 +1,8 @@
// Copyright 2026 Yiancar
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#define HAL_USE_PWM TRUE
#include_next <halconf.h>
+885
View File
@@ -0,0 +1,885 @@
{
"manufacturer": "Yiancar-Designs",
"keyboard_name": "Stratum 80",
"maintainer": "Yiancar-Designs",
"bootloader": "stm32-dfu",
"diode_direction": "COL2ROW",
"features": {
"bootmagic": true,
"extrakey": true,
"mousekey": true,
"nkro": true,
"rgblight": true
},
"indicators": {
"caps_lock": "B6",
"on_state": 0
},
"matrix_pins": {
"cols": ["A1", "B9", "A3", "A4", "A5", "A6", "A7", "B0", "B1", "B2", "B10", "B11", "B12", "B13", "B14", "B15", "A8"],
"rows": ["A2", "A14", "A15", "B3", "B4", "B5"]
},
"processor": "STM32F072",
"rgblight": {
"animations": {
"alternating": true,
"breathing": true,
"christmas": true,
"knight": true,
"rainbow_mood": true,
"rainbow_swirl": true,
"rgb_test": true,
"snake": true,
"static_gradient": true,
"twinkle": true
},
"default": {
"sat": 0
},
"max_brightness": 160,
"led_count": 25
},
"url": "https://yiancar-designs.com",
"usb": {
"device_version": "0.0.1",
"pid": "0x4C57",
"vid": "0x8968"
},
"ws2812": {
"driver": "pwm",
"pin": "A9"
},
"community_layouts": ["tkl_ansi", "tkl_ansi_tsangan", "tkl_ansi_split_bs_rshift", "tkl_ansi_tsangan_split_bs_rshift", "tkl_iso", "tkl_iso_split_bs_rshift", "tkl_iso_tsangan", "tkl_iso_tsangan_split_bs_rshift"],
"layouts": {
"LAYOUT_all": {
"layout": [
{ "matrix": [0, 0], "x": 0, "y": 0 },
{ "matrix": [0, 1], "x": 2, "y": 0 },
{ "matrix": [0, 2], "x": 3, "y": 0 },
{ "matrix": [0, 3], "x": 4, "y": 0 },
{ "matrix": [0, 4], "x": 5, "y": 0 },
{ "matrix": [0, 5], "x": 6.5, "y": 0 },
{ "matrix": [0, 6], "x": 7.5, "y": 0 },
{ "matrix": [0, 7], "x": 8.5, "y": 0 },
{ "matrix": [0, 8], "x": 9.5, "y": 0 },
{ "matrix": [0, 9], "x": 11, "y": 0 },
{ "matrix": [0, 10], "x": 12, "y": 0 },
{ "matrix": [0, 11], "x": 13, "y": 0 },
{ "matrix": [0, 12], "x": 14, "y": 0 },
{ "matrix": [0, 14], "x": 15.25, "y": 0 },
{ "matrix": [0, 15], "x": 16.25, "y": 0 },
{ "matrix": [0, 16], "x": 17.25, "y": 0 },
{ "matrix": [1, 0], "x": 0, "y": 1.25 },
{ "matrix": [1, 1], "x": 1, "y": 1.25 },
{ "matrix": [1, 2], "x": 2, "y": 1.25 },
{ "matrix": [1, 3], "x": 3, "y": 1.25 },
{ "matrix": [1, 4], "x": 4, "y": 1.25 },
{ "matrix": [1, 5], "x": 5, "y": 1.25 },
{ "matrix": [1, 6], "x": 6, "y": 1.25 },
{ "matrix": [1, 7], "x": 7, "y": 1.25 },
{ "matrix": [1, 8], "x": 8, "y": 1.25 },
{ "matrix": [1, 9], "x": 9, "y": 1.25 },
{ "matrix": [1, 10], "x": 10, "y": 1.25 },
{ "matrix": [1, 11], "x": 11, "y": 1.25 },
{ "matrix": [1, 12], "x": 12, "y": 1.25 },
{ "matrix": [1, 13], "x": 13, "y": 1.25 },
{ "matrix": [0, 13], "x": 14, "y": 1.25 },
{ "matrix": [1, 14], "x": 15.25, "y": 1.25 },
{ "matrix": [1, 15], "x": 16.25, "y": 1.25 },
{ "matrix": [1, 16], "x": 17.25, "y": 1.25 },
{ "matrix": [2, 0], "w": 1.5, "x": 0, "y": 2.25 },
{ "matrix": [2, 1], "x": 1.5, "y": 2.25 },
{ "matrix": [2, 2], "x": 2.5, "y": 2.25 },
{ "matrix": [2, 3], "x": 3.5, "y": 2.25 },
{ "matrix": [2, 4], "x": 4.5, "y": 2.25 },
{ "matrix": [2, 5], "x": 5.5, "y": 2.25 },
{ "matrix": [2, 6], "x": 6.5, "y": 2.25 },
{ "matrix": [2, 7], "x": 7.5, "y": 2.25 },
{ "matrix": [2, 8], "x": 8.5, "y": 2.25 },
{ "matrix": [2, 9], "x": 9.5, "y": 2.25 },
{ "matrix": [2, 10], "x": 10.5, "y": 2.25 },
{ "matrix": [2, 11], "x": 11.5, "y": 2.25 },
{ "matrix": [2, 12], "x": 12.5, "y": 2.25 },
{ "matrix": [3, 12], "w": 1.5, "x": 13.5, "y": 2.25 },
{ "matrix": [2, 14], "x": 15.25, "y": 2.25 },
{ "matrix": [2, 15], "x": 16.25, "y": 2.25 },
{ "matrix": [2, 16], "x": 17.25, "y": 2.25 },
{ "matrix": [3, 0], "w": 1.75, "x": 0, "y": 3.25 },
{ "matrix": [3, 1], "x": 1.75, "y": 3.25 },
{ "matrix": [3, 2], "x": 2.75, "y": 3.25 },
{ "matrix": [3, 3], "x": 3.75, "y": 3.25 },
{ "matrix": [3, 4], "x": 4.75, "y": 3.25 },
{ "matrix": [3, 5], "x": 5.75, "y": 3.25 },
{ "matrix": [3, 6], "x": 6.75, "y": 3.25 },
{ "matrix": [3, 7], "x": 7.75, "y": 3.25 },
{ "matrix": [3, 8], "x": 8.75, "y": 3.25 },
{ "matrix": [3, 9], "x": 9.75, "y": 3.25 },
{ "matrix": [3, 10], "x": 10.75, "y": 3.25 },
{ "matrix": [3, 11], "x": 11.75, "y": 3.25 },
{ "matrix": [3, 13], "w": 2.25, "x": 12.75, "y": 3.25 },
{ "matrix": [4, 0], "w": 1.25, "x": 0, "y": 4.25 },
{ "matrix": [4, 1], "x": 1.25, "y": 4.25 },
{ "matrix": [4, 2], "x": 2.25, "y": 4.25 },
{ "matrix": [4, 3], "x": 3.25, "y": 4.25 },
{ "matrix": [4, 4], "x": 4.25, "y": 4.25 },
{ "matrix": [4, 5], "x": 5.25, "y": 4.25 },
{ "matrix": [4, 6], "x": 6.25, "y": 4.25 },
{ "matrix": [4, 7], "x": 7.25, "y": 4.25 },
{ "matrix": [4, 8], "x": 8.25, "y": 4.25 },
{ "matrix": [4, 9], "x": 9.25, "y": 4.25 },
{ "matrix": [4, 10], "x": 10.25, "y": 4.25 },
{ "matrix": [4, 11], "x": 11.25, "y": 4.25 },
{ "matrix": [4, 12], "w": 1.75, "x": 12.25, "y": 4.25 },
{ "matrix": [4, 13], "x": 14, "y": 4.25 },
{ "matrix": [4, 15], "x": 16.25, "y": 4.25 },
{ "matrix": [5, 0], "w": 1.25, "x": 0, "y": 5.25 },
{ "matrix": [5, 1], "w": 1.25, "x": 1.25, "y": 5.25 },
{ "matrix": [5, 2], "w": 1.25, "x": 2.5, "y": 5.25 },
{ "matrix": [5, 6], "w": 6.25, "x": 3.75, "y": 5.25 },
{ "matrix": [5, 10], "w": 1.25, "x": 10, "y": 5.25 },
{ "matrix": [5, 11], "w": 1.25, "x": 11.25, "y": 5.25 },
{ "matrix": [5, 12], "w": 1.25, "x": 12.5, "y": 5.25 },
{ "matrix": [5, 13], "w": 1.25, "x": 13.75, "y": 5.25 },
{ "matrix": [5, 14], "x": 15.25, "y": 5.25 },
{ "matrix": [5, 15], "x": 16.25, "y": 5.25 },
{ "matrix": [5, 16], "x": 17.25, "y": 5.25 }
]
},
"LAYOUT_tkl_ansi": {
"layout": [
{ "matrix": [0, 0], "x": 0, "y": 0 },
{ "matrix": [0, 1], "x": 2, "y": 0 },
{ "matrix": [0, 2], "x": 3, "y": 0 },
{ "matrix": [0, 3], "x": 4, "y": 0 },
{ "matrix": [0, 4], "x": 5, "y": 0 },
{ "matrix": [0, 5], "x": 6.5, "y": 0 },
{ "matrix": [0, 6], "x": 7.5, "y": 0 },
{ "matrix": [0, 7], "x": 8.5, "y": 0 },
{ "matrix": [0, 8], "x": 9.5, "y": 0 },
{ "matrix": [0, 9], "x": 11, "y": 0 },
{ "matrix": [0, 10], "x": 12, "y": 0 },
{ "matrix": [0, 11], "x": 13, "y": 0 },
{ "matrix": [0, 12], "x": 14, "y": 0 },
{ "matrix": [0, 14], "x": 15.25, "y": 0 },
{ "matrix": [0, 15], "x": 16.25, "y": 0 },
{ "matrix": [0, 16], "x": 17.25, "y": 0 },
{ "matrix": [1, 0], "x": 0, "y": 1.25 },
{ "matrix": [1, 1], "x": 1, "y": 1.25 },
{ "matrix": [1, 2], "x": 2, "y": 1.25 },
{ "matrix": [1, 3], "x": 3, "y": 1.25 },
{ "matrix": [1, 4], "x": 4, "y": 1.25 },
{ "matrix": [1, 5], "x": 5, "y": 1.25 },
{ "matrix": [1, 6], "x": 6, "y": 1.25 },
{ "matrix": [1, 7], "x": 7, "y": 1.25 },
{ "matrix": [1, 8], "x": 8, "y": 1.25 },
{ "matrix": [1, 9], "x": 9, "y": 1.25 },
{ "matrix": [1, 10], "x": 10, "y": 1.25 },
{ "matrix": [1, 11], "x": 11, "y": 1.25 },
{ "matrix": [1, 12], "x": 12, "y": 1.25 },
{ "matrix": [1, 13], "w": 2, "x": 13, "y": 1.25 },
{ "matrix": [1, 14], "x": 15.25, "y": 1.25 },
{ "matrix": [1, 15], "x": 16.25, "y": 1.25 },
{ "matrix": [1, 16], "x": 17.25, "y": 1.25 },
{ "matrix": [2, 0], "w": 1.5, "x": 0, "y": 2.25 },
{ "matrix": [2, 1], "x": 1.5, "y": 2.25 },
{ "matrix": [2, 2], "x": 2.5, "y": 2.25 },
{ "matrix": [2, 3], "x": 3.5, "y": 2.25 },
{ "matrix": [2, 4], "x": 4.5, "y": 2.25 },
{ "matrix": [2, 5], "x": 5.5, "y": 2.25 },
{ "matrix": [2, 6], "x": 6.5, "y": 2.25 },
{ "matrix": [2, 7], "x": 7.5, "y": 2.25 },
{ "matrix": [2, 8], "x": 8.5, "y": 2.25 },
{ "matrix": [2, 9], "x": 9.5, "y": 2.25 },
{ "matrix": [2, 10], "x": 10.5, "y": 2.25 },
{ "matrix": [2, 11], "x": 11.5, "y": 2.25 },
{ "matrix": [2, 12], "x": 12.5, "y": 2.25 },
{ "matrix": [3, 12], "w": 1.5, "x": 13.5, "y": 2.25 },
{ "matrix": [2, 14], "x": 15.25, "y": 2.25 },
{ "matrix": [2, 15], "x": 16.25, "y": 2.25 },
{ "matrix": [2, 16], "x": 17.25, "y": 2.25 },
{ "matrix": [3, 0], "w": 1.75, "x": 0, "y": 3.25 },
{ "matrix": [3, 1], "x": 1.75, "y": 3.25 },
{ "matrix": [3, 2], "x": 2.75, "y": 3.25 },
{ "matrix": [3, 3], "x": 3.75, "y": 3.25 },
{ "matrix": [3, 4], "x": 4.75, "y": 3.25 },
{ "matrix": [3, 5], "x": 5.75, "y": 3.25 },
{ "matrix": [3, 6], "x": 6.75, "y": 3.25 },
{ "matrix": [3, 7], "x": 7.75, "y": 3.25 },
{ "matrix": [3, 8], "x": 8.75, "y": 3.25 },
{ "matrix": [3, 9], "x": 9.75, "y": 3.25 },
{ "matrix": [3, 10], "x": 10.75, "y": 3.25 },
{ "matrix": [3, 11], "x": 11.75, "y": 3.25 },
{ "matrix": [3, 13], "w": 2.25, "x": 12.75, "y": 3.25 },
{ "matrix": [4, 0], "w": 2.25, "x": 0, "y": 4.25 },
{ "matrix": [4, 2], "x": 2.25, "y": 4.25 },
{ "matrix": [4, 3], "x": 3.25, "y": 4.25 },
{ "matrix": [4, 4], "x": 4.25, "y": 4.25 },
{ "matrix": [4, 5], "x": 5.25, "y": 4.25 },
{ "matrix": [4, 6], "x": 6.25, "y": 4.25 },
{ "matrix": [4, 7], "x": 7.25, "y": 4.25 },
{ "matrix": [4, 8], "x": 8.25, "y": 4.25 },
{ "matrix": [4, 9], "x": 9.25, "y": 4.25 },
{ "matrix": [4, 10], "x": 10.25, "y": 4.25 },
{ "matrix": [4, 11], "x": 11.25, "y": 4.25 },
{ "matrix": [4, 12], "w": 2.75, "x": 12.25, "y": 4.25 },
{ "matrix": [4, 15], "x": 16.25, "y": 4.25 },
{ "matrix": [5, 0], "w": 1.25, "x": 0, "y": 5.25 },
{ "matrix": [5, 1], "w": 1.25, "x": 1.25, "y": 5.25 },
{ "matrix": [5, 2], "w": 1.25, "x": 2.5, "y": 5.25 },
{ "matrix": [5, 6], "w": 6.25, "x": 3.75, "y": 5.25 },
{ "matrix": [5, 10], "w": 1.25, "x": 10, "y": 5.25 },
{ "matrix": [5, 11], "w": 1.25, "x": 11.25, "y": 5.25 },
{ "matrix": [5, 12], "w": 1.25, "x": 12.5, "y": 5.25 },
{ "matrix": [5, 13], "w": 1.25, "x": 13.75, "y": 5.25 },
{ "matrix": [5, 14], "x": 15.25, "y": 5.25 },
{ "matrix": [5, 15], "x": 16.25, "y": 5.25 },
{ "matrix": [5, 16], "x": 17.25, "y": 5.25 }
]
},
"LAYOUT_tkl_ansi_split_bs_rshift": {
"layout": [
{ "matrix": [0, 0], "x": 0, "y": 0 },
{ "matrix": [0, 1], "x": 2, "y": 0 },
{ "matrix": [0, 2], "x": 3, "y": 0 },
{ "matrix": [0, 3], "x": 4, "y": 0 },
{ "matrix": [0, 4], "x": 5, "y": 0 },
{ "matrix": [0, 5], "x": 6.5, "y": 0 },
{ "matrix": [0, 6], "x": 7.5, "y": 0 },
{ "matrix": [0, 7], "x": 8.5, "y": 0 },
{ "matrix": [0, 8], "x": 9.5, "y": 0 },
{ "matrix": [0, 9], "x": 11, "y": 0 },
{ "matrix": [0, 10], "x": 12, "y": 0 },
{ "matrix": [0, 11], "x": 13, "y": 0 },
{ "matrix": [0, 12], "x": 14, "y": 0 },
{ "matrix": [0, 14], "x": 15.25, "y": 0 },
{ "matrix": [0, 15], "x": 16.25, "y": 0 },
{ "matrix": [0, 16], "x": 17.25, "y": 0 },
{ "matrix": [1, 0], "x": 0, "y": 1.25 },
{ "matrix": [1, 1], "x": 1, "y": 1.25 },
{ "matrix": [1, 2], "x": 2, "y": 1.25 },
{ "matrix": [1, 3], "x": 3, "y": 1.25 },
{ "matrix": [1, 4], "x": 4, "y": 1.25 },
{ "matrix": [1, 5], "x": 5, "y": 1.25 },
{ "matrix": [1, 6], "x": 6, "y": 1.25 },
{ "matrix": [1, 7], "x": 7, "y": 1.25 },
{ "matrix": [1, 8], "x": 8, "y": 1.25 },
{ "matrix": [1, 9], "x": 9, "y": 1.25 },
{ "matrix": [1, 10], "x": 10, "y": 1.25 },
{ "matrix": [1, 11], "x": 11, "y": 1.25 },
{ "matrix": [1, 12], "x": 12, "y": 1.25 },
{ "matrix": [1, 13], "x": 13, "y": 1.25 },
{ "matrix": [0, 13], "x": 14, "y": 1.25 },
{ "matrix": [1, 14], "x": 15.25, "y": 1.25 },
{ "matrix": [1, 15], "x": 16.25, "y": 1.25 },
{ "matrix": [1, 16], "x": 17.25, "y": 1.25 },
{ "matrix": [2, 0], "w": 1.5, "x": 0, "y": 2.25 },
{ "matrix": [2, 1], "x": 1.5, "y": 2.25 },
{ "matrix": [2, 2], "x": 2.5, "y": 2.25 },
{ "matrix": [2, 3], "x": 3.5, "y": 2.25 },
{ "matrix": [2, 4], "x": 4.5, "y": 2.25 },
{ "matrix": [2, 5], "x": 5.5, "y": 2.25 },
{ "matrix": [2, 6], "x": 6.5, "y": 2.25 },
{ "matrix": [2, 7], "x": 7.5, "y": 2.25 },
{ "matrix": [2, 8], "x": 8.5, "y": 2.25 },
{ "matrix": [2, 9], "x": 9.5, "y": 2.25 },
{ "matrix": [2, 10], "x": 10.5, "y": 2.25 },
{ "matrix": [2, 11], "x": 11.5, "y": 2.25 },
{ "matrix": [2, 12], "x": 12.5, "y": 2.25 },
{ "matrix": [3, 12], "w": 1.5, "x": 13.5, "y": 2.25 },
{ "matrix": [2, 14], "x": 15.25, "y": 2.25 },
{ "matrix": [2, 15], "x": 16.25, "y": 2.25 },
{ "matrix": [2, 16], "x": 17.25, "y": 2.25 },
{ "matrix": [3, 0], "w": 1.75, "x": 0, "y": 3.25 },
{ "matrix": [3, 1], "x": 1.75, "y": 3.25 },
{ "matrix": [3, 2], "x": 2.75, "y": 3.25 },
{ "matrix": [3, 3], "x": 3.75, "y": 3.25 },
{ "matrix": [3, 4], "x": 4.75, "y": 3.25 },
{ "matrix": [3, 5], "x": 5.75, "y": 3.25 },
{ "matrix": [3, 6], "x": 6.75, "y": 3.25 },
{ "matrix": [3, 7], "x": 7.75, "y": 3.25 },
{ "matrix": [3, 8], "x": 8.75, "y": 3.25 },
{ "matrix": [3, 9], "x": 9.75, "y": 3.25 },
{ "matrix": [3, 10], "x": 10.75, "y": 3.25 },
{ "matrix": [3, 11], "x": 11.75, "y": 3.25 },
{ "matrix": [3, 13], "w": 2.25, "x": 12.75, "y": 3.25 },
{ "matrix": [4, 0], "w": 2.25, "x": 0, "y": 4.25 },
{ "matrix": [4, 2], "x": 2.25, "y": 4.25 },
{ "matrix": [4, 3], "x": 3.25, "y": 4.25 },
{ "matrix": [4, 4], "x": 4.25, "y": 4.25 },
{ "matrix": [4, 5], "x": 5.25, "y": 4.25 },
{ "matrix": [4, 6], "x": 6.25, "y": 4.25 },
{ "matrix": [4, 7], "x": 7.25, "y": 4.25 },
{ "matrix": [4, 8], "x": 8.25, "y": 4.25 },
{ "matrix": [4, 9], "x": 9.25, "y": 4.25 },
{ "matrix": [4, 10], "x": 10.25, "y": 4.25 },
{ "matrix": [4, 11], "x": 11.25, "y": 4.25 },
{ "matrix": [4, 12], "w": 1.75, "x": 12.25, "y": 4.25 },
{ "matrix": [4, 13], "x": 14, "y": 4.25 },
{ "matrix": [4, 15], "x": 16.25, "y": 4.25 },
{ "matrix": [5, 0], "w": 1.25, "x": 0, "y": 5.25 },
{ "matrix": [5, 1], "w": 1.25, "x": 1.25, "y": 5.25 },
{ "matrix": [5, 2], "w": 1.25, "x": 2.5, "y": 5.25 },
{ "matrix": [5, 6], "w": 6.25, "x": 3.75, "y": 5.25 },
{ "matrix": [5, 10], "w": 1.25, "x": 10, "y": 5.25 },
{ "matrix": [5, 11], "w": 1.25, "x": 11.25, "y": 5.25 },
{ "matrix": [5, 12], "w": 1.25, "x": 12.5, "y": 5.25 },
{ "matrix": [5, 13], "w": 1.25, "x": 13.75, "y": 5.25 },
{ "matrix": [5, 14], "x": 15.25, "y": 5.25 },
{ "matrix": [5, 15], "x": 16.25, "y": 5.25 },
{ "matrix": [5, 16], "x": 17.25, "y": 5.25 }
]
},
"LAYOUT_tkl_ansi_tsangan": {
"layout": [
{ "matrix": [0, 0], "x": 0, "y": 0 },
{ "matrix": [0, 1], "x": 2, "y": 0 },
{ "matrix": [0, 2], "x": 3, "y": 0 },
{ "matrix": [0, 3], "x": 4, "y": 0 },
{ "matrix": [0, 4], "x": 5, "y": 0 },
{ "matrix": [0, 5], "x": 6.5, "y": 0 },
{ "matrix": [0, 6], "x": 7.5, "y": 0 },
{ "matrix": [0, 7], "x": 8.5, "y": 0 },
{ "matrix": [0, 8], "x": 9.5, "y": 0 },
{ "matrix": [0, 9], "x": 11, "y": 0 },
{ "matrix": [0, 10], "x": 12, "y": 0 },
{ "matrix": [0, 11], "x": 13, "y": 0 },
{ "matrix": [0, 12], "x": 14, "y": 0 },
{ "matrix": [0, 14], "x": 15.25, "y": 0 },
{ "matrix": [0, 15], "x": 16.25, "y": 0 },
{ "matrix": [0, 16], "x": 17.25, "y": 0 },
{ "matrix": [1, 0], "x": 0, "y": 1.25 },
{ "matrix": [1, 1], "x": 1, "y": 1.25 },
{ "matrix": [1, 2], "x": 2, "y": 1.25 },
{ "matrix": [1, 3], "x": 3, "y": 1.25 },
{ "matrix": [1, 4], "x": 4, "y": 1.25 },
{ "matrix": [1, 5], "x": 5, "y": 1.25 },
{ "matrix": [1, 6], "x": 6, "y": 1.25 },
{ "matrix": [1, 7], "x": 7, "y": 1.25 },
{ "matrix": [1, 8], "x": 8, "y": 1.25 },
{ "matrix": [1, 9], "x": 9, "y": 1.25 },
{ "matrix": [1, 10], "x": 10, "y": 1.25 },
{ "matrix": [1, 11], "x": 11, "y": 1.25 },
{ "matrix": [1, 12], "x": 12, "y": 1.25 },
{ "matrix": [1, 13], "w": 2, "x": 13, "y": 1.25 },
{ "matrix": [1, 14], "x": 15.25, "y": 1.25 },
{ "matrix": [1, 15], "x": 16.25, "y": 1.25 },
{ "matrix": [1, 16], "x": 17.25, "y": 1.25 },
{ "matrix": [2, 0], "w": 1.5, "x": 0, "y": 2.25 },
{ "matrix": [2, 1], "x": 1.5, "y": 2.25 },
{ "matrix": [2, 2], "x": 2.5, "y": 2.25 },
{ "matrix": [2, 3], "x": 3.5, "y": 2.25 },
{ "matrix": [2, 4], "x": 4.5, "y": 2.25 },
{ "matrix": [2, 5], "x": 5.5, "y": 2.25 },
{ "matrix": [2, 6], "x": 6.5, "y": 2.25 },
{ "matrix": [2, 7], "x": 7.5, "y": 2.25 },
{ "matrix": [2, 8], "x": 8.5, "y": 2.25 },
{ "matrix": [2, 9], "x": 9.5, "y": 2.25 },
{ "matrix": [2, 10], "x": 10.5, "y": 2.25 },
{ "matrix": [2, 11], "x": 11.5, "y": 2.25 },
{ "matrix": [2, 12], "x": 12.5, "y": 2.25 },
{ "matrix": [3, 12], "w": 1.5, "x": 13.5, "y": 2.25 },
{ "matrix": [2, 14], "x": 15.25, "y": 2.25 },
{ "matrix": [2, 15], "x": 16.25, "y": 2.25 },
{ "matrix": [2, 16], "x": 17.25, "y": 2.25 },
{ "matrix": [3, 0], "w": 1.75, "x": 0, "y": 3.25 },
{ "matrix": [3, 1], "x": 1.75, "y": 3.25 },
{ "matrix": [3, 2], "x": 2.75, "y": 3.25 },
{ "matrix": [3, 3], "x": 3.75, "y": 3.25 },
{ "matrix": [3, 4], "x": 4.75, "y": 3.25 },
{ "matrix": [3, 5], "x": 5.75, "y": 3.25 },
{ "matrix": [3, 6], "x": 6.75, "y": 3.25 },
{ "matrix": [3, 7], "x": 7.75, "y": 3.25 },
{ "matrix": [3, 8], "x": 8.75, "y": 3.25 },
{ "matrix": [3, 9], "x": 9.75, "y": 3.25 },
{ "matrix": [3, 10], "x": 10.75, "y": 3.25 },
{ "matrix": [3, 11], "x": 11.75, "y": 3.25 },
{ "matrix": [3, 13], "w": 2.25, "x": 12.75, "y": 3.25 },
{ "matrix": [4, 0], "w": 2.25, "x": 0, "y": 4.25 },
{ "matrix": [4, 2], "x": 2.25, "y": 4.25 },
{ "matrix": [4, 3], "x": 3.25, "y": 4.25 },
{ "matrix": [4, 4], "x": 4.25, "y": 4.25 },
{ "matrix": [4, 5], "x": 5.25, "y": 4.25 },
{ "matrix": [4, 6], "x": 6.25, "y": 4.25 },
{ "matrix": [4, 7], "x": 7.25, "y": 4.25 },
{ "matrix": [4, 8], "x": 8.25, "y": 4.25 },
{ "matrix": [4, 9], "x": 9.25, "y": 4.25 },
{ "matrix": [4, 10], "x": 10.25, "y": 4.25 },
{ "matrix": [4, 11], "x": 11.25, "y": 4.25 },
{ "matrix": [4, 12], "w": 2.75, "x": 12.25, "y": 4.25 },
{ "matrix": [4, 15], "x": 16.25, "y": 4.25 },
{ "matrix": [5, 0], "w": 1.5, "x": 0, "y": 5.25 },
{ "matrix": [5, 1], "x": 1.5, "y": 5.25 },
{ "matrix": [5, 2], "w": 1.5, "x": 2.5, "y": 5.25 },
{ "matrix": [5, 6], "w": 7, "x": 4, "y": 5.25 },
{ "matrix": [5, 11], "w": 1.5, "x": 11, "y": 5.25 },
{ "matrix": [5, 12], "x": 12.5, "y": 5.25 },
{ "matrix": [5, 13], "w": 1.5, "x": 13.5, "y": 5.25 },
{ "matrix": [5, 14], "x": 15.25, "y": 5.25 },
{ "matrix": [5, 15], "x": 16.25, "y": 5.25 },
{ "matrix": [5, 16], "x": 17.25, "y": 5.25 }
]
},
"LAYOUT_tkl_ansi_tsangan_split_bs_rshift": {
"layout": [
{ "matrix": [0, 0], "x": 0, "y": 0 },
{ "matrix": [0, 1], "x": 2, "y": 0 },
{ "matrix": [0, 2], "x": 3, "y": 0 },
{ "matrix": [0, 3], "x": 4, "y": 0 },
{ "matrix": [0, 4], "x": 5, "y": 0 },
{ "matrix": [0, 5], "x": 6.5, "y": 0 },
{ "matrix": [0, 6], "x": 7.5, "y": 0 },
{ "matrix": [0, 7], "x": 8.5, "y": 0 },
{ "matrix": [0, 8], "x": 9.5, "y": 0 },
{ "matrix": [0, 9], "x": 11, "y": 0 },
{ "matrix": [0, 10], "x": 12, "y": 0 },
{ "matrix": [0, 11], "x": 13, "y": 0 },
{ "matrix": [0, 12], "x": 14, "y": 0 },
{ "matrix": [0, 14], "x": 15.25, "y": 0 },
{ "matrix": [0, 15], "x": 16.25, "y": 0 },
{ "matrix": [0, 16], "x": 17.25, "y": 0 },
{ "matrix": [1, 0], "x": 0, "y": 1.25 },
{ "matrix": [1, 1], "x": 1, "y": 1.25 },
{ "matrix": [1, 2], "x": 2, "y": 1.25 },
{ "matrix": [1, 3], "x": 3, "y": 1.25 },
{ "matrix": [1, 4], "x": 4, "y": 1.25 },
{ "matrix": [1, 5], "x": 5, "y": 1.25 },
{ "matrix": [1, 6], "x": 6, "y": 1.25 },
{ "matrix": [1, 7], "x": 7, "y": 1.25 },
{ "matrix": [1, 8], "x": 8, "y": 1.25 },
{ "matrix": [1, 9], "x": 9, "y": 1.25 },
{ "matrix": [1, 10], "x": 10, "y": 1.25 },
{ "matrix": [1, 11], "x": 11, "y": 1.25 },
{ "matrix": [1, 12], "x": 12, "y": 1.25 },
{ "matrix": [1, 13], "x": 13, "y": 1.25 },
{ "matrix": [0, 13], "x": 14, "y": 1.25 },
{ "matrix": [1, 14], "x": 15.25, "y": 1.25 },
{ "matrix": [1, 15], "x": 16.25, "y": 1.25 },
{ "matrix": [1, 16], "x": 17.25, "y": 1.25 },
{ "matrix": [2, 0], "w": 1.5, "x": 0, "y": 2.25 },
{ "matrix": [2, 1], "x": 1.5, "y": 2.25 },
{ "matrix": [2, 2], "x": 2.5, "y": 2.25 },
{ "matrix": [2, 3], "x": 3.5, "y": 2.25 },
{ "matrix": [2, 4], "x": 4.5, "y": 2.25 },
{ "matrix": [2, 5], "x": 5.5, "y": 2.25 },
{ "matrix": [2, 6], "x": 6.5, "y": 2.25 },
{ "matrix": [2, 7], "x": 7.5, "y": 2.25 },
{ "matrix": [2, 8], "x": 8.5, "y": 2.25 },
{ "matrix": [2, 9], "x": 9.5, "y": 2.25 },
{ "matrix": [2, 10], "x": 10.5, "y": 2.25 },
{ "matrix": [2, 11], "x": 11.5, "y": 2.25 },
{ "matrix": [2, 12], "x": 12.5, "y": 2.25 },
{ "matrix": [3, 12], "w": 1.5, "x": 13.5, "y": 2.25 },
{ "matrix": [2, 14], "x": 15.25, "y": 2.25 },
{ "matrix": [2, 15], "x": 16.25, "y": 2.25 },
{ "matrix": [2, 16], "x": 17.25, "y": 2.25 },
{ "matrix": [3, 0], "w": 1.75, "x": 0, "y": 3.25 },
{ "matrix": [3, 1], "x": 1.75, "y": 3.25 },
{ "matrix": [3, 2], "x": 2.75, "y": 3.25 },
{ "matrix": [3, 3], "x": 3.75, "y": 3.25 },
{ "matrix": [3, 4], "x": 4.75, "y": 3.25 },
{ "matrix": [3, 5], "x": 5.75, "y": 3.25 },
{ "matrix": [3, 6], "x": 6.75, "y": 3.25 },
{ "matrix": [3, 7], "x": 7.75, "y": 3.25 },
{ "matrix": [3, 8], "x": 8.75, "y": 3.25 },
{ "matrix": [3, 9], "x": 9.75, "y": 3.25 },
{ "matrix": [3, 10], "x": 10.75, "y": 3.25 },
{ "matrix": [3, 11], "x": 11.75, "y": 3.25 },
{ "matrix": [3, 13], "w": 2.25, "x": 12.75, "y": 3.25 },
{ "matrix": [4, 0], "w": 2.25, "x": 0, "y": 4.25 },
{ "matrix": [4, 2], "x": 2.25, "y": 4.25 },
{ "matrix": [4, 3], "x": 3.25, "y": 4.25 },
{ "matrix": [4, 4], "x": 4.25, "y": 4.25 },
{ "matrix": [4, 5], "x": 5.25, "y": 4.25 },
{ "matrix": [4, 6], "x": 6.25, "y": 4.25 },
{ "matrix": [4, 7], "x": 7.25, "y": 4.25 },
{ "matrix": [4, 8], "x": 8.25, "y": 4.25 },
{ "matrix": [4, 9], "x": 9.25, "y": 4.25 },
{ "matrix": [4, 10], "x": 10.25, "y": 4.25 },
{ "matrix": [4, 11], "x": 11.25, "y": 4.25 },
{ "matrix": [4, 12], "w": 1.75, "x": 12.25, "y": 4.25 },
{ "matrix": [4, 13], "x": 14, "y": 4.25 },
{ "matrix": [4, 15], "x": 16.25, "y": 4.25 },
{ "matrix": [5, 0], "w": 1.5, "x": 0, "y": 5.25 },
{ "matrix": [5, 1], "x": 1.5, "y": 5.25 },
{ "matrix": [5, 2], "w": 1.5, "x": 2.5, "y": 5.25 },
{ "matrix": [5, 6], "w": 7, "x": 4, "y": 5.25 },
{ "matrix": [5, 11], "w": 1.5, "x": 11, "y": 5.25 },
{ "matrix": [5, 12], "x": 12.5, "y": 5.25 },
{ "matrix": [5, 13], "w": 1.5, "x": 13.5, "y": 5.25 },
{ "matrix": [5, 14], "x": 15.25, "y": 5.25 },
{ "matrix": [5, 15], "x": 16.25, "y": 5.25 },
{ "matrix": [5, 16], "x": 17.25, "y": 5.25 }
]
},
"LAYOUT_tkl_iso": {
"layout": [
{ "matrix": [0, 0], "x": 0, "y": 0 },
{ "matrix": [0, 1], "x": 2, "y": 0 },
{ "matrix": [0, 2], "x": 3, "y": 0 },
{ "matrix": [0, 3], "x": 4, "y": 0 },
{ "matrix": [0, 4], "x": 5, "y": 0 },
{ "matrix": [0, 5], "x": 6.5, "y": 0 },
{ "matrix": [0, 6], "x": 7.5, "y": 0 },
{ "matrix": [0, 7], "x": 8.5, "y": 0 },
{ "matrix": [0, 8], "x": 9.5, "y": 0 },
{ "matrix": [0, 9], "x": 11, "y": 0 },
{ "matrix": [0, 10], "x": 12, "y": 0 },
{ "matrix": [0, 11], "x": 13, "y": 0 },
{ "matrix": [0, 12], "x": 14, "y": 0 },
{ "matrix": [0, 14], "x": 15.25, "y": 0 },
{ "matrix": [0, 15], "x": 16.25, "y": 0 },
{ "matrix": [0, 16], "x": 17.25, "y": 0 },
{ "matrix": [1, 0], "x": 0, "y": 1.25 },
{ "matrix": [1, 1], "x": 1, "y": 1.25 },
{ "matrix": [1, 2], "x": 2, "y": 1.25 },
{ "matrix": [1, 3], "x": 3, "y": 1.25 },
{ "matrix": [1, 4], "x": 4, "y": 1.25 },
{ "matrix": [1, 5], "x": 5, "y": 1.25 },
{ "matrix": [1, 6], "x": 6, "y": 1.25 },
{ "matrix": [1, 7], "x": 7, "y": 1.25 },
{ "matrix": [1, 8], "x": 8, "y": 1.25 },
{ "matrix": [1, 9], "x": 9, "y": 1.25 },
{ "matrix": [1, 10], "x": 10, "y": 1.25 },
{ "matrix": [1, 11], "x": 11, "y": 1.25 },
{ "matrix": [1, 12], "x": 12, "y": 1.25 },
{ "matrix": [1, 13], "w": 2, "x": 13, "y": 1.25 },
{ "matrix": [1, 14], "x": 15.25, "y": 1.25 },
{ "matrix": [1, 15], "x": 16.25, "y": 1.25 },
{ "matrix": [1, 16], "x": 17.25, "y": 1.25 },
{ "matrix": [2, 0], "w": 1.5, "x": 0, "y": 2.25 },
{ "matrix": [2, 1], "x": 1.5, "y": 2.25 },
{ "matrix": [2, 2], "x": 2.5, "y": 2.25 },
{ "matrix": [2, 3], "x": 3.5, "y": 2.25 },
{ "matrix": [2, 4], "x": 4.5, "y": 2.25 },
{ "matrix": [2, 5], "x": 5.5, "y": 2.25 },
{ "matrix": [2, 6], "x": 6.5, "y": 2.25 },
{ "matrix": [2, 7], "x": 7.5, "y": 2.25 },
{ "matrix": [2, 8], "x": 8.5, "y": 2.25 },
{ "matrix": [2, 9], "x": 9.5, "y": 2.25 },
{ "matrix": [2, 10], "x": 10.5, "y": 2.25 },
{ "matrix": [2, 11], "x": 11.5, "y": 2.25 },
{ "matrix": [2, 12], "x": 12.5, "y": 2.25 },
{ "matrix": [2, 14], "x": 15.25, "y": 2.25 },
{ "matrix": [2, 15], "x": 16.25, "y": 2.25 },
{ "matrix": [2, 16], "x": 17.25, "y": 2.25 },
{ "matrix": [3, 0], "w": 1.75, "x": 0, "y": 3.25 },
{ "matrix": [3, 1], "x": 1.75, "y": 3.25 },
{ "matrix": [3, 2], "x": 2.75, "y": 3.25 },
{ "matrix": [3, 3], "x": 3.75, "y": 3.25 },
{ "matrix": [3, 4], "x": 4.75, "y": 3.25 },
{ "matrix": [3, 5], "x": 5.75, "y": 3.25 },
{ "matrix": [3, 6], "x": 6.75, "y": 3.25 },
{ "matrix": [3, 7], "x": 7.75, "y": 3.25 },
{ "matrix": [3, 8], "x": 8.75, "y": 3.25 },
{ "matrix": [3, 9], "x": 9.75, "y": 3.25 },
{ "matrix": [3, 10], "x": 10.75, "y": 3.25 },
{ "matrix": [3, 11], "x": 11.75, "y": 3.25 },
{ "matrix": [3, 12], "x": 12.75, "y": 3.25 },
{ "h": 2, "matrix": [3, 13], "w": 1.25, "x": 13.75, "y": 2.25 },
{ "matrix": [4, 0], "w": 1.25, "x": 0, "y": 4.25 },
{ "matrix": [4, 1], "x": 1.25, "y": 4.25 },
{ "matrix": [4, 2], "x": 2.25, "y": 4.25 },
{ "matrix": [4, 3], "x": 3.25, "y": 4.25 },
{ "matrix": [4, 4], "x": 4.25, "y": 4.25 },
{ "matrix": [4, 5], "x": 5.25, "y": 4.25 },
{ "matrix": [4, 6], "x": 6.25, "y": 4.25 },
{ "matrix": [4, 7], "x": 7.25, "y": 4.25 },
{ "matrix": [4, 8], "x": 8.25, "y": 4.25 },
{ "matrix": [4, 9], "x": 9.25, "y": 4.25 },
{ "matrix": [4, 10], "x": 10.25, "y": 4.25 },
{ "matrix": [4, 11], "x": 11.25, "y": 4.25 },
{ "matrix": [4, 12], "w": 2.75, "x": 12.25, "y": 4.25 },
{ "matrix": [4, 15], "x": 16.25, "y": 4.25 },
{ "matrix": [5, 0], "w": 1.25, "x": 0, "y": 5.25 },
{ "matrix": [5, 1], "w": 1.25, "x": 1.25, "y": 5.25 },
{ "matrix": [5, 2], "w": 1.25, "x": 2.5, "y": 5.25 },
{ "matrix": [5, 6], "w": 6.25, "x": 3.75, "y": 5.25 },
{ "matrix": [5, 10], "w": 1.25, "x": 10, "y": 5.25 },
{ "matrix": [5, 11], "w": 1.25, "x": 11.25, "y": 5.25 },
{ "matrix": [5, 12], "w": 1.25, "x": 12.5, "y": 5.25 },
{ "matrix": [5, 13], "w": 1.25, "x": 13.75, "y": 5.25 },
{ "matrix": [5, 14], "x": 15.25, "y": 5.25 },
{ "matrix": [5, 15], "x": 16.25, "y": 5.25 },
{ "matrix": [5, 16], "x": 17.25, "y": 5.25 }
]
},
"LAYOUT_tkl_iso_split_bs_rshift": {
"layout": [
{ "matrix": [0, 0], "x": 0, "y": 0 },
{ "matrix": [0, 1], "x": 2, "y": 0 },
{ "matrix": [0, 2], "x": 3, "y": 0 },
{ "matrix": [0, 3], "x": 4, "y": 0 },
{ "matrix": [0, 4], "x": 5, "y": 0 },
{ "matrix": [0, 5], "x": 6.5, "y": 0 },
{ "matrix": [0, 6], "x": 7.5, "y": 0 },
{ "matrix": [0, 7], "x": 8.5, "y": 0 },
{ "matrix": [0, 8], "x": 9.5, "y": 0 },
{ "matrix": [0, 9], "x": 11, "y": 0 },
{ "matrix": [0, 10], "x": 12, "y": 0 },
{ "matrix": [0, 11], "x": 13, "y": 0 },
{ "matrix": [0, 12], "x": 14, "y": 0 },
{ "matrix": [0, 14], "x": 15.25, "y": 0 },
{ "matrix": [0, 15], "x": 16.25, "y": 0 },
{ "matrix": [0, 16], "x": 17.25, "y": 0 },
{ "matrix": [1, 0], "x": 0, "y": 1.25 },
{ "matrix": [1, 1], "x": 1, "y": 1.25 },
{ "matrix": [1, 2], "x": 2, "y": 1.25 },
{ "matrix": [1, 3], "x": 3, "y": 1.25 },
{ "matrix": [1, 4], "x": 4, "y": 1.25 },
{ "matrix": [1, 5], "x": 5, "y": 1.25 },
{ "matrix": [1, 6], "x": 6, "y": 1.25 },
{ "matrix": [1, 7], "x": 7, "y": 1.25 },
{ "matrix": [1, 8], "x": 8, "y": 1.25 },
{ "matrix": [1, 9], "x": 9, "y": 1.25 },
{ "matrix": [1, 10], "x": 10, "y": 1.25 },
{ "matrix": [1, 11], "x": 11, "y": 1.25 },
{ "matrix": [1, 12], "x": 12, "y": 1.25 },
{ "matrix": [1, 13], "x": 13, "y": 1.25 },
{ "matrix": [0, 13], "x": 14, "y": 1.25 },
{ "matrix": [1, 14], "x": 15.25, "y": 1.25 },
{ "matrix": [1, 15], "x": 16.25, "y": 1.25 },
{ "matrix": [1, 16], "x": 17.25, "y": 1.25 },
{ "matrix": [2, 0], "w": 1.5, "x": 0, "y": 2.25 },
{ "matrix": [2, 1], "x": 1.5, "y": 2.25 },
{ "matrix": [2, 2], "x": 2.5, "y": 2.25 },
{ "matrix": [2, 3], "x": 3.5, "y": 2.25 },
{ "matrix": [2, 4], "x": 4.5, "y": 2.25 },
{ "matrix": [2, 5], "x": 5.5, "y": 2.25 },
{ "matrix": [2, 6], "x": 6.5, "y": 2.25 },
{ "matrix": [2, 7], "x": 7.5, "y": 2.25 },
{ "matrix": [2, 8], "x": 8.5, "y": 2.25 },
{ "matrix": [2, 9], "x": 9.5, "y": 2.25 },
{ "matrix": [2, 10], "x": 10.5, "y": 2.25 },
{ "matrix": [2, 11], "x": 11.5, "y": 2.25 },
{ "matrix": [2, 12], "x": 12.5, "y": 2.25 },
{ "matrix": [2, 14], "x": 15.25, "y": 2.25 },
{ "matrix": [2, 15], "x": 16.25, "y": 2.25 },
{ "matrix": [2, 16], "x": 17.25, "y": 2.25 },
{ "matrix": [3, 0], "w": 1.75, "x": 0, "y": 3.25 },
{ "matrix": [3, 1], "x": 1.75, "y": 3.25 },
{ "matrix": [3, 2], "x": 2.75, "y": 3.25 },
{ "matrix": [3, 3], "x": 3.75, "y": 3.25 },
{ "matrix": [3, 4], "x": 4.75, "y": 3.25 },
{ "matrix": [3, 5], "x": 5.75, "y": 3.25 },
{ "matrix": [3, 6], "x": 6.75, "y": 3.25 },
{ "matrix": [3, 7], "x": 7.75, "y": 3.25 },
{ "matrix": [3, 8], "x": 8.75, "y": 3.25 },
{ "matrix": [3, 9], "x": 9.75, "y": 3.25 },
{ "matrix": [3, 10], "x": 10.75, "y": 3.25 },
{ "matrix": [3, 11], "x": 11.75, "y": 3.25 },
{ "matrix": [3, 12], "x": 12.75, "y": 3.25 },
{ "h": 2, "matrix": [3, 13], "w": 1.25, "x": 13.75, "y": 2.25 },
{ "matrix": [4, 0], "w": 1.25, "x": 0, "y": 4.25 },
{ "matrix": [4, 1], "x": 1.25, "y": 4.25 },
{ "matrix": [4, 2], "x": 2.25, "y": 4.25 },
{ "matrix": [4, 3], "x": 3.25, "y": 4.25 },
{ "matrix": [4, 4], "x": 4.25, "y": 4.25 },
{ "matrix": [4, 5], "x": 5.25, "y": 4.25 },
{ "matrix": [4, 6], "x": 6.25, "y": 4.25 },
{ "matrix": [4, 7], "x": 7.25, "y": 4.25 },
{ "matrix": [4, 8], "x": 8.25, "y": 4.25 },
{ "matrix": [4, 9], "x": 9.25, "y": 4.25 },
{ "matrix": [4, 10], "x": 10.25, "y": 4.25 },
{ "matrix": [4, 11], "x": 11.25, "y": 4.25 },
{ "matrix": [4, 12], "w": 1.75, "x": 12.25, "y": 4.25 },
{ "matrix": [4, 13], "x": 14, "y": 4.25 },
{ "matrix": [4, 15], "x": 16.25, "y": 4.25 },
{ "matrix": [5, 0], "w": 1.25, "x": 0, "y": 5.25 },
{ "matrix": [5, 1], "w": 1.25, "x": 1.25, "y": 5.25 },
{ "matrix": [5, 2], "w": 1.25, "x": 2.5, "y": 5.25 },
{ "matrix": [5, 6], "w": 6.25, "x": 3.75, "y": 5.25 },
{ "matrix": [5, 10], "w": 1.25, "x": 10, "y": 5.25 },
{ "matrix": [5, 11], "w": 1.25, "x": 11.25, "y": 5.25 },
{ "matrix": [5, 12], "w": 1.25, "x": 12.5, "y": 5.25 },
{ "matrix": [5, 13], "w": 1.25, "x": 13.75, "y": 5.25 },
{ "matrix": [5, 14], "x": 15.25, "y": 5.25 },
{ "matrix": [5, 15], "x": 16.25, "y": 5.25 },
{ "matrix": [5, 16], "x": 17.25, "y": 5.25 }
]
},
"LAYOUT_tkl_iso_tsangan": {
"layout": [
{ "matrix": [0, 0], "x": 0, "y": 0 },
{ "matrix": [0, 1], "x": 2, "y": 0 },
{ "matrix": [0, 2], "x": 3, "y": 0 },
{ "matrix": [0, 3], "x": 4, "y": 0 },
{ "matrix": [0, 4], "x": 5, "y": 0 },
{ "matrix": [0, 5], "x": 6.5, "y": 0 },
{ "matrix": [0, 6], "x": 7.5, "y": 0 },
{ "matrix": [0, 7], "x": 8.5, "y": 0 },
{ "matrix": [0, 8], "x": 9.5, "y": 0 },
{ "matrix": [0, 9], "x": 11, "y": 0 },
{ "matrix": [0, 10], "x": 12, "y": 0 },
{ "matrix": [0, 11], "x": 13, "y": 0 },
{ "matrix": [0, 12], "x": 14, "y": 0 },
{ "matrix": [0, 14], "x": 15.25, "y": 0 },
{ "matrix": [0, 15], "x": 16.25, "y": 0 },
{ "matrix": [0, 16], "x": 17.25, "y": 0 },
{ "matrix": [1, 0], "x": 0, "y": 1.25 },
{ "matrix": [1, 1], "x": 1, "y": 1.25 },
{ "matrix": [1, 2], "x": 2, "y": 1.25 },
{ "matrix": [1, 3], "x": 3, "y": 1.25 },
{ "matrix": [1, 4], "x": 4, "y": 1.25 },
{ "matrix": [1, 5], "x": 5, "y": 1.25 },
{ "matrix": [1, 6], "x": 6, "y": 1.25 },
{ "matrix": [1, 7], "x": 7, "y": 1.25 },
{ "matrix": [1, 8], "x": 8, "y": 1.25 },
{ "matrix": [1, 9], "x": 9, "y": 1.25 },
{ "matrix": [1, 10], "x": 10, "y": 1.25 },
{ "matrix": [1, 11], "x": 11, "y": 1.25 },
{ "matrix": [1, 12], "x": 12, "y": 1.25 },
{ "matrix": [1, 13], "w": 2, "x": 13, "y": 1.25 },
{ "matrix": [1, 14], "x": 15.25, "y": 1.25 },
{ "matrix": [1, 15], "x": 16.25, "y": 1.25 },
{ "matrix": [1, 16], "x": 17.25, "y": 1.25 },
{ "matrix": [2, 0], "w": 1.5, "x": 0, "y": 2.25 },
{ "matrix": [2, 1], "x": 1.5, "y": 2.25 },
{ "matrix": [2, 2], "x": 2.5, "y": 2.25 },
{ "matrix": [2, 3], "x": 3.5, "y": 2.25 },
{ "matrix": [2, 4], "x": 4.5, "y": 2.25 },
{ "matrix": [2, 5], "x": 5.5, "y": 2.25 },
{ "matrix": [2, 6], "x": 6.5, "y": 2.25 },
{ "matrix": [2, 7], "x": 7.5, "y": 2.25 },
{ "matrix": [2, 8], "x": 8.5, "y": 2.25 },
{ "matrix": [2, 9], "x": 9.5, "y": 2.25 },
{ "matrix": [2, 10], "x": 10.5, "y": 2.25 },
{ "matrix": [2, 11], "x": 11.5, "y": 2.25 },
{ "matrix": [2, 12], "x": 12.5, "y": 2.25 },
{ "matrix": [2, 14], "x": 15.25, "y": 2.25 },
{ "matrix": [2, 15], "x": 16.25, "y": 2.25 },
{ "matrix": [2, 16], "x": 17.25, "y": 2.25 },
{ "matrix": [3, 0], "w": 1.75, "x": 0, "y": 3.25 },
{ "matrix": [3, 1], "x": 1.75, "y": 3.25 },
{ "matrix": [3, 2], "x": 2.75, "y": 3.25 },
{ "matrix": [3, 3], "x": 3.75, "y": 3.25 },
{ "matrix": [3, 4], "x": 4.75, "y": 3.25 },
{ "matrix": [3, 5], "x": 5.75, "y": 3.25 },
{ "matrix": [3, 6], "x": 6.75, "y": 3.25 },
{ "matrix": [3, 7], "x": 7.75, "y": 3.25 },
{ "matrix": [3, 8], "x": 8.75, "y": 3.25 },
{ "matrix": [3, 9], "x": 9.75, "y": 3.25 },
{ "matrix": [3, 10], "x": 10.75, "y": 3.25 },
{ "matrix": [3, 11], "x": 11.75, "y": 3.25 },
{ "matrix": [3, 12], "x": 12.75, "y": 3.25 },
{ "h": 2, "matrix": [3, 13], "w": 1.25, "x": 13.75, "y": 2.25 },
{ "matrix": [4, 0], "w": 1.25, "x": 0, "y": 4.25 },
{ "matrix": [4, 1], "x": 1.25, "y": 4.25 },
{ "matrix": [4, 2], "x": 2.25, "y": 4.25 },
{ "matrix": [4, 3], "x": 3.25, "y": 4.25 },
{ "matrix": [4, 4], "x": 4.25, "y": 4.25 },
{ "matrix": [4, 5], "x": 5.25, "y": 4.25 },
{ "matrix": [4, 6], "x": 6.25, "y": 4.25 },
{ "matrix": [4, 7], "x": 7.25, "y": 4.25 },
{ "matrix": [4, 8], "x": 8.25, "y": 4.25 },
{ "matrix": [4, 9], "x": 9.25, "y": 4.25 },
{ "matrix": [4, 10], "x": 10.25, "y": 4.25 },
{ "matrix": [4, 11], "x": 11.25, "y": 4.25 },
{ "matrix": [4, 12], "w": 2.75, "x": 12.25, "y": 4.25 },
{ "matrix": [4, 15], "x": 16.25, "y": 4.25 },
{ "matrix": [5, 0], "w": 1.5, "x": 0, "y": 5.25 },
{ "matrix": [5, 1], "x": 1.5, "y": 5.25 },
{ "matrix": [5, 2], "w": 1.5, "x": 2.5, "y": 5.25 },
{ "matrix": [5, 6], "w": 7, "x": 4, "y": 5.25 },
{ "matrix": [5, 11], "w": 1.5, "x": 11, "y": 5.25 },
{ "matrix": [5, 12], "x": 12.5, "y": 5.25 },
{ "matrix": [5, 13], "w": 1.5, "x": 13.5, "y": 5.25 },
{ "matrix": [5, 14], "x": 15.25, "y": 5.25 },
{ "matrix": [5, 15], "x": 16.25, "y": 5.25 },
{ "matrix": [5, 16], "x": 17.25, "y": 5.25 }
]
},
"LAYOUT_tkl_iso_tsangan_split_bs_rshift": {
"layout": [
{ "matrix": [0, 0], "x": 0, "y": 0 },
{ "matrix": [0, 1], "x": 2, "y": 0 },
{ "matrix": [0, 2], "x": 3, "y": 0 },
{ "matrix": [0, 3], "x": 4, "y": 0 },
{ "matrix": [0, 4], "x": 5, "y": 0 },
{ "matrix": [0, 5], "x": 6.5, "y": 0 },
{ "matrix": [0, 6], "x": 7.5, "y": 0 },
{ "matrix": [0, 7], "x": 8.5, "y": 0 },
{ "matrix": [0, 8], "x": 9.5, "y": 0 },
{ "matrix": [0, 9], "x": 11, "y": 0 },
{ "matrix": [0, 10], "x": 12, "y": 0 },
{ "matrix": [0, 11], "x": 13, "y": 0 },
{ "matrix": [0, 12], "x": 14, "y": 0 },
{ "matrix": [0, 14], "x": 15.25, "y": 0 },
{ "matrix": [0, 15], "x": 16.25, "y": 0 },
{ "matrix": [0, 16], "x": 17.25, "y": 0 },
{ "matrix": [1, 0], "x": 0, "y": 1.25 },
{ "matrix": [1, 1], "x": 1, "y": 1.25 },
{ "matrix": [1, 2], "x": 2, "y": 1.25 },
{ "matrix": [1, 3], "x": 3, "y": 1.25 },
{ "matrix": [1, 4], "x": 4, "y": 1.25 },
{ "matrix": [1, 5], "x": 5, "y": 1.25 },
{ "matrix": [1, 6], "x": 6, "y": 1.25 },
{ "matrix": [1, 7], "x": 7, "y": 1.25 },
{ "matrix": [1, 8], "x": 8, "y": 1.25 },
{ "matrix": [1, 9], "x": 9, "y": 1.25 },
{ "matrix": [1, 10], "x": 10, "y": 1.25 },
{ "matrix": [1, 11], "x": 11, "y": 1.25 },
{ "matrix": [1, 12], "x": 12, "y": 1.25 },
{ "matrix": [1, 13], "x": 13, "y": 1.25 },
{ "matrix": [0, 13], "x": 14, "y": 1.25 },
{ "matrix": [1, 14], "x": 15.25, "y": 1.25 },
{ "matrix": [1, 15], "x": 16.25, "y": 1.25 },
{ "matrix": [1, 16], "x": 17.25, "y": 1.25 },
{ "matrix": [2, 0], "w": 1.5, "x": 0, "y": 2.25 },
{ "matrix": [2, 1], "x": 1.5, "y": 2.25 },
{ "matrix": [2, 2], "x": 2.5, "y": 2.25 },
{ "matrix": [2, 3], "x": 3.5, "y": 2.25 },
{ "matrix": [2, 4], "x": 4.5, "y": 2.25 },
{ "matrix": [2, 5], "x": 5.5, "y": 2.25 },
{ "matrix": [2, 6], "x": 6.5, "y": 2.25 },
{ "matrix": [2, 7], "x": 7.5, "y": 2.25 },
{ "matrix": [2, 8], "x": 8.5, "y": 2.25 },
{ "matrix": [2, 9], "x": 9.5, "y": 2.25 },
{ "matrix": [2, 10], "x": 10.5, "y": 2.25 },
{ "matrix": [2, 11], "x": 11.5, "y": 2.25 },
{ "matrix": [2, 12], "x": 12.5, "y": 2.25 },
{ "matrix": [2, 14], "x": 15.25, "y": 2.25 },
{ "matrix": [2, 15], "x": 16.25, "y": 2.25 },
{ "matrix": [2, 16], "x": 17.25, "y": 2.25 },
{ "matrix": [3, 0], "w": 1.75, "x": 0, "y": 3.25 },
{ "matrix": [3, 1], "x": 1.75, "y": 3.25 },
{ "matrix": [3, 2], "x": 2.75, "y": 3.25 },
{ "matrix": [3, 3], "x": 3.75, "y": 3.25 },
{ "matrix": [3, 4], "x": 4.75, "y": 3.25 },
{ "matrix": [3, 5], "x": 5.75, "y": 3.25 },
{ "matrix": [3, 6], "x": 6.75, "y": 3.25 },
{ "matrix": [3, 7], "x": 7.75, "y": 3.25 },
{ "matrix": [3, 8], "x": 8.75, "y": 3.25 },
{ "matrix": [3, 9], "x": 9.75, "y": 3.25 },
{ "matrix": [3, 10], "x": 10.75, "y": 3.25 },
{ "matrix": [3, 11], "x": 11.75, "y": 3.25 },
{ "matrix": [3, 12], "x": 12.75, "y": 3.25 },
{ "h": 2, "matrix": [3, 13], "w": 1.25, "x": 13.75, "y": 2.25 },
{ "matrix": [4, 0], "w": 1.25, "x": 0, "y": 4.25 },
{ "matrix": [4, 1], "x": 1.25, "y": 4.25 },
{ "matrix": [4, 2], "x": 2.25, "y": 4.25 },
{ "matrix": [4, 3], "x": 3.25, "y": 4.25 },
{ "matrix": [4, 4], "x": 4.25, "y": 4.25 },
{ "matrix": [4, 5], "x": 5.25, "y": 4.25 },
{ "matrix": [4, 6], "x": 6.25, "y": 4.25 },
{ "matrix": [4, 7], "x": 7.25, "y": 4.25 },
{ "matrix": [4, 8], "x": 8.25, "y": 4.25 },
{ "matrix": [4, 9], "x": 9.25, "y": 4.25 },
{ "matrix": [4, 10], "x": 10.25, "y": 4.25 },
{ "matrix": [4, 11], "x": 11.25, "y": 4.25 },
{ "matrix": [4, 12], "w": 1.75, "x": 12.25, "y": 4.25 },
{ "matrix": [4, 13], "x": 14, "y": 4.25 },
{ "matrix": [4, 15], "x": 16.25, "y": 4.25 },
{ "matrix": [5, 0], "w": 1.5, "x": 0, "y": 5.25 },
{ "matrix": [5, 1], "x": 1.5, "y": 5.25 },
{ "matrix": [5, 2], "w": 1.5, "x": 2.5, "y": 5.25 },
{ "matrix": [5, 6], "w": 7, "x": 4, "y": 5.25 },
{ "matrix": [5, 11], "w": 1.5, "x": 11, "y": 5.25 },
{ "matrix": [5, 12], "x": 12.5, "y": 5.25 },
{ "matrix": [5, 13], "w": 1.5, "x": 13.5, "y": 5.25 },
{ "matrix": [5, 14], "x": 15.25, "y": 5.25 },
{ "matrix": [5, 15], "x": 16.25, "y": 5.25 },
{ "matrix": [5, 16], "x": 17.25, "y": 5.25 }
]
}
}
}
@@ -0,0 +1,14 @@
// Copyright 2026 Yiancar
// SPDX-License-Identifier: GPL-2.0-or-later
#include QMK_KEYBOARD_H
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT_all( /* Base */
KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_PSCR, KC_SCRL, KC_PAUS,
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_DEL, KC_INS, KC_HOME, KC_PGUP,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_DEL, KC_END, KC_PGDN,
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT,
KC_LSFT, KC_NUBS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_RSFT, KC_UP,
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, KC_RGUI, KC_APP, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT)
};
+9
View File
@@ -0,0 +1,9 @@
// Copyright 2026 Yiancar
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include_next <mcuconf.h>
#undef STM32_PWM_USE_TIM1
#define STM32_PWM_USE_TIM1 TRUE
+32
View File
@@ -0,0 +1,32 @@
# Stratum
This is a standard TKL layout PCB. It supports VIA.
* Keyboard Maintainer: [Yiancar](http://yiancar-designs.com/) and on [GitHub](https://github.com/yiancar)
* Hardware Supported: A TKL keyboard with STM32F072CB
* Hardware Availability: https://artifact-industries.com
## Instructions
### Build
Make example for this keyboard (after setting up your build environment):
make artifact/stratum:default
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
### Reset
- Unplug
- Hold Escape
- Plug In
- Unplug
- Release Escape
### Flash
- Unplug
- Hold Escape
- Plug In
- Flash using QMK Toolbox or CLI (`make artifact/stratum:<keymap>:flash`)
+9
View File
@@ -0,0 +1,9 @@
// Copyright 2026 Yiancar
// SPDX-License-Identifier: GPL-2.0-or-later
#include "quantum.h"
void led_init_ports(void) {
// Set our LED pins as open drain outputs
gpio_set_pin_output_open_drain(LED_CAPS_LOCK_PIN);
}
@@ -18,6 +18,10 @@
#include "eeprom.h"
#include "version.h" // for QMK_BUILDDATE used in EEPROM magic
#ifdef VIA_ENABLE
# include "via.h"
#endif
/* Artificial delay added to get media keys to work in the encoder*/
#define MEDIA_KEY_DELAY 10
@@ -54,22 +58,16 @@ void board_init(void) {
}
uint32_t read_custom_config(void *data, uint32_t offset, uint32_t length) {
#ifdef VIA_ENABLE
return via_read_custom_config(data, offset, length);
#else
return eeconfig_read_kb_datablock(data, offset, length);
#endif
}
uint32_t write_custom_config(const void *data, uint32_t offset, uint32_t length) {
#ifdef VIA_ENABLE
return via_update_custom_config(data, offset, length);
#else
return eeconfig_update_kb_datablock(data, offset, length);
#endif
}
void keyboard_post_init_kb(void) {
custom_config_load();
/*
This is a workaround to some really weird behavior
Without this code, the OLED will turn on, but not when you initially plug the keyboard in.
@@ -305,14 +303,8 @@ bool encoder_update_kb(uint8_t index, bool clockwise) {
return true;
}
void custom_config_reset(void){
for(int i = 0; i < VIA_EEPROM_CUSTOM_CONFIG_SIZE; ++i) {
uint8_t dummy = 0;
write_custom_config(&dummy, i, 1);
}
uint8_t encoder_modes = 0x1F;
write_custom_config(&encoder_modes, EEPROM_ENABLED_ENCODER_MODES_OFFSET, 1);
void custom_config_reset(void) {
eeconfig_init_kb_datablock();
}
void custom_config_load(void){
@@ -322,40 +314,20 @@ void custom_config_load(void){
#endif
}
// Called from via_init() if VIA_ENABLE
// Called from matrix_init_kb() if not VIA_ENABLE
void satisfaction_core_init(void)
{
// This checks both an EEPROM reset (from bootmagic lite, keycodes)
// and also firmware build date (from via_eeprom_is_valid())
if (eeconfig_is_enabled()) {
custom_config_load();
} else {
#ifdef DYNAMIC_KEYMAP_ENABLE
// Reset the custom stuff
custom_config_reset();
#endif
// DO NOT set EEPROM valid here, let caller do this
}
void eeconfig_init_kb_datablock(void) {
uint8_t default_data[EECONFIG_KB_DATA_SIZE] = { 0 };
default_data[EEPROM_ENABLED_ENCODER_MODES_OFFSET] = 0x1F;
eeconfig_update_kb_datablock(default_data, 0, sizeof(default_data));
}
void matrix_init_kb(void)
{
#ifndef VIA_ENABLE
satisfaction_core_init();
#endif // VIA_ENABLE
void matrix_init_kb(void) {
rtcGetTime(&RTCD1, &last_timespec);
matrix_init_user();
oled_request_wakeup();
}
#ifdef VIA_ENABLE
void via_init_kb(void) {
satisfaction_core_init();
}
#endif // VIA_ENABLE
void housekeeping_task_kb(void) {
rtcGetTime(&RTCD1, &last_timespec);
uint16_t minutes_since_midnight = last_timespec.millisecond / 1000 / 60;
@@ -8,7 +8,6 @@
#include <hal.h>
#include "via.h" // only for EEPROM address
#include "satisfaction_keycodes.h"
#define EEPROM_ENABLED_ENCODER_MODES_OFFSET 0
@@ -3,6 +3,8 @@
#pragma once
#include "keycodes.h"
enum my_keycodes {
ENC_PRESS = QK_KB_0,
CLOCK_SET,
+1 -8
View File
@@ -34,15 +34,8 @@
// OLED timeout reimplemented in the keyboard-specific code
#define CUSTOM_OLED_TIMEOUT 60000
// Custom config starts after VIA's EEPROM usage,
// dynamic keymaps start after this.
// Custom config Usage:
// 1 for enabled encoder modes (1 byte)
// 1 for OLED default mode (1 byte)
// 6 for 3x custom encoder settings, left, right, and press (18 bytes)
#define VIA_EEPROM_CUSTOM_CONFIG_SIZE 20
// And if VIA isn't enabled, fall back to using standard QMK for configuration
#ifndef VIA_ENABLE
#define EECONFIG_KB_DATA_SIZE VIA_EEPROM_CUSTOM_CONFIG_SIZE
#endif
#define EECONFIG_KB_DATA_SIZE 20
@@ -32,18 +32,11 @@
// OLED timeout reimplemented in the keyboard-specific code
#define CUSTOM_OLED_TIMEOUT 60000
// Custom config starts after VIA's EEPROM usage,
// dynamic keymaps start after this.
// Custom config Usage:
// 1 for enabled encoder modes (1 byte)
// 1 for OLED default mode (1 byte)
// 6 for 3x custom encoder settings, left, right, and press (18 bytes)
#define VIA_EEPROM_CUSTOM_CONFIG_SIZE 20
// And if VIA isn't enabled, fall back to using standard QMK for configuration
#ifndef VIA_ENABLE
#define EECONFIG_KB_DATA_SIZE VIA_EEPROM_CUSTOM_CONFIG_SIZE
#endif
#define EECONFIG_KB_DATA_SIZE 20
// VIA lighting is handled by the keyboard-level code
#define VIA_CUSTOM_LIGHTING_ENABLE
+1 -1
View File
@@ -16,13 +16,13 @@
#include "ec_switch_matrix.h"
#include "action.h"
#include "print.h"
#include "via.h"
#ifdef SPLIT_KEYBOARD
# include "transactions.h"
#endif
#ifdef VIA_ENABLE
# include "via.h"
void ec_rescale_values(uint8_t item);
void ec_save_threshold_data(uint8_t option);
+13
View File
@@ -0,0 +1,13 @@
// Copyright 2011 Jun Wako <wakojun@gmail.com>
// SPDX-License-Identifier: GPL-2.0-or-later
#include "led.h"
#include "adb.h"
bool led_update_kb(led_t led_state) {
bool res = led_update_user(led_state);
if(res) {
adb_host_kbd_led(~led_state.raw);
}
return res;
}
+1 -1
View File
@@ -1,5 +1,5 @@
CUSTOM_MATRIX = yes
SRC += matrix.c adb.c led.c
SRC += matrix.c adb.c
# OPT_DEFS += -DADB_MOUSE_ENABLE -DMOUSE_ENABLE
+116
View File
@@ -0,0 +1,116 @@
{
"board": "GENERIC_RP_RP2040",
"bootloader": "rp2040",
"diode_direction": "COL2ROW",
"features": {
"bootmagic": true,
"extrakey": true,
"mousekey": true
},
"processor": "RP2040",
"ps2": {
"driver": "vendor",
"enabled": true,
"mouse_enabled": true
},
"layouts": {
"LAYOUT_iso": {
"layout": [
{"label": "Esc", "matrix": [5, 0], "x": 0, "y": 0, "w": 0.9, "h": 0.75},
{"label": "Mute", "matrix": [4, 10], "x": 0.9, "y": 0, "w": 0.75, "h": 0.5},
{"label": "Vol -", "matrix": [3, 10], "x": 1.65, "y": 0, "w": 0.75, "h": 0.5},
{"label": "Vol +", "matrix": [2, 10], "x": 2.4, "y": 0, "w": 0.75, "h": 0.5},
{"label": "ThinkVantage", "matrix": [5, 10], "x": 3.5, "y": 0, "w": 1.25, "h": 0.5},
{"label": "PrtSc", "matrix": [1, 13], "x": 8.9, "y": 0, "w": 0.9, "h": 0.65},
{"label": "ScrLk", "matrix": [2, 13], "x": 9.8, "y": 0, "w": 0.9, "h": 0.65},
{"label": "Pause", "matrix": [6, 12], "x": 10.7, "y": 0, "w": 0.9, "h": 0.65},
{"label": "Insert", "matrix": [0, 9], "x": 12, "y": 0, "w": 0.9, "h": 0.65},
{"label": "Home", "matrix": [0, 12], "x": 12.9, "y": 0, "w": 0.9, "h": 0.65},
{"label": "PgUp", "matrix": [0, 11], "x": 13.8, "y": 0, "w": 0.9, "h": 0.65},
{"label": "F1", "matrix": [0, 1], "x": 0, "y": 0.75, "w": 0.9, "h": 0.65},
{"label": "F2", "matrix": [0, 2], "x": 0.9, "y": 0.75, "w": 0.9, "h": 0.65},
{"label": "F3", "matrix": [3, 2], "x": 1.8, "y": 0.75, "w": 0.9, "h": 0.65},
{"label": "F4", "matrix": [5, 2], "x": 2.7, "y": 0.75, "w": 0.9, "h": 0.65},
{"label": "F5", "matrix": [5, 8], "x": 4, "y": 0.75, "w": 0.9, "h": 0.65},
{"label": "F6", "matrix": [5, 5], "x": 4.9, "y": 0.75, "w": 0.9, "h": 0.65},
{"label": "F7", "matrix": [3, 6], "x": 5.8, "y": 0.75, "w": 0.9, "h": 0.65},
{"label": "F8", "matrix": [0, 6], "x": 6.7, "y": 0.75, "w": 0.9, "h": 0.65},
{"label": "F9", "matrix": [0, 8], "x": 8, "y": 0.75, "w": 0.9, "h": 0.65},
{"label": "F10", "matrix": [1, 8], "x": 8.9, "y": 0.75, "w": 0.9, "h": 0.65},
{"label": "F11", "matrix": [1, 10], "x": 9.8, "y": 0.75, "w": 0.9, "h": 0.65},
{"label": "F12", "matrix": [1, 9], "x": 10.7, "y": 0.75, "w": 0.9, "h": 0.65},
{"label": "Delete", "matrix": [0, 10], "x": 12, "y": 0.75, "w": 0.9, "h": 0.65},
{"label": "End", "matrix": [1, 12], "x": 12.9, "y": 0.75, "w": 0.9, "h": 0.65},
{"label": "PgDn", "matrix": [1, 11], "x": 13.8, "y": 0.75, "w": 0.9, "h": 0.65},
{"label": "`\u00ac", "matrix": [0, 0], "x": 0, "y": 1.4},
{"label": "1!", "matrix": [1, 0], "x": 1, "y": 1.4},
{"label": "2\"", "matrix": [1, 1], "x": 2, "y": 1.4},
{"label": "3\u00a3", "matrix": [1, 2], "x": 3, "y": 1.4},
{"label": "4$", "matrix": [1, 3], "x": 4, "y": 1.4},
{"label": "5%", "matrix": [0, 3], "x": 5, "y": 1.4},
{"label": "6^", "matrix": [0, 4], "x": 6, "y": 1.4},
{"label": "7&", "matrix": [1, 4], "x": 7, "y": 1.4},
{"label": "8*", "matrix": [1, 5], "x": 8, "y": 1.4},
{"label": "9(", "matrix": [1, 6], "x": 9, "y": 1.4},
{"label": "0)", "matrix": [1, 7], "x": 10, "y": 1.4},
{"label": "-_", "matrix": [0, 7], "x": 11, "y": 1.4},
{"label": "=+", "matrix": [0, 5], "x": 12, "y": 1.4},
{"label": "Bksp", "matrix": [3, 8], "x": 13, "y": 1.4, "w": 2},
{"label": "Tab", "matrix": [3, 0], "x": 0, "y": 2.4, "w": 1.5},
{"label": "Q", "matrix": [2, 0], "x": 1.5, "y": 2.4},
{"label": "W", "matrix": [2, 1], "x": 2.5, "y": 2.4},
{"label": "E", "matrix": [2, 2], "x": 3.5, "y": 2.4},
{"label": "R", "matrix": [2, 3], "x": 4.5, "y": 2.4},
{"label": "T", "matrix": [3, 3], "x": 5.5, "y": 2.4},
{"label": "Y", "matrix": [3, 4], "x": 6.5, "y": 2.4},
{"label": "U", "matrix": [2, 4], "x": 7.5, "y": 2.4},
{"label": "I", "matrix": [2, 5], "x": 8.5, "y": 2.4},
{"label": "O", "matrix": [2, 6], "x": 9.5, "y": 2.4},
{"label": "P", "matrix": [2, 7], "x": 10.5, "y": 2.4},
{"label": "[{", "matrix": [3, 7], "x": 11.5, "y": 2.4},
{"label": "]}", "matrix": [3, 5], "x": 12.5, "y": 2.4},
{"label": "Caps Lock", "matrix": [3, 1], "x": 0, "y": 3.4, "w": 1.75},
{"label": "A", "matrix": [4, 0], "x": 1.75, "y": 3.4},
{"label": "S", "matrix": [4, 1], "x": 2.75, "y": 3.4},
{"label": "D", "matrix": [4, 2], "x": 3.75, "y": 3.4},
{"label": "F", "matrix": [4, 3], "x": 4.75, "y": 3.4},
{"label": "G", "matrix": [5, 3], "x": 5.75, "y": 3.4},
{"label": "H", "matrix": [5, 4], "x": 6.75, "y": 3.4},
{"label": "J", "matrix": [4, 4], "x": 7.75, "y": 3.4},
{"label": "K", "matrix": [4, 5], "x": 8.75, "y": 3.4},
{"label": "L", "matrix": [4, 6], "x": 9.75, "y": 3.4},
{"label": ";:", "matrix": [4, 7], "x": 10.75, "y": 3.4},
{"label": "'@", "matrix": [5, 7], "x": 11.75, "y": 3.4},
{"label": "#~", "matrix": [6, 7], "x": 12.75, "y": 3.4},
{"label": "Enter", "matrix": [6, 8], "x": 13.75, "y": 2.4, "w": 1.25, "h": 2},
{"label": "Shift", "matrix": [3, 14], "x": 0, "y": 4.4, "w": 1.25},
{"label": "\\|", "matrix": [5, 1], "x": 1.25, "y": 4.4},
{"label": "Z", "matrix": [6, 0], "x": 2.25, "y": 4.4},
{"label": "X", "matrix": [6, 1], "x": 3.25, "y": 4.4},
{"label": "C", "matrix": [6, 2], "x": 4.25, "y": 4.4},
{"label": "V", "matrix": [6, 3], "x": 5.25, "y": 4.4},
{"label": "B", "matrix": [7, 3], "x": 6.25, "y": 4.4},
{"label": "N", "matrix": [7, 4], "x": 7.25, "y": 4.4},
{"label": "M", "matrix": [6, 4], "x": 8.25, "y": 4.4},
{"label": ",<", "matrix": [6, 5], "x": 9.25, "y": 4.4},
{"label": ".>", "matrix": [6, 6], "x": 10.25, "y": 4.4},
{"label": "/?", "matrix": [7, 7], "x": 11.25, "y": 4.4},
{"label": "Shift", "matrix": [6, 14], "x": 12.25, "y": 4.4, "w": 2.75},
{"label": "Fn", "matrix": [4, 9], "x": 0, "y": 5.4},
{"label": "Ctrl", "matrix": [0, 15], "x": 1, "y": 5.4, "w": 1.25},
{"label": "Left OS", "matrix": [2, 11], "x": 2.25, "y": 5.4, "w": 0.9},
{"label": "Alt", "matrix": [5, 13], "x": 3.15, "y": 5.4},
{"label": "Space", "matrix": [7, 8], "x": 4.15, "y": 5.4, "w": 5},
{"label": "AltGr", "matrix": [7, 13], "x": 9.25, "y": 5.4},
{"label": "Menu", "matrix": [4, 11], "x": 10.25, "y": 5.4},
{"label": "Ctrl", "matrix": [6, 15], "x": 11.25, "y": 5.4},
{"label": "Browser Back", "matrix": [6, 11], "x": 12.25, "y": 5.4, "w": 0.9, "h": 0.75},
{"label": "Up", "matrix": [5, 12], "x": 13.15, "y": 5.4, "w": 0.9, "h": 0.75},
{"label": "Browser Forward", "matrix": [7, 11], "x": 14.05, "y": 5.4, "w": 0.9, "h": 0.75},
{"label": "Left", "matrix": [7, 12], "x": 12.25, "y": 6.15, "w": 0.9, "h": 0.75},
{"label": "Down", "matrix": [7, 10], "x": 13.15, "y": 6.15, "w": 0.9, "h": 0.75},
{"label": "Right", "matrix": [7, 9], "x": 14.05, "y": 6.15, "w": 0.9, "h": 0.75}
]
}
}
}
@@ -0,0 +1,19 @@
{
"manufacturer": "Frank Adams",
"keyboard_name": "converter/thinkpad_t6x/pico_t61",
"maintainer": "Al En",
"matrix_pins": {
"cols": ["GP27", "GP26", "GP17", "GP14", "GP12", "GP19", "GP18", "GP15", "GP13", "GP6", "GP16", "GP5", "GP28", "GP2", "GP4", "GP3"],
"rows": ["GP11", "GP22", "GP10", "GP21", "GP9", "GP20", "GP8", "GP7"]
},
"ps2": {
"clock_pin": "GP0",
"data_pin": "GP1"
},
"url": "https://github.com/thedalles77/USB_Laptop_Keyboard_Controller/tree/master/Example_Keyboards/Pico_T61_Keyboard",
"usb": {
"device_version": "1.0.0",
"pid": "0xBACA",
"vid": "0xFEED"
}
}
@@ -0,0 +1,27 @@
# converter/thinkpad_t6x/pico_t61
![converter/thinkpad_t6x/pico_t61](https://i.imgur.com/KDouWIc.jpeg)
This is a converter PCB for Lenovo Thinkpad keyboards from T60, T400 and X200 series, based on the Raspberry Pi Pico W. The QMK implementation here is specific to the converter in the link below. Similar PCB designs to convert a Thinkpad keyboard to USB exist, but they use a different microcontroller and wiring of the keyboard connector with the MCU.
* Keyboard Maintainer: [Al En](https://github.com/gitaen)
* Hardware Supported: The linked converter PCB with keyboards from various Thinkpad models
* Hardware Availability: [Custom PCB](https://github.com/thedalles77/USB_Laptop_Keyboard_Controller/tree/master/Example_Keyboards/Pico_T61_Keyboard)
Make example for this keyboard (after setting up your build environment):
make converter/thinkpad_t6x/pico_t61:default
Flashing example for this keyboard:
make converter/thinkpad_t6x/pico_t61:default:flash
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
## Bootloader
Enter the bootloader in 3 ways:
* **Bootmagic reset**: Hold down the key at (0,0) in the matrix (\`~) and plug in the keyboard
* **Physical BOOTSEL button**: Hold down the BOOTSEL button on the Raspberry PiPico W and plug the keyboard
* **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is available
@@ -2,130 +2,18 @@
"manufacturer": "strobo5",
"keyboard_name": "converter/thinkpad_t6x/rpi_pico",
"maintainer": "strobo5",
"board": "GENERIC_RP_RP2040",
"bootloader": "rp2040",
"diode_direction": "COL2ROW",
"features": {
"bootmagic": true,
"extrakey": true,
"mousekey": true
},
"matrix_pins": {
"cols": ["GP7", "GP9", "GP11", "GP13", "GP17", "GP16", "GP14", "GP12", "GP15", "GP8", "GP10", "GP6", "GP4", "GP2", "GP5", "GP3"],
"rows": ["GP20", "GP26", "GP22", "GP21", "GP18", "GP19", "GP27", "GP28"]
},
"processor": "RP2040",
"ps2": {
"clock_pin": "GP1",
"data_pin": "GP0",
"driver": "vendor",
"enabled": true,
"mouse_enabled": true
"data_pin": "GP0"
},
"url": "https://github.com/strobo5/T61_PiPico_Scanner",
"usb": {
"device_version": "1.0.0",
"pid": "0x0000",
"vid": "0xFEED"
},
"layouts": {
"LAYOUT_iso": {
"layout": [
{"label": "Esc", "matrix": [5, 0], "x": 0, "y": 0, "w": 0.9, "h": 0.75},
{"label": "Mute", "matrix": [4, 10], "x": 0.9, "y": 0, "w": 0.75, "h": 0.5},
{"label": "Vol -", "matrix": [3, 10], "x": 1.65, "y": 0, "w": 0.75, "h": 0.5},
{"label": "Vol +", "matrix": [2, 10], "x": 2.4, "y": 0, "w": 0.75, "h": 0.5},
{"label": "ThinkVantage", "matrix": [5, 10], "x": 3.5, "y": 0, "w": 1.25, "h": 0.5},
{"label": "PrtSc", "matrix": [1, 13], "x": 8.9, "y": 0, "w": 0.9, "h": 0.65},
{"label": "ScrLk", "matrix": [2, 13], "x": 9.8, "y": 0, "w": 0.9, "h": 0.65},
{"label": "Pause", "matrix": [6, 12], "x": 10.7, "y": 0, "w": 0.9, "h": 0.65},
{"label": "Insert", "matrix": [0, 9], "x": 12, "y": 0, "w": 0.9, "h": 0.65},
{"label": "Home", "matrix": [0, 12], "x": 12.9, "y": 0, "w": 0.9, "h": 0.65},
{"label": "PgUp", "matrix": [0, 11], "x": 13.8, "y": 0, "w": 0.9, "h": 0.65},
{"label": "F1", "matrix": [0, 1], "x": 0, "y": 0.75, "w": 0.9, "h": 0.65},
{"label": "F2", "matrix": [0, 2], "x": 0.9, "y": 0.75, "w": 0.9, "h": 0.65},
{"label": "F3", "matrix": [3, 2], "x": 1.8, "y": 0.75, "w": 0.9, "h": 0.65},
{"label": "F4", "matrix": [5, 2], "x": 2.7, "y": 0.75, "w": 0.9, "h": 0.65},
{"label": "F5", "matrix": [5, 8], "x": 4, "y": 0.75, "w": 0.9, "h": 0.65},
{"label": "F6", "matrix": [5, 5], "x": 4.9, "y": 0.75, "w": 0.9, "h": 0.65},
{"label": "F7", "matrix": [3, 6], "x": 5.8, "y": 0.75, "w": 0.9, "h": 0.65},
{"label": "F8", "matrix": [0, 6], "x": 6.7, "y": 0.75, "w": 0.9, "h": 0.65},
{"label": "F9", "matrix": [0, 8], "x": 8, "y": 0.75, "w": 0.9, "h": 0.65},
{"label": "F10", "matrix": [1, 8], "x": 8.9, "y": 0.75, "w": 0.9, "h": 0.65},
{"label": "F11", "matrix": [1, 10], "x": 9.8, "y": 0.75, "w": 0.9, "h": 0.65},
{"label": "F12", "matrix": [1, 9], "x": 10.7, "y": 0.75, "w": 0.9, "h": 0.65},
{"label": "Delete", "matrix": [0, 10], "x": 12, "y": 0.75, "w": 0.9, "h": 0.65},
{"label": "End", "matrix": [1, 12], "x": 12.9, "y": 0.75, "w": 0.9, "h": 0.65},
{"label": "PgDn", "matrix": [1, 11], "x": 13.8, "y": 0.75, "w": 0.9, "h": 0.65},
{"label": "`\u00ac", "matrix": [0, 0], "x": 0, "y": 1.4},
{"label": "1!", "matrix": [1, 0], "x": 1, "y": 1.4},
{"label": "2\"", "matrix": [1, 1], "x": 2, "y": 1.4},
{"label": "3\u00a3", "matrix": [1, 2], "x": 3, "y": 1.4},
{"label": "4$", "matrix": [1, 3], "x": 4, "y": 1.4},
{"label": "5%", "matrix": [0, 3], "x": 5, "y": 1.4},
{"label": "6^", "matrix": [0, 4], "x": 6, "y": 1.4},
{"label": "7&", "matrix": [1, 4], "x": 7, "y": 1.4},
{"label": "8*", "matrix": [1, 5], "x": 8, "y": 1.4},
{"label": "9(", "matrix": [1, 6], "x": 9, "y": 1.4},
{"label": "0)", "matrix": [1, 7], "x": 10, "y": 1.4},
{"label": "-_", "matrix": [0, 7], "x": 11, "y": 1.4},
{"label": "=+", "matrix": [0, 5], "x": 12, "y": 1.4},
{"label": "Bksp", "matrix": [3, 8], "x": 13, "y": 1.4, "w": 2},
{"label": "Tab", "matrix": [3, 0], "x": 0, "y": 2.4, "w": 1.5},
{"label": "Q", "matrix": [2, 0], "x": 1.5, "y": 2.4},
{"label": "W", "matrix": [2, 1], "x": 2.5, "y": 2.4},
{"label": "E", "matrix": [2, 2], "x": 3.5, "y": 2.4},
{"label": "R", "matrix": [2, 3], "x": 4.5, "y": 2.4},
{"label": "T", "matrix": [3, 3], "x": 5.5, "y": 2.4},
{"label": "Y", "matrix": [3, 4], "x": 6.5, "y": 2.4},
{"label": "U", "matrix": [2, 4], "x": 7.5, "y": 2.4},
{"label": "I", "matrix": [2, 5], "x": 8.5, "y": 2.4},
{"label": "O", "matrix": [2, 6], "x": 9.5, "y": 2.4},
{"label": "P", "matrix": [2, 7], "x": 10.5, "y": 2.4},
{"label": "[{", "matrix": [3, 7], "x": 11.5, "y": 2.4},
{"label": "]}", "matrix": [3, 5], "x": 12.5, "y": 2.4},
{"label": "Caps Lock", "matrix": [3, 1], "x": 0, "y": 3.4, "w": 1.75},
{"label": "A", "matrix": [4, 0], "x": 1.75, "y": 3.4},
{"label": "S", "matrix": [4, 1], "x": 2.75, "y": 3.4},
{"label": "D", "matrix": [4, 2], "x": 3.75, "y": 3.4},
{"label": "F", "matrix": [4, 3], "x": 4.75, "y": 3.4},
{"label": "G", "matrix": [5, 3], "x": 5.75, "y": 3.4},
{"label": "H", "matrix": [5, 4], "x": 6.75, "y": 3.4},
{"label": "J", "matrix": [4, 4], "x": 7.75, "y": 3.4},
{"label": "K", "matrix": [4, 5], "x": 8.75, "y": 3.4},
{"label": "L", "matrix": [4, 6], "x": 9.75, "y": 3.4},
{"label": ";:", "matrix": [4, 7], "x": 10.75, "y": 3.4},
{"label": "'@", "matrix": [5, 7], "x": 11.75, "y": 3.4},
{"label": "#~", "matrix": [6, 7], "x": 12.75, "y": 3.4},
{"label": "Enter", "matrix": [6, 8], "x": 13.75, "y": 2.4, "w": 1.25, "h": 2},
{"label": "Shift", "matrix": [3, 14], "x": 0, "y": 4.4, "w": 1.25},
{"label": "\\|", "matrix": [5, 1], "x": 1.25, "y": 4.4},
{"label": "Z", "matrix": [6, 0], "x": 2.25, "y": 4.4},
{"label": "X", "matrix": [6, 1], "x": 3.25, "y": 4.4},
{"label": "C", "matrix": [6, 2], "x": 4.25, "y": 4.4},
{"label": "V", "matrix": [6, 3], "x": 5.25, "y": 4.4},
{"label": "B", "matrix": [7, 3], "x": 6.25, "y": 4.4},
{"label": "N", "matrix": [7, 4], "x": 7.25, "y": 4.4},
{"label": "M", "matrix": [6, 4], "x": 8.25, "y": 4.4},
{"label": ",<", "matrix": [6, 5], "x": 9.25, "y": 4.4},
{"label": ".>", "matrix": [6, 6], "x": 10.25, "y": 4.4},
{"label": "/?", "matrix": [7, 7], "x": 11.25, "y": 4.4},
{"label": "Shift", "matrix": [6, 14], "x": 12.25, "y": 4.4, "w": 2.75},
{"label": "Fn", "matrix": [4, 9], "x": 0, "y": 5.4},
{"label": "Ctrl", "matrix": [0, 15], "x": 1, "y": 5.4, "w": 1.25},
{"label": "Left OS", "matrix": [2, 11], "x": 2.25, "y": 5.4, "w": 0.9},
{"label": "Alt", "matrix": [5, 13], "x": 3.15, "y": 5.4},
{"label": "Space", "matrix": [7, 8], "x": 4.15, "y": 5.4, "w": 5},
{"label": "AltGr", "matrix": [7, 13], "x": 9.25, "y": 5.4},
{"label": "Menu", "matrix": [4, 11], "x": 10.25, "y": 5.4},
{"label": "Ctrl", "matrix": [6, 15], "x": 11.25, "y": 5.4},
{"label": "Browser Back", "matrix": [6, 11], "x": 12.25, "y": 5.4, "w": 0.9, "h": 0.75},
{"label": "Up", "matrix": [5, 12], "x": 13.15, "y": 5.4, "w": 0.9, "h": 0.75},
{"label": "Browser Forward", "matrix": [7, 11], "x": 14.05, "y": 5.4, "w": 0.9, "h": 0.75},
{"label": "Left", "matrix": [7, 12], "x": 12.25, "y": 6.15, "w": 0.9, "h": 0.75},
{"label": "Down", "matrix": [7, 10], "x": 13.15, "y": 6.15, "w": 0.9, "h": 0.75},
{"label": "Right", "matrix": [7, 9], "x": 14.05, "y": 6.15, "w": 0.9, "h": 0.75}
]
}
}
}
@@ -224,11 +224,14 @@ extern "C" {
}
}
void led_set(uint8_t usb_led) {
if (kbd1.isReady()) kbd1.SetReport(0, 0, 2, 0, 1, &usb_led);
if (kbd2.isReady()) kbd2.SetReport(0, 0, 2, 0, 1, &usb_led);
if (kbd3.isReady()) kbd3.SetReport(0, 0, 2, 0, 1, &usb_led);
if (kbd4.isReady()) kbd4.SetReport(0, 0, 2, 0, 1, &usb_led);
led_update_kb((led_t){.raw = usb_led});
bool led_update_kb(led_t led_state) {
bool res = led_update_user(led_state);
if(res) {
if (kbd1.isReady()) kbd1.SetReport(0, 0, 2, 0, 1, &led_state.raw);
if (kbd2.isReady()) kbd2.SetReport(0, 0, 2, 0, 1, &led_state.raw);
if (kbd3.isReady()) kbd3.SetReport(0, 0, 2, 0, 1, &led_state.raw);
if (kbd4.isReady()) kbd4.SetReport(0, 0, 2, 0, 1, &led_state.raw);
}
return res;
}
}
+9
View File
@@ -0,0 +1,9 @@
// Copyright 2022 Nick Brassel (@tzarc)
// SPDX-License-Identifier: GPL-2.0-or-later
#include "quantum.h"
void bootloader_jump(void) {
// TODO: Work out how to jump to LDROM, for now just reset the board.
NVIC_SystemReset();
}
@@ -0,0 +1,90 @@
{
"keyboard_name": "One 2 SF ANSI",
"usb": {
"pid": "0x07AF",
"device_version": "0.0.1"
},
"layout_aliases": {
"LAYOUT_ansi": "LAYOUT"
},
"layouts": {
"LAYOUT": {
"layout": [
{"label": "Esc", "matrix": [0, 0], "x": 0, "y": 0},
{"label": "1", "matrix": [0, 1], "x": 1, "y": 0},
{"label": "2", "matrix": [0, 2], "x": 2, "y": 0},
{"label": "3", "matrix": [0, 3], "x": 3, "y": 0},
{"label": "4", "matrix": [0, 4], "x": 4, "y": 0},
{"label": "5", "matrix": [0, 5], "x": 5, "y": 0},
{"label": "6", "matrix": [0, 6], "x": 6, "y": 0},
{"label": "7", "matrix": [0, 7], "x": 7, "y": 0},
{"label": "8", "matrix": [0, 8], "x": 8, "y": 0},
{"label": "9", "matrix": [0, 9], "x": 9, "y": 0},
{"label": "0", "matrix": [0, 10], "x": 10, "y": 0},
{"label": "-", "matrix": [0, 11], "x": 11, "y": 0},
{"label": "=", "matrix": [0, 12], "x": 12, "y": 0},
{"label": "Backspace", "matrix": [0, 13], "x": 13, "y": 0, "w": 2},
{"label": "Delete", "matrix": [0, 14], "x": 15.25, "y": 0},
{"label": "Tab", "matrix": [1, 0], "x": 0, "y": 1, "w": 1.5},
{"label": "Q", "matrix": [1, 1], "x": 1.5, "y": 1},
{"label": "W", "matrix": [1, 2], "x": 2.5, "y": 1},
{"label": "E", "matrix": [1, 3], "x": 3.5, "y": 1},
{"label": "R", "matrix": [1, 4], "x": 4.5, "y": 1},
{"label": "T", "matrix": [1, 5], "x": 5.5, "y": 1},
{"label": "Y", "matrix": [1, 6], "x": 6.5, "y": 1},
{"label": "U", "matrix": [1, 7], "x": 7.5, "y": 1},
{"label": "I", "matrix": [1, 8], "x": 8.5, "y": 1},
{"label": "O", "matrix": [1, 9], "x": 9.5, "y": 1},
{"label": "P", "matrix": [1, 10], "x": 10.5, "y": 1},
{"label": "[", "matrix": [1, 11], "x": 11.5, "y": 1},
{"label": "]", "matrix": [1, 12], "x": 12.5, "y": 1},
{"label": "\\", "matrix": [1, 13], "x": 13.5, "y": 1, "w": 1.5},
{"label": "Page Up", "matrix": [1, 14], "x": 15.25, "y": 1},
{"label": "Caps Lock", "matrix": [2, 0], "x": 0, "y": 2, "w": 1.75},
{"label": "A", "matrix": [2, 1], "x": 1.75, "y": 2},
{"label": "S", "matrix": [2, 2], "x": 2.75, "y": 2},
{"label": "D", "matrix": [2, 3], "x": 3.75, "y": 2},
{"label": "F", "matrix": [2, 4], "x": 4.75, "y": 2},
{"label": "G", "matrix": [2, 5], "x": 5.75, "y": 2},
{"label": "H", "matrix": [2, 6], "x": 6.75, "y": 2},
{"label": "J", "matrix": [2, 7], "x": 7.75, "y": 2},
{"label": "K", "matrix": [2, 8], "x": 8.75, "y": 2},
{"label": "L", "matrix": [2, 9], "x": 9.75, "y": 2},
{"label": ";", "matrix": [2, 10], "x": 10.75, "y": 2},
{"label": "'", "matrix": [2, 11], "x": 11.75, "y": 2},
{"label": "Enter", "matrix": [2, 13], "x": 12.75, "y": 2, "w": 2.25},
{"label": "Page Down", "matrix": [2, 14], "x": 15.25, "y": 2},
{"label": "Shift", "matrix": [3, 0], "x": 0, "y": 3, "w": 2.25},
{"label": "Z", "matrix": [3, 2], "x": 2.25, "y": 3},
{"label": "X", "matrix": [3, 3], "x": 3.25, "y": 3},
{"label": "C", "matrix": [3, 4], "x": 4.25, "y": 3},
{"label": "V", "matrix": [3, 5], "x": 5.25, "y": 3},
{"label": "B", "matrix": [3, 6], "x": 6.25, "y": 3},
{"label": "N", "matrix": [3, 7], "x": 7.25, "y": 3},
{"label": "M", "matrix": [3, 8], "x": 8.25, "y": 3},
{"label": ",", "matrix": [3, 9], "x": 9.25, "y": 3},
{"label": ".", "matrix": [3, 10], "x": 10.25, "y": 3},
{"label": "/", "matrix": [3, 11], "x": 11.25, "y": 3},
{"label": "Shift", "matrix": [3, 12], "x": 12.25, "y": 3, "w": 2},
{"label": "\u2191", "matrix": [3, 13], "x": 14.25, "y": 3},
{"label": "Ctrl", "matrix": [4, 0], "x": 0, "y": 4, "w": 1.25},
{"label": "GUI", "matrix": [4, 1], "x": 1.25, "y": 4, "w": 1.25},
{"label": "Alt", "matrix": [4, 2], "x": 2.5, "y": 4, "w": 1.25},
{"label": "Space", "matrix": [4, 5], "x": 3.75, "y": 4, "w": 6.25},
{"label": "Alt", "matrix": [4, 9], "x": 10, "y": 4},
{"label": "Fn", "matrix": [4, 10], "x": 11, "y": 4},
{"label": "Ctrl", "matrix": [4, 11], "x": 12, "y": 4, "w": 1.25},
{"label": "\u2190", "matrix": [4, 12], "x": 13.25, "y": 4},
{"label": "\u2193", "matrix": [4, 13], "x": 14.25, "y": 4},
{"label": "\u2192", "matrix": [4, 14], "x": 15.25, "y": 4}
]
}
}
}
@@ -0,0 +1,12 @@
// Copyright 2019 /u/KeepItUnder
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
// place overrides here
#define GRAVE_ESC_GUI_OVERRIDE
#define MK_3_SPEED
#define MK_C_OFFSET_UNMOD 400 /* Cursor offset per movement (unmodified) */
#define MK_C_INTERVAL_UNMOD 5 /* Time between cursor movements (unmodified) */
#define MK_W_OFFSET_UNMOD 100 /* Scroll steps per scroll action (unmodified) */
#define MK_W_INTERVAL_UNMOD 10 /* Time between scroll steps (unmodified) */
@@ -1,34 +1,17 @@
/* Copyright 2019 /u/KeepItUnder
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Copyright 2019 /u/KeepItUnder
// SPDX-License-Identifier: GPL-2.0-or-later
#include QMK_KEYBOARD_H
// LAYERS
enum Layer {
_QWERTY = 0, // Standard QWERTY layer
_FUNCTION, // Function key layer
_COLOUR // RGB key layer
_QWERTY,
_FUNCTION,
_COLOUR
};
#define _QW _QWERTY
#define _FN _FUNCTION
#define _CLR _COLOUR
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[_QWERTY] = LAYOUT_ansi(
// 2 3 4 5 6 7 8 9 10 11 12 13 14 15
[_QWERTY] = LAYOUT(
QK_GESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_DEL,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_PGUP,
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_PGDN,
@@ -36,15 +19,15 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(1), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT
),
[_FUNCTION] = LAYOUT_ansi(
[_FUNCTION] = LAYOUT(
KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, _______,
_______, MS_BTN1, MS_UP, MS_BTN2, MS_WHLU, _______, KC_INS, _______, KC_UP, KC_PAUS, KC_PGUP, KC_HOME, KC_PSCR, _______, KC_HOME,
_______, MS_LEFT, MS_DOWN, MS_RGHT, MS_WHLD, _______, KC_SCRL, KC_LEFT, KC_DOWN, KC_RGHT, KC_PGDN, KC_END, _______, KC_END,
_______, RM_TOGG, RM_NEXT, RM_HUEU, RM_HUED, RM_SATU, RM_SATD, KC_MUTE, KC_VOLD, KC_VOLU, _______, _______, _______,
_______, _______, _______, _______, MO(2), _______, _______, _______, _______, _______
_______, _______, _______, QK_BOOT, MO(2), _______, _______, _______, _______, _______
),
[_COLOUR] = LAYOUT_ansi(
[_COLOUR] = LAYOUT(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
+2 -15
View File
@@ -1,18 +1,5 @@
/* Copyright 2020 QMK
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Copyright 2020 QMK
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
+2 -16
View File
@@ -1,19 +1,5 @@
/*
Copyright 2019 /u/KeepItUnder
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Copyright 2019 /u/KeepItUnder
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
+23
View File
@@ -0,0 +1,23 @@
{
"manufacturer": "Ducky",
"maintainer": "f7urry",
"bootloader": "custom",
"usb": {
"vid": "0x445B"
},
"host": {
"default": {
"nkro": true
}
},
"matrix_pins": {
"cols": ["B10", "B9", "C13", "C12", "C11", "C10", "C9", "C8", "A15", "A14", "A13", "D0", "D1", "D2", "B15"],
"rows": ["D11", "B4", "B5", "B6", "B7"]
},
"diode_direction": "COL2ROW",
"features": {
"mousekey": true,
"extrakey": true,
"nkro": true
}
}
@@ -0,0 +1,91 @@
{
"keyboard_name": "One 2 SF ISO",
"usb": {
"pid": "0x07AE",
"device_version": "0.0.1"
},
"layout_aliases": {
"LAYOUT_iso": "LAYOUT"
},
"layouts": {
"LAYOUT": {
"layout": [
{"label": "Esc", "matrix": [0, 0], "x": 0, "y": 0},
{"label": "1", "matrix": [0, 1], "x": 1, "y": 0},
{"label": "2", "matrix": [0, 2], "x": 2, "y": 0},
{"label": "3", "matrix": [0, 3], "x": 3, "y": 0},
{"label": "4", "matrix": [0, 4], "x": 4, "y": 0},
{"label": "5", "matrix": [0, 5], "x": 5, "y": 0},
{"label": "6", "matrix": [0, 6], "x": 6, "y": 0},
{"label": "7", "matrix": [0, 7], "x": 7, "y": 0},
{"label": "8", "matrix": [0, 8], "x": 8, "y": 0},
{"label": "9", "matrix": [0, 9], "x": 9, "y": 0},
{"label": "0", "matrix": [0, 10], "x": 10, "y": 0},
{"label": "-", "matrix": [0, 11], "x": 11, "y": 0},
{"label": "=", "matrix": [0, 12], "x": 12, "y": 0},
{"label": "Backspace", "matrix": [0, 13], "x": 13, "y": 0, "w": 2},
{"label": "Delete", "matrix": [0, 14], "x": 15.25, "y": 0},
{"label": "Tab", "matrix": [1, 0], "x": 0, "y": 1, "w": 1.5},
{"label": "Q", "matrix": [1, 1], "x": 1.5, "y": 1},
{"label": "W", "matrix": [1, 2], "x": 2.5, "y": 1},
{"label": "E", "matrix": [1, 3], "x": 3.5, "y": 1},
{"label": "R", "matrix": [1, 4], "x": 4.5, "y": 1},
{"label": "T", "matrix": [1, 5], "x": 5.5, "y": 1},
{"label": "Y", "matrix": [1, 6], "x": 6.5, "y": 1},
{"label": "U", "matrix": [1, 7], "x": 7.5, "y": 1},
{"label": "I", "matrix": [1, 8], "x": 8.5, "y": 1},
{"label": "O", "matrix": [1, 9], "x": 9.5, "y": 1},
{"label": "P", "matrix": [1, 10], "x": 10.5, "y": 1},
{"label": "[", "matrix": [1, 11], "x": 11.5, "y": 1},
{"label": "]", "matrix": [1, 12], "x": 12.5, "y": 1},
{"label": "Page Up", "matrix": [1, 14], "x": 15.25, "y": 1},
{"label": "Caps Lock", "matrix": [2, 0], "x": 0, "y": 2, "w": 1.75},
{"label": "A", "matrix": [2, 1], "x": 1.75, "y": 2},
{"label": "S", "matrix": [2, 2], "x": 2.75, "y": 2},
{"label": "D", "matrix": [2, 3], "x": 3.75, "y": 2},
{"label": "F", "matrix": [2, 4], "x": 4.75, "y": 2},
{"label": "G", "matrix": [2, 5], "x": 5.75, "y": 2},
{"label": "H", "matrix": [2, 6], "x": 6.75, "y": 2},
{"label": "J", "matrix": [2, 7], "x": 7.75, "y": 2},
{"label": "K", "matrix": [2, 8], "x": 8.75, "y": 2},
{"label": "L", "matrix": [2, 9], "x": 9.75, "y": 2},
{"label": ";", "matrix": [2, 10], "x": 10.75, "y": 2},
{"label": "'", "matrix": [2, 11], "x": 11.75, "y": 2},
{"label": "#", "matrix": [2, 12], "x": 12.75, "y": 2},
{"label": "Enter", "matrix": [2, 13], "x": 13.75, "y": 1, "w": 1.25, "h": 2},
{"label": "Page Down", "matrix": [2, 14], "x": 15.25, "y": 2},
{"label": "Shift", "matrix": [3, 0], "x": 0, "y": 3, "w": 1.25},
{"label": "\\", "matrix": [3, 1], "x": 1.25, "y": 3},
{"label": "Z", "matrix": [3, 2], "x": 2.25, "y": 3},
{"label": "X", "matrix": [3, 3], "x": 3.25, "y": 3},
{"label": "C", "matrix": [3, 4], "x": 4.25, "y": 3},
{"label": "V", "matrix": [3, 5], "x": 5.25, "y": 3},
{"label": "B", "matrix": [3, 6], "x": 6.25, "y": 3},
{"label": "N", "matrix": [3, 7], "x": 7.25, "y": 3},
{"label": "M", "matrix": [3, 8], "x": 8.25, "y": 3},
{"label": ",", "matrix": [3, 9], "x": 9.25, "y": 3},
{"label": ".", "matrix": [3, 10], "x": 10.25, "y": 3},
{"label": "/", "matrix": [3, 11], "x": 11.25, "y": 3},
{"label": "Shift", "matrix": [3, 12], "x": 12.25, "y": 3, "w": 2},
{"label": "\u2191", "matrix": [3, 13], "x": 14.25, "y": 3},
{"label": "Ctrl", "matrix": [4, 0], "x": 0, "y": 4, "w": 1.25},
{"label": "GUI", "matrix": [4, 1], "x": 1.25, "y": 4, "w": 1.25},
{"label": "Alt", "matrix": [4, 2], "x": 2.5, "y": 4, "w": 1.25},
{"label": "Space", "matrix": [4, 5], "x": 3.75, "y": 4, "w": 6.25},
{"label": "Alt", "matrix": [4, 9], "x": 10, "y": 4},
{"label": "Fn", "matrix": [4, 10], "x": 11, "y": 4},
{"label": "Ctrl", "matrix": [4, 11], "x": 12, "y": 4, "w": 1.25},
{"label": "\u2190", "matrix": [4, 12], "x": 13.25, "y": 4},
{"label": "\u2193", "matrix": [4, 13], "x": 14.25, "y": 4},
{"label": "\u2192", "matrix": [4, 14], "x": 15.25, "y": 4}
]
}
}
}
@@ -0,0 +1,12 @@
// Copyright 2019 /u/KeepItUnder
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
// place overrides here
#define GRAVE_ESC_GUI_OVERRIDE
#define MK_3_SPEED
#define MK_C_OFFSET_UNMOD 400 /* Cursor offset per movement (unmodified) */
#define MK_C_INTERVAL_UNMOD 5 /* Time between cursor movements (unmodified) */
#define MK_W_OFFSET_UNMOD 100 /* Scroll steps per scroll action (unmodified) */
#define MK_W_INTERVAL_UNMOD 10 /* Time between scroll steps (unmodified) */
@@ -1,34 +1,17 @@
/* Copyright 2019 /u/KeepItUnder
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Copyright 2019 /u/KeepItUnder
// SPDX-License-Identifier: GPL-2.0-or-later
#include QMK_KEYBOARD_H
// LAYERS
enum Layer {
_QWERTY = 0, // Standard QWERTY layer
_FUNCTION, // Function key layer
_COLOUR // RGB key layer
_QWERTY,
_FUNCTION,
_COLOUR
};
#define _QW _QWERTY
#define _FN _FUNCTION
#define _CLR _COLOUR
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[_QWERTY] = LAYOUT_iso(
// 2 3 4 5 6 7 8 9 10 11 12 13 14 15
[_QWERTY] = LAYOUT(
QK_GESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_DEL,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_PGUP,
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_NUHS, KC_ENT, KC_PGDN,
@@ -36,15 +19,15 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(1), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT
),
[_FUNCTION] = LAYOUT_iso(
[_FUNCTION] = LAYOUT(
KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, _______,
_______, MS_BTN1, MS_UP, MS_BTN2, MS_WHLU, _______, KC_INS, _______, KC_UP, KC_PAUS, KC_PGUP, KC_HOME, KC_PSCR, KC_HOME,
_______, MS_LEFT, MS_DOWN, MS_RGHT, MS_WHLD, _______, KC_SCRL, KC_LEFT, KC_DOWN, KC_RGHT, KC_PGDN, KC_END, _______, _______, KC_END,
_______, _______, RM_TOGG, RM_NEXT, RM_HUEU, RM_HUED, RM_SATU, RM_SATD, KC_MUTE, KC_VOLD, KC_VOLU, _______, _______, _______,
_______, _______, _______, _______, MO(2), _______, _______, _______, _______, _______
_______, _______, _______, QK_BOOT, MO(2), _______, _______, _______, _______, _______
),
[_COLOUR] = LAYOUT_iso(
[_COLOUR] = LAYOUT(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
-269
View File
@@ -1,269 +0,0 @@
{
"keyboard_name": "One 2 SF",
"manufacturer": "Ducky",
"maintainer": "f7urry",
"usb": {
"vid": "0x445B",
"pid": "0x07AF",
"device_version": "0.0.1"
},
"host": {
"default": {
"nkro": true
}
},
"matrix_pins": {
"cols": ["B10", "B9", "C13", "C12", "C11", "C10", "C9", "C8", "A15", "A14", "A13", "D0", "D1", "D2", "B15", "B8"],
"rows": ["D11", "B4", "B5", "B6", "B7"]
},
"diode_direction": "COL2ROW",
"dip_switch": {
"matrix_grid": [ [0,14], [1,14], [2,14], [3,14] ]
},
"features": {
"bootmagic": true,
"mousekey": true,
"extrakey": true,
"nkro": true,
"dip_switch": true
},
"layouts": {
"LAYOUT_all": {
"layout": [
{"label": "Esc", "matrix": [0, 0], "x": 0, "y": 0},
{"label": "1", "matrix": [0, 1], "x": 1, "y": 0},
{"label": "2", "matrix": [0, 2], "x": 2, "y": 0},
{"label": "3", "matrix": [0, 3], "x": 3, "y": 0},
{"label": "4", "matrix": [0, 4], "x": 4, "y": 0},
{"label": "5", "matrix": [0, 5], "x": 5, "y": 0},
{"label": "6", "matrix": [0, 6], "x": 6, "y": 0},
{"label": "7", "matrix": [0, 7], "x": 7, "y": 0},
{"label": "8", "matrix": [0, 8], "x": 8, "y": 0},
{"label": "9", "matrix": [0, 9], "x": 9, "y": 0},
{"label": "0", "matrix": [0, 10], "x": 10, "y": 0},
{"label": "-", "matrix": [0, 11], "x": 11, "y": 0},
{"label": "=", "matrix": [0, 12], "x": 12, "y": 0},
{"label": "Backspace", "matrix": [0, 13], "x": 13, "y": 0, "w": 2},
{"label": "Delete", "matrix": [0, 14], "x": 15.25, "y": 0},
{"label": "Tab", "matrix": [1, 0], "x": 0, "y": 1, "w": 1.5},
{"label": "Q", "matrix": [1, 1], "x": 1.5, "y": 1},
{"label": "W", "matrix": [1, 2], "x": 2.5, "y": 1},
{"label": "E", "matrix": [1, 3], "x": 3.5, "y": 1},
{"label": "R", "matrix": [1, 4], "x": 4.5, "y": 1},
{"label": "T", "matrix": [1, 5], "x": 5.5, "y": 1},
{"label": "Y", "matrix": [1, 6], "x": 6.5, "y": 1},
{"label": "U", "matrix": [1, 7], "x": 7.5, "y": 1},
{"label": "I", "matrix": [1, 8], "x": 8.5, "y": 1},
{"label": "O", "matrix": [1, 9], "x": 9.5, "y": 1},
{"label": "P", "matrix": [1, 10], "x": 10.5, "y": 1},
{"label": "[", "matrix": [1, 11], "x": 11.5, "y": 1},
{"label": "]", "matrix": [1, 12], "x": 12.5, "y": 1},
{"label": "\\", "matrix": [1, 13], "x": 13.5, "y": 1, "w": 1.5},
{"label": "Page Up", "matrix": [1, 14], "x": 15.25, "y": 1},
{"label": "Caps Lock", "matrix": [2, 0], "x": 0, "y": 2, "w": 1.75},
{"label": "A", "matrix": [2, 1], "x": 1.75, "y": 2},
{"label": "S", "matrix": [2, 2], "x": 2.75, "y": 2},
{"label": "D", "matrix": [2, 3], "x": 3.75, "y": 2},
{"label": "F", "matrix": [2, 4], "x": 4.75, "y": 2},
{"label": "G", "matrix": [2, 5], "x": 5.75, "y": 2},
{"label": "H", "matrix": [2, 6], "x": 6.75, "y": 2},
{"label": "J", "matrix": [2, 7], "x": 7.75, "y": 2},
{"label": "K", "matrix": [2, 8], "x": 8.75, "y": 2},
{"label": "L", "matrix": [2, 9], "x": 9.75, "y": 2},
{"label": ";", "matrix": [2, 10], "x": 10.75, "y": 2},
{"label": "'", "matrix": [2, 11], "x": 11.75, "y": 2},
{"label": "#", "matrix": [2, 12], "x": 12.75, "y": 2},
{"label": "Enter", "matrix": [2, 13], "x": 13.75, "y": 2, "w": 1.25},
{"label": "Page Down", "matrix": [2, 14], "x": 15.25, "y": 2},
{"label": "Shift", "matrix": [3, 0], "x": 0, "y": 3, "w": 1.25},
{"label": "\\", "matrix": [3, 1], "x": 1.25, "y": 3},
{"label": "Z", "matrix": [3, 2], "x": 2.25, "y": 3},
{"label": "X", "matrix": [3, 3], "x": 3.25, "y": 3},
{"label": "C", "matrix": [3, 4], "x": 4.25, "y": 3},
{"label": "V", "matrix": [3, 5], "x": 5.25, "y": 3},
{"label": "B", "matrix": [3, 6], "x": 6.25, "y": 3},
{"label": "N", "matrix": [3, 7], "x": 7.25, "y": 3},
{"label": "M", "matrix": [3, 8], "x": 8.25, "y": 3},
{"label": ",", "matrix": [3, 9], "x": 9.25, "y": 3},
{"label": ".", "matrix": [3, 10], "x": 10.25, "y": 3},
{"label": "/", "matrix": [3, 11], "x": 11.25, "y": 3},
{"label": "Shift", "matrix": [3, 12], "x": 12.25, "y": 3, "w": 2},
{"label": "\u2191", "matrix": [3, 13], "x": 14.25, "y": 3},
{"label": "Ctrl", "matrix": [4, 0], "x": 0, "y": 4, "w": 1.25},
{"label": "GUI", "matrix": [4, 1], "x": 1.25, "y": 4, "w": 1.25},
{"label": "Alt", "matrix": [4, 2], "x": 2.5, "y": 4, "w": 1.25},
{"label": "Space", "matrix": [4, 5], "x": 3.75, "y": 4, "w": 6.25},
{"label": "Alt", "matrix": [4, 9], "x": 10, "y": 4},
{"label": "Fn", "matrix": [4, 10], "x": 11, "y": 4},
{"label": "Ctrl", "matrix": [4, 11], "x": 12, "y": 4, "w": 1.25},
{"label": "\u2190", "matrix": [4, 12], "x": 13.25, "y": 4},
{"label": "\u2193", "matrix": [4, 13], "x": 14.25, "y": 4},
{"label": "\u2192", "matrix": [4, 14], "x": 15.25, "y": 4}
]
},
"LAYOUT_ansi": {
"layout": [
{"label": "Esc", "matrix": [0, 0], "x": 0, "y": 0},
{"label": "1", "matrix": [0, 1], "x": 1, "y": 0},
{"label": "2", "matrix": [0, 2], "x": 2, "y": 0},
{"label": "3", "matrix": [0, 3], "x": 3, "y": 0},
{"label": "4", "matrix": [0, 4], "x": 4, "y": 0},
{"label": "5", "matrix": [0, 5], "x": 5, "y": 0},
{"label": "6", "matrix": [0, 6], "x": 6, "y": 0},
{"label": "7", "matrix": [0, 7], "x": 7, "y": 0},
{"label": "8", "matrix": [0, 8], "x": 8, "y": 0},
{"label": "9", "matrix": [0, 9], "x": 9, "y": 0},
{"label": "0", "matrix": [0, 10], "x": 10, "y": 0},
{"label": "-", "matrix": [0, 11], "x": 11, "y": 0},
{"label": "=", "matrix": [0, 12], "x": 12, "y": 0},
{"label": "Backspace", "matrix": [0, 13], "x": 13, "y": 0, "w": 2},
{"label": "Delete", "matrix": [0, 14], "x": 15.25, "y": 0},
{"label": "Tab", "matrix": [1, 0], "x": 0, "y": 1, "w": 1.5},
{"label": "Q", "matrix": [1, 1], "x": 1.5, "y": 1},
{"label": "W", "matrix": [1, 2], "x": 2.5, "y": 1},
{"label": "E", "matrix": [1, 3], "x": 3.5, "y": 1},
{"label": "R", "matrix": [1, 4], "x": 4.5, "y": 1},
{"label": "T", "matrix": [1, 5], "x": 5.5, "y": 1},
{"label": "Y", "matrix": [1, 6], "x": 6.5, "y": 1},
{"label": "U", "matrix": [1, 7], "x": 7.5, "y": 1},
{"label": "I", "matrix": [1, 8], "x": 8.5, "y": 1},
{"label": "O", "matrix": [1, 9], "x": 9.5, "y": 1},
{"label": "P", "matrix": [1, 10], "x": 10.5, "y": 1},
{"label": "[", "matrix": [1, 11], "x": 11.5, "y": 1},
{"label": "]", "matrix": [1, 12], "x": 12.5, "y": 1},
{"label": "\\", "matrix": [1, 13], "x": 13.5, "y": 1, "w": 1.5},
{"label": "Page Up", "matrix": [1, 14], "x": 15.25, "y": 1},
{"label": "Caps Lock", "matrix": [2, 0], "x": 0, "y": 2, "w": 1.75},
{"label": "A", "matrix": [2, 1], "x": 1.75, "y": 2},
{"label": "S", "matrix": [2, 2], "x": 2.75, "y": 2},
{"label": "D", "matrix": [2, 3], "x": 3.75, "y": 2},
{"label": "F", "matrix": [2, 4], "x": 4.75, "y": 2},
{"label": "G", "matrix": [2, 5], "x": 5.75, "y": 2},
{"label": "H", "matrix": [2, 6], "x": 6.75, "y": 2},
{"label": "J", "matrix": [2, 7], "x": 7.75, "y": 2},
{"label": "K", "matrix": [2, 8], "x": 8.75, "y": 2},
{"label": "L", "matrix": [2, 9], "x": 9.75, "y": 2},
{"label": ";", "matrix": [2, 10], "x": 10.75, "y": 2},
{"label": "'", "matrix": [2, 11], "x": 11.75, "y": 2},
{"label": "Enter", "matrix": [2, 13], "x": 12.75, "y": 2, "w": 2.25},
{"label": "Page Down", "matrix": [2, 14], "x": 15.25, "y": 2},
{"label": "Shift", "matrix": [3, 0], "x": 0, "y": 3, "w": 2.25},
{"label": "Z", "matrix": [3, 2], "x": 2.25, "y": 3},
{"label": "X", "matrix": [3, 3], "x": 3.25, "y": 3},
{"label": "C", "matrix": [3, 4], "x": 4.25, "y": 3},
{"label": "V", "matrix": [3, 5], "x": 5.25, "y": 3},
{"label": "B", "matrix": [3, 6], "x": 6.25, "y": 3},
{"label": "N", "matrix": [3, 7], "x": 7.25, "y": 3},
{"label": "M", "matrix": [3, 8], "x": 8.25, "y": 3},
{"label": ",", "matrix": [3, 9], "x": 9.25, "y": 3},
{"label": ".", "matrix": [3, 10], "x": 10.25, "y": 3},
{"label": "/", "matrix": [3, 11], "x": 11.25, "y": 3},
{"label": "Shift", "matrix": [3, 12], "x": 12.25, "y": 3, "w": 2},
{"label": "\u2191", "matrix": [3, 13], "x": 14.25, "y": 3},
{"label": "Ctrl", "matrix": [4, 0], "x": 0, "y": 4, "w": 1.25},
{"label": "GUI", "matrix": [4, 1], "x": 1.25, "y": 4, "w": 1.25},
{"label": "Alt", "matrix": [4, 2], "x": 2.5, "y": 4, "w": 1.25},
{"label": "Space", "matrix": [4, 5], "x": 3.75, "y": 4, "w": 6.25},
{"label": "Alt", "matrix": [4, 9], "x": 10, "y": 4},
{"label": "Fn", "matrix": [4, 10], "x": 11, "y": 4},
{"label": "Ctrl", "matrix": [4, 11], "x": 12, "y": 4, "w": 1.25},
{"label": "\u2190", "matrix": [4, 12], "x": 13.25, "y": 4},
{"label": "\u2193", "matrix": [4, 13], "x": 14.25, "y": 4},
{"label": "\u2192", "matrix": [4, 14], "x": 15.25, "y": 4}
]
},
"LAYOUT_iso": {
"layout": [
{"label": "Esc", "matrix": [0, 0], "x": 0, "y": 0},
{"label": "1", "matrix": [0, 1], "x": 1, "y": 0},
{"label": "2", "matrix": [0, 2], "x": 2, "y": 0},
{"label": "3", "matrix": [0, 3], "x": 3, "y": 0},
{"label": "4", "matrix": [0, 4], "x": 4, "y": 0},
{"label": "5", "matrix": [0, 5], "x": 5, "y": 0},
{"label": "6", "matrix": [0, 6], "x": 6, "y": 0},
{"label": "7", "matrix": [0, 7], "x": 7, "y": 0},
{"label": "8", "matrix": [0, 8], "x": 8, "y": 0},
{"label": "9", "matrix": [0, 9], "x": 9, "y": 0},
{"label": "0", "matrix": [0, 10], "x": 10, "y": 0},
{"label": "-", "matrix": [0, 11], "x": 11, "y": 0},
{"label": "=", "matrix": [0, 12], "x": 12, "y": 0},
{"label": "Backspace", "matrix": [0, 13], "x": 13, "y": 0, "w": 2},
{"label": "Delete", "matrix": [0, 14], "x": 15.25, "y": 0},
{"label": "Tab", "matrix": [1, 0], "x": 0, "y": 1, "w": 1.5},
{"label": "Q", "matrix": [1, 1], "x": 1.5, "y": 1},
{"label": "W", "matrix": [1, 2], "x": 2.5, "y": 1},
{"label": "E", "matrix": [1, 3], "x": 3.5, "y": 1},
{"label": "R", "matrix": [1, 4], "x": 4.5, "y": 1},
{"label": "T", "matrix": [1, 5], "x": 5.5, "y": 1},
{"label": "Y", "matrix": [1, 6], "x": 6.5, "y": 1},
{"label": "U", "matrix": [1, 7], "x": 7.5, "y": 1},
{"label": "I", "matrix": [1, 8], "x": 8.5, "y": 1},
{"label": "O", "matrix": [1, 9], "x": 9.5, "y": 1},
{"label": "P", "matrix": [1, 10], "x": 10.5, "y": 1},
{"label": "[", "matrix": [1, 11], "x": 11.5, "y": 1},
{"label": "]", "matrix": [1, 12], "x": 12.5, "y": 1},
{"label": "Page Up", "matrix": [1, 14], "x": 15.25, "y": 1},
{"label": "Caps Lock", "matrix": [2, 0], "x": 0, "y": 2, "w": 1.75},
{"label": "A", "matrix": [2, 1], "x": 1.75, "y": 2},
{"label": "S", "matrix": [2, 2], "x": 2.75, "y": 2},
{"label": "D", "matrix": [2, 3], "x": 3.75, "y": 2},
{"label": "F", "matrix": [2, 4], "x": 4.75, "y": 2},
{"label": "G", "matrix": [2, 5], "x": 5.75, "y": 2},
{"label": "H", "matrix": [2, 6], "x": 6.75, "y": 2},
{"label": "J", "matrix": [2, 7], "x": 7.75, "y": 2},
{"label": "K", "matrix": [2, 8], "x": 8.75, "y": 2},
{"label": "L", "matrix": [2, 9], "x": 9.75, "y": 2},
{"label": ";", "matrix": [2, 10], "x": 10.75, "y": 2},
{"label": "'", "matrix": [2, 11], "x": 11.75, "y": 2},
{"label": "#", "matrix": [2, 12], "x": 12.75, "y": 2},
{"label": "Enter", "matrix": [2, 13], "x": 13.75, "y": 1, "w": 1.25, "h": 2},
{"label": "Page Down", "matrix": [2, 14], "x": 15.25, "y": 2},
{"label": "Shift", "matrix": [3, 0], "x": 0, "y": 3, "w": 1.25},
{"label": "\\", "matrix": [3, 1], "x": 1.25, "y": 3},
{"label": "Z", "matrix": [3, 2], "x": 2.25, "y": 3},
{"label": "X", "matrix": [3, 3], "x": 3.25, "y": 3},
{"label": "C", "matrix": [3, 4], "x": 4.25, "y": 3},
{"label": "V", "matrix": [3, 5], "x": 5.25, "y": 3},
{"label": "B", "matrix": [3, 6], "x": 6.25, "y": 3},
{"label": "N", "matrix": [3, 7], "x": 7.25, "y": 3},
{"label": "M", "matrix": [3, 8], "x": 8.25, "y": 3},
{"label": ",", "matrix": [3, 9], "x": 9.25, "y": 3},
{"label": ".", "matrix": [3, 10], "x": 10.25, "y": 3},
{"label": "/", "matrix": [3, 11], "x": 11.25, "y": 3},
{"label": "Shift", "matrix": [3, 12], "x": 12.25, "y": 3, "w": 2},
{"label": "\u2191", "matrix": [3, 13], "x": 14.25, "y": 3},
{"label": "Ctrl", "matrix": [4, 0], "x": 0, "y": 4, "w": 1.25},
{"label": "GUI", "matrix": [4, 1], "x": 1.25, "y": 4, "w": 1.25},
{"label": "Alt", "matrix": [4, 2], "x": 2.5, "y": 4, "w": 1.25},
{"label": "Space", "matrix": [4, 5], "x": 3.75, "y": 4, "w": 6.25},
{"label": "Alt", "matrix": [4, 9], "x": 10, "y": 4},
{"label": "Fn", "matrix": [4, 10], "x": 11, "y": 4},
{"label": "Ctrl", "matrix": [4, 11], "x": 12, "y": 4, "w": 1.25},
{"label": "\u2190", "matrix": [4, 12], "x": 13.25, "y": 4},
{"label": "\u2193", "matrix": [4, 13], "x": 14.25, "y": 4},
{"label": "\u2192", "matrix": [4, 14], "x": 15.25, "y": 4}
]
}
}
}
@@ -1,18 +0,0 @@
# Matrix Diagram for Ducky One 2 SF
```
┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐┌───┐
│00 │01 │02 │03 │04 │05 │06 │07 │08 │09 │0A │0B │0C │0D ││0E │
├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤├───┤ ┌─────┐
│10 │11 │12 │13 │14 │15 │16 │17 │18 │19 │1A │1B │1C │1D ││1E │ │ │
├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤├───┤ ┌──┴┐2D │
│20 │21 │22 │23 │24 │25 │26 │27 │28 │29 │2A │2B │2D ││2E │ │2C │ │
├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─────┬──┴┼───┘ └───┴────┘
│30 │31 │32 │33 │34 │35 │36 │37 │38 │39 │3A │3B │3C │3D │ ISO Enter
├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴──┬┴──┬┴───┬───┼───┼───┐
│40 │41 │42 │45 │49 │4A │4B │4C │4D │4E │
└────┴────┴────┴────────────────────────┴───┴───┴────┴───┴───┴───┘
┌────────┐
│30 │ 2.25u LShift
└────────┘
```
+1 -1
View File
@@ -43,7 +43,7 @@
#define NUC123_USB_USE_USB0 TRUE
#define NUC123_USB_USE_USB1 TRUE
#define NUC123_SERIAL_USE_UART0 TRUE
#define NUC123_SERIAL_USE_UART0 FALSE
#define NUC123_SERIAL_CLKSRC NUC123_SERIAL_CLKSRC_HSI
#define NUC123_MCUCONF
+10 -7
View File
@@ -2,18 +2,16 @@
A 65% keyboard by Ducky.
This firmware was tested on the Ducky One 2 SF 1967ST version.
* Keyboard Maintainer: [f7urry](https://github.com/f7urry)
* Hardware Supported: Ducky One 2 SF RGB (DKON1967ST), NUC123SD4AN0 + MBI5043GP
* Only ANSI layout is supported at this time
* ISO compiles but is **untested**
* VIA still WIP.
* RGB LEDs are currently disabled until the driver is merged.
* DIP switches are disabled due to hardware incompatibilities
## Compiling the Firmware:
make ducky/one2sf/1967st:default
make ducky/one2sf/1967st/ansi:default
make ducky/one2sf/1967st/iso:default
## Accessing Bootloader Mode
@@ -24,11 +22,16 @@ To enter the 1967ST bootloader to flash, boot the keyboard while holding D+L.
There are then two ways to flash the keyboard:
pip install --user nuvoton-isp
nuvoisp -f ducky_one2sf_ansi.bin
nuvoisp -f ducky_one2sf_1967st_ansi_default.bin
Alternatively you can use elfmimi's [nu-isp-cli](https://lib.rs/crates/nu-isp-cli) which is more complete than nuvoisp and allows flashing .hex files as well.
cargo install nu-isp-cli
nu-isp-cli flash ducky_one2sf_ansi.bin
nu-isp-cli flash ducky_one2sf_1967st_ansi_default.bin
or
make ducky/one2sf/1967st/ansi:default:flash
make ducky/one2sf/1967st/iso:default:flash
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
+3
View File
@@ -15,3 +15,6 @@ BOARD = NUC123SD4AN0
MCU = cortex-m0
# ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
ARMV = 6
# Needs elevated access to 0416:3f00 on Linux
PROGRAM_CMD = nu-isp-cli flash $(BUILD_DIR)/$(TARGET).bin
@@ -1,25 +0,0 @@
/* Copyright 2019 /u/KeepItUnder
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
// place overrides here
#define GRAVE_ESC_GUI_OVERRIDE
#define MK_3_SPEED
#define MK_C_OFFSET_UNMOD 400 /* Cursor offset per movement (unmodified) */
#define MK_C_INTERVAL_UNMOD 5 /* Time between cursor movements (unmodified) */
#define MK_W_OFFSET_UNMOD 100 /* Scroll steps per scroll action (unmodified) */
#define MK_W_INTERVAL_UNMOD 10 /* Time between scroll steps (unmodified) */
@@ -1,55 +0,0 @@
/* Copyright 2019 /u/KeepItUnder
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include QMK_KEYBOARD_H
// LAYERS
enum Layer {
_QWERTY = 0, // Standard QWERTY layer
_FUNCTION, // Function key layer
_COLOUR // RGB key layer
};
#define _QW _QWERTY
#define _FN _FUNCTION
#define _CLR _COLOUR
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[_QWERTY] = LAYOUT_all(
// 2 3 4 5 6 7 8 9 10 11 12 13 14 15
QK_GESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_DEL,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_PGUP,
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_NUHS, KC_ENT, KC_PGDN,
KC_LSFT, KC_NUBS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP,
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(1), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT
),
[_FUNCTION] = LAYOUT_all(
KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, _______,
_______, MS_BTN1, MS_UP, MS_BTN2, MS_WHLU, _______, KC_INS, _______, KC_UP, KC_PAUSE, KC_PGUP, KC_HOME, KC_PSCR, _______, KC_HOME,
_______, MS_LEFT, MS_DOWN, MS_RGHT, MS_WHLD, _______, KC_SCRL, KC_LEFT, KC_DOWN, KC_RIGHT, KC_PGDN, KC_END, _______, _______, KC_END,
_______, _______, RM_TOGG, RM_NEXT, RM_HUEU, RM_HUED, RM_SATU, RM_SATD, KC_MUTE, KC_VOLD, KC_VOLU, _______, _______, _______,
_______, _______, _______, _______, MO(2), _______, _______, _______, _______, _______
),
[_COLOUR] = LAYOUT_all(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, RM_TOGG, RM_NEXT, RM_HUEU, RM_HUED, RM_SATU, RM_SATD, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______
),
};
-24
View File
@@ -152,27 +152,3 @@ const aw20216s_led_t PROGMEM g_aw20216s_leds[AW20216S_LED_COUNT] = {
{1, SW10_CS16, SW10_CS17, SW10_CS18} // 120, LED 20
};
#endif
#ifdef EEPROM_ENABLE
#include "spi_master.h"
void spi_init(void) {
static bool is_initialised = false;
if (!is_initialised) {
is_initialised = true;
// Try releasing special pins for a short time
gpio_set_pin_input(SPI_SCK_PIN);
gpio_set_pin_input(SPI_MOSI_PIN);
gpio_set_pin_input(SPI_MISO_PIN);
chThdSleepMilliseconds(10);
palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), PAL_MODE_ALTERNATE(SPI_SCK_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST | PAL_WB32_CURRENT_LEVEL3);
palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), PAL_MODE_ALTERNATE(SPI_MOSI_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST);
palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), PAL_MODE_ALTERNATE(SPI_MISO_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST);
}
}
#endif
-24
View File
@@ -153,27 +153,3 @@ const aw20216s_led_t PROGMEM g_aw20216s_leds[AW20216S_LED_COUNT] = {
{1, SW10_CS16, SW10_CS17, SW10_CS18} // 120, LED 20
};
#endif
#ifdef EEPROM_ENABLE
#include "spi_master.h"
void spi_init(void) {
static bool is_initialised = false;
if (!is_initialised) {
is_initialised = true;
// Try releasing special pins for a short time
gpio_set_pin_input(SPI_SCK_PIN);
gpio_set_pin_input(SPI_MOSI_PIN);
gpio_set_pin_input(SPI_MISO_PIN);
chThdSleepMilliseconds(10);
palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), PAL_MODE_ALTERNATE(SPI_SCK_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST | PAL_WB32_CURRENT_LEVEL3);
palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), PAL_MODE_ALTERNATE(SPI_MOSI_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST);
palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), PAL_MODE_ALTERNATE(SPI_MISO_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST);
}
}
#endif
@@ -0,0 +1,13 @@
// Copyright 2026 QMK
// SPDX-License-Identifier: GPL-2.0-or-later
#include QMK_KEYBOARD_H
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {LAYOUT_ortho_1x1(KC_A)};
void keyboard_post_init_user(void) {
// Customise these values to desired behaviour
debug_enable = true;
debug_matrix = true;
// debug_keyboard=true;
// debug_mouse=true;
}
@@ -0,0 +1,10 @@
{
"config": {
"features": {
"console": true
}
},
"modules": [
"qmk/nvm_test"
]
}
@@ -0,0 +1,40 @@
// Copyright 2026 QMK
// SPDX-License-Identifier: GPL-2.0-or-later
#include QMK_KEYBOARD_H
#include "virtser.h"
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
LAYOUT_ortho_1x1(KC_A)
};
static uint32_t counter = 0;
void virtser_recv(const uint8_t ch) {
static const char *lut = "0123456789ABCDEF";
counter++;
virtser_send(lut[(ch & 0xF0) >> 4]);
virtser_send(lut[ch & 0xF]);
}
#ifdef CONSOLE_ENABLE
void keyboard_post_init_user(void) {
// Customise these values to desired behaviour
debug_enable = true;
// debug_matrix=true;
// debug_keyboard=true;
// debug_mouse=true;
}
void housekeeping_task_user(void) {
static uint32_t last = 0;
if (timer_elapsed32(last) > 1000) {
uprintf("recv: %ld!\n", counter);
last = timer_read32();
}
}
#endif
@@ -0,0 +1,12 @@
{
"config": {
"usb": {
"shared_endpoint": {
"keyboard": true
}
},
"features": {
"virtser": true
}
}
}
@@ -0,0 +1,12 @@
// Copyright 2026 ToYoNiX <toyonix.assemmohamed.2005@gmail.com>
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
// Split configuration
#define SPLIT_HAND_PIN_LOW_IS_LEFT
// Enable full duplex operation mode
#define SERIAL_USART_FULL_DUPLEX
#define SERIAL_USART_TX_PIN B6
#define SERIAL_USART_RX_PIN B7
@@ -0,0 +1,9 @@
// Copyright 2024 zvecr <git@zvecr.com>
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#define HAL_USE_SERIAL TRUE
#define SERIAL_USB_BUFFERS_SIZE 256
#include_next <halconf.h>
@@ -0,0 +1,102 @@
{
"manufacturer": "Assem Mohamed",
"keyboard_name": "handwired/tnx_corne_f401",
"maintainer": "ToYoNiX",
"development_board": "blackpill_f401",
"bootloader": "tinyuf2",
"diode_direction": "COL2ROW",
"encoder": {
"rotary": [
{"pin_a": "B9", "pin_b": "B8", "resolution": 2}
]
},
"split": {
"enabled": true,
"handedness": {
"pin": "C13"
},
"serial": {
"driver": "usart"
},
"transport": {
"watchdog": true
},
"encoder": {
"right": {
"rotary": [
{"pin_a": "B9", "pin_b": "B8", "resolution": 2}
]
}
}
},
"features": {
"bootmagic": true,
"extrakey": true,
"encoder": true,
"mousekey": true,
"nkro": true
},
"host": {
"default": {
"nkro": true
}
},
"matrix_pins": {
"cols": ["A8", "B15", "B14", "B13", "B12"],
"rows": ["B0", "A5", "A4", "A3"]
},
"usb": {
"device_version": "1.0.0",
"pid": "0x544E",
"vid": "0x4B42"
},
"layouts": {
"LAYOUT_split_3x5_3": {
"layout": [
{"matrix": [0, 0], "x": 0, "y": 0.3},
{"matrix": [0, 1], "x": 1, "y": 0.1},
{"matrix": [0, 2], "x": 2, "y": 0},
{"matrix": [0, 3], "x": 3, "y": 0.1},
{"matrix": [0, 4], "x": 4, "y": 0.2},
{"matrix": [4, 4], "x": 8, "y": 0.2},
{"matrix": [4, 3], "x": 9, "y": 0.1},
{"matrix": [4, 2], "x": 10, "y": 0},
{"matrix": [4, 1], "x": 11, "y": 0.1},
{"matrix": [4, 0], "x": 12, "y": 0.3},
{"matrix": [1, 0], "x": 0, "y": 1.3},
{"matrix": [1, 1], "x": 1, "y": 1.1},
{"matrix": [1, 2], "x": 2, "y": 1},
{"matrix": [1, 3], "x": 3, "y": 1.1},
{"matrix": [1, 4], "x": 4, "y": 1.2},
{"matrix": [5, 4], "x": 8, "y": 1.2},
{"matrix": [5, 3], "x": 9, "y": 1.1},
{"matrix": [5, 2], "x": 10, "y": 1},
{"matrix": [5, 1], "x": 11, "y": 1.1},
{"matrix": [5, 0], "x": 12, "y": 1.3},
{"matrix": [2, 0], "x": 0, "y": 2.3},
{"matrix": [2, 1], "x": 1, "y": 2.1},
{"matrix": [2, 2], "x": 2, "y": 2},
{"matrix": [2, 3], "x": 3, "y": 2.1},
{"matrix": [2, 4], "x": 4, "y": 2.2},
{"matrix": [6, 4], "x": 8, "y": 2.2},
{"matrix": [6, 3], "x": 9, "y": 2.1},
{"matrix": [6, 2], "x": 10, "y": 2},
{"matrix": [6, 1], "x": 11, "y": 2.1},
{"matrix": [6, 0], "x": 12, "y": 2.3},
{"matrix": [3, 2], "x": 3, "y": 3.7},
{"matrix": [3, 3], "x": 4, "y": 3.7},
{"matrix": [3, 4], "x": 5, "y": 3.2, "h": 1.5},
{"matrix": [7, 4], "x": 7, "y": 3.2, "h": 1.5},
{"matrix": [7, 3], "x": 8, "y": 3.7},
{"matrix": [7, 2], "x": 9, "y": 3.7}
]
}
}
}
@@ -0,0 +1,64 @@
// Copyright 2026 ToYoNiX <toyonix.assemmohamed.2005@gmail.com>
// SPDX-License-Identifier: GPL-2.0-or-later
#include QMK_KEYBOARD_H
// Home Row Mods - custom modifier order
#define HM_A LSFT_T(KC_A) // Shift
#define HM_S LCTL_T(KC_S) // Ctrl
#define HM_D LGUI_T(KC_D) // Win/GUI
#define HM_F LALT_T(KC_F) // Alt
#define HM_J LALT_T(KC_J) // Alt
#define HM_K LGUI_T(KC_K) // Win/GUI
#define HM_L LCTL_T(KC_L) // Ctrl
#define HM_SCLN RSFT_T(KC_SCLN) // Shift
// Keymap
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* BASE Layer: QWERTY */
[0] = LAYOUT_split_3x5_3(
//A8 B15 B14 B13 B12 B12 B13 B14 B15 A8
KC_Q, KC_W, KC_E, KC_R, KC_T, /*B0*/ KC_Y, KC_U, KC_I, KC_O, KC_P,
HM_A, HM_S, HM_D, HM_F, KC_G, /*A5*/ KC_H, HM_J, HM_K, HM_L, HM_SCLN,
KC_Z, KC_X, KC_C, KC_V, KC_B, /*A4*/ KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH,
KC_ESC, KC_SPC, MO(1), /*A3*/ MO(2), KC_BSPC, KC_ENT
),
[1] = LAYOUT_split_3x5_3(
KC_TAB, KC_7, KC_8, KC_9, KC_0, KC_GRV, KC_QUOT, KC_MINS, KC_EQL, KC_NO,
KC_LSFT, KC_4, KC_5, KC_6, KC_PSCR, KC_HOME, KC_LBRC, KC_RBRC, KC_BSLS, KC_RSFT,
KC_LGUI, KC_1, KC_2, KC_3, KC_DEL, KC_END, KC_COMM, KC_DOT, KC_SLSH, KC_NO,
_______, _______, _______, _______, _______, _______
),
[2] = LAYOUT_split_3x5_3(
QK_BOOT, KC_F7, KC_F8, KC_F9, KC_F10, TO(3), KC_NO, KC_NO, KC_NO, KC_NO,
KC_NO, KC_F4, KC_F5, KC_F6, KC_F11, KC_NO, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT,
QK_RBT, KC_F1, KC_F2, KC_F3, KC_F12, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
_______, _______, _______, _______, _______, _______
),
// Gaming Layers
[3] = LAYOUT_split_3x5_3(
KC_TAB, KC_Q, KC_W, KC_E, KC_R, TO(0), KC_NO, KC_NO, KC_NO, KC_NO,
KC_LSFT, KC_A, KC_S, KC_D, KC_F, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
KC_LCTL, KC_Z, KC_X, KC_C, KC_V, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
KC_ESC, KC_SPC, LT(4, KC_LGUI), KC_NO, KC_NO, KC_NO
),
[4] = LAYOUT_split_3x5_3(
KC_NO, KC_7, KC_8, KC_9, KC_0, TO(0), KC_NO, KC_NO, KC_NO, KC_NO,
KC_M, KC_4, KC_5, KC_6, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
KC_B, KC_1, KC_2, KC_3, KC_F3, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
_______, _______, _______, KC_NO, KC_NO, KC_NO
)
};
// Encoders
#if defined(ENCODER_MAP_ENABLE)
const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][NUM_DIRECTIONS] = {
[0] = { ENCODER_CCW_CW(KC_VOLD, KC_VOLU), ENCODER_CCW_CW(MS_WHLD, MS_WHLU) },
[1] = { ENCODER_CCW_CW(KC_NO, KC_NO), ENCODER_CCW_CW(KC_BRIU, KC_BRID) },
[2] = { ENCODER_CCW_CW(KC_PGUP, KC_PGDN), ENCODER_CCW_CW(KC_NO, KC_NO) },
[3] = { ENCODER_CCW_CW(KC_VOLD, KC_VOLU), ENCODER_CCW_CW(KC_NO, KC_NO) },
[4] = { ENCODER_CCW_CW(KC_NO, KC_NO), ENCODER_CCW_CW(KC_NO, KC_NO) },
// Encoder 1 Encoder 2
};
#endif
@@ -0,0 +1 @@
ENCODER_MAP_ENABLE = yes
@@ -0,0 +1,8 @@
// Copyright 2024 zvecr <git@zvecr.com>
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include_next <mcuconf.h>
#undef STM32_SERIAL_USE_USART1
#define STM32_SERIAL_USE_USART1 TRUE
@@ -0,0 +1,26 @@
# handwired/tnx_corne_f401
![handwired/tnx_corne_f401](https://i.imgur.com/rHiwS60.jpeg)
*A handwired Corne keyboard using STM32 microcontrollers, with encoder support.*
* Keyboard Maintainer: [Assem Mohamed](https://github.com/ToYoNiX)
* Hardware Supported: STM32F401, STM32F411, or STM32F103 development boards with USB HID support
* Hardware Availability: Commonly available Blackpill F401 and Bluepill F103 boards, plus EC11 encoders and a TRRS cable
Make example for this keyboard (after setting up your build environment):
make handwired/tnx_corne_f401:default
Flashing example for this keyboard:
make handwired/tnx_corne_f401:default:flash
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
## Bootloader
Enter the bootloader in 2 ways:
* **Physical reset button**: Double-press the reset button on the dev board to enter DFU mode
* **Keycode in layout**: Press the key mapped to `QK_BOOT`
@@ -0,0 +1,54 @@
{
"manufacturer": "Harry Cutts",
"keyboard_name": "TwentyPad",
"maintainer": "HarryCutts",
"bootloader": "atmel-dfu",
"features": {
"bootmagic": true,
"extrakey": true,
"mousekey": true
},
"matrix_pins": {
"direct": [
["B7", "D5", "B5", "F6"],
["B3", "D3", "B4", "F7"],
["B2", "D2", "D7", "C7"],
["B1", "D1", "D6", "C6"],
["B0", "D0", "D4", "B6"]
]
},
"processor": "atmega32u4",
"url": "https://github.com/HarryCutts/twentypad/",
"usb": {
"device_version": "1.0.0",
"pid": "0x209D",
"vid": "0xFEED"
},
"community_layouts": ["ortho_5x4"],
"layouts": {
"LAYOUT_ortho_5x4": {
"layout": [
{"label": "B7", "matrix": [0, 0], "x": 0, "y": 0},
{"label": "D5", "matrix": [0, 1], "x": 1, "y": 0},
{"label": "B5", "matrix": [0, 2], "x": 2, "y": 0},
{"label": "F6", "matrix": [0, 3], "x": 3, "y": 0},
{"label": "B3", "matrix": [1, 0], "x": 0, "y": 1},
{"label": "D3", "matrix": [1, 1], "x": 1, "y": 1},
{"label": "B4", "matrix": [1, 2], "x": 2, "y": 1},
{"label": "F7", "matrix": [1, 3], "x": 3, "y": 1},
{"label": "B2", "matrix": [2, 0], "x": 0, "y": 2},
{"label": "D2", "matrix": [2, 1], "x": 1, "y": 2},
{"label": "D7", "matrix": [2, 2], "x": 2, "y": 2},
{"label": "C7", "matrix": [2, 3], "x": 3, "y": 2},
{"label": "B1", "matrix": [3, 0], "x": 0, "y": 3},
{"label": "D1", "matrix": [3, 1], "x": 1, "y": 3},
{"label": "D6", "matrix": [3, 2], "x": 2, "y": 3},
{"label": "C6", "matrix": [3, 3], "x": 3, "y": 3},
{"label": "B0", "matrix": [4, 0], "x": 0, "y": 4},
{"label": "D0", "matrix": [4, 1], "x": 1, "y": 4},
{"label": "D4", "matrix": [4, 2], "x": 2, "y": 4},
{"label": "B6", "matrix": [4, 3], "x": 3, "y": 4}
]
}
}
}
@@ -0,0 +1,14 @@
{
"keyboard": "handwired/twentypad",
"keymap": "default",
"layout": "LAYOUT_ortho_5x4",
"layers": [
[
"KC_CALCULATOR", "KC_KP_SLASH", "KC_KP_ASTERISK", "KC_KP_MINUS",
"KC_KP_7", "KC_KP_8", "KC_KP_9", "KC_KP_PLUS",
"KC_KP_4", "KC_KP_5", "KC_KP_6", "KC_LEFT_PAREN",
"KC_KP_1", "KC_KP_2", "KC_KP_3", "KC_RIGHT_PAREN",
"KC_KP_0", "KC_KP_DOT", "KC_KP_EQUAL", "KC_KP_ENTER"
]
]
}
+26
View File
@@ -0,0 +1,26 @@
# TwentyPad
![TwentyPad](https://i.imgur.com/e1Bsg1M.jpeg)
A simple twenty-key macro pad, built to learn PCB design.
* Keyboard Maintainer: [Harry Cutts](https://github.com/HarryCutts)
* Hardware Supported: ATMEGA32U4 on a [custom PCB](https://github.com/HarryCutts/twentypad/)
Make example for this keyboard (after setting up your build environment):
qmk compile -kb handwired/twentypad -km default
Flashing example for this keyboard:
qmk flash -kb handwired/twentypad -km default
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
## Bootloader
Enter the bootloader in 3 ways:
* **Bootmagic reset**: Hold down the key at (0,0) in the matrix (the top left key) and plug in the keyboard
* **Physical reset button**: Press the button marked `SWR1` in the top-left of the PCB
* **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is available
+32
View File
@@ -0,0 +1,32 @@
// Copyright 2026 Heer (@heer)
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
// ── OLED (SH1106 1.3", 128×64, I2C address 0x3C) ────────────────────────────
#define OLED_DISPLAY_128X64
#define OLED_IC OLED_IC_SH1106
#define OLED_COLUMN_OFFSET 2
#define OLED_BRIGHTNESS 180
#define OLED_TIMEOUT 0
#define OLED_UPDATE_INTERVAL 10
// NOTE: do NOT raise OLED_UPDATE_PROCESS_LIMIT. The default of 1 keeps each I2C
// transaction to a single 32-byte block.
//
// TESTED, TWICE, ON HARDWARE: a limit of 4 — only 128 bytes, one page, the write
// size stock SSD1306/SH1106 drivers use — blanks this panel completely. The board
// keeps running (keys and encoders work) but the display never comes up. The
// reasoning that "a page is safe because everyone writes pages" is wrong for this
// module. Do not try it again.
//
// OLED_UPDATE_INTERVAL is a different knob and is safe to shorten: it changes how
// OFTEN a block is flushed, not how BIG the transaction is, which stays one
// 32-byte block. At the old 33ms, swapping the right-hand panel between the key
// grid and the encoder bars took ~21 blocks * 33ms = ~700ms to reach the glass —
// you would turn the knob and see the bar most of a second later. 10ms puts that
// at ~210ms. If the panel ever misbehaves, this is the first value to put back.
// ── I2C (OLED on GP16=SDA, GP17=SCL via RP2040 I2C0) ────────────────────────
#define I2C_DRIVER I2CD0
#define I2C1_SDA_PIN GP16
#define I2C1_SCL_PIN GP17
+8
View File
@@ -0,0 +1,8 @@
// Copyright 2026 Heer (@heer)
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#define HAL_USE_I2C TRUE
#include_next <halconf.h>
+51
View File
@@ -0,0 +1,51 @@
// Copyright 2026 Heer (@heer)
// SPDX-License-Identifier: GPL-2.0-or-later
#include "quantum.h"
#ifdef OLED_ENABLE
// The panel is mounted upside-down on the PCB, so the rotation belongs to the
// board rather than to any one keymap.
//
// This returns the rotation and nothing else. oled_driver.c does:
//
// oled_rotation = oled_init_user(oled_init_kb(rotation));
//
// so the driver already chains the keymap's hook onto this one's result —
// calling oled_init_user() from in here would run it twice.
oled_rotation_t oled_init_kb(oled_rotation_t rotation) {
return OLED_ROTATION_180;
}
// A keymap that draws its own screen returns false from oled_task_user, which
// stops the board's default display painting over it. This mirrors the weak
// default in oled_driver.c, which is simply `return oled_task_user();`.
bool oled_task_kb(void) {
if (!oled_task_user()) {
return false;
}
oled_set_cursor(0, 0);
oled_write_P(PSTR(" HEER S1"), false);
oled_set_cursor(0, 1);
oled_write_P(PSTR("---------------"), false);
// Shown as a number, not a name: a board-level default cannot know what any
// given keymap calls its layers.
oled_set_cursor(0, 2);
oled_write_P(PSTR("LAYER "), false);
oled_write_char('0' + get_highest_layer(layer_state), false);
oled_set_cursor(0, 3);
oled_write_P(PSTR("["), false);
for (uint8_t i = 0; i < 4; i++) {
oled_write_P(get_highest_layer(layer_state) == i ? PSTR("*") : PSTR("-"), false);
}
oled_write_P(PSTR("]"), false);
return true;
}
#endif // OLED_ENABLE
+56
View File
@@ -0,0 +1,56 @@
{
"manufacturer": "Heer Works",
"keyboard_name": "HEER S1",
"maintainer": "heer",
"bootloader": "rp2040",
"processor": "RP2040",
"usb": {
"vid": "0x4857",
"pid": "0x5331",
"device_version": "1.0.0"
},
"matrix_pins": {
"masked": true,
"cols": ["GP8", "GP9", "GP10", "GP11"],
"rows": ["GP4", "GP5", "GP6", "GP7", "GP2", "GP14"]
},
"diode_direction": "ROW2COL",
"encoder": {
"rotary": [
{"pin_a": "GP0", "pin_b": "GP1"},
{"pin_a": "GP12", "pin_b": "GP13"}
]
},
"features": {
"bootmagic": true,
"encoder": true,
"extrakey": true,
"mousekey": true,
"nkro": true,
"oled": true
},
"layouts": {
"LAYOUT": {
"layout": [
{"matrix": [4, 0], "x": 0, "y": 0, "encoder": 0},
{"matrix": [5, 0], "x": 1, "y": 0, "encoder": 1},
{"matrix": [0, 0], "x": 0, "y": 1},
{"matrix": [0, 1], "x": 1, "y": 1},
{"matrix": [0, 2], "x": 2, "y": 1},
{"matrix": [0, 3], "x": 3, "y": 1},
{"matrix": [1, 0], "x": 0, "y": 2},
{"matrix": [1, 1], "x": 1, "y": 2},
{"matrix": [1, 2], "x": 2, "y": 2},
{"matrix": [1, 3], "x": 3, "y": 2},
{"matrix": [2, 0], "x": 0, "y": 3},
{"matrix": [2, 1], "x": 1, "y": 3},
{"matrix": [2, 2], "x": 2, "y": 3},
{"matrix": [2, 3], "x": 3, "y": 3},
{"matrix": [3, 0], "x": 0, "y": 4},
{"matrix": [3, 1], "x": 1, "y": 4},
{"matrix": [3, 2], "x": 2, "y": 4},
{"matrix": [3, 3], "x": 3, "y": 4}
]
}
}
}
@@ -0,0 +1,56 @@
// Copyright 2026 Heer (@heer)
// SPDX-License-Identifier: GPL-2.0-or-later
#include QMK_KEYBOARD_H
enum layers {
L_BASE,
L_MEDIA,
L_EDIT,
L_SYS,
};
// The bottom-right key advances to the next layer and wraps, so all four are
// reachable using nothing but standard keycodes.
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[L_BASE] = LAYOUT(
TO(L_MEDIA), TO(L_BASE),
KC_1, KC_2, KC_3, KC_4,
KC_5, KC_6, KC_7, KC_8,
KC_9, KC_0, KC_MINS, KC_EQL,
KC_BSPC, KC_ENT, KC_ESC, TO(L_MEDIA)
),
[L_MEDIA] = LAYOUT(
TO(L_EDIT), TO(L_BASE),
KC_MPLY, KC_MSTP, KC_MPRV, KC_MNXT,
KC_VOLD, KC_VOLU, KC_MUTE, _______,
KC_BRID, KC_BRIU, _______, _______,
_______, _______, _______, TO(L_EDIT)
),
[L_EDIT] = LAYOUT(
TO(L_SYS), TO(L_BASE),
LCTL(KC_Z), LCTL(KC_X), LCTL(KC_C), LCTL(KC_V),
LCTL(KC_A), LCTL(KC_S), LCTL(KC_F), LCTL(KC_H),
LCTL(KC_N), LCTL(KC_W), LCTL(KC_T), LCTL(KC_P),
KC_DEL, KC_HOME, KC_END, TO(L_SYS)
),
[L_SYS] = LAYOUT(
TO(L_BASE), TO(L_BASE),
KC_F1, KC_F2, KC_F3, KC_F4,
KC_F5, KC_F6, KC_F7, KC_F8,
KC_F9, KC_F10, KC_F11, KC_F12,
KC_PSCR, KC_SCRL, KC_PAUS, TO(L_BASE)
),
};
#if defined(ENCODER_MAP_ENABLE)
const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][NUM_DIRECTIONS] = {
[L_BASE] = { ENCODER_CCW_CW(KC_VOLD, KC_VOLU), ENCODER_CCW_CW(KC_LEFT, KC_RGHT) },
[L_MEDIA] = { ENCODER_CCW_CW(KC_MPRV, KC_MNXT), ENCODER_CCW_CW(KC_BRID, KC_BRIU) },
[L_EDIT] = { ENCODER_CCW_CW(LCTL(KC_Z), LCTL(KC_Y)), ENCODER_CCW_CW(KC_UP, KC_DOWN) },
[L_SYS] = { ENCODER_CCW_CW(KC_F11, KC_F12), ENCODER_CCW_CW(KC_PGDN, KC_PGUP) },
};
#endif
@@ -0,0 +1 @@
ENCODER_MAP_ENABLE = yes
+9
View File
@@ -0,0 +1,9 @@
// Copyright 2026 Heer (@heer)
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include_next <mcuconf.h>
#undef RP_I2C_USE_I2C0
#define RP_I2C_USE_I2C0 TRUE

Some files were not shown because too many files have changed in this diff Show More