1
0
Fork 0

keyhive sofle rgb: fix configuration. (#15339)

* keyhive sofle rgb: fix configuration.

* Add Colemak-DH and cycle layer keycode.

* Fix indentation.

* Add PLACEHOLDER for better readability.

* Fix breaking changes.

* Just one colemak.

* PR Cleanup

* Use NO_PIN definition instead of C7
* Define animations individually
* Remove via json file and update documentation
* Reduce LED brightness, one of the animations caused a crash

* More PR feedback.

* Better credit.
* Disable NKRO.

* Cleanup RGB configuration.

* animations defined in keymap.

* Update keyboards/sofle/keyhive/readme.md

* PR Feedback.

* Update phrasing from template.

* Disable RGBLIGHT_ENABLE in keymap for better compatibility with default keymap.

* Set a default animation.

* Use default in keyboard readme.

* Update keyboards/sofle/keyhive/info.json

* Move via specific layout into via keymap.
This commit is contained in:
Will Winder 2022-01-11 15:17:37 -05:00 committed by GitHub
parent 1fdc42155a
commit 1f618c8302
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 513 additions and 176 deletions

View file

@ -20,43 +20,33 @@
#include "config_common.h" #include "config_common.h"
// USB Device descriptor parameter // USB Device descriptor parameter
#define VENDOR_ID 0xFC32 #define VENDOR_ID 0xFC32
#define PRODUCT_ID 0x1287 #define PRODUCT_ID 0x1287
#define DEVICE_VER 0x0002 #define DEVICE_VER 0x0002
#define MANUFACTURER Keyhive #define MANUFACTURER Keyhive
#define PRODUCT Sofle // VIA version for this PCB is incorrect for the bottom row #define PRODUCT Sofle
// Key matrix size // Key matrix size
// Rows are doubled-up. Added extra column for rotary encoder VIA mapping. // Rows are doubled-up. Added extra column for rotary encoder VIA mapping.
#define MATRIX_ROWS 10 #define MATRIX_ROWS 10
#define MATRIX_COLS 6 #define MATRIX_COLS 7
// wiring of each half // wiring of each half
#define MATRIX_ROW_PINS \ #define MATRIX_ROW_PINS { C6, D7, E6, B4, B5 }
{ C6, D7, E6, B4, B5 } #define MATRIX_COL_PINS { B6, B2, B3, B1, F7, F6, NO_PIN } // A virtual pin is needed for the encoder key matrix in via.
#define MATRIX_COL_PINS \ #define MATRIX_ROW_PINS_RIGHT { C6, D7, E6, B4, B5 }
{ B6, B2, B3, B1, F7, F6 } #define MATRIX_COL_PINS_RIGHT { F6, F7, B1, B3, B2, B6, NO_PIN } // A virtual pin is needed for the encoder key matrix in via.
#define MATRIX_ROW_PINS_RIGHT \
{ C6, D7, E6, B4, B5 }
#define MATRIX_COL_PINS_RIGHT \
{ F6, F7, B1, B3, B2, B6 }
#define DIODE_DIRECTION COL2ROW #define DIODE_DIRECTION COL2ROW
#define DEBOUNCE 5 #define DEBOUNCE 5
// Encoder support // Encoder support
#define ENCODERS_PAD_A \ #define ENCODERS_PAD_A { F5 }
{ F5 } #define ENCODERS_PAD_B { F4 }
#define ENCODERS_PAD_B \ #define ENCODERS_PAD_A_RIGHT { F4 }
{ F4 } #define ENCODERS_PAD_B_RIGHT { F5 }
#define ENCODERS_PAD_A_RIGHT \ #define ENCODER_RESOLUTIONS { 4, 2 } // Left encoder seems to have double-output issue but right does not.
{ F4 }
#define ENCODERS_PAD_B_RIGHT \
{ F5 }
#define ENCODER_RESOLUTIONS \
{ 4, 2 } // Left encoder seems to have double-output issue but right does not.
#define TAP_CODE_DELAY 10 #define TAP_CODE_DELAY 10
@ -72,34 +62,41 @@
#define SPLIT_TRANSPORT_MIRROR #define SPLIT_TRANSPORT_MIRROR
// Add RGB underglow // Add RGB underglow
#define RGB_DI_PIN D3 // by defining in the keyboard, incompatible keymaps will fail to compile.
#define RGBLED_NUM 74 #ifdef RGBLIGHT_ENABLE
#define RGBLED_SPLIT \ # define RGB_DI_PIN D3
{ 37, 37 } # define RGBLED_NUM 74
# define RGBLED_SPLIT {37,37}
# define RGBLIGHT_LIMIT_VAL 100 // LED Brightness, high power draw may exceed the USB limitations of 0.6A and cause a crash.
# define RGBLIGHT_HUE_STEP 10
# define RGBLIGHT_SAT_STEP 17
# define RGBLIGHT_VAL_STEP 17
//# define RGBLIGHT_LAYERS //Enable layer light indicators. Not required as updates are done in layer_state_set_user and led_update_user (+588).
# define RGBLIGHT_SLEEP //Turn off LEDs when computer sleeping (+72)
#define RGBLIGHT_LIMIT_VAL 160 // Power draw may exceed 0.6A at max brightness with white colour. //RGB LED Conversion macro from physical array to electric array (+146). This results in better looking animated effects.
#define RGBLIGHT_LAYERS //First section is the LED matrix, second section is the electrical wiring order, and the third section is the desired mapping
#define RGBLIGHT_LAYERS_OVERRIDE_RGB_OFF # define LED_LAYOUT( \
#define RGBLIGHT_SLEEP L00, L01, L02, L03, L04, L05, L08, L09, L010, L011, L012, L013, \
L10, L12, L14, L19, L111, L113, \
L20, L21, L22, L23, L24, L25, L28, L29, L210, L211, L212, L213, \
L30, L31, L32, L33, L34, L35, L38, L39, L310, L311, L312, L313, \
L40, L42, L44, L49, L411, L413, \
L50, L51, L52, L53, L54, L55, L58, L59, L510, L511, L512, L513, \
L62, L63, L64, L65, L66, L67, L68, L69, L610, L611, \
L71, L76, L77, L712 )\
{ \
L14,L12,L10,L40,L42,L44,L71,L76,L66,L65,L55,L35,L25,L05,L04,L24,L34,L54,L64,L63,L53,L33,L23,L03,L02,L22,L32,L52,L62,L51,L31,L21,L01,L00,L20,L30,L50,L19,L111,L113,L413,L411,L49,L712,L77,L67,L68,L58,L38,L28,L08,L09,L29,L39,L59,L69,L610,L510,L310,L210,L010,L011,L211,L311,L511,L611,L512,L312,L212,L012,L013,L213,L313,L513, \
}
//RGB LED logical order map
# define RGBLIGHT_LED_MAP LED_LAYOUT( \
5, 6, 17, 18, 29, 30, 43, 44, 55, 56, 67, 68, \
4, 16, 28, 45, 57, 69, \
3, 7, 15, 19, 27, 31, 42, 46, 54, 58, 66, 70, \
2, 8, 14, 20, 26, 32, 41, 47, 53, 59, 65, 71, \
1, 13, 25, 48, 60, 72, \
0, 9, 12, 21, 24, 33, 40, 49, 52, 61, 64, 73, \
11, 22, 23, 34, 35, 38, 39, 50, 51, 62, \
10, 36, 37, 63 )
#define DRIVER_LED_TOTAL RGBLED_NUM #endif
#define RGB_MATRIX_SPLIT RGBLED_SPLIT
#define RGB_MATRIX_KEYPRESSES // reacts to keypresses
#define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
#define RGB_MATRIX_FRAMEBUFFER_EFFECTS
#define RGB_MATRIX_KEYPRESSES // reacts to keypresses
// # define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses)
// # define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
#define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
#define RGB_MATRIX_FRAMEBUFFER_EFFECTS
// # define RGB_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness)
// # define RGB_MATRIX_LED_FLUSH_LIMIT 16 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms) is equivalent to limiting to 60fps (increases keyboard responsiveness)
#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 150 // limits maximum brightness of LEDs to 150 out of 255. Higher may cause the controller to crash.
#define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_GRADIENT_LEFT_RIGHT
#define RGB_MATRIX_HUE_STEP 8
#define RGB_MATRIX_SAT_STEP 8
#define RGB_MATRIX_VAL_STEP 8
#define RGB_MATRIX_SPD_STEP 10

View file

@ -17,74 +17,3 @@
*/ */
#include "keyhive.h" #include "keyhive.h"
#ifdef RGB_MATRIX_ENABLE
// Physical Layout
// Columns
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13
// ROWS
// 12 13 22 23 32 33 33 32 23 22 13 12 0
// 02 03 04 04 03 02
// 11 14 21 24 31 34 34 31 24 21 14 11 1
// 01 01
// 10 15 20 25 30 35 35 30 25 20 15 10 2
//
// 09 16 19 26 29 36 36 29 26 19 16 09 3
//
// 08 17 18 27 28 28 27 18 17 08 4
// 07 06 05 05 06 07
// clang-format off
led_config_t g_led_config = {
{
{ 11, 12, 21, 22, 31, 32 },
{ 10, 13, 20, 23, 30, 33 },
{ 9, 14, 19, 24, 29, 34},
{ 8, 15, 18, 25, 28, 35},
{ 7, 16, 17, 26, 27, NO_LED },
{ 47, 48, 57, 58, 67, 68},
{ 46, 49, 56, 59, 66, 69},
{ 45, 50, 55, 60, 65, 70},
{ 44, 51, 54, 61, 64, 71},
{ 43, 52, 53, 62, 63, NO_LED }
},
{
// Left side underglow
{96, 40}, {16, 20}, {48, 10}, {80, 18}, {88, 60}, {56, 57}, {24,60},
// Left side Matrix
{32, 57}, { 0, 48}, { 0, 36}, { 0, 24}, { 0, 12},
{16, 12}, {16, 24}, {16, 36}, {16, 48}, {48, 55},
{64, 57}, {32, 45}, {32, 33}, {32, 21}, {32, 9},
{48, 7}, {48, 19}, {48, 31}, {48, 43}, {80, 59},
{96, 64}, {64, 45}, {64, 33}, {64, 21}, {64, 9},
{80, 10}, {80, 22}, {80, 34}, {80, 47},
// Right side underglow
{128, 40}, {208, 20}, {176, 10}, {144, 18}, {136, 60}, {168, 57}, {200,60},
// Right side Matrix
{192, 57}, {224, 48}, {224, 36}, {224, 24}, {224, 12},
{208, 12}, {208, 24}, {208, 36}, {208, 48}, {176, 55},
{160, 57}, {192, 45}, {192, 33}, {192, 21}, {192, 9},
{176, 7}, {176, 19}, {176, 31}, {176, 43}, {144, 59},
{128, 64}, {160, 45}, {160, 33}, {160, 21}, {160, 9},
{144, 10}, {144, 22}, {144, 34}, {144, 47},
},
{
LED_FLAG_NONE, LED_FLAG_UNDERGLOW, LED_FLAG_UNDERGLOW, LED_FLAG_UNDERGLOW, LED_FLAG_UNDERGLOW, LED_FLAG_UNDERGLOW, LED_FLAG_UNDERGLOW,
LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT,
LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT,
LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT,
LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT,
LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT,
LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT,
LED_FLAG_NONE, LED_FLAG_UNDERGLOW, LED_FLAG_UNDERGLOW, LED_FLAG_UNDERGLOW, LED_FLAG_UNDERGLOW, LED_FLAG_UNDERGLOW, LED_FLAG_UNDERGLOW,
LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT,
LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT,
LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT,
LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT,
LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT,
LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT, LED_FLAG_KEYLIGHT
}
};
#endif

View file

@ -21,7 +21,7 @@
#include "quantum.h" #include "quantum.h"
// clang-format off // clang-format off
// Extra keys are added for rotary encoder support in VIA
#define LAYOUT( \ #define LAYOUT( \
LA1, LA2, LA3, LA4, LA5, LA6, RA6, RA5, RA4, RA3, RA2, RA1, \ LA1, LA2, LA3, LA4, LA5, LA6, RA6, RA5, RA4, RA3, RA2, RA1, \
LB1, LB2, LB3, LB4, LB5, LB6, RB6, RB5, RB4, RB3, RB2, RB1, \ LB1, LB2, LB3, LB4, LB5, LB6, RB6, RB5, RB4, RB3, RB2, RB1, \
@ -30,18 +30,17 @@
LE2, LE3, LE4, LE5, LE6, RE5, RE4, RE3, RE2, RE1 \ LE2, LE3, LE4, LE5, LE6, RE5, RE4, RE3, RE2, RE1 \
) \ ) \
{ \ { \
{ LA1, LA2, LA3, LA4, LA5, LA6 }, \ { LA1, LA2, LA3, LA4, LA5, LA6, KC_NO }, \
{ LB1, LB2, LB3, LB4, LB5, LB6 }, \ { LB1, LB2, LB3, LB4, LB5, LB6, KC_NO }, \
{ LC1, LC2, LC3, LC4, LC5, LC6 }, \ { LC1, LC2, LC3, LC4, LC5, LC6, KC_NO }, \
{ LD1, LD2, LD3, LD4, LD5, LD6 }, \ { LD1, LD2, LD3, LD4, LD5, LD6, KC_NO }, \
{ LE1, LE2, LE3, LE4, LE5, LE6 }, \ { LE1, LE2, LE3, LE4, LE5, LE6, KC_NO }, \
{ RA1, RA2, RA3, RA4, RA5, RA6 }, \ { RA1, RA2, RA3, RA4, RA5, RA6, KC_NO }, \
{ RB1, RB2, RB3, RB4, RB5, RB6 }, \ { RB1, RB2, RB3, RB4, RB5, RB6, KC_NO }, \
{ RC1, RC2, RC3, RC4, RC5, RC6 }, \ { RC1, RC2, RC3, RC4, RC5, RC6, KC_NO }, \
{ RD1, RD2, RD3, RD4, RD5, RD6 }, \ { RD1, RD2, RD3, RD4, RD5, RD6, KC_NO }, \
{ RE1, RE2, RE3, RE4, RE5, RE6 } \ { RE1, RE2, RE3, RE4, RE5, RE6, KC_NO } \
} }
//RGB LED Conversion macro from physical array to electric array (+146 to firmware size) //RGB LED Conversion macro from physical array to electric array (+146 to firmware size)
// clang-format on // clang-format on

View file

@ -1,66 +1,54 @@
# Sofle Keyboard # Keyhive Sofle Keyboard
![SofleKeyboard version 2.1 RGB Keyhive](https://i.imgur.com/WH9OoWuh.jpg) ![SofleKeyboard version 2.1 RGB Keyhive](https://i.imgur.com/WH9OoWuh.jpg)
Sofle is 6×4+5 keys column-staggered split keyboard. Based on Lily58, Corne and Helix keyboards. Sofle is 6×4+5 keys column-staggered split keyboard. Based on Lily58, Corne and Helix keyboards.
For detailed instructions on using VIA and flashing, please refer to the sections further down the page!
For details about the keyboard design, refer to Josef's blog: [Sofle Keyboard - a split keyboard based on Lily58 and Crkbd](https://josef-adamcik.cz/electronics/let-me-introduce-you-sofle-keyboard-split-keyboard-based-on-lily58.html) For details about the keyboard design, refer to Josef's blog: [Sofle Keyboard - a split keyboard based on Lily58 and Crkbd](https://josef-adamcik.cz/electronics/let-me-introduce-you-sofle-keyboard-split-keyboard-based-on-lily58.html)
Build guide: [Keyhive Sofle RGB build guide](https://github.com/keyhive/build_guides/blob/master/docs/keyboards/sofle-rgb.md) Build guide: [Keyhive Sofle RGB build guide](https://github.com/keyhive/build_guides/blob/master/docs/keyboards/sofle-rgb.md)
* Keyboard Maintainer: [Solartempest] * Keyboard Maintainer: [Winder](https://github.com/winder)
* Hardware Supported: SofleKeyboard V2.1 RGB PCB, ProMicro / Elite-C * Hardware Supported: Keyhive Sofle RGB, ProMicro / Elite-C
* Hardware Availability: [Keyhive](https://keyhive.xyz/shop/sofle) * Hardware Availability: [Keyhive](https://keyhive.xyz/shop/sofle)
# Custom Features: ### Acknowledgements
### OLED Features: * Solartempest - the image on this page and most of the code is either copied directly or inspired by their fork. [Solartempest's fork.](https://github.com/solartempest/qmk_firmware/tree/master/keyboards/solartempest/sofle).
- Includes Snakey keyboard pet! Slithers according to WPM, bites, and sticks its tongue out at you! * [Keyhive fork](https://github.com/keyhive/qmk_firmware) defined all of the board settings.
- OLED displays current layer, lock key status, WPM, custom logo, and custom name.
- OLED shuts off on idle and when computer is sleeping.
- Includes working Luna keyboard pet.
- Includes working Bongocat (disable RGB for sufficient space).
- Includes stock OLED code as well.
### RGB Features: # Supported Keymaps
- Adds custom layer lighting with custom gradients for each layer.
- RGB underglow support and remapped to physical locations (nicer gradients and effects).
- Adds white caps lock, scroll lock, and num lock key indicators using the top row/underglow LEDs.
### Rotary Encoder and VIA Features: The keyhive schematic has been slightly modified compared to the open source sofle and not all keymaps are compatible.
- Fully emappable left encoder controls volume up/down/mute. Right encoder PGUP/PGDOWN.
- Allows for live remapping of per-layer rotary encoder functions in VIA.
- VIA support included by default.
- This fixes the Keyhive left bottom row offset issue in VIA. You will need to import sofle.json in VIA.
- Custom macro key in VIA for Super Alt Tab, which is fully compatible with rotary encoders.
- Custom macro key in VIA for moving windows to other monitors in Windows, which is fully compatible with rotary encoders.
### Tap and Other Features: * **default**: Basic functionality, no rgb, no VIA.
- Push left-shift + backspace to delete whole words. Right-shift + backspace to delete whole words in the opposite direction. * [keyhive_via](../keymaps/keyhive_via/readme.md) - Includes rgblighting and special support for remapping encoders with VIA.
- Double tap layers to stay on a layer instead of momentary push. * **Other**: may work but backwards compatibility is not guaranteed or tested.
- Adds key combo functionality.
- Symmetric modifiers (CMD/Super, Alt/Opt, Ctrl, Shift).
## Using with VIA # VIA Support
As of 1.3.1, the VIA tool does not support Keyhive/Sofle V2 out of the box.
- After flashing, in VIA make sure to Import Keymap, which is "sofle VIA keymap.json". This will alow VIA to recognize the updated layout and custom functions. VIA will not auto-recognize the keyboard with this firmware because of the necessary customization. See [keyhive_via](../keymaps/keyhive_via/readme.md) for details about configuring and using VIA.
- Go to Save+Load to Load Saved Layout. You can import my own layout "sofle VIA layout.json" or just use the Keymap tab to assign your own keys. Having another keyboard connected can be handy for doing this step.
- It is a good idea to Save Current Layout after you decide on your mapping.
# Compiling
Make example for this keyboard (after setting up your build environment): Make example for this keyboard (after setting up your build environment):
make sofle/keyhive:default make sofle/keyhive:default
Flashing example for this keyboard: ## Flashing
make sofle/keyhive:default:flash Flash using the correct command below (or use QMK Toolbox). These commands can be mixed if, for example, you have an Elite C on the left and a pro micro on the right.
Press reset button on he keyboard when asked. Press reset button on the keyboard when asked.
Disconnect the first half, connect the second one and repeat the process. Disconnect the first half, connect the second one and repeat the process.
# for Pro Micro-based builds
make sofle/keyhive:default:avrdude-split-left
make sofle/keyhive:default:avrdude-split-right
# for Elite C or DFU bootloader builds
make sofle/keyhive:default:dfu-split-left
make sofle/keyhive:default:dfu-split-right
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). 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).

View file

@ -14,7 +14,7 @@ CONSOLE_ENABLE = no # Console for debug
COMMAND_ENABLE = no # Commands for debug and configuration COMMAND_ENABLE = no # Commands for debug and configuration
NKRO_ENABLE = yes # Enable N-Key Rollover NKRO_ENABLE = yes # Enable N-Key Rollover
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
RGBLIGHT_ENABLE = yes # Enable keyboard RGB underglow RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
AUDIO_ENABLE = no # Audio output AUDIO_ENABLE = no # Audio output
ENCODER_ENABLE = yes ENCODER_ENABLE = yes
LTO_ENABLE = yes LTO_ENABLE = yes

View file

@ -0,0 +1,48 @@
/* Copyright 2020 Josef Adamcik
* Modification for VIA support and RGB underglow by Jens Bonk-Wiltfang
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
/* The way how "handedness" is decided (which half is which),
see https://docs.qmk.fm/#/feature_split_keyboard?id=setting-handedness
for more options.
*/
// More lighting options in quantum/rgblight/rgblight.h
#ifdef RGBLIGHT_ENABLE
# define RGBLIGHT_DEFAULT_MODE RGBLIGHT_MODE_RAINBOW_SWIRL+2
// Disabling some of these is a good way to save flash space.
# define RGBLIGHT_EFFECT_ALTERNATING // 108
# define RGBLIGHT_EFFECT_RGB_TEST // 158
# define RGBLIGHT_EFFECT_RAINBOW_MOOD // 160
# define RGBLIGHT_EFFECT_STATIC_GRADIENT // 168
# define RGBLIGHT_EFFECT_RAINBOW_SWIRL // 192
# define RGBLIGHT_EFFECT_BREATHING // 348
# define RGBLIGHT_EFFECT_KNIGHT // 336
# define RGBLIGHT_EFFECT_SNAKE // 406
# define RGBLIGHT_EFFECT_CHRISTMAS // 508
/*
#define RGBLIGHT_EFFECT_TWINKLE // 1156
*/
#endif
// Disabled to save space
#define NO_ACTION_ONESHOT // 332
#define NO_ACTION_MACRO // 0
#define NO_ACTION_FUNCTION // 0
#define DISABLE_LEADER // 0

View file

@ -0,0 +1,49 @@
/* Copyright 2020 Josef Adamcik
* Modification for VIA support and RGB underglow by Jens Bonk-Wiltfang
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//Setting up what encoder rotation does. If your encoder can be pressed as a button, that function can be set in Via.
#ifdef ENCODER_ENABLE
static uint8_t encoder_state[2] = {0};
//Use these keymap positions to specify the encoder functions on rotate.
static keypos_t encoder_ccw[2] = {{6, 3}, {6, 8}};
static keypos_t encoder_cw[2] = {{6, 1}, {6, 6}};
void encoder_action_unregister(void) {
for (int index = 0; index < 2; ++index) {
if (encoder_state[index]) {
keyevent_t encoder_event = (keyevent_t){.key = encoder_state[index] >> 1 ? encoder_cw[index] : encoder_ccw[index], .pressed = false, .time = (timer_read() | 1)};
encoder_state[index] = 0;
action_exec(encoder_event);
}
}
}
void encoder_action_register(uint8_t index, bool clockwise) {
keyevent_t encoder_event = (keyevent_t){.key = clockwise ? encoder_cw[index] : encoder_ccw[index], .pressed = true, .time = (timer_read() | 1)};
encoder_state[index] = (clockwise ^ 1) | (clockwise << 1);
action_exec(encoder_event);
}
void matrix_scan_user(void) { encoder_action_unregister(); }
bool encoder_update_user(uint8_t index, bool clockwise) {
encoder_action_register(index, clockwise);
return false;
};
#endif

View file

@ -0,0 +1,191 @@
/* Copyright 2020 Josef Adamcik
* Modification for VIA support and RGB underglow by Jens Bonk-Wiltfang
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include QMK_KEYBOARD_H
#include "oled.c"
#include "encoder.c"
// Base layer is the number of layers CYCLE selects from.
#define BASE_LAYERS 2
enum custom_keycodes {
PLACEHOLDER = SAFE_RANGE, // can always be here (4 bytes)
CYCLE // cycle through first BASE_LAYERS (62 bytes)
};
enum custom_layers {
_QWERTY,
_COLEMAK,
_LOWER,
_RAISE
};
// Extra keys are added for rotary encoder support in VIA
#define LAYOUT_via( \
LA1, LA2, LA3, LA4, LA5, LA6, RA6, RA5, RA4, RA3, RA2, RA1, \
LB1, LB2, LB3, LB4, LB5, LB6, LB7, RB7, RB6, RB5, RB4, RB3, RB2, RB1, \
LC1, LC2, LC3, LC4, LC5, LC6, LE1, RE6, RC6, RC5, RC4, RC3, RC2, RC1, \
LD1, LD2, LD3, LD4, LD5, LD6, LD7, RD7, RD6, RD5, RD4, RD3, RD2, RD1, \
LE2, LE3, LE4, LE5, LE6, RE5, RE4, RE3, RE2, RE1 \
) \
{ \
{ LA1, LA2, LA3, LA4, LA5, LA6, KC_NO }, \
{ LB1, LB2, LB3, LB4, LB5, LB6, LB7 }, \
{ LC1, LC2, LC3, LC4, LC5, LC6, KC_NO }, \
{ LD1, LD2, LD3, LD4, LD5, LD6, LD7 }, \
{ LE1, LE2, LE3, LE4, LE5, LE6, KC_NO }, \
{ RA1, RA2, RA3, RA4, RA5, RA6, KC_NO }, \
{ RB1, RB2, RB3, RB4, RB5, RB6, RB7 }, \
{ RC1, RC2, RC3, RC4, RC5, RC6, KC_NO }, \
{ RD1, RD2, RD3, RD4, RD5, RD6, RD7 }, \
{ RE1, RE2, RE3, RE4, RE5, RE6, KC_NO } \
}
//Default keymap. This can be changed in Via. Use oled.c to change beavior that Via cannot change.
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/*
* QWERTY
* ,-----------------------------------------. ,-----------------------------------------.
* | ` | 1 | 2 | 3 | 4 | 5 |-------. E ,-------| 6 | 7 | 8 | 9 | 0 | ` |
* |------+------+------+------+------+------| VolUp |< N >| Pg Up |------+------+------+------+------+------|
* | ESC | Q | W | E | R | T |-------. C ,-------| Y | U | I | O | P | Bspc |
* |------+------+------+------+------+------| Mute |< O >| |------+------+------+------+------+------|
* | Tab | A | S | D | F | G |-------. D ,-------| H | J | K | L | ; | ' |
* |------+------+------+------+------+------| VolDn |< E >| Pg Dn |------+------+------+------+------+------|
* |LShift| Z | X | C | V | B |-------| R |-------| N | M | , | . | / |RShift|
* `-----------------------------------------/ / \ \-----------------------------------------'
* | LGUI | LAlt | LCTR |LOWER | /Enter / \Space \ |RAISE | RCTR | RAlt | RGUI |
* | | | | |/ / \ \ | | | | |
* `-----------------------------------' '------''---------------------------'
*/
[_QWERTY] = LAYOUT_via(
KC_GRV, KC_1 , KC_2 , KC_3 , KC_4 , KC_5 , KC_6 , KC_7 , KC_8 , KC_9 , KC_0 , KC_GRV ,
KC_ESC, KC_Q , KC_W , KC_E , KC_R , KC_T , KC_VOLU, KC_PGUP, KC_Y , KC_U , KC_I , KC_O , KC_P , KC_BSPC,
KC_TAB, KC_A , KC_S , KC_D , KC_F , KC_G , KC_MUTE, KC_NO , KC_H , KC_J , KC_K , KC_L , KC_SCLN, KC_QUOT,
KC_LSFT, KC_Z , KC_X , KC_C , KC_V , KC_B , KC_VOLD, KC_PGDN, KC_N , KC_M , KC_COMM, KC_DOT , KC_SLSH, KC_RSFT,
KC_LGUI,KC_LALT ,KC_LCTRL,MO(_LOWER), KC_ENT , KC_SPC ,MO(_RAISE),KC_RCTRL, KC_RALT, KC_RGUI
),
/*
* COLEMAK - Vanilla
* ,-----------------------------------------. ,-----------------------------------------.
* | ` | 1 | 2 | 3 | 4 | 5 |-------. E ,-------| 6 | 7 | 8 | 9 | 0 | ` |
* |------+------+------+------+------+------| VolUp |< N >| Pg Up |------+------+------+------+------+------|
* | ESC | Q | W | F | P | G |-------. C ,-------| J | L | U | Y | ; | Bspc |
* |------+------+------+------+------+------| Mute |< O >| |------+------+------+------+------+------|
* | TAB | A | R | S | T | D |-------. D ,-------| H | N | E | I | O | ' |
* |------+------+------+------+------+------| VolDn |< E >| Pg Dn |------+------+------+------+------+------|
* |LShift| Z | X | C | V | B |-------| R |-------| K | M | , | . | / |RShift|
* `-----------------------------------------/ / \ \-----------------------------------------'
* | LGUI | LAlt | LCTR |LOWER | /Enter / \Space \ |RAISE | RCTR | RAlt | RGUI |
* | | | | |/ / \ \ | | | | |
* `-----------------------------------' '------''---------------------------'
*/
/*
[_COLEMAK] = LAYOUT_via(
KC_GRV , KC_1 , KC_2 , KC_3 , KC_4 , KC_5 , KC_6 , KC_7 , KC_8 , KC_9 , KC_0 , KC_GRV ,
KC_ESC , KC_Q , KC_W , KC_F , KC_P , KC_G , KC_VOLU, KC_PGUP, KC_J , KC_L , KC_U , KC_Y , KC_SCLN, KC_BSPC,
KC_TAB , KC_A , KC_R , KC_S , KC_T , KC_D , KC_MUTE, KC_NO , KC_H , KC_N , KC_E , KC_I , KC_O , KC_QUOT,
KC_LSFT, KC_Z , KC_X , KC_C , KC_V , KC_B , KC_VOLD, KC_PGDN, KC_N , KC_M , KC_COMM, KC_DOT, KC_SLSH, KC_RSFT,
KC_LGUI, KC_LALT,KC_LCTRL,MO(_LOWER), KC_ENT , KC_SPC ,MO(_RAISE),KC_RCTRL, KC_RALT, KC_RGUI
),
*/
/*
* COLEMAK-DH
* ,-----------------------------------------. ,-----------------------------------------.
* | ` | 1 | 2 | 3 | 4 | 5 |-------. E ,-------| 6 | 7 | 8 | 9 | 0 | ` |
* |------+------+------+------+------+------| VolUp |< N >| Pg Up |------+------+------+------+------+------|
* | ESC | Q | W | F | P | B |-------. C ,-------| J | L | U | Y | ; | Bspc |
* |------+------+------+------+------+------| Mute |< O >| |------+------+------+------+------+------|
* | TAB | A | R | S | T | G |-------. D ,-------| M | N | E | I | O | ' |
* |------+------+------+------+------+------| VolDn |< E >| Pg Dn |------+------+------+------+------+------|
* |LShift| Z | X | C | D | V |-------| R |-------| K | H | , | . | / |RShift|
* `-----------------------------------------/ / \ \-----------------------------------------'
* | LGUI | LAlt | LCTR |LOWER | /Enter / \Space \ |RAISE | RCTR | RAlt | RGUI |
* | | | | |/ / \ \ | | | | |
* `-----------------------------------' '------''---------------------------'
*/
[_COLEMAK] = LAYOUT_via(
KC_GRV , KC_1 , KC_2 , KC_3 , KC_4 , KC_5 , KC_6 , KC_7 , KC_8 , KC_9 , KC_0 , KC_GRV ,
KC_ESC , KC_Q , KC_W , KC_F , KC_P , KC_B , KC_VOLU, KC_PGUP, KC_J , KC_L , KC_U , KC_Y , KC_SCLN, KC_BSPC,
KC_TAB , KC_A , KC_R , KC_S , KC_T , KC_G , KC_MUTE, KC_NO , KC_M , KC_N , KC_E , KC_I , KC_O , KC_QUOT,
KC_LSFT, KC_Z , KC_X , KC_C , KC_D , KC_V , KC_VOLD, KC_PGDN, KC_K , KC_H , KC_COMM, KC_DOT, KC_SLSH, KC_RSFT,
KC_LGUI, KC_LALT,KC_LCTRL,MO(_LOWER), KC_ENT , KC_SPC ,MO(_RAISE),KC_RCTRL, KC_RALT, KC_RGUI
),
/* LOWER
* ,-----------------------------------------. ,-----------------------------------------.
* | | F1 | F2 | F3 | F4 | F5 |-------. E ,-------| F6 | F7 | F8 | F9 | F10 | F11 |
* |------+------+------+------+------+------| |< N >| |------+------+------+------+------+------|
* | ` | 1 | 2 | 3 | 4 | 5 |-------. C ,-------| 6 | 7 | 8 | 9 | 0 | F12 |
* |------+------+------+------+------+------| |< O >| |------+------+------+------+------+------|
* | Tab | ! | @ | # | $ | % |-------. D ,-------| ^ | & | * | ( | ) | | |
* |------+------+------+------+------+------| |< E >| |------+------+------+------+------+------|
* | Shift| = | - | + | { | } |-------| R |-------| [ | ] | ; | : | \ | |
* `-----------------------------------------/ / \ \-----------------------------------------'
* | LGUI | LAlt | LCTR |LOWER | /Enter / \Space \ |RAISE | RCTR | RAlt | RGUI |
* | | | | |/ / \ \ | | | | |
* `-----------------------------------' '------''---------------------------'
*/
[_LOWER] = LAYOUT_via(
_______, KC_F1 , KC_F2 , KC_F3 , KC_F4 , KC_F5 , KC_F6 , KC_F7 , KC_F8 , KC_F9 , KC_F10 , KC_F11 ,
KC_GRV , KC_1 , KC_2 , KC_3 , KC_4 , KC_5 , _______, _______, KC_6 , KC_7 , KC_8 , KC_9 , KC_0 , KC_F12 ,
_______, KC_EXLM, KC_AT , KC_HASH, KC_DLR , KC_PERC, _______, _______, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_PIPE,
_______, KC_EQL , KC_MINS, KC_PLUS, KC_LCBR, KC_RCBR, _______, _______, KC_LBRC, KC_RBRC, KC_SCLN, KC_COLN, KC_BSLS, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______
),
/* RAISE
* ,----------------------------------------. ,-----------------------------------------.
* |Cycle | | | | | |-------. E ,-------| | | | | | |
* |------+------+------+------+------+------| |< N >| |------+------+------+------+------+------|
* | Esc | Ins | Pscr | Menu | | |-------. C ,-------| | | Up | | DLine| Bspc |
* |------+------+------+------+------+------| |< O >| |------+------+------+------+------+------|
* | Tab | LAt | LCtl |LShift| | Caps |-------. D ,-------| | Left | Down | Rigth| Del | Bspc |
* |------+------+------+------+------+------| |< E >| |------+------+------+------+------+------|
* |Shift | Undo | Cut | Copy | Paste| |-------| R |-------| | LStr | | LEnd | | Shift|
* `-----------------------------------------/ / \ \-----------------------------------------'
* | LGUI | LAlt | LCTR |LOWER | /Enter / \Space \ |RAISE | RCTR | RAlt | RGUI |
* | | | | |/ / \ \ | | | | |
* `----------------------------------' '------''---------------------------'
*/
[_RAISE] = LAYOUT_via(
CYCLE, _______, _______, _______, _______ , _______, _______, _______, _______, _______, _______, _______,
_______, KC_INS , KC_PSCR, KC_APP , XXXXXXX , XXXXXXX, _______, _______, KC_PGUP, _______, KC_UP , _______, _______, KC_BSPC,
_______, KC_LALT, KC_LCTL, KC_LSFT, XXXXXXX , KC_CAPS, _______, _______, KC_PGDN, KC_LEFT, KC_DOWN, KC_RGHT, KC_DEL , KC_BSPC,
_______, KC_UNDO, KC_CUT , KC_COPY, KC_PASTE, XXXXXXX, _______, _______, XXXXXXX, _______, XXXXXXX, _______, XXXXXXX, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______
)
};
// Custom keycode handling.
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
// handling this once instead of in each keycode uses less program memory.
if ((keycode >= SAFE_RANGE) && !(record->event.pressed)) {
return false;
}
switch (keycode) {
case CYCLE:
set_single_persistent_default_layer((1+get_highest_layer(default_layer_state)) % BASE_LAYERS);
break;
}
// this uses less memory than returning in each case.
return keycode < SAFE_RANGE;
};

View file

@ -0,0 +1,85 @@
/* Copyright 2020 Josef Adamcik
* Modification for VIA support and RGB underglow by Jens Bonk-Wiltfang
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//Sets up what the OLED screens display.
#ifdef OLED_ENABLE
static void render_logo(void) {
static const char PROGMEM qmk_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(qmk_logo, false);
}
static void print_status_narrow(void) {
// Print current mode
oled_write_P(PSTR("\n\n"), false);
switch (get_highest_layer(default_layer_state)) {
case 0: // _QWERTY
oled_write_ln_P(PSTR("Qwrt\n"), false);
break;
case 1: // _COLEMAK
oled_write_ln_P(PSTR("Clmk\n"), false);
break;
default:
oled_write_P(PSTR("Mod"), false);
break;
}
oled_write_P(PSTR("\n\n"), false);
// Print current layer
oled_write_ln_P(PSTR("LAYER"), false);
switch (get_highest_layer(layer_state)) {
case 0: // _QWERTY
case 1: // _COLEMAK
oled_write_P(PSTR("Base\n"), false);
break;
case 2:
oled_write_P(PSTR("Lower"), false);
break;
case 3:
oled_write_P(PSTR("Raise"), false);
break;
default:
oled_write_ln_P(PSTR("Undef"), false);
}
oled_write_P(PSTR("\n\n"), false);
led_t led_usb_state = host_keyboard_led_state();
oled_write_ln_P(PSTR("CPSLK"), led_usb_state.caps_lock);
}
oled_rotation_t oled_init_user(oled_rotation_t rotation) {
if (is_keyboard_master()) {
return OLED_ROTATION_270;
}
return rotation;
}
bool oled_task_user(void) {
if (is_keyboard_master()) {
print_status_narrow();
} else {
render_logo();
}
return false;
}
#endif

View file

@ -0,0 +1,49 @@
# Only compatible with sofle/keyhive firmware which adds an extra column of keys for encoder mapping.
![SofleKeyboard version 2.1 RGB Keyhive](https://i.imgur.com/Oa6spvZ.png)
# Configuring VIA / Vial App
This firmware will not auto-recognize until [PR #1060](https://github.com/the-via/keyboards/pull/1060) is accepted to the VIA keyboard database. For now you must install the new layout:
1. Download [keyhive_sofle_rgb.json](https://raw.githubusercontent.com/the-via/keyboards/48372baae5ab451d752988121fa4f1dd47b2c1ce/src/sofle/keyhive_sofle_rgb.json).
2. In the VIA app, select `File > Import Keymap` from the menu.
3. Open the file you just downloaded.
**You'll have to do this every time you use VIA or Vial until the PR is accepted.**
# Using with VIA
* The default layouts should be loaded automatically.
* Layouts can be backed up in VIA in the SAVE+LOAD section.
* It is a good idea to Save Current Layout after you decide on your mapping.
# Custom Features:
### Rotary Encoder and VIA Features:
* Fully remappable. Left encoder controls volume up/down/mute. Right encoder PGUP/PGDOWN.
* Allows for live remapping of per-layer rotary encoder functions in VIA.
* VIA support with **keyhive_via** keymap.
# Compiling
Make example for this keyboard (after setting up your build environment):
make sofle/keyhive:keyhive_via
## Flashing
Flash using the correct command below (or use QMK Toolbox). These commands can be mixed if, for example, you have an Elite C on the left and a pro micro on the right.
Press reset button on the keyboard when asked.
Disconnect the first half, connect the second one and repeat the process.
# for Pro Micro-based builds
make sofle/keyhive:keyhive_via:avrdude-split-left
make sofle/keyhive:keyhive_via:avrdude-split-right
# for Elite C or DFU bootloader builds
make sofle/keyhive:keyhive_via:dfu-split-left
make sofle/keyhive:keyhive_via:dfu-split-right
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).

View file

@ -0,0 +1,2 @@
VIA_ENABLE = yes
RGBLIGHT_ENABLE = yes

View file

@ -58,7 +58,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* `-----------------------------------------/ / \ \-----------------------------------------' * `-----------------------------------------/ / \ \-----------------------------------------'
* | LGUI | LAlt | LCTR |LOWER | /Enter / \Space \ |RAISE | RCTR | RAlt | RGUI | * | LGUI | LAlt | LCTR |LOWER | /Enter / \Space \ |RAISE | RCTR | RAlt | RGUI |
* | | | | |/ / \ \ | | | | | * | | | | |/ / \ \ | | | | |
* `----------------------------------' '------''---------------------------' * `-----------------------------------' '------''---------------------------'
*/ */
[1] = LAYOUT( [1] = LAYOUT(
@ -97,7 +97,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* |------+------+------+------+------+------| |------+------+------+------+------+------| * |------+------+------+------+------+------| |------+------+------+------+------+------|
* | Tab | LAt | LCtl |LShift| | Caps |-------. ,-------| | Left | Down | Rigth| Del | Bspc | * | Tab | LAt | LCtl |LShift| | Caps |-------. ,-------| | Left | Down | Rigth| Del | Bspc |
* |------+------+------+------+------+------| MUTE | | |------+------+------+------+------+------| * |------+------+------+------+------+------| MUTE | | |------+------+------+------+------+------|
* |Shift | Undo | Cut | Copy | Paste| |-------| |-------| | LStr | | LEnd | | Shift| * |Shift | Undo | Cut | Copy | Paste| |--------| |-------| | LStr | | LEnd | | Shift|
* `-----------------------------------------/ / \ \-----------------------------------------' * `-----------------------------------------/ / \ \-----------------------------------------'
* | LGUI | LAlt | LCTR |LOWER | /Enter / \Space \ |RAISE | RCTR | RAlt | RGUI | * | LGUI | LAlt | LCTR |LOWER | /Enter / \Space \ |RAISE | RCTR | RAlt | RGUI |
* | | | | |/ / \ \ | | | | | * | | | | |/ / \ \ | | | | |