From 1aa52124cab7fef299b1031eb527a63de9562667 Mon Sep 17 00:00:00 2001 From: Vino Rodrigues <366673+vinorodrigues@users.noreply.github.com> Date: Thu, 18 May 2023 05:01:08 +1000 Subject: [PATCH 01/19] [Keyboard] Add Moondrop Dash75 (#20890) Co-authored-by: Drashna Jaelre --- keyboards/moondrop/dash75/info.json | 119 ++++++++++++++++++ .../dash75/keymaps/default/keymap.json | 18 +++ .../moondrop/dash75/keymaps/via/config.h | 6 + .../moondrop/dash75/keymaps/via/keymap.json | 24 ++++ keyboards/moondrop/dash75/r1/config.h | 10 ++ keyboards/moondrop/dash75/r1/info.json | 6 + keyboards/moondrop/dash75/r1/rules.mk | 2 + keyboards/moondrop/dash75/readme.md | 29 +++++ 8 files changed, 214 insertions(+) create mode 100644 keyboards/moondrop/dash75/info.json create mode 100644 keyboards/moondrop/dash75/keymaps/default/keymap.json create mode 100644 keyboards/moondrop/dash75/keymaps/via/config.h create mode 100644 keyboards/moondrop/dash75/keymaps/via/keymap.json create mode 100644 keyboards/moondrop/dash75/r1/config.h create mode 100644 keyboards/moondrop/dash75/r1/info.json create mode 100644 keyboards/moondrop/dash75/r1/rules.mk create mode 100644 keyboards/moondrop/dash75/readme.md diff --git a/keyboards/moondrop/dash75/info.json b/keyboards/moondrop/dash75/info.json new file mode 100644 index 000000000000..13e28fb32541 --- /dev/null +++ b/keyboards/moondrop/dash75/info.json @@ -0,0 +1,119 @@ +{ + "manufacturer": "MOONDROP", + "keyboard_name": "Dash 75", + "maintainer": "vinorodrigues", + "bootloader": "atmel-dfu", + "features": { + "bootmagic": true, + "command": false, + "console": false, + "extrakey": true, + "mousekey": true, + "nkro": false, + "lto": true + }, + "diode_direction": "COL2ROW", + "matrix_pins": { + "rows": ["B6", "B5", "B4", "D7", "D6", "D4"], + "cols": ["C6", "B2", "B3", "F7", "F6", "F5", "F4", "F1", "F0", "B7", "D5", "D3", "D2", "D0", "D1"] + }, + "processor": "atmega32u4", + "url": "https://moondroplab.com/en/products/dash75", + "usb": { + "vid": "0x6DD4", + "pid": "0x7501", + "device_version": "1.5.0" + }, + "layouts": { + "LAYOUT": { + "layout": [ + { "matrix": [0, 0], "x": 0, "y": 0 }, + { "matrix": [0, 1], "x": 1.5, "y": 0 }, + { "matrix": [0, 2], "x": 2.5, "y": 0 }, + { "matrix": [0, 3], "x": 3.5, "y": 0 }, + { "matrix": [0, 4], "x": 4.5, "y": 0 }, + { "matrix": [0, 6], "x": 6, "y": 0 }, + { "matrix": [0, 7], "x": 7, "y": 0 }, + { "matrix": [0, 8], "x": 8, "y": 0 }, + { "matrix": [0, 9], "x": 9, "y": 0 }, + { "matrix": [0, 10], "x": 10.5, "y": 0 }, + { "matrix": [0, 11], "x": 11.5, "y": 0 }, + { "matrix": [0, 12], "x": 12.5, "y": 0 }, + { "matrix": [0, 13], "x": 13.5, "y": 0 }, + { "matrix": [0, 14], "x": 15, "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, "w": 2 }, + { "matrix": [1, 14], "x": 15, "y": 1.25 }, + + { "matrix": [2, 0], "x": 0, "y": 2.25, "w": 1.5 }, + { "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, 13], "x": 13.5, "y": 2.25, "w": 1.5 }, + { "matrix": [2, 14], "x": 15, "y": 2.25 }, + + { "matrix": [3, 0], "x": 0, "y": 3.25, "w": 1.75 }, + { "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], "x": 12.75, "y": 3.25, "w": 2.25 }, + { "matrix": [3, 14], "x": 15, "y": 3.25 }, + + { "matrix": [4, 0], "x": 0, "y": 4.25, "w": 2.25 }, + { "matrix": [4, 1], "x": 2.25, "y": 4.25 }, + { "matrix": [4, 2], "x": 3.25, "y": 4.25 }, + { "matrix": [4, 3], "x": 4.25, "y": 4.25 }, + { "matrix": [4, 4], "x": 5.25, "y": 4.25 }, + { "matrix": [4, 5], "x": 6.25, "y": 4.25 }, + { "matrix": [4, 6], "x": 7.25, "y": 4.25 }, + { "matrix": [4, 7], "x": 8.25, "y": 4.25 }, + { "matrix": [4, 8], "x": 9.25, "y": 4.25 }, + { "matrix": [4, 9], "x": 10.25, "y": 4.25 }, + { "matrix": [4, 10], "x": 11.25, "y": 4.25 }, + { "matrix": [4, 12], "x": 12.25, "y": 4.25, "w": 1.75 }, + { "matrix": [4, 13], "x": 14, "y": 4.25 }, + { "matrix": [4, 14], "x": 15, "y": 4.25 }, + + { "matrix": [5, 0], "x": 0, "y": 5.25, "w": 1.25 }, + { "matrix": [5, 1], "x": 1.25, "y": 5.25, "w": 1.25 }, + { "matrix": [5, 2], "x": 2.5, "y": 5.25, "w": 1.25 }, + { "matrix": [5, 5], "x": 3.75, "y": 5.25, "w": 6.25 }, + { "matrix": [5, 9], "x": 10, "y": 5.25, "w": 1.25 }, + { "matrix": [5, 10], "x": 11.25, "y": 5.25, "w": 1.25 }, + { "matrix": [5, 12], "x": 13, "y": 5.25 }, + { "matrix": [5, 13], "x": 14, "y": 5.25 }, + { "matrix": [5, 14], "x": 15, "y": 5.25 } + ] + } + } +} diff --git a/keyboards/moondrop/dash75/keymaps/default/keymap.json b/keyboards/moondrop/dash75/keymaps/default/keymap.json new file mode 100644 index 000000000000..67811c18a376 --- /dev/null +++ b/keyboards/moondrop/dash75/keymaps/default/keymap.json @@ -0,0 +1,18 @@ +{ + "version": 1, + "notes": "This file is a keymap.json file for moondrop/dash75", + "keyboard": "moondrop/dash75", + "keymap": "default", + "layout": "LAYOUT", + "author": "vinorodrigues", + "layers": [ + [ + "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_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_INS", + "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_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_PGUP", + "KC_LSFT", "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_PGDN", + "KC_LCTL", "KC_LGUI", "KC_LALT", "KC_SPC", "KC_RALT", "KC_APP", "KC_LEFT", "KC_DOWN", "KC_RGHT" + ] + ] +} diff --git a/keyboards/moondrop/dash75/keymaps/via/config.h b/keyboards/moondrop/dash75/keymaps/via/config.h new file mode 100644 index 000000000000..3b36fe3a07ba --- /dev/null +++ b/keyboards/moondrop/dash75/keymaps/via/config.h @@ -0,0 +1,6 @@ +// Copyright 2023 moondroplab (@moondroplab) +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#define VIA_FIRMWARE_VERSION 1 diff --git a/keyboards/moondrop/dash75/keymaps/via/keymap.json b/keyboards/moondrop/dash75/keymaps/via/keymap.json new file mode 100644 index 000000000000..6d43ee82c80f --- /dev/null +++ b/keyboards/moondrop/dash75/keymaps/via/keymap.json @@ -0,0 +1,24 @@ +{ + "version": 1, + "notes": "This file is a keymap.json file for moondrop/dash75", + "keyboard": "moondrop/dash75", + "keymap": "via", + "layout": "LAYOUT", + "author": "vinorodrigues", + "config": { + "features": { + "via": true, + "lto": true + } + }, + "layers": [ + [ + "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_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_INS", + "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_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_PGUP", + "KC_LSFT", "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_PGDN", + "KC_LCTL", "KC_LGUI", "KC_LALT", "KC_SPC", "KC_RALT", "KC_APP", "KC_LEFT", "KC_DOWN", "KC_RGHT" + ] + ] +} diff --git a/keyboards/moondrop/dash75/r1/config.h b/keyboards/moondrop/dash75/r1/config.h new file mode 100644 index 000000000000..16b6125a2d89 --- /dev/null +++ b/keyboards/moondrop/dash75/r1/config.h @@ -0,0 +1,10 @@ +// Copyright 2023 moondroplab (@moondroplab) +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#define SERIAL_NUMBER "Dash 75" + +#define USB_SUSPEND_WAKEUP_DELAY 5000 // wait for USB hub to start + +#define HOLD_ON_OTHER_KEY_PRESS diff --git a/keyboards/moondrop/dash75/r1/info.json b/keyboards/moondrop/dash75/r1/info.json new file mode 100644 index 000000000000..b562070dc9d8 --- /dev/null +++ b/keyboards/moondrop/dash75/r1/info.json @@ -0,0 +1,6 @@ +{ + "usb": { + "pid": "0x7501", + "device_version": "1.5.0" + } +} diff --git a/keyboards/moondrop/dash75/r1/rules.mk b/keyboards/moondrop/dash75/r1/rules.mk new file mode 100644 index 000000000000..6441046fb6a4 --- /dev/null +++ b/keyboards/moondrop/dash75/r1/rules.mk @@ -0,0 +1,2 @@ +# This file intentionally left blank +# ** Settings are Data Driven and reside in `info.json` ** diff --git a/keyboards/moondrop/dash75/readme.md b/keyboards/moondrop/dash75/readme.md new file mode 100644 index 000000000000..5b015f6d5b0d --- /dev/null +++ b/keyboards/moondrop/dash75/readme.md @@ -0,0 +1,29 @@ +# Moondrop Dash75 + +![Moondrop Dash75](https://i.imgur.com/mxaYcvqh.jpg) + +The 75%, Commodore 64 inspired, keyboard with integrated USB Hub and headphone DAC/Amp + +* Keyboard Maintainer: [vinorodrigues](https://github.com/vinorodrigues) +* Hardware Supported: + * Moondrop Dash75 +* Hardware Availability: [moondroplab.com](https://moondroplab.com/en/products/dash75) + +Make example for this keyboard (after setting up your build environment): + + make moondrop/dash75/r1:default + +Flashing example for this keyboard: + + make moondrop/dash75/r1: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 (usually the top left key or Escape) and plug in the keyboard +* **Physical reset button**: Briefly press the button on the back of the PCB - some may have pads you must short instead +* **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is available From ff22015ba0fe813e547577017fbb0e64e5da9d6d Mon Sep 17 00:00:00 2001 From: James Young <18669334+noroadsleft@users.noreply.github.com> Date: Wed, 17 May 2023 12:01:39 -0700 Subject: [PATCH 02/19] AEBoards Aegis Layout Additions (#20960) * add matrix_diagram.md * rename LAYOUT_aegis to LAYOUT_all * info.json: apply friendly formatting * add LAYOUT_numpad with reference keymap * add LAYOUT_2u_bs_275u_rshift with reference keymap --- keyboards/aeboards/aegis/info.json | 477 +++++++++++++----- .../aeboards/aegis/keymaps/default/keymap.c | 8 +- .../default_2u_bs_275u_rshift/keymap.c | 72 +++ .../aegis/keymaps/default_numpad/keymap.c | 72 +++ keyboards/aeboards/aegis/keymaps/via/keymap.c | 8 +- keyboards/aeboards/aegis/matrix_diagram.md | 32 ++ 6 files changed, 543 insertions(+), 126 deletions(-) create mode 100644 keyboards/aeboards/aegis/keymaps/default_2u_bs_275u_rshift/keymap.c create mode 100644 keyboards/aeboards/aegis/keymaps/default_numpad/keymap.c create mode 100644 keyboards/aeboards/aegis/matrix_diagram.md diff --git a/keyboards/aeboards/aegis/info.json b/keyboards/aeboards/aegis/info.json index 5fe143318f0a..823e45c8e2e0 100644 --- a/keyboards/aeboards/aegis/info.json +++ b/keyboards/aeboards/aegis/info.json @@ -15,126 +15,367 @@ "diode_direction": "COL2ROW", "processor": "atmega32u4", "bootloader": "atmel-dfu", + "layout_aliases": { + "LAYOUT_aegis": "LAYOUT_all" + }, "layouts": { - "LAYOUT_aegis": { + "LAYOUT_all": { "layout": [ - {"matrix": [0, 0], "x": 0, "y": 0}, - {"matrix": [1, 0], "x": 1, "y": 0}, - {"matrix": [0, 1], "x": 2, "y": 0}, - {"matrix": [1, 1], "x": 3, "y": 0}, - - {"matrix": [0, 2], "x": 4.5, "y": 0}, - - {"matrix": [1, 2], "x": 6.5, "y": 0}, - {"matrix": [0, 3], "x": 7.5, "y": 0}, - {"matrix": [1, 3], "x": 8.5, "y": 0}, - {"matrix": [0, 4], "x": 9.5, "y": 0}, - - {"matrix": [1, 4], "x": 11, "y": 0}, - {"matrix": [0, 5], "x": 12, "y": 0}, - {"matrix": [1, 5], "x": 13, "y": 0}, - {"matrix": [0, 6], "x": 14, "y": 0}, - - {"matrix": [1, 6], "x": 15.5, "y": 0}, - {"matrix": [0, 7], "x": 16.5, "y": 0}, - {"matrix": [1, 7], "x": 17.5, "y": 0}, - {"matrix": [0, 8], "x": 18.5, "y": 0}, - - {"matrix": [2, 0], "x": 0, "y": 1.5}, - {"matrix": [3, 0], "x": 1, "y": 1.5}, - {"matrix": [2, 1], "x": 2, "y": 1.5}, - {"matrix": [3, 1], "x": 3, "y": 1.5}, - - {"matrix": [2, 2], "x": 4.5, "y": 1.5}, - {"matrix": [3, 2], "x": 5.5, "y": 1.5}, - {"matrix": [2, 3], "x": 6.5, "y": 1.5}, - {"matrix": [3, 3], "x": 7.5, "y": 1.5}, - {"matrix": [2, 4], "x": 8.5, "y": 1.5}, - {"matrix": [3, 4], "x": 9.5, "y": 1.5}, - {"matrix": [2, 5], "x": 10.5, "y": 1.5}, - {"matrix": [3, 5], "x": 11.5, "y": 1.5}, - {"matrix": [2, 6], "x": 12.5, "y": 1.5}, - {"matrix": [3, 6], "x": 13.5, "y": 1.5}, - {"matrix": [2, 7], "x": 14.5, "y": 1.5}, - {"matrix": [3, 7], "x": 15.5, "y": 1.5}, - {"matrix": [2, 8], "x": 16.5, "y": 1.5}, - {"matrix": [3, 8], "x": 17.5, "y": 1.5}, - {"matrix": [1, 8], "x": 18.5, "y": 1.5}, - - {"matrix": [4, 0], "x": 0, "y": 2.5}, - {"matrix": [5, 0], "x": 1, "y": 2.5}, - {"matrix": [4, 1], "x": 2, "y": 2.5}, - {"matrix": [5, 1], "x": 3, "y": 2.5}, - - {"matrix": [4, 2], "x": 4.5, "y": 2.5, "w": 1.5}, - {"matrix": [5, 2], "x": 6, "y": 2.5}, - {"matrix": [4, 3], "x": 7, "y": 2.5}, - {"matrix": [5, 3], "x": 8, "y": 2.5}, - {"matrix": [4, 4], "x": 9, "y": 2.5}, - {"matrix": [5, 4], "x": 10, "y": 2.5}, - {"matrix": [4, 5], "x": 11, "y": 2.5}, - {"matrix": [5, 5], "x": 12, "y": 2.5}, - {"matrix": [4, 6], "x": 13, "y": 2.5}, - {"matrix": [5, 6], "x": 14, "y": 2.5}, - {"matrix": [4, 7], "x": 15, "y": 2.5}, - {"matrix": [5, 7], "x": 16, "y": 2.5}, - {"matrix": [4, 8], "x": 17, "y": 2.5}, - {"matrix": [5, 8], "x": 18, "y": 2.5, "w": 1.5}, - - {"matrix": [6, 0], "x": 0, "y": 3.5}, - {"matrix": [7, 0], "x": 1, "y": 3.5}, - {"matrix": [6, 1], "x": 2, "y": 3.5}, - {"matrix": [7, 1], "x": 3, "y": 3.5}, - - {"matrix": [6, 2], "x": 4.5, "y": 3.5, "w": 1.75}, - {"matrix": [7, 2], "x": 6.25, "y": 3.5}, - {"matrix": [6, 3], "x": 7.25, "y": 3.5}, - {"matrix": [7, 3], "x": 8.25, "y": 3.5}, - {"matrix": [6, 4], "x": 9.25, "y": 3.5}, - {"matrix": [7, 4], "x": 10.25, "y": 3.5}, - {"matrix": [6, 5], "x": 11.25, "y": 3.5}, - {"matrix": [7, 5], "x": 12.25, "y": 3.5}, - {"matrix": [6, 6], "x": 13.25, "y": 3.5}, - {"matrix": [7, 6], "x": 14.25, "y": 3.5}, - {"matrix": [6, 7], "x": 15.25, "y": 3.5}, - {"matrix": [7, 7], "x": 16.25, "y": 3.5}, - {"matrix": [6, 8], "x": 17.25, "y": 3.5, "w": 2.25}, - - {"matrix": [8, 0], "x": 0, "y": 4.5}, - {"matrix": [9, 0], "x": 1, "y": 4.5}, - {"matrix": [8, 1], "x": 2, "y": 4.5}, - {"matrix": [9, 1], "x": 3, "y": 4.5}, - - {"matrix": [8, 2], "x": 4.25, "y": 4.75}, - - {"matrix": [9, 2], "x": 5.5, "y": 4.5, "w": 1.25}, - {"matrix": [8, 3], "x": 6.75, "y": 4.5}, - {"matrix": [9, 3], "x": 7.75, "y": 4.5}, - {"matrix": [8, 4], "x": 8.75, "y": 4.5}, - {"matrix": [9, 4], "x": 9.75, "y": 4.5}, - {"matrix": [8, 5], "x": 10.75, "y": 4.5}, - {"matrix": [9, 5], "x": 11.75, "y": 4.5}, - {"matrix": [8, 6], "x": 12.75, "y": 4.5}, - {"matrix": [9, 6], "x": 13.75, "y": 4.5}, - {"matrix": [8, 7], "x": 14.75, "y": 4.5}, - {"matrix": [9, 7], "x": 15.75, "y": 4.5}, - {"matrix": [8, 8], "x": 16.75, "y": 4.5, "w": 1.75}, - {"matrix": [9, 8], "x": 18.5, "y": 4.5}, - - {"matrix": [10, 0], "x": 0, "y": 5.5}, - {"matrix": [11, 0], "x": 1, "y": 5.5}, - {"matrix": [10, 1], "x": 2, "y": 5.5}, - - {"matrix": [11, 1], "x": 3.25, "y": 5.75}, - {"matrix": [10, 2], "x": 4.25, "y": 5.75}, - {"matrix": [11, 2], "x": 5.25, "y": 5.75}, - - {"matrix": [10, 3], "x": 6.5, "y": 5.5, "w": 1.25}, - {"matrix": [11, 3], "x": 7.75, "y": 5.5, "w": 1.25}, - {"matrix": [11, 5], "x": 9, "y": 5.5, "w": 6.25}, - {"matrix": [11, 7], "x": 15.25, "y": 5.5, "w": 1.5}, - {"matrix": [10, 8], "x": 16.75, "y": 5.5, "w": 1.25}, - {"matrix": [11, 8], "x": 18, "y": 5.5, "w": 1.5} + {"label": "End", "matrix": [0, 0], "x": 0, "y": 0}, + {"label": "Home", "matrix": [1, 0], "x": 1, "y": 0}, + {"label": "Page Down", "matrix": [0, 1], "x": 2, "y": 0}, + {"label": "Page Up", "matrix": [1, 1], "x": 3, "y": 0}, + + {"label": "Esc", "matrix": [0, 2], "x": 4.5, "y": 0}, + + {"label": "F1", "matrix": [1, 2], "x": 6.5, "y": 0}, + {"label": "F2", "matrix": [0, 3], "x": 7.5, "y": 0}, + {"label": "F3", "matrix": [1, 3], "x": 8.5, "y": 0}, + {"label": "F4", "matrix": [0, 4], "x": 9.5, "y": 0}, + + {"label": "F5", "matrix": [1, 4], "x": 11, "y": 0}, + {"label": "F6", "matrix": [0, 5], "x": 12, "y": 0}, + {"label": "F7", "matrix": [1, 5], "x": 13, "y": 0}, + {"label": "F8", "matrix": [0, 6], "x": 14, "y": 0}, + + {"label": "F9", "matrix": [1, 6], "x": 15.5, "y": 0}, + {"label": "F10", "matrix": [0, 7], "x": 16.5, "y": 0}, + {"label": "F11", "matrix": [1, 7], "x": 17.5, "y": 0}, + {"label": "F12", "matrix": [0, 8], "x": 18.5, "y": 0}, + + {"label": "-", "matrix": [2, 0], "x": 0, "y": 1.5}, + {"label": "*", "matrix": [3, 0], "x": 1, "y": 1.5}, + {"label": "/", "matrix": [2, 1], "x": 2, "y": 1.5}, + {"label": "Backspace", "matrix": [3, 1], "x": 3, "y": 1.5}, + + {"label": "`", "matrix": [2, 2], "x": 4.5, "y": 1.5}, + {"label": "1", "matrix": [3, 2], "x": 5.5, "y": 1.5}, + {"label": "2", "matrix": [2, 3], "x": 6.5, "y": 1.5}, + {"label": "3", "matrix": [3, 3], "x": 7.5, "y": 1.5}, + {"label": "4", "matrix": [2, 4], "x": 8.5, "y": 1.5}, + {"label": "5", "matrix": [3, 4], "x": 9.5, "y": 1.5}, + {"label": "6", "matrix": [2, 5], "x": 10.5, "y": 1.5}, + {"label": "7", "matrix": [3, 5], "x": 11.5, "y": 1.5}, + {"label": "8", "matrix": [2, 6], "x": 12.5, "y": 1.5}, + {"label": "9", "matrix": [3, 6], "x": 13.5, "y": 1.5}, + {"label": "0", "matrix": [2, 7], "x": 14.5, "y": 1.5}, + {"label": "-", "matrix": [3, 7], "x": 15.5, "y": 1.5}, + {"label": "=", "matrix": [2, 8], "x": 16.5, "y": 1.5}, + {"label": "\\", "matrix": [3, 8], "x": 17.5, "y": 1.5}, + {"label": "Delete", "matrix": [1, 8], "x": 18.5, "y": 1.5}, + + {"label": "+", "matrix": [4, 0], "x": 0, "y": 2.5}, + {"label": "9", "matrix": [5, 0], "x": 1, "y": 2.5}, + {"label": "8", "matrix": [4, 1], "x": 2, "y": 2.5}, + {"label": "7", "matrix": [5, 1], "x": 3, "y": 2.5}, + + {"label": "Tab", "matrix": [4, 2], "x": 4.5, "y": 2.5, "w": 1.5}, + {"label": "Q", "matrix": [5, 2], "x": 6, "y": 2.5}, + {"label": "W", "matrix": [4, 3], "x": 7, "y": 2.5}, + {"label": "E", "matrix": [5, 3], "x": 8, "y": 2.5}, + {"label": "R", "matrix": [4, 4], "x": 9, "y": 2.5}, + {"label": "T", "matrix": [5, 4], "x": 10, "y": 2.5}, + {"label": "Y", "matrix": [4, 5], "x": 11, "y": 2.5}, + {"label": "U", "matrix": [5, 5], "x": 12, "y": 2.5}, + {"label": "I", "matrix": [4, 6], "x": 13, "y": 2.5}, + {"label": "O", "matrix": [5, 6], "x": 14, "y": 2.5}, + {"label": "P", "matrix": [4, 7], "x": 15, "y": 2.5}, + {"label": "[", "matrix": [5, 7], "x": 16, "y": 2.5}, + {"label": "]", "matrix": [4, 8], "x": 17, "y": 2.5}, + {"label": "Backspace", "matrix": [5, 8], "x": 18, "y": 2.5, "w": 1.5}, + + {"label": "+", "matrix": [6, 0], "x": 0, "y": 3.5}, + {"label": "6", "matrix": [7, 0], "x": 1, "y": 3.5}, + {"label": "5", "matrix": [6, 1], "x": 2, "y": 3.5}, + {"label": "4", "matrix": [7, 1], "x": 3, "y": 3.5}, + + {"label": "Ctrl", "matrix": [6, 2], "x": 4.5, "y": 3.5, "w": 1.75}, + {"label": "A", "matrix": [7, 2], "x": 6.25, "y": 3.5}, + {"label": "S", "matrix": [6, 3], "x": 7.25, "y": 3.5}, + {"label": "D", "matrix": [7, 3], "x": 8.25, "y": 3.5}, + {"label": "F", "matrix": [6, 4], "x": 9.25, "y": 3.5}, + {"label": "G", "matrix": [7, 4], "x": 10.25, "y": 3.5}, + {"label": "H", "matrix": [6, 5], "x": 11.25, "y": 3.5}, + {"label": "J", "matrix": [7, 5], "x": 12.25, "y": 3.5}, + {"label": "K", "matrix": [6, 6], "x": 13.25, "y": 3.5}, + {"label": "L", "matrix": [7, 6], "x": 14.25, "y": 3.5}, + {"label": ";", "matrix": [6, 7], "x": 15.25, "y": 3.5}, + {"label": "'", "matrix": [7, 7], "x": 16.25, "y": 3.5}, + {"label": "Enter", "matrix": [6, 8], "x": 17.25, "y": 3.5, "w": 2.25}, + + {"label": "Enter", "matrix": [8, 0], "x": 0, "y": 4.5}, + {"label": "3", "matrix": [9, 0], "x": 1, "y": 4.5}, + {"label": "2", "matrix": [8, 1], "x": 2, "y": 4.5}, + {"label": "1", "matrix": [9, 1], "x": 3, "y": 4.5}, + + {"label": "\u2191", "matrix": [8, 2], "x": 4.25, "y": 4.75}, + + {"label": "Shift", "matrix": [9, 2], "x": 5.5, "y": 4.5, "w": 1.25}, + {"label": "Z", "matrix": [8, 3], "x": 6.75, "y": 4.5}, + {"label": "X", "matrix": [9, 3], "x": 7.75, "y": 4.5}, + {"label": "C", "matrix": [8, 4], "x": 8.75, "y": 4.5}, + {"label": "V", "matrix": [9, 4], "x": 9.75, "y": 4.5}, + {"label": "B", "matrix": [8, 5], "x": 10.75, "y": 4.5}, + {"label": "N", "matrix": [9, 5], "x": 11.75, "y": 4.5}, + {"label": "M", "matrix": [8, 6], "x": 12.75, "y": 4.5}, + {"label": ",", "matrix": [9, 6], "x": 13.75, "y": 4.5}, + {"label": ".", "matrix": [8, 7], "x": 14.75, "y": 4.5}, + {"label": "/", "matrix": [9, 7], "x": 15.75, "y": 4.5}, + {"label": "Shift", "matrix": [8, 8], "x": 16.75, "y": 4.5, "w": 1.75}, + {"label": "Fn", "matrix": [9, 8], "x": 18.5, "y": 4.5}, + + {"label": "Enter", "matrix": [10, 0], "x": 0, "y": 5.5}, + {"label": ".", "matrix": [11, 0], "x": 1, "y": 5.5}, + {"label": "0", "matrix": [10, 1], "x": 2, "y": 5.5}, + + {"label": "\u2190", "matrix": [11, 1], "x": 3.25, "y": 5.75}, + {"label": "\u2193", "matrix": [10, 2], "x": 4.25, "y": 5.75}, + {"label": "\u2192", "matrix": [11, 2], "x": 5.25, "y": 5.75}, + + {"label": "Fn", "matrix": [10, 3], "x": 6.5, "y": 5.5, "w": 1.25}, + {"label": "Alt", "matrix": [11, 3], "x": 7.75, "y": 5.5, "w": 1.25}, + {"label": "Space", "matrix": [11, 5], "x": 9, "y": 5.5, "w": 6.25}, + {"label": "Alt", "matrix": [11, 7], "x": 15.25, "y": 5.5, "w": 1.5}, + {"label": "GUI", "matrix": [10, 8], "x": 16.75, "y": 5.5, "w": 1.25}, + {"label": "Ctrl", "matrix": [11, 8], "x": 18, "y": 5.5, "w": 1.5} + ] + }, + "LAYOUT_2u_bs_275u_rshift": { + "layout": [ + {"label": "End", "matrix": [0, 0], "x": 0, "y": 0}, + {"label": "Home", "matrix": [1, 0], "x": 1, "y": 0}, + {"label": "Page Down", "matrix": [0, 1], "x": 2, "y": 0}, + {"label": "Page Up", "matrix": [1, 1], "x": 3, "y": 0}, + + {"label": "Esc", "matrix": [0, 2], "x": 4.5, "y": 0}, + + {"label": "F1", "matrix": [1, 2], "x": 6.5, "y": 0}, + {"label": "F2", "matrix": [0, 3], "x": 7.5, "y": 0}, + {"label": "F3", "matrix": [1, 3], "x": 8.5, "y": 0}, + {"label": "F4", "matrix": [0, 4], "x": 9.5, "y": 0}, + + {"label": "F5", "matrix": [1, 4], "x": 11, "y": 0}, + {"label": "F6", "matrix": [0, 5], "x": 12, "y": 0}, + {"label": "F7", "matrix": [1, 5], "x": 13, "y": 0}, + {"label": "F8", "matrix": [0, 6], "x": 14, "y": 0}, + + {"label": "F9", "matrix": [1, 6], "x": 15.5, "y": 0}, + {"label": "F10", "matrix": [0, 7], "x": 16.5, "y": 0}, + {"label": "F11", "matrix": [1, 7], "x": 17.5, "y": 0}, + {"label": "F12", "matrix": [0, 8], "x": 18.5, "y": 0}, + + {"label": "-", "matrix": [2, 0], "x": 0, "y": 1.5}, + {"label": "*", "matrix": [3, 0], "x": 1, "y": 1.5}, + {"label": "/", "matrix": [2, 1], "x": 2, "y": 1.5}, + {"label": "Backspace", "matrix": [3, 1], "x": 3, "y": 1.5}, + + {"label": "`", "matrix": [2, 2], "x": 4.5, "y": 1.5}, + {"label": "1", "matrix": [3, 2], "x": 5.5, "y": 1.5}, + {"label": "2", "matrix": [2, 3], "x": 6.5, "y": 1.5}, + {"label": "3", "matrix": [3, 3], "x": 7.5, "y": 1.5}, + {"label": "4", "matrix": [2, 4], "x": 8.5, "y": 1.5}, + {"label": "5", "matrix": [3, 4], "x": 9.5, "y": 1.5}, + {"label": "6", "matrix": [2, 5], "x": 10.5, "y": 1.5}, + {"label": "7", "matrix": [3, 5], "x": 11.5, "y": 1.5}, + {"label": "8", "matrix": [2, 6], "x": 12.5, "y": 1.5}, + {"label": "9", "matrix": [3, 6], "x": 13.5, "y": 1.5}, + {"label": "0", "matrix": [2, 7], "x": 14.5, "y": 1.5}, + {"label": "-", "matrix": [3, 7], "x": 15.5, "y": 1.5}, + {"label": "=", "matrix": [2, 8], "x": 16.5, "y": 1.5}, + {"label": "Backspace", "matrix": [3, 8], "x": 17.5, "y": 1.5, "w": 2}, + + {"label": "+", "matrix": [4, 0], "x": 0, "y": 2.5}, + {"label": "9", "matrix": [5, 0], "x": 1, "y": 2.5}, + {"label": "8", "matrix": [4, 1], "x": 2, "y": 2.5}, + {"label": "7", "matrix": [5, 1], "x": 3, "y": 2.5}, + + {"label": "Tab", "matrix": [4, 2], "x": 4.5, "y": 2.5, "w": 1.5}, + {"label": "Q", "matrix": [5, 2], "x": 6, "y": 2.5}, + {"label": "W", "matrix": [4, 3], "x": 7, "y": 2.5}, + {"label": "E", "matrix": [5, 3], "x": 8, "y": 2.5}, + {"label": "R", "matrix": [4, 4], "x": 9, "y": 2.5}, + {"label": "T", "matrix": [5, 4], "x": 10, "y": 2.5}, + {"label": "Y", "matrix": [4, 5], "x": 11, "y": 2.5}, + {"label": "U", "matrix": [5, 5], "x": 12, "y": 2.5}, + {"label": "I", "matrix": [4, 6], "x": 13, "y": 2.5}, + {"label": "O", "matrix": [5, 6], "x": 14, "y": 2.5}, + {"label": "P", "matrix": [4, 7], "x": 15, "y": 2.5}, + {"label": "[", "matrix": [5, 7], "x": 16, "y": 2.5}, + {"label": "]", "matrix": [4, 8], "x": 17, "y": 2.5}, + {"label": "Backspace", "matrix": [5, 8], "x": 18, "y": 2.5, "w": 1.5}, + + {"label": "+", "matrix": [6, 0], "x": 0, "y": 3.5}, + {"label": "6", "matrix": [7, 0], "x": 1, "y": 3.5}, + {"label": "5", "matrix": [6, 1], "x": 2, "y": 3.5}, + {"label": "4", "matrix": [7, 1], "x": 3, "y": 3.5}, + + {"label": "Ctrl", "matrix": [6, 2], "x": 4.5, "y": 3.5, "w": 1.75}, + {"label": "A", "matrix": [7, 2], "x": 6.25, "y": 3.5}, + {"label": "S", "matrix": [6, 3], "x": 7.25, "y": 3.5}, + {"label": "D", "matrix": [7, 3], "x": 8.25, "y": 3.5}, + {"label": "F", "matrix": [6, 4], "x": 9.25, "y": 3.5}, + {"label": "G", "matrix": [7, 4], "x": 10.25, "y": 3.5}, + {"label": "H", "matrix": [6, 5], "x": 11.25, "y": 3.5}, + {"label": "J", "matrix": [7, 5], "x": 12.25, "y": 3.5}, + {"label": "K", "matrix": [6, 6], "x": 13.25, "y": 3.5}, + {"label": "L", "matrix": [7, 6], "x": 14.25, "y": 3.5}, + {"label": ";", "matrix": [6, 7], "x": 15.25, "y": 3.5}, + {"label": "'", "matrix": [7, 7], "x": 16.25, "y": 3.5}, + {"label": "Enter", "matrix": [6, 8], "x": 17.25, "y": 3.5, "w": 2.25}, + + {"label": "Enter", "matrix": [8, 0], "x": 0, "y": 4.5}, + {"label": "3", "matrix": [9, 0], "x": 1, "y": 4.5}, + {"label": "2", "matrix": [8, 1], "x": 2, "y": 4.5}, + {"label": "1", "matrix": [9, 1], "x": 3, "y": 4.5}, + + {"label": "\u2191", "matrix": [8, 2], "x": 4.25, "y": 4.75}, + + {"label": "Shift", "matrix": [9, 2], "x": 5.5, "y": 4.5, "w": 1.25}, + {"label": "Z", "matrix": [8, 3], "x": 6.75, "y": 4.5}, + {"label": "X", "matrix": [9, 3], "x": 7.75, "y": 4.5}, + {"label": "C", "matrix": [8, 4], "x": 8.75, "y": 4.5}, + {"label": "V", "matrix": [9, 4], "x": 9.75, "y": 4.5}, + {"label": "B", "matrix": [8, 5], "x": 10.75, "y": 4.5}, + {"label": "N", "matrix": [9, 5], "x": 11.75, "y": 4.5}, + {"label": "M", "matrix": [8, 6], "x": 12.75, "y": 4.5}, + {"label": ",", "matrix": [9, 6], "x": 13.75, "y": 4.5}, + {"label": ".", "matrix": [8, 7], "x": 14.75, "y": 4.5}, + {"label": "/", "matrix": [9, 7], "x": 15.75, "y": 4.5}, + {"label": "Shift", "matrix": [8, 8], "x": 16.75, "y": 4.5, "w": 2.75}, + + {"label": "Enter", "matrix": [10, 0], "x": 0, "y": 5.5}, + {"label": ".", "matrix": [11, 0], "x": 1, "y": 5.5}, + {"label": "0", "matrix": [10, 1], "x": 2, "y": 5.5}, + + {"label": "\u2190", "matrix": [11, 1], "x": 3.25, "y": 5.75}, + {"label": "\u2193", "matrix": [10, 2], "x": 4.25, "y": 5.75}, + {"label": "\u2192", "matrix": [11, 2], "x": 5.25, "y": 5.75}, + + {"label": "Fn", "matrix": [10, 3], "x": 6.5, "y": 5.5, "w": 1.25}, + {"label": "Alt", "matrix": [11, 3], "x": 7.75, "y": 5.5, "w": 1.25}, + {"label": "Space", "matrix": [11, 5], "x": 9, "y": 5.5, "w": 6.25}, + {"label": "Alt", "matrix": [11, 7], "x": 15.25, "y": 5.5, "w": 1.5}, + {"label": "GUI", "matrix": [10, 8], "x": 16.75, "y": 5.5, "w": 1.25}, + {"label": "Ctrl", "matrix": [11, 8], "x": 18, "y": 5.5, "w": 1.5} + ] + }, + "LAYOUT_numpad": { + "layout": [ + {"label": "End", "matrix": [0, 0], "x": 0, "y": 0}, + {"label": "Home", "matrix": [1, 0], "x": 1, "y": 0}, + {"label": "Page Down", "matrix": [0, 1], "x": 2, "y": 0}, + {"label": "Page Up", "matrix": [1, 1], "x": 3, "y": 0}, + + {"label": "Esc", "matrix": [0, 2], "x": 4.5, "y": 0}, + + {"label": "F1", "matrix": [1, 2], "x": 6.5, "y": 0}, + {"label": "F2", "matrix": [0, 3], "x": 7.5, "y": 0}, + {"label": "F3", "matrix": [1, 3], "x": 8.5, "y": 0}, + {"label": "F4", "matrix": [0, 4], "x": 9.5, "y": 0}, + + {"label": "F5", "matrix": [1, 4], "x": 11, "y": 0}, + {"label": "F6", "matrix": [0, 5], "x": 12, "y": 0}, + {"label": "F7", "matrix": [1, 5], "x": 13, "y": 0}, + {"label": "F8", "matrix": [0, 6], "x": 14, "y": 0}, + + {"label": "F9", "matrix": [1, 6], "x": 15.5, "y": 0}, + {"label": "F10", "matrix": [0, 7], "x": 16.5, "y": 0}, + {"label": "F11", "matrix": [1, 7], "x": 17.5, "y": 0}, + {"label": "F12", "matrix": [0, 8], "x": 18.5, "y": 0}, + + {"label": "-", "matrix": [2, 0], "x": 0, "y": 1.5}, + {"label": "*", "matrix": [3, 0], "x": 1, "y": 1.5}, + {"label": "/", "matrix": [2, 1], "x": 2, "y": 1.5}, + {"label": "Backspace", "matrix": [3, 1], "x": 3, "y": 1.5}, + + {"label": "`", "matrix": [2, 2], "x": 4.5, "y": 1.5}, + {"label": "1", "matrix": [3, 2], "x": 5.5, "y": 1.5}, + {"label": "2", "matrix": [2, 3], "x": 6.5, "y": 1.5}, + {"label": "3", "matrix": [3, 3], "x": 7.5, "y": 1.5}, + {"label": "4", "matrix": [2, 4], "x": 8.5, "y": 1.5}, + {"label": "5", "matrix": [3, 4], "x": 9.5, "y": 1.5}, + {"label": "6", "matrix": [2, 5], "x": 10.5, "y": 1.5}, + {"label": "7", "matrix": [3, 5], "x": 11.5, "y": 1.5}, + {"label": "8", "matrix": [2, 6], "x": 12.5, "y": 1.5}, + {"label": "9", "matrix": [3, 6], "x": 13.5, "y": 1.5}, + {"label": "0", "matrix": [2, 7], "x": 14.5, "y": 1.5}, + {"label": "-", "matrix": [3, 7], "x": 15.5, "y": 1.5}, + {"label": "=", "matrix": [2, 8], "x": 16.5, "y": 1.5}, + {"label": "\\", "matrix": [3, 8], "x": 17.5, "y": 1.5}, + {"label": "Delete", "matrix": [1, 8], "x": 18.5, "y": 1.5}, + + {"label": "+", "matrix": [6, 0], "x": 0, "y": 2.5, "h": 2}, + {"label": "9", "matrix": [5, 0], "x": 1, "y": 2.5}, + {"label": "8", "matrix": [4, 1], "x": 2, "y": 2.5}, + {"label": "7", "matrix": [5, 1], "x": 3, "y": 2.5}, + + {"label": "Tab", "matrix": [4, 2], "x": 4.5, "y": 2.5, "w": 1.5}, + {"label": "Q", "matrix": [5, 2], "x": 6, "y": 2.5}, + {"label": "W", "matrix": [4, 3], "x": 7, "y": 2.5}, + {"label": "E", "matrix": [5, 3], "x": 8, "y": 2.5}, + {"label": "R", "matrix": [4, 4], "x": 9, "y": 2.5}, + {"label": "T", "matrix": [5, 4], "x": 10, "y": 2.5}, + {"label": "Y", "matrix": [4, 5], "x": 11, "y": 2.5}, + {"label": "U", "matrix": [5, 5], "x": 12, "y": 2.5}, + {"label": "I", "matrix": [4, 6], "x": 13, "y": 2.5}, + {"label": "O", "matrix": [5, 6], "x": 14, "y": 2.5}, + {"label": "P", "matrix": [4, 7], "x": 15, "y": 2.5}, + {"label": "[", "matrix": [5, 7], "x": 16, "y": 2.5}, + {"label": "]", "matrix": [4, 8], "x": 17, "y": 2.5}, + {"label": "Backspace", "matrix": [5, 8], "x": 18, "y": 2.5, "w": 1.5}, + + {"label": "6", "matrix": [7, 0], "x": 1, "y": 3.5}, + {"label": "5", "matrix": [6, 1], "x": 2, "y": 3.5}, + {"label": "4", "matrix": [7, 1], "x": 3, "y": 3.5}, + + {"label": "Ctrl", "matrix": [6, 2], "x": 4.5, "y": 3.5, "w": 1.75}, + {"label": "A", "matrix": [7, 2], "x": 6.25, "y": 3.5}, + {"label": "S", "matrix": [6, 3], "x": 7.25, "y": 3.5}, + {"label": "D", "matrix": [7, 3], "x": 8.25, "y": 3.5}, + {"label": "F", "matrix": [6, 4], "x": 9.25, "y": 3.5}, + {"label": "G", "matrix": [7, 4], "x": 10.25, "y": 3.5}, + {"label": "H", "matrix": [6, 5], "x": 11.25, "y": 3.5}, + {"label": "J", "matrix": [7, 5], "x": 12.25, "y": 3.5}, + {"label": "K", "matrix": [6, 6], "x": 13.25, "y": 3.5}, + {"label": "L", "matrix": [7, 6], "x": 14.25, "y": 3.5}, + {"label": ";", "matrix": [6, 7], "x": 15.25, "y": 3.5}, + {"label": "'", "matrix": [7, 7], "x": 16.25, "y": 3.5}, + {"label": "Enter", "matrix": [6, 8], "x": 17.25, "y": 3.5, "w": 2.25}, + + {"label": "Enter", "matrix": [8, 0], "x": 0, "y": 4.5, "h": 2}, + {"label": "3", "matrix": [9, 0], "x": 1, "y": 4.5}, + {"label": "2", "matrix": [8, 1], "x": 2, "y": 4.5}, + {"label": "1", "matrix": [9, 1], "x": 3, "y": 4.5}, + + {"label": "\u2191", "matrix": [8, 2], "x": 4.25, "y": 4.75}, + + {"label": "Shift", "matrix": [9, 2], "x": 5.5, "y": 4.5, "w": 1.25}, + {"label": "Z", "matrix": [8, 3], "x": 6.75, "y": 4.5}, + {"label": "X", "matrix": [9, 3], "x": 7.75, "y": 4.5}, + {"label": "C", "matrix": [8, 4], "x": 8.75, "y": 4.5}, + {"label": "V", "matrix": [9, 4], "x": 9.75, "y": 4.5}, + {"label": "B", "matrix": [8, 5], "x": 10.75, "y": 4.5}, + {"label": "N", "matrix": [9, 5], "x": 11.75, "y": 4.5}, + {"label": "M", "matrix": [8, 6], "x": 12.75, "y": 4.5}, + {"label": ",", "matrix": [9, 6], "x": 13.75, "y": 4.5}, + {"label": ".", "matrix": [8, 7], "x": 14.75, "y": 4.5}, + {"label": "/", "matrix": [9, 7], "x": 15.75, "y": 4.5}, + {"label": "Shift", "matrix": [8, 8], "x": 16.75, "y": 4.5, "w": 1.75}, + {"label": "Fn", "matrix": [9, 8], "x": 18.5, "y": 4.5}, + + {"label": ".", "matrix": [11, 0], "x": 1, "y": 5.5}, + {"label": "0", "matrix": [10, 1], "x": 2, "y": 5.5}, + + {"label": "\u2190", "matrix": [11, 1], "x": 3.25, "y": 5.75}, + {"label": "\u2193", "matrix": [10, 2], "x": 4.25, "y": 5.75}, + {"label": "\u2192", "matrix": [11, 2], "x": 5.25, "y": 5.75}, + + {"label": "Fn", "matrix": [10, 3], "x": 6.5, "y": 5.5, "w": 1.25}, + {"label": "Alt", "matrix": [11, 3], "x": 7.75, "y": 5.5, "w": 1.25}, + {"label": "Space", "matrix": [11, 5], "x": 9, "y": 5.5, "w": 6.25}, + {"label": "Alt", "matrix": [11, 7], "x": 15.25, "y": 5.5, "w": 1.5}, + {"label": "GUI", "matrix": [10, 8], "x": 16.75, "y": 5.5, "w": 1.25}, + {"label": "Ctrl", "matrix": [11, 8], "x": 18, "y": 5.5, "w": 1.5} ] } } diff --git a/keyboards/aeboards/aegis/keymaps/default/keymap.c b/keyboards/aeboards/aegis/keymaps/default/keymap.c index 8437ffeb4ed5..0aa14fdea8ef 100644 --- a/keyboards/aeboards/aegis/keymaps/default/keymap.c +++ b/keyboards/aeboards/aegis/keymaps/default/keymap.c @@ -33,7 +33,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * | | 0 | left |Dn| rhgt | FN | Alt | Space |Alt |Gui| ctrl| | * `------------------------------------------------------------------------------------' */ - [0] = LAYOUT_aegis( + [0] = LAYOUT_all( KC_END , KC_HOME, KC_PGDN, KC_PGUP, 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_PMNS, KC_PAST, KC_PSLS, KC_BSPC, 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_BSLS, KC_DEL, KC_PPLS, KC_P9 , KC_P8 , KC_P7 , 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_BSPC, @@ -42,7 +42,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { KC_PENT, KC_PDOT, KC_P0 , KC_LEFT, KC_DOWN, KC_RGHT, MO(1), KC_LALT, KC_SPC, KC_RALT, KC_RGUI, KC_RCTL ), - [1] = LAYOUT_aegis( + [1] = LAYOUT_all( KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PGDN, KC_UP , KC_PGDN, KC_BSPC, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, @@ -51,7 +51,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS ), - [2] = LAYOUT_aegis( + [2] = LAYOUT_all( KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, @@ -60,7 +60,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS ), - [3] = LAYOUT_aegis( + [3] = LAYOUT_all( KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, diff --git a/keyboards/aeboards/aegis/keymaps/default_2u_bs_275u_rshift/keymap.c b/keyboards/aeboards/aegis/keymaps/default_2u_bs_275u_rshift/keymap.c new file mode 100644 index 000000000000..f43df66f2301 --- /dev/null +++ b/keyboards/aeboards/aegis/keymaps/default_2u_bs_275u_rshift/keymap.c @@ -0,0 +1,72 @@ +/* Copyright 2018 Jason Williams (Wilba) + * + * 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 . + */ +#include QMK_KEYBOARD_H + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + /* Keymap BASE: (Base Layer) Default Layer + * ,-------------------. ,-------------------------------------------------------------. + * |End |Home|PgDn|PgUp| |Esc| F1| F2| F3| F4| | F5| F6| F7| F8| | F9|F10|F11|F12| + * `-------------------' `-------------------------------------------------------------' + * + * |-------------------| ,-------------------------------------------------------------. + * | - | * | / |BSPC| | ~ | 1 | 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| Bcksp | + * |-------------------| |-------------------------------------------------------------| + * | + | 9 | 8 | 7 | |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \ | + * |-------------------| |-------------------------------------------------------------| + * | + | 6 | 5 | 4 | |Ctrl | A| S| D| F| G| H| J| K| L| ;| '|Return | + * |-------------------| |-------------------------------------------------------------| + * |Ent | 3 | 2 | 1 | |Up| |Shift| Z| X| C| V| B| N| M| ,| .| /| Shift | + * |------------------------------------------------------------------------------------| + * |Ent | . | 0 | left |Dn| rhgt | FN | Alt | Space |Alt |Gui| ctrl| + * `------------------------------------------------------------------------------------' + */ + [0] = LAYOUT_2u_bs_275u_rshift( + KC_END , KC_HOME, KC_PGDN, KC_PGUP, 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_PMNS, KC_PAST, KC_PSLS, KC_BSPC, 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_PPLS, KC_P9 , KC_P8 , KC_P7 , 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_PPLS, KC_P6 , KC_P5 , KC_P4 , KC_LCTL, 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_PENT, KC_P3 , KC_P2 , KC_P1 , KC_UP , KC_LSFT, KC_Z , KC_X , KC_C , KC_V , KC_B , KC_N , KC_M , KC_COMM, KC_DOT , KC_SLSH, KC_RSFT, + KC_PENT, KC_PDOT, KC_P0 , KC_LEFT, KC_DOWN, KC_RGHT, MO(1), KC_LALT, KC_SPC, KC_RALT, KC_RGUI, KC_RCTL + ), + + [1] = LAYOUT_2u_bs_275u_rshift( + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PGDN, KC_UP , KC_PGDN, KC_BSPC, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_ENT , KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPRV, KC_MPLY, KC_MNXT, KC_VOLD, KC_VOLU, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS + ), + + [2] = LAYOUT_2u_bs_275u_rshift( + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS + ), + + [3] = LAYOUT_2u_bs_275u_rshift( + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS + ) + +}; diff --git a/keyboards/aeboards/aegis/keymaps/default_numpad/keymap.c b/keyboards/aeboards/aegis/keymaps/default_numpad/keymap.c new file mode 100644 index 000000000000..3ee23cf8c295 --- /dev/null +++ b/keyboards/aeboards/aegis/keymaps/default_numpad/keymap.c @@ -0,0 +1,72 @@ +/* Copyright 2018 Jason Williams (Wilba) + * + * 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 . + */ +#include QMK_KEYBOARD_H + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + /* Keymap BASE: (Base Layer) Default Layer + * ,-------------------. ,-------------------------------------------------------------. + * |End |Home|PgDn|PgUp| |Esc| F1| F2| F3| F4| | F5| F6| F7| F8| | F9|F10|F11|F12| + * `-------------------' `-------------------------------------------------------------' + * + * |-------------------| ,-------------------------------------------------------------. + * |- | * | / |BSPC| | ~ | 1 | 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|pipe| del| + * |-------------------| |-------------------------------------------------------------| + * | | 9 | 8 | 7 | |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| BSPC | + * | + |--------------| |-------------------------------------------------------------| + * | | 6 | 5 | 4 | |Ctrl | A| S| D| F| G| H| J| K| L| ;| '|Return | + * |-------------------| |-------------------------------------------------------------| + * | | 3 | 2 | 1 | |Up| |Shift| Z| X| C| V| B| N| M| ,| .| /|Shift | FN | + * | ENT|-------------------------------------------------------------------------------| + * | | . | 0 | left |Dn| rhgt | FN | Alt | Space |Alt |Gui| ctrl| | + * `------------------------------------------------------------------------------------' + */ + [0] = LAYOUT_numpad( + KC_END , KC_HOME, KC_PGDN, KC_PGUP, 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_PMNS, KC_PAST, KC_PSLS, KC_BSPC, 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_BSLS, KC_DEL, + KC_PPLS, KC_P9 , KC_P8 , KC_P7 , 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_BSPC, + KC_P6 , KC_P5 , KC_P4 , KC_LCTL, 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_PENT, KC_P3 , KC_P2 , KC_P1 , KC_UP , KC_LSFT, KC_Z , KC_X , KC_C , KC_V , KC_B , KC_N , KC_M , KC_COMM, KC_DOT , KC_SLSH, KC_RSFT, MO(1), + KC_PDOT, KC_P0 , KC_LEFT, KC_DOWN, KC_RGHT, MO(1), KC_LALT, KC_SPC, KC_RALT, KC_RGUI, KC_RCTL + ), + + [1] = LAYOUT_numpad( + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PGDN, KC_UP , KC_PGDN, KC_BSPC, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_ENT , KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPRV, KC_MPLY, KC_MNXT, KC_VOLD, KC_VOLU, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS + ), + + [2] = LAYOUT_numpad( + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS + ), + + [3] = LAYOUT_numpad( + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS + ) + +}; diff --git a/keyboards/aeboards/aegis/keymaps/via/keymap.c b/keyboards/aeboards/aegis/keymaps/via/keymap.c index 8437ffeb4ed5..0aa14fdea8ef 100644 --- a/keyboards/aeboards/aegis/keymaps/via/keymap.c +++ b/keyboards/aeboards/aegis/keymaps/via/keymap.c @@ -33,7 +33,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * | | 0 | left |Dn| rhgt | FN | Alt | Space |Alt |Gui| ctrl| | * `------------------------------------------------------------------------------------' */ - [0] = LAYOUT_aegis( + [0] = LAYOUT_all( KC_END , KC_HOME, KC_PGDN, KC_PGUP, 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_PMNS, KC_PAST, KC_PSLS, KC_BSPC, 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_BSLS, KC_DEL, KC_PPLS, KC_P9 , KC_P8 , KC_P7 , 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_BSPC, @@ -42,7 +42,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { KC_PENT, KC_PDOT, KC_P0 , KC_LEFT, KC_DOWN, KC_RGHT, MO(1), KC_LALT, KC_SPC, KC_RALT, KC_RGUI, KC_RCTL ), - [1] = LAYOUT_aegis( + [1] = LAYOUT_all( KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PGDN, KC_UP , KC_PGDN, KC_BSPC, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, @@ -51,7 +51,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS ), - [2] = LAYOUT_aegis( + [2] = LAYOUT_all( KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, @@ -60,7 +60,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS ), - [3] = LAYOUT_aegis( + [3] = LAYOUT_all( KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, diff --git a/keyboards/aeboards/aegis/matrix_diagram.md b/keyboards/aeboards/aegis/matrix_diagram.md new file mode 100644 index 000000000000..d768f6615313 --- /dev/null +++ b/keyboards/aeboards/aegis/matrix_diagram.md @@ -0,0 +1,32 @@ +# Matrix Diagram for AEboards Aegis + +``` +┌───┬───┬───┬───┐ ┌───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ +│00 │10 │01 │11 │ │02 │ │12 │03 │13 │04 │ │14 │05 │15 │06 │ │16 │07 │17 │08 │ +└───┴───┴───┴───┘ └───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ +┌───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐ ┌───────┐ +│20 │30 │21 │31 │ │22 │32 │23 │33 │24 │34 │25 │35 │26 │36 │27 │37 │28 │38 │18 │ │38 │ 2u Backspace +├───┼───┼───┼───┤ ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┤ └───────┘ +│40 │50 │41 │51 │ │42 │52 │43 │53 │44 │54 │45 │55 │46 │56 │47 │57 │48 │58 │ +├───┼───┼───┼───┤ ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤ +│60 │70 │61 │71 │ │62 │72 │63 │73 │64 │74 │65 │75 │66 │76 │67 │77 │68 │ +├───┼───┼───┼───┤ └───┬──┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────┬───┤ ┌──────────┐ +│80 │90 │81 │91 │┌───┐│92 │83 │93 │84 │94 │85 │95 │86 │96 │87 │97 │88 │98 │ │88 │ 2.75u RShift +├───┼───┼───┼───┘│82 │└───┬┴───┼───┴┬──┴───┴───┴───┴───┴───┴─┬─┴───┼────┬─┴───┤ └──────────┘ +│A0 │B0 │A1 │┌───┼───┼───┐│A3 │B3 │B5 │B7 │A8 │B8 │ +└───┴───┴───┘│B1 │A2 │B2 │└────┴────┴────────────────────────┴─────┴────┴─────┘ + └───┴───┴───┘ + ┌───┬───┬───────────────────────────┬─────┬───┬─────┐ + │A3 │B3 │B5 │B7 │A8 │B8 │ 7u Space + └───┴───┴───────────────────────────┴─────┴───┴─────┘ +[NUMPAD OPTIONS]─────────────────── +┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ +│40 │50 │41 │51 │ │ │50 │41 │51 │ +├───┼───┼───┼───┤ │60 ├───┼───┼───┤ +│60 │70 │61 │ │ │ │70 │61 │71 │ +├───┼───┼───┤91 │ ├───┼───┼───┼───┤ +│80 │90 │81 │ │ │ │90 │81 │91 │ +├───┴───┼───┼───┘ │80 ├───┴───┼───┘ +│A0 │A1 │ │ │A1 │ +└───────┴───┘ └───┴───────┘ +``` From 7e6ad6d28cedfea7a019fa60175af87e5c2c08e7 Mon Sep 17 00:00:00 2001 From: Danny Date: Thu, 18 May 2023 06:29:06 -0400 Subject: [PATCH 03/19] Add Cepstrum Rev. 1 Keyboard (#20721) Co-authored-by: Drashna Jaelre --- keyboards/keebio/cepstrum/info.json | 122 ++++++++++ .../keebio/cepstrum/keymaps/default/keymap.c | 21 ++ .../keebio/cepstrum/keymaps/via/keymap.c | 21 ++ .../keebio/cepstrum/keymaps/via/rules.mk | 2 + keyboards/keebio/cepstrum/readme.md | 27 +++ keyboards/keebio/cepstrum/rev1/config.h | 65 ++++++ keyboards/keebio/cepstrum/rev1/halconf.h | 21 ++ keyboards/keebio/cepstrum/rev1/info.json | 212 ++++++++++++++++++ keyboards/keebio/cepstrum/rev1/mcuconf.h | 9 + keyboards/keebio/cepstrum/rev1/rules.mk | 2 + 10 files changed, 502 insertions(+) create mode 100644 keyboards/keebio/cepstrum/info.json create mode 100644 keyboards/keebio/cepstrum/keymaps/default/keymap.c create mode 100644 keyboards/keebio/cepstrum/keymaps/via/keymap.c create mode 100644 keyboards/keebio/cepstrum/keymaps/via/rules.mk create mode 100644 keyboards/keebio/cepstrum/readme.md create mode 100644 keyboards/keebio/cepstrum/rev1/config.h create mode 100644 keyboards/keebio/cepstrum/rev1/halconf.h create mode 100644 keyboards/keebio/cepstrum/rev1/info.json create mode 100644 keyboards/keebio/cepstrum/rev1/mcuconf.h create mode 100644 keyboards/keebio/cepstrum/rev1/rules.mk diff --git a/keyboards/keebio/cepstrum/info.json b/keyboards/keebio/cepstrum/info.json new file mode 100644 index 000000000000..61d1b43f8b3d --- /dev/null +++ b/keyboards/keebio/cepstrum/info.json @@ -0,0 +1,122 @@ +{ + "manufacturer": "Keebio", + "url": "https://keeb.io", + "maintainer": "nooges", + "usb": { + "vid": "0xCB10" + }, + "features": { + "bootmagic": true, + "command": false, + "console": true, + "extrakey": true, + "mousekey": true, + "nkro": false + }, + "split": { + "enabled": true + }, + "build": { + "lto": true + }, + "layouts": { + "LAYOUT_65xt": { + "layout": [ + {"label":"F1", "x":0, "y":0}, + {"label":"F2", "x":1, "y":0}, + + {"label":"Esc", "x":2.25, "y":0}, + {"label":"1", "x":3.25, "y":0}, + {"label":"2", "x":4.25, "y":0}, + {"label":"3", "x":5.25, "y":0}, + {"label":"4", "x":6.25, "y":0}, + {"label":"5", "x":7.25, "y":0}, + {"label":"6", "x":8.25, "y":0}, + + {"label":"7", "x":10.25, "y":0}, + {"label":"8", "x":11.25, "y":0}, + {"label":"9", "x":12.25, "y":0}, + {"label":"0", "x":13.25, "y":0}, + {"label":"-", "x":14.25, "y":0}, + {"label":"=", "x":15.25, "y":0}, + {"label":"Bksp", "x":17.25, "y":0, "w": 2}, + {"label":"Del", "x":18.25, "y":0}, + + {"label":"F3", "x":0, "y":1}, + {"label":"F4", "x":1, "y":1}, + + {"label":"Tab", "x":2.25, "y":1, "w":1.5}, + {"label":"Q", "x":3.75, "y":1}, + {"label":"W", "x":4.75, "y":1}, + {"label":"E", "x":5.75, "y":1}, + {"label":"R", "x":6.75, "y":1}, + {"label":"T", "x":7.75, "y":1}, + + {"label":"Y", "x":9.75, "y":1}, + {"label":"U", "x":10.75, "y":1}, + {"label":"I", "x":11.75, "y":1}, + {"label":"O", "x":12.75, "y":1}, + {"label":"P", "x":13.75, "y":1}, + {"label":"{", "x":14.75, "y":1}, + {"label":"}", "x":15.75, "y":1}, + {"label":"|", "x":16.75, "y":1, "w":1.5}, + {"label":"Home", "x":18.25, "y":1}, + + {"label":"F5", "x":0, "y":2}, + {"label":"F6", "x":1, "y":2}, + + {"label":"Caps Lock", "x":2.25, "y":2, "w":1.75}, + {"label":"A", "x":4, "y":2}, + {"label":"S", "x":5, "y":2}, + {"label":"D", "x":6, "y":2}, + {"label":"F", "x":7, "y":2}, + {"label":"G", "x":8, "y":2}, + + {"label":"H", "x":10, "y":2}, + {"label":"J", "x":11, "y":2}, + {"label":"K", "x":12, "y":2}, + {"label":"L", "x":13, "y":2}, + {"label":":", "x":14, "y":2}, + {"label":"\"", "x":15, "y":2}, + {"label":"Enter", "x":16, "y":2, "w":2.25}, + {"label":"PgUp", "x":18.25, "y":2}, + + {"label":"F7", "x":0, "y":3}, + {"label":"F8", "x":1, "y":3}, + + {"label":"Shift", "x":2.25, "y":3, "w":2.25}, + {"label":"Z", "x":4.5, "y":3}, + {"label":"X", "x":5.5, "y":3}, + {"label":"C", "x":6.5, "y":3}, + {"label":"V", "x":7.5, "y":3}, + {"label":"B", "x":8.5, "y":3}, + + {"label":"N", "x":10.5, "y":3}, + {"label":"M", "x":11.5, "y":3}, + {"label":",", "x":12.5, "y":3}, + {"label":".", "x":13.5, "y":3}, + {"label":"/", "x":14.5, "y":3}, + {"label":"Shift", "x":15.5, "y":3, "w":1.75}, + {"label":"Up", "x":17.25, "y":3}, + {"label":"PgDn", "x":18.25, "y":3}, + + {"label":"F9", "x":0, "y":4}, + {"label":"F10", "x":1, "y":4}, + + {"label":"Ctrl", "x":2.25, "y":4, "w":1.25}, + {"label":"Win", "x":3.5, "y":4, "w":1.25}, + {"label":"Alt", "x":4.75, "y":4, "w":1.25}, + {"label":"Fn", "x":6, "y":4, "w":1.25}, + {"label":"Space", "x":7.25, "y":4}, + + {"label":"Space", "x":11.75, "y":4, "w":1.5}, + {"label":"Alt", "x":13.25, "y":4}, + {"label":"Fn", "x":14.25, "y":4}, + {"label":"Ctrl", "x":15.25, "y":4}, + {"label":"Left", "x":16.25, "y":4}, + {"label":"Down", "x":17.25, "y":4}, + {"label":"Right", "x":18.25, "y":4} + ] + } + } +} diff --git a/keyboards/keebio/cepstrum/keymaps/default/keymap.c b/keyboards/keebio/cepstrum/keymaps/default/keymap.c new file mode 100644 index 000000000000..e8fc2e29c95b --- /dev/null +++ b/keyboards/keebio/cepstrum/keymaps/default/keymap.c @@ -0,0 +1,21 @@ +// Copyright 2023 Danny Nguyen (danny@keeb.io) +// SPDX-License-Identifier: GPL-2.0-or-later + +#include QMK_KEYBOARD_H + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + [0] = LAYOUT_65xt( + KC_F1, KC_F2, 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_F3, KC_F4, 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_HOME, + KC_F5, KC_F6, 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_PGUP, + KC_F7, KC_F8, KC_LSFT, 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_PGDN, + KC_F9, KC_F10, KC_LCTL, KC_LGUI, KC_LALT, MO(1), KC_SPC, KC_SPC, KC_RALT, MO(1), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT + ), + [1] = LAYOUT_65xt( + RGB_HUI, RGB_HUD, 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, _______, _______, + RGB_SAI, RGB_SAD, RGB_TOG, RGB_MOD, KC_UP, _______, QK_BOOT, EE_CLR, _______, _______, _______, _______, _______, _______, _______, _______, KC_END, + RGB_VAI, RGB_VAD, _______, KC_LEFT, KC_DOWN, KC_RGHT, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, EE_CLR, _______, _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ + ) +}; diff --git a/keyboards/keebio/cepstrum/keymaps/via/keymap.c b/keyboards/keebio/cepstrum/keymaps/via/keymap.c new file mode 100644 index 000000000000..e8fc2e29c95b --- /dev/null +++ b/keyboards/keebio/cepstrum/keymaps/via/keymap.c @@ -0,0 +1,21 @@ +// Copyright 2023 Danny Nguyen (danny@keeb.io) +// SPDX-License-Identifier: GPL-2.0-or-later + +#include QMK_KEYBOARD_H + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + [0] = LAYOUT_65xt( + KC_F1, KC_F2, 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_F3, KC_F4, 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_HOME, + KC_F5, KC_F6, 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_PGUP, + KC_F7, KC_F8, KC_LSFT, 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_PGDN, + KC_F9, KC_F10, KC_LCTL, KC_LGUI, KC_LALT, MO(1), KC_SPC, KC_SPC, KC_RALT, MO(1), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT + ), + [1] = LAYOUT_65xt( + RGB_HUI, RGB_HUD, 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, _______, _______, + RGB_SAI, RGB_SAD, RGB_TOG, RGB_MOD, KC_UP, _______, QK_BOOT, EE_CLR, _______, _______, _______, _______, _______, _______, _______, _______, KC_END, + RGB_VAI, RGB_VAD, _______, KC_LEFT, KC_DOWN, KC_RGHT, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, EE_CLR, _______, _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ + ) +}; diff --git a/keyboards/keebio/cepstrum/keymaps/via/rules.mk b/keyboards/keebio/cepstrum/keymaps/via/rules.mk new file mode 100644 index 000000000000..36b7ba9cbc98 --- /dev/null +++ b/keyboards/keebio/cepstrum/keymaps/via/rules.mk @@ -0,0 +1,2 @@ +VIA_ENABLE = yes +LTO_ENABLE = yes diff --git a/keyboards/keebio/cepstrum/readme.md b/keyboards/keebio/cepstrum/readme.md new file mode 100644 index 000000000000..c646c6b6ab78 --- /dev/null +++ b/keyboards/keebio/cepstrum/readme.md @@ -0,0 +1,27 @@ +# Cepstrum + +A split 65XT staggered keyboard made and sold by Keebio. [More info at Keebio](https://keeb.io). + +* Keyboard Maintainer: [Bakingpy/nooges](https://github.com/nooges) +* Hardware Availability: [Keebio](https://keeb.io/) + +Make example for this keyboard (after setting up your build environment): + + make keebio/cepstrum/rev1:default + +Example of flashing this keyboard: + + make keebio/cepstrum/rev1:default:flash + +Handedness detection is already hardwired onto the PCB, so no need to deal with `EE_HANDS` or flashing .eep files. + +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 one of these ways: + +* **Physical reset button**: Press and hold the button on the back of the PCB for at least 2 seconds and let go, or double-press the button +* **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is available + +A build guide for this keyboard can be found here: [Keebio Build Guides](https://docs.keeb.io) diff --git a/keyboards/keebio/cepstrum/rev1/config.h b/keyboards/keebio/cepstrum/rev1/config.h new file mode 100644 index 000000000000..1dedcef2b099 --- /dev/null +++ b/keyboards/keebio/cepstrum/rev1/config.h @@ -0,0 +1,65 @@ +// Copyright 2022 Danny Nguyen (danny@keeb.io) +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#define SPLIT_HAND_PIN GP4 +#define USB_VBUS_PIN GP12 +#define SERIAL_USART_FULL_DUPLEX +#define SERIAL_USART_TX_PIN GP0 +#define SERIAL_USART_RX_PIN GP1 +#define SERIAL_USART_PIN_SWAP +#define RP2040_BOOTLOADER_DOUBLE_TAP_RESET +#define RP2040_BOOTLOADER_DOUBLE_TAP_RESET_TIMEOUT 1000U +#define I2C_DRIVER I2CD2 +#define I2C1_SCL_PIN GP22 +#define I2C1_SDA_PIN GP23 + +// RGB Matrix +#define ENABLE_RGB_MATRIX_ALPHAS_MODS +#define ENABLE_RGB_MATRIX_GRADIENT_UP_DOWN +#define ENABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT +#define ENABLE_RGB_MATRIX_BREATHING +#define ENABLE_RGB_MATRIX_BAND_SAT +#define ENABLE_RGB_MATRIX_BAND_VAL +#define ENABLE_RGB_MATRIX_BAND_PINWHEEL_SAT +#define ENABLE_RGB_MATRIX_BAND_PINWHEEL_VAL +#define ENABLE_RGB_MATRIX_BAND_SPIRAL_SAT +#define ENABLE_RGB_MATRIX_BAND_SPIRAL_VAL +#define ENABLE_RGB_MATRIX_CYCLE_ALL +#define ENABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT +#define ENABLE_RGB_MATRIX_CYCLE_UP_DOWN +#define ENABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON +#define ENABLE_RGB_MATRIX_CYCLE_OUT_IN +#define ENABLE_RGB_MATRIX_CYCLE_OUT_IN_DUAL +#define ENABLE_RGB_MATRIX_CYCLE_PINWHEEL +#define ENABLE_RGB_MATRIX_CYCLE_SPIRAL +#define ENABLE_RGB_MATRIX_DUAL_BEACON +#define ENABLE_RGB_MATRIX_RAINBOW_BEACON +#define ENABLE_RGB_MATRIX_RAINBOW_PINWHEELS +// enabled only if RGB_MATRIX_FRAMEBUFFER_EFFECTS is defined +#define ENABLE_RGB_MATRIX_TYPING_HEATMAP +#define ENABLE_RGB_MATRIX_DIGITAL_RAIN +// enabled only of RGB_MATRIX_KEYPRESSES or RGB_MATRIX_KEYRELEASES is defined +#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE +#define ENABLE_RGB_MATRIX_SOLID_REACTIVE +#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE +#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE +#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS +#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS +#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS +#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS +#define ENABLE_RGB_MATRIX_SPLASH +#define ENABLE_RGB_MATRIX_MULTISPLASH +#define ENABLE_RGB_MATRIX_SOLID_SPLASH +#define ENABLE_RGB_MATRIX_SOLID_MULTISPLASH + +#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 120 +#define RGB_MATRIX_DEFAULT_VAL RGB_MATRIX_MAXIMUM_BRIGHTNESS +#define WS2812_DI_PIN GP18 +#define RGB_DI_PIN WS2812_DI_PIN +#define RGB_MATRIX_LED_COUNT 96 +#define RGB_DISABLE_WHEN_USB_SUSPENDED +#define RGB_MATRIX_FRAMEBUFFER_EFFECTS +#define RGB_MATRIX_KEYPRESSES +#define SPLIT_TRANSPORT_MIRROR diff --git a/keyboards/keebio/cepstrum/rev1/halconf.h b/keyboards/keebio/cepstrum/rev1/halconf.h new file mode 100644 index 000000000000..2e098f5113d9 --- /dev/null +++ b/keyboards/keebio/cepstrum/rev1/halconf.h @@ -0,0 +1,21 @@ +/* Copyright 2022 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 . + */ + +#pragma once + +#define HAL_USE_I2C TRUE + +#include_next diff --git a/keyboards/keebio/cepstrum/rev1/info.json b/keyboards/keebio/cepstrum/rev1/info.json new file mode 100644 index 000000000000..a9f8c83d12d3 --- /dev/null +++ b/keyboards/keebio/cepstrum/rev1/info.json @@ -0,0 +1,212 @@ +{ + "keyboard_name": "Cepstrum Rev. 1", + "usb": {"pid": "0x1557", "device_version": "1.0.0"}, + "processor": "RP2040", + "bootloader": "rp2040", + "diode_direction": "COL2ROW", + "features": { + "rgb_matrix": true + }, + "split": { + "enabled": true, + "matrix_pins": { + "right": { + "cols": ["GP29", "GP28", "GP27", "GP26", "GP25", "GP21", "GP15", "GP9", "GP10"], + "rows": ["GP2", "GP3", "GP5", "GP8", "GP19"] + } + } + }, + "matrix_pins": { + "cols": ["GP29", "GP28", "GP27", "GP2", "GP3", "GP5", "GP6", "GP7", "GP8"], + "rows": ["GP26", "GP25", "GP21", "GP20", "GP19"] + }, + "layouts": { + "LAYOUT_65xt": { + "layout": [ + { "label": "F1", "matrix": [0, 0], "w": 1, "x": 0, "y": 0 }, + { "label": "F2", "matrix": [0, 1], "w": 1, "x": 1, "y": 0 }, + { "label": "Esc", "matrix": [0, 2], "w": 1, "x": 2.25, "y": 0 }, + { "label": "1", "matrix": [0, 3], "w": 1, "x": 3.25, "y": 0 }, + { "label": "2", "matrix": [0, 4], "w": 1, "x": 4.25, "y": 0 }, + { "label": "3", "matrix": [0, 5], "w": 1, "x": 5.25, "y": 0 }, + { "label": "4", "matrix": [0, 6], "w": 1, "x": 6.25, "y": 0 }, + { "label": "5", "matrix": [0, 7], "w": 1, "x": 7.25, "y": 0 }, + { "label": "6", "matrix": [0, 8], "w": 1, "x": 8.25, "y": 0 }, + { "label": "7", "matrix": [5, 0], "w": 1, "x": 10.25, "y": 0 }, + { "label": "8", "matrix": [5, 1], "w": 1, "x": 11.25, "y": 0 }, + { "label": "9", "matrix": [5, 2], "w": 1, "x": 12.25, "y": 0 }, + { "label": "0", "matrix": [5, 3], "w": 1, "x": 13.25, "y": 0 }, + { "label": "-", "matrix": [5, 4], "w": 1, "x": 14.25, "y": 0 }, + { "label": "=", "matrix": [5, 5], "w": 1, "x": 15.25, "y": 0 }, + { "label": "Bksp", "matrix": [5, 7], "w": 2, "x": 17.25, "y": 0 }, + { "label": "Del", "matrix": [5, 8], "w": 1, "x": 18.25, "y": 0 }, + { "label": "F3", "matrix": [1, 0], "w": 1, "x": 0, "y": 1 }, + { "label": "F4", "matrix": [1, 1], "w": 1, "x": 1, "y": 1 }, + { "label": "Tab", "matrix": [1, 2], "w": 1.5, "x": 2.25, "y": 1 }, + { "label": "Q", "matrix": [1, 3], "w": 1, "x": 3.75, "y": 1 }, + { "label": "W", "matrix": [1, 4], "w": 1, "x": 4.75, "y": 1 }, + { "label": "E", "matrix": [1, 5], "w": 1, "x": 5.75, "y": 1 }, + { "label": "R", "matrix": [1, 6], "w": 1, "x": 6.75, "y": 1 }, + { "label": "T", "matrix": [1, 7], "w": 1, "x": 7.75, "y": 1 }, + { "label": "Y", "matrix": [6, 0], "w": 1, "x": 9.75, "y": 1 }, + { "label": "U", "matrix": [6, 1], "w": 1, "x": 10.75, "y": 1 }, + { "label": "I", "matrix": [6, 2], "w": 1, "x": 11.75, "y": 1 }, + { "label": "O", "matrix": [6, 3], "w": 1, "x": 12.75, "y": 1 }, + { "label": "P", "matrix": [6, 4], "w": 1, "x": 13.75, "y": 1 }, + { "label": "{", "matrix": [6, 5], "w": 1, "x": 14.75, "y": 1 }, + { "label": "}", "matrix": [6, 6], "w": 1, "x": 15.75, "y": 1 }, + { "label": "|", "matrix": [6, 7], "w": 1.5, "x": 16.75, "y": 1 }, + { "label": "Home", "matrix": [6, 8], "w": 1, "x": 18.25, "y": 1 }, + { "label": "F5", "matrix": [2, 0], "w": 1, "x": 0, "y": 2 }, + { "label": "F6", "matrix": [2, 1], "w": 1, "x": 1, "y": 2 }, + { "label": "Caps Lock", "matrix": [2, 2], "w": 1.75, "x": 2.25, "y": 2 }, + { "label": "A", "matrix": [2, 3], "w": 1, "x": 4, "y": 2 }, + { "label": "S", "matrix": [2, 4], "w": 1, "x": 5, "y": 2 }, + { "label": "D", "matrix": [2, 5], "w": 1, "x": 6, "y": 2 }, + { "label": "F", "matrix": [2, 6], "w": 1, "x": 7, "y": 2 }, + { "label": "G", "matrix": [2, 7], "w": 1, "x": 8, "y": 2 }, + { "label": "H", "matrix": [7, 0], "w": 1, "x": 10, "y": 2 }, + { "label": "J", "matrix": [7, 1], "w": 1, "x": 11, "y": 2 }, + { "label": "K", "matrix": [7, 2], "w": 1, "x": 12, "y": 2 }, + { "label": "L", "matrix": [7, 3], "w": 1, "x": 13, "y": 2 }, + { "label": ":", "matrix": [7, 4], "w": 1, "x": 14, "y": 2 }, + { "label": "\"", "matrix": [7, 5], "w": 1, "x": 15, "y": 2 }, + { "label": "Enter", "matrix": [7, 7], "w": 2.25, "x": 16, "y": 2 }, + { "label": "PgUp", "matrix": [7, 8], "w": 1, "x": 18.25, "y": 2 }, + { "label": "F7", "matrix": [3, 0], "w": 1, "x": 0, "y": 3 }, + { "label": "F8", "matrix": [3, 1], "w": 1, "x": 1, "y": 3 }, + { "label": "Shift", "matrix": [3, 2], "w": 2.25, "x": 2.25, "y": 3 }, + { "label": "Z", "matrix": [3, 4], "w": 1, "x": 4.5, "y": 3 }, + { "label": "X", "matrix": [3, 5], "w": 1, "x": 5.5, "y": 3 }, + { "label": "C", "matrix": [3, 6], "w": 1, "x": 6.5, "y": 3 }, + { "label": "V", "matrix": [3, 7], "w": 1, "x": 7.5, "y": 3 }, + { "label": "B", "matrix": [3, 8], "w": 1, "x": 8.5, "y": 3 }, + { "label": "N", "matrix": [8, 0], "w": 1, "x": 10.5, "y": 3 }, + { "label": "M", "matrix": [8, 1], "w": 1, "x": 11.5, "y": 3 }, + { "label": ",", "matrix": [8, 2], "w": 1, "x": 12.5, "y": 3 }, + { "label": ".", "matrix": [8, 3], "w": 1, "x": 13.5, "y": 3 }, + { "label": "/", "matrix": [8, 4], "w": 1, "x": 14.5, "y": 3 }, + { "label": "Shift", "matrix": [8, 6], "w": 1.75, "x": 15.5, "y": 3 }, + { "label": "Up", "matrix": [8, 7], "w": 1, "x": 17.25, "y": 3 }, + { "label": "PgDn", "matrix": [8, 8], "w": 1, "x": 18.25, "y": 3 }, + { "label": "F9", "matrix": [4, 0], "w": 1, "x": 0, "y": 4 }, + { "label": "F10", "matrix": [4, 1], "w": 1, "x": 1, "y": 4 }, + { "label": "Ctrl", "matrix": [4, 2], "w": 1.25, "x": 2.25, "y": 4 }, + { "label": "Win", "matrix": [4, 3], "w": 1.25, "x": 3.5, "y": 4 }, + { "label": "Alt", "matrix": [4, 4], "w": 1.25, "x": 4.75, "y": 4 }, + { "label": "Fn", "matrix": [4, 5], "w": 1.25, "x": 6, "y": 4 }, + { "label": "Space", "matrix": [4, 7], "w": 1, "x": 7.25, "y": 4 }, + { "label": "Space", "matrix": [9, 1], "w": 1.5, "x": 11.75, "y": 4 }, + { "label": "Alt", "matrix": [9, 2], "w": 1, "x": 13.25, "y": 4 }, + { "label": "Fn", "matrix": [9, 3], "w": 1, "x": 14.25, "y": 4 }, + { "label": "Ctrl", "matrix": [9, 4], "w": 1, "x": 15.25, "y": 4 }, + { "label": "Left", "matrix": [9, 6], "w": 1, "x": 16.25, "y": 4 }, + { "label": "Down", "matrix": [9, 7], "w": 1, "x": 17.25, "y": 4 }, + { "label": "Right", "matrix": [9, 8], "w": 1, "x": 18.25, "y": 4 } + ] + } + }, + "rgb_matrix": { + "driver": "WS2812", + "split_count": [48, 48], + "layout": [ + {"flags":2, "x":46, "y":0}, + {"flags":2, "x":71, "y":0}, + {"flags":2, "x":95, "y":0}, + {"flags":2, "x":83, "y":57}, + {"flags":2, "x":68, "y":57}, + {"flags":2, "x":37, "y":57}, + {"matrix": [0,2], "flags":4, "x":28, "y":4}, + {"matrix": [0,3], "flags":4, "x":40, "y":4}, + {"matrix": [0,4], "flags":4, "x":52, "y":4}, + {"matrix": [0,5], "flags":4, "x":64, "y":4}, + {"matrix": [0,6], "flags":4, "x":77, "y":4}, + {"matrix": [0,7], "flags":4, "x":89, "y":4}, + {"matrix": [0,8], "flags":4, "x":101, "y":4}, + {"matrix": [1,7], "flags":4, "x":95, "y":18}, + {"matrix": [1,6], "flags":4, "x":83, "y":18}, + {"matrix": [1,5], "flags":4, "x":71, "y":18}, + {"matrix": [1,4], "flags":4, "x":58, "y":18}, + {"matrix": [1,3], "flags":4, "x":46, "y":18}, + {"matrix": [1,2], "flags":4, "x":31, "y":18}, + {"matrix": [2,2], "flags":4, "x":32, "y":32}, + {"matrix": [2,3], "flags":4, "x":49, "y":32}, + {"matrix": [2,4], "flags":4, "x":61, "y":32}, + {"matrix": [2,5], "flags":4, "x":74, "y":32}, + {"matrix": [2,6], "flags":4, "x":86, "y":32}, + {"matrix": [2,7], "flags":4, "x":98, "y":32}, + {"matrix": [3,8], "flags":4, "x":104, "y":46}, + {"matrix": [3,7], "flags":4, "x":92, "y":46}, + {"matrix": [3,6], "flags":4, "x":80, "y":46}, + {"matrix": [3,5], "flags":4, "x":68, "y":46}, + {"matrix": [3,4], "flags":4, "x":55, "y":46}, + {"matrix": [3,2], "flags":4, "x":35, "y":46}, + {"matrix": [4,2], "flags":4, "x":29, "y":60}, + {"matrix": [4,3], "flags":4, "x":44, "y":60}, + {"matrix": [4,4], "flags":4, "x":60, "y":60}, + {"matrix": [4,5], "flags":4, "x":75, "y":60}, + {"matrix": [4,7], "flags":4, "x":97, "y":60}, + {"matrix": [4,1], "flags":4, "x":12, "y":60}, + {"matrix": [4,0], "flags":4, "x":0, "y":60}, + {"flags":2, "x":6, "y":53}, + {"matrix": [3,1], "flags":4, "x":12, "y":46}, + {"matrix": [3,0], "flags":4, "x":0, "y":46}, + {"matrix": [2,0], "flags":4, "x":0, "y":32}, + {"matrix": [2,1], "flags":4, "x":12, "y":32}, + {"matrix": [1,1], "flags":4, "x":12, "y":18}, + {"matrix": [1,0], "flags":4, "x":0, "y":18}, + {"flags":2, "x":6, "y":14}, + {"matrix": [0,1], "flags":4, "x":12, "y":4}, + {"matrix": [0,0], "flags":4, "x":0, "y":4}, + + {"flags":2, "x":221, "y":11}, + {"matrix": [5,8], "flags":4, "x":224, "y":4}, + {"matrix": [5,7], "flags":4, "x":206, "y":4}, + {"flags":2, "x":193, "y":0}, + {"matrix": [5,5], "flags":4, "x":187, "y":4}, + {"matrix": [5,4], "flags":4, "x":175, "y":4}, + {"flags":2, "x":169, "y":0}, + {"matrix": [5,3], "flags":4, "x":163, "y":4}, + {"matrix": [5,2], "flags":4, "x":150, "y":4}, + {"flags":2, "x":144, "y":0}, + {"matrix": [5,1], "flags":4, "x":138, "y":4}, + {"matrix": [5,0], "flags":4, "x":126, "y":4}, + {"matrix": [6,0], "flags":4, "x":120, "y":18}, + {"matrix": [6,1], "flags":4, "x":132, "y":18}, + {"matrix": [6,2], "flags":4, "x":144, "y":18}, + {"matrix": [6,3], "flags":4, "x":156, "y":18}, + {"matrix": [6,4], "flags":4, "x":169, "y":18}, + {"matrix": [6,5], "flags":4, "x":181, "y":18}, + {"matrix": [6,6], "flags":4, "x":193, "y":18}, + {"matrix": [6,7], "flags":4, "x":209, "y":18}, + {"matrix": [6,8], "flags":4, "x":224, "y":18}, + {"matrix": [7,8], "flags":4, "x":224, "y":32}, + {"matrix": [7,7], "flags":4, "x":204, "y":32}, + {"matrix": [7,5], "flags":4, "x":184, "y":32}, + {"matrix": [7,4], "flags":4, "x":172, "y":32}, + {"matrix": [7,3], "flags":4, "x":160, "y":32}, + {"matrix": [7,2], "flags":4, "x":147, "y":32}, + {"matrix": [7,1], "flags":4, "x":135, "y":32}, + {"matrix": [7,0], "flags":4, "x":123, "y":32}, + {"matrix": [8,0], "flags":4, "x":129, "y":46}, + {"matrix": [8,1], "flags":4, "x":141, "y":46}, + {"matrix": [8,2], "flags":4, "x":153, "y":46}, + {"matrix": [8,3], "flags":4, "x":166, "y":46}, + {"matrix": [8,4], "flags":4, "x":178, "y":46}, + {"matrix": [8,6], "flags":4, "x":195, "y":46}, + {"matrix": [8,7], "flags":4, "x":212, "y":46}, + {"matrix": [8,8], "flags":4, "x":224, "y":46}, + {"matrix": [9,8], "flags":4, "x":224, "y":60}, + {"flags":2, "x":218, "y":57}, + {"matrix": [9,7], "flags":4, "x":212, "y":60}, + {"matrix": [9,6], "flags":4, "x":199, "y":60}, + {"flags":2, "x":193, "y":57}, + {"matrix": [9,4], "flags":4, "x":187, "y":60}, + {"matrix": [9,3], "flags":4, "x":173, "y":60}, + {"flags":2, "x":166, "y":64}, + {"matrix": [9,2], "flags":4, "x":158, "y":60}, + {"matrix": [9,1], "flags":4, "x":137, "y":60}, + {"flags":2, "x":126, "y":64}, + ] + } +} diff --git a/keyboards/keebio/cepstrum/rev1/mcuconf.h b/keyboards/keebio/cepstrum/rev1/mcuconf.h new file mode 100644 index 000000000000..c8a510784cda --- /dev/null +++ b/keyboards/keebio/cepstrum/rev1/mcuconf.h @@ -0,0 +1,9 @@ +// Copyright 2022 Danny Nguyen (danny@keeb.io) +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include_next + +#undef RP_I2C_USE_I2C1 +#define RP_I2C_USE_I2C1 TRUE diff --git a/keyboards/keebio/cepstrum/rev1/rules.mk b/keyboards/keebio/cepstrum/rev1/rules.mk new file mode 100644 index 000000000000..8fb51ec82d52 --- /dev/null +++ b/keyboards/keebio/cepstrum/rev1/rules.mk @@ -0,0 +1,2 @@ +SERIAL_DRIVER = vendor +WS2812_DRIVER = vendor From b50abd370ddc301c7781de4c7360f79ee0b57e0d Mon Sep 17 00:00:00 2001 From: Danny Date: Thu, 18 May 2023 11:49:35 -0400 Subject: [PATCH 04/19] Define RGB_DI_PIN directly instead of using another define (#20983) --- keyboards/keebio/cepstrum/rev1/config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keyboards/keebio/cepstrum/rev1/config.h b/keyboards/keebio/cepstrum/rev1/config.h index 1dedcef2b099..7650feba851c 100644 --- a/keyboards/keebio/cepstrum/rev1/config.h +++ b/keyboards/keebio/cepstrum/rev1/config.h @@ -57,7 +57,7 @@ #define RGB_MATRIX_MAXIMUM_BRIGHTNESS 120 #define RGB_MATRIX_DEFAULT_VAL RGB_MATRIX_MAXIMUM_BRIGHTNESS #define WS2812_DI_PIN GP18 -#define RGB_DI_PIN WS2812_DI_PIN +#define RGB_DI_PIN GP18 #define RGB_MATRIX_LED_COUNT 96 #define RGB_DISABLE_WHEN_USB_SUSPENDED #define RGB_MATRIX_FRAMEBUFFER_EFFECTS From a4771e4fe4479869a997b130c1435ee072cbc2fa Mon Sep 17 00:00:00 2001 From: adophoxia <100170946+adophoxia@users.noreply.github.com> Date: Thu, 18 May 2023 09:21:07 -0700 Subject: [PATCH 05/19] [Keyboard] Add Fancytech Fancyalice66 (#20647) Co-authored-by: Joel Challis Co-authored-by: Ryan Co-authored-by: jack <0x6a73@protonmail.com> Co-authored-by: Drashna Jaelre --- keyboards/fancytech/fancyalice66/config.h | 14 + .../fancytech/fancyalice66/fancyalice66.c | 29 +++ keyboards/fancytech/fancyalice66/info.json | 244 ++++++++++++++++++ .../fancyalice66/keymaps/default/keymap.c | 49 ++++ .../fancyalice66/keymaps/via/keymap.c | 57 ++++ .../fancyalice66/keymaps/via/rules.mk | 1 + keyboards/fancytech/fancyalice66/readme.md | 27 ++ keyboards/fancytech/fancyalice66/rules.mk | 1 + 8 files changed, 422 insertions(+) create mode 100644 keyboards/fancytech/fancyalice66/config.h create mode 100644 keyboards/fancytech/fancyalice66/fancyalice66.c create mode 100644 keyboards/fancytech/fancyalice66/info.json create mode 100644 keyboards/fancytech/fancyalice66/keymaps/default/keymap.c create mode 100644 keyboards/fancytech/fancyalice66/keymaps/via/keymap.c create mode 100644 keyboards/fancytech/fancyalice66/keymaps/via/rules.mk create mode 100644 keyboards/fancytech/fancyalice66/readme.md create mode 100644 keyboards/fancytech/fancyalice66/rules.mk diff --git a/keyboards/fancytech/fancyalice66/config.h b/keyboards/fancytech/fancyalice66/config.h new file mode 100644 index 000000000000..b6fcea0c6bc3 --- /dev/null +++ b/keyboards/fancytech/fancyalice66/config.h @@ -0,0 +1,14 @@ +// Copyright 2022 chent7 (@chent7) +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#ifdef RGB_MATRIX_ENABLE +# define WS2812_DI_PIN B0 +# define RGB_DI_PIN B0 +# define RGB_MATRIX_LED_COUNT 82 + + /* RGB Matrix effect */ +# define RGB_MATRIX_KEYPRESSES // reacts to keypresses +# define RGB_MATRIX_FRAMEBUFFER_EFFECTS +#endif \ No newline at end of file diff --git a/keyboards/fancytech/fancyalice66/fancyalice66.c b/keyboards/fancytech/fancyalice66/fancyalice66.c new file mode 100644 index 000000000000..72e5355a3112 --- /dev/null +++ b/keyboards/fancytech/fancyalice66/fancyalice66.c @@ -0,0 +1,29 @@ +/* Copyright 2023 Adophoxia + * + * 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 . + */ + +#include "quantum.h" + +#ifdef RGB_MATRIX_ENABLE +bool rgb_matrix_indicators_kb(void) { + if (!rgb_matrix_indicators_user()) { + return false; + } + if (host_keyboard_led_state().caps_lock) { + rgb_matrix_set_color(43, 0xFF, 0xFF, 0xFF); + } + return true; +} +#endif \ No newline at end of file diff --git a/keyboards/fancytech/fancyalice66/info.json b/keyboards/fancytech/fancyalice66/info.json new file mode 100644 index 000000000000..1be7f3763941 --- /dev/null +++ b/keyboards/fancytech/fancyalice66/info.json @@ -0,0 +1,244 @@ +{ + "manufacturer": "Fancytech", + "keyboard_name": "FancyAlice66", + "maintainer": "Adophoxia", + "bootloader": "caterina", + "diode_direction": "ROW2COL", + "encoder": { + "rotary": [ + {"pin_a": "F0", "pin_b": "F1", "resolution": 2} + ] + }, + "features": { + "bootmagic": true, + "encoder": false, + "extrakey": true, + "lto": true, + "mousekey": true, + "nkro": true, + "rgb_matrix": true + }, + "matrix_pins": { + "cols": ["C6", "E6", "B5", "B4", "D7", "D6", "D4", "D5", "D3", "D2", "D1", "D0", "B7", "B3", "B2", "B1"], + "rows": ["F4", "F5", "F6", "F7", "C7"] + }, + "processor": "atmega32u4", + "rgb_matrix": { + "animations": { + "alphas_mods": true, + "band_pinwheel_sat": true, + "band_pinwheel_val": true, + "band_sat": true, + "band_spiral_sat": true, + "band_spiral_val": true, + "band_val": true, + "breathing": true, + "cycle_all": true, + "cycle_left_right": true, + "cycle_out_in": true, + "cycle_out_in_dual": true, + "cycle_pinwheel": true, + "cycle_spiral": true, + "cycle_up_down": true, + "dual_beacon": true, + "gradient_left_right": true, + "gradient_up_down": true, + "hue_breathing": true, + "hue_pendulum": true, + "hue_wave": true, + "jellybean_raindrops": true, + "multisplash": true, + "pixel_fractal": true, + "pixel_rain": true, + "rainbow_beacon": true, + "rainbow_moving_chevron": true, + "rainbow_pinwheels": true, + "raindrops": true, + "solid_multisplash": true, + "solid_reactive": true, + "solid_reactive_cross": true, + "solid_reactive_multicross": true, + "solid_reactive_multinexus": true, + "solid_reactive_multiwide": true, + "solid_reactive_nexus": true, + "solid_reactive_simple": true, + "solid_reactive_wide": true, + "solid_splash": true, + "splash": true + }, + "driver": "WS2812", + "layout": [ + {"flags": 1, "matrix": [0, 0], "x": 0, "y": 0}, + {"flags": 4, "matrix": [0, 1], "x": 15, "y": 0}, + {"flags": 4, "matrix": [0, 2], "x": 30, "y": 0}, + {"flags": 4, "matrix": [0, 3], "x": 45, "y": 0}, + {"flags": 4, "matrix": [0, 4], "x": 60, "y": 0}, + {"flags": 4, "matrix": [0, 5], "x": 75, "y": 0}, + {"flags": 4, "matrix": [0, 6], "x": 90, "y": 0}, + {"flags": 4, "matrix": [0, 7], "x": 105, "y": 0}, + {"flags": 4, "matrix": [0, 8], "x": 120, "y": 0}, + {"flags": 4, "matrix": [0, 9], "x": 135, "y": 0}, + {"flags": 4, "matrix": [0, 10], "x": 150, "y": 0}, + {"flags": 4, "matrix": [0, 11], "x": 164, "y": 0}, + {"flags": 4, "matrix": [0, 12], "x": 180, "y": 0}, + {"flags": 1, "matrix": [0, 13], "x": 194, "y": 0}, + {"flags": 4, "matrix": [0, 15], "x": 224, "y": 0}, + + {"flags": 1, "matrix": [1, 0], "x": 0, "y": 16}, + {"flags": 4, "matrix": [1, 1], "x": 15, "y": 16}, + {"flags": 4, "matrix": [1, 2], "x": 30, "y": 16}, + {"flags": 4, "matrix": [1, 3], "x": 45, "y": 16}, + {"flags": 4, "matrix": [1, 4], "x": 60, "y": 16}, + {"flags": 4, "matrix": [1, 5], "x": 75, "y": 16}, + {"flags": 4, "matrix": [1, 7], "x": 105, "y": 16}, + {"flags": 4, "matrix": [1, 8], "x": 120, "y": 16}, + {"flags": 4, "matrix": [1, 9], "x": 135, "y": 16}, + {"flags": 4, "matrix": [1, 10], "x": 150, "y": 16}, + {"flags": 4, "matrix": [1, 11], "x": 164, "y": 16}, + {"flags": 4, "matrix": [1, 12], "x": 180, "y": 16}, + {"flags": 4, "matrix": [1, 13], "x": 194, "y": 16}, + {"flags": 4, "matrix": [1, 14], "x": 209, "y": 16}, + {"flags": 4, "matrix": [1, 15], "x": 224, "y": 16}, + + {"flags": 1, "matrix": [2, 0], "x": 0, "y": 32}, + {"flags": 4, "matrix": [2, 1], "x": 15, "y": 32}, + {"flags": 4, "matrix": [2, 2], "x": 30, "y": 32}, + {"flags": 4, "matrix": [2, 3], "x": 45, "y": 32}, + {"flags": 4, "matrix": [2, 4], "x": 60, "y": 32}, + {"flags": 4, "matrix": [2, 5], "x": 75, "y": 32}, + {"flags": 4, "matrix": [2, 7], "x": 105, "y": 32}, + {"flags": 4, "matrix": [2, 8], "x": 120, "y": 32}, + {"flags": 4, "matrix": [2, 9], "x": 135, "y": 32}, + {"flags": 4, "matrix": [2, 10], "x": 150, "y": 32}, + {"flags": 4, "matrix": [2, 11], "x": 164, "y": 32}, + {"flags": 4, "matrix": [2, 12], "x": 180, "y": 32}, + {"flags": 1, "matrix": [2, 13], "x": 194, "y": 32}, + {"flags": 4, "matrix": [2, 15], "x": 224, "y": 32}, + + {"flags": 1, "matrix": [3, 0], "x": 0, "y": 48}, + {"flags": 4, "matrix": [3, 1], "x": 15, "y": 48}, + {"flags": 4, "matrix": [3, 2], "x": 30, "y": 48}, + {"flags": 4, "matrix": [3, 3], "x": 45, "y": 48}, + {"flags": 4, "matrix": [3, 4], "x": 60, "y": 48}, + {"flags": 4, "matrix": [3, 5], "x": 75, "y": 48}, + {"flags": 4, "matrix": [3, 7], "x": 105, "y": 48}, + {"flags": 4, "matrix": [3, 8], "x": 120, "y": 48}, + {"flags": 4, "matrix": [3, 9], "x": 135, "y": 48}, + {"flags": 4, "matrix": [3, 10], "x": 150, "y": 48}, + {"flags": 4, "matrix": [3, 11], "x": 164, "y": 48}, + {"flags": 4, "matrix": [3, 12], "x": 180, "y": 48}, + {"flags": 4, "matrix": [3, 14], "x": 209, "y": 48}, + + {"flags": 1, "matrix": [4, 0], "x": 0, "y": 64}, + {"flags": 1, "matrix": [4, 2], "x": 30, "y": 64}, + {"flags": 4, "matrix": [4, 3], "x": 45, "y": 64}, + {"flags": 1, "matrix": [4, 6], "x": 90, "y": 64}, + {"flags": 4, "matrix": [4, 7], "x": 105, "y": 64}, + {"flags": 1, "matrix": [4, 10], "x": 150, "y": 64}, + {"flags": 4, "matrix": [4, 13], "x": 194, "y": 64}, + {"flags": 4, "matrix": [4, 14], "x": 209, "y": 64}, + {"flags": 4, "matrix": [4, 15], "x": 224, "y": 64}, + + {"flags": 2, "x": 37, "y": 64}, + {"flags": 2, "x": 75, "y": 64}, + {"flags": 2, "x": 112, "y": 64}, + {"flags": 2, "x": 149, "y": 64}, + {"flags": 2, "x": 187, "y": 64}, + {"flags": 2, "x": 224, "y": 64}, + {"flags": 2, "x": 224, "y": 32}, + {"flags": 2, "x": 224, "y": 0}, + {"flags": 2, "x": 187, "y": 0}, + {"flags": 2, "x": 149, "y": 0}, + {"flags": 2, "x": 112, "y": 0}, + {"flags": 2, "x": 75, "y": 0}, + {"flags": 2, "x": 37, "y": 0}, + {"flags": 2, "x": 0, "y": 0}, + {"flags": 2, "x": 0, "y": 32}, + {"flags": 2, "x": 0, "y": 64} + ], + "max_brightness": 200 + }, + "url": "https://www.aliexpress.com/item/1005004272392611.html", + "usb": { + "device_version": "0.0.1", + "force_nkro": true, + "pid": "0x3663", + "vid": "0xECED" + }, + "layouts": { + "LAYOUT": { + "layout": [ + {"matrix": [0, 0], "x": 0.75, "y": 0.5}, + {"matrix": [0, 1], "x": 1.75, "y": 0.5}, + {"matrix": [0, 2], "x": 2.75, "y": 0.25}, + {"matrix": [0, 3], "x": 3.75, "y": 0.5}, + {"matrix": [0, 4], "x": 4.75, "y": 0.5}, + {"matrix": [0, 5], "x": 5.75, "y": 0.5}, + {"matrix": [0, 6], "x": 6.75, "y": 0.5}, + {"matrix": [0, 7], "x": 8.75, "y": 0.5}, + {"matrix": [0, 8], "x": 9.75, "y": 0.5}, + {"matrix": [0, 9], "x": 10.75, "y": 0.5}, + {"matrix": [0, 10], "x": 11.75, "y": 0.5}, + {"matrix": [0, 11], "x": 12.75, "y": 0.25}, + {"matrix": [0, 12], "x": 13.75, "y": 0.5}, + {"matrix": [0, 13], "w": 2, "x": 14.75, "y": 0.5}, + {"matrix": [0, 15], "x": 17, "y": 0}, + + {"matrix": [1, 0], "w": 1.5, "x": 0.5, "y": 1.5}, + {"matrix": [1, 1], "x": 2, "y": 1.5}, + {"matrix": [1, 2], "x": 3.25, "y": 1.5}, + {"matrix": [1, 3], "x": 4.25, "y": 1.5}, + {"matrix": [1, 4], "x": 5.25, "y": 1.5}, + {"matrix": [1, 5], "x": 6.25, "y": 1.5}, + {"matrix": [1, 7], "x": 8.5, "y": 1.5}, + {"matrix": [1, 8], "x": 9.5, "y": 1.5}, + {"matrix": [1, 9], "x": 10.5, "y": 1.5}, + {"matrix": [1, 10], "x": 11.5, "y": 1.5}, + {"matrix": [1, 11], "x": 12.5, "y": 1.5}, + {"matrix": [1, 12], "x": 13.5, "y": 1.5}, + {"matrix": [1, 13], "x": 14.5, "y": 1.5}, + {"matrix": [1, 14], "w": 1.5, "x": 15.5, "y": 1.5}, + {"matrix": [1, 15], "x": 17.25, "y": 1}, + + {"matrix": [2, 0], "w": 1.75, "x": 0.25, "y": 2.5}, + {"matrix": [2, 1], "x": 2, "y": 2.5}, + {"matrix": [2, 2], "x": 3.5, "y": 2.5}, + {"matrix": [2, 3], "x": 4.5, "y": 2.5}, + {"matrix": [2, 4], "x": 5.5, "y": 2.5}, + {"matrix": [2, 5], "x": 6.5, "y": 2.5}, + {"matrix": [2, 7], "x": 8.75, "y": 2.5}, + {"matrix": [2, 8], "x": 9.75, "y": 2.5}, + {"matrix": [2, 9], "x": 10.75, "y": 2.5}, + {"matrix": [2, 10], "x": 11.75, "y": 2.5}, + {"matrix": [2, 11], "x": 13, "y": 2.5}, + {"matrix": [2, 12], "x": 14, "y": 2.5}, + {"matrix": [2, 13], "w": 2.25, "x": 15, "y": 2.5}, + {"matrix": [2, 15], "x": 17.5, "y": 2}, + + {"matrix": [3, 0], "w": 2.25, "x": 0, "y": 3.5}, + {"matrix": [3, 1], "x": 2.25, "y": 3.5}, + {"matrix": [3, 2], "x": 3.75, "y": 3.5}, + {"matrix": [3, 3], "x": 4.75, "y": 3.5}, + {"matrix": [3, 4], "x": 5.75, "y": 3.5}, + {"matrix": [3, 5], "x": 6.75, "y": 3.5}, + {"matrix": [3, 7], "x": 9, "y": 3.5}, + {"matrix": [3, 8], "x": 10, "y": 3.5}, + {"matrix": [3, 9], "x": 11, "y": 3.5}, + {"matrix": [3, 10], "x": 12, "y": 3.5}, + {"matrix": [3, 11], "x": 13.25, "y": 3.5}, + {"matrix": [3, 12], "w": 1.75, "x": 14.25, "y": 3.5}, + {"matrix": [3, 14], "x": 16.25, "y": 3.75}, + + {"matrix": [4, 0], "w": 1.5, "x": 0, "y": 4.5}, + {"matrix": [4, 2], "w": 1.5, "x": 3.5, "y": 4.5}, + {"matrix": [4, 3], "w": 2.25, "x": 5, "y": 4.5}, + {"matrix": [4, 6], "x": 7.25, "y": 4.5}, + {"matrix": [4, 7], "w": 2.75, "x": 8.75, "y": 4.5}, + {"matrix": [4, 10], "w": 1.5, "x": 11.5, "y": 4.5}, + {"matrix": [4, 13], "x": 15.25, "y": 4.75}, + {"matrix": [4, 14], "x": 16.25, "y": 4.75}, + {"matrix": [4, 15], "x": 17.25, "y": 4.75} + ] + } + } +} \ No newline at end of file diff --git a/keyboards/fancytech/fancyalice66/keymaps/default/keymap.c b/keyboards/fancytech/fancyalice66/keymaps/default/keymap.c new file mode 100644 index 000000000000..0fed76c1b311 --- /dev/null +++ b/keyboards/fancytech/fancyalice66/keymaps/default/keymap.c @@ -0,0 +1,49 @@ +/* Copyright 2023 Adophoxia + * + * 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 . + */ + +#include QMK_KEYBOARD_H +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + + /* + * ┌───┬───┬───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┬───┬───────┐ ┌───┐ + * │Esc│ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ │ 7 │ 8 │ 9 │ 0 │ - │ = │Backsp │ │Del│ + * ┌┴───┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┘ ┌─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┴┐ └┬──┴┐ + * │ Tab │ Q │ W │ E │ R │ T │ │ Y │ U │ I │ O │ P │ [ │ ] │ \ │ │PgD│ + * ┌┴─────┼───┼───┼───┼───┼───┤ └┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴──────┴┐ └┬──┴┐ + * │ Caps │ A │ S │ D │ F │ G │ │ H │ J │ K │ L │ ; │ ' │ Enter │ │PgU│ + * ┌┴──────┴┬──┴┬──┴┬──┴┬──┴┬──┴┐ └─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───────┬─┬┴──┼───┘ + * │ Shift │ Z │ X │ C │ V │ B │ │ N │ M │ , │ . │ / │ Shift │ │Up │ + * ├─────┬──┴───┼───┴─┬─┴───┴─┬─┴─┐ ┌─┴───┴───┴┬──┴──┬┴───┴───────┬─┴─┼───┼───┐ + * │ Ctl │ │ Alt │ │FN │ │ │ Alt │ │Lft│Dwn│Rgt│ + * └─────┘ └─────┴───────┴───┘ └──────────┴─────┘ └───┴───┴───┘ + */ + + [0] = LAYOUT( + KC_ESC, 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, + KC_LSFT, 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_LALT, KC_SPC, MO(1), KC_SPC, KC_RALT, KC_LEFT, KC_DOWN, KC_RGHT + ), + + [1] = LAYOUT( + KC_TILD, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, QK_BOOT, KC_PSCR, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, RGB_SAI, RGB_SAD, RGB_TOG, RGB_HUI, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, RGB_HUD, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, RGB_VAI, + _______, _______, _______, _______, _______, RGB_MOD, _______, RGB_VAD, _______ + ) +}; \ No newline at end of file diff --git a/keyboards/fancytech/fancyalice66/keymaps/via/keymap.c b/keyboards/fancytech/fancyalice66/keymaps/via/keymap.c new file mode 100644 index 000000000000..1d32c8f5e85d --- /dev/null +++ b/keyboards/fancytech/fancyalice66/keymaps/via/keymap.c @@ -0,0 +1,57 @@ +/* Copyright 2023 Adophoxia + * + * 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 . + */ + +#include QMK_KEYBOARD_H + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + + /* + * ┌───┬───┬───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┬───┬───────┐ ┌───┐ + * │Esc│ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ │ 7 │ 8 │ 9 │ 0 │ - │ = │Backsp │ │Del│ + * ┌┴───┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┘ ┌─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┴┐ └┬──┴┐ + * │ Tab │ Q │ W │ E │ R │ T │ │ Y │ U │ I │ O │ P │ [ │ ] │ \ │ │PgD│ + * ┌┴─────┼───┼───┼───┼───┼───┤ └┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴──────┴┐ └┬──┴┐ + * │ Caps │ A │ S │ D │ F │ G │ │ H │ J │ K │ L │ ; │ ' │ Enter │ │PgU│ + * ┌┴──────┴┬──┴┬──┴┬──┴┬──┴┬──┴┐ └─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───────┬─┬┴──┼───┘ + * │ Shift │ Z │ X │ C │ V │ B │ │ N │ M │ , │ . │ / │ Shift │ │Up │ + * ├─────┬──┴───┼───┴─┬─┴───┴─┬─┴─┐ ┌─┴───┴───┴┬──┴──┬┴───┴───────┬─┴─┼───┼───┐ + * │ Ctl │ │ Alt │ │FN │ │ │ Alt │ │Lft│Dwn│Rgt│ + * └─────┘ └─────┴───────┴───┘ └──────────┴─────┘ └───┴───┴───┘ + */ + + [0] = LAYOUT( + KC_ESC, 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, + KC_LSFT, 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_LALT, KC_SPC, MO(1), KC_SPC, KC_RALT, KC_LEFT, KC_DOWN, KC_RGHT + ), + + [1] = LAYOUT( + KC_TILD, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, QK_BOOT, KC_PSCR, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, RGB_SAI, RGB_SAD, RGB_TOG, RGB_HUI, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, RGB_HUD, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, RGB_VAI, + _______, _______, _______, _______, _______, RGB_MOD, _______, RGB_VAD, _______ + ) +}; + +#if defined(ENCODER_MAP_ENABLE) +const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = { + [0] = { ENCODER_CCW_CW(KC_VOLD, KC_VOLU) }, + [1] = { ENCODER_CCW_CW(KC_TRNS, KC_TRNS) } +}; +#endif \ No newline at end of file diff --git a/keyboards/fancytech/fancyalice66/keymaps/via/rules.mk b/keyboards/fancytech/fancyalice66/keymaps/via/rules.mk new file mode 100644 index 000000000000..036bd6d1c3ec --- /dev/null +++ b/keyboards/fancytech/fancyalice66/keymaps/via/rules.mk @@ -0,0 +1 @@ +VIA_ENABLE = yes \ No newline at end of file diff --git a/keyboards/fancytech/fancyalice66/readme.md b/keyboards/fancytech/fancyalice66/readme.md new file mode 100644 index 000000000000..b81f1841cf14 --- /dev/null +++ b/keyboards/fancytech/fancyalice66/readme.md @@ -0,0 +1,27 @@ +# FancyAlice66 + +![FancyAlice66](https://i.imgur.com/kg0TUlIh.jpeg) + +FancyAlice66 is a Alice layout mechanical keyboard produced by FancyTech, powered by ATM32U4. + +* Keyboard Maintainer: [Adophoxia](https://github.com/Adophoxia) +* Hardware Supported: FancyAlice66 PCB (Atmega32U4) +* Hardware Availability: [AliExpress](https://www.aliexpress.com/item/1005004272392611.html) [TaoBao](https://item.taobao.com/item.htm?spm=a1z09.2.0.0.13892e8dGQ8r0o&id=674705234595) + +Make example for this keyboard (after setting up your build environment): + + make fancytech/fancyalice66:default + +Flashing example for this keyboard: + + make fancytech/fancyalice66: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 (usually the top left key or Escape) and plug in the keyboard +* **Physical reset button**: Briefly press the button on the back of the PCB - some may have pads you must short instead +* **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is available diff --git a/keyboards/fancytech/fancyalice66/rules.mk b/keyboards/fancytech/fancyalice66/rules.mk new file mode 100644 index 000000000000..7ff128fa692e --- /dev/null +++ b/keyboards/fancytech/fancyalice66/rules.mk @@ -0,0 +1 @@ +# This file intentionally left blank \ No newline at end of file From dc75c23f5c4768d48e6e77fb4e795ff0e0ee2d7f Mon Sep 17 00:00:00 2001 From: Ryan Date: Fri, 19 May 2023 16:05:43 +1000 Subject: [PATCH 06/19] CLI: Improve keymap folder resolution (#20981) --- lib/python/qmk/cli/new/keymap.py | 8 ++++---- lib/python/qmk/importers.py | 4 ++-- lib/python/qmk/keymap.py | 4 ++-- lib/python/qmk/path.py | 25 ++++++++++++++++++++++--- lib/python/qmk/tests/test_qmk_path.py | 4 ++-- 5 files changed, 32 insertions(+), 13 deletions(-) diff --git a/lib/python/qmk/cli/new/keymap.py b/lib/python/qmk/cli/new/keymap.py index e7823bc46dd2..9b0ac221a4ae 100755 --- a/lib/python/qmk/cli/new/keymap.py +++ b/lib/python/qmk/cli/new/keymap.py @@ -5,7 +5,7 @@ from milc import cli from milc.questions import question -from qmk.path import is_keyboard, keymap +from qmk.path import is_keyboard, keymaps, keymap from qmk.git import git_get_username from qmk.decorators import automagic_keyboard, automagic_keymap from qmk.keyboard import keyboard_completer, keyboard_folder @@ -50,9 +50,9 @@ def new_keymap(cli): return False # generate keymap paths - km_path = keymap(kb_name) - keymap_path_default = km_path / 'default' - keymap_path_new = km_path / user_name + keymaps_dirs = keymaps(kb_name) + keymap_path_default = keymap(kb_name, 'default') + keymap_path_new = keymaps_dirs[0] / user_name if not keymap_path_default.exists(): cli.log.error(f'Default keymap {{fg_cyan}}{keymap_path_default}{{fg_reset}} does not exist!') diff --git a/lib/python/qmk/importers.py b/lib/python/qmk/importers.py index 307c66ee3ccd..edc1f940daa6 100644 --- a/lib/python/qmk/importers.py +++ b/lib/python/qmk/importers.py @@ -5,7 +5,7 @@ from qmk.git import git_get_username from qmk.json_schema import validate -from qmk.path import keyboard, keymap +from qmk.path import keyboard, keymaps from qmk.constants import MCU2BOOTLOADER, LEGACY_KEYCODES from qmk.json_encoders import InfoJSONEncoder, KeymapJSONEncoder from qmk.json_schema import deep_update, json_load @@ -84,7 +84,7 @@ def import_keymap(keymap_data): kb_name = keymap_data['keyboard'] km_name = keymap_data['keymap'] - km_folder = keymap(kb_name) / km_name + km_folder = keymaps(kb_name)[0] / km_name keyboard_keymap = km_folder / 'keymap.json' # This is the deepest folder in the expected tree diff --git a/lib/python/qmk/keymap.py b/lib/python/qmk/keymap.py index 825267a1fe71..11e8d39dadf5 100644 --- a/lib/python/qmk/keymap.py +++ b/lib/python/qmk/keymap.py @@ -379,7 +379,7 @@ def write_json(keyboard, keymap, layout, layers, macros=None): """ keymap_json = generate_json(keyboard, keymap, layout, layers, macros=None) keymap_content = json.dumps(keymap_json) - keymap_file = qmk.path.keymap(keyboard) / keymap / 'keymap.json' + keymap_file = qmk.path.keymaps(keyboard)[0] / keymap / 'keymap.json' return write_file(keymap_file, keymap_content) @@ -406,7 +406,7 @@ def write(keymap_json): A list of macros for this keymap. """ keymap_content = generate_c(keymap_json) - keymap_file = qmk.path.keymap(keymap_json['keyboard']) / keymap_json['keymap'] / 'keymap.c' + keymap_file = qmk.path.keymaps(keymap_json['keyboard'])[0] / keymap_json['keymap'] / 'keymap.c' return write_file(keymap_file, keymap_content) diff --git a/lib/python/qmk/path.py b/lib/python/qmk/path.py index 556d0eefc858..9d248451b86f 100644 --- a/lib/python/qmk/path.py +++ b/lib/python/qmk/path.py @@ -36,8 +36,8 @@ def keyboard(keyboard_name): return Path('keyboards') / keyboard_name -def keymap(keyboard_name): - """Locate the correct directory for storing a keymap. +def keymaps(keyboard_name): + """Returns all of the `keymaps/` directories for a given keyboard. Args: @@ -45,17 +45,36 @@ def keymap(keyboard_name): The name of the keyboard. Example: clueboard/66/rev3 """ keyboard_folder = keyboard(keyboard_name) + found_dirs = [] for _ in range(MAX_KEYBOARD_SUBFOLDERS): if (keyboard_folder / 'keymaps').exists(): - return (keyboard_folder / 'keymaps').resolve() + found_dirs.append((keyboard_folder / 'keymaps').resolve()) keyboard_folder = keyboard_folder.parent + if len(found_dirs) > 0: + return found_dirs + logging.error('Could not find the keymaps directory!') raise NoSuchKeyboardError('Could not find keymaps directory for: %s' % keyboard_name) +def keymap(keyboard_name, keymap_name): + """Locate the directory of a given keymap. + + Args: + + keyboard_name + The name of the keyboard. Example: clueboard/66/rev3 + keymap_name + The name of the keymap. Example: default + """ + for keymap_dir in keymaps(keyboard_name): + if (keymap_dir / keymap_name).exists(): + return (keymap_dir / keymap_name).resolve() + + def normpath(path): """Returns a `pathlib.Path()` object for a given path. diff --git a/lib/python/qmk/tests/test_qmk_path.py b/lib/python/qmk/tests/test_qmk_path.py index 4b5132f13d32..cc068e39dad8 100644 --- a/lib/python/qmk/tests/test_qmk_path.py +++ b/lib/python/qmk/tests/test_qmk_path.py @@ -5,8 +5,8 @@ def test_keymap_pytest_basic(): - path = qmk.path.keymap('handwired/pytest/basic') - assert path.samefile('keyboards/handwired/pytest/basic/keymaps') + path = qmk.path.keymap('handwired/pytest/basic', 'default') + assert path.samefile('keyboards/handwired/pytest/basic/keymaps/default') def test_normpath(): From 449240f19802ab4a1a7484f90c27fc7045d57b11 Mon Sep 17 00:00:00 2001 From: Jay Greco Date: Fri, 19 May 2023 17:22:07 -0700 Subject: [PATCH 07/19] scramble: Add XOSC delay for startup (#20991) --- keyboards/nullbitsco/scramble/v2/config.h | 1 + 1 file changed, 1 insertion(+) diff --git a/keyboards/nullbitsco/scramble/v2/config.h b/keyboards/nullbitsco/scramble/v2/config.h index d3b3c44222cf..945a4da9deca 100644 --- a/keyboards/nullbitsco/scramble/v2/config.h +++ b/keyboards/nullbitsco/scramble/v2/config.h @@ -22,6 +22,7 @@ along with this program. If not, see . #define TAP_CODE_DELAY 10 /* RP2040-specific defines*/ +#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64 #define RP2040_FLASH_GENERIC_03H #define I2C1_SDA_PIN GP26 #define I2C1_SCL_PIN GP27 From d1395ca4d52ee8c510b5105917f9138a85721548 Mon Sep 17 00:00:00 2001 From: Duncan Sutherland <75046609+dunk2k@users.noreply.github.com> Date: Sat, 20 May 2023 13:06:53 +0100 Subject: [PATCH 08/19] add additional layouts to `dactyl_manuform` variants (#20688) --- .../handwired/dactyl_manuform/4x5/info.json | 50 +++++++++ .../4x5/keymaps/default/keymap.c | 20 ++++ .../handwired/dactyl_manuform/4x5/readme.md | 6 ++ .../handwired/dactyl_manuform/4x5_5/info.json | 50 +++++++++ .../handwired/dactyl_manuform/4x5_5/readme.md | 6 ++ .../handwired/dactyl_manuform/4x6_5/info.json | 101 ++++++++++++++++++ .../handwired/dactyl_manuform/4x6_5/readme.md | 7 ++ 7 files changed, 240 insertions(+) create mode 100644 keyboards/handwired/dactyl_manuform/4x5/readme.md create mode 100644 keyboards/handwired/dactyl_manuform/4x5_5/readme.md create mode 100644 keyboards/handwired/dactyl_manuform/4x6_5/readme.md diff --git a/keyboards/handwired/dactyl_manuform/4x5/info.json b/keyboards/handwired/dactyl_manuform/4x5/info.json index bb3b3e6c2c27..5fdab01ef43c 100644 --- a/keyboards/handwired/dactyl_manuform/4x5/info.json +++ b/keyboards/handwired/dactyl_manuform/4x5/info.json @@ -21,6 +21,7 @@ }, "processor": "atmega32u4", "bootloader": "caterina", + "community_layouts": ["split_3x5_3"], "layouts": { "LAYOUT": { "layout": [ @@ -84,6 +85,55 @@ {"matrix": [9, 1], "x": 8, "y": 6}, {"matrix": [9, 2], "x": 9, "y": 6} ] + }, + "LAYOUT_split_3x5_3": { + "layout": [ + {"matrix": [0, 0], "x": 0, "y": 0}, + {"matrix": [0, 1], "x": 1, "y": 0}, + {"matrix": [0, 2], "x": 2, "y": 0}, + {"matrix": [0, 3], "x": 3, "y": 0}, + {"matrix": [0, 4], "x": 4, "y": 0}, + + {"matrix": [5, 4], "x": 10, "y": 0}, + {"matrix": [5, 3], "x": 11, "y": 0}, + {"matrix": [5, 2], "x": 12, "y": 0}, + {"matrix": [5, 1], "x": 13, "y": 0}, + {"matrix": [5, 0], "x": 14, "y": 0}, + + {"matrix": [1, 0], "x": 0, "y": 1}, + {"matrix": [1, 1], "x": 1, "y": 1}, + {"matrix": [1, 2], "x": 2, "y": 1}, + {"matrix": [1, 3], "x": 3, "y": 1}, + {"matrix": [1, 4], "x": 4, "y": 1}, + + {"matrix": [6, 4], "x": 10, "y": 1}, + {"matrix": [6, 3], "x": 11, "y": 1}, + {"matrix": [6, 2], "x": 12, "y": 1}, + {"matrix": [6, 1], "x": 13, "y": 1}, + {"matrix": [6, 0], "x": 14, "y": 1}, + + {"matrix": [2, 0], "x": 0, "y": 2}, + {"matrix": [2, 1], "x": 1, "y": 2}, + {"matrix": [2, 2], "x": 2, "y": 2}, + {"matrix": [2, 3], "x": 3, "y": 2}, + {"matrix": [2, 4], "x": 4, "y": 2}, + + {"matrix": [7, 4], "x": 10, "y": 2}, + {"matrix": [7, 3], "x": 11, "y": 2}, + {"matrix": [7, 2], "x": 12, "y": 2}, + {"matrix": [7, 1], "x": 13, "y": 2}, + {"matrix": [7, 0], "x": 14, "y": 2}, + + {"matrix": [3, 3], "x": 3, "y": 4}, + {"matrix": [3, 4], "x": 4, "y": 4}, + + {"matrix": [8, 4], "x": 10, "y": 4}, + {"matrix": [8, 3], "x": 11, "y": 4}, + + {"matrix": [4, 4], "x": 5, "y": 5}, + + {"matrix": [9, 4], "x": 9, "y": 5} + ] } } } diff --git a/keyboards/handwired/dactyl_manuform/4x5/keymaps/default/keymap.c b/keyboards/handwired/dactyl_manuform/4x5/keymaps/default/keymap.c index 7f71f3db89e0..375c20824441 100644 --- a/keyboards/handwired/dactyl_manuform/4x5/keymaps/default/keymap.c +++ b/keyboards/handwired/dactyl_manuform/4x5/keymaps/default/keymap.c @@ -1,3 +1,23 @@ +/* +This is the c configuration file for the keymap + +Copyright 2012 Jun Wako +Copyright 2015 Jack Humbert + +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 . +*/ + #include QMK_KEYBOARD_H #define _BASE 0 diff --git a/keyboards/handwired/dactyl_manuform/4x5/readme.md b/keyboards/handwired/dactyl_manuform/4x5/readme.md new file mode 100644 index 000000000000..b332f63f9f53 --- /dev/null +++ b/keyboards/handwired/dactyl_manuform/4x5/readme.md @@ -0,0 +1,6 @@ +## QMK Layouts + +The following layout is supported: +| Layout | Diagram | +| :---: | :---: | +| Split_3x5_3 | ![split_3x5_3](https://i.imgur.com/vxnpauX.jpg) | diff --git a/keyboards/handwired/dactyl_manuform/4x5_5/info.json b/keyboards/handwired/dactyl_manuform/4x5_5/info.json index 00bcdff99052..7ad7118ee472 100644 --- a/keyboards/handwired/dactyl_manuform/4x5_5/info.json +++ b/keyboards/handwired/dactyl_manuform/4x5_5/info.json @@ -18,6 +18,7 @@ }, "processor": "atmega32u4", "bootloader": "atmel-dfu", + "community_layouts": ["split_3x5_3"], "layouts": { "LAYOUT": { "layout": [ @@ -79,6 +80,55 @@ {"matrix": [9, 1], "x": 6, "y": 6}, {"matrix": [9, 2], "x": 7, "y": 6} ] + }, + "LAYOUT_split_3x5_3": { + "layout": [ + {"matrix": [0, 0], "x": 0, "y": 0}, + {"matrix": [0, 1], "x": 1, "y": 0}, + {"matrix": [0, 2], "x": 2, "y": 0}, + {"matrix": [0, 3], "x": 3, "y": 0}, + {"matrix": [0, 4], "x": 4, "y": 0}, + + {"matrix": [5, 0], "x": 6, "y": 0}, + {"matrix": [5, 1], "x": 7, "y": 0}, + {"matrix": [5, 2], "x": 8, "y": 0}, + {"matrix": [5, 3], "x": 9, "y": 0}, + {"matrix": [5, 4], "x": 10, "y": 0}, + + {"matrix": [1, 0], "x": 0, "y": 1}, + {"matrix": [1, 1], "x": 1, "y": 1}, + {"matrix": [1, 2], "x": 2, "y": 1}, + {"matrix": [1, 3], "x": 3, "y": 1}, + {"matrix": [1, 4], "x": 4, "y": 1}, + + {"matrix": [6, 0], "x": 6, "y": 1}, + {"matrix": [6, 1], "x": 7, "y": 1}, + {"matrix": [6, 2], "x": 8, "y": 1}, + {"matrix": [6, 3], "x": 9, "y": 1}, + {"matrix": [6, 4], "x": 10, "y": 1}, + + {"matrix": [2, 0], "x": 0, "y": 2}, + {"matrix": [2, 1], "x": 1, "y": 2}, + {"matrix": [2, 2], "x": 2, "y": 2}, + {"matrix": [2, 3], "x": 3, "y": 2}, + {"matrix": [2, 4], "x": 4, "y": 2}, + + {"matrix": [7, 0], "x": 6, "y": 2}, + {"matrix": [7, 1], "x": 7, "y": 2}, + {"matrix": [7, 2], "x": 8, "y": 2}, + {"matrix": [7, 3], "x": 9, "y": 2}, + {"matrix": [7, 4], "x": 10, "y": 2}, + + {"matrix": [3, 3], "x": 3, "y": 4}, + + {"matrix": [8, 1], "x": 7, "y": 4}, + + {"matrix": [3, 4], "x": 3, "y": 5}, + {"matrix": [4, 4], "x": 4, "y": 5}, + + {"matrix": [9, 0], "x": 6, "y": 5}, + {"matrix": [8, 0], "x": 7, "y": 5} + ] } } } diff --git a/keyboards/handwired/dactyl_manuform/4x5_5/readme.md b/keyboards/handwired/dactyl_manuform/4x5_5/readme.md new file mode 100644 index 000000000000..8557e66214ff --- /dev/null +++ b/keyboards/handwired/dactyl_manuform/4x5_5/readme.md @@ -0,0 +1,6 @@ +## QMK Layouts + +The following layout is supported: +| Layout | Diagram | +| :---: | :---: | +| Split_3x5_3 | ![split_3x5_3](https://i.imgur.com/BHnwCkr.jpg) | diff --git a/keyboards/handwired/dactyl_manuform/4x6_5/info.json b/keyboards/handwired/dactyl_manuform/4x6_5/info.json index 63edf390aeb9..b9ebd6d7df1e 100644 --- a/keyboards/handwired/dactyl_manuform/4x6_5/info.json +++ b/keyboards/handwired/dactyl_manuform/4x6_5/info.json @@ -21,6 +21,7 @@ }, "processor": "atmega32u4", "bootloader": "caterina", + "community_layouts": ["split_3x6_3", "split_3x5_3"], "layouts": { "LAYOUT": { "layout": [ @@ -86,6 +87,106 @@ {"matrix": [9, 3], "x": 10, "y": 5}, {"matrix": [9, 1], "x": 11, "y": 5} ] + }, + "LAYOUT_split_3x6_3": { + "layout": [ + {"matrix": [0, 0], "x": 0, "y": 0}, + {"matrix": [0, 1], "x": 1, "y": 0}, + {"matrix": [0, 2], "x": 2, "y": 0}, + {"matrix": [0, 3], "x": 3, "y": 0}, + {"matrix": [0, 4], "x": 4, "y": 0}, + {"matrix": [0, 5], "x": 5, "y": 0}, + + {"matrix": [5, 0], "x": 11, "y": 0}, + {"matrix": [5, 1], "x": 12, "y": 0}, + {"matrix": [5, 2], "x": 13, "y": 0}, + {"matrix": [5, 3], "x": 14, "y": 0}, + {"matrix": [5, 4], "x": 15, "y": 0}, + {"matrix": [5, 5], "x": 16, "y": 0}, + + {"matrix": [1, 0], "x": 0, "y": 1}, + {"matrix": [1, 1], "x": 1, "y": 1}, + {"matrix": [1, 2], "x": 2, "y": 1}, + {"matrix": [1, 3], "x": 3, "y": 1}, + {"matrix": [1, 4], "x": 4, "y": 1}, + {"matrix": [1, 5], "x": 5, "y": 1}, + + {"matrix": [6, 0], "x": 11, "y": 1}, + {"matrix": [6, 1], "x": 12, "y": 1}, + {"matrix": [6, 2], "x": 13, "y": 1}, + {"matrix": [6, 3], "x": 14, "y": 1}, + {"matrix": [6, 4], "x": 15, "y": 1}, + {"matrix": [6, 5], "x": 16, "y": 1}, + + {"matrix": [2, 0], "x": 0, "y": 2}, + {"matrix": [2, 1], "x": 1, "y": 2}, + {"matrix": [2, 2], "x": 2, "y": 2}, + {"matrix": [2, 3], "x": 3, "y": 2}, + {"matrix": [2, 4], "x": 4, "y": 2}, + {"matrix": [2, 5], "x": 5, "y": 2}, + + {"matrix": [7, 0], "x": 11, "y": 2}, + {"matrix": [7, 1], "x": 12, "y": 2}, + {"matrix": [7, 2], "x": 13, "y": 2}, + {"matrix": [7, 3], "x": 14, "y": 2}, + {"matrix": [7, 4], "x": 15, "y": 2}, + {"matrix": [7, 5], "x": 16, "y": 2}, + + {"matrix": [3, 4], "x": 4, "y": 4}, + {"matrix": [4, 5], "x": 5, "y": 4}, + {"matrix": [4, 3], "x": 6, "y": 4}, + + {"matrix": [9, 2], "x": 10, "y": 4}, + {"matrix": [9, 0], "x": 11, "y": 4}, + {"matrix": [8, 1], "x": 12, "y": 4} + ] + }, + "LAYOUT_split_3x5_3": { + "layout": [ + {"matrix": [0, 1], "x": 0, "y": 0}, + {"matrix": [0, 2], "x": 1, "y": 0}, + {"matrix": [0, 3], "x": 2, "y": 0}, + {"matrix": [0, 4], "x": 3, "y": 0}, + {"matrix": [0, 5], "x": 4, "y": 0}, + + {"matrix": [5, 0], "x": 10, "y": 0}, + {"matrix": [5, 1], "x": 11, "y": 0}, + {"matrix": [5, 2], "x": 12, "y": 0}, + {"matrix": [5, 3], "x": 13, "y": 0}, + {"matrix": [5, 4], "x": 14, "y": 0}, + + {"matrix": [1, 1], "x": 0, "y": 1}, + {"matrix": [1, 2], "x": 1, "y": 1}, + {"matrix": [1, 3], "x": 2, "y": 1}, + {"matrix": [1, 4], "x": 3, "y": 1}, + {"matrix": [1, 5], "x": 4, "y": 1}, + + {"matrix": [6, 0], "x": 10, "y": 1}, + {"matrix": [6, 1], "x": 11, "y": 1}, + {"matrix": [6, 2], "x": 12, "y": 1}, + {"matrix": [6, 3], "x": 13, "y": 1}, + {"matrix": [6, 4], "x": 14, "y": 1}, + + {"matrix": [2, 1], "x": 0, "y": 2}, + {"matrix": [2, 2], "x": 1, "y": 2}, + {"matrix": [2, 3], "x": 2, "y": 2}, + {"matrix": [2, 4], "x": 3, "y": 2}, + {"matrix": [2, 5], "x": 4, "y": 2}, + + {"matrix": [7, 0], "x": 10, "y": 2}, + {"matrix": [7, 1], "x": 11, "y": 2}, + {"matrix": [7, 2], "x": 12, "y": 2}, + {"matrix": [7, 3], "x": 13, "y": 2}, + {"matrix": [7, 4], "x": 14, "y": 2}, + + {"matrix": [3, 4], "x": 4, "y": 3}, + {"matrix": [4, 5], "x": 5, "y": 3}, + {"matrix": [4, 3], "x": 6, "y": 3}, + + {"matrix": [9, 2], "x": 8, "y": 3}, + {"matrix": [9, 0], "x": 9, "y": 3}, + {"matrix": [8, 1], "x": 10, "y": 3} + ] } } } diff --git a/keyboards/handwired/dactyl_manuform/4x6_5/readme.md b/keyboards/handwired/dactyl_manuform/4x6_5/readme.md new file mode 100644 index 000000000000..b6db0923830f --- /dev/null +++ b/keyboards/handwired/dactyl_manuform/4x6_5/readme.md @@ -0,0 +1,7 @@ +## QMK Layouts + +The following layouts are supported: +| Layout | Diagram | +| :---: | :---: | +| Split_3x6_3 | ![split_3x6_3](https://i.imgur.com/0XmjFw9.jpg) | +| Split_3x5_3 | ![split_3x5_3](https://i.imgur.com/DYdFDKj.jpg) | From e278715f7f48e6a2e46cb3f4702b2c6eb27eb1d3 Mon Sep 17 00:00:00 2001 From: Daniel Kao Date: Sat, 20 May 2023 05:07:50 -0700 Subject: [PATCH 09/19] Support PS/2 mouse 9-bit output with MOUSE_EXTENDED_REPORT (#20734) --- drivers/ps2/ps2_mouse.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/ps2/ps2_mouse.c b/drivers/ps2/ps2_mouse.c index b32ad1e222d4..d6911d66f214 100644 --- a/drivers/ps2/ps2_mouse.c +++ b/drivers/ps2/ps2_mouse.c @@ -81,10 +81,10 @@ void ps2_mouse_task(void) { rcv = ps2_host_send(PS2_MOUSE_READ_DATA); if (rcv == PS2_ACK) { mouse_report.buttons = ps2_host_recv_response(); - mouse_report.x = ps2_host_recv_response() * PS2_MOUSE_X_MULTIPLIER; - mouse_report.y = ps2_host_recv_response() * PS2_MOUSE_Y_MULTIPLIER; + mouse_report.x = ps2_host_recv_response(); + mouse_report.y = ps2_host_recv_response(); # ifdef PS2_MOUSE_ENABLE_SCROLLING - mouse_report.v = -(ps2_host_recv_response() & PS2_MOUSE_SCROLL_MASK) * PS2_MOUSE_V_MULTIPLIER; + mouse_report.v = -(ps2_host_recv_response() & PS2_MOUSE_SCROLL_MASK); # endif } else { if (debug_mouse) print("ps2_mouse: fail to get mouse packet\n"); @@ -92,10 +92,10 @@ void ps2_mouse_task(void) { #else if (pbuf_has_data()) { mouse_report.buttons = ps2_host_recv_response(); - mouse_report.x = ps2_host_recv_response() * PS2_MOUSE_X_MULTIPLIER; - mouse_report.y = ps2_host_recv_response() * PS2_MOUSE_Y_MULTIPLIER; + mouse_report.x = ps2_host_recv_response(); + mouse_report.y = ps2_host_recv_response(); # ifdef PS2_MOUSE_ENABLE_SCROLLING - mouse_report.v = -(ps2_host_recv_response() & PS2_MOUSE_SCROLL_MASK) * PS2_MOUSE_V_MULTIPLIER; + mouse_report.v = -(ps2_host_recv_response() & PS2_MOUSE_SCROLL_MASK); # endif } else { if (debug_mouse) print("ps2_mouse: fail to get mouse packet\n"); @@ -168,6 +168,7 @@ void ps2_mouse_set_sample_rate(ps2_mouse_sample_rate_t sample_rate) { #define X_IS_OVF (mouse_report->buttons & (1 << PS2_MOUSE_X_OVFLW)) #define Y_IS_OVF (mouse_report->buttons & (1 << PS2_MOUSE_Y_OVFLW)) static inline void ps2_mouse_convert_report_to_hid(report_mouse_t *mouse_report) { +#ifndef MOUSE_EXTENDED_REPORT // PS/2 mouse data is '9-bit integer'(-256 to 255) which is comprised of sign-bit and 8-bit value. // bit: 8 7 ... 0 // sign \8-bit/ @@ -175,8 +176,18 @@ static inline void ps2_mouse_convert_report_to_hid(report_mouse_t *mouse_report) // Meanwhile USB HID mouse indicates 8bit data(-127 to 127), note that -128 is not used. // // This converts PS/2 data into HID value. Use only -127-127 out of PS/2 9-bit. + mouse_report->x *= PS2_MOUSE_X_MULTIPLIER; + mouse_report->y *= PS2_MOUSE_Y_MULTIPLIER; mouse_report->x = X_IS_NEG ? ((!X_IS_OVF && -127 <= mouse_report->x && mouse_report->x <= -1) ? mouse_report->x : -127) : ((!X_IS_OVF && 0 <= mouse_report->x && mouse_report->x <= 127) ? mouse_report->x : 127); mouse_report->y = Y_IS_NEG ? ((!Y_IS_OVF && -127 <= mouse_report->y && mouse_report->y <= -1) ? mouse_report->y : -127) : ((!Y_IS_OVF && 0 <= mouse_report->y && mouse_report->y <= 127) ? mouse_report->y : 127); +#else + // Sign extend if negative, otherwise leave positive 8-bits as-is + mouse_report->x = X_IS_NEG ? (mouse_report->x | ~0xFF) : mouse_report->x; + mouse_report->y = Y_IS_NEG ? (mouse_report->y | ~0xFF) : mouse_report->y; + mouse_report->x *= PS2_MOUSE_X_MULTIPLIER; + mouse_report->y *= PS2_MOUSE_Y_MULTIPLIER; +#endif + mouse_report->v *= PS2_MOUSE_V_MULTIPLIER; #ifdef PS2_MOUSE_INVERT_BUTTONS // swap left & right buttons @@ -197,8 +208,8 @@ static inline void ps2_mouse_convert_report_to_hid(report_mouse_t *mouse_report) #endif #ifdef PS2_MOUSE_ROTATE - int8_t x = mouse_report->x; - int8_t y = mouse_report->y; + mouse_xy_report_t x = mouse_report->x; + mouse_xy_report_t y = mouse_report->y; # if PS2_MOUSE_ROTATE == 90 mouse_report->x = y; mouse_report->y = -x; From 0d844a5d4bf15746379a0c1c4bea830ec2c7a5fe Mon Sep 17 00:00:00 2001 From: Alabahuy Date: Sat, 20 May 2023 19:10:13 +0700 Subject: [PATCH 10/19] Add sriwedari70 and move kamigakushi to new folder (#20334) Co-authored-by: Ryan Co-authored-by: zacksupreme --- data/mappings/keyboard_aliases.hjson | 6 + keyboards/{ => jaykeeb}/kamigakushi/config.h | 0 keyboards/{ => jaykeeb}/kamigakushi/halconf.h | 0 keyboards/{ => jaykeeb}/kamigakushi/info.json | 0 .../kamigakushi/keymaps/default/keymap.c | 0 .../kamigakushi/keymaps/via/keymap.c | 0 .../kamigakushi/keymaps/via/rules.mk | 0 keyboards/{ => jaykeeb}/kamigakushi/mcuconf.h | 0 keyboards/{ => jaykeeb}/kamigakushi/readme.md | 4 +- keyboards/{ => jaykeeb}/kamigakushi/rules.mk | 0 keyboards/jaykeeb/sriwedari70/info.json | 148 ++++++++++++++++++ .../sriwedari70/keymaps/default/keymap.c | 41 +++++ .../jaykeeb/sriwedari70/keymaps/via/keymap.c | 49 ++++++ .../jaykeeb/sriwedari70/keymaps/via/rules.mk | 2 + keyboards/jaykeeb/sriwedari70/readme.md | 27 ++++ keyboards/jaykeeb/sriwedari70/rules.mk | 1 + keyboards/rart/rart80/keymaps/via/rules.mk | 2 - keyboards/rart/rart80/rules.mk | 2 +- 18 files changed, 277 insertions(+), 5 deletions(-) rename keyboards/{ => jaykeeb}/kamigakushi/config.h (100%) rename keyboards/{ => jaykeeb}/kamigakushi/halconf.h (100%) rename keyboards/{ => jaykeeb}/kamigakushi/info.json (100%) rename keyboards/{ => jaykeeb}/kamigakushi/keymaps/default/keymap.c (100%) rename keyboards/{ => jaykeeb}/kamigakushi/keymaps/via/keymap.c (100%) rename keyboards/{ => jaykeeb}/kamigakushi/keymaps/via/rules.mk (100%) rename keyboards/{ => jaykeeb}/kamigakushi/mcuconf.h (100%) rename keyboards/{ => jaykeeb}/kamigakushi/readme.md (92%) rename keyboards/{ => jaykeeb}/kamigakushi/rules.mk (100%) create mode 100644 keyboards/jaykeeb/sriwedari70/info.json create mode 100644 keyboards/jaykeeb/sriwedari70/keymaps/default/keymap.c create mode 100644 keyboards/jaykeeb/sriwedari70/keymaps/via/keymap.c create mode 100644 keyboards/jaykeeb/sriwedari70/keymaps/via/rules.mk create mode 100644 keyboards/jaykeeb/sriwedari70/readme.md create mode 100644 keyboards/jaykeeb/sriwedari70/rules.mk delete mode 100644 keyboards/rart/rart80/keymaps/via/rules.mk diff --git a/data/mappings/keyboard_aliases.hjson b/data/mappings/keyboard_aliases.hjson index f005bb34c399..f4ec3c6b7bec 100644 --- a/data/mappings/keyboard_aliases.hjson +++ b/data/mappings/keyboard_aliases.hjson @@ -272,6 +272,12 @@ "jones": { "target": "jones/v03_1" }, + "kamigakushi": { + "target": "jaykeeb/kamigakushi", + "layouts": { + "LAYOUT": "LAYOUT_65_ansi_blocker_tsangan" + } + }, "katana60": { "target": "rominronin/katana60/rev1" }, diff --git a/keyboards/kamigakushi/config.h b/keyboards/jaykeeb/kamigakushi/config.h similarity index 100% rename from keyboards/kamigakushi/config.h rename to keyboards/jaykeeb/kamigakushi/config.h diff --git a/keyboards/kamigakushi/halconf.h b/keyboards/jaykeeb/kamigakushi/halconf.h similarity index 100% rename from keyboards/kamigakushi/halconf.h rename to keyboards/jaykeeb/kamigakushi/halconf.h diff --git a/keyboards/kamigakushi/info.json b/keyboards/jaykeeb/kamigakushi/info.json similarity index 100% rename from keyboards/kamigakushi/info.json rename to keyboards/jaykeeb/kamigakushi/info.json diff --git a/keyboards/kamigakushi/keymaps/default/keymap.c b/keyboards/jaykeeb/kamigakushi/keymaps/default/keymap.c similarity index 100% rename from keyboards/kamigakushi/keymaps/default/keymap.c rename to keyboards/jaykeeb/kamigakushi/keymaps/default/keymap.c diff --git a/keyboards/kamigakushi/keymaps/via/keymap.c b/keyboards/jaykeeb/kamigakushi/keymaps/via/keymap.c similarity index 100% rename from keyboards/kamigakushi/keymaps/via/keymap.c rename to keyboards/jaykeeb/kamigakushi/keymaps/via/keymap.c diff --git a/keyboards/kamigakushi/keymaps/via/rules.mk b/keyboards/jaykeeb/kamigakushi/keymaps/via/rules.mk similarity index 100% rename from keyboards/kamigakushi/keymaps/via/rules.mk rename to keyboards/jaykeeb/kamigakushi/keymaps/via/rules.mk diff --git a/keyboards/kamigakushi/mcuconf.h b/keyboards/jaykeeb/kamigakushi/mcuconf.h similarity index 100% rename from keyboards/kamigakushi/mcuconf.h rename to keyboards/jaykeeb/kamigakushi/mcuconf.h diff --git a/keyboards/kamigakushi/readme.md b/keyboards/jaykeeb/kamigakushi/readme.md similarity index 92% rename from keyboards/kamigakushi/readme.md rename to keyboards/jaykeeb/kamigakushi/readme.md index e50b8563f345..d134b08cd38c 100644 --- a/keyboards/kamigakushi/readme.md +++ b/keyboards/jaykeeb/kamigakushi/readme.md @@ -10,11 +10,11 @@ PCB Mechanical keyboard replace for kamigakushi Make example for this keyboard (after setting up your build environment): - make kamigakushi:default + make jaykeeb/kamigakushi:default Flashing example for this keyboard: - make kamigakushi:default:flash + make jaykeeb/kamigakushi: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). diff --git a/keyboards/kamigakushi/rules.mk b/keyboards/jaykeeb/kamigakushi/rules.mk similarity index 100% rename from keyboards/kamigakushi/rules.mk rename to keyboards/jaykeeb/kamigakushi/rules.mk diff --git a/keyboards/jaykeeb/sriwedari70/info.json b/keyboards/jaykeeb/sriwedari70/info.json new file mode 100644 index 000000000000..c9569a9724a3 --- /dev/null +++ b/keyboards/jaykeeb/sriwedari70/info.json @@ -0,0 +1,148 @@ +{ + "manufacturer": "Jaykeeb Studio", + "keyboard_name": "sriwedari70", + "maintainer": "Alabahuy", + "bootloader": "rp2040", + "diode_direction": "COL2ROW", + "features": { + "bootmagic": true, + "command": false, + "console": false, + "extrakey": true, + "mousekey": true, + "nkro": true, + "encoder": true, + "rgblight": true + }, + "matrix_pins": { + "cols": ["GP24", "GP17", "GP16", "GP14", "GP13", "GP12", "GP11", "GP10", "GP9", "GP8", "GP7", "GP6", "GP5", "GP4", "GP3", "GP2", "GP1"], + "rows": ["GP23", "GP29", "GP15", "GP21", "GP22"] + }, + "indicators": { + "caps_lock": "GP0", + "on_state": 0 + }, + "encoder": { + "rotary": [ + {"pin_a": "GP25", "pin_b": "GP26", "resolution": 2}, + {"pin_a": "GP27", "pin_b": "GP28", "resolution": 2} + ] + }, + "rgblight": { + "led_count": 8, + "hue_steps": 8, + "saturation_steps": 8, + "brightness_steps": 8, + "max_brightness": 255, + "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 + } + }, + "ws2812": { + "pin": "GP18", + "driver": "vendor" + }, + "processor": "RP2040", + "url": "https://www.tokopedia.com/jaykeeb", + "usb": { + "device_version": "1.0.0", + "pid": "0x0770", + "vid": "0x414C" + }, + "layouts": { + "LAYOUT": { + "layout": [ + {"matrix": [0, 0], "x": 0, "y": 0}, + {"matrix": [0, 1], "x": 1, "y": 0}, + {"matrix": [0, 2], "x": 2.25, "y": 0}, + {"matrix": [0, 3], "x": 3.5, "y": 0}, + {"matrix": [0, 4], "x": 4.5, "y": 0}, + {"matrix": [0, 5], "x": 5.5, "y": 0}, + {"matrix": [0, 6], "x": 6.5, "y": 0}, + {"matrix": [0, 7], "x": 7.5, "y": 0}, + {"matrix": [0, 8], "x": 8.5, "y": 0}, + {"matrix": [0, 9], "x": 9.5, "y": 0}, + {"matrix": [0, 10], "x": 10.5, "y": 0}, + {"matrix": [0, 11], "x": 11.5, "y": 0}, + {"matrix": [0, 12], "x": 12.5, "y": 0}, + {"matrix": [0, 13], "x": 13.5, "y": 0}, + {"matrix": [0, 14], "x": 14.5, "y": 0}, + {"matrix": [0, 15], "x": 15.5, "y": 0}, + {"matrix": [0, 16], "x": 16.5, "y": 0}, + {"matrix": [1, 16], "x": 17.5, "y": 0}, + + {"matrix": [1, 0], "x": 0, "y": 1}, + {"matrix": [1, 1], "x": 1, "y": 1}, + {"matrix": [1, 2], "x": 2.25, "y": 1}, + {"matrix": [1, 3], "x": 3.5, "y": 1, "w": 1.5}, + {"matrix": [1, 4], "x": 5, "y": 1}, + {"matrix": [1, 5], "x": 6, "y": 1}, + {"matrix": [1, 6], "x": 7, "y": 1}, + {"matrix": [1, 7], "x": 8, "y": 1}, + {"matrix": [1, 8], "x": 9, "y": 1}, + {"matrix": [1, 9], "x": 10, "y": 1}, + {"matrix": [1, 10], "x": 11, "y": 1}, + {"matrix": [1, 11], "x": 12, "y": 1}, + {"matrix": [1, 12], "x": 13, "y": 1}, + {"matrix": [1, 13], "x": 14, "y": 1}, + {"matrix": [1, 14], "x": 15, "y": 1}, + {"matrix": [1, 15], "x": 16, "y": 1}, + {"matrix": [2, 16], "x": 17, "y": 1, "w": 1.5}, + + {"matrix": [2, 0], "x": 0, "y": 2}, + {"matrix": [2, 1], "x": 1, "y": 2}, + {"matrix": [2, 3], "x": 3.5, "y": 2, "w": 1.75}, + {"matrix": [2, 4], "x": 5.25, "y": 2}, + {"matrix": [2, 5], "x": 6.25, "y": 2}, + {"matrix": [2, 6], "x": 7.25, "y": 2}, + {"matrix": [2, 7], "x": 8.25, "y": 2}, + {"matrix": [2, 8], "x": 9.25, "y": 2}, + {"matrix": [2, 9], "x": 10.25, "y": 2}, + {"matrix": [2, 10], "x": 11.25, "y": 2}, + {"matrix": [2, 11], "x": 12.25, "y": 2}, + {"matrix": [2, 12], "x": 13.25, "y": 2}, + {"matrix": [2, 13], "x": 14.25, "y": 2}, + {"matrix": [2, 14], "x": 15.25, "y": 2}, + {"matrix": [2, 15], "x": 16.25, "y": 2, "w": 2.25}, + + {"matrix": [3, 0], "x": 0, "y": 3}, + {"matrix": [3, 1], "x": 1, "y": 3}, + {"matrix": [3, 2], "x": 2.25, "y": 3.25}, + {"matrix": [3, 3], "x": 3.5, "y": 3, "w": 1.25}, + {"matrix": [3, 4], "x": 4.75, "y": 3}, + {"matrix": [3, 5], "x": 5.75, "y": 3}, + {"matrix": [3, 6], "x": 6.75, "y": 3}, + {"matrix": [3, 7], "x": 7.75, "y": 3}, + {"matrix": [3, 8], "x": 8.75, "y": 3}, + {"matrix": [3, 9], "x": 9.75, "y": 3}, + {"matrix": [3, 10], "x": 10.75, "y": 3}, + {"matrix": [3, 11], "x": 11.75, "y": 3}, + {"matrix": [3, 12], "x": 12.75, "y": 3}, + {"matrix": [3, 13], "x": 13.75, "y": 3}, + {"matrix": [3, 14], "x": 14.75, "y": 3}, + {"matrix": [3, 15], "x": 15.75, "y": 3, "w": 1.75}, + {"matrix": [3, 16], "x": 17.5, "y": 3}, + + {"matrix": [4, 0], "x": 0, "y": 4}, + {"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.5, "y": 4, "w": 1.5}, + {"matrix": [4, 5], "x": 6, "y": 4, "w": 1.5}, + {"matrix": [4, 10], "x": 7.5, "y": 4, "w": 7}, + {"matrix": [4, 14], "x": 14.5, "y": 4, "w": 1.5}, + {"matrix": [4, 15], "x": 16, "y": 4}, + {"matrix": [4, 16], "x": 17, "y": 4, "w": 1.5} + ] + } + } +} \ No newline at end of file diff --git a/keyboards/jaykeeb/sriwedari70/keymaps/default/keymap.c b/keyboards/jaykeeb/sriwedari70/keymaps/default/keymap.c new file mode 100644 index 000000000000..ddb4a1cf68ff --- /dev/null +++ b/keyboards/jaykeeb/sriwedari70/keymaps/default/keymap.c @@ -0,0 +1,41 @@ +// Copyright 2023 Alabahuy (@Alabahuy) +// SPDX-License-Identifier: GPL-2.0-or-later + +#include QMK_KEYBOARD_H + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + + [0] = LAYOUT( + KC_HOME, KC_PSCR, KC_SCRL, KC_ESC, 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_GRV, + KC_PGUP, KC_PAUS, KC_INS, 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_PGDN, KC_DEL, 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_END, KC_APP, KC_UP, KC_LSFT, KC_BSLS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, MO(1), + KC_MENU, KC_LEFT, KC_DOWN, KC_RGHT, KC_LCTL, KC_LALT, KC_SPC, KC_RALT, KC_RGUI, KC_RCTL + ), + + [1] = LAYOUT( + _______, _______, _______, _______, 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, QK_BOOT, + _______, _______, _______, _______, _______, _______, _______, KC_INS, _______, _______, _______, _______, KC_PSCR, KC_SCRL, KC_PAUS, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, KC_MUTE, KC_VOLD, KC_VOLU, _______, _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ + ) + +}; + +bool encoder_update_user(uint8_t index, bool clockwise) { + if (index == 0) { /* First encoder */ + if (clockwise) { + tap_code_delay(KC_VOLU, 10); + } else { + tap_code_delay(KC_VOLD, 10); + } + } else if (index == 1) { /* Second encoder */ + if (clockwise) { + tap_code_delay(KC_BRIU, 10); + } else { + tap_code_delay(KC_BRID, 10); + } + } + return false; +} diff --git a/keyboards/jaykeeb/sriwedari70/keymaps/via/keymap.c b/keyboards/jaykeeb/sriwedari70/keymaps/via/keymap.c new file mode 100644 index 000000000000..cf4040c21d8f --- /dev/null +++ b/keyboards/jaykeeb/sriwedari70/keymaps/via/keymap.c @@ -0,0 +1,49 @@ +// Copyright 2023 Alabahuy (@Alabahuy) +// SPDX-License-Identifier: GPL-2.0-or-later + +#include QMK_KEYBOARD_H + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + + [0] = LAYOUT( + KC_HOME, KC_PSCR, KC_SCRL, KC_ESC, 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_GRV, + KC_PGUP, KC_PAUS, KC_INS, 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_PGDN, KC_DEL, 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_END, KC_APP, KC_UP, KC_LSFT, KC_BSLS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, MO(1), + KC_MENU, KC_LEFT, KC_DOWN, KC_RGHT, KC_LCTL, KC_LALT, KC_SPC, KC_RALT, KC_RGUI, KC_RCTL + ), + + [1] = LAYOUT( + _______, _______, _______, _______, 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, QK_BOOT, + _______, _______, _______, _______, _______, _______, _______, KC_INS, _______, _______, _______, _______, KC_PSCR, KC_SCRL, KC_PAUS, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, KC_MUTE, KC_VOLD, KC_VOLU, _______, _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ + ), + + [2] = LAYOUT( + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ + ), + + [3] = LAYOUT( + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ + ) + +}; + +#if defined(ENCODER_MAP_ENABLE) +const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = { + [0] = { ENCODER_CCW_CW(KC_MS_WH_UP, KC_MS_WH_DOWN), ENCODER_CCW_CW(KC_VOLD, KC_VOLU) }, + [1] = { ENCODER_CCW_CW(RGB_HUD, RGB_HUI), ENCODER_CCW_CW(RGB_SAD, RGB_SAI) }, + [2] = { ENCODER_CCW_CW(RGB_VAD, RGB_VAI), ENCODER_CCW_CW(RGB_SPD, RGB_SPI) }, + [3] = { ENCODER_CCW_CW(RGB_RMOD, RGB_MOD), ENCODER_CCW_CW(KC_RIGHT, KC_LEFT) }, +}; +#endif diff --git a/keyboards/jaykeeb/sriwedari70/keymaps/via/rules.mk b/keyboards/jaykeeb/sriwedari70/keymaps/via/rules.mk new file mode 100644 index 000000000000..f1adcab005e8 --- /dev/null +++ b/keyboards/jaykeeb/sriwedari70/keymaps/via/rules.mk @@ -0,0 +1,2 @@ +VIA_ENABLE = yes +ENCODER_MAP_ENABLE = yes diff --git a/keyboards/jaykeeb/sriwedari70/readme.md b/keyboards/jaykeeb/sriwedari70/readme.md new file mode 100644 index 000000000000..6ed7a7745034 --- /dev/null +++ b/keyboards/jaykeeb/sriwedari70/readme.md @@ -0,0 +1,27 @@ +# sriwedari70 + +![sriwedari70](https://i.imgur.com/6iPYoEqh.png) + +60% layout with 2 extra macro and arrow cluster in the left keyboard and support double encoder + +* Keyboard Maintainer: [Alabahuy](https://github.com/Alabahuy) +* Hardware Supported: Sriwedari70, RP2040, Encoder +* Hardware Availability: Private GB + +Make example for this keyboard (after setting up your build environment): + + make jaykeeb/sriwedari70:default + +Flashing example for this keyboard: + + make jaykeeb/sriwedari70: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 (usually the top left key or Escape) and plug in the keyboard +* **Physical reset button**: Briefly press the button on the back of the PCB - some may have pads you must short instead +* **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is available diff --git a/keyboards/jaykeeb/sriwedari70/rules.mk b/keyboards/jaykeeb/sriwedari70/rules.mk new file mode 100644 index 000000000000..7ff128fa692e --- /dev/null +++ b/keyboards/jaykeeb/sriwedari70/rules.mk @@ -0,0 +1 @@ +# This file intentionally left blank \ No newline at end of file diff --git a/keyboards/rart/rart80/keymaps/via/rules.mk b/keyboards/rart/rart80/keymaps/via/rules.mk deleted file mode 100644 index 36b7ba9cbc98..000000000000 --- a/keyboards/rart/rart80/keymaps/via/rules.mk +++ /dev/null @@ -1,2 +0,0 @@ -VIA_ENABLE = yes -LTO_ENABLE = yes diff --git a/keyboards/rart/rart80/rules.mk b/keyboards/rart/rart80/rules.mk index 1dfa09e016fa..044259ad5def 100644 --- a/keyboards/rart/rart80/rules.mk +++ b/keyboards/rart/rart80/rules.mk @@ -12,4 +12,4 @@ COMMAND_ENABLE = yes # Commands for debug and configuration NKRO_ENABLE = yes # Enable N-Key Rollover BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality RGBLIGHT_ENABLE = yes # Enable keyboard RGB underglow -AUDIO_ENABLE = no # Audio output \ No newline at end of file +AUDIO_ENABLE = no # Audio output From 9dec31d0561b3982cd944d6ff4682c685ccde3a9 Mon Sep 17 00:00:00 2001 From: Less/Rikki <86894501+lesshonor@users.noreply.github.com> Date: Sat, 20 May 2023 08:10:44 -0400 Subject: [PATCH 11/19] [keyboard] update ymdk/id75/rules.mk for develop (#20592) --- keyboards/ymdk/id75/rules.mk | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/keyboards/ymdk/id75/rules.mk b/keyboards/ymdk/id75/rules.mk index 61d5793cc2fc..47220e8853a9 100644 --- a/keyboards/ymdk/id75/rules.mk +++ b/keyboards/ymdk/id75/rules.mk @@ -1,9 +1,8 @@ # Configure for 128K flash -#MCU_LDSCRIPT = STM32F103xB +MCU_LDSCRIPT = STM32F103xB # Wildcard to allow APM32 MCU DFU_SUFFIX_ARGS = -p FFFF -v FFFF -WS2812_DRIVER = pwm # Enter lower-power sleep mode when on the ChibiOS idle thread OPT_DEFS += -DCORTEX_ENABLE_WFI_IDLE=TRUE From 7b31c18d464356bde219c5b3fff346f3e7a89d1a Mon Sep 17 00:00:00 2001 From: Peter Date: Sat, 20 May 2023 12:11:57 +0000 Subject: [PATCH 12/19] Fix English word list retrieval in qmk generate-autocorrect-data (#20915) --- lib/python/qmk/cli/generate/autocorrect_data.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/python/qmk/cli/generate/autocorrect_data.py b/lib/python/qmk/cli/generate/autocorrect_data.py index 5b70e0cb4e16..b11c66d95d21 100644 --- a/lib/python/qmk/cli/generate/autocorrect_data.py +++ b/lib/python/qmk/cli/generate/autocorrect_data.py @@ -63,7 +63,13 @@ def parse_file(file_name: str) -> List[Tuple[str, str]]: """ try: + import english_words + correct_words = english_words.get_english_words_set(['web2'], lower=True, alpha=True) + except AttributeError: from english_words import english_words_lower_alpha_set as correct_words + if not cli.args.quiet: + cli.echo('The english_words package is outdated, update by running:') + cli.echo(' {fg_cyan}python3 -m pip install english_words --upgrade') except ImportError: if not cli.args.quiet: cli.echo('Autocorrection will falsely trigger when a typo is a substring of a correctly spelled word.') From ab8c5013c856bfa23289d7892be1c2bee808b542 Mon Sep 17 00:00:00 2001 From: Ryan Date: Sat, 20 May 2023 22:12:59 +1000 Subject: [PATCH 13/19] BIOI G60/Morgan65: use custom Bluetooth driver (#20897) --- builddefs/common_features.mk | 4 +- data/schemas/keyboard.jsonschema | 2 +- keyboards/bioi/ble.c | 87 ++----- keyboards/bioi/ble.h | 6 - keyboards/bioi/g60/rules.mk | 15 +- keyboards/bioi/main.c | 388 ------------------------------- keyboards/bioi/morgan65/rules.mk | 15 +- 7 files changed, 43 insertions(+), 474 deletions(-) delete mode 100644 keyboards/bioi/main.c diff --git a/builddefs/common_features.mk b/builddefs/common_features.mk index 61dffb27137e..e904d6beb975 100644 --- a/builddefs/common_features.mk +++ b/builddefs/common_features.mk @@ -906,10 +906,11 @@ ifeq ($(strip $(BLUETOOTH_ENABLE)), yes) OPT_DEFS += -DBLUETOOTH_ENABLE NO_USB_STARTUP_CHECK := yes COMMON_VPATH += $(DRIVER_PATH)/bluetooth - SRC += outputselect.c bluetooth.c + SRC += outputselect.c ifeq ($(strip $(BLUETOOTH_DRIVER)), BluefruitLE) OPT_DEFS += -DBLUETOOTH_BLUEFRUIT_LE -DHAL_USE_SPI=TRUE + SRC += $(DRIVER_PATH)/bluetooth/bluetooth.c SRC += $(DRIVER_PATH)/bluetooth/bluefruit_le.cpp QUANTUM_LIB_SRC += analog.c QUANTUM_LIB_SRC += spi_master.c @@ -917,6 +918,7 @@ ifeq ($(strip $(BLUETOOTH_ENABLE)), yes) ifeq ($(strip $(BLUETOOTH_DRIVER)), RN42) OPT_DEFS += -DBLUETOOTH_RN42 -DHAL_USE_SERIAL=TRUE + SRC += $(DRIVER_PATH)/bluetooth/bluetooth.c SRC += $(DRIVER_PATH)/bluetooth/rn42.c QUANTUM_LIB_SRC += uart.c endif diff --git a/data/schemas/keyboard.jsonschema b/data/schemas/keyboard.jsonschema index d608e8f79606..ba4a7eec5570 100644 --- a/data/schemas/keyboard.jsonschema +++ b/data/schemas/keyboard.jsonschema @@ -146,7 +146,7 @@ "properties": { "driver": { "type": "string", - "enum": ["BluefruitLE", "RN42"] + "enum": ["BluefruitLE", "RN42", "custom"] } } }, diff --git a/keyboards/bioi/ble.c b/keyboards/bioi/ble.c index 7118cef8c635..12c180966a9f 100644 --- a/keyboards/bioi/ble.c +++ b/keyboards/bioi/ble.c @@ -12,35 +12,17 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#include -#include "report.h" -#include "host.h" -#include "host_driver.h" -#include "keyboard.h" -#include "action.h" -#include "led.h" - -#include "sendchar.h" -#include "debug.h" -#ifdef SLEEP_LED_ENABLE -#include "sleep_led.h" -#endif -#include "suspend.h" - -#include "usb_descriptor.h" -#include "lufa.h" -#include "quantum.h" -#include - -#include "print.h" - +#include "bluetooth.h" #include "ble.h" #include "usart.h" +#include "progmem.h" +#include "wait.h" +#include "debug.h" +#include "usb_descriptor.h" +#include "report.h" keyboard_config_t ble_config; -static uint8_t bluefruit_keyboard_leds = 0; - static void bluefruit_serial_send(uint8_t); void send_str(const char *str) @@ -89,30 +71,13 @@ static void bluefruit_serial_send(uint8_t data) serial_send(data); } -/*------------------------------------------------------------------* - * Host driver - *------------------------------------------------------------------*/ - -static uint8_t keyboard_leds(void); -static void send_keyboard(report_keyboard_t *report); -static void send_mouse(report_mouse_t *report); -static void send_extra(report_extra_t *report); - -host_driver_t bluefruit_driver = { - keyboard_leds, - send_keyboard, - send_mouse, - send_extra -}; - -host_driver_t null_driver = {}; - -static uint8_t keyboard_leds(void) -{ - return bluefruit_keyboard_leds; +void bluetooth_init(void) { + usart_init(); } -static void send_keyboard(report_keyboard_t *report) +void bluetooth_task(void) {} + +void bluetooth_send_keyboard(report_keyboard_t *report) { #ifdef BLUEFRUIT_TRACE_SERIAL bluefruit_trace_header(); @@ -136,7 +101,7 @@ static void send_keyboard(report_keyboard_t *report) #endif } -static void send_mouse(report_mouse_t *report) +void bluetooth_send_mouse(report_mouse_t *report) { #ifdef BLUEFRUIT_TRACE_SERIAL bluefruit_trace_header(); @@ -177,27 +142,25 @@ static void send_mouse(report_mouse_t *report) #define CONSUMER2BLUEFRUIT(usage) \ (usage == AUDIO_MUTE ? 0x00e2 : (usage == AUDIO_VOL_UP ? 0x00e9 : (usage == AUDIO_VOL_DOWN ? 0x00ea : (usage == TRANSPORT_NEXT_TRACK ? 0x00b5 : (usage == TRANSPORT_PREV_TRACK ? 0x00b6 : (usage == TRANSPORT_STOP ? 0x00b7 : (usage == TRANSPORT_STOP_EJECT ? 0x00b8 : (usage == TRANSPORT_PLAY_PAUSE ? 0x00b1 : (usage == AL_CC_CONFIG ? 0x0183 : (usage == AL_EMAIL ? 0x018c : (usage == AL_CALCULATOR ? 0x0192 : (usage == AL_LOCAL_BROWSER ? 0x0196 : (usage == AC_SEARCH ? 0x021f : (usage == AC_HOME ? 0x0223 : (usage == AC_BACK ? 0x0224 : (usage == AC_FORWARD ? 0x0225 : (usage == AC_STOP ? 0x0226 : (usage == AC_REFRESH ? 0x0227 : (usage == AC_BOOKMARKS ? 0x022a : 0))))))))))))))))))) -static void send_extra(report_extra_t *report) +void bluetooth_send_consumer(uint16_t usage) { - if (report->report_id == REPORT_ID_CONSUMER) { - uint16_t bitmap = CONSUMER2BLUEFRUIT(report->usage); + uint16_t bitmap = CONSUMER2BLUEFRUIT(usage); #ifdef BLUEFRUIT_TRACE_SERIAL - dprintf("\nData: "); - debug_hex16(data); - dprintf("; bitmap: "); - debug_hex16(bitmap); - dprintf("\n"); - bluefruit_trace_header(); + dprintf("\nData: "); + debug_hex16(data); + dprintf("; bitmap: "); + debug_hex16(bitmap); + dprintf("\n"); + bluefruit_trace_header(); #endif - send_str(PSTR("AT+BLEHIDCONTROLKEY=0x")); - send_bytes((bitmap >> 8) & 0xFF); - send_bytes(bitmap & 0xFF); - send_str(PSTR("\r\n")); + send_str(PSTR("AT+BLEHIDCONTROLKEY=0x")); + send_bytes((bitmap >> 8) & 0xFF); + send_bytes(bitmap & 0xFF); + send_str(PSTR("\r\n")); #ifdef BLUEFRUIT_TRACE_SERIAL - bluefruit_trace_footer(); + bluefruit_trace_footer(); #endif - } } void usart_init(void) diff --git a/keyboards/bioi/ble.h b/keyboards/bioi/ble.h index 9167a09728df..529ebf5241d6 100644 --- a/keyboards/bioi/ble.h +++ b/keyboards/bioi/ble.h @@ -15,9 +15,6 @@ along with this program. If not, see . #pragma once #include -#include "host_driver.h" -#include "host.h" - typedef union { uint32_t raw; @@ -28,9 +25,6 @@ typedef union { extern keyboard_config_t ble_config; -extern host_driver_t bluefruit_driver; -extern host_driver_t null_driver; - void send_str(const char *str); void usart_init(void); void module_reset(void); diff --git a/keyboards/bioi/g60/rules.mk b/keyboards/bioi/g60/rules.mk index d6c97aa974c3..a22a56ecec3f 100644 --- a/keyboards/bioi/g60/rules.mk +++ b/keyboards/bioi/g60/rules.mk @@ -1,14 +1,6 @@ # Processor frequency F_CPU = 8000000 -SRC += usart.c \ - ble.c \ - main.c - -OPT_DEFS += -DPROTOCOL_BLE -OPT_DEFS += -DUART_RX1_BUFFER_SIZE=16 -DUART_TX1_BUFFER_SIZE=16 -OPT_DEFS += -DUSART1_ENABLED - # Build Options # change yes to no to disable # @@ -22,5 +14,12 @@ BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality RGBLIGHT_ENABLE = yes # Enable keyboard RGB underglow AUDIO_ENABLE = no # Audio output LTO_ENABLE = yes # Reduce firmware size +BLUETOOTH_ENABLE = yes +BLUETOOTH_DRIVER = custom VIA_ENABLE = yes # VIA support should be enabled here due to the main() loop will be compiled first. + +SRC += usart.c ble.c + +OPT_DEFS += -DUART_RX1_BUFFER_SIZE=16 -DUART_TX1_BUFFER_SIZE=16 +OPT_DEFS += -DUSART1_ENABLED diff --git a/keyboards/bioi/main.c b/keyboards/bioi/main.c deleted file mode 100644 index eb149eb7cd14..000000000000 --- a/keyboards/bioi/main.c +++ /dev/null @@ -1,388 +0,0 @@ -/* -Copyright 2019 Basic I/O Instruments(Scott Wei) -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 . -*/ - -#include -#include - -#include "report.h" -#include "host.h" -#include "host_driver.h" -#include "keyboard.h" -#include "action.h" -#include "led.h" -#include "sendchar.h" -#include "debug.h" -#include "print.h" -#ifdef SLEEP_LED_ENABLE -#include "sleep_led.h" -#endif -#include "suspend.h" - -#include "usb_descriptor.h" -#include "lufa.h" -#include "quantum.h" -#include - -#ifdef NKRO_ENABLE -#include "keycode_config.h" - -extern keymap_config_t keymap_config; -#endif - -#ifdef AUDIO_ENABLE -#include -#endif - -#ifdef BLUETOOTH_ENABLE -#ifdef BLUETOOTH_BLUEFRUIT_LE -#include "bluefruit_le.h" -#else -#include "bluetooth.h" -#endif -#endif - -#ifdef VIRTSER_ENABLE -#include "virtser.h" -#endif - -#if defined(RGBLIGHT_ENABLE) -#include "rgblight.h" -#endif - -#ifdef MIDI_ENABLE -#include "qmk_midi.h" -#endif - -#ifdef RAW_ENABLE -#include "raw_hid.h" -#endif - -#include "ble.h" -#include "usart.h" - -#include -#include - -bool force_usb = false; //Reserved for FORCE USB Mode function. -bool force_ble = false; //Reserved for FORCE USB Mode function. - -bool usb_connected = false; -bool ble_enabled = false; - -uint32_t kb_idle_timer = 0; - -bool usb_state_sent = false; - -uint8_t USB_DeviceLastState = 0; - -#ifdef RAW_ENABLE -/** \brief Raw HID Task - * - * FIXME: Needs doc - */ -static void raw_hid_task(void) -{ - // Create a temporary buffer to hold the read in data from the host - uint8_t data[RAW_EPSIZE]; - bool data_read = false; - - // Device must be connected and configured for the task to run - if (USB_DeviceState != DEVICE_STATE_Configured) - return; - - Endpoint_SelectEndpoint(RAW_OUT_EPNUM); - - // Check to see if a packet has been sent from the host - if (Endpoint_IsOUTReceived()) - { - // Check to see if the packet contains data - if (Endpoint_IsReadWriteAllowed()) - { - /* Read data */ - Endpoint_Read_Stream_LE(data, sizeof(data), NULL); - data_read = true; - } - - // Finalize the stream transfer to receive the last packet - Endpoint_ClearOUT(); - - if (data_read) - { - raw_hid_receive(data, sizeof(data)); - } - } -} -#endif - -static void setup_mcu(void) -{ - /* Disable watchdog if enabled by bootloader/fuses */ - MCUSR &= ~(1 << WDRF); - wdt_disable(); - - CLKPR = (1 << CLKPCE); - CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0); -} - -static void setup_usb(void) -{ - // Leonardo needs. Without this USB device is not recognized. - USB_Disable(); - - USB_Init(); - - // for Console_Task - USB_Device_EnableSOFEvents(); - print_set_sendchar(sendchar); -} - -void power_saving(void) -{ - power_adc_disable(); - power_usart0_disable(); - power_spi_disable(); - power_twi_disable(); - - USBCON |= (1 << FRZCLK); // Freeze the USB Clock - PLLCSR &= ~(1 << PLLE); // Disable the USB Clock (PPL) - USBCON &= ~(1 << USBE); -} - -void power_recover(void) -{ - - USBCON |= (1 << USBE); - PLLCSR |= (1 << PLLE); // Resume the USB Clock (PPL) - USBCON &= ~(1 << FRZCLK); // Resume the USB Clock - - power_adc_enable(); - power_usart0_enable(); - power_spi_enable(); - power_twi_enable(); -} - -void ble_task_init(void) -{ - kb_idle_timer = timer_read32(); //Mark current time, reserved for further usage; -} - -void ble_task(void) -{ - - if (USB_DeviceLastState != USB_DeviceState) - { - usb_state_sent = false; -#ifdef BLE_DEBUG - send_str(PSTR("USB State Changed\r\n")); - if (USB_DeviceState == DEVICE_STATE_Unattached) - { - send_str(PSTR("USB State Unattached\r\n")); - } -#endif - if (USB_DeviceState == DEVICE_STATE_Powered) - { -#ifdef BLE_DEBUG - send_str(PSTR("USB State Powered\r\n")); -#endif - power_recover(); - host_set_driver(&null_driver); - } -#ifdef BLE_DEBUG - if ((USB_DeviceState == DEVICE_STATE_Default)) - { - send_str(PSTR("USB State Default\r\n")); - } - if ((USB_DeviceState == DEVICE_STATE_Addressed)) - { - send_str(PSTR("USB State Addressed\r\n")); - } - if (USB_DeviceState == DEVICE_STATE_Configured) - { - send_str(PSTR("USB State Configured\r\n")); - } - if (USB_DeviceState > DEVICE_STATE_Unattached) - { - } - else - { - // - } -#endif - } - else - { -#ifdef BLE_DEBUG - if (!usb_state_sent) - { - if (USB_DeviceState == DEVICE_STATE_Unattached) - { - send_str(PSTR("USB State Stopped at Unattached\r\n")); - } - if (USB_DeviceState == DEVICE_STATE_Powered) - { - send_str(PSTR("USB State Stopped at Powered\r\n")); - } - if ((USB_DeviceState == DEVICE_STATE_Default)) - { - send_str(PSTR("USB State Stopped at Default\r\n")); - } - if ((USB_DeviceState == DEVICE_STATE_Addressed)) - { - send_str(PSTR("USB State Stopped at Addressed\r\n")); - } - if (USB_DeviceState == DEVICE_STATE_Configured) - { - send_str(PSTR("USB State Stopped at Configured\r\n")); - } - } -#endif - if (USB_DeviceState == DEVICE_STATE_Unattached) - { - if (host_get_driver() && host_get_driver() != &bluefruit_driver) - { -#ifdef BLE_DEBUG - send_str(PSTR("USB State stopped at Unattached\r\n")); -#endif - ble_task_init(); - - force_usb = 0; - usb_connected = 0; - - //Reinit USB to prepare for next connection. - USB_Init(); - USB_Detach(); - USB_Attach(); - -#ifdef BLE_DEBUG - send_str(PSTR("Loading &bluefruit_driver\r\n")); -#endif - host_set_driver(&bluefruit_driver); - clear_keyboard(); - power_saving(); - } - else - { - //Do nothing if USB is unattached and the driver is &bluefruit_driver - } - } - if (USB_DeviceState == DEVICE_STATE_Configured) - { - if (host_get_driver() && host_get_driver() != &lufa_driver) - { -#ifdef BLE_DEBUG - send_str(PSTR("USB State stopped at Configured\r\n")); -#endif - power_recover(); - - usb_connected = 1; - ble_enabled = 0; -#ifdef BLE_DEBUG - send_str(PSTR("Loading &lufa_driver\r\n")); -#endif - host_set_driver(&lufa_driver); - clear_keyboard(); - } - else - { - //Do nothing if the driver is &lufa_driver - } - } - - usb_state_sent = true; - } - - USB_DeviceLastState = USB_DeviceState; -} - -// Use a custom main() function because the task logic is different from the common one. -int main(void) -{ -#ifdef MIDI_ENABLE - setup_midi(); -#endif - - setup_mcu(); - - keyboard_setup(); - - setup_usb(); - sei(); - -#if defined(BLUETOOTH_RN42) - serial_init(); -#endif - - /* wait for USB startup to get ready for debug output */ - uint8_t timeout = 255; // timeout when USB is not available(Bluetooth) - while (timeout-- && USB_DeviceState != DEVICE_STATE_Configured) - { - wait_ms(4); -#if defined(INTERRUPT_CONTROL_ENDPOINT) - ; -#else - USB_USBTask(); -#endif - } - - print("\nUSB init\n"); - - keyboard_init(); - host_set_driver(&lufa_driver); - - backlight_disable(); - //host_set_driver(&lufa_driver); - print("Keyboard initialized.\n"); - - //Init Hardware UART - usart_init(); - -#ifdef BLE_DEBUG - send_str(PSTR("Keyboard has been setup up\r\n")); - - if (usb_connected) - { - send_str(PSTR("usb_connected=1\r\n")); - } - else - { - send_str(PSTR("usb_connected=0\r\n")); - } -#endif - -#ifdef SLEEP_LED_ENABLE - sleep_led_init(); -#endif - -#ifdef VIRTSER_ENABLE - virtser_init(); -#endif - - while (1) - { - ble_task(); - keyboard_task(); - -#ifdef RAW_ENABLE - raw_hid_task(); -#endif - -#if defined(RGBLIGHT_ENABLE) - rgblight_task(); -#endif - -#if !defined(INTERRUPT_CONTROL_ENDPOINT) - USB_USBTask(); -#endif - } -} diff --git a/keyboards/bioi/morgan65/rules.mk b/keyboards/bioi/morgan65/rules.mk index d6c97aa974c3..a22a56ecec3f 100644 --- a/keyboards/bioi/morgan65/rules.mk +++ b/keyboards/bioi/morgan65/rules.mk @@ -1,14 +1,6 @@ # Processor frequency F_CPU = 8000000 -SRC += usart.c \ - ble.c \ - main.c - -OPT_DEFS += -DPROTOCOL_BLE -OPT_DEFS += -DUART_RX1_BUFFER_SIZE=16 -DUART_TX1_BUFFER_SIZE=16 -OPT_DEFS += -DUSART1_ENABLED - # Build Options # change yes to no to disable # @@ -22,5 +14,12 @@ BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality RGBLIGHT_ENABLE = yes # Enable keyboard RGB underglow AUDIO_ENABLE = no # Audio output LTO_ENABLE = yes # Reduce firmware size +BLUETOOTH_ENABLE = yes +BLUETOOTH_DRIVER = custom VIA_ENABLE = yes # VIA support should be enabled here due to the main() loop will be compiled first. + +SRC += usart.c ble.c + +OPT_DEFS += -DUART_RX1_BUFFER_SIZE=16 -DUART_TX1_BUFFER_SIZE=16 +OPT_DEFS += -DUSART1_ENABLED From b93f05dc35e911a5c5f758722545d96c66be88c6 Mon Sep 17 00:00:00 2001 From: Drashna Jaelre Date: Sat, 20 May 2023 05:13:39 -0700 Subject: [PATCH 14/19] [Keyboard] Fixup Crkbd default keymap (#20962) --- keyboards/crkbd/crkbd.c | 152 ++++++++++++++++++-- keyboards/crkbd/info.json | 52 ++++--- keyboards/crkbd/keymaps/default/config.h | 2 - keyboards/crkbd/keymaps/default/keymap.c | 114 +-------------- keyboards/crkbd/keymaps/default/rules.mk | 5 - keyboards/crkbd/keymaps/via/keymap.c | 107 -------------- keyboards/crkbd/keymaps/via/rules.mk | 3 - keyboards/crkbd/lib/host_led_state_reader.c | 2 +- keyboards/crkbd/lib/keylogger.c | 2 +- keyboards/crkbd/lib/logo_reader.c | 2 +- keyboards/crkbd/lib/mode_icon_reader.c | 2 +- keyboards/crkbd/lib/rgb_state_reader.c | 1 + keyboards/crkbd/lib/timelogger.c | 2 +- keyboards/crkbd/r2g/info.json | 61 ++++++++ keyboards/crkbd/r2g/r2g.c | 114 +-------------- keyboards/crkbd/r2g/rules.mk | 6 - keyboards/crkbd/rev1/common/rules.mk | 1 - keyboards/crkbd/rev1/info.json | 63 +++++++- keyboards/crkbd/rev1/legacy/rules.mk | 1 - keyboards/crkbd/rev1/rev1.c | 96 ------------- keyboards/crkbd/rev1/rules.mk | 1 - keyboards/crkbd/rules.mk | 14 -- 22 files changed, 308 insertions(+), 495 deletions(-) delete mode 100644 keyboards/crkbd/keymaps/default/rules.mk delete mode 100644 keyboards/crkbd/rev1/common/rules.mk delete mode 100644 keyboards/crkbd/rev1/legacy/rules.mk delete mode 100644 keyboards/crkbd/rev1/rev1.c diff --git a/keyboards/crkbd/crkbd.c b/keyboards/crkbd/crkbd.c index aadc0bacf02d..ea1dc2e04218 100644 --- a/keyboards/crkbd/crkbd.c +++ b/keyboards/crkbd/crkbd.c @@ -19,17 +19,145 @@ along with this program. If not, see . #include "quantum.h" #ifdef SWAP_HANDS_ENABLE -__attribute__ ((weak)) -const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { - // Left - {{0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}}, - {{0, 5}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}}, - {{0, 6}, {1, 6}, {2, 6}, {3, 6}, {4, 6}, {5, 6}}, - {{0, 7}, {1, 7}, {2, 7}, {3, 7}, {4, 7}, {5, 7}}, - // Right - {{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}}, - {{0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}}, - {{0, 2}, {1, 2}, {2, 2}, {3, 2}, {4, 2}, {5, 2}}, - {{0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}, {5, 3}} +__attribute__((weak)) const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { + // Left + {{0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}}, + {{0, 5}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}}, + {{0, 6}, {1, 6}, {2, 6}, {3, 6}, {4, 6}, {5, 6}}, + {{0, 7}, {1, 7}, {2, 7}, {3, 7}, {4, 7}, {5, 7}}, + // Right + {{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}}, + {{0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}}, + {{0, 2}, {1, 2}, {2, 2}, {3, 2}, {4, 2}, {5, 2}}, + {{0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}, {5, 3}} }; #endif + +#ifdef OLED_ENABLE + +oled_rotation_t oled_init_kb(oled_rotation_t rotation) { + if (!is_keyboard_master()) { + return OLED_ROTATION_180; // flips the display 180 degrees if offhand + } + return rotation; +} + +static void oled_render_layer_state(void) { + oled_write_P(PSTR("Layer: "), false); + switch (get_highest_layer(layer_state)) { + case 0: + oled_write_ln_P(PSTR("Default"), false); + break; + case 1: + oled_write_ln_P(PSTR("Lower"), false); + break; + case 2: + oled_write_ln_P(PSTR("Raise"), false); + break; + case 3: + oled_write_ln_P(PSTR("Adjust"), false); + break; + default: + oled_write_ln_P(PSTR("Undef"), false); + break; + } +} + +char key_name = ' '; +uint16_t last_keycode; +uint8_t last_row; +uint8_t last_col; + +static const char PROGMEM code_to_name[60] = {' ', ' ', ' ', ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'R', 'E', 'B', 'T', '_', '-', '=', '[', ']', '\\', '#', ';', '\'', '`', ',', '.', '/', ' ', ' ', ' '}; + +static void set_keylog(uint16_t keycode, keyrecord_t *record) { + key_name = ' '; + last_keycode = keycode; + if (IS_QK_MOD_TAP(keycode)) { + if (record->tap.count) { + keycode = QK_MOD_TAP_GET_TAP_KEYCODE(keycode); + } else { + keycode = 0xE0 + biton(QK_MOD_TAP_GET_MODS(keycode) & 0xF) + biton(QK_MOD_TAP_GET_MODS(keycode) & 0x10); + } + } else if (IS_QK_LAYER_TAP(keycode) && record->tap.count) { + keycode = QK_LAYER_TAP_GET_TAP_KEYCODE(keycode); + } else if (IS_QK_MODS(keycode)) { + keycode = QK_MODS_GET_BASIC_KEYCODE(keycode); + } else if (IS_QK_ONE_SHOT_MOD(keycode)) { + keycode = 0xE0 + biton(QK_ONE_SHOT_MOD_GET_MODS(keycode) & 0xF) + biton(QK_ONE_SHOT_MOD_GET_MODS(keycode) & 0x10); + } + if (keycode > ARRAY_SIZE(code_to_name)) { + return; + } + + // update keylog + key_name = code_to_name[keycode]; + last_row = record->event.key.row; + last_col = record->event.key.col; +} + +static const char *depad_str(const char *depad_str, char depad_char) { + while (*depad_str == depad_char) + ++depad_str; + return depad_str; +} + +static void oled_render_keylog(void) { + const char *last_row_str = get_u8_str(last_row, ' '); + oled_write(depad_str(last_row_str, ' '), false); + oled_write_P(PSTR("x"), false); + const char *last_col_str = get_u8_str(last_col, ' '); + oled_write(depad_str(last_col_str, ' '), false); + oled_write_P(PSTR(", k"), false); + const char *last_keycode_str = get_u16_str(last_keycode, ' '); + oled_write(depad_str(last_keycode_str, ' '), false); + oled_write_P(PSTR(":"), false); + oled_write_char(key_name, false); +} + +// static void render_bootmagic_status(bool status) { +// /* Show Ctrl-Gui Swap options */ +// static const char PROGMEM logo[][2][3] = { +// {{0x97, 0x98, 0}, {0xb7, 0xb8, 0}}, +// {{0x95, 0x96, 0}, {0xb5, 0xb6, 0}}, +// }; +// if (status) { +// oled_write_ln_P(logo[0][0], false); +// oled_write_ln_P(logo[0][1], false); +// } else { +// oled_write_ln_P(logo[1][0], false); +// oled_write_ln_P(logo[1][1], false); +// } +// } + +__attribute__((weak)) void oled_render_logo(void) { + // clang-format off + static const char PROGMEM crkbd_logo[] = { + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, + 0}; + // clang-format on + oled_write_P(crkbd_logo, false); +} + +bool oled_task_kb(void) { + if (!oled_task_user()) { + return false; + } + if (is_keyboard_master()) { + oled_render_layer_state(); + oled_render_keylog(); + } else { + oled_render_logo(); + } + return false; +} + +bool process_record_kb(uint16_t keycode, keyrecord_t *record) { + if (record->event.pressed) { + set_keylog(keycode, record); + } + return process_record_user(keycode, record); +} +#endif // OLED_ENABLE diff --git a/keyboards/crkbd/info.json b/keyboards/crkbd/info.json index 94b5f18083cc..198ef51d5f09 100644 --- a/keyboards/crkbd/info.json +++ b/keyboards/crkbd/info.json @@ -1,21 +1,35 @@ { - "keyboard_name": "Corne", - "manufacturer": "foostan", - "url": "", - "maintainer": "qmk", - "usb": { - "vid": "0x4653", - "pid": "0x0001", - "device_version": "0.0.1" - }, - "rgb_matrix": { - "driver": "WS2812" - }, - "matrix_pins": { - "cols": ["F4", "F5", "F6", "F7", "B1", "B3"], - "rows": ["D4", "C6", "D7", "E6"] - }, - "diode_direction": "COL2ROW", - "processor": "atmega32u4", - "community_layouts": ["split_3x5_3", "split_3x6_3"] + "keyboard_name": "Corne", + "manufacturer": "foostan", + "url": "", + "maintainer": "qmk", + "usb": { + "vid": "0x4653", + "pid": "0x0001", + "device_version": "0.0.1" + }, + "rgb_matrix": { + "driver": "WS2812" + }, + "features": { + "bootmagic": true, + "extrakey": true, + "lto": true, + "mousekey": true, + "nkro": true, + "oled": true + }, + "build": { + "lto": true + }, + "matrix_pins": { + "cols": [ "F4", "F5", "F6", "F7", "B1", "B3" ], + "rows": [ "D4", "C6", "D7", "E6" ] + }, + "diode_direction": "COL2ROW", + "split": { + "enabled": true + }, + "processor": "atmega32u4", + "community_layouts": [ "split_3x5_3", "split_3x6_3" ] } diff --git a/keyboards/crkbd/keymaps/default/config.h b/keyboards/crkbd/keymaps/default/config.h index 4e70141dad6d..9d4be81fa3cd 100644 --- a/keyboards/crkbd/keymaps/default/config.h +++ b/keyboards/crkbd/keymaps/default/config.h @@ -47,5 +47,3 @@ along with this program. If not, see . #define RGBLIGHT_SAT_STEP 17 #define RGBLIGHT_VAL_STEP 17 #endif - -#define OLED_FONT_H "keyboards/crkbd/lib/glcdfont.c" diff --git a/keyboards/crkbd/keymaps/default/keymap.c b/keyboards/crkbd/keymaps/default/keymap.c index 23e706e64b46..e46743af6b20 100644 --- a/keyboards/crkbd/keymaps/default/keymap.c +++ b/keyboards/crkbd/keymaps/default/keymap.c @@ -17,10 +17,9 @@ along with this program. If not, see . */ #include QMK_KEYBOARD_H -#include const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { - [0] = LAYOUT_split_3x6_3( + [0] = LAYOUT_split_3x6_3( //,-----------------------------------------------------. ,-----------------------------------------------------. KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC, //|--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------| @@ -33,7 +32,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { ), - [1] = LAYOUT_split_3x6_3( + [1] = LAYOUT_split_3x6_3( //,-----------------------------------------------------. ,-----------------------------------------------------. KC_TAB, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC, //|--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------| @@ -45,7 +44,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { //`--------------------------' `--------------------------' ), - [2] = LAYOUT_split_3x6_3( + [2] = LAYOUT_split_3x6_3( //,-----------------------------------------------------. ,-----------------------------------------------------. KC_TAB, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_BSPC, //|--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------| @@ -57,7 +56,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { //`--------------------------' `--------------------------' ), - [3] = LAYOUT_split_3x6_3( + [3] = LAYOUT_split_3x6_3( //,-----------------------------------------------------. ,-----------------------------------------------------. QK_BOOT, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, //|--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------| @@ -69,108 +68,3 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { //`--------------------------' `--------------------------' ) }; - -#ifdef OLED_ENABLE -oled_rotation_t oled_init_user(oled_rotation_t rotation) { - if (!is_keyboard_master()) { - return OLED_ROTATION_180; // flips the display 180 degrees if offhand - } - return rotation; -} - -#define L_BASE 0 -#define L_LOWER 2 -#define L_RAISE 4 -#define L_ADJUST 8 - -void oled_render_layer_state(void) { - oled_write_P(PSTR("Layer: "), false); - switch (layer_state) { - case L_BASE: - oled_write_ln_P(PSTR("Default"), false); - break; - case L_LOWER: - oled_write_ln_P(PSTR("Lower"), false); - break; - case L_RAISE: - oled_write_ln_P(PSTR("Raise"), false); - break; - case L_ADJUST: - case L_ADJUST|L_LOWER: - case L_ADJUST|L_RAISE: - case L_ADJUST|L_LOWER|L_RAISE: - oled_write_ln_P(PSTR("Adjust"), false); - break; - } -} - - -char keylog_str[24] = {}; - -const char code_to_name[60] = { - ' ', ' ', ' ', ' ', 'a', 'b', 'c', 'd', 'e', 'f', - 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', - 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', - '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', - 'R', 'E', 'B', 'T', '_', '-', '=', '[', ']', '\\', - '#', ';', '\'', '`', ',', '.', '/', ' ', ' ', ' '}; - -void set_keylog(uint16_t keycode, keyrecord_t *record) { - char name = ' '; - if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) || - (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX)) { keycode = keycode & 0xFF; } - if (keycode < 60) { - name = code_to_name[keycode]; - } - - // update keylog - snprintf(keylog_str, sizeof(keylog_str), "%dx%d, k%2d : %c", - record->event.key.row, record->event.key.col, - keycode, name); -} - -void oled_render_keylog(void) { - oled_write(keylog_str, false); -} - -void render_bootmagic_status(bool status) { - /* Show Ctrl-Gui Swap options */ - static const char PROGMEM logo[][2][3] = { - {{0x97, 0x98, 0}, {0xb7, 0xb8, 0}}, - {{0x95, 0x96, 0}, {0xb5, 0xb6, 0}}, - }; - if (status) { - oled_write_ln_P(logo[0][0], false); - oled_write_ln_P(logo[0][1], false); - } else { - oled_write_ln_P(logo[1][0], false); - oled_write_ln_P(logo[1][1], false); - } -} - -void oled_render_logo(void) { - static const char PROGMEM crkbd_logo[] = { - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, - 0}; - oled_write_P(crkbd_logo, false); -} - -bool oled_task_user(void) { - if (is_keyboard_master()) { - oled_render_layer_state(); - oled_render_keylog(); - } else { - oled_render_logo(); - } - return false; -} - -bool process_record_user(uint16_t keycode, keyrecord_t *record) { - if (record->event.pressed) { - set_keylog(keycode, record); - } - return true; -} -#endif // OLED_ENABLE diff --git a/keyboards/crkbd/keymaps/default/rules.mk b/keyboards/crkbd/keymaps/default/rules.mk deleted file mode 100644 index c14c202faeae..000000000000 --- a/keyboards/crkbd/keymaps/default/rules.mk +++ /dev/null @@ -1,5 +0,0 @@ -MOUSEKEY_ENABLE = yes # Mouse keys -RGBLIGHT_ENABLE = yes # Enable WS2812 RGB underlight. -OLED_ENABLE = yes -OLED_DRIVER = SSD1306 -LTO_ENABLE = yes diff --git a/keyboards/crkbd/keymaps/via/keymap.c b/keyboards/crkbd/keymaps/via/keymap.c index 3e93d5bbcfd9..aed0f1a3e35f 100644 --- a/keyboards/crkbd/keymaps/via/keymap.c +++ b/keyboards/crkbd/keymaps/via/keymap.c @@ -68,110 +68,3 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { //`--------------------------' `--------------------------' ) }; - -#ifdef OLED_ENABLE -#include - -oled_rotation_t oled_init_user(oled_rotation_t rotation) { - if (!is_keyboard_master()) { - return OLED_ROTATION_180; // flips the display 180 degrees if offhand - } - return rotation; -} - -#define L_BASE 0 -#define L_LOWER 2 -#define L_RAISE 4 -#define L_ADJUST 8 - -void oled_render_layer_state(void) { - oled_write_P(PSTR("Layer: "), false); - switch (layer_state) { - case L_BASE: - oled_write_ln_P(PSTR("Default"), false); - break; - case L_LOWER: - oled_write_ln_P(PSTR("Lower"), false); - break; - case L_RAISE: - oled_write_ln_P(PSTR("Raise"), false); - break; - case L_ADJUST: - case L_ADJUST|L_LOWER: - case L_ADJUST|L_RAISE: - case L_ADJUST|L_LOWER|L_RAISE: - oled_write_ln_P(PSTR("Adjust"), false); - break; - } -} - - -char keylog_str[24] = {}; - -const char code_to_name[60] = { - ' ', ' ', ' ', ' ', 'a', 'b', 'c', 'd', 'e', 'f', - 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', - 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', - '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', - 'R', 'E', 'B', 'T', '_', '-', '=', '[', ']', '\\', - '#', ';', '\'', '`', ',', '.', '/', ' ', ' ', ' '}; - -void set_keylog(uint16_t keycode, keyrecord_t *record) { - char name = ' '; - if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) || - (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX)) { keycode = keycode & 0xFF; } - if (keycode < 60) { - name = code_to_name[keycode]; - } - - // update keylog - snprintf(keylog_str, sizeof(keylog_str), "%dx%d, k%2d : %c", - record->event.key.row, record->event.key.col, - keycode, name); -} - -void oled_render_keylog(void) { - oled_write(keylog_str, false); -} - -void render_bootmagic_status(bool status) { - /* Show Ctrl-Gui Swap options */ - static const char PROGMEM logo[][2][3] = { - {{0x97, 0x98, 0}, {0xb7, 0xb8, 0}}, - {{0x95, 0x96, 0}, {0xb5, 0xb6, 0}}, - }; - if (status) { - oled_write_ln_P(logo[0][0], false); - oled_write_ln_P(logo[0][1], false); - } else { - oled_write_ln_P(logo[1][0], false); - oled_write_ln_P(logo[1][1], false); - } -} - -void oled_render_logo(void) { - static const char PROGMEM crkbd_logo[] = { - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, - 0}; - oled_write_P(crkbd_logo, false); -} - -bool oled_task_user(void) { - if (is_keyboard_master()) { - oled_render_layer_state(); - oled_render_keylog(); - } else { - oled_render_logo(); - } - return false; -} - -bool process_record_user(uint16_t keycode, keyrecord_t *record) { - if (record->event.pressed) { - set_keylog(keycode, record); - } - return true; -} -#endif // OLED_ENABLE diff --git a/keyboards/crkbd/keymaps/via/rules.mk b/keyboards/crkbd/keymaps/via/rules.mk index ee593dcbb7d0..51ea4d125f92 100644 --- a/keyboards/crkbd/keymaps/via/rules.mk +++ b/keyboards/crkbd/keymaps/via/rules.mk @@ -1,6 +1,3 @@ MOUSEKEY_ENABLE = no # Mouse keys -RGBLIGHT_ENABLE = yes # Enable WS2812 RGB underlight. VIA_ENABLE = yes # Enable VIA -OLED_ENABLE = yes -OLED_DRIVER = SSD1306 LTO_ENABLE = yes diff --git a/keyboards/crkbd/lib/host_led_state_reader.c b/keyboards/crkbd/lib/host_led_state_reader.c index 41ac55dc2bfb..a0684e4a277b 100644 --- a/keyboards/crkbd/lib/host_led_state_reader.c +++ b/keyboards/crkbd/lib/host_led_state_reader.c @@ -1,5 +1,5 @@ #include -#include "crkbd.h" +#include "quantum.h" char host_led_state_str[24]; diff --git a/keyboards/crkbd/lib/keylogger.c b/keyboards/crkbd/lib/keylogger.c index 8f2a8ce3cc2e..9adb55d6eeb9 100644 --- a/keyboards/crkbd/lib/keylogger.c +++ b/keyboards/crkbd/lib/keylogger.c @@ -1,5 +1,5 @@ #include -#include "crkbd.h" +#include "quantum.h" char keylog_str[24] = {}; char keylogs_str[21] = {}; diff --git a/keyboards/crkbd/lib/logo_reader.c b/keyboards/crkbd/lib/logo_reader.c index 1bc1503a6042..4a710bb25023 100644 --- a/keyboards/crkbd/lib/logo_reader.c +++ b/keyboards/crkbd/lib/logo_reader.c @@ -1,4 +1,4 @@ -#include "crkbd.h" +#include "quantum.h" const char *read_logo(void) { static char logo[] = { diff --git a/keyboards/crkbd/lib/mode_icon_reader.c b/keyboards/crkbd/lib/mode_icon_reader.c index 04c226506a4e..02a63ec1c606 100644 --- a/keyboards/crkbd/lib/mode_icon_reader.c +++ b/keyboards/crkbd/lib/mode_icon_reader.c @@ -1,5 +1,5 @@ #include -#include "crkbd.h" +#include "quantum.h" char mode_icon[24]; diff --git a/keyboards/crkbd/lib/rgb_state_reader.c b/keyboards/crkbd/lib/rgb_state_reader.c index 3d74fb45e4e3..a255cd662d20 100644 --- a/keyboards/crkbd/lib/rgb_state_reader.c +++ b/keyboards/crkbd/lib/rgb_state_reader.c @@ -1,6 +1,7 @@ #ifdef RGBLIGHT_ENABLE #include +#include "quantum.h" extern rgblight_config_t rgblight_config; char rbf_info_str[24]; diff --git a/keyboards/crkbd/lib/timelogger.c b/keyboards/crkbd/lib/timelogger.c index 69828a3a0882..bce9d99a4be6 100644 --- a/keyboards/crkbd/lib/timelogger.c +++ b/keyboards/crkbd/lib/timelogger.c @@ -1,5 +1,5 @@ #include -#include "crkbd.h" +#include "quantum.h" char timelog_str[24] = {}; int last_time = 0; diff --git a/keyboards/crkbd/r2g/info.json b/keyboards/crkbd/r2g/info.json index 6440a61bf7c8..cfd29368e61e 100644 --- a/keyboards/crkbd/r2g/info.json +++ b/keyboards/crkbd/r2g/info.json @@ -1,4 +1,7 @@ { + "features": { + "rgb_matrix": true + }, "split": { "soft_serial_pin": "D2" }, @@ -110,5 +113,63 @@ {"matrix": [7, 3], "x": 10, "y": 3.7} ] } + }, + "rgb_matrix": { + "layout": [ + {"x": 85, "y": 16, "flags": 2}, + {"x": 50, "y": 13, "flags": 2}, + {"x": 16, "y": 20, "flags": 2}, + {"x": 16, "y": 38, "flags": 2}, + {"x": 50, "y": 48, "flags": 2}, + {"x": 85, "y": 52, "flags": 2}, + {"matrix": [3, 5], "x": 95, "y": 63, "flags": 1}, + {"matrix": [2, 5], "x": 85, "y": 39, "flags": 4}, + {"matrix": [1, 5], "x": 85, "y": 21, "flags": 4}, + {"matrix": [0, 5], "x": 85, "y": 4, "flags": 4}, + {"matrix": [0, 4], "x": 68, "y": 2, "flags": 4}, + {"matrix": [1, 4], "x": 68, "y": 19, "flags": 4}, + {"matrix": [2, 4], "x": 68, "y": 37, "flags": 4}, + {"matrix": [3, 4], "x": 80, "y": 58, "flags": 1}, + {"matrix": [3, 3], "x": 60, "y": 55, "flags": 1}, + {"matrix": [2, 3], "x": 50, "y": 35, "flags": 4}, + {"matrix": [1, 3], "x": 50, "y": 13, "flags": 4}, + {"matrix": [0, 3], "x": 50, "y": 0, "flags": 4}, + {"matrix": [0, 2], "x": 33, "y": 3, "flags": 4}, + {"matrix": [1, 2], "x": 33, "y": 20, "flags": 4}, + {"matrix": [2, 2], "x": 33, "y": 37, "flags": 4}, + {"matrix": [2, 1], "x": 16, "y": 42, "flags": 4}, + {"matrix": [1, 1], "x": 16, "y": 24, "flags": 4}, + {"matrix": [0, 1], "x": 16, "y": 7, "flags": 4}, + {"matrix": [0, 0], "x": 0, "y": 7, "flags": 1}, + {"matrix": [1, 0], "x": 0, "y": 24, "flags": 1}, + {"matrix": [2, 0], "x": 0, "y": 41, "flags": 1}, + {"x": 139, "y": 16, "flags": 2}, + {"x": 174, "y": 13, "flags": 2}, + {"x": 208, "y": 20, "flags": 2}, + {"x": 208, "y": 38, "flags": 2}, + {"x": 174, "y": 48, "flags": 2}, + {"x": 139, "y": 52, "flags": 2}, + {"matrix": [7, 5], "x": 129, "y": 63, "flags": 1}, + {"matrix": [6, 5], "x": 139, "y": 39, "flags": 4}, + {"matrix": [5, 5], "x": 139, "y": 21, "flags": 4}, + {"matrix": [4, 5], "x": 139, "y": 4, "flags": 4}, + {"matrix": [4, 4], "x": 156, "y": 2, "flags": 4}, + {"matrix": [5, 4], "x": 156, "y": 19, "flags": 4}, + {"matrix": [6, 4], "x": 156, "y": 37, "flags": 4}, + {"matrix": [7, 4], "x": 144, "y": 58, "flags": 1}, + {"matrix": [7, 3], "x": 164, "y": 55, "flags": 1}, + {"matrix": [6, 3], "x": 174, "y": 35, "flags": 4}, + {"matrix": [5, 3], "x": 174, "y": 13, "flags": 4}, + {"matrix": [4, 3], "x": 174, "y": 0, "flags": 4}, + {"matrix": [4, 2], "x": 191, "y": 3, "flags": 4}, + {"matrix": [5, 2], "x": 191, "y": 20, "flags": 4}, + {"matrix": [6, 2], "x": 191, "y": 37, "flags": 4}, + {"matrix": [6, 1], "x": 208, "y": 42, "flags": 4}, + {"matrix": [5, 1], "x": 208, "y": 24, "flags": 4}, + {"matrix": [4, 1], "x": 208, "y": 7, "flags": 4}, + {"matrix": [4, 0], "x": 224, "y": 7, "flags": 1}, + {"matrix": [5, 0], "x": 224, "y": 24, "flags": 1}, + {"matrix": [6, 0], "x": 224, "y": 41, "flags": 1} + ] } } diff --git a/keyboards/crkbd/r2g/r2g.c b/keyboards/crkbd/r2g/r2g.c index a4d138b98afd..ef7b84b4a983 100644 --- a/keyboards/crkbd/r2g/r2g.c +++ b/keyboards/crkbd/r2g/r2g.c @@ -88,98 +88,7 @@ led_config_t g_led_config = { { #endif #ifdef OLED_ENABLE - -oled_rotation_t oled_init_kb(oled_rotation_t rotation) { - if (!is_keyboard_master()) { - return OLED_ROTATION_180; // flips the display 180 degrees if offhand - } - return rotation; -} - -enum Layers{ - L_BASE, L_LOWER, L_RAISE, L_ADJUST -}; - -void oled_render_layer_state_r2g(void) { - oled_write_P(PSTR("Layer: "), false); - switch (get_highest_layer(layer_state)) { - case L_BASE: - oled_write_ln_P(PSTR("Default"), false); - break; - case L_LOWER: - oled_write_ln_P(PSTR("Lower"), false); - break; - case L_RAISE: - oled_write_ln_P(PSTR("Raise"), false); - break; - case L_ADJUST: - oled_write_ln_P(PSTR("Adjust"), false); - break; - } -} - -//char keylog_str_r2g[24] = {}; - -const char code_to_name_r2g[60] = { - ' ', ' ', ' ', ' ', 'a', 'b', 'c', 'd', 'e', 'f', - 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', - 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', - '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', - 'R', 'E', 'B', 'T', '_', '-', '=', '[', ']', '\\', - '#', ';', '\'', '`', ',', '.', '/', ' ', ' ', ' '}; - -char key_name_r2g = ' '; -uint16_t last_keycode_r2g; -uint8_t last_row_r2g; -uint8_t last_col_r2g; - -void set_keylog_r2g(uint16_t keycode, keyrecord_t *record) { - key_name_r2g = ' '; - last_keycode_r2g = keycode; - if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) || - (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX)) { last_keycode_r2g = keycode & 0xFF; } - if (keycode < 60) { - key_name_r2g = code_to_name_r2g[keycode]; - } - last_row_r2g = record->event.key.row; - last_col_r2g = record->event.key.col; -} - -const char *depad_str(const char *depad_str, char depad_char) { - while (*depad_str == depad_char) ++depad_str; - return depad_str; -} - -void oled_render_keylog_r2g(void) { - //oled_write(keylog_str_r2g, false); - const char *last_row_r2g_str = get_u8_str(last_row_r2g, ' '); - oled_write(depad_str(last_row_r2g_str, ' '), false); - oled_write_P(PSTR("x"), false); - const char *last_col_r2g_str = get_u8_str(last_col_r2g, ' '); - oled_write(depad_str(last_col_r2g_str, ' '), false); - oled_write_P(PSTR(", k"), false); - const char *last_keycode_r2g_str = get_u16_str(last_keycode_r2g, ' '); - oled_write(depad_str(last_keycode_r2g_str, ' '), false); - oled_write_P(PSTR(":"), false); - oled_write_char(key_name_r2g, false); -} - -void render_bootmagic_status_r2g(bool status) { - /* Show Ctrl-Gui Swap options */ - static const char PROGMEM logo[][2][3] = { - {{0x97, 0x98, 0}, {0xb7, 0xb8, 0}}, - {{0x95, 0x96, 0}, {0xb5, 0xb6, 0}}, - }; - if (status) { - oled_write_ln_P(logo[0][0], false); - oled_write_ln_P(logo[0][1], false); - } else { - oled_write_ln_P(logo[1][0], false); - oled_write_ln_P(logo[1][1], false); - } -} - -void oled_render_logo_r2g(void) { +void oled_render_logo(void) { static const char PROGMEM mb_logo[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, @@ -218,23 +127,4 @@ void oled_render_logo_r2g(void) { //oled_set_cursor(oled_max_chars()/2,oled_max_lines()/2); //oled_write_P(PSTR("R2G"), false); } - -bool oled_task_kb(void) { - if (!oled_task_user()) { return false; } - if (is_keyboard_master()) { - oled_render_layer_state_r2g(); - oled_render_keylog_r2g(); - } else { - oled_render_logo_r2g(); - } - return false; -} - -bool process_record_kb(uint16_t keycode, keyrecord_t *record) { - if (record->event.pressed) { - set_keylog_r2g(keycode, record); - } - return process_record_user(keycode, record); -} -#endif // OLED_ENABLE - +#endif diff --git a/keyboards/crkbd/r2g/rules.mk b/keyboards/crkbd/r2g/rules.mk index 7cf008d00384..e69de29bb2d1 100644 --- a/keyboards/crkbd/r2g/rules.mk +++ b/keyboards/crkbd/r2g/rules.mk @@ -1,6 +0,0 @@ -OLED_ENABLE = yes -OLED_DRIVER = SSD1306 -LTO_ENABLE = yes -RGBLIGHT_ENABLE = yes - -SPLIT_KEYBOARD = yes diff --git a/keyboards/crkbd/rev1/common/rules.mk b/keyboards/crkbd/rev1/common/rules.mk deleted file mode 100644 index 836587e45e68..000000000000 --- a/keyboards/crkbd/rev1/common/rules.mk +++ /dev/null @@ -1 +0,0 @@ -DEFAULT_FOLDER = crkbd/rev1 diff --git a/keyboards/crkbd/rev1/info.json b/keyboards/crkbd/rev1/info.json index cadb908cf16d..4f63c95170c4 100644 --- a/keyboards/crkbd/rev1/info.json +++ b/keyboards/crkbd/rev1/info.json @@ -1,11 +1,72 @@ { + "features": { + "rgblight": true + }, "split": { "soft_serial_pin": "D2" }, "ws2812": { "pin": "D3" }, - "bootloader": "caterina", + "rgb_matrix": { + "layout": [ + {"x": 85, "y": 16, "flags": 2}, + {"x": 50, "y": 13, "flags": 2}, + {"x": 16, "y": 20, "flags": 2}, + {"x": 16, "y": 38, "flags": 2}, + {"x": 50, "y": 48, "flags": 2}, + {"x": 85, "y": 52, "flags": 2}, + {"matrix": [3, 5], "x": 95, "y": 63, "flags": 1}, + {"matrix": [2, 5], "x": 85, "y": 39, "flags": 4}, + {"matrix": [1, 5], "x": 85, "y": 21, "flags": 4}, + {"matrix": [0, 5], "x": 85, "y": 4, "flags": 4}, + {"matrix": [0, 4], "x": 68, "y": 2, "flags": 4}, + {"matrix": [1, 4], "x": 68, "y": 19, "flags": 4}, + {"matrix": [2, 4], "x": 68, "y": 37, "flags": 4}, + {"matrix": [3, 4], "x": 80, "y": 58, "flags": 1}, + {"matrix": [3, 3], "x": 60, "y": 55, "flags": 1}, + {"matrix": [2, 3], "x": 50, "y": 35, "flags": 4}, + {"matrix": [1, 3], "x": 50, "y": 13, "flags": 4}, + {"matrix": [0, 3], "x": 50, "y": 0, "flags": 4}, + {"matrix": [0, 2], "x": 33, "y": 3, "flags": 4}, + {"matrix": [1, 2], "x": 33, "y": 20, "flags": 4}, + {"matrix": [2, 2], "x": 33, "y": 37, "flags": 4}, + {"matrix": [2, 1], "x": 16, "y": 42, "flags": 4}, + {"matrix": [1, 1], "x": 16, "y": 24, "flags": 4}, + {"matrix": [0, 1], "x": 16, "y": 7, "flags": 4}, + {"matrix": [0, 0], "x": 0, "y": 7, "flags": 1}, + {"matrix": [1, 0], "x": 0, "y": 24, "flags": 1}, + {"matrix": [2, 0], "x": 0, "y": 41, "flags": 1}, + {"x": 139, "y": 16, "flags": 2}, + {"x": 174, "y": 13, "flags": 2}, + {"x": 208, "y": 20, "flags": 2}, + {"x": 208, "y": 38, "flags": 2}, + {"x": 174, "y": 48, "flags": 2}, + {"x": 139, "y": 52, "flags": 2}, + {"matrix": [7, 5], "x": 129, "y": 63, "flags": 1}, + {"matrix": [6, 5], "x": 139, "y": 39, "flags": 4}, + {"matrix": [5, 5], "x": 139, "y": 21, "flags": 4}, + {"matrix": [4, 5], "x": 139, "y": 4, "flags": 4}, + {"matrix": [4, 4], "x": 156, "y": 2, "flags": 4}, + {"matrix": [5, 4], "x": 156, "y": 19, "flags": 4}, + {"matrix": [6, 4], "x": 156, "y": 37, "flags": 4}, + {"matrix": [7, 4], "x": 144, "y": 58, "flags": 1}, + {"matrix": [7, 3], "x": 164, "y": 55, "flags": 1}, + {"matrix": [6, 3], "x": 174, "y": 35, "flags": 4}, + {"matrix": [5, 3], "x": 174, "y": 13, "flags": 4}, + {"matrix": [4, 3], "x": 174, "y": 0, "flags": 4}, + {"matrix": [4, 2], "x": 191, "y": 3, "flags": 4}, + {"matrix": [5, 2], "x": 191, "y": 20, "flags": 4}, + {"matrix": [6, 2], "x": 191, "y": 37, "flags": 4}, + {"matrix": [6, 1], "x": 208, "y": 42, "flags": 4}, + {"matrix": [5, 1], "x": 208, "y": 24, "flags": 4}, + {"matrix": [4, 1], "x": 208, "y": 7, "flags": 4}, + {"matrix": [4, 0], "x": 224, "y": 7, "flags": 1}, + {"matrix": [5, 0], "x": 224, "y": 24, "flags": 1}, + {"matrix": [6, 0], "x": 224, "y": 41, "flags": 1} + ] + }, + "development_board": "promicro", "layout_aliases": { "LAYOUT": "LAYOUT_split_3x6_3" }, diff --git a/keyboards/crkbd/rev1/legacy/rules.mk b/keyboards/crkbd/rev1/legacy/rules.mk deleted file mode 100644 index 836587e45e68..000000000000 --- a/keyboards/crkbd/rev1/legacy/rules.mk +++ /dev/null @@ -1 +0,0 @@ -DEFAULT_FOLDER = crkbd/rev1 diff --git a/keyboards/crkbd/rev1/rev1.c b/keyboards/crkbd/rev1/rev1.c deleted file mode 100644 index cb337d15bc9e..000000000000 --- a/keyboards/crkbd/rev1/rev1.c +++ /dev/null @@ -1,96 +0,0 @@ -/* -Copyright 2019 @foostan -Copyright 2020 Drashna Jaelre <@drashna> - -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 . -*/ -#include "quantum.h" - -#ifdef RGB_MATRIX_ENABLE - - // Logical Layout - // Columns - // Left - // 0 1 2 3 4 5 - // ROWS - // 25 24 19 18 11 10 0 - // 03 02 01 - // 26 23 20 17 12 09 1 - // 04 05 06 - // 27 22 21 16 13 08 2 - // - // 15 14 07 3 - // - // Right - // 0 1 2 3 4 5 - // ROWS - // 25 24 19 18 11 10 4 - // 03 02 01 - // 26 23 20 17 12 09 5 - // 04 05 06 - // 27 22 21 16 13 08 6 - // - // 15 14 07 7 - // - // Physical Layout - // Columns - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 - // ROWS - // 25 24 19 18 11 10 10 11 18 19 24 25 0 - // 03 02 01 01 02 03 - // 26 23 20 17 12 09 09 12 17 20 23 26 1 - // 04 04 - // 27 22 21 16 13 08 08 13 16 21 22 27 2 - // 05 06 06 05 - // 15 14 07 07 14 15 3 - -led_config_t g_led_config = { { - { 24, 23, 18, 17, 10, 9 }, - { 25, 22, 19, 16, 11, 8 }, - { 26, 21, 20, 15, 12, 7 }, - { NO_LED, NO_LED, NO_LED, 14, 13, 6 }, - { 51, 50, 45, 44, 37, 36 }, - { 52, 49, 46, 43, 38, 35 }, - { 53, 48, 47, 42, 39, 34 }, - { NO_LED, NO_LED, NO_LED, 41, 40, 33 } -}, { - { 85, 16 }, { 50, 13 }, { 16, 20 }, { 16, 38 }, { 50, 48 }, { 85, 52 }, { 95, 63 }, - { 85, 39 }, { 85, 21 }, { 85, 4 }, { 68, 2 }, { 68, 19 }, { 68, 37 }, { 80, 58 }, - { 60, 55 }, { 50, 35 }, { 50, 13 }, { 50, 0 }, { 33, 3 }, { 33, 20 }, { 33, 37 }, - { 16, 42 }, { 16, 24 }, { 16, 7 }, { 0, 7 }, { 0, 24 }, { 0, 41 }, { 139, 16 }, - { 174, 13 }, { 208, 20 }, { 208, 38 }, { 174, 48 }, { 139, 52 }, { 129, 63 }, { 139, 39 }, - { 139, 21 }, { 139, 4 }, { 156, 2 }, { 156, 19 }, { 156, 37 }, { 144, 58 }, { 164, 55 }, - { 174, 35 }, { 174, 13 }, { 174, 0 }, { 191, 3 }, { 191, 20 }, { 191, 37 }, { 208, 42 }, - { 208, 24 }, { 208, 7 }, { 224, 7 }, { 224, 24 }, { 224, 41 } -}, { - 2, 2, 2, 2, 2, 2, 1, - 4, 4, 4, 4, 4, 4, 1, - 1, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 1, 1, 1, 2, - 2, 2, 2, 2, 2, 1, 4, - 4, 4, 4, 4, 4, 1, 1, - 4, 4, 4, 4, 4, 4, 4, - 4, 4, 1, 1, 1 -} }; - -void suspend_power_down_kb(void) { - rgb_matrix_set_suspend_state(true); - suspend_power_down_user(); -} - -void suspend_wakeup_init_kb(void) { - rgb_matrix_set_suspend_state(false); - suspend_wakeup_init_user(); -} -#endif diff --git a/keyboards/crkbd/rev1/rules.mk b/keyboards/crkbd/rev1/rules.mk index d38a61809075..e69de29bb2d1 100644 --- a/keyboards/crkbd/rev1/rules.mk +++ b/keyboards/crkbd/rev1/rules.mk @@ -1 +0,0 @@ -SPLIT_KEYBOARD = yes diff --git a/keyboards/crkbd/rules.mk b/keyboards/crkbd/rules.mk index 89dbcd35bd9e..a63f102097f2 100644 --- a/keyboards/crkbd/rules.mk +++ b/keyboards/crkbd/rules.mk @@ -1,20 +1,6 @@ # Build Options # change yes to no to disable # -BOOTMAGIC_ENABLE = yes # Enable Bootmagic Lite -MOUSEKEY_ENABLE = yes # Mouse keys -EXTRAKEY_ENABLE = yes # Audio control and System control -CONSOLE_ENABLE = no # Console for debug -COMMAND_ENABLE = no # Commands for debug and configuration -NKRO_ENABLE = yes # Enable N-Key Rollover -BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality -RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow -AUDIO_ENABLE = no # Audio output -RGB_MATRIX_ENABLE = no -LTO_ENABLE = yes - -# if firmware size over limit, try this option -# LTO_ENABLE = yes DEFAULT_FOLDER = crkbd/rev1 From 102c42b14bc79a178d16ae5217d739490a312ea4 Mon Sep 17 00:00:00 2001 From: Ryan Date: Sat, 20 May 2023 22:14:43 +1000 Subject: [PATCH 15/19] `qmk find`: usability improvements (#20440) --- docs/cli_commands.md | 19 +++++++++++-- lib/python/qmk/cli/find.py | 12 +++++--- lib/python/qmk/makefile.py | 2 +- lib/python/qmk/search.py | 56 ++++++++++++++++++++++++++++---------- 4 files changed, 67 insertions(+), 22 deletions(-) diff --git a/docs/cli_commands.md b/docs/cli_commands.md index d759c9c35aec..79fd9de57576 100644 --- a/docs/cli_commands.md +++ b/docs/cli_commands.md @@ -165,16 +165,31 @@ qmk find -f 'processor=STM32F411' qmk find -f 'processor=STM32F411' -f 'features.rgb_matrix=true' ``` +The following filter expressions are also supported: + + - `exists(key)`: Match targets where `key` is present. + - `absent(key)`: Match targets where `key` is not present. + - `contains(key, value)`: Match targets where `key` contains `value`. Can be used for strings, arrays and object keys. + - `length(key, value)`: Match targets where the length of `key` is `value`. Can be used for strings, arrays and objects. + +You can also list arbitrary values for each matched target with `--print`: + +``` +qmk find -f 'processor=STM32F411' -p 'keyboard_name' -p 'features.rgb_matrix' +``` + **Usage**: ``` -qmk find [-h] [-km KEYMAP] [-f FILTER] +qmk find [-h] [-km KEYMAP] [-p PRINT] [-f FILTER] options: -km KEYMAP, --keymap KEYMAP The keymap name to build. Default is 'default'. + -p PRINT, --print PRINT + For each matched target, print the value of the supplied info.json key. May be passed multiple times. -f FILTER, --filter FILTER - Filter the list of keyboards based on the supplied value in rules.mk. Matches info.json structure, and accepts the formats 'features.rgblight=true' or 'exists(matrix_pins.direct)'. May be passed multiple times, all filters need to match. Value may include wildcards such as '*' and '?'. + Filter the list of keyboards based on their info.json data. Accepts the formats key=value, function(key), or function(key,value), eg. 'features.rgblight=true'. Valid functions are 'absent', 'contains', 'exists' and 'length'. May be passed multiple times; all filters need to match. Value may include wildcards such as '*' and '?'. ``` ## `qmk console` diff --git a/lib/python/qmk/cli/find.py b/lib/python/qmk/cli/find.py index b6f74380ab4d..b8340f5f33a7 100644 --- a/lib/python/qmk/cli/find.py +++ b/lib/python/qmk/cli/find.py @@ -11,13 +11,17 @@ action='append', default=[], help= # noqa: `format-python` and `pytest` don't agree here. - "Filter the list of keyboards based on the supplied value in rules.mk. Matches info.json structure, and accepts the formats 'features.rgblight=true' or 'exists(matrix_pins.direct)'. May be passed multiple times, all filters need to match. Value may include wildcards such as '*' and '?'." # noqa: `format-python` and `pytest` don't agree here. + "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 '?'." # noqa: `format-python` and `pytest` don't agree here. ) +@cli.argument('-p', '--print', arg_only=True, action='append', default=[], help="For each matched target, print the value of the supplied info.json key. May be passed multiple times.") @cli.argument('-km', '--keymap', type=str, default='default', help="The keymap name to build. Default is 'default'.") @cli.subcommand('Find builds which match supplied search criteria.') def find(cli): """Search through all keyboards and keymaps for a given search criteria. """ - targets = search_keymap_targets(cli.args.keymap, cli.args.filter) - for target in targets: - print(f'{target[0]}:{target[1]}') + targets = search_keymap_targets(cli.args.keymap, cli.args.filter, cli.args.print) + for keyboard, keymap, print_vals in targets: + print(f'{keyboard}:{keymap}') + + for key, val in print_vals: + print(f' {key}={val}') diff --git a/lib/python/qmk/makefile.py b/lib/python/qmk/makefile.py index 02c2e70050c3..ae95abbf2368 100644 --- a/lib/python/qmk/makefile.py +++ b/lib/python/qmk/makefile.py @@ -18,7 +18,7 @@ def parse_rules_mk_file(file, rules_mk=None): file = Path(file) if file.exists(): - rules_mk_lines = file.read_text().split("\n") + rules_mk_lines = file.read_text(encoding='utf-8').split("\n") for line in rules_mk_lines: # Filter out comments diff --git a/lib/python/qmk/search.py b/lib/python/qmk/search.py index af48900e6be3..8728890b2777 100644 --- a/lib/python/qmk/search.py +++ b/lib/python/qmk/search.py @@ -45,7 +45,7 @@ def _load_keymap_info(keyboard, keymap): return (keyboard, keymap, keymap_json(keyboard, keymap)) -def search_keymap_targets(keymap='default', filters=[]): +def search_keymap_targets(keymap='default', filters=[], print_vals=[]): targets = [] with multiprocessing.Pool() as pool: @@ -66,14 +66,43 @@ def search_keymap_targets(keymap='default', filters=[]): cli.log.info('Parsing data for all matching keyboard/keymap combinations...') valid_keymaps = [(e[0], e[1], dotty(e[2])) for e in pool.starmap(_load_keymap_info, target_list)] + function_re = re.compile(r'^(?P[a-zA-Z]+)\((?P[a-zA-Z0-9_\.]+)(,\s*(?P[^#]+))?\)$') equals_re = re.compile(r'^(?P[a-zA-Z0-9_\.]+)\s*=\s*(?P[^#]+)$') - exists_re = re.compile(r'^exists\((?P[a-zA-Z0-9_\.]+)\)$') - for filter_txt in filters: - f = equals_re.match(filter_txt) - if f is not None: - key = f.group('key') - value = f.group('value') - cli.log.info(f'Filtering on condition ("{key}" == "{value}")...') + + for filter_expr in filters: + function_match = function_re.match(filter_expr) + equals_match = equals_re.match(filter_expr) + + if function_match is not None: + func_name = function_match.group('function').lower() + key = function_match.group('key') + value = function_match.group('value') + + if value is not None: + if func_name == 'length': + valid_keymaps = filter(lambda e: key in e[2] and len(e[2].get(key)) == int(value), valid_keymaps) + elif func_name == 'contains': + valid_keymaps = filter(lambda e: key in e[2] and value in e[2].get(key), valid_keymaps) + else: + cli.log.warning(f'Unrecognized filter expression: {function_match.group(0)}') + continue + + cli.log.info(f'Filtering on condition: {{fg_green}}{func_name}{{fg_reset}}({{fg_cyan}}{key}{{fg_reset}}, {{fg_cyan}}{value}{{fg_reset}})...') + else: + if func_name == 'exists': + valid_keymaps = filter(lambda e: key in e[2], valid_keymaps) + elif func_name == 'absent': + valid_keymaps = filter(lambda e: key not in e[2], valid_keymaps) + else: + cli.log.warning(f'Unrecognized filter expression: {function_match.group(0)}') + continue + + cli.log.info(f'Filtering on condition: {{fg_green}}{func_name}{{fg_reset}}({{fg_cyan}}{key}{{fg_reset}})...') + + elif equals_match is not None: + key = equals_match.group('key') + value = equals_match.group('value') + cli.log.info(f'Filtering on condition: {{fg_cyan}}{key}{{fg_reset}} == {{fg_cyan}}{value}{{fg_reset}}...') def _make_filter(k, v): expr = fnmatch.translate(v) @@ -87,13 +116,10 @@ def f(e): return f valid_keymaps = filter(_make_filter(key, value), valid_keymaps) + else: + cli.log.warning(f'Unrecognized filter expression: {filter_expr}') + continue - f = exists_re.match(filter_txt) - if f is not None: - key = f.group('key') - cli.log.info(f'Filtering on condition (exists: "{key}")...') - valid_keymaps = filter(lambda e: e[2].get(key) is not None, valid_keymaps) - - targets = [(e[0], e[1]) for e in valid_keymaps] + targets = [(e[0], e[1], [(p, e[2].get(p)) for p in print_vals]) for e in valid_keymaps] return targets From 6d90fa2300b463f5cc6920022a445d5ed217124c Mon Sep 17 00:00:00 2001 From: Ryan Date: Sat, 20 May 2023 22:15:05 +1000 Subject: [PATCH 16/19] `qmk format-json`: Expose full key path and respect `sort_keys` (#20836) --- lib/python/qmk/cli/c2json.py | 2 +- lib/python/qmk/cli/format/json.py | 2 +- lib/python/qmk/cli/generate/info_json.py | 2 +- lib/python/qmk/cli/info.py | 2 +- lib/python/qmk/cli/migrate.py | 2 +- lib/python/qmk/cli/new/keyboard.py | 2 +- lib/python/qmk/cli/via2json.py | 2 +- lib/python/qmk/importers.py | 6 +- lib/python/qmk/json_encoders.py | 80 +++++++++++------------- 9 files changed, 48 insertions(+), 52 deletions(-) diff --git a/lib/python/qmk/cli/c2json.py b/lib/python/qmk/cli/c2json.py index 43110a93875a..7f6aca070a1d 100644 --- a/lib/python/qmk/cli/c2json.py +++ b/lib/python/qmk/cli/c2json.py @@ -57,7 +57,7 @@ def c2json(cli): cli.args.output.parent.mkdir(parents=True, exist_ok=True) if cli.args.output.exists(): cli.args.output.replace(cli.args.output.parent / (cli.args.output.name + '.bak')) - cli.args.output.write_text(json.dumps(keymap_json, cls=InfoJSONEncoder)) + cli.args.output.write_text(json.dumps(keymap_json, cls=InfoJSONEncoder, sort_keys=True)) if not cli.args.quiet: cli.log.info('Wrote keymap to %s.', cli.args.output) diff --git a/lib/python/qmk/cli/format/json.py b/lib/python/qmk/cli/format/json.py index 19d504491f12..058b61329424 100755 --- a/lib/python/qmk/cli/format/json.py +++ b/lib/python/qmk/cli/format/json.py @@ -62,4 +62,4 @@ def format_json(cli): json_file['layers'][layer_num] = current_layer # Display the results - print(json.dumps(json_file, cls=json_encoder)) + print(json.dumps(json_file, cls=json_encoder, sort_keys=True)) diff --git a/lib/python/qmk/cli/generate/info_json.py b/lib/python/qmk/cli/generate/info_json.py index 0dc80f10ccce..08c294146bc4 100755 --- a/lib/python/qmk/cli/generate/info_json.py +++ b/lib/python/qmk/cli/generate/info_json.py @@ -76,7 +76,7 @@ def generate_info_json(cli): # Build the info.json file kb_info_json = info_json(cli.config.generate_info_json.keyboard) strip_info_json(kb_info_json) - info_json_text = json.dumps(kb_info_json, indent=4, cls=InfoJSONEncoder) + info_json_text = json.dumps(kb_info_json, indent=4, cls=InfoJSONEncoder, sort_keys=True) if cli.args.output: # Write to a file diff --git a/lib/python/qmk/cli/info.py b/lib/python/qmk/cli/info.py index 839139346c2f..cfb73ce1fd91 100755 --- a/lib/python/qmk/cli/info.py +++ b/lib/python/qmk/cli/info.py @@ -200,7 +200,7 @@ def info(cli): # Output in the requested format if cli.args.format == 'json': - print(json.dumps(kb_info_json, cls=InfoJSONEncoder)) + print(json.dumps(kb_info_json, cls=InfoJSONEncoder, sort_keys=True)) return True elif cli.args.format == 'text': print_dotted_output(kb_info_json) diff --git a/lib/python/qmk/cli/migrate.py b/lib/python/qmk/cli/migrate.py index 4164f9c8adfa..c1b1ad1ea9da 100644 --- a/lib/python/qmk/cli/migrate.py +++ b/lib/python/qmk/cli/migrate.py @@ -75,7 +75,7 @@ def migrate(cli): # Finally write out updated info.json cli.log.info(f' Updating {target_info}') - target_info.write_text(json.dumps(info_data.to_dict(), cls=InfoJSONEncoder)) + target_info.write_text(json.dumps(info_data.to_dict(), cls=InfoJSONEncoder, sort_keys=True)) cli.log.info(f'{{fg_green}}Migration of keyboard {{fg_cyan}}{cli.args.keyboard}{{fg_green}} complete!{{fg_reset}}') cli.log.info(f"Verify build with {{fg_yellow}}qmk compile -kb {cli.args.keyboard} -km default{{fg_reset}}.") diff --git a/lib/python/qmk/cli/new/keyboard.py b/lib/python/qmk/cli/new/keyboard.py index cdd391916874..ce956d0ce147 100644 --- a/lib/python/qmk/cli/new/keyboard.py +++ b/lib/python/qmk/cli/new/keyboard.py @@ -102,7 +102,7 @@ def augment_community_info(src, dest): item["matrix"] = [int(item["y"]), int(item["x"])] # finally write out the updated info.json - dest.write_text(json.dumps(info, cls=InfoJSONEncoder)) + dest.write_text(json.dumps(info, cls=InfoJSONEncoder, sort_keys=True)) def _question(*args, **kwargs): diff --git a/lib/python/qmk/cli/via2json.py b/lib/python/qmk/cli/via2json.py index 6edc9dfbe5ed..77823b5d9d78 100755 --- a/lib/python/qmk/cli/via2json.py +++ b/lib/python/qmk/cli/via2json.py @@ -141,5 +141,5 @@ def via2json(cli): # Generate the keymap.json keymap_json = generate_json(cli.args.keymap, cli.args.keyboard, keymap_layout, keymap_data, macro_data) - keymap_lines = [json.dumps(keymap_json, cls=KeymapJSONEncoder)] + keymap_lines = [json.dumps(keymap_json, cls=KeymapJSONEncoder, sort_keys=True)] dump_lines(cli.args.output, keymap_lines, cli.args.quiet) diff --git a/lib/python/qmk/importers.py b/lib/python/qmk/importers.py index edc1f940daa6..8c449a719406 100644 --- a/lib/python/qmk/importers.py +++ b/lib/python/qmk/importers.py @@ -91,7 +91,7 @@ def import_keymap(keymap_data): keyboard_keymap.parent.mkdir(parents=True, exist_ok=True) # Dump out all those lovely files - keyboard_keymap.write_text(json.dumps(keymap_data, cls=KeymapJSONEncoder)) + keyboard_keymap.write_text(json.dumps(keymap_data, cls=KeymapJSONEncoder, sort_keys=True)) return (kb_name, km_name) @@ -139,8 +139,8 @@ def import_keyboard(info_data, keymap_data=None): temp = json_load(keyboard_info) deep_update(temp, info_data) - keyboard_info.write_text(json.dumps(temp, cls=InfoJSONEncoder)) - keyboard_keymap.write_text(json.dumps(keymap_data, cls=KeymapJSONEncoder)) + keyboard_info.write_text(json.dumps(temp, cls=InfoJSONEncoder, sort_keys=True)) + keyboard_keymap.write_text(json.dumps(keymap_data, cls=KeymapJSONEncoder, sort_keys=True)) return kb_name diff --git a/lib/python/qmk/json_encoders.py b/lib/python/qmk/json_encoders.py index e61c63aff3ed..1e90f6a28808 100755 --- a/lib/python/qmk/json_encoders.py +++ b/lib/python/qmk/json_encoders.py @@ -27,39 +27,56 @@ def encode_decimal(self, obj): return float(obj) - def encode_dict_single_line(self, obj): - return "{" + ", ".join(f"{self.encode(key)}: {self.encode(element)}" for key, element in sorted(obj.items(), key=self.sort_layout)) + "}" + def encode_dict(self, obj, path): + """Encode a dict-like object. + """ + if obj: + self.indentation_level += 1 + + items = sorted(obj.items(), key=self.sort_dict) if self.sort_keys else obj.items() + output = [self.indent_str + f"{json.dumps(key)}: {self.encode(value, path + [key])}" for key, value in items] - def encode_list(self, obj, key=None): + self.indentation_level -= 1 + + return "{\n" + ",\n".join(output) + "\n" + self.indent_str + "}" + else: + return "{}" + + def encode_dict_single_line(self, obj, path): + """Encode a dict-like object onto a single line. + """ + return "{" + ", ".join(f"{json.dumps(key)}: {self.encode(value, path + [key])}" for key, value in sorted(obj.items(), key=self.sort_layout)) + "}" + + def encode_list(self, obj, path): """Encode a list-like object. """ if self.primitives_only(obj): - return "[" + ", ".join(self.encode(element) for element in obj) + "]" + return "[" + ", ".join(self.encode(value, path + [index]) for index, value in enumerate(obj)) + "]" else: self.indentation_level += 1 - if key in ('layout', 'rotary'): - # These are part of a layout or led/encoder config, put them on a single line. - output = [self.indent_str + self.encode_dict_single_line(element) for element in obj] + if path[-1] in ('layout', 'rotary'): + # These are part of a LED layout or encoder config, put them on a single line + output = [self.indent_str + self.encode_dict_single_line(value, path + [index]) for index, value in enumerate(obj)] else: - output = [self.indent_str + self.encode(element) for element in obj] + output = [self.indent_str + self.encode(value, path + [index]) for index, value in enumerate(obj)] self.indentation_level -= 1 return "[\n" + ",\n".join(output) + "\n" + self.indent_str + "]" - def encode(self, obj, key=None): - """Encode keymap.json objects for QMK. + def encode(self, obj, path=[]): + """Encode JSON objects for QMK. """ if isinstance(obj, Decimal): return self.encode_decimal(obj) elif isinstance(obj, (list, tuple)): - return self.encode_list(obj, key) + return self.encode_list(obj, path) elif isinstance(obj, dict): - return self.encode_dict(obj, key) + return self.encode_dict(obj, path) else: return super().encode(obj) @@ -80,19 +97,10 @@ def indent_str(self): class InfoJSONEncoder(QMKJSONEncoder): """Custom encoder to make info.json's a little nicer to work with. """ - def encode_dict(self, obj, key): - """Encode info.json dictionaries. + def sort_layout(self, item): + """Sorts the hashes in a nice way. """ - if obj: - self.indentation_level += 1 - output = [self.indent_str + f"{json.dumps(k)}: {self.encode(v, k)}" for k, v in sorted(obj.items(), key=self.sort_dict)] - self.indentation_level -= 1 - return "{\n" + ",\n".join(output) + "\n" + self.indent_str + "}" - else: - return "{}" - - def sort_layout(self, key): - key = key[0] + key = item[0] if key == 'label': return '00label' @@ -117,14 +125,14 @@ def sort_layout(self, key): return key - def sort_dict(self, key): + def sort_dict(self, item): """Forces layout to the back of the sort order. """ - key = key[0] + key = item[0] if self.indentation_level == 1: if key == 'manufacturer': - return '10keyboard_name' + return '10manufacturer' elif key == 'keyboard_name': return '11keyboard_name' @@ -150,19 +158,7 @@ def sort_dict(self, key): class KeymapJSONEncoder(QMKJSONEncoder): """Custom encoder to make keymap.json's a little nicer to work with. """ - def encode_dict(self, obj, key): - """Encode dictionary objects for keymap.json. - """ - if obj: - self.indentation_level += 1 - output = [self.indent_str + f"{json.dumps(k)}: {self.encode(v, k)}" for k, v in sorted(obj.items(), key=self.sort_dict)] - self.indentation_level -= 1 - return "{\n" + ",\n".join(output) + "\n" + self.indent_str + "}" - - else: - return "{}" - - def encode_list(self, obj, k=None): + def encode_list(self, obj, path): """Encode a list-like object. """ if self.indentation_level == 2: @@ -196,10 +192,10 @@ def encode_list(self, obj, k=None): return "[\n" + ",\n".join(output) + "\n" + self.indent_str + "]" - def sort_dict(self, key): + def sort_dict(self, item): """Sorts the hashes in a nice way. """ - key = key[0] + key = item[0] if self.indentation_level == 1: if key == 'version': From 21b660fa07455a0173770ccab1cd21d7c7625014 Mon Sep 17 00:00:00 2001 From: Sergey Vlasov Date: Sat, 20 May 2023 15:15:55 +0300 Subject: [PATCH 17/19] Move `pre_process_record_kb()` before `process_combo()` (#20969) --- docs/understanding_qmk.md | 2 +- quantum/quantum.c | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/understanding_qmk.md b/docs/understanding_qmk.md index 9c5f0419a116..7cb46bd8cf2e 100644 --- a/docs/understanding_qmk.md +++ b/docs/understanding_qmk.md @@ -129,9 +129,9 @@ The `process_record()` function itself is deceptively simple, but hidden within * [`void action_exec(keyevent_t event)`](https://github.com/qmk/qmk_firmware/blob/325da02e57fe7374e77b82cb00360ba45167e25c/quantum/action.c#L78-L140) * [`void pre_process_record_quantum(keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/325da02e57fe7374e77b82cb00360ba45167e25c/quantum/quantum.c#L204) - * [`bool process_combo(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/325da02e57fe7374e77b82cb00360ba45167e25c/quantum/process_keycode/process_combo.c#L521) * [`bool pre_process_record_kb(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/27119fa77e8a1b95fff80718d3db4f3e32849298/quantum/quantum.c#L117) * [`bool pre_process_record_user(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/27119fa77e8a1b95fff80718d3db4f3e32849298/quantum/quantum.c#L121) + * [`bool process_combo(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/325da02e57fe7374e77b82cb00360ba45167e25c/quantum/process_keycode/process_combo.c#L521) * [`void process_record(keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/325da02e57fe7374e77b82cb00360ba45167e25c/quantum/action.c#L254) * [`bool process_record_quantum(keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/325da02e57fe7374e77b82cb00360ba45167e25c/quantum/quantum.c#L224) * [Map this record to a keycode](https://github.com/qmk/qmk_firmware/blob/325da02e57fe7374e77b82cb00360ba45167e25c/quantum/quantum.c#L225) diff --git a/quantum/quantum.c b/quantum/quantum.c index 950be3182e78..fdc24fa2d0b9 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -211,12 +211,11 @@ uint16_t get_event_keycode(keyevent_t event, bool update_layer_cache) { /* Get keycode, and then process pre tapping functionality */ bool pre_process_record_quantum(keyrecord_t *record) { uint16_t keycode = get_record_keycode(record, true); + return pre_process_record_kb(keycode, record) && #ifdef COMBO_ENABLE - if (!(process_combo(keycode, record))) { - return false; - } + process_combo(keycode, record) && #endif - return pre_process_record_kb(keycode, record); + true; } /* Get keycode, and then call keyboard function */ From e1766df185869d8a591228d37f3f7b6d5b4049b4 Mon Sep 17 00:00:00 2001 From: Albert Y <76888457+filterpaper@users.noreply.github.com> Date: Sat, 20 May 2023 20:16:36 +0800 Subject: [PATCH 18/19] Add a change log for PR20584 (#20998) --- docs/ChangeLog/20230528/PR20584.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 docs/ChangeLog/20230528/PR20584.md diff --git a/docs/ChangeLog/20230528/PR20584.md b/docs/ChangeLog/20230528/PR20584.md new file mode 100644 index 000000000000..e9e49f5730a2 --- /dev/null +++ b/docs/ChangeLog/20230528/PR20584.md @@ -0,0 +1,3 @@ +Two new boolean callback functions, `pre_process_record_kb` and `pre_process_record_user`, are added in this change. They are called at the beginning of `process_record`, right before `process_combo`. + +Similar to existing `*_kb` and `*_user` callback functions, returning `false` will halt further processing of key events. The `pre_process_record_user` function will allow user space opportunity to handle or capture an input before it undergoes quantum processing. For example, while action tapping is still resolving the tap or hold output of a mod-tap key, `pre_process_record_user` can capture the next key record of an input event that follows. That key record can be used to influence the [decision of the mod-tap](https://docs.qmk.fm/#/tap_hold) key that is currently undergoing quantum processing. From 3993b15f054265071730cdb450f43457dcf4c64a Mon Sep 17 00:00:00 2001 From: Pascal Getreuer <50221757+getreuer@users.noreply.github.com> Date: Sat, 20 May 2023 05:35:06 -0700 Subject: [PATCH 19/19] [Core] Add Repeat Key ("repeat last key") as a core feature. (#19700) Co-authored-by: casuanoob <96005765+casuanoob@users.noreply.github.com> Co-authored-by: Sergey Vlasov --- builddefs/generic_features.mk | 1 + builddefs/show_options.mk | 3 +- data/constants/keycodes/keycodes_0.0.3.hjson | 0 .../keycodes/keycodes_0.0.3_quantum.hjson | 18 + docs/_summary.md | 1 + docs/feature_repeat_key.md | 457 +++++++++++ docs/ja/_summary.md | 1 + docs/keycodes.md | 9 + docs/zh-cn/_summary.md | 1 + quantum/action.c | 4 +- quantum/action.h | 2 +- quantum/keycodes.h | 6 +- quantum/process_keycode/process_repeat_key.c | 109 +++ quantum/process_keycode/process_repeat_key.h | 62 ++ quantum/quantum.c | 5 +- quantum/quantum.h | 5 + quantum/repeat_key.c | 282 +++++++ quantum/repeat_key.h | 80 ++ tests/repeat_key/alt_repeat_key/config.h | 18 + tests/repeat_key/alt_repeat_key/test.mk | 18 + .../alt_repeat_key/test_alt_repeat_key.cpp | 523 ++++++++++++ tests/repeat_key/config.h | 20 + tests/repeat_key/repeat_key_combo/config.h | 18 + tests/repeat_key/repeat_key_combo/test.mk | 18 + .../test_repeat_key_combo.cpp | 67 ++ tests/repeat_key/test.mk | 18 + tests/repeat_key/test_repeat_key.cpp | 754 ++++++++++++++++++ tests/test_common/keycode_table.cpp | 2 + tests/test_common/test_driver.hpp | 12 + 29 files changed, 2508 insertions(+), 6 deletions(-) create mode 100644 data/constants/keycodes/keycodes_0.0.3.hjson create mode 100644 data/constants/keycodes/keycodes_0.0.3_quantum.hjson create mode 100644 docs/feature_repeat_key.md create mode 100644 quantum/process_keycode/process_repeat_key.c create mode 100644 quantum/process_keycode/process_repeat_key.h create mode 100644 quantum/repeat_key.c create mode 100644 quantum/repeat_key.h create mode 100644 tests/repeat_key/alt_repeat_key/config.h create mode 100644 tests/repeat_key/alt_repeat_key/test.mk create mode 100644 tests/repeat_key/alt_repeat_key/test_alt_repeat_key.cpp create mode 100644 tests/repeat_key/config.h create mode 100644 tests/repeat_key/repeat_key_combo/config.h create mode 100644 tests/repeat_key/repeat_key_combo/test.mk create mode 100644 tests/repeat_key/repeat_key_combo/test_repeat_key_combo.cpp create mode 100644 tests/repeat_key/test.mk create mode 100644 tests/repeat_key/test_repeat_key.cpp diff --git a/builddefs/generic_features.mk b/builddefs/generic_features.mk index 5a1ef5c6f0a5..4e058dcd2659 100644 --- a/builddefs/generic_features.mk +++ b/builddefs/generic_features.mk @@ -32,6 +32,7 @@ GENERIC_FEATURES = \ KEY_OVERRIDE \ LEADER \ PROGRAMMABLE_BUTTON \ + REPEAT_KEY \ SECURE \ SPACE_CADET \ SWAP_HANDS \ diff --git a/builddefs/show_options.mk b/builddefs/show_options.mk index 9723b45438a8..8bcc02083bc5 100644 --- a/builddefs/show_options.mk +++ b/builddefs/show_options.mk @@ -85,7 +85,8 @@ OTHER_OPTION_NAMES = \ SECURE_ENABLE \ CAPS_WORD_ENABLE \ AUTOCORRECT_ENABLE \ - TRI_LAYER_ENABLE + TRI_LAYER_ENABLE \ + REPEAT_KEY_ENABLE define NAME_ECHO @printf " %-30s = %-16s # %s\\n" "$1" "$($1)" "$(origin $1)" diff --git a/data/constants/keycodes/keycodes_0.0.3.hjson b/data/constants/keycodes/keycodes_0.0.3.hjson new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/data/constants/keycodes/keycodes_0.0.3_quantum.hjson b/data/constants/keycodes/keycodes_0.0.3_quantum.hjson new file mode 100644 index 000000000000..23a3c9b06d3b --- /dev/null +++ b/data/constants/keycodes/keycodes_0.0.3_quantum.hjson @@ -0,0 +1,18 @@ +{ + "keycodes": { + "0x7C79": { + "group": "quantum", + "key": "QK_REPEAT_KEY", + "aliases": [ + "QK_REP" + ] + }, + "0x7C7A": { + "group": "quantum", + "key": "QK_ALT_REPEAT_KEY", + "aliases": [ + "QK_AREP" + ] + } + } +} diff --git a/docs/_summary.md b/docs/_summary.md index ce579cb07126..3d9bde6b1795 100644 --- a/docs/_summary.md +++ b/docs/_summary.md @@ -70,6 +70,7 @@ * [Macros](feature_macros.md) * [Mouse Keys](feature_mouse_keys.md) * [Programmable Button](feature_programmable_button.md) + * [Repeat Key](feature_repeat_key.md) * [Space Cadet Shift](feature_space_cadet.md) * [US ANSI Shifted Keys](keycodes_us_ansi_shifted.md) diff --git a/docs/feature_repeat_key.md b/docs/feature_repeat_key.md new file mode 100644 index 000000000000..6fa8a724ef75 --- /dev/null +++ b/docs/feature_repeat_key.md @@ -0,0 +1,457 @@ +# Repeat Key + +The Repeat Key performs the action of the last pressed key. Tapping the Repeat +Key after tapping the Z key types another "`z`." This is useful for +typing doubled letters, like the `z` in "`dazzle`": a double tap on Z +can instead be a roll from Z to Repeat, which is +potentially faster and more comfortable. The Repeat Key is also useful for +hotkeys, like repeating Ctrl + Shift + Right Arrow to select by word. + +Repeat Key remembers mods that were active with the last key press. These mods +are combined with any additional mods while pressing the Repeat Key. If the last +press key was Ctrl + Z, then Shift + +Repeat performs Ctrl + Shift + `Z`. + +## How do I enable Repeat Key + +In your `rules.mk`, add: + +```make +REPEAT_KEY_ENABLE = yes +``` + +Then pick a key in your keymap and assign it the keycode `QK_REPEAT_KEY` (short +alias `QK_REP`). Optionally, use the keycode `QK_ALT_REPEAT_KEY` (short alias +`QK_AREP`) on another key. + +## Keycodes + +|Keycode |Aliases |Description | +|-----------------------|---------|-------------------------------------| +|`QK_REPEAT_KEY` |`QK_REP` |Repeat the last pressed key | +|`QK_ALT_REPEAT_KEY` |`QK_AREP`|Perform alternate of the last key | + +## Alternate Repeating + +The Alternate Repeat Key performs the "alternate" action of the last pressed key +if it is defined. By default, Alternate Repeat is defined for navigation keys to +act in the reverse direction. When the last key is the common "select by word" +hotkey Ctrl + Shift + Right Arrow, the Alternate Repeat Key performs Ctrl + +Shift + Left Arrow, which together with the Repeat Key enables convenient +selection by words in either direction. + +Alternate Repeat is enabled with the Repeat Key by default. Optionally, to +reduce firmware size, Alternate Repeat may be disabled by adding in config.h: + +```c +#define NO_ALT_REPEAT_KEY +``` + +The following alternate keys are defined by default. See +`get_alt_repeat_key_keycode_user()` below for how to change or add to these +definitions. Where it makes sense, these definitions also include combinations +with mods, like Ctrl + Left ↔ Ctrl + Right Arrow. + +**Navigation** + +|Keycodes |Description | +|-----------------------------------|-----------------------------------| +|`KC_LEFT` ↔ `KC_RGHT` | Left ↔ Right Arrow | +|`KC_UP` ↔ `KC_DOWN` | Up ↔ Down Arrow | +|`KC_HOME` ↔ `KC_END` | Home ↔ End | +|`KC_PGUP` ↔ `KC_PGDN` | Page Up ↔ Page Down | +|`KC_MS_L` ↔ `KC_MS_R` | Mouse Cursor Left ↔ Right | +|`KC_MS_U` ↔ `KC_MS_D` | Mouse Cursor Up ↔ Down | +|`KC_WH_L` ↔ `KC_WH_R` | Mouse Wheel Left ↔ Right | +|`KC_WH_U` ↔ `KC_WH_D` | Mouse Wheel Up ↔ Down | + +**Misc** + +|Keycodes |Description | +|-----------------------------------|-----------------------------------| +|`KC_BSPC` ↔ `KC_DEL` | Backspace ↔ Delete | +|`KC_LBRC` ↔ `KC_RBRC` | `[` ↔ `]` | +|`KC_LCBR` ↔ `KC_RCBR` | `{` ↔ `}` | + +**Media** + +|Keycodes |Description | +|-----------------------------------|-----------------------------------| +|`KC_WBAK` ↔ `KC_WFWD` | Browser Back ↔ Forward | +|`KC_MNXT` ↔ `KC_MPRV` | Next ↔ Previous Media Track | +|`KC_MFFD` ↔ `KC_MRWD` | Fast Forward ↔ Rewind Media | +|`KC_VOLU` ↔ `KC_VOLD` | Volume Up ↔ Down | +|`KC_BRIU` ↔ `KC_BRID` | Brightness Up ↔ Down | + +**Hotkeys in Vim, Emacs, and other programs** + +|Keycodes |Description | +|-----------------------------------|-----------------------------------| +|mod + `KC_F` ↔ mod + `KC_B` | Forward ↔ Backward | +|mod + `KC_D` ↔ mod + `KC_U` | Down ↔ Up | +|mod + `KC_N` ↔ mod + `KC_P` | Next ↔ Previous | +|mod + `KC_A` ↔ mod + `KC_E` | Home ↔ End | +|mod + `KC_O` ↔ mod + `KC_I` | Vim jump list Older ↔ Newer | +|`KC_J` ↔ `KC_K` | Down ↔ Up | +|`KC_H` ↔ `KC_L` | Left ↔ Right | +|`KC_W` ↔ `KC_B` | Forward ↔ Backward by Word | + +(where above, "mod" is Ctrl, Alt, or GUI) + + +## Defining alternate keys + +Use the `get_alt_repeat_key_keycode_user()` callback to define the "alternate" +for additional keys or override the default definitions. For example, to define +Ctrl + Y as the alternate of Ctrl + Z, and vice versa, add the following in +keymap.c: + +```c +uint16_t get_alt_repeat_key_keycode_user(uint16_t keycode, uint8_t mods) { + if ((mods & MOD_MASK_CTRL)) { // Was Ctrl held? + switch (keycode) { + case KC_Y: return C(KC_Z); // Ctrl + Y reverses to Ctrl + Z. + case KC_Z: return C(KC_Y); // Ctrl + Z reverses to Ctrl + Y. + } + } + + return KC_TRNS; // Defer to default definitions. +} +``` + +The `keycode` and `mods` args are the keycode and mods that were active with the +last pressed key. The meaning of the return value from this function is: + +* `KC_NO` – do nothing (any predefined alternate key is not used); +* `KC_TRNS` – use the default alternate key if it exists; +* anything else – use the specified keycode. Any keycode may be returned + as an alternate key, including custom keycodes. + +Another example, defining Shift + Tab as the alternate of Tab, and vice versa: + +```c +uint16_t get_alt_repeat_key_keycode_user(uint16_t keycode, uint8_t mods) { + bool shifted = (mods & MOD_MASK_SHIFT); // Was Shift held? + switch (keycode) { + case KC_TAB: + if (shifted) { // If the last key was Shift + Tab, + return KC_TAB; // ... the reverse is Tab. + } else { // Otherwise, the last key was Tab, + return S(KC_TAB); // ... and the reverse is Shift + Tab. + } + } + + return KC_TRNS; +} +``` + +#### Eliminating SFBs + +Alternate Repeat can be configured more generally to perform an action that +"complements" the last key. Alternate Repeat is not limited to reverse +repeating, and it need not be symmetric. You can use it to eliminate cases of +same-finger bigrams in your layout, that is, pairs of letters typed by the same +finger. The following addresses the top 5 same-finger bigrams in English on +QWERTY, so that for instance "`ed`" may be typed as E, Alt +Repeat. + +```c +uint16_t get_alt_repeat_key_keycode_user(uint16_t keycode, uint8_t mods) { + switch (keycode) { + case KC_E: return KC_D; // For "ED" bigram. + case KC_D: return KC_E; // For "DE" bigram. + case KC_C: return KC_E; // For "CE" bigram. + case KC_L: return KC_O; // For "LO" bigram. + case KC_U: return KC_N; // For "UN" bigram. + } + + return KC_TRNS; +} +``` + +#### Typing shortcuts + +A useful possibility is having Alternate Repeat press [a +macro](feature_macros.md). This way macros can be used without having to +dedicate keys to them. The following defines a couple shortcuts. + +* Typing K, Alt Repeat produces "`keyboard`," with the + initial "`k`" typed as usual and the "`eybord`" produced by the macro. +* Typing ., Alt Repeat produces "`../`," handy for "up + directory" on the shell. Similary, . types the initial "`.`" and + "`./`" is produced by the macro. + +```c +enum custom_keycodes { + M_KEYBOARD = SAFE_RANGE, + M_UPDIR, + // Other custom keys... +}; + +uint16_t get_alt_repeat_key_keycode_user(uint16_t keycode, uint8_t mods) { + switch (keycode) { + case KC_K: return M_KEYBOARD; + case KC_DOT: return M_UPDIR; + } + + return KC_TRNS; +} + +bool process_record_user(uint16_t keycode, keyrecord_t* record) { + switch (keycode) { + case M_KEYBOARD: SEND_STRING(/*k*/"eyboard"); break; + case M_UPDIR: SEND_STRING(/*.*/"./"); break; + } + return true; +} +``` + +## Ignoring certain keys and mods + +In tracking what is "the last key" to be repeated or alternate repeated, +modifier and layer switch keys are always ignored. This makes it possible to set +some mods and change layers between pressing a key and repeating it. By default, +all other (non-modifier, non-layer switch) keys are remembered so that they are +eligible for repeating. To configure additional keys to be ignored, define +`remember_last_key_user()` in your keymap.c. + +#### Ignoring a key + +The following ignores the Backspace key: + +```c +bool remember_last_key_user(uint16_t keycode, keyrecord_t* record, + uint8_t* remembered_mods) { + switch (keycode) { + case KC_BSPC: + return false; // Ignore backspace. + } + + return true; // Other keys can be repeated. +} +``` + +Then for instance, the Repeat key in Left Arrow, +Backspace, Repeat sends Left Arrow again instead of +repeating Backspace. + +The `remember_last_key_user()` callback is called on every key press excluding +modifiers and layer switches. Returning true indicates the key is remembered, +while false means it is ignored. + +#### Filtering remembered mods + +The `remembered_mods` arg represents the mods that will be remembered with +this key. It can be modified to forget certain mods. This may be +useful to forget capitalization when repeating shifted letters, so that "Aaron" +does not becom "AAron": + +```c +bool remember_last_key_user(uint16_t keycode, keyrecord_t* record, + uint8_t* remembered_mods) { + // Forget Shift on letter keys when Shift or AltGr are the only mods. + switch (keycode) { + case KC_A ... KC_Z: + if ((*remembered_mods & ~(MOD_MASK_SHIFT | MOD_BIT(KC_RALT))) == 0) { + *remembered_mods &= ~MOD_MASK_SHIFT; + } + break; + } + + return true; +} +``` + +#### Further conditions + +Besides checking the keycode, this callback could also make conditions based on +the current layer state (with `IS_LAYER_ON(layer)`) or mods (`get_mods()`). For +example, the following ignores keys on layer 2 as well as key combinations +involving GUI: + +```c +bool remember_last_key_user(uint16_t keycode, keyrecord_t* record, + uint8_t* remembered_mods) { + if (IS_LAYER_ON(2) || (get_mods() & MOD_MASK_GUI)) { + return false; // Ignore layer 2 keys and GUI chords. + } + + return true; // Other keys can be repeated. +} +``` + +?> See [Layer Functions](feature_layers.md#functions) and [Checking Modifier +State](feature_advanced_keycodes.md#checking-modifier-state) for further +details. + + +## Handle how a key is repeated + +By default, pressing the Repeat Key will simply behave as if the last key +were pressed again. This also works with macro keys with custom handlers, +invoking the macro again. In case fine-tuning is needed for sensible repetition, +you can handle how a key is repeated with `get_repeat_key_count()` within +`process_record_user()`. + +The `get_repeat_key_count()` function returns a signed count of times the key +has been repeated or alternate repeated. When a key is pressed as usual, +`get_repeat_key_count()` is 0. On the first repeat, it is 1, then the second +repeat, 2, and so on. Negative counts are used similarly for alternate +repeating. For instance supposing `MY_MACRO` is a custom keycode used in the +layout: + +```c +bool process_record_user(uint16_t keycode, keyrecord_t* record) { + switch (keycode) { + case MY_MACRO: + if (get_repeat_key_count() > 0) { + // MY_MACRO is being repeated! + if (record->event.pressed) { + SEND_STRING("repeat!"); + } + } else { + // MY_MACRO is being used normally. + if (record->event.pressed) { + SEND_STRING("macro"); + } + } + return false; + + // Other macros... + } + return true; +} +``` + +## Handle how a key is alternate repeated + +Pressing the Alternate Repeat Key behaves as if the "alternate" of the last +pressed key were pressed, if an alternate is defined. To define how a particular +key is alternate repeated, use the `get_alt_repeat_key_keycode_user()` callback +as described above to define which keycode to use as its alternate. Beyond this, +`get_repeat_key_count()` may be used in custom handlers to fine-tune behavior +when alternate repeating. + +The following example defines `MY_MACRO` as its own alternate, and specially +handles repeating and alternate repeating: + +```c +uint16_t get_alt_repeat_key_keycode_user(uint16_t keycode, uint8_t mods) { + switch (keycode) { + case MY_MACRO: return MY_MACRO; // MY_MACRO is its own alternate. + } + return KC_TRNS; +} + +bool process_record_user(uint16_t keycode, keyrecord_t* record) { + switch (keycode) { + case MY_MACRO: + if (get_repeat_key_count() > 0) { // Repeating. + if (record->event.pressed) { + SEND_STRING("repeat!"); + } + } else if (get_repeat_key_count() < 0) { // Alternate repeating. + if (record->event.pressed) { + SEND_STRING("alt repeat!"); + } + } else { // Used normally. + if (record->event.pressed) { + SEND_STRING("macro"); + } + } + return false; + + // Other macros... + } + return true; +} +``` + + +## Functions + +| Function | Description | +|--------------------------------|------------------------------------------------------------------------| +| `get_last_keycode()` | The last key's keycode, the key to be repeated. | +| `get_last_mods()` | Mods to apply when repeating. | +| `set_last_keycode(kc)` | Set the keycode to be repeated. | +| `set_last_mods(mods)` | Set the mods to apply when repeating. | +| `get_repeat_key_count()` | Signed count of times the key has been repeated or alternate repeated. | +| `get_alt_repeat_key_keycode()` | Keycode to be used for alternate repeating. | + + +## Additional "Alternate" keys + +By leveraging `get_last_keycode()` in macros, it is possible to define +additional, distinct "Alternate Repeat"-like keys. The following defines two +keys `ALTREP2` and `ALTREP3` and implements ten shortcuts with them for common +English 5-gram letter patterns, taking inspiration from +[Stenotype](feature_stenography.md): + + +| Typing | Produces | Typing | Produces | +|----------------------------------|----------|----------------------------------|----------| +| A, ALTREP2 | `ation` | A, ALTREP3 | `about` | +| I, ALTREP2 | `ition` | I, ALTREP3 | `inter` | +| S, ALTREP2 | `ssion` | S, ALTREP3 | `state` | +| T, ALTREP2 | `their` | T, ALTREP3 | `there` | +| W, ALTREP2 | `which` | W, ALTREP3 | `would` | + +```c +enum custom_keycodes { + ALTREP2 = SAFE_RANGE, + ALTREP3, +}; + +// Use ALTREP2 and ALTREP3 in your layout... + +bool remember_last_key_user(uint16_t keycode, keyrecord_t* record, + uint8_t* remembered_mods) { + switch (keycode) { + case ALTREP2: + case ALTREP3: + return false; // Ignore ALTREP keys. + } + + return true; // Other keys can be repeated. +} + +static void process_altrep2(uint16_t keycode, uint8_t mods) { + switch (keycode) { + case KC_A: SEND_STRING(/*a*/"tion"); break; + case KC_I: SEND_STRING(/*i*/"tion"); break; + case KC_S: SEND_STRING(/*s*/"sion"); break; + case KC_T: SEND_STRING(/*t*/"heir"); break; + case KC_W: SEND_STRING(/*w*/"hich"); break; + } +} + +static void process_altrep3(uint16_t keycode, uint8_t mods) { + switch (keycode) { + case KC_A: SEND_STRING(/*a*/"bout"); break; + case KC_I: SEND_STRING(/*i*/"nter"); break; + case KC_S: SEND_STRING(/*s*/"tate"); break; + case KC_T: SEND_STRING(/*t*/"here"); break; + case KC_W: SEND_STRING(/*w*/"ould"); break; + } +} + +bool process_record_user(uint16_t keycode, keyrecord_t* record) { + switch (keycode) { + case ALTREP2: + if (record->event.pressed) { + process_altrep2(get_last_keycode(), get_last_mods()); + } + return false; + + case ALTREP3: + if (record->event.pressed) { + process_altrep3(get_last_keycode(), get_last_mods()); + } + return false; + } + + return true; +} +``` + diff --git a/docs/ja/_summary.md b/docs/ja/_summary.md index e49853bfd435..4d6f2348d5cf 100644 --- a/docs/ja/_summary.md +++ b/docs/ja/_summary.md @@ -68,6 +68,7 @@ * [モッドタップ](ja/mod_tap.md) * [マクロ](ja/feature_macros.md) * [マウスキー](ja/feature_mouse_keys.md) + * [Repeat Key](ja/feature_repeat_key.md) * [Space Cadet Shift](ja/feature_space_cadet.md) * [US ANSI シフトキー](ja/keycodes_us_ansi_shifted.md) diff --git a/docs/keycodes.md b/docs/keycodes.md index cad050ccf776..e5b6246af794 100644 --- a/docs/keycodes.md +++ b/docs/keycodes.md @@ -803,6 +803,15 @@ See also: [Programmable Button](feature_programmable_button.md) |`QK_PROGRAMMABLE_BUTTON_31`|`PB_31`|Programmable button 31| |`QK_PROGRAMMABLE_BUTTON_32`|`PB_32`|Programmable button 32| +## Repeat Key :id=repeat-key + +See also: [Repeat Key](feature_repeat_key.md) + +|Keycode |Aliases |Description | +|-----------------------|---------|-------------------------------------| +|`QK_REPEAT_KEY` |`QK_REP` |Repeat the last pressed key | +|`QK_ALT_REPEAT_KEY` |`QK_AREP`|Perform alternate of the last key | + ## Space Cadet :id=space-cadet See also: [Space Cadet](feature_space_cadet.md) diff --git a/docs/zh-cn/_summary.md b/docs/zh-cn/_summary.md index b8c26ac27535..0fc92e33d3ae 100644 --- a/docs/zh-cn/_summary.md +++ b/docs/zh-cn/_summary.md @@ -73,6 +73,7 @@ * [Mod-Tap](zh-cn/mod_tap.md) * [宏](zh-cn/feature_macros.md) * [鼠标键](zh-cn/feature_mouse_keys.md) + * [Repeat Key](zh-cn/feature_repeat_key.md) * [Space Cadet Shift](zh-cn/feature_space_cadet.md) * [US ANSI上档键值](zh-cn/keycodes_us_ansi_shifted.md) diff --git a/quantum/action.c b/quantum/action.c index 59bfefc4954b..a45e70c55729 100644 --- a/quantum/action.c +++ b/quantum/action.c @@ -285,7 +285,7 @@ void process_record(keyrecord_t *record) { } void process_record_handler(keyrecord_t *record) { -#ifdef COMBO_ENABLE +#if defined(COMBO_ENABLE) || defined(REPEAT_KEY_ENABLE) action_t action; if (record->keycode) { action = action_for_keycode(record->keycode); @@ -1109,7 +1109,7 @@ bool is_tap_record(keyrecord_t *record) { return false; } -#ifdef COMBO_ENABLE +#if defined(COMBO_ENABLE) || defined(REPEAT_KEY_ENABLE) action_t action; if (record->keycode) { action = action_for_keycode(record->keycode); diff --git a/quantum/action.h b/quantum/action.h index 2a2c294c5a9e..d5b15c6f1732 100644 --- a/quantum/action.h +++ b/quantum/action.h @@ -50,7 +50,7 @@ typedef struct { #ifndef NO_ACTION_TAPPING tap_t tap; #endif -#ifdef COMBO_ENABLE +#if defined(COMBO_ENABLE) || defined(REPEAT_KEY_ENABLE) uint16_t keycode; #endif } keyrecord_t; diff --git a/quantum/keycodes.h b/quantum/keycodes.h index 34b13c29af52..bbf10da36d97 100644 --- a/quantum/keycodes.h +++ b/quantum/keycodes.h @@ -721,6 +721,8 @@ enum qk_keycode_defines { QK_AUTOCORRECT_TOGGLE = 0x7C76, QK_TRI_LAYER_LOWER = 0x7C77, QK_TRI_LAYER_UPPER = 0x7C78, + QK_REPEAT_KEY = 0x7C79, + QK_ALT_REPEAT_KEY = 0x7C7A, QK_KB_0 = 0x7E00, QK_KB_1 = 0x7E01, QK_KB_2 = 0x7E02, @@ -1362,6 +1364,8 @@ enum qk_keycode_defines { AC_TOGG = QK_AUTOCORRECT_TOGGLE, TL_LOWR = QK_TRI_LAYER_LOWER, TL_UPPR = QK_TRI_LAYER_UPPER, + QK_REP = QK_REPEAT_KEY, + QK_AREP = QK_ALT_REPEAT_KEY, }; // Range Helpers @@ -1413,6 +1417,6 @@ enum qk_keycode_defines { #define IS_MACRO_KEYCODE(code) ((code) >= QK_MACRO_0 && (code) <= QK_MACRO_31) #define IS_BACKLIGHT_KEYCODE(code) ((code) >= QK_BACKLIGHT_ON && (code) <= QK_BACKLIGHT_TOGGLE_BREATHING) #define IS_RGB_KEYCODE(code) ((code) >= RGB_TOG && (code) <= RGB_MODE_TWINKLE) -#define IS_QUANTUM_KEYCODE(code) ((code) >= QK_BOOTLOADER && (code) <= QK_TRI_LAYER_UPPER) +#define IS_QUANTUM_KEYCODE(code) ((code) >= QK_BOOTLOADER && (code) <= QK_ALT_REPEAT_KEY) #define IS_KB_KEYCODE(code) ((code) >= QK_KB_0 && (code) <= QK_KB_31) #define IS_USER_KEYCODE(code) ((code) >= QK_USER_0 && (code) <= QK_USER_31) diff --git a/quantum/process_keycode/process_repeat_key.c b/quantum/process_keycode/process_repeat_key.c new file mode 100644 index 000000000000..f819aa226e91 --- /dev/null +++ b/quantum/process_keycode/process_repeat_key.c @@ -0,0 +1,109 @@ +// Copyright 2022-2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "process_repeat_key.h" + +// Default implementation of remember_last_key_user(). +__attribute__((weak)) bool remember_last_key_user(uint16_t keycode, keyrecord_t* record, uint8_t* remembered_mods) { + return true; +} + +static bool remember_last_key(uint16_t keycode, keyrecord_t* record, uint8_t* remembered_mods) { + switch (keycode) { + // Ignore MO, TO, TG, TT, and TL layer switch keys. + case QK_MOMENTARY ... QK_MOMENTARY_MAX: + case QK_TO ... QK_TO_MAX: + case QK_TOGGLE_LAYER ... QK_TOGGLE_LAYER_MAX: + case QK_LAYER_TAP_TOGGLE ... QK_LAYER_TAP_TOGGLE_MAX: + // Ignore mod keys. + case KC_LCTL ... KC_RGUI: + case KC_HYPR: + case KC_MEH: +#ifndef NO_ACTION_ONESHOT // Ignore one-shot keys. + case QK_ONE_SHOT_LAYER ... QK_ONE_SHOT_LAYER_MAX: + case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX: +#endif // NO_ACTION_ONESHOT +#ifdef TRI_LAYER_ENABLE // Ignore Tri Layer keys. + case QK_TRI_LAYER_LOWER: + case QK_TRI_LAYER_UPPER: +#endif // TRI_LAYER_ENABLE + return false; + + // Ignore hold events on tap-hold keys. +#ifndef NO_ACTION_TAPPING + case QK_MOD_TAP ... QK_MOD_TAP_MAX: +# ifndef NO_ACTION_LAYER + case QK_LAYER_TAP ... QK_LAYER_TAP_MAX: +# endif // NO_ACTION_LAYER + if (record->tap.count == 0) { + return false; + } + break; +#endif // NO_ACTION_TAPPING + +#ifdef SWAP_HANDS_ENABLE + case QK_SWAP_HANDS ... QK_SWAP_HANDS_MAX: + if (IS_SWAP_HANDS_KEYCODE(keycode) || record->tap.count == 0) { + return false; + } + break; +#endif // SWAP_HANDS_ENABLE + + case QK_REPEAT_KEY: +#ifndef NO_ALT_REPEAT_KEY + case QK_ALT_REPEAT_KEY: +#endif // NO_ALT_REPEAT_KEY + return false; + } + + return remember_last_key_user(keycode, record, remembered_mods); +} + +bool process_last_key(uint16_t keycode, keyrecord_t* record) { + if (get_repeat_key_count()) { + return true; + } + + if (record->event.pressed) { + uint8_t remembered_mods = get_mods() | get_weak_mods(); +#ifndef NO_ACTION_ONESHOT + remembered_mods |= get_oneshot_mods(); +#endif // NO_ACTION_ONESHOT + + if (remember_last_key(keycode, record, &remembered_mods)) { + set_last_record(keycode, record); + set_last_mods(remembered_mods); + } + } + + return true; +} + +bool process_repeat_key(uint16_t keycode, keyrecord_t* record) { + if (get_repeat_key_count()) { + return true; + } + + if (keycode == QK_REPEAT_KEY) { + repeat_key_invoke(&record->event); + return false; +#ifndef NO_ALT_REPEAT_KEY + } else if (keycode == QK_ALT_REPEAT_KEY) { + alt_repeat_key_invoke(&record->event); + return false; +#endif // NO_ALT_REPEAT_KEY + } + + return true; +} diff --git a/quantum/process_keycode/process_repeat_key.h b/quantum/process_keycode/process_repeat_key.h new file mode 100644 index 000000000000..eddc50f254c9 --- /dev/null +++ b/quantum/process_keycode/process_repeat_key.h @@ -0,0 +1,62 @@ +// Copyright 2022-2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "quantum.h" + +/** + * @brief Process handler for remembering the last key. + * + * @param keycode Keycode registered by matrix press, per keymap + * @param record keyrecord_t structure + * @return true Continue processing keycodes, and send to host + * @return false Stop processing keycodes, and don't send to host + */ +bool process_last_key(uint16_t keycode, keyrecord_t* record); + +/** + * @brief Optional callback defining which keys are remembered. + * + * @param keycode Keycode that was just pressed + * @param record keyrecord_t structure + * @param remembered_mods Mods that will be remembered with this key + * @return true Key is remembered + * @return false Key is ignored + * + * Modifier and layer switch keys are always ignored. For all other keys, this + * callback is called on every key press. Returning true means that the key is + * remembered, false means it is ignored. By default, all non-modifier, + * non-layer switch keys are remembered. + * + * The `remembered_mods` arg represents the mods that will be remembered with + * this key. It can be modified to forget certain mods, for instance to forget + * capitalization when repeating shifted letters: + * + * // Forget Shift on letter keys. + * if (KC_A <= keycode && keycode <= KC_Z && (*remembered_mods & ~MOD_MASK_SHIFT) == 0) { + * *remembered_mods = 0; + * } + */ +bool remember_last_key_user(uint16_t keycode, keyrecord_t* record, uint8_t* remembered_mods); + +/** + * @brief Process handler for Repeat Key feature. + * + * @param keycode Keycode registered by matrix press, per keymap + * @param record keyrecord_t structure + * @return true Continue processing keycodes, and send to host + * @return false Stop processing keycodes, and don't send to host + */ +bool process_repeat_key(uint16_t keycode, keyrecord_t* record); diff --git a/quantum/quantum.c b/quantum/quantum.c index fdc24fa2d0b9..091cf298f73f 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -176,7 +176,7 @@ void soft_reset_keyboard(void) { /* Convert record into usable keycode via the contained event. */ uint16_t get_record_keycode(keyrecord_t *record, bool update_layer_cache) { -#ifdef COMBO_ENABLE +#if defined(COMBO_ENABLE) || defined(REPEAT_KEY_ENABLE) if (record->keycode) { return record->keycode; } @@ -273,6 +273,9 @@ bool process_record_quantum(keyrecord_t *record) { // Must run asap to ensure all keypresses are recorded. process_dynamic_macro(keycode, record) && #endif +#ifdef REPEAT_KEY_ENABLE + process_last_key(keycode, record) && process_repeat_key(keycode, record) && +#endif #if defined(AUDIO_ENABLE) && defined(AUDIO_CLICKY) process_clicky(keycode, record) && #endif diff --git a/quantum/quantum.h b/quantum/quantum.h index fec92a5244a5..31a1a63a7acb 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -251,6 +251,11 @@ extern layer_state_t layer_state; # include "process_tri_layer.h" #endif +#ifdef REPEAT_KEY_ENABLE +# include "repeat_key.h" +# include "process_repeat_key.h" +#endif + void set_single_persistent_default_layer(uint8_t default_layer); #define IS_LAYER_ON(layer) layer_state_is(layer) diff --git a/quantum/repeat_key.c b/quantum/repeat_key.c new file mode 100644 index 000000000000..0689c6d45476 --- /dev/null +++ b/quantum/repeat_key.c @@ -0,0 +1,282 @@ +// Copyright 2022-2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "repeat_key.h" + +// Variables saving the state of the last key press. +static keyrecord_t last_record = {0}; +static uint8_t last_mods = 0; +// Signed count of the number of times the last key has been repeated or +// alternate repeated: it is 0 when a key is pressed normally, positive when +// repeated, and negative when alternate repeated. +static int8_t last_repeat_count = 0; +// The repeat_count, but set to 0 outside of repeat_key_invoke() so that it is +// nonzero only while a repeated key is being processed. +static int8_t processing_repeat_count = 0; + +uint16_t get_last_keycode(void) { + return last_record.keycode; +} + +uint8_t get_last_mods(void) { + return last_mods; +} + +void set_last_keycode(uint16_t keycode) { + set_last_record(keycode, &(keyrecord_t){ +#ifndef NO_ACTION_TAPPING + .tap.interrupted = false, + .tap.count = 1, +#endif + }); +} + +void set_last_mods(uint8_t mods) { + last_mods = mods; +} + +void set_last_record(uint16_t keycode, keyrecord_t* record) { + last_record = *record; + last_record.keycode = keycode; + last_repeat_count = 0; +} + +/** @brief Updates `last_repeat_count` in direction `dir`. */ +static void update_last_repeat_count(int8_t dir) { + if (dir * last_repeat_count < 0) { + last_repeat_count = dir; + } else if (dir * last_repeat_count < 127) { + last_repeat_count += dir; + } +} + +int8_t get_repeat_key_count(void) { + return processing_repeat_count; +} + +void repeat_key_invoke(const keyevent_t* event) { + // It is possible (e.g. in rolled presses) that the last key changes while + // the Repeat Key is pressed. To prevent stuck keys, it is important to + // remember separately what key record was processed on press so that the + // the corresponding record is generated on release. + static keyrecord_t registered_record = {0}; + static int8_t registered_repeat_count = 0; + // Since this function calls process_record(), it may recursively call + // itself. We return early if `processing_repeat_count` is nonzero to + // prevent infinite recursion. + if (processing_repeat_count || !last_record.keycode) { + return; + } + + if (event->pressed) { + update_last_repeat_count(1); + // On press, apply the last mods state, stacking on top of current mods. + register_weak_mods(last_mods); + registered_record = last_record; + registered_repeat_count = last_repeat_count; + } + + // Generate a keyrecord and plumb it into the event pipeline. + registered_record.event = *event; + processing_repeat_count = registered_repeat_count; + process_record(®istered_record); + processing_repeat_count = 0; + + // On release, restore the mods state. + if (!event->pressed) { + unregister_weak_mods(last_mods); + } +} + +#ifndef NO_ALT_REPEAT_KEY +/** + * @brief Find alternate keycode from a table of opposing keycode pairs. + * @param table Array of pairs of basic keycodes, declared as PROGMEM. + * @param table_size_bytes The size of the table in bytes. + * @param target The basic keycode to find. + * @return The alternate basic keycode, or KC_NO if none was found. + * + * @note The table keycodes and target must be basic keycodes. + * + * This helper is used several times below to define alternate keys. Given a + * table of pairs of basic keycodes, the function finds the pair containing + * `target` and returns the other keycode in the pair. + */ +static uint8_t find_alt_keycode(const uint8_t (*table)[2], uint8_t table_size_bytes, uint8_t target) { + const uint8_t* keycodes = (const uint8_t*)table; + for (uint8_t i = 0; i < table_size_bytes; ++i) { + if (target == pgm_read_byte(keycodes + i)) { + // Xor (i ^ 1) the index to get the other element in the pair. + return pgm_read_byte(keycodes + (i ^ 1)); + } + } + return KC_NO; +} + +uint16_t get_alt_repeat_key_keycode(void) { + uint16_t keycode = last_record.keycode; + uint8_t mods = last_mods; + + // Call the user callback first to give it a chance to override the default + // alternate key definitions that follow. + uint16_t alt_keycode = get_alt_repeat_key_keycode_user(keycode, mods); + + if (alt_keycode != KC_TRANSPARENT) { + return alt_keycode; + } + + // Convert 8-bit mods to the 5-bit format used in keycodes. This is lossy: + // if left and right handed mods were mixed, they all become right handed. + mods = ((mods & 0xf0) ? /* set right hand bit */ 0x10 : 0) + // Combine right and left hand mods. + | (((mods >> 4) | mods) & 0xf); + + switch (keycode) { + case QK_MODS ... QK_MODS_MAX: // Unpack modifier + basic key. + mods |= QK_MODS_GET_MODS(keycode); + keycode = QK_MODS_GET_BASIC_KEYCODE(keycode); + break; + +# ifndef NO_ACTION_TAPPING + case QK_MOD_TAP ... QK_MOD_TAP_MAX: + keycode = QK_MOD_TAP_GET_TAP_KEYCODE(keycode); + break; +# ifndef NO_ACTION_LAYER + case QK_LAYER_TAP ... QK_LAYER_TAP_MAX: + keycode = QK_LAYER_TAP_GET_TAP_KEYCODE(keycode); + break; +# endif // NO_ACTION_LAYER +# endif // NO_ACTION_TAPPING + +# ifdef SWAP_HANDS_ENABLE + case QK_SWAP_HANDS ... QK_SWAP_HANDS_MAX: + if (IS_SWAP_HANDS_KEYCODE(keycode)) { + return KC_NO; + } + keycode = QK_SWAP_HANDS_GET_TAP_KEYCODE(keycode); + break; +# endif // SWAP_HANDS_ENABLE + } + + if (IS_QK_BASIC(keycode)) { + if ((mods & (MOD_LCTL | MOD_LALT | MOD_LGUI))) { + // The last key was pressed with a modifier other than Shift. + // The following maps + // mod + F <-> mod + B + // and a few others, supporting several core hotkeys used in + // Emacs, Vim, less, and other programs. + // clang-format off + static const uint8_t pairs[][2] PROGMEM = { + {KC_F , KC_B }, // Forward / Backward. + {KC_D , KC_U }, // Down / Up. + {KC_N , KC_P }, // Next / Previous. + {KC_A , KC_E }, // Home / End. + {KC_O , KC_I }, // Older / Newer in Vim jump list. + }; + // clang-format on + alt_keycode = find_alt_keycode(pairs, sizeof(pairs), keycode); + } else { + // The last key was pressed with no mods or only Shift. The + // following map a few more Vim hotkeys. + // clang-format off + static const uint8_t pairs[][2] PROGMEM = { + {KC_J , KC_K }, // Down / Up. + {KC_H , KC_L }, // Left / Right. + // These two lines map W and E to B, and B to W. + {KC_W , KC_B }, // Forward / Backward by word. + {KC_E , KC_B }, // Forward / Backward by word. + }; + // clang-format on + alt_keycode = find_alt_keycode(pairs, sizeof(pairs), keycode); + } + + if (!alt_keycode) { + // The following key pairs are considered with any mods. + // clang-format off + static const uint8_t pairs[][2] PROGMEM = { + {KC_LEFT, KC_RGHT}, // Left / Right Arrow. + {KC_UP , KC_DOWN}, // Up / Down Arrow. + {KC_HOME, KC_END }, // Home / End. + {KC_PGUP, KC_PGDN}, // Page Up / Page Down. + {KC_BSPC, KC_DEL }, // Backspace / Delete. + {KC_LBRC, KC_RBRC}, // Brackets [ ] and { }. +#ifdef EXTRAKEY_ENABLE + {KC_WBAK, KC_WFWD}, // Browser Back / Forward. + {KC_MNXT, KC_MPRV}, // Next / Previous Media Track. + {KC_MFFD, KC_MRWD}, // Fast Forward / Rewind Media. + {KC_VOLU, KC_VOLD}, // Volume Up / Down. + {KC_BRIU, KC_BRID}, // Brightness Up / Down. +#endif // EXTRAKEY_ENABLE +#ifdef MOUSEKEY_ENABLE + {KC_MS_L, KC_MS_R}, // Mouse Cursor Left / Right. + {KC_MS_U, KC_MS_D}, // Mouse Cursor Up / Down. + {KC_WH_L, KC_WH_R}, // Mouse Wheel Left / Right. + {KC_WH_U, KC_WH_D}, // Mouse Wheel Up / Down. +#endif // MOUSEKEY_ENABLE + }; + // clang-format on + alt_keycode = find_alt_keycode(pairs, sizeof(pairs), keycode); + } + + if (alt_keycode) { + // Combine basic keycode with mods. + return (mods << 8) | alt_keycode; + } + } + + return KC_NO; // No alternate key found. +} + +void alt_repeat_key_invoke(const keyevent_t* event) { + static keyrecord_t registered_record = {0}; + static int8_t registered_repeat_count = 0; + // Since this function calls process_record(), it may recursively call + // itself. We return early if `processing_repeat_count` is nonzero to + // prevent infinite recursion. + if (processing_repeat_count) { + return; + } + + if (event->pressed) { + registered_record = (keyrecord_t){ +# ifndef NO_ACTION_TAPPING + .tap.interrupted = false, + .tap.count = 0, +# endif + .keycode = get_alt_repeat_key_keycode(), + }; + } + + // Early return if there is no alternate key defined. + if (!registered_record.keycode) { + return; + } + + if (event->pressed) { + update_last_repeat_count(-1); + registered_repeat_count = last_repeat_count; + } + + // Generate a keyrecord and plumb it into the event pipeline. + registered_record.event = *event; + processing_repeat_count = registered_repeat_count; + process_record(®istered_record); + processing_repeat_count = 0; +} + +// Default implementation of get_alt_repeat_key_keycode_user(). +__attribute__((weak)) uint16_t get_alt_repeat_key_keycode_user(uint16_t keycode, uint8_t mods) { + return KC_TRANSPARENT; +} +#endif // NO_ALT_REPEAT_KEY diff --git a/quantum/repeat_key.h b/quantum/repeat_key.h new file mode 100644 index 000000000000..06e83645295c --- /dev/null +++ b/quantum/repeat_key.h @@ -0,0 +1,80 @@ +// Copyright 2022-2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "quantum.h" + +uint16_t get_last_keycode(void); /**< Keycode of the last key. */ +uint8_t get_last_mods(void); /**< Mods active with the last key. */ +void set_last_keycode(uint16_t keycode); /**< Sets the last key. */ +void set_last_mods(uint8_t mods); /**< Sets the last mods. */ + +/** @brief Gets the record for the last key. */ +keyrecord_t* get_last_record(void); + +/** @brief Sets keycode and record info for the last key. */ +void set_last_record(uint16_t keycode, keyrecord_t* record); + +/** + * @brief Signed count of times the key has been repeated or alternate repeated. + * + * @note The count is nonzero only while a repeated or alternate-repeated key is + * being processed. + * + * When a key is pressed normally, the count is 0. When the Repeat Key is used + * to repeat a key, the count is 1 on the first repeat, 2 on the second repeat, + * and continuing up to 127. + * + * Negative counts are used similarly for alternate repeating. When the + * Alternate Repeat Key is used, the count is -1 on the first alternate repeat, + * -2 on the second, continuing down to -127. + */ +int8_t get_repeat_key_count(void); + +/** + * @brief Calls `process_record()` on a generated record repeating the last key. + * @param event Event information in the generated record. + */ +void repeat_key_invoke(const keyevent_t* event); + +#ifndef NO_ALT_REPEAT_KEY + +/** + * @brief Keycode to be used for alternate repeating. + * + * Alternate Repeat performs this keycode based on the last eligible pressed key + * and mods, get_last_keycode() and get_last_mods(). For example, when the last + * key was KC_UP, this function returns KC_DOWN. The function returns KC_NO if + * the last key doesn't have a defined alternate. + */ +uint16_t get_alt_repeat_key_keycode(void); + +/** + * @brief Calls `process_record()` to alternate repeat the last key. + * @param event Event information in the generated record. + */ +void alt_repeat_key_invoke(const keyevent_t* event); + +/** + * @brief Optional user callback to define additional alternate keys. + * + * When `get_alt_repeat_key_keycode()` is called, it first calls this callback. + * It should return a keycode representing the "alternate" of the given keycode + * and mods. Returning KC_NO defers to the default definitions in + * `get_alt_repeat_key_keycode()`. + */ +uint16_t get_alt_repeat_key_keycode_user(uint16_t keycode, uint8_t mods); + +#endif // NO_ALT_REPEAT_KEY diff --git a/tests/repeat_key/alt_repeat_key/config.h b/tests/repeat_key/alt_repeat_key/config.h new file mode 100644 index 000000000000..d0c4ddadbd3b --- /dev/null +++ b/tests/repeat_key/alt_repeat_key/config.h @@ -0,0 +1,18 @@ +// Copyright 2023 Google LLC +// +// 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 . + +#pragma once + +#include "test_common.h" diff --git a/tests/repeat_key/alt_repeat_key/test.mk b/tests/repeat_key/alt_repeat_key/test.mk new file mode 100644 index 000000000000..080871c81645 --- /dev/null +++ b/tests/repeat_key/alt_repeat_key/test.mk @@ -0,0 +1,18 @@ +# Copyright 2023 Google LLC +# +# 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 . + +REPEAT_KEY_ENABLE = yes + +EXTRAKEY_ENABLE = yes diff --git a/tests/repeat_key/alt_repeat_key/test_alt_repeat_key.cpp b/tests/repeat_key/alt_repeat_key/test_alt_repeat_key.cpp new file mode 100644 index 000000000000..ae525acb4554 --- /dev/null +++ b/tests/repeat_key/alt_repeat_key/test_alt_repeat_key.cpp @@ -0,0 +1,523 @@ +// Copyright 2023 Google LLC +// +// 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 . + +#include + +#include "keyboard_report_util.hpp" +#include "keycode.h" +#include "test_common.hpp" +#include "test_fixture.hpp" +#include "test_keymap_key.hpp" + +using ::testing::AnyNumber; +using ::testing::InSequence; + +namespace { + +bool process_record_user_default(uint16_t keycode, keyrecord_t* record) { + return true; +} + +bool remember_last_key_user_default(uint16_t keycode, keyrecord_t* record, uint8_t* remembered_mods) { + return true; +} + +uint16_t get_alt_repeat_key_keycode_user_default(uint16_t keycode, uint8_t mods) { + return KC_TRNS; +} + +// Indirections so that process_record_user() can be replaced with other +// functions in the test cases below. +std::function process_record_user_fun = process_record_user_default; +std::function remember_last_key_user_fun = remember_last_key_user_default; +std::function get_alt_repeat_key_keycode_user_fun = get_alt_repeat_key_keycode_user_default; + +extern "C" bool process_record_user(uint16_t keycode, keyrecord_t* record) { + return process_record_user_fun(keycode, record); +} + +extern "C" bool remember_last_key_user(uint16_t keycode, keyrecord_t* record, uint8_t* remembered_mods) { + return remember_last_key_user_fun(keycode, record, remembered_mods); +} + +extern "C" uint16_t get_alt_repeat_key_keycode_user(uint16_t keycode, uint8_t mods) { + return get_alt_repeat_key_keycode_user_fun(keycode, mods); +} + +class AltRepeatKey : public TestFixture { + public: + bool process_record_user_was_called_; + + void SetUp() override { + process_record_user_fun = process_record_user_default; + remember_last_key_user_fun = remember_last_key_user_default; + get_alt_repeat_key_keycode_user_fun = get_alt_repeat_key_keycode_user_default; + } + + void ExpectProcessRecordUserCalledWith(bool expected_press, uint16_t expected_keycode, int8_t expected_repeat_key_count) { + process_record_user_was_called_ = false; + process_record_user_fun = [=](uint16_t keycode, keyrecord_t* record) { + EXPECT_EQ(record->event.pressed, expected_press); + EXPECT_KEYCODE_EQ(keycode, expected_keycode); + EXPECT_EQ(get_repeat_key_count(), expected_repeat_key_count); + // Tests below use this to verify process_record_user() was called. + process_record_user_was_called_ = true; + return true; + }; + } + + // Expects that the characters of `s` are sent. + // NOTE: This implementation is limited to chars a-z, A-Z. + void ExpectString(TestDriver& driver, const std::string& s) { + InSequence seq; + for (int c : s) { + switch (c) { + case 'a' ... 'z': { // Lowercase letter. + uint16_t keycode = c - ('a' - KC_A); + EXPECT_REPORT(driver, (keycode)); + } break; + + case 'A' ... 'Z': { // Capital letter = KC_LSFT + letter key. + uint16_t keycode = c - ('A' - KC_A); + EXPECT_REPORT(driver, (KC_LSFT, keycode)); + } break; + } + } + } +}; + +TEST_F(AltRepeatKey, AlternateBasic) { + TestDriver driver; + KeymapKey key_bspc(0, 0, 0, KC_BSPC); + KeymapKey key_pgdn(0, 1, 0, KC_PGDN); + KeymapKey key_pgup(0, 2, 0, KC_PGUP); + KeymapKey key_repeat(0, 4, 0, QK_REP); + KeymapKey key_alt_repeat(0, 5, 0, QK_AREP); + set_keymap({key_bspc, key_pgdn, key_pgup, key_repeat, key_alt_repeat}); + + // Allow any number of empty reports. + EXPECT_EMPTY_REPORT(driver).Times(AnyNumber()); + { + InSequence seq; + EXPECT_REPORT(driver, (KC_BSPC)); + EXPECT_REPORT(driver, (KC_DEL)); + EXPECT_REPORT(driver, (KC_DEL)); + EXPECT_REPORT(driver, (KC_BSPC)); + EXPECT_REPORT(driver, (KC_DEL)); + EXPECT_REPORT(driver, (KC_PGDN)); + EXPECT_REPORT(driver, (KC_PGUP)); + EXPECT_REPORT(driver, (KC_PGUP)); + EXPECT_REPORT(driver, (KC_PGDN)); + } + + tap_key(key_bspc); + + for (int n = 1; n <= 2; ++n) { // Tap the Alternate Repeat Key twice. + ExpectProcessRecordUserCalledWith(true, KC_DEL, -n); + key_alt_repeat.press(); // Press the Alternate Repeat Key. + run_one_scan_loop(); + EXPECT_TRUE(process_record_user_was_called_); + + // Expect the corresponding release event. + ExpectProcessRecordUserCalledWith(false, KC_DEL, -n); + key_alt_repeat.release(); // Release the Repeat Key. + run_one_scan_loop(); + EXPECT_TRUE(process_record_user_was_called_); + } + + process_record_user_fun = process_record_user_default; + tap_keys(key_repeat, key_alt_repeat); + tap_keys(key_pgdn, key_alt_repeat); + tap_keys(key_pgup, key_alt_repeat); + + testing::Mock::VerifyAndClearExpectations(&driver); +} + +struct TestParamsAlternateKeyCodes { + uint16_t keycode; + uint8_t mods; + uint16_t expected_alt_keycode; +}; + +// Tests `get_alt_repeat_key_keycode()` for various keycodes. +TEST_F(AltRepeatKey, GetAltRepeatKeyKeycode) { + for (const auto& params : std::vector({ + // clang-format off + // Each line tests one call to `get_alt_repeat_key_keycode()`: + // {keycode, mods, expected_alt_keycode}. + // Arrows. + {KC_LEFT, 0, KC_RGHT}, + {KC_RGHT, 0, KC_LEFT}, + {KC_LEFT, MOD_BIT(KC_LSFT), LSFT(KC_RGHT)}, + {KC_LEFT, MOD_BIT(KC_RSFT), RSFT(KC_RGHT)}, + {KC_LEFT, MOD_BIT(KC_LCTL) | MOD_BIT(KC_LSFT), C(S(KC_RGHT))}, + {KC_LEFT, MOD_BIT(KC_LGUI), LGUI(KC_RGHT)}, + {C(KC_LEFT), MOD_BIT(KC_LSFT), C(S(KC_RGHT))}, + {KC_UP, 0, KC_DOWN}, + // Navigation keys. + {KC_PGUP, 0, KC_PGDN}, + {KC_HOME, 0, KC_END }, + // Media keys. + {KC_WBAK, 0, KC_WFWD}, + {KC_MNXT, 0, KC_MPRV}, + {KC_MRWD, 0, KC_MFFD}, + {KC_VOLU, 0, KC_VOLD}, + {KC_BRIU, 0, KC_BRID}, + // Emacs navigation. + {KC_N, MOD_BIT(KC_LCTL), C(KC_P)}, + {KC_B, MOD_BIT(KC_LCTL), LCTL(KC_F)}, + {KC_B, MOD_BIT(KC_RCTL), RCTL(KC_F)}, + {KC_B, MOD_BIT(KC_LALT), LALT(KC_F)}, + {KC_F, MOD_BIT(KC_LCTL), C(KC_B)}, + {KC_A, MOD_BIT(KC_LCTL), C(KC_E)}, + {KC_D, MOD_BIT(KC_LCTL), C(KC_U)}, + // Vim navigation. + {KC_J, 0, KC_K}, + {KC_K, 0, KC_J}, + {KC_H, 0, KC_L}, + {KC_B, 0, KC_W}, + {KC_W, 0, KC_B}, + {KC_E, 0, KC_B}, + {KC_B, MOD_BIT(KC_LSFT), S(KC_W)}, + {KC_W, MOD_BIT(KC_LSFT), S(KC_B)}, + {KC_E, MOD_BIT(KC_LSFT), S(KC_B)}, + {KC_O, MOD_BIT(KC_LCTL), C(KC_I)}, + {KC_I, MOD_BIT(KC_LCTL), C(KC_O)}, + // Other. + {KC_DEL, 0, KC_BSPC}, + {KC_LBRC, 0, KC_RBRC}, + {KC_LCBR, 0, KC_RCBR}, + // Some keys where the last key is a tap-hold key. + {LSFT_T(KC_F), MOD_BIT(KC_RCTL), RCTL(KC_B)}, + {LT(1, KC_A), MOD_BIT(KC_RGUI), RGUI(KC_E)}, + {RALT_T(KC_J), 0, KC_K}, + // Some keys where no alternate is defined. + {KC_A, 0, KC_NO}, + {KC_F1, 0, KC_NO}, + {QK_LEAD, 0, KC_NO}, + {MO(1), 0, KC_NO}, + // clang-format on + })) { + SCOPED_TRACE(std::string("Input keycode: ") + get_keycode_identifier_or_default(params.keycode)); + set_last_keycode(params.keycode); + set_last_mods(params.mods); + + const uint16_t actual = get_alt_repeat_key_keycode(); + + EXPECT_KEYCODE_EQ(get_alt_repeat_key_keycode(), params.expected_alt_keycode); + } +} + +// Test adding to and overriding the above through the +// `get_alt_repeat_key_keycode_user()` callback. +TEST_F(AltRepeatKey, GetAltRepeatKeyKeycodeUser) { + get_alt_repeat_key_keycode_user_fun = [](uint16_t keycode, uint8_t mods) -> uint16_t { + bool shifted = (mods & MOD_MASK_SHIFT); + switch (keycode) { + case KC_LEFT: + return KC_ENT; + case MO(1): + return TG(1); + case KC_TAB: // Tab <-> Shift + Tab example. + if (shifted) { + return KC_TAB; + } else { + return S(KC_TAB); + } + } + + // Ctrl + Y <-> Ctrl + Z example. + if ((mods & MOD_MASK_CTRL)) { + switch (keycode) { + case KC_Y: + return C(KC_Z); + case KC_Z: + return C(KC_Y); + } + } + + return KC_NO; + }; + + set_last_keycode(KC_LEFT); + EXPECT_KEYCODE_EQ(get_alt_repeat_key_keycode(), KC_ENT); + + set_last_keycode(MO(1)); + EXPECT_KEYCODE_EQ(get_alt_repeat_key_keycode(), TG(1)); + + set_last_keycode(KC_TAB); + EXPECT_KEYCODE_EQ(get_alt_repeat_key_keycode(), S(KC_TAB)); + + set_last_keycode(KC_TAB); + set_last_mods(MOD_BIT(KC_LSFT)); + EXPECT_KEYCODE_EQ(get_alt_repeat_key_keycode(), KC_TAB); + + set_last_keycode(KC_Z); + set_last_mods(MOD_BIT(KC_LCTL)); + EXPECT_KEYCODE_EQ(get_alt_repeat_key_keycode(), C(KC_Y)); + + set_last_keycode(KC_Y); + set_last_mods(MOD_BIT(KC_LCTL)); + EXPECT_KEYCODE_EQ(get_alt_repeat_key_keycode(), C(KC_Z)); +} + +// Tests rolling from a key to Alternate Repeat. +TEST_F(AltRepeatKey, RollingToAltRepeat) { + TestDriver driver; + KeymapKey key_left(0, 0, 0, KC_LEFT); + KeymapKey key_alt_repeat(0, 1, 0, QK_AREP); + set_keymap({key_left, key_alt_repeat}); + + { + InSequence seq; + EXPECT_REPORT(driver, (KC_LEFT)); + EXPECT_REPORT(driver, (KC_LEFT, KC_RGHT)); + EXPECT_REPORT(driver, (KC_RGHT)); + EXPECT_EMPTY_REPORT(driver); + EXPECT_REPORT(driver, (KC_RGHT)); + EXPECT_EMPTY_REPORT(driver); + } + + // Perform a rolled press from Left to Alternate Repeat. + + ExpectProcessRecordUserCalledWith(true, KC_LEFT, 0); + key_left.press(); + run_one_scan_loop(); + EXPECT_TRUE(process_record_user_was_called_); + + ExpectProcessRecordUserCalledWith(true, KC_RGHT, -1); + key_alt_repeat.press(); // Press the Alternate Repeat Key. + run_one_scan_loop(); + EXPECT_TRUE(process_record_user_was_called_); + + ExpectProcessRecordUserCalledWith(false, KC_LEFT, 0); + key_left.release(); + run_one_scan_loop(); + EXPECT_TRUE(process_record_user_was_called_); + + ExpectProcessRecordUserCalledWith(false, KC_RGHT, -1); + key_alt_repeat.release(); // Release the Alternate Repeat Key. + run_one_scan_loop(); + EXPECT_TRUE(process_record_user_was_called_); + + process_record_user_fun = process_record_user_default; + tap_key(key_alt_repeat); + + testing::Mock::VerifyAndClearExpectations(&driver); +} + +// Tests rolling from Alternate Repeat to another key. +TEST_F(AltRepeatKey, RollingFromAltRepeat) { + TestDriver driver; + KeymapKey key_left(0, 0, 0, KC_LEFT); + KeymapKey key_up(0, 1, 0, KC_UP); + KeymapKey key_alt_repeat(0, 2, 0, QK_AREP); + set_keymap({key_left, key_up, key_alt_repeat}); + + { + InSequence seq; + EXPECT_REPORT(driver, (KC_LEFT)); + EXPECT_EMPTY_REPORT(driver); + EXPECT_REPORT(driver, (KC_RGHT)); + EXPECT_REPORT(driver, (KC_RGHT, KC_UP)); + EXPECT_REPORT(driver, (KC_UP)); + EXPECT_EMPTY_REPORT(driver); + EXPECT_REPORT(driver, (KC_DOWN)); + EXPECT_EMPTY_REPORT(driver); + } + + tap_key(key_left); + + // Perform a rolled press from Alternate Repeat to Up. + + ExpectProcessRecordUserCalledWith(true, KC_RGHT, -1); + key_alt_repeat.press(); // Press the Alternate Repeat Key. + run_one_scan_loop(); + EXPECT_TRUE(process_record_user_was_called_); + + ExpectProcessRecordUserCalledWith(true, KC_UP, 0); + key_up.press(); + run_one_scan_loop(); + EXPECT_TRUE(process_record_user_was_called_); + + EXPECT_KEYCODE_EQ(get_last_keycode(), KC_UP); + + ExpectProcessRecordUserCalledWith(false, KC_RGHT, -1); + key_alt_repeat.release(); // Release the Alternate Repeat Key. + run_one_scan_loop(); + EXPECT_TRUE(process_record_user_was_called_); + + ExpectProcessRecordUserCalledWith(false, KC_UP, 0); + key_up.release(); + run_one_scan_loop(); + EXPECT_TRUE(process_record_user_was_called_); + + process_record_user_fun = process_record_user_default; + tap_key(key_alt_repeat); + + testing::Mock::VerifyAndClearExpectations(&driver); +} + +// Tests using the Alternate Repeat Key on a macro that doesn't have an +// alternate keycode defined. +TEST_F(AltRepeatKey, AlternateUnsupportedMacro) { + TestDriver driver; + KeymapKey key_foo(0, 0, 0, QK_USER_0); + KeymapKey key_alt_repeat(0, 1, 0, QK_AREP); + set_keymap({key_foo, key_alt_repeat}); + + process_record_user_fun = [=](uint16_t keycode, keyrecord_t* record) { + process_record_user_was_called_ = true; + switch (keycode) { + case QK_USER_0: + if (record->event.pressed) { + SEND_STRING("foo"); + } + break; + } + return true; + }; + + // Allow any number of empty reports. + EXPECT_EMPTY_REPORT(driver).Times(AnyNumber()); + ExpectString(driver, "foofoo"); + + process_record_user_was_called_ = false; + tap_key(key_foo); + + EXPECT_TRUE(process_record_user_was_called_); + EXPECT_KEYCODE_EQ(get_last_keycode(), QK_USER_0); + EXPECT_KEYCODE_EQ(get_alt_repeat_key_keycode(), KC_NO); + + process_record_user_was_called_ = false; + key_alt_repeat.press(); // Press Alternate Repeat. + run_one_scan_loop(); + + EXPECT_FALSE(process_record_user_was_called_); + + process_record_user_was_called_ = false; + key_alt_repeat.release(); // Release Alternate Repeat. + run_one_scan_loop(); + + EXPECT_FALSE(process_record_user_was_called_); + + process_record_user_was_called_ = false; + tap_key(key_foo); + + EXPECT_TRUE(process_record_user_was_called_); + + testing::Mock::VerifyAndClearExpectations(&driver); +} + +// Tests a macro with custom alternate behavior. +TEST_F(AltRepeatKey, MacroCustomAlternate) { + TestDriver driver; + KeymapKey key_foo(0, 0, 0, QK_USER_0); + KeymapKey key_alt_repeat(0, 1, 0, QK_AREP); + set_keymap({key_foo, key_alt_repeat}); + + get_alt_repeat_key_keycode_user_fun = [](uint16_t keycode, uint8_t mods) -> uint16_t { + switch (keycode) { + case QK_USER_0: + return QK_USER_0; // QK_USER_0 handles its own alternate. + default: + return KC_NO; // No key by default. + } + }; + process_record_user_fun = [=](uint16_t keycode, keyrecord_t* record) { + process_record_user_was_called_ = true; + switch (keycode) { + case QK_USER_0: + if (record->event.pressed) { + if (get_repeat_key_count() >= 0) { + SEND_STRING("foo"); + } else { // Key is being alternate repeated. + SEND_STRING("bar"); + } + } + break; + } + return true; + }; + + // Allow any number of empty reports. + EXPECT_EMPTY_REPORT(driver).Times(AnyNumber()); + ExpectString(driver, "foobarbar"); + + tap_keys(key_foo, key_alt_repeat, key_alt_repeat); + + testing::Mock::VerifyAndClearExpectations(&driver); +} + +// Tests the Additional "Alternate" keys example from the documentation page. +TEST_F(AltRepeatKey, AdditionalAlternateKeysExample) { + TestDriver driver; + KeymapKey key_a(0, 0, 0, KC_A); + KeymapKey key_w(0, 1, 0, KC_W); + KeymapKey key_altrep2(0, 2, 0, QK_USER_0); + KeymapKey key_altrep3(0, 3, 0, QK_USER_1); + set_keymap({key_a, key_w, key_altrep2, key_altrep3}); + + remember_last_key_user_fun = [](uint16_t keycode, keyrecord_t* record, uint8_t* remembered_mods) { + switch (keycode) { + case QK_USER_0: + case QK_USER_1: + return false; // Ignore ALTREP keys. + } + return true; // Other keys can be repeated. + }; + process_record_user_fun = [=](uint16_t keycode, keyrecord_t* record) { + switch (keycode) { + case QK_USER_0: + if (record->event.pressed) { + const uint16_t last_key = get_last_keycode(); + switch (last_key) { + case KC_A: + SEND_STRING(/*a*/ "tion"); + break; + case KC_W: + SEND_STRING(/*w*/ "hich"); + break; + } + } + return false; + case QK_USER_1: + if (record->event.pressed) { + const uint16_t last_key = get_last_keycode(); + switch (last_key) { + case KC_A: + SEND_STRING(/*a*/ "bout"); + break; + case KC_W: + SEND_STRING(/*w*/ "ould"); + break; + } + } + return false; + } + return true; + }; + + // Allow any number of empty reports. + EXPECT_EMPTY_REPORT(driver).Times(AnyNumber()); + ExpectString(driver, "ationwhichaboutwould"); + + tap_keys(key_a, key_altrep2, key_w, key_altrep2); + tap_keys(key_a, key_altrep3, key_w, key_altrep3); + + testing::Mock::VerifyAndClearExpectations(&driver); +} + +} // namespace diff --git a/tests/repeat_key/config.h b/tests/repeat_key/config.h new file mode 100644 index 000000000000..003d980c824b --- /dev/null +++ b/tests/repeat_key/config.h @@ -0,0 +1,20 @@ +// Copyright 2023 Google LLC +// +// 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 . + +#pragma once + +#include "test_common.h" + +#define NO_ALT_REPEAT_KEY diff --git a/tests/repeat_key/repeat_key_combo/config.h b/tests/repeat_key/repeat_key_combo/config.h new file mode 100644 index 000000000000..d0c4ddadbd3b --- /dev/null +++ b/tests/repeat_key/repeat_key_combo/config.h @@ -0,0 +1,18 @@ +// Copyright 2023 Google LLC +// +// 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 . + +#pragma once + +#include "test_common.h" diff --git a/tests/repeat_key/repeat_key_combo/test.mk b/tests/repeat_key/repeat_key_combo/test.mk new file mode 100644 index 000000000000..db6ea7789a2d --- /dev/null +++ b/tests/repeat_key/repeat_key_combo/test.mk @@ -0,0 +1,18 @@ +# Copyright 2023 Google LLC +# +# 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 . + +REPEAT_KEY_ENABLE = yes + +COMBO_ENABLE = yes diff --git a/tests/repeat_key/repeat_key_combo/test_repeat_key_combo.cpp b/tests/repeat_key/repeat_key_combo/test_repeat_key_combo.cpp new file mode 100644 index 000000000000..2d2fbaa9665a --- /dev/null +++ b/tests/repeat_key/repeat_key_combo/test_repeat_key_combo.cpp @@ -0,0 +1,67 @@ +// Copyright 2023 Google LLC +// +// 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 . + +#include "keyboard_report_util.hpp" +#include "keycode.h" +#include "test_common.hpp" +#include "test_fixture.hpp" +#include "test_keymap_key.hpp" + +using ::testing::AnyNumber; +using ::testing::InSequence; + +namespace { + +extern "C" { +// Define a combo: KC_X + KC_Y = KC_Q. +const uint16_t xy_combo[] PROGMEM = {KC_X, KC_Y, COMBO_END}; +combo_t key_combos[] = {COMBO(xy_combo, KC_Q)}; +uint16_t COMBO_LEN = sizeof(key_combos) / sizeof(*key_combos); +} // extern "C" + +class RepeatKey : public TestFixture {}; + +// Tests repeating a combo, KC_X + KC_Y = KC_Q, by typing +// "X, Repeat, Repeat, {X Y}, Repeat, Repeat". This produces "xxxqqq". +TEST_F(RepeatKey, Combo) { + TestDriver driver; + KeymapKey key_x(0, 0, 0, KC_X); + KeymapKey key_y(0, 1, 0, KC_Y); + KeymapKey key_repeat(0, 2, 0, QK_REP); + set_keymap({key_x, key_y, key_repeat}); + + // Allow any number of empty reports. + EXPECT_EMPTY_REPORT(driver).Times(AnyNumber()); + { + InSequence seq; + EXPECT_REPORT(driver, (KC_X)); + EXPECT_REPORT(driver, (KC_X)); + EXPECT_REPORT(driver, (KC_X)); + EXPECT_REPORT(driver, (KC_Q)); + EXPECT_REPORT(driver, (KC_Q)); + EXPECT_REPORT(driver, (KC_Q)); + } + + tap_keys(key_x, key_repeat, key_repeat); + tap_combo({key_x, key_y}); + + EXPECT_KEYCODE_EQ(get_last_keycode(), KC_Q); + + tap_keys(key_repeat, key_repeat); + + testing::Mock::VerifyAndClearExpectations(&driver); +} + +} // namespace diff --git a/tests/repeat_key/test.mk b/tests/repeat_key/test.mk new file mode 100644 index 000000000000..aec8ff3bfb89 --- /dev/null +++ b/tests/repeat_key/test.mk @@ -0,0 +1,18 @@ +# Copyright 2023 Google LLC +# +# 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 . + +REPEAT_KEY_ENABLE = yes + +AUTO_SHIFT_ENABLE = yes diff --git a/tests/repeat_key/test_repeat_key.cpp b/tests/repeat_key/test_repeat_key.cpp new file mode 100644 index 000000000000..eee44fc10448 --- /dev/null +++ b/tests/repeat_key/test_repeat_key.cpp @@ -0,0 +1,754 @@ +// Copyright 2023 Google LLC +// +// 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 . + +#include + +#include "keyboard_report_util.hpp" +#include "keycode.h" +#include "test_common.hpp" +#include "test_fixture.hpp" +#include "test_keymap_key.hpp" + +using ::testing::AnyNumber; +using ::testing::AnyOf; +using ::testing::InSequence; + +#define FOO_MACRO SAFE_RANGE + +namespace { + +bool process_record_user_default(uint16_t keycode, keyrecord_t* record) { + return true; +} + +bool remember_last_key_user_default(uint16_t keycode, keyrecord_t* record, uint8_t* remembered_mods) { + return true; +} + +// Indirection so that process_record_user() and remember_last_key_user() +// can be replaced with other functions in the test cases below. +std::function process_record_user_fun = process_record_user_default; +std::function remember_last_key_user_fun = remember_last_key_user_default; + +extern "C" bool process_record_user(uint16_t keycode, keyrecord_t* record) { + return process_record_user_fun(keycode, record); +} +extern "C" bool remember_last_key_user(uint16_t keycode, keyrecord_t* record, uint8_t* remembered_mods) { + return remember_last_key_user_fun(keycode, record, remembered_mods); +} + +class RepeatKey : public TestFixture { + public: + bool process_record_user_was_called_; + + void SetUp() override { + autoshift_disable(); + process_record_user_fun = process_record_user_default; + remember_last_key_user_fun = remember_last_key_user_default; + } + + void ExpectProcessRecordUserCalledWith(bool expected_press, uint16_t expected_keycode, int8_t expected_repeat_key_count) { + process_record_user_was_called_ = false; + process_record_user_fun = [=](uint16_t keycode, keyrecord_t* record) { + EXPECT_EQ(record->event.pressed, expected_press); + EXPECT_KEYCODE_EQ(keycode, expected_keycode); + EXPECT_EQ(get_repeat_key_count(), expected_repeat_key_count); + // Tests below use this to verify process_record_user() was called. + process_record_user_was_called_ = true; + return true; + }; + } + + // Expects that the characters of `s` are sent. + // NOTE: This implementation is limited to chars a-z, A-Z. + void ExpectString(TestDriver& driver, const std::string& s) { + InSequence seq; + for (int c : s) { + switch (c) { + case 'a' ... 'z': { // Lowercase letter. + uint16_t keycode = c - ('a' - KC_A); + EXPECT_REPORT(driver, (keycode)); + } break; + + case 'A' ... 'Z': { // Capital letter = KC_LSFT + letter key. + uint16_t keycode = c - ('A' - KC_A); + EXPECT_REPORT(driver, (KC_LSFT, keycode)); + } break; + } + } + } +}; + +// Tests that "A, Repeat, Repeat, B, Repeat" produces "aaabb". +TEST_F(RepeatKey, Basic) { + TestDriver driver; + KeymapKey key_a(0, 0, 0, KC_A); + KeymapKey key_b(0, 1, 0, KC_B); + KeymapKey key_repeat(0, 2, 0, QK_REP); + set_keymap({key_a, key_b, key_repeat}); + + // Allow any number of empty reports. + EXPECT_EMPTY_REPORT(driver).Times(AnyNumber()); + ExpectString(driver, "aaabb"); + + // When KC_A is pressed, process_record_user() should be called + // with a press event with keycode == KC_A and repeat_key_count() == 0. + ExpectProcessRecordUserCalledWith(true, KC_A, 0); + key_a.press(); + run_one_scan_loop(); + EXPECT_TRUE(process_record_user_was_called_); + + // After pressing A, the keycode of the key to be repeated is KC_A. + EXPECT_KEYCODE_EQ(get_last_keycode(), KC_A); + EXPECT_EQ(get_last_mods(), 0); + + // Expect the corresponding release event when A is released. + ExpectProcessRecordUserCalledWith(false, KC_A, 0); + key_a.release(); + run_one_scan_loop(); + + for (int n = 1; n <= 2; ++n) { // Tap the Repeat Key twice. + // When Repeat is pressed, process_record_user() should be called with a + // press event with keycode == KC_A and repeat_key_count() == n. + ExpectProcessRecordUserCalledWith(true, KC_A, n); + key_repeat.press(); // Press the Repeat Key. + run_one_scan_loop(); + EXPECT_TRUE(process_record_user_was_called_); + + // Expect the corresponding release event. + ExpectProcessRecordUserCalledWith(false, KC_A, n); + key_repeat.release(); // Release the Repeat Key. + run_one_scan_loop(); + EXPECT_TRUE(process_record_user_was_called_); + } + + process_record_user_fun = process_record_user_default; + tap_key(key_b); + // Then after tapping key_b, the keycode to be repeated becomes KC_B. + EXPECT_KEYCODE_EQ(get_last_keycode(), KC_B); + + tap_key(key_repeat); + + testing::Mock::VerifyAndClearExpectations(&driver); +} + +// Tests repeating a macro. The keycode FOO_MACRO sends "foo" when pressed. The +// test taps "FOO_MACRO, Repeat, Repeat", producing "foofoofoo". +TEST_F(RepeatKey, Macro) { + TestDriver driver; + KeymapKey key_foo(0, 0, 0, FOO_MACRO); + KeymapKey key_repeat(0, 1, 0, QK_REP); + set_keymap({key_foo, key_repeat}); + + // Define process_record_user() to handle FOO_MACRO. + process_record_user_fun = [](uint16_t keycode, keyrecord_t* record) { + switch (keycode) { + case FOO_MACRO: + if (record->event.pressed) { + SEND_STRING("foo"); + } + break; + } + return true; + }; + + // Allow any number of empty reports. + EXPECT_EMPTY_REPORT(driver).Times(AnyNumber()); + ExpectString(driver, "foofoofoo"); + + tap_key(key_foo); + + EXPECT_KEYCODE_EQ(get_last_keycode(), FOO_MACRO); + + tap_keys(key_repeat, key_repeat); + + testing::Mock::VerifyAndClearExpectations(&driver); +} + +// Tests a macro with customized repeat behavior: "foo" is sent normally, "bar" +// on the first repeat, and "baz" on subsequent repeats. The test taps +// "FOO_MACRO, Repeat, Repeat, FOO_MACRO, Repeat", producing "foobarbazfoobar". +TEST_F(RepeatKey, MacroCustomRepeat) { + TestDriver driver; + KeymapKey key_foo(0, 0, 0, FOO_MACRO); + KeymapKey key_repeat(0, 1, 0, QK_REP); + set_keymap({key_foo, key_repeat}); + + process_record_user_fun = [](uint16_t keycode, keyrecord_t* record) { + switch (keycode) { + case FOO_MACRO: + if (record->event.pressed) { + switch (get_repeat_key_count()) { + case 0: // When pressed normally. + SEND_STRING("foo"); + break; + case 1: // On first repeat. + SEND_STRING("bar"); + break; + default: // On subsequent repeats. + SEND_STRING("baz"); + break; + } + } + break; + } + return true; + }; + + // Allow any number of empty reports. + EXPECT_EMPTY_REPORT(driver).Times(AnyNumber()); + ExpectString(driver, "foobarbazfoobar"); + + tap_key(key_foo); + + EXPECT_KEYCODE_EQ(get_last_keycode(), FOO_MACRO); + + tap_keys(key_repeat, key_repeat, key_foo, key_repeat); + + testing::Mock::VerifyAndClearExpectations(&driver); +} + +// Tests repeating keys on different layers. A 2-layer keymap is defined: +// Layer 0: QK_REP , MO(1) , KC_A +// Layer 1: KC_TRNS, KC_TRNS, KC_B +// The test does the following, which should produce "bbbaaa": +// 1. Hold MO(1), switching to layer 1. +// 2. Tap KC_B on layer 1. +// 3. Release MO(1), switching back to layer 0. +// 4. Tap Repeat twice. +// 5. Tap KC_A on layer 0. +// 6. Hold MO(1), switching to layer 1. +// 7. Tap Repeat twice. +TEST_F(RepeatKey, AcrossLayers) { + TestDriver driver; + KeymapKey key_repeat(0, 0, 0, QK_REP); + KeymapKey key_mo_1(0, 1, 0, MO(1)); + KeymapKey regular_key(0, 2, 0, KC_A); + set_keymap({// Layer 0. + key_repeat, key_mo_1, regular_key, + // Layer 1. + KeymapKey{1, 0, 0, KC_TRNS}, KeymapKey{1, 1, 0, KC_TRNS}, KeymapKey{1, 2, 0, KC_B}}); + + // Allow any number of empty reports. + EXPECT_EMPTY_REPORT(driver).Times(AnyNumber()); + ExpectString(driver, "bbbaaa"); + + key_mo_1.press(); // Hold the MO(1) layer key. + run_one_scan_loop(); + tap_key(regular_key); // Taps the KC_B key on layer 1. + + EXPECT_KEYCODE_EQ(get_last_keycode(), KC_B); + + key_mo_1.release(); // Release the layer key. + run_one_scan_loop(); + tap_keys(key_repeat, key_repeat); + tap_key(regular_key); // Taps the KC_A key on layer 0. + + EXPECT_KEYCODE_EQ(get_last_keycode(), KC_A); + + key_mo_1.press(); // Hold the layer key. + run_one_scan_loop(); + tap_keys(key_repeat, key_repeat); + + testing::Mock::VerifyAndClearExpectations(&driver); +} + +// Tests "A(down), Repeat(down), A(up), Repeat(up), Repeat" produces "aaa". +TEST_F(RepeatKey, RollingToRepeat) { + TestDriver driver; + KeymapKey key_a(0, 0, 0, KC_A); + KeymapKey key_repeat(0, 1, 0, QK_REP); + set_keymap({key_a, key_repeat}); + + { + InSequence seq; + EXPECT_REPORT(driver, (KC_A)); + EXPECT_EMPTY_REPORT(driver); + EXPECT_REPORT(driver, (KC_A)); + EXPECT_EMPTY_REPORT(driver); + EXPECT_REPORT(driver, (KC_A)); + EXPECT_EMPTY_REPORT(driver); + } + + // Perform a rolled press from A to Repeat. + + ExpectProcessRecordUserCalledWith(true, KC_A, 0); + key_a.press(); + run_one_scan_loop(); + EXPECT_TRUE(process_record_user_was_called_); + + ExpectProcessRecordUserCalledWith(true, KC_A, 1); + key_repeat.press(); // Press the Repeat Key. + run_one_scan_loop(); + EXPECT_TRUE(process_record_user_was_called_); + + ExpectProcessRecordUserCalledWith(false, KC_A, 0); + key_a.release(); + run_one_scan_loop(); + EXPECT_TRUE(process_record_user_was_called_); + + ExpectProcessRecordUserCalledWith(false, KC_A, 1); + key_repeat.release(); // Release the Repeat Key. + run_one_scan_loop(); + EXPECT_TRUE(process_record_user_was_called_); + + process_record_user_fun = process_record_user_default; + tap_key(key_repeat); + + testing::Mock::VerifyAndClearExpectations(&driver); +} + +// Tests "A, Repeat(down), B(down), Repeat(up), B(up), Repeat" produces "aabb". +TEST_F(RepeatKey, RollingFromRepeat) { + TestDriver driver; + KeymapKey key_a(0, 0, 0, KC_A); + KeymapKey key_b(0, 1, 0, KC_B); + KeymapKey key_repeat(0, 2, 0, QK_REP); + set_keymap({key_a, key_b, key_repeat}); + + { + InSequence seq; + EXPECT_REPORT(driver, (KC_A)); + EXPECT_EMPTY_REPORT(driver); + EXPECT_REPORT(driver, (KC_A)); + EXPECT_REPORT(driver, (KC_A, KC_B)); + EXPECT_REPORT(driver, (KC_B)); + EXPECT_EMPTY_REPORT(driver); + EXPECT_REPORT(driver, (KC_B)); + EXPECT_EMPTY_REPORT(driver); + } + + tap_key(key_a); + + // Perform a rolled press from Repeat to B. + + ExpectProcessRecordUserCalledWith(true, KC_A, 1); + key_repeat.press(); // Press the Repeat Key. + run_one_scan_loop(); + EXPECT_TRUE(process_record_user_was_called_); + + ExpectProcessRecordUserCalledWith(true, KC_B, 0); + key_b.press(); + run_one_scan_loop(); + EXPECT_TRUE(process_record_user_was_called_); + + EXPECT_KEYCODE_EQ(get_last_keycode(), KC_B); + + ExpectProcessRecordUserCalledWith(false, KC_A, 1); + key_repeat.release(); // Release the Repeat Key. + run_one_scan_loop(); + EXPECT_TRUE(process_record_user_was_called_); + + ExpectProcessRecordUserCalledWith(false, KC_B, 0); + key_b.release(); + run_one_scan_loop(); + EXPECT_TRUE(process_record_user_was_called_); + + process_record_user_fun = process_record_user_default; + tap_key(key_repeat); + + testing::Mock::VerifyAndClearExpectations(&driver); +} + +// Tests Repeat Key with a modifier, types "AltGr+C, Repeat, Repeat, C". +TEST_F(RepeatKey, RecallMods) { + TestDriver driver; + KeymapKey key_c(0, 0, 0, KC_C); + KeymapKey key_altgr(0, 1, 0, KC_RALT); + KeymapKey key_repeat(0, 2, 0, QK_REP); + set_keymap({key_c, key_altgr, key_repeat}); + + // Allow any number of reports with no keys or only KC_RALT. + // clang-format off + EXPECT_CALL(driver, send_keyboard_mock(AnyOf( + KeyboardReport(), + KeyboardReport(KC_RALT)))) + .Times(AnyNumber()); + // clang-format on + + { // Expect: "AltGr+C, AltGr+C, AltGr+C, C". + InSequence seq; + EXPECT_REPORT(driver, (KC_RALT, KC_C)); + EXPECT_REPORT(driver, (KC_RALT, KC_C)); + EXPECT_REPORT(driver, (KC_RALT, KC_C)); + EXPECT_REPORT(driver, (KC_C)); + } + + key_altgr.press(); + run_one_scan_loop(); + tap_key(key_c); + key_altgr.release(); + run_one_scan_loop(); + + EXPECT_KEYCODE_EQ(get_last_keycode(), KC_C); + EXPECT_EQ(get_last_mods(), MOD_BIT(KC_RALT)); + + tap_keys(key_repeat, key_repeat, key_c); + + testing::Mock::VerifyAndClearExpectations(&driver); +} + +// Tests that Repeat Key stacks mods, types +// "Ctrl+Left, Repeat, Shift+Repeat, Shift+Repeat, Repeat, Left". +TEST_F(RepeatKey, StackMods) { + TestDriver driver; + KeymapKey key_left(0, 0, 0, KC_LEFT); + KeymapKey key_shift(0, 1, 0, KC_LSFT); + KeymapKey key_ctrl(0, 2, 0, KC_LCTL); + KeymapKey key_repeat(0, 3, 0, QK_REP); + set_keymap({key_left, key_shift, key_ctrl, key_repeat}); + + // Allow any number of reports with no keys or only mods. + // clang-format off + EXPECT_CALL(driver, send_keyboard_mock(AnyOf( + KeyboardReport(), + KeyboardReport(KC_LCTL), + KeyboardReport(KC_LSFT), + KeyboardReport(KC_LCTL, KC_LSFT)))) + .Times(AnyNumber()); + // clang-format on + + { // Expect: "Ctrl+Left, Ctrl+Shift+Left". + InSequence seq; + EXPECT_REPORT(driver, (KC_LCTL, KC_LEFT)); + EXPECT_REPORT(driver, (KC_LCTL, KC_LEFT)); + EXPECT_REPORT(driver, (KC_LCTL, KC_LSFT, KC_LEFT)); + EXPECT_REPORT(driver, (KC_LCTL, KC_LSFT, KC_LEFT)); + EXPECT_REPORT(driver, (KC_LCTL, KC_LEFT)); + EXPECT_REPORT(driver, (KC_LEFT)); + } + + key_ctrl.press(); + run_one_scan_loop(); + tap_key(key_left); + run_one_scan_loop(); + key_ctrl.release(); + run_one_scan_loop(); + + EXPECT_KEYCODE_EQ(get_last_keycode(), KC_LEFT); + EXPECT_EQ(get_last_mods(), MOD_BIT(KC_LCTL)); + + tap_key(key_repeat); + + key_shift.press(); + run_one_scan_loop(); + tap_keys(key_repeat, key_repeat); + key_shift.release(); + run_one_scan_loop(); + + EXPECT_EQ(get_last_mods(), MOD_BIT(KC_LCTL)); + + tap_keys(key_repeat, key_left); + + testing::Mock::VerifyAndClearExpectations(&driver); +} + +// Types: "S(KC_1), Repeat, Ctrl+Repeat, Ctrl+Repeat, Repeat, KC_2". +TEST_F(RepeatKey, ShiftedKeycode) { + TestDriver driver; + KeymapKey key_exlm(0, 0, 0, S(KC_1)); + KeymapKey key_2(0, 1, 0, KC_2); + KeymapKey key_ctrl(0, 2, 0, KC_LCTL); + KeymapKey key_repeat(0, 3, 0, QK_REP); + set_keymap({key_exlm, key_2, key_ctrl, key_repeat}); + + // Allow any number of reports with no keys or only mods. + // clang-format off + EXPECT_CALL(driver, send_keyboard_mock(AnyOf( + KeyboardReport(), + KeyboardReport(KC_LCTL), + KeyboardReport(KC_LSFT), + KeyboardReport(KC_LCTL, KC_LSFT)))) + .Times(AnyNumber()); + // clang-format on + + { // Expect: "Shift+1, Shift+1, Ctrl+Shift+1, Ctrl+Shift+1, Shift+1, 2". + InSequence seq; + EXPECT_REPORT(driver, (KC_LSFT, KC_1)); + EXPECT_REPORT(driver, (KC_LSFT, KC_1)); + EXPECT_REPORT(driver, (KC_LCTL, KC_LSFT, KC_1)); + EXPECT_REPORT(driver, (KC_LCTL, KC_LSFT, KC_1)); + EXPECT_REPORT(driver, (KC_LSFT, KC_1)); + EXPECT_REPORT(driver, (KC_2)); + } + + tap_key(key_exlm); + + EXPECT_KEYCODE_EQ(get_last_keycode(), S(KC_1)); + + tap_key(key_repeat); + + key_ctrl.press(); + run_one_scan_loop(); + tap_keys(key_repeat, key_repeat); + key_ctrl.release(); + run_one_scan_loop(); + + tap_keys(key_repeat, key_2); + + testing::Mock::VerifyAndClearExpectations(&driver); +} + +// Tests Repeat Key with a one-shot Shift, types +// "A, OSM(MOD_LSFT), Repeat, Repeat". +TEST_F(RepeatKey, WithOneShotShift) { + TestDriver driver; + KeymapKey key_a(0, 0, 0, KC_A); + KeymapKey key_oneshot_shift(0, 1, 0, OSM(MOD_LSFT)); + KeymapKey key_repeat(0, 2, 0, QK_REP); + set_keymap({key_a, key_oneshot_shift, key_repeat}); + + // Allow any number of reports with no keys or only KC_RALT. + // clang-format off + EXPECT_CALL(driver, send_keyboard_mock(AnyOf( + KeyboardReport(), + KeyboardReport(KC_LSFT)))) + .Times(AnyNumber()); + // clang-format on + ExpectString(driver, "aAa"); + + tap_keys(key_a, key_oneshot_shift, key_repeat, key_repeat); + + testing::Mock::VerifyAndClearExpectations(&driver); +} + +// Tests Repeat Key with a mod-tap key, types +// "A, Repeat, Repeat, A(down), Repeat, Repeat, A(up), Repeat". +TEST_F(RepeatKey, ModTap) { + TestDriver driver; + KeymapKey key_mt_a(0, 0, 0, LSFT_T(KC_A)); + KeymapKey key_repeat(0, 1, 0, QK_REP); + set_keymap({key_mt_a, key_repeat}); + + // Allow any number of reports with no keys or only KC_LSFT. + // clang-format off + EXPECT_CALL(driver, send_keyboard_mock(AnyOf( + KeyboardReport(), + KeyboardReport(KC_LSFT)))) + .Times(AnyNumber()); + // clang-format on + ExpectString(driver, "aaaAAa"); + + tap_key(key_mt_a); + + EXPECT_KEYCODE_EQ(get_last_keycode(), LSFT_T(KC_A)); + + tap_keys(key_repeat, key_repeat); + key_mt_a.press(); + run_one_scan_loop(); + tap_key(key_repeat, TAPPING_TERM + 1); + tap_key(key_repeat); + key_mt_a.release(); + run_one_scan_loop(); + tap_key(key_repeat); + + testing::Mock::VerifyAndClearExpectations(&driver); +} + +// Tests with Auto Shift. When repeating an autoshiftable key, it does not +// matter how long the original key was held, rather, quickly tapping vs. +// long-pressing the Repeat Key determines whether the shifted key is repeated. +// +// The test does the following, which should produce "aaABbB": +// 1. Tap KC_A quickly. +// 2. Tap Repeat Key quickly. +// 3. Long-press Repeat Key. +// 4. Long-press KC_B. +// 5. Tap Repeat Key quickly. +// 6. Long-press Repeat Key. +TEST_F(RepeatKey, AutoShift) { + TestDriver driver; + KeymapKey key_a(0, 0, 0, KC_A); + KeymapKey key_b(0, 1, 0, KC_B); + KeymapKey key_repeat(0, 2, 0, QK_REP); + set_keymap({key_a, key_b, key_repeat}); + + autoshift_enable(); + + // Allow any number of reports with no keys or only KC_LSFT. + // clang-format off + EXPECT_CALL(driver, send_keyboard_mock(AnyOf( + KeyboardReport(), + KeyboardReport(KC_LSFT)))) + .Times(AnyNumber()); + // clang-format on + ExpectString(driver, "aaABbB"); + + tap_key(key_a); // Tap A quickly. + + EXPECT_KEYCODE_EQ(get_last_keycode(), KC_A); + EXPECT_EQ(get_last_mods(), 0); + + tap_key(key_repeat); + tap_key(key_repeat, AUTO_SHIFT_TIMEOUT + 1); + + tap_key(key_b, AUTO_SHIFT_TIMEOUT + 1); // Long press B. + + EXPECT_KEYCODE_EQ(get_last_keycode(), KC_B); + EXPECT_EQ(get_last_mods(), 0); + + tap_key(key_repeat); + tap_key(key_repeat, AUTO_SHIFT_TIMEOUT + 1); + + testing::Mock::VerifyAndClearExpectations(&driver); +} + +// Defines `remember_last_key_user()` to forget the Shift mod and types: +// "Ctrl+A, Repeat, Shift+A, Repeat, Shift+Repeat". +TEST_F(RepeatKey, FilterRememberedMods) { + TestDriver driver; + KeymapKey key_a(0, 0, 0, KC_A); + KeymapKey key_ctrl(0, 1, 0, KC_LCTL); + KeymapKey key_shift(0, 2, 0, KC_LSFT); + KeymapKey key_repeat(0, 3, 0, QK_REP); + set_keymap({key_a, key_ctrl, key_shift, key_repeat}); + + remember_last_key_user_fun = [](uint16_t keycode, keyrecord_t* record, uint8_t* remembered_mods) { + *remembered_mods &= ~MOD_MASK_SHIFT; + return true; + }; + + // Allow any number of reports with no keys or only mods. + // clang-format off + EXPECT_CALL(driver, send_keyboard_mock(AnyOf( + KeyboardReport(), + KeyboardReport(KC_LCTL), + KeyboardReport(KC_LSFT), + KeyboardReport(KC_LCTL, KC_LSFT)))) + .Times(AnyNumber()); + // clang-format on + + { // Expect: "Ctrl+A, Ctrl+A, Shift+A, A, Shift+A". + InSequence seq; + EXPECT_REPORT(driver, (KC_LCTL, KC_A)); + EXPECT_REPORT(driver, (KC_LCTL, KC_A)); + EXPECT_REPORT(driver, (KC_LSFT, KC_A)); + EXPECT_REPORT(driver, (KC_A)); + EXPECT_REPORT(driver, (KC_LSFT, KC_A)); + } + + key_ctrl.press(); + run_one_scan_loop(); + tap_key(key_a); + + EXPECT_EQ(get_last_mods(), MOD_BIT(KC_LCTL)); + + key_ctrl.release(); + run_one_scan_loop(); + + tap_key(key_repeat); + key_shift.press(); + run_one_scan_loop(); + tap_key(key_a); + + EXPECT_EQ(get_last_mods(), 0); // Shift should be forgotten. + + key_shift.release(); + run_one_scan_loop(); + + tap_key(key_repeat); + + key_shift.press(); + run_one_scan_loop(); + tap_key(key_repeat); + key_shift.release(); + run_one_scan_loop(); + + testing::Mock::VerifyAndClearExpectations(&driver); +} + +// Tests set_last_keycode() and set_last_mods(). +TEST_F(RepeatKey, SetRepeatKeyKeycode) { + TestDriver driver; + KeymapKey key_repeat(0, 0, 0, QK_REP); + set_keymap({key_repeat}); + + // Allow any number of reports with no keys or only KC_LSFT. + // clang-format off + EXPECT_CALL(driver, send_keyboard_mock(AnyOf( + KeyboardReport(), + KeyboardReport(KC_LSFT)))) + .Times(AnyNumber()); + // clang-format on + ExpectString(driver, "aaBB"); + + set_last_keycode(KC_A); + EXPECT_KEYCODE_EQ(get_last_keycode(), KC_A); + + for (int n = 1; n <= 2; ++n) { // Tap the Repeat Key twice. + // When Repeat is pressed, process_record_user() should be called with a + // press event with keycode == KC_A and repeat_key_count() == n. + ExpectProcessRecordUserCalledWith(true, KC_A, n); + key_repeat.press(); // Press the Repeat Key. + run_one_scan_loop(); + EXPECT_TRUE(process_record_user_was_called_); + + // Expect the corresponding release event. + ExpectProcessRecordUserCalledWith(false, KC_A, n); + key_repeat.release(); // Release the Repeat Key. + run_one_scan_loop(); + EXPECT_TRUE(process_record_user_was_called_); + } + + process_record_user_fun = process_record_user_default; + set_last_keycode(KC_B); + set_last_mods(MOD_BIT(KC_LSFT)); + + tap_keys(key_repeat, key_repeat); + + set_last_keycode(KC_NO); + tap_keys(key_repeat, key_repeat); // Has no effect. + + testing::Mock::VerifyAndClearExpectations(&driver); +} + +// Tests the `repeat_key_invoke()` function. +TEST_F(RepeatKey, RepeatKeyInvoke) { + TestDriver driver; + KeymapKey key_s(0, 0, 0, KC_S); + set_keymap({key_s}); + + // Allow any number of empty reports. + EXPECT_EMPTY_REPORT(driver).Times(AnyNumber()); + ExpectString(driver, "ss"); + + tap_key(key_s); + + EXPECT_KEYCODE_EQ(get_last_keycode(), KC_S); + + // Calling repeat_key_invoke() should result in process_record_user() + // getting a press event with keycode KC_S. + ExpectProcessRecordUserCalledWith(true, KC_S, 1); + keyevent_t event; + event.key = {0, 0}; + event.pressed = true; + event.time = timer_read(); + event.type = KEY_EVENT; + repeat_key_invoke(&event); + run_one_scan_loop(); + EXPECT_TRUE(process_record_user_was_called_); + + // Make the release event. + ExpectProcessRecordUserCalledWith(false, KC_S, 1); + event.pressed = false; + event.time = timer_read(); + repeat_key_invoke(&event); + run_one_scan_loop(); + EXPECT_TRUE(process_record_user_was_called_); + + testing::Mock::VerifyAndClearExpectations(&driver); +} + +} // namespace diff --git a/tests/test_common/keycode_table.cpp b/tests/test_common/keycode_table.cpp index d21630c01be1..9ed80cdbcf66 100644 --- a/tests/test_common/keycode_table.cpp +++ b/tests/test_common/keycode_table.cpp @@ -663,6 +663,8 @@ std::map KEYCODE_ID_TABLE = { {QK_AUTOCORRECT_TOGGLE, "QK_AUTOCORRECT_TOGGLE"}, {QK_TRI_LAYER_LOWER, "QK_TRI_LAYER_LOWER"}, {QK_TRI_LAYER_UPPER, "QK_TRI_LAYER_UPPER"}, + {QK_REPEAT_KEY, "QK_REPEAT_KEY"}, + {QK_ALT_REPEAT_KEY, "QK_ALT_REPEAT_KEY"}, {QK_KB_0, "QK_KB_0"}, {QK_KB_1, "QK_KB_1"}, {QK_KB_2, "QK_KB_2"}, diff --git a/tests/test_common/test_driver.hpp b/tests/test_common/test_driver.hpp index 8d09e448405a..d8a6885d0ff8 100644 --- a/tests/test_common/test_driver.hpp +++ b/tests/test_common/test_driver.hpp @@ -20,6 +20,7 @@ #include #include "host.h" #include "keyboard_report_util.hpp" +#include "keycode_util.hpp" #include "test_logger.hpp" class TestDriver { @@ -98,6 +99,17 @@ class TestDriver { */ #define EXPECT_NO_REPORT(driver) EXPECT_ANY_REPORT(driver).Times(0) +/** @brief Tests whether keycode `actual` is equal to `expected`. */ +#define EXPECT_KEYCODE_EQ(actual, expected) EXPECT_THAT((actual), KeycodeEq((expected))) + +MATCHER_P(KeycodeEq, expected_keycode, "is equal to " + testing::PrintToString(expected_keycode) + ", keycode " + get_keycode_identifier_or_default(expected_keycode)) { + if (arg == expected_keycode) { + return true; + } + *result_listener << "keycode " << get_keycode_identifier_or_default(arg); + return false; +} + /** * @brief Verify and clear all gmock expectations that have been setup until * this point.