Compare commits
34
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6c069776fb | ||
|
|
586d1deb4e | ||
|
|
796b7733f5 | ||
|
|
9eb86d2069 | ||
|
|
a08ed5dc25 | ||
|
|
7e477e1aa8 | ||
|
|
3be9f9b9ad | ||
|
|
e0786e6118 | ||
|
|
9340579031 | ||
|
|
d43c712301 | ||
|
|
c75b52f94b | ||
|
|
3525a5f1a5 | ||
|
|
10a1447adc | ||
|
|
24a4a4da11 | ||
|
|
9aaebbcf54 | ||
|
|
081590f85d | ||
|
|
2db4682264 | ||
|
|
f256c49727 | ||
|
|
0247de4988 | ||
|
|
4139c97b22 | ||
|
|
917afe5f57 | ||
|
|
9e731bce1e | ||
|
|
3f10abc6fd | ||
|
|
4eba21a2fd | ||
|
|
15918db7ac | ||
|
|
eb5756f530 | ||
|
|
cd3e10ba13 | ||
|
|
083e4a701a | ||
|
|
ab6aa1838c | ||
|
|
270be1fa28 | ||
|
|
76e7ee4027 | ||
|
|
7310bdd780 | ||
|
|
a77fee7f04 | ||
|
|
e208dd64f3 |
No files matched your search
@@ -1,25 +1,35 @@
|
||||
# KMK: Clackety Keyboards Powered by Python
|
||||

|
||||
|
||||
|
||||
KMK is a feature-rich and beginner-friendly firmware for computer keyboards
|
||||
written and configured in
|
||||
[CircuitPython](https://github.com/adafruit/circuitpython). **KMK is currently
|
||||
in public beta, and transitioning to a new core, however should handle almost
|
||||
all workflows without major issues**.
|
||||
in public beta, however should handle most workflows without major issues**.
|
||||
|
||||
<!--
|
||||
@klardotsh 06 July 2021: commented for now because CDN builds have been broken
|
||||
for ages and folks are (reasonably) getting confused.
|
||||
|
||||
You can always find the latest releases on our CDN, in [compiled and
|
||||
optimized](https://cdn.kmkfw.io/kmk-latest.zip) and [raw, hackable text
|
||||
file](https://cdn.kmkfw.io/kmk-latest.unoptimized.zip) forms. These follow the
|
||||
`master` branch here on GitHub.
|
||||
-->
|
||||
|
||||
> If you need support with KMK or just want to say hi, find us in
|
||||
> [#kmkfw:klar.sh on Matrix](https://matrix.to/#/#kmkfw:klar.sh). This channel
|
||||
> is bridged to Discord
|
||||
> [here](https://discordapp.com/widget?id=493256121075761173&theme=dark) for
|
||||
> convenience.
|
||||
>
|
||||
> If you ask for help on chat or open a bug report, if possible please give us
|
||||
> your commit SHA, found by running `from kmk.consts import KMK_RELEASE;
|
||||
> print(KMK_RELEASE)` in the REPL on your controller.
|
||||
|
||||
## Features
|
||||
|
||||
@@ -42,28 +52,22 @@ file](https://cdn.kmkfw.io/kmk-latest.unoptimized.zip) forms. These follow the
|
||||
- Bluetooth HID and split keyboards. No more wires.
|
||||
|
||||
## Getting Started
|
||||
Our getting started guide can be found [here](https://github.com/KMKfw/docs/Getting_Started.md)
|
||||
|
||||
Our getting started guide can be found
|
||||
[here](https://github.com/KMKfw/kmk_firmware/blob/master/docs/Getting_Started.md)
|
||||
|
||||
## The KMK Team
|
||||
|
||||
KMK is primarily written and maintained by @klardotsh and @kdb424, but
|
||||
contributions are welcome from all, whether it's in the form of code,
|
||||
documentation, hardware designs, feature ideas, or anything else that comes to
|
||||
mind. KMK's contributors and other helpers are listed alphabetically by username
|
||||
below (we'll try to keep this up to date!):
|
||||
mind. A list of KMK's contributors can be found [on
|
||||
GitHub](https://github.com/KMKfw/kmk_firmware/graphs/contributors).
|
||||
|
||||
- [Dan Halbert (@dhalbert)](https://github.com/dhalbert)
|
||||
- [Elvis Pfützenreuter (@elvis-epx)](https://github.com/elvis-epx)
|
||||
- [Kyle Brown (@kdb424)](https://github.com/kdb424)
|
||||
- [Josh Klar (@klardotsh)](https://github.com/klardotsh)
|
||||
- [Limor Fried (@ladyada)](https://github.com/ladyada)
|
||||
- [Ryan Karpinski (@rk463345)](https://github.com/rk463345)
|
||||
- [@siddacious](https://github.com/siddacious)
|
||||
- [Scott Shawcroft (@tannewt)](https://github.com/tannewt)
|
||||
|
||||
> While Adafruit employees and affiliates are included in the above list and
|
||||
> their help has been crucial to KMK's success, KMK is not an official Adafruit
|
||||
> project, and the Core team is not compensated by Adafruit for its development.
|
||||
> While Adafruit employees and affiliates are occasionally found in the commit
|
||||
> log and their help has been crucial to KMK's success, KMK is not an official
|
||||
> Adafruit project, and the Core team is not compensated by Adafruit for its
|
||||
> development.
|
||||
|
||||
## Code Style
|
||||
|
||||
@@ -84,3 +88,10 @@ All documentation and hardware designs are licensed under the [Creative Commons
|
||||
Attribution-ShareAlike 4.0](https://creativecommons.org/licenses/by-sa/4.0/)
|
||||
license. Contributions to this repository must use these licenses unless
|
||||
otherwise agreed to by the Core team.
|
||||
|
||||
|
||||
## Stargazers over time
|
||||
|
||||
[](https://starchart.cc/KMKfw/kmk_firmware)
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
# Atreus62
|
||||
|
||||

|
||||
|
||||
Atreus62 is a 60% column staggered keyboard pinky stagger
|
||||
|
||||
kb.py is designed to work with the Teensy 4.1
|
||||
|
||||
Retailers (USA)
|
||||
[Atreus62](https://shop.profetkeyboards.com/product/atreus62-keyboard)
|
||||
|
||||
Extentions enabled by default
|
||||
- [Layers](https://github.com/KMKfw/kmk_firmware/tree/master/docs/layers.md) Need more keys than switches? Use layers.
|
||||
- [RGB](https://github.com/KMKfw/kmk_firmware/tree/master/docs/rgb.md) Light it up
|
||||
- [Encoder](https://github.com/KMKfw/kmk_firmware/tree/master/docs/encoder.md) Twist control for all the things
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import board
|
||||
|
||||
from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard
|
||||
from kmk.matrix import DiodeOrientation
|
||||
|
||||
# from kmk.matrix import intify_coordinate as ic
|
||||
|
||||
|
||||
class KMKKeyboard(_KMKKeyboard):
|
||||
col_pins = (
|
||||
board.D24,
|
||||
board.D25,
|
||||
board.D26,
|
||||
board.D27,
|
||||
board.D28,
|
||||
board.D29,
|
||||
board.D30,
|
||||
board.D31,
|
||||
board.D32,
|
||||
board.D33,
|
||||
board.D34,
|
||||
board.D35,
|
||||
)
|
||||
|
||||
row_pins = (board.D3, board.D4, board.D5, board.D6, board.D7, board.D8)
|
||||
|
||||
diode_orientation = DiodeOrientation.ROWS
|
||||
# diode_orientation = DiodeOrientation.COLUMNS
|
||||
@@ -0,0 +1,220 @@
|
||||
import board
|
||||
|
||||
from kb import KMKKeyboard
|
||||
|
||||
from kmk.handlers.sequences import send_string, simple_key_sequence
|
||||
from kmk.keys import KC
|
||||
from kmk.modules.encoder import EncoderHandler
|
||||
from kmk.modules.layers import Layers
|
||||
|
||||
# local_increment = None
|
||||
# local_decrement = None
|
||||
|
||||
keyboard = KMKKeyboard()
|
||||
|
||||
# custom keys used for encoder actions
|
||||
Zoom_in = KC.LCTRL(KC.EQUAL)
|
||||
Zoom_out = KC.LCTRL(KC.MINUS)
|
||||
|
||||
# standard filler keys
|
||||
_______ = KC.TRNS
|
||||
XXXXXXX = KC.NO
|
||||
|
||||
# for use in the encoder extension
|
||||
encoder_map = [
|
||||
[
|
||||
(
|
||||
KC.VOLU,
|
||||
KC.VOLD,
|
||||
2,
|
||||
), # Only 1 encoder is being used, so only one tuple per layer is required
|
||||
],
|
||||
[
|
||||
(Zoom_in, Zoom_out, 1),
|
||||
],
|
||||
[
|
||||
(_______, _______, 1), # no action taken by the encoder on this layer
|
||||
],
|
||||
]
|
||||
|
||||
layers_ext = Layers()
|
||||
|
||||
encoder_ext = EncoderHandler([board.D40], [board.D41], encoder_map)
|
||||
encoder_ext.encoders[0].is_inverted = True
|
||||
|
||||
keyboard.modules = [layers_ext, encoder_ext]
|
||||
|
||||
keyboard.tap_time = 250
|
||||
keyboard.debug_enabled = False
|
||||
|
||||
|
||||
# custom keys
|
||||
NEW = KC.LCTL(KC.N)
|
||||
NEW_DIR = KC.LCTL(KC.LSFT(KC.N))
|
||||
CAD = KC.LCTL(KC.LALT(KC.DEL))
|
||||
RES = KC.LCTL(KC.LSFT(KC.ESC))
|
||||
FE = KC.LGUI(KC.E)
|
||||
LT1_DEL = KC.LT(1, KC.DEL)
|
||||
LT2_ENT = KC.LT(2, KC.ENT)
|
||||
SAVE_AS = KC.LCTL(KC.LSFT(KC.S))
|
||||
PSCR = KC.LGUI(KC.PSCR)
|
||||
SNIP = simple_key_sequence(
|
||||
(
|
||||
KC.LGUI,
|
||||
KC.MACRO_SLEEP_MS(25),
|
||||
KC.S,
|
||||
KC.N,
|
||||
KC.I,
|
||||
KC.P,
|
||||
KC.MACRO_SLEEP_MS(25),
|
||||
KC.ENT,
|
||||
)
|
||||
)
|
||||
|
||||
# programming layer keys
|
||||
UINT = simple_key_sequence(
|
||||
(
|
||||
KC.U,
|
||||
KC.I,
|
||||
KC.N,
|
||||
KC.T,
|
||||
)
|
||||
)
|
||||
INT = simple_key_sequence(
|
||||
(
|
||||
KC.I,
|
||||
KC.N,
|
||||
KC.T,
|
||||
)
|
||||
)
|
||||
DOUBLE = simple_key_sequence(
|
||||
(
|
||||
KC.D,
|
||||
KC.O,
|
||||
KC.U,
|
||||
KC.B,
|
||||
KC.L,
|
||||
KC.E,
|
||||
)
|
||||
)
|
||||
BOOL = simple_key_sequence(
|
||||
(
|
||||
KC.B,
|
||||
KC.O,
|
||||
KC.O,
|
||||
KC.L,
|
||||
)
|
||||
)
|
||||
BYTE = simple_key_sequence(
|
||||
(
|
||||
KC.B,
|
||||
KC.Y,
|
||||
KC.T,
|
||||
KC.E,
|
||||
)
|
||||
)
|
||||
SBYTE = simple_key_sequence(
|
||||
(
|
||||
KC.S,
|
||||
KC.B,
|
||||
KC.Y,
|
||||
KC.T,
|
||||
KC.E,
|
||||
)
|
||||
)
|
||||
CHAR = simple_key_sequence(
|
||||
(
|
||||
KC.C,
|
||||
KC.H,
|
||||
KC.A,
|
||||
KC.R,
|
||||
)
|
||||
)
|
||||
GETSET = simple_key_sequence(
|
||||
(
|
||||
KC.LBRC,
|
||||
KC.SPC,
|
||||
KC.G,
|
||||
KC.E,
|
||||
KC.T,
|
||||
KC.SCLN,
|
||||
KC.SPC,
|
||||
KC.S,
|
||||
KC.E,
|
||||
KC.T,
|
||||
KC.SCLN,
|
||||
KC.SPC,
|
||||
KC.RBRC,
|
||||
)
|
||||
)
|
||||
PUBLIC = simple_key_sequence(
|
||||
(
|
||||
KC.P,
|
||||
KC.U,
|
||||
KC.B,
|
||||
KC.L,
|
||||
KC.I,
|
||||
KC.C,
|
||||
)
|
||||
)
|
||||
DEBUGWL = simple_key_sequence(
|
||||
(
|
||||
KC.LSFT(KC.D),
|
||||
KC.E,
|
||||
KC.B,
|
||||
KC.U,
|
||||
KC.G,
|
||||
KC.DOT,
|
||||
KC.LSFT(KC.W),
|
||||
KC.R,
|
||||
KC.I,
|
||||
KC.T,
|
||||
KC.E,
|
||||
KC.LSFT(KC.L),
|
||||
KC.I,
|
||||
KC.N,
|
||||
KC.E,
|
||||
KC.LSFT(KC.N9),
|
||||
)
|
||||
)
|
||||
PRINT = simple_key_sequence(
|
||||
(
|
||||
KC.P,
|
||||
KC.R,
|
||||
KC.I,
|
||||
KC.N,
|
||||
KC.T,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
# make keymap
|
||||
keyboard.keymap = [
|
||||
[ # qwerty
|
||||
KC.ESC, KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0, KC.MINS,
|
||||
KC.CAPS, KC.Q, KC.W, KC.E, KC.R, KC.T, KC.Y, KC.U, KC.I, KC.O, KC.P, KC.PSLS,
|
||||
KC.TAB, KC.A, KC.S, KC.D, KC.F, KC.G, KC.H, KC.J, KC.K, KC.L, KC.SCLN, KC.QUOT,
|
||||
KC.TRNS, KC.Z, KC.X, KC.C, KC.V, KC.B, KC.N, KC.M, KC.COMM, KC.DOT, KC.SLSH, FE,
|
||||
KC.BSPC, KC.DEL, KC.LALT, KC.LSFT, KC.LCTL, KC.BSPC, KC.SPC, KC.ENT, KC.RSFT, KC.RCTL, KC.ENT, KC.RGUI,
|
||||
XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC.MO(1), KC.MO(2), KC.MUTE, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
|
||||
],
|
||||
[ # navnum
|
||||
KC.TRNS, SAVE_AS, PSCR, SNIP, KC.LGUI, NEW_DIR, KC.PSLS, KC.RGUI, KC.NO, KC.NO, KC.NO, KC.MINS,
|
||||
KC.BSLS, KC.NO, KC.HOME, KC.UP, KC.END, NEW, KC.N5, KC.N6, KC.N7, KC.N8, KC.N9, KC.BSLS,
|
||||
KC.F2, KC.NO, KC.LEFT, KC.DOWN, KC.RGHT, KC.HASH, KC.N0, KC.N1, KC.N2, KC.N3, KC.N4, KC.QUOT,
|
||||
KC.LSFT, KC.NO, KC.NO, KC.NO, KC.TAB, KC.UNDS, KC.MINS, KC.PPLS, KC.MINS, KC.PAST, KC.PSLS, KC.LBRC,
|
||||
KC.BSPC, KC.NO, KC.NO, KC.NO, KC.NO, KC.TRNS, KC.SPC, KC.EQL, KC.N0, KC.DOT, KC.ENT, KC.RGUI,
|
||||
XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC.TRNS, KC.TRNS, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
|
||||
],
|
||||
[ # sym/prog
|
||||
KC.TRNS, KC.NO, KC.NO, KC.NO, KC.F2, KC.AMPR, PRINT, DEBUGWL, SAVE_AS, KC.NO, KC.NO, KC.NO,
|
||||
KC.BSLS, KC.NO, KC.NO, KC.LCBR, KC.RCBR, KC.AT, INT, GETSET, KC.UP, KC.NO, KC.NO, KC.NO,
|
||||
KC.TAB, KC.NO, KC.NO, KC.LPRN, KC.RPRN, KC.DLR, BOOL, KC.LEFT, KC.DOWN, KC.RGHT, KC.NO, KC.NO,
|
||||
KC.LSFT, KC.NO, KC.NO, KC.LBRC, KC.RBRC, KC.PERC, UINT, DOUBLE, KC.NO, KC.NO, KC.NO, KC.NO,
|
||||
KC.BSPC, KC.LGUI, KC.LALT, KC.LSFT, KC.LCTL, KC.DEL, KC.TRNS, PUBLIC, KC.RCTL, KC.RALT, KC.ENT, KC.RESET,
|
||||
XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC.TRNS, KC.TRNS, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
|
||||
],
|
||||
]
|
||||
|
||||
if __name__ == '__main__':
|
||||
keyboard.go()
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||

|
||||
|
||||
A split keyboard with a 3x6 collumnar stagger and 3 thumb keys.
|
||||
A split keyboard with a 3x6 columnar stagger and 3 thumb keys.
|
||||
|
||||
kb.py is designed to work with the nice!nano
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import board
|
||||
|
||||
from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard
|
||||
from kmk.matrix import DiodeOrientation
|
||||
from kmk.matrix import intify_coordinate as ic
|
||||
|
||||
|
||||
class KMKKeyboard(_KMKKeyboard):
|
||||
col_pins = (
|
||||
board.A3,
|
||||
board.A2,
|
||||
board.A1,
|
||||
board.A0,
|
||||
board.SCK,
|
||||
board.MISO,
|
||||
)
|
||||
row_pins = (board.D4, board.D5, board.D6, board.D7)
|
||||
diode_orientation = DiodeOrientation.COLUMNS
|
||||
data_pin = board.RX
|
||||
rgb_pixel_pin = board.D0
|
||||
i2c = board.I2C
|
||||
|
||||
coord_mapping = []
|
||||
coord_mapping.extend(ic(0, x) for x in range(12))
|
||||
coord_mapping.extend(ic(1, x) for x in range(12))
|
||||
coord_mapping.extend(ic(2, x) for x in range(12))
|
||||
|
||||
# And now, to handle R3, which at this point is down to just six keys
|
||||
coord_mapping.extend(ic(3, x) for x in range(3, 9))
|
||||
@@ -1,4 +1,4 @@
|
||||
from kb import KMKKeyboard, rgb_pixel_pin
|
||||
from kb import KMKKeyboard
|
||||
from kmk.extensions.rgb import RGB
|
||||
from kmk.keys import KC
|
||||
from kmk.modules.layers import Layers
|
||||
@@ -7,7 +7,7 @@ from kmk.modules.split import Split, SplitSide, SplitType
|
||||
keyboard = KMKKeyboard()
|
||||
|
||||
# Adding extensions
|
||||
rgb = RGB(pixel_pin=rgb_pixel_pin, num_pixels=27, val_limit=100, hue_default=190, sat_default=100, val_default=5)
|
||||
rgb = RGB(pixel_pin=keyboard.rgb_pixel_pin, num_pixels=27, val_limit=100, hue_default=190, sat_default=100, val_default=5)
|
||||
|
||||
# TODO Comment one of these on each side
|
||||
split_side = SplitSide.LEFT
|
||||
|
||||
+78
-55
@@ -1,67 +1,84 @@
|
||||
# Getting Started
|
||||
|
||||
## Microcontrollers
|
||||
KMK will run on most microcontrollers supported by
|
||||
[Circuitpython](https://circuitpython.org/downloads). Our recommended
|
||||
microcontrollers are found [here](Officially_Supported_Microcontrollers.md)
|
||||
|
||||
## Firmware
|
||||
### KMKPython
|
||||
KMKPython is a fork of Circuitpython, but with libraries for most extensions
|
||||
built in. This saves you from having to get them all and keep them updated
|
||||
yourself. There may be other features added in the future that are exclusive to
|
||||
KMKPython. For the nice!nano, this is highly recommended, and used in place of
|
||||
Circuitpython.
|
||||
Notable differences include
|
||||
- Built in libraries for bluetooth, RGB, and more
|
||||
- Saves space as builds are optimized for keyboards
|
||||
- Microcontrollers like the nice!nano will be able to access all features out of
|
||||
the box.
|
||||
> Life was like a box of chocolates. You never know what you're gonna get.
|
||||
|
||||
### Circuitpython
|
||||
Circuitpython can be installed by following this guide using the guide
|
||||
[here](https://learn.adafruit.com/welcome-to-circuitpython/installing-circuitpython).
|
||||
It's recommended to run the latest stable version that is at least 5.0 or higher.
|
||||
Beta versions may work, but expect limited support.
|
||||
#### Notable differences include
|
||||
- Supports more devices
|
||||
- Less built in libraries. If using RGB, bluetooth, and more, you will have to
|
||||
add these libraries yourself
|
||||
- Some devices such as the nice!nano don't have much free space, so not all
|
||||
features can be installed at the same time
|
||||
|
||||
## Getting KMK
|
||||
You can always find the latest releases on our CDN, in
|
||||
[compiled and optimized](https://cdn.kmkfw.io/kmk-latest.zip) and
|
||||
[raw, hackable text file](https://cdn.kmkfw.io/kmk-latest.unoptimized.zip)
|
||||
forms. These follow the `master` branch here on GitHub. Just get the KMK folder
|
||||
and drop this directly in the CIRCUITPYTHON directory (not in a sub folder).
|
||||
Make sure to extract the zip, and put the `kmk` folder on the root of the
|
||||
CIRCUITPY drive on the microcontroller
|
||||
KMK is a keyboard focused layer that sits on top of [CircuitPython](https://circuitpython.org/). As such, it should work with most [boards that support CircuitPython](https://circuitpython.org/downloads). It is best to use the last stable version (>5.0).
|
||||
Known working and recommended devices can be found [here](Officially_Supported_Microcontrollers.md)
|
||||
|
||||
## Turning a controller into a keyboard
|
||||
### Supported keyboards
|
||||
If your keyboard and microcontroller are officially supported, simply visit the
|
||||
page for your files, and dropping them on the root of the "flash drive". Those
|
||||
pages can be found [here](https://github.com/KMKfw/boards). You will need the
|
||||
`kb.py` and `main.py`. More advanced instructions can be found
|
||||
[here](config_and_keymap.md). If using Curcuitpython and NOT KMKPython, you will
|
||||
also need [boot.py](https://github.com/KMKfw/kmk_firmware/blob/master/boot.py)
|
||||
We are also providing a keyboard optimized version of CircuitPython (simplified to cope with memory limits of certain boards and with a selection of preinstalled relevant modules). If you're wondering why use KMKPython rather than barebone CircuitPython, we tried to compare both approaches [here](kmkpython_vs_circuitpython.md)
|
||||
|
||||
### Porting a keyboard
|
||||
If you are porting a board to KMK, check the page [here](porting_to_kmk.md).
|
||||
<br>
|
||||
|
||||
### Handwired Keyboard
|
||||
If you are doing a hand wire, check [here](handwiring.md)
|
||||
## TL;DR Quick start guide
|
||||
> To infinity and beyond!
|
||||
1. [Install CircuitPython on your board](https://learn.adafruit.com/welcome-to-circuitpython/installing-circuitpython). With most boards, it should be as easy as drag and dropping the firmware on the drive
|
||||
2. Get a [copy of KMK](https://github.com/KMKfw/kmk_firmware/archive/refs/heads/master.zip) from the master branch
|
||||
3. Unzip it and copy the KMK folder and the boot.py file at the root of the USB drive corresponding to your board (often appearing as CIRCUITPY)
|
||||
4. Create a new *code.py* or *main.py* file in the same root directory (same level as boot.py) with the example content hereunder:
|
||||
|
||||
## Additional features
|
||||
Want to have fun features such as RGB, split keyboards and more? Check out what
|
||||
extensions can do [here](extensions.md)
|
||||
|
||||
## Debugging
|
||||
Debugging help can be found [here](debugging.md)
|
||||
|
||||
***IMPORTANT:*** adapt the GP0 / GP1 pins to your specific board ! <br>
|
||||
|
||||
|
||||
```
|
||||
print("Starting")
|
||||
|
||||
import board
|
||||
|
||||
from kmk.kmk_keyboard import KMKKeyboard
|
||||
from kmk.keys import KC
|
||||
from kmk.matrix import DiodeOrientation
|
||||
|
||||
keyboard = KMKKeyboard()
|
||||
|
||||
keyboard.col_pins = (board.GP0,)
|
||||
keyboard.row_pins = (board.GP1,)
|
||||
keyboard.diode_orientation = DiodeOrientation.COLUMNS
|
||||
|
||||
keyboard.keymap = [
|
||||
[KC.A,]
|
||||
]
|
||||
|
||||
if __name__ == '__main__':
|
||||
keyboard.go()
|
||||
```
|
||||
|
||||
5. With a wire / paperclip / whatever, connect GPIO 0 & GPIO 1 together (or the pins you chose for your boards)
|
||||
|
||||
6. If it prints a "A" (or a "Q" or ... depending on your keyboard layout), you're done!
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
## Now that you're up and running, you may want to go further...
|
||||
> This is your last chance. After this, there is no turning back. You take the blue pill—the story ends, you wake up in your bed and believe whatever you want to believe. You take the red pill—you stay in Wonderland, and I show you how deep the rabbit hole goes. Remember: all I'm offering is the truth. Nothing more.
|
||||
|
||||
### You're extremely lucky and you have a fully supported keyboard
|
||||
If your keyboard and microcontroller are officially supported, simply visit the page for your files, and dropping them on the root of the "flash drive". Those pages can be found [here](https://github.com/KMKfw/boards). You will need the `kb.py` and `main.py`. More advanced instructions can be found [here](config_and_keymap.md).
|
||||
Please note that we recommend using [KMKPython](https://github.com/KMKfw/kmkpython) for these boards as it is optimized for them. If using Circuitpython and NOT KMKPython, you will also need [boot.py](https://github.com/KMKfw/kmk_firmware/blob/master/boot.py)
|
||||
|
||||
### You've got another, maybe DIY, board and want to customise KMK for it
|
||||
First, be sure to understand how your device work, and particularly its specific matrix configuration. You can have a look [here](http://pcbheaven.com/wikipages/How_Key_Matrices_Works/) or read the [guide](https://docs.qmk.fm/#/hand_wire) provided by the QMK team for handwired keyboards
|
||||
<br>Once you've got the gist of it:
|
||||
- You can have a look [here](config_and_keymap.md) and [here](keys.md) to start customizing your code.py / main.py file
|
||||
- There's a [reference](keycodes.md) of the available keycodes
|
||||
- [International](international.md) extension adds keys for non US layouts and [Media Keys](media_keys.md) adds keys for ... media
|
||||
|
||||
And to go even further:
|
||||
- [Sequences](sequences.md) are used for sending multiple keystrokes in a single action
|
||||
- [Layers](layers.md) can transform the whole way your keyboard is behaving with a single touch
|
||||
- [ModTap](modtap.md) allow you tu customize the way a key behaves wether it is tapped or hold, and [TapDance](tapdance.md) depending on the number of times it is pressed
|
||||
|
||||
Want to have fun features such as RGB, split keyboards and more? Check out what builtin [modules](modules.md) and [extensions](extensions.md) can do!
|
||||
You can also get ideas from the various [user examples](https://github.com/KMKfw/user_keymaps) that we provide and dig into our [documentation](https://github.com/KMKfw/kmk_firmware/tree/master/docs)
|
||||
|
||||
<br>
|
||||
|
||||
## Additional help and support
|
||||
> Roads? Where we're going we don't need roads.
|
||||
|
||||
In case you need it, debugging help can be found [here](debugging.md)
|
||||
|
||||
If you need support with KMK or just want to say hi, find us in
|
||||
[#kmkfw:klar.sh on Matrix](https://matrix.to/#/#kmkfw:klar.sh). This channel is
|
||||
bridged to Discord [here](https://discordapp.com/widget?id=493256121075761173&theme=dark)
|
||||
@@ -69,3 +86,9 @@ for convenience. If you ask for help on chat or open a bug report, if possible
|
||||
please give us your commit SHA, found by running
|
||||
`from kmk.consts import KMK_RELEASE; print(KMK_RELEASE)` in the REPL on your
|
||||
controller.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
File renamed without changes.
@@ -0,0 +1,58 @@
|
||||
# Encoder
|
||||
Add twist control to your keyboard! Volume, zoom, anything you want.
|
||||
|
||||
## Enabling the extension
|
||||
The constructor takes a minimun of 3 arguments: a list of pad_a pins, a list of pad_b pins,
|
||||
and an encoder_map. The encoder_map is modeled after the keymap and works the
|
||||
same way. It should have as many layers as your keymap, and use KC.NO keys for
|
||||
layers that you don't require any action. The encoder supports a velocity mode
|
||||
if you desire to make something for video or sound editing. The direction of
|
||||
increment/decrement can be changed to make sense for the direction the knob is
|
||||
turning by setting the is_inverted flag.
|
||||
|
||||
## Configuration
|
||||
|
||||
There is a complete example in the Atreus62 main.py
|
||||
|
||||
Create your special keys:
|
||||
```python
|
||||
Zoom_in = KC.LCTRL(KC.EQUAL)
|
||||
Zoom_out = KC.LCTRL(KC.MINUS)
|
||||
```
|
||||
Create the encoder_map.
|
||||
|
||||
Anatomy of an encoder_map tuple: (increment_key, decrement_key, keys presses per encoder click)
|
||||
|
||||
```python
|
||||
|
||||
# create the encoder map, modeled after the keymap
|
||||
encoder_map = [
|
||||
[
|
||||
# Only 1 encoder is being used, so only one tuple per layer is required
|
||||
# Increment key is volume up, decrement key is volume down, and sends 2
|
||||
# key presses for every "click" felt while turning the encoder.
|
||||
(KC.VOLU,KC.VOLD,2),
|
||||
[
|
||||
# only one key press sent per encoder click
|
||||
(Zoom_in, Zoom_out,1),
|
||||
],
|
||||
[
|
||||
# No action keys sent here, the resolution is a dummy number, to be
|
||||
# removed in the future.
|
||||
(_______,_______,1),#
|
||||
]
|
||||
]
|
||||
|
||||
# create the encoder instance, and pass in a list of pad a pins, a lsit of pad b
|
||||
# pins, and the encoder map created above
|
||||
encoder_ext = EncoderHandler([board.D40],[board.D41], encoder_map)
|
||||
|
||||
# if desired, you can flip the incrfement/decrement direction of the knob by
|
||||
# setting the is_inerted flag to True. If you turn the knob to the right and
|
||||
# the volume goes down, setting this flag will make it go up. It's default
|
||||
# setting is False
|
||||
encoder_ext.encoders[0].is_inverted = True
|
||||
|
||||
# Make sure to add the encoder_ext to the modules list
|
||||
keyboard.modules = [encoder_ext]
|
||||
```
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
# Handwire keyboards
|
||||
This guide will not talk about the physical wiring. Check out our
|
||||
[recommended microcontrollers](Offiially_Supported_Microcontrollers.md) and
|
||||
follow the amazing guide for that[here](https://docs.qmk.fm/#/hand_wire). That
|
||||
[recommended microcontrollers](Officially_Supported_Microcontrollers.md) and
|
||||
follow the amazing guide for that [here](https://docs.qmk.fm/#/hand_wire). That
|
||||
guide can be followed until you are setting up the firmware. After wiring the
|
||||
keyboard, you can refer to our porting guide [here](porting_to_kmk.md)
|
||||
@@ -0,0 +1,110 @@
|
||||
# はじめに
|
||||
> Life was like a box of chocolates. You never know what you're gonna get.
|
||||
|
||||
KMKは[CircuitPython](https://circuitpython.org/)の上に配置されるキーボード用の実装レイヤーです。
|
||||
そのため、[CircuitPythonをサポートするほとんどのボード](https://circuitpython.org/downloads)と互換性があります。
|
||||
|
||||
最新の安定したバージョンを使用することをおすすめします。(>5.0)
|
||||
使用可能やおすすめなデバイスは[こちら](Officially_Supported_Microcontrollers.md)から確認できます。
|
||||
|
||||
CircuitPythonの最適化バージョン(特定のボードの容量制限に対処した、プリインストールされた関連モジュールの選択が可能なバージョン)も提供しています。
|
||||
|
||||
なぜCircuitPythonよりKMKPythonを使用するか気になっていたら、両方を比較した[実績](kmkpython_vs_circuitpython.md)があります。
|
||||
|
||||
<br>
|
||||
|
||||
## TL;DR クイックスタートガイド
|
||||
> To infinity and beyond!
|
||||
|
||||
1. CircuitPythonをボードに[インストール](https://learn.adafruit.com/welcome-to-circuitpython/installing-circuitpython)する。
|
||||
|
||||
|
||||
2. マスターブランチから[KMKのコピー](https://github.com/KMKfw/kmk_firmware/archive/refs/heads/master.zip)を取得。
|
||||
|
||||
|
||||
3. ファイルを展開し、KMKフォルダーとboot.pyファイルをUSBドライブのルート(CIRCUITPYと表示されることが多い)にコピーする。
|
||||
|
||||
|
||||
4. 同じルートディレクトリー(boot.pyと同レベル)に新規で*code.py* または *main.py*のファイルを作成する。中身は以下の例とする。
|
||||
|
||||
***重要:*** GP0 / GP1 ピンを使用ボードに合わせて下さい!<br>
|
||||
|
||||
|
||||
```
|
||||
print("Starting")
|
||||
|
||||
import board
|
||||
|
||||
from kmk.kmk_keyboard import KMKKeyboard
|
||||
from kmk.keys import KC
|
||||
from kmk.matrix import DiodeOrientation
|
||||
|
||||
keyboard = KMKKeyboard()
|
||||
|
||||
keyboard.col_pins = (board.GP0,)
|
||||
keyboard.row_pins = (board.GP1,)
|
||||
keyboard.diode_orientation = DiodeOrientation.COLUMNS
|
||||
|
||||
keyboard.keymap = [
|
||||
[KC.A,]
|
||||
]
|
||||
|
||||
if __name__ == '__main__':
|
||||
keyboard.go()
|
||||
```
|
||||
|
||||
1. ワイヤーなどでGPIO 0とGPIO 1(またはほかに指定したピン)を接続する。
|
||||
|
||||
|
||||
2. "A"や"Q"(キーボードのレイアウトによって異なる)が表示されたら、完成!
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
## とりあえず一通り動くようになったので、もっとに先へ進みたい場合
|
||||
> This is your last chance. After this, there is no turning back. You take the blue pill—the story ends, you wake up in your bed and believe whatever you want to believe. You take the red pill—you stay in Wonderland, and I show you how deep the rabbit hole goes. Remember: all I'm offering is the truth. Nothing more.
|
||||
|
||||
### フルサポートされているキーボードを持っている場合
|
||||
あなたのキーボードとマイコンが正式にサポートされている場合、[こちらのページ](https://github.com/KMKfw/boards)から`kb.py` と `main.py`を"flash drive"のルートに落とす必要があります。より高度な手順は[こちら](config_and_keymap.md)から確認できます。
|
||||
|
||||
このボードに最適化されているため、 [KMKPython](https://github.com/KMKfw/kmkpython) の使用を推奨します。
|
||||
|
||||
Circuitpythonを使用する場合、 [boot.py](https://github.com/KMKfw/kmk_firmware/blob/master/boot.py)も必要になります。
|
||||
|
||||
### ほかに自作ボードなどを持っていて、カスタマイズされたKMKを導入したい場合
|
||||
|
||||
最初にデバイスの動作や具体的なマトリックス構成についてしっかり理解してください。
|
||||
QMKチームが提供している手配線キーボード用の[ガイド](https://docs.qmk.fm/#/hand_wire)と[ドキュメント](http://pcbheaven.com/wikipages/How_Key_Matrices_Works/) を確認できます。
|
||||
|
||||
<br>要旨をつかめてきたら:
|
||||
- [ここ](config_and_keymap.md) と [ここ](keys.md)を見て、code.py / main.py ファイルをカスタイマイズできます。
|
||||
|
||||
- 使用可能なキーコードの[リファレンス](keycodes.md)があります。
|
||||
|
||||
- [インターナショナル](international.md)は、US配列以外のキーボードにキーを追加する拡張機能で、[メディアキー](media_keys.md)は・・・メディアにキーを追加する拡張機能です。
|
||||
|
||||
さらに先へ進むと:
|
||||
- [シーケンス](sequences.md) 一つのアクションで複数のキーストロークを送信するために使用します。
|
||||
- [レイヤー](layers.md)でタッチ一つでキーボードの全体の動きを変えることができます。
|
||||
|
||||
- [モドタップ](modtap.md) でキーの押し/長押しの動作を設定し、何回押されたかによって[タップダンス](tapdance.md)を設定します。
|
||||
|
||||
RGBや分裂型などの機能を楽しめたい場合は、ビルトイン[モジュール](modules.md)と[拡張機能](extensions.md)を見てみてください!
|
||||
|
||||
私たちが提供する、いろんな [ユーザー事例](https://github.com/KMKfw/user_keymaps)や[ドキュメント](https://github.com/KMKfw/kmk_firmware/tree/master/docs)からアイデアを得ることもできます。
|
||||
|
||||
<br>
|
||||
|
||||
## ヘルプ/サポート
|
||||
> Roads? Where we're going we don't need roads.
|
||||
|
||||
デバッグについてのヘルプが必要な場合は[こちら](debugging.md)。
|
||||
|
||||
KMKについてサポートが必要な場合や、コミュニケーションをとりたい場合は[こちら](https://matrix.to/#/#kmkfw:klar.sh)。
|
||||
このチャネルは[Discord](https://discordapp.com/widget?id=493256121075761173&theme=dark) からも見ることができます。
|
||||
|
||||
チャットやバグ報告などでヘルプを求める場合、可能な限り、コントローラーのREPLに`from kmk.consts import KMK_RELEASE; print(KMK_RELEASE)`を実行することによって表示されるコミットSHAを記載してください。
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -165,6 +165,31 @@
|
||||
|`KC.RIGHT_ANGLE_BRACKET`|`KC.RABK`, `KC.GT` |`>` |
|
||||
|`KC.QUESTION` |`KC.QUES` |`?` |
|
||||
|
||||
## [International Keys]
|
||||
|
||||
|Key |Aliases |Description |
|
||||
|------------------------|------------------------------|-----------------------|
|
||||
|`KC.NONUS_HASH` |`KC.NUHS` |ISO Right of LSHIFT |
|
||||
|`KC.NONUS_BSLASH` |`KC.NUBS` |ISO Left of Return |
|
||||
|`KC.APPLICATION` |`KC.APP`,`KC.SEL`,`KC.WINMENU`|Menu Key (Near RCTRL) |
|
||||
|`KC.INT1` |`KC.RO` | |
|
||||
|`KC.INT2` |`KC.KANA` | |
|
||||
|`KC.INT3` |`KC.JYEN` | |
|
||||
|`KC.INT4` |`KC.HENK` | |
|
||||
|`KC.INT5` |`KC.MHEN` | |
|
||||
|`KC.INT6` | | |
|
||||
|`KC.INT7` | | |
|
||||
|`KC.INT8` | | |
|
||||
|`KC.INT9` | | |
|
||||
|`KC.LANG1` |`HAEN` | |
|
||||
|`KC.LANG2` |`HAEJ` | |
|
||||
|`KC.LANG3` | | |
|
||||
|`KC.LANG4` | | |
|
||||
|`KC.LANG5` | | |
|
||||
|`KC.LANG6` | | |
|
||||
|`KC.LANG7` | | |
|
||||
|`KC.LANG8` | | |
|
||||
|`KC.LANG9` | | |
|
||||
|
||||
## [Internal Keys]
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
## Firmware of choice
|
||||
### KMKPython
|
||||
KMKPython is a fork of Circuitpython, but with libraries for most extensions
|
||||
built in. This saves you from having to get them all and keep them updated
|
||||
yourself. There may be other features added in the future that are exclusive to
|
||||
KMKPython. For the nice!nano, this is highly recommended, and used in place of
|
||||
Circuitpython.
|
||||
Notable differences include
|
||||
- Built in libraries for bluetooth, RGB, and more
|
||||
- Saves space as builds are optimized for keyboards
|
||||
- Microcontrollers like the nice!nano will be able to access all features out of
|
||||
the box.
|
||||
|
||||
### Circuitpython
|
||||
Circuitpython can be installed by following this guide using the guide
|
||||
[here](https://learn.adafruit.com/welcome-to-circuitpython/installing-circuitpython).
|
||||
It's recommended to run the latest stable version that is at least 5.0 or higher.
|
||||
Beta versions may work, but expect limited support.
|
||||
#### Notable differences include
|
||||
- Supports more devices
|
||||
- Less built in libraries. If using RGB, bluetooth, and more, you will have to
|
||||
add these libraries yourself
|
||||
- Some devices such as the nice!nano don't have much free space, so not all
|
||||
features can be installed at the same time
|
||||
@@ -0,0 +1,140 @@
|
||||
# Começando
|
||||
> A vida era como uma caixa de chocolates. Você nunca saberia o que iria
|
||||
> encontrar.
|
||||
|
||||
KMK é uma camada focada em teclados que assenta-se em cima de
|
||||
[CircuitPython](https://circuitpython.org/). Como tal, ela deve funcionar com a
|
||||
maior parte das [placas que suportam
|
||||
CircuitPython](https://circuitpython.org/downloads). É melhor usar a última
|
||||
versão estável (>5.0). Dispositivos funcionais e recomendados podem ser
|
||||
encontrados [aqui](Officially_Supported_Microcontrollers.md)
|
||||
|
||||
Também fornecemos uma versão de CircuitPython otimizada para teclados
|
||||
(simplificada para lidar com os limites de certas placas e com a seleção dos
|
||||
módulos relevantes pré-instalados). Se você estiver se perguntando por que usar
|
||||
KMKPython em vez do CircuitPython cru, tentamos comparar ambas as abordagens
|
||||
[aqui](kmkpython_vs_circuitpython.md)
|
||||
|
||||
<br>
|
||||
|
||||
## Guia Rápido
|
||||
> Ao Infinito e Além!
|
||||
|
||||
1. [Installe CircuitPython na tua
|
||||
placa](https://learn.adafruit.com/welcome-to-circuitpython/installing-circuitpython).
|
||||
Com a maioria das placas, deve ser algo tão fácil quanto copiar e colar o
|
||||
firmware no drive.
|
||||
2. Obtenha uma [cópia do
|
||||
KMK](https://github.com/KMKfw/kmk_firmware/archive/refs/heads/master.zip) a
|
||||
partir do ramo master.
|
||||
3. Descompacte e cole o diretório KMK e o arquivo boot.py na raiz do drive USB
|
||||
correspondente à tua placa (geralmente aparecendo como CIRCUITPY).
|
||||
4. Crie um novo arquivo *code.py* ou *main.py* no mesmo diretório raiz (no
|
||||
mesmo nível de boot.py) com o exemplo contido abaixo:
|
||||
|
||||
***IMPORTANTE:*** adapte os pinos GP0 / GP1 para a tua placa específica! <br>
|
||||
|
||||
```
|
||||
print("Starting")
|
||||
|
||||
import board
|
||||
|
||||
from kmk.kmk_keyboard import KMKKeyboard
|
||||
from kmk.keys import KC
|
||||
from kmk.matrix import DiodeOrientation
|
||||
|
||||
keyboard = KMKKeyboard()
|
||||
|
||||
keyboard.col_pins = (board.GP0,)
|
||||
keyboard.row_pins = (board.GP1,)
|
||||
keyboard.diode_orientation = DiodeOrientation.COLUMNS
|
||||
|
||||
keyboard.keymap = [
|
||||
[KC.A,]
|
||||
]
|
||||
|
||||
if __name__ == '__main__':
|
||||
keyboard.go()
|
||||
```
|
||||
|
||||
5. Usando um fio, um clipe de papel ou o que seja, conecte o GPIO 0 e o GPIO 1
|
||||
(ou os pinos que você escolheu para tua placa).
|
||||
|
||||
6. Se ela imprimir um "A" (ou um "Q" ou o que depender do teu layout de
|
||||
teclado), você conseguiu!
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
## Agora que tudo está no seu lugar, você pode querer ir além...
|
||||
|
||||
> Esta é tua última chance. Após isso Esta é sua última chance. Depois não há
|
||||
> como voltar. Se tomar a pílula azul a história acaba, e você acordará na sua
|
||||
> cama acreditando no que quiser. Se tomar a pílula vermelha ficará no País das
|
||||
> Maravilhas e eu te mostrarei até onde vai a toca do coelho. Lembre-se: tudo o
|
||||
> que estou te oferecendo é a verdade. Nada mais.
|
||||
|
||||
### Você é extremamente sortudo e tem um teclado totalmente suportado
|
||||
|
||||
Se seu teclado e micro-controlador são suportados oficialmente, simplesmente
|
||||
visite a webpage com os seus arquivos e coloque-os na raiz do "flash drive".
|
||||
Estas webpages podem ser vistas [aqui](https://github.com/KMKfw/boards). Você
|
||||
precisará dos arquivos `kb.py` e `main.py`. Instruções mais avançadas podem ser
|
||||
vistas [aqui*](config_and_keymap.md).
|
||||
|
||||
Note que recomendamos utilizar [KMKPython](https://github.com/KMKfw/kmkpython)
|
||||
para essas placas pois ele é otimizado para elas. Se você usar o Circuitpython
|
||||
em vez do KMKPython, você também vai precisar do
|
||||
[boot.py](https://github.com/KMKfw/kmk_firmware/blob/master/boot.py).
|
||||
|
||||
### Você obteve outro teclado, possivelmente artesanal, e quer customizar o KMK para ele
|
||||
|
||||
Primeiro, certifique-se de entender como o seu teclado funciona, e em particular
|
||||
sua configuração matricial específica. Você pode observar
|
||||
[aqui](http://pcbheaven.com/wikipages/How_Key_Matrices_Works/) ou ler o
|
||||
[guia](https://docs.qmk.fm/#/hand_wire) feito pelo time da QMK para teclados
|
||||
artesanais.
|
||||
|
||||
<br>Uma vez que você compreendeu a essência da coisa:
|
||||
- Você pode dar uma olhada [aqui*](config_and_keymap.md) e [aqui*](keys.md) para
|
||||
começar a customizar seu arquivo code.py / main.py.
|
||||
- Eis uma [referência*](keycodes.md) dos códigos de teclas (*keycodes*)
|
||||
disponíveis.
|
||||
- A extensão [internacional](international.md) acrescenta teclas para layouts
|
||||
não-americanos, e as [teclas de mídia](media_keys.md) acrecentam teclas
|
||||
para... mídia.
|
||||
|
||||
E para ir mais além:
|
||||
|
||||
- [Sequências*](sequences.md) são usadas para enviar múltiplas teclas em uma ação
|
||||
só;
|
||||
- [Camadas*](layers.md) podem transformar totalmente como seu teclado age com um
|
||||
simples toque.
|
||||
- [ModTap*](modtap.md) te permite customizar a maneira que uma tecla age quando é
|
||||
pressionada ou "segurada"; e o
|
||||
- [TapDance*](tapdance.md) dependendo do número de vezes que ela é pressionada.
|
||||
|
||||
Você quer extensões divertidas como RGB, teclados divididos ao meio e mais?
|
||||
Confira o que os [módulos*](modules.md) e [extensões*](extensions.md) podem
|
||||
fazer!
|
||||
|
||||
Você também pode obter ideias dos vários [exemplos de
|
||||
usuários](https://github.com/KMKfw/user_keymaps) que fornecemos e fuce nossa
|
||||
[documentação](https://github.com/KMKfw/kmk_firmware/tree/master/docs).
|
||||
|
||||
<br>
|
||||
|
||||
## Ajuda e Suporte Adicionais
|
||||
> Roads? Where we're going we don't need roads.
|
||||
|
||||
Caso precise, ajuda para depuração pode ser encontrada [aqui](debugging.md).
|
||||
|
||||
Se você precisa de suporte com o KMK ou quer somente dizer oi, encontre-nos no
|
||||
canal [#kmkfw:klar.sh no Matrix](https://matrix.to/#/#kmkfw:klar.sh). Este canal
|
||||
tem uma ponte no Discord
|
||||
[aqui](https://discordapp.com/widget?id=493256121075761173&theme=dark) por
|
||||
conveniência. Se você precisa de ajuda ou pretende abrir um bug report, se
|
||||
possível forneça o hash SHA do *commit* utilizado, o qual pode ser obtido
|
||||
executando este comando no REPL de seu controlador:
|
||||
|
||||
`from kmk.consts import KMK_RELEASE; print(KMK_RELEASE)`
|
||||
@@ -0,0 +1,72 @@
|
||||
# Micro-Controladores Oficialmente Suportados
|
||||
|
||||
Enquanto a maioria dos dispositivos com Circuitpython são muito bons para
|
||||
teclados artesanais, amaioria dos teclados é projetada para aceitar um Pro
|
||||
Micro. As placas listadas abaixo ou são, ou podem ser adaptadas para essa
|
||||
pinagem a fim de usar teclados comuns já presentes no mercado.
|
||||
|
||||
## Nice!Nano
|
||||
|
||||
Características:
|
||||
- Pinagem Pro Micro
|
||||
- Suporte a USB HID e Bluetooth
|
||||
- Pode ser usado para teclados divididos Bluetooth sem fio
|
||||
- Suporte a bateria, incluindo carga
|
||||
|
||||
Desvantagens:
|
||||
- 25 dólares por micro-controladores na maioria das revendedoras
|
||||
|
||||
Varejistas comund:
|
||||
- [Boardsource](https://boardsource.xyz/store/5f4a1733bbaa5c635b83ed67)
|
||||
- [NiceKeyboards](https://nicekeyboards.com/collections/group-buy/products/nice-nano-v1-0).
|
||||
|
||||
## ItsyBitsy M4 Express
|
||||
|
||||
Características:
|
||||
- Preços acessíveis a partir de 15 dólares
|
||||
- Pode rodar a maior parte das vantagens do KMK, incluindo RGB
|
||||
|
||||
Desvantagens:
|
||||
- Precisa de adaptadir para funcionar com a pinagem do Pro Micro. O adaptador
|
||||
pode ser encontrado
|
||||
[AQUI](https://github.com/KMKfw/kmk_firmware/tree/master/hardware)
|
||||
|
||||
Varejistas Comuns:
|
||||
- [Adafruit](https://www.adafruit.com/product/3800)
|
||||
|
||||
## RP2040
|
||||
|
||||
Características:
|
||||
- Preço bastante acessível
|
||||
- Bastante poderosa dado o preço
|
||||
|
||||
Desvantagens:
|
||||
- Pouco suporte para kits de teclado
|
||||
|
||||
Varejistas comuns:
|
||||
- [Adafruit](https://www.adafruit.com/pico?src=raspberrypi)
|
||||
- [Sparkfun](https://www.sparkfun.com/products/17829?src=raspberrypi)
|
||||
|
||||
## Adafruit ItsyBitsy nRF52840 Express
|
||||
|
||||
Características:
|
||||
- Suporte a USB HID e Bluetooth
|
||||
- Mais acessível que o Nice!Nano, apenas 18 dólares
|
||||
|
||||
Desvantagens:
|
||||
- Precisa de adaptador para funcionar com teclados de pinagem Pro Micro pinout
|
||||
keyboards. O adaptador pode ser encontrado
|
||||
[AQUI](https://github.com/KMKfw/kmk_firmware/tree/master/hardware)
|
||||
- O suporte à bateria precisa de uma placa adicional encontrada
|
||||
[AQUI](https://www.adafruit.com/product/2124)
|
||||
|
||||
Varejistas comuns:
|
||||
- [Adafruit](https://www.adafruit.com/product/4481)
|
||||
|
||||
## Outros Micro-Controladores
|
||||
|
||||
O mínimo que você vai precisar:
|
||||
|
||||
- CircuitPython/KMKpython
|
||||
- 256KB de armazenamento flash
|
||||
- HID sobre USB e/ou Bluetooth.
|
||||
@@ -0,0 +1,31 @@
|
||||
## Comparação de Firmware
|
||||
|
||||
### KMKPython
|
||||
|
||||
KMKPython é um *fork* do Circuitpython, mas com bibliotecas para a maior parte
|
||||
das extensões já embutidas. Isto te poupa de ter que reuni-las e atualizá-las
|
||||
manualmente. Pode haver outras características adicionadas no futuro exclusivas
|
||||
para o KMKPython. Para o nice!nano, o KMKPython é altamente recomendado e usado
|
||||
em lugar do Circuitpython.
|
||||
|
||||
#### Diferenças Notáveis
|
||||
|
||||
- Bibliotecas embutidas para Bluetooth, RGB etc.
|
||||
- Economiza espaço, pois os binários gerados são otimizados para teclados.
|
||||
- micro-controladores como o nice!nano poderão acessar todas as vantagens
|
||||
diretamente.
|
||||
|
||||
### Circuitpython
|
||||
|
||||
Circuitpython pode ser instalado seguindo [este
|
||||
guia](https://learn.adafruit.com/welcome-to-circuitpython/installing-circuitpython).
|
||||
É recomendável utilizar a versão mais recente, 5.0 ou superior. Versões beta
|
||||
podem funcionar, mas espere suporte limitado.
|
||||
|
||||
#### Diferenças Notáveis
|
||||
|
||||
- Suporta mais dispositivos.
|
||||
- Menos bibliotecas embutidas. Se precisar de RGB, Bluetooth e mais, você terá
|
||||
que adicionar estas bibliotecas manualmente.
|
||||
- Alguns dispositivos como o nice!nano não dispõem de muito espaço livre, então
|
||||
nem todas as vantagens podem ser instaladas ao mesmo tempo.
|
||||
+273
-405
@@ -10,6 +10,8 @@ from kmk.key_validators import (
|
||||
)
|
||||
from kmk.types import AttrDict, UnicodeModeKeyMeta
|
||||
|
||||
DEBUG_OUTPUT = False
|
||||
|
||||
FIRST_KMK_INTERNAL_KEY = const(1000)
|
||||
NEXT_AVAILABLE_KEY = 1000
|
||||
|
||||
@@ -17,416 +19,85 @@ KEY_SIMPLE = const(0)
|
||||
KEY_MODIFIER = const(1)
|
||||
KEY_CONSUMER = const(2)
|
||||
|
||||
ALL_ALPHAS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
ALL_NUMBERS = '1234567890'
|
||||
# since KC.1 isn't valid Python, alias to KC.N1
|
||||
ALL_NUMBER_ALIASES = tuple(f'N{x}' for x in ALL_NUMBERS)
|
||||
|
||||
|
||||
class InfiniteLoopDetected(Exception):
|
||||
pass
|
||||
|
||||
|
||||
# this is a bit of an FP style thing - combining a pipe operator a-la F# with
|
||||
# a bootleg Maybe monad to clean up these make_key sequences
|
||||
def left_pipe_until_some(candidate, functor, *args_iter):
|
||||
for args in args_iter:
|
||||
result = functor(candidate, *args)
|
||||
if result is not None:
|
||||
return result
|
||||
|
||||
|
||||
def first_truthy(candidate, *funcs):
|
||||
for func in funcs:
|
||||
result = func(candidate)
|
||||
if result is not None:
|
||||
return result
|
||||
|
||||
|
||||
def maybe_make_mod_key(candidate, code, names):
|
||||
if candidate in names:
|
||||
return make_mod_key(code=code, names=names)
|
||||
|
||||
|
||||
def maybe_make_key(candidate, code, names):
|
||||
if candidate in names:
|
||||
return make_key(code=code, names=names)
|
||||
|
||||
|
||||
def maybe_make_shifted_key(candidate, target_name, names):
|
||||
if candidate in names:
|
||||
return make_shifted_key(target_name=target_name, names=names)
|
||||
|
||||
|
||||
def maybe_make_consumer_key(candidate, code, names):
|
||||
if candidate in names:
|
||||
return make_consumer_key(code=code, names=names)
|
||||
|
||||
|
||||
class KeyAttrDict(AttrDict):
|
||||
def __getattr__(self, key):
|
||||
def __getattr__(self, key, depth=0):
|
||||
if depth > 1:
|
||||
raise InfiniteLoopDetected()
|
||||
|
||||
try:
|
||||
return super(KeyAttrDict, self).__getattr__(key)
|
||||
except Exception:
|
||||
pass
|
||||
# Modifiers
|
||||
if key in ('LEFT_CONTROL', 'LCTRL', 'LCTL'):
|
||||
make_mod_key(code=0x01, names=('LEFT_CONTROL', 'LCTRL', 'LCTL'))
|
||||
elif key in ('LEFT_SHIFT', 'LSHIFT', 'LSFT'):
|
||||
make_mod_key(code=0x02, names=('LEFT_SHIFT', 'LSHIFT', 'LSFT'))
|
||||
elif key in ('LEFT_ALT', 'LALT'):
|
||||
make_mod_key(code=0x04, names=('LEFT_ALT', 'LALT'))
|
||||
elif key in ('LEFT_SUPER', 'LGUI', 'LCMD', 'LWIN'):
|
||||
make_mod_key(code=0x08, names=('LEFT_SUPER', 'LGUI', 'LCMD', 'LWIN'))
|
||||
elif key in ('RIGHT_CONTROL', 'RCTRL', 'RCTL'):
|
||||
make_mod_key(code=0x10, names=('RIGHT_CONTROL', 'RCTRL', 'RCTL'))
|
||||
elif key in ('RIGHT_SHIFT', 'RSHIFT', 'RSFT'):
|
||||
make_mod_key(code=0x20, names=('RIGHT_SHIFT', 'RSHIFT', 'RSFT'))
|
||||
elif key in ('RIGHT_ALT', 'RALT'):
|
||||
make_mod_key(code=0x40, names=('RIGHT_ALT', 'RALT'))
|
||||
elif key in ('RIGHT_SUPER', 'RGUI', 'RCMD', 'RWIN'):
|
||||
make_mod_key(code=0x80, names=('RIGHT_SUPER', 'RGUI', 'RCMD', 'RWIN'))
|
||||
# MEH = LCTL | LALT | LSFT# MEH = LCTL |
|
||||
elif key in ('MEH',):
|
||||
make_mod_key(code=0x07, names=('MEH',))
|
||||
# HYPR = LCTL | LALT | LSFT | LGUI
|
||||
elif key in ('HYPER', 'HYPR'):
|
||||
make_mod_key(code=0x0F, names=('HYPER', 'HYPR'))
|
||||
|
||||
# Basic ASCII letters
|
||||
elif key in ('A',):
|
||||
make_key(code=4, names=('A',))
|
||||
elif key in ('B',):
|
||||
make_key(code=5, names=('B',))
|
||||
elif key in ('C',):
|
||||
make_key(code=6, names=('C',))
|
||||
elif key in ('D',):
|
||||
make_key(code=7, names=('D',))
|
||||
elif key in ('E',):
|
||||
make_key(code=8, names=('E',))
|
||||
elif key in ('F',):
|
||||
make_key(code=9, names=('F',))
|
||||
elif key in ('G',):
|
||||
make_key(code=10, names=('G',))
|
||||
elif key in ('H',):
|
||||
make_key(code=11, names=('H',))
|
||||
elif key in ('I',):
|
||||
make_key(code=12, names=('I',))
|
||||
elif key in ('J',):
|
||||
make_key(code=13, names=('J',))
|
||||
elif key in ('K',):
|
||||
make_key(code=14, names=('K',))
|
||||
elif key in ('L',):
|
||||
make_key(code=15, names=('L',))
|
||||
elif key in ('M',):
|
||||
make_key(code=16, names=('M',))
|
||||
elif key in ('N',):
|
||||
make_key(code=17, names=('N',))
|
||||
elif key in ('O',):
|
||||
make_key(code=18, names=('O',))
|
||||
elif key in ('P',):
|
||||
make_key(code=19, names=('P',))
|
||||
elif key in ('Q',):
|
||||
make_key(code=20, names=('Q',))
|
||||
elif key in ('R',):
|
||||
make_key(code=21, names=('R',))
|
||||
elif key in ('S',):
|
||||
make_key(code=22, names=('S',))
|
||||
elif key in ('T',):
|
||||
make_key(code=23, names=('T',))
|
||||
elif key in ('U',):
|
||||
make_key(code=24, names=('U',))
|
||||
elif key in ('V',):
|
||||
make_key(code=25, names=('V',))
|
||||
elif key in ('W',):
|
||||
make_key(code=26, names=('W',))
|
||||
elif key in ('X',):
|
||||
make_key(code=27, names=('X',))
|
||||
elif key in ('Y',):
|
||||
make_key(code=28, names=('Y',))
|
||||
elif key in ('Z',):
|
||||
make_key(code=29, names=('Z',))
|
||||
# Basic ASCII letters/numbers don't need anything fancy, so check those
|
||||
# in the laziest way
|
||||
if key in ALL_ALPHAS:
|
||||
make_key(code=4 + ALL_ALPHAS.index(key), names=(key,))
|
||||
elif key in ALL_NUMBERS or key in ALL_NUMBER_ALIASES:
|
||||
try:
|
||||
offset = ALL_NUMBERS.index(key)
|
||||
except ValueError:
|
||||
offset = ALL_NUMBER_ALIASES.index(key)
|
||||
|
||||
# Numbers
|
||||
# Aliases to play nicely with AttrDict, since KC.1 isn't a valid
|
||||
# attribute key in Python, but KC.N1 is
|
||||
elif key in ('1', 'N1'):
|
||||
make_key(code=30, names=('1', 'N1'))
|
||||
elif key in ('2', 'N2'):
|
||||
make_key(code=31, names=('2', 'N2'))
|
||||
elif key in ('3', 'N3'):
|
||||
make_key(code=32, names=('3', 'N3'))
|
||||
elif key in ('4', 'N4'):
|
||||
make_key(code=33, names=('4', 'N4'))
|
||||
elif key in ('5', 'N5'):
|
||||
make_key(code=34, names=('5', 'N5'))
|
||||
elif key in ('6', 'N6'):
|
||||
make_key(code=35, names=('6', 'N6'))
|
||||
elif key in ('7', 'N7'):
|
||||
make_key(code=36, names=('7', 'N7'))
|
||||
elif key in ('8', 'N8'):
|
||||
make_key(code=37, names=('8', 'N8'))
|
||||
elif key in ('9', 'N9'):
|
||||
make_key(code=38, names=('9', 'N9'))
|
||||
elif key in ('0', 'N0'):
|
||||
make_key(code=39, names=('0', 'N0'))
|
||||
names = (ALL_NUMBERS[offset], ALL_NUMBER_ALIASES[offset])
|
||||
make_key(code=30 + offset, names=names)
|
||||
|
||||
# More ASCII standard keys
|
||||
elif key in ('ENTER', 'ENT', '\n'):
|
||||
make_key(code=40, names=('ENTER', 'ENT', '\n'))
|
||||
elif key in ('ESCAPE', 'ESC'):
|
||||
make_key(code=41, names=('ESCAPE', 'ESC'))
|
||||
elif key in ('BACKSPACE', 'BSPC', 'BKSP'):
|
||||
make_key(code=42, names=('BACKSPACE', 'BSPC', 'BKSP'))
|
||||
elif key in ('TAB', '\t'):
|
||||
make_key(code=43, names=('TAB', '\t'))
|
||||
elif key in ('SPACE', 'SPC', ' '):
|
||||
make_key(code=44, names=('SPACE', 'SPC', ' '))
|
||||
elif key in ('MINUS', 'MINS', '-'):
|
||||
make_key(code=45, names=('MINUS', 'MINS', '-'))
|
||||
elif key in ('EQUAL', 'EQL', '='):
|
||||
make_key(code=46, names=('EQUAL', 'EQL', '='))
|
||||
elif key in ('LBRACKET', 'LBRC', '['):
|
||||
make_key(code=47, names=('LBRACKET', 'LBRC', '['))
|
||||
elif key in ('RBRACKET', 'RBRC', ']'):
|
||||
make_key(code=48, names=('RBRACKET', 'RBRC', ']'))
|
||||
elif key in ('BACKSLASH', 'BSLASH', 'BSLS', '\\'):
|
||||
make_key(code=49, names=('BACKSLASH', 'BSLASH', 'BSLS', '\\'))
|
||||
elif key in ('SEMICOLON', 'SCOLON', 'SCLN', ';'):
|
||||
make_key(code=51, names=('SEMICOLON', 'SCOLON', 'SCLN', ';'))
|
||||
elif key in ('QUOTE', 'QUOT', "'"):
|
||||
make_key(code=52, names=('QUOTE', 'QUOT', "'"))
|
||||
elif key in ('GRAVE', 'GRV', 'ZKHK', '`'):
|
||||
make_key(code=53, names=('GRAVE', 'GRV', 'ZKHK', '`'))
|
||||
elif key in ('COMMA', 'COMM', ','):
|
||||
make_key(code=54, names=('COMMA', 'COMM', ','))
|
||||
elif key in ('DOT', '.'):
|
||||
make_key(code=55, names=('DOT', '.'))
|
||||
elif key in ('SLASH', 'SLSH'):
|
||||
make_key(code=56, names=('SLASH', 'SLSH'))
|
||||
|
||||
# Function Keys
|
||||
elif key in ('F1',):
|
||||
make_key(code=58, names=('F1',))
|
||||
elif key in ('F2',):
|
||||
make_key(code=59, names=('F2',))
|
||||
elif key in ('F3',):
|
||||
make_key(code=60, names=('F3',))
|
||||
elif key in ('F4',):
|
||||
make_key(code=61, names=('F4',))
|
||||
elif key in ('F5',):
|
||||
make_key(code=62, names=('F5',))
|
||||
elif key in ('F6',):
|
||||
make_key(code=63, names=('F6',))
|
||||
elif key in ('F7',):
|
||||
make_key(code=64, names=('F7',))
|
||||
elif key in ('F8',):
|
||||
make_key(code=65, names=('F8',))
|
||||
elif key in ('F9',):
|
||||
make_key(code=66, names=('F9',))
|
||||
elif key in ('F10',):
|
||||
make_key(code=67, names=('F10',))
|
||||
elif key in ('F11',):
|
||||
make_key(code=68, names=('F11',))
|
||||
elif key in ('F12',):
|
||||
make_key(code=69, names=('F12',))
|
||||
elif key in ('F13',):
|
||||
make_key(code=104, names=('F13',))
|
||||
elif key in ('F14',):
|
||||
make_key(code=105, names=('F14',))
|
||||
elif key in ('F15',):
|
||||
make_key(code=106, names=('F15',))
|
||||
elif key in ('F16',):
|
||||
make_key(code=107, names=('F16',))
|
||||
elif key in ('F17',):
|
||||
make_key(code=108, names=('F17',))
|
||||
elif key in ('F18',):
|
||||
make_key(code=109, names=('F18',))
|
||||
elif key in ('F19',):
|
||||
make_key(code=110, names=('F19',))
|
||||
elif key in ('F20',):
|
||||
make_key(code=111, names=('F20',))
|
||||
elif key in ('F21',):
|
||||
make_key(code=112, names=('F21',))
|
||||
elif key in ('F22',):
|
||||
make_key(code=113, names=('F22',))
|
||||
elif key in ('F23',):
|
||||
make_key(code=114, names=('F23',))
|
||||
elif key in ('F24',):
|
||||
make_key(code=115, names=('F24',))
|
||||
|
||||
# Lock Keys, Navigation, etc.
|
||||
elif key in ('CAPS_LOCK', 'CAPSLOCK', 'CLCK', 'CAPS'):
|
||||
make_key(code=57, names=('CAPS_LOCK', 'CAPSLOCK', 'CLCK', 'CAPS'))
|
||||
# FIXME: Investigate whether this key actually works, and
|
||||
# uncomment when/if it does.
|
||||
# elif key in ('LOCKING_CAPS', 'LCAP'):
|
||||
# # make_key(code=130, names=('LOCKING_CAPS', 'LCAP'))
|
||||
elif key in ('PRINT_SCREEN', 'PSCREEN', 'PSCR'):
|
||||
make_key(code=70, names=('PRINT_SCREEN', 'PSCREEN', 'PSCR'))
|
||||
elif key in ('SCROLL_LOCK', 'SCROLLLOCK', 'SLCK'):
|
||||
make_key(code=71, names=('SCROLL_LOCK', 'SCROLLLOCK', 'SLCK'))
|
||||
# FIXME: Investigate whether this key actually works, and
|
||||
# uncomment when/if it does.
|
||||
# elif key in ('LOCKING_SCROLL', 'LSCRL'):
|
||||
# make_key(code=132, names=('LOCKING_SCROLL', 'LSCRL'))
|
||||
elif key in ('PAUSE', 'PAUS', 'BRK'):
|
||||
make_key(code=72, names=('PAUSE', 'PAUS', 'BRK'))
|
||||
elif key in ('INSERT', 'INS'):
|
||||
make_key(code=73, names=('INSERT', 'INS'))
|
||||
elif key in ('HOME',):
|
||||
make_key(code=74, names=('HOME',))
|
||||
elif key in ('PGUP',):
|
||||
make_key(code=75, names=('PGUP',))
|
||||
elif key in ('DELETE', 'DEL'):
|
||||
make_key(code=76, names=('DELETE', 'DEL'))
|
||||
elif key in ('END',):
|
||||
make_key(code=77, names=('END',))
|
||||
elif key in ('PGDOWN', 'PGDN'):
|
||||
make_key(code=78, names=('PGDOWN', 'PGDN'))
|
||||
elif key in ('RIGHT', 'RGHT'):
|
||||
make_key(code=79, names=('RIGHT', 'RGHT'))
|
||||
elif key in ('LEFT',):
|
||||
make_key(code=80, names=('LEFT',))
|
||||
elif key in ('DOWN',):
|
||||
make_key(code=81, names=('DOWN',))
|
||||
elif key in ('UP',):
|
||||
make_key(code=82, names=('UP',))
|
||||
|
||||
# Numpad
|
||||
elif key in ('NUM_LOCK', 'NUMLOCK', 'NLCK'):
|
||||
make_key(code=83, names=('NUM_LOCK', 'NUMLOCK', 'NLCK'))
|
||||
# FIXME: Investigate whether this key actually works, and
|
||||
# uncomment when/if it does.
|
||||
# elif key in ('LOCKING_NUM', 'LNUM'):
|
||||
# make_key(code=131, names=('LOCKING_NUM', 'LNUM'))
|
||||
elif key in ('KP_SLASH', 'NUMPAD_SLASH', 'PSLS'):
|
||||
make_key(code=84, names=('KP_SLASH', 'NUMPAD_SLASH', 'PSLS'))
|
||||
elif key in ('KP_ASTERISK', 'NUMPAD_ASTERISK', 'PAST'):
|
||||
make_key(code=85, names=('KP_ASTERISK', 'NUMPAD_ASTERISK', 'PAST'))
|
||||
elif key in ('KP_MINUS', 'NUMPAD_MINUS', 'PMNS'):
|
||||
make_key(code=86, names=('KP_MINUS', 'NUMPAD_MINUS', 'PMNS'))
|
||||
elif key in ('KP_PLUS', 'NUMPAD_PLUS', 'PPLS'):
|
||||
make_key(code=87, names=('KP_PLUS', 'NUMPAD_PLUS', 'PPLS'))
|
||||
elif key in ('KP_ENTER', 'NUMPAD_ENTER', 'PENT'):
|
||||
make_key(code=88, names=('KP_ENTER', 'NUMPAD_ENTER', 'PENT'))
|
||||
elif key in ('KP_1', 'P1', 'NUMPAD_1'):
|
||||
make_key(code=89, names=('KP_1', 'P1', 'NUMPAD_1'))
|
||||
elif key in ('KP_2', 'P2', 'NUMPAD_2'):
|
||||
make_key(code=90, names=('KP_2', 'P2', 'NUMPAD_2'))
|
||||
elif key in ('KP_3', 'P3', 'NUMPAD_3'):
|
||||
make_key(code=91, names=('KP_3', 'P3', 'NUMPAD_3'))
|
||||
elif key in ('KP_4', 'P4', 'NUMPAD_4'):
|
||||
make_key(code=92, names=('KP_4', 'P4', 'NUMPAD_4'))
|
||||
elif key in ('KP_5', 'P5', 'NUMPAD_5'):
|
||||
make_key(code=93, names=('KP_5', 'P5', 'NUMPAD_5'))
|
||||
elif key in ('KP_6', 'P6', 'NUMPAD_6'):
|
||||
make_key(code=94, names=('KP_6', 'P6', 'NUMPAD_6'))
|
||||
elif key in ('KP_7', 'P7', 'NUMPAD_7'):
|
||||
make_key(code=95, names=('KP_7', 'P7', 'NUMPAD_7'))
|
||||
elif key in ('KP_8', 'P8', 'NUMPAD_8'):
|
||||
make_key(code=96, names=('KP_8', 'P8', 'NUMPAD_8'))
|
||||
elif key in ('KP_9', 'P9', 'NUMPAD_9'):
|
||||
make_key(code=97, names=('KP_9', 'P9', 'NUMPAD_9'))
|
||||
elif key in ('KP_0', 'P0', 'NUMPAD_0'):
|
||||
make_key(code=98, names=('KP_0', 'P0', 'NUMPAD_0'))
|
||||
elif key in ('KP_DOT', 'PDOT', 'NUMPAD_DOT'):
|
||||
make_key(code=99, names=('KP_DOT', 'PDOT', 'NUMPAD_DOT'))
|
||||
elif key in ('KP_EQUAL', 'PEQL', 'NUMPAD_EQUAL'):
|
||||
make_key(code=103, names=('KP_EQUAL', 'PEQL', 'NUMPAD_EQUAL'))
|
||||
elif key in ('KP_COMMA', 'PCMM', 'NUMPAD_COMMA'):
|
||||
make_key(code=133, names=('KP_COMMA', 'PCMM', 'NUMPAD_COMMA'))
|
||||
elif key in ('KP_EQUAL_AS400', 'NUMPAD_EQUAL_AS400'):
|
||||
make_key(code=134, names=('KP_EQUAL_AS400', 'NUMPAD_EQUAL_AS400'))
|
||||
|
||||
# Making life better for folks on tiny keyboards especially: exposes
|
||||
# the 'shifted' keys as raw keys. Under the hood we're still
|
||||
# sending Shift+(whatever key is normally pressed) to get these, so
|
||||
# for example `KC_AT` will hold shift and press 2.
|
||||
elif key in ('TILDE', 'TILD', '~'):
|
||||
make_shifted_key('GRAVE', names=('TILDE', 'TILD', '~'))
|
||||
elif key in ('EXCLAIM', 'EXLM', '!'):
|
||||
make_shifted_key('1', names=('EXCLAIM', 'EXLM', '!'))
|
||||
elif key in ('AT', '@'):
|
||||
make_shifted_key('2', names=('AT', '@'))
|
||||
elif key in ('HASH', 'POUND', '#'):
|
||||
make_shifted_key('3', names=('HASH', 'POUND', '#'))
|
||||
elif key in ('DOLLAR', 'DLR', '$'):
|
||||
make_shifted_key('4', names=('DOLLAR', 'DLR', '$'))
|
||||
elif key in ('PERCENT', 'PERC', '%'):
|
||||
make_shifted_key('5', names=('PERCENT', 'PERC', '%'))
|
||||
elif key in ('CIRCUMFLEX', 'CIRC', '^'):
|
||||
make_shifted_key('6', names=('CIRCUMFLEX', 'CIRC', '^'))
|
||||
elif key in ('AMPERSAND', 'AMPR', '&'):
|
||||
make_shifted_key('7', names=('AMPERSAND', 'AMPR', '&'))
|
||||
elif key in ('ASTERISK', 'ASTR', '*'):
|
||||
make_shifted_key('8', names=('ASTERISK', 'ASTR', '*'))
|
||||
elif key in ('LEFT_PAREN', 'LPRN', '('):
|
||||
make_shifted_key('9', names=('LEFT_PAREN', 'LPRN', '('))
|
||||
elif key in ('RIGHT_PAREN', 'RPRN', ')'):
|
||||
make_shifted_key('0', names=('RIGHT_PAREN', 'RPRN', ')'))
|
||||
elif key in ('UNDERSCORE', 'UNDS', '_'):
|
||||
make_shifted_key('MINUS', names=('UNDERSCORE', 'UNDS', '_'))
|
||||
elif key in ('PLUS', '+'):
|
||||
make_shifted_key('EQUAL', names=('PLUS', '+'))
|
||||
elif key in ('LEFT_CURLY_BRACE', 'LCBR', '{'):
|
||||
make_shifted_key('LBRACKET', names=('LEFT_CURLY_BRACE', 'LCBR', '{'))
|
||||
elif key in ('RIGHT_CURLY_BRACE', 'RCBR', '}'):
|
||||
make_shifted_key('RBRACKET', names=('RIGHT_CURLY_BRACE', 'RCBR', '}'))
|
||||
elif key in ('PIPE', '|'):
|
||||
make_shifted_key('BACKSLASH', names=('PIPE', '|'))
|
||||
elif key in ('COLON', 'COLN', ':'):
|
||||
make_shifted_key('SEMICOLON', names=('COLON', 'COLN', ':'))
|
||||
elif key in ('DOUBLE_QUOTE', 'DQUO', 'DQT', '"'):
|
||||
make_shifted_key('QUOTE', names=('DOUBLE_QUOTE', 'DQUO', 'DQT', '"'))
|
||||
elif key in ('LEFT_ANGLE_BRACKET', 'LABK', '<'):
|
||||
make_shifted_key('COMMA', names=('LEFT_ANGLE_BRACKET', 'LABK', '<'))
|
||||
elif key in ('RIGHT_ANGLE_BRACKET', 'RABK', '>'):
|
||||
make_shifted_key('DOT', names=('RIGHT_ANGLE_BRACKET', 'RABK', '>'))
|
||||
elif key in ('QUESTION', 'QUES', '?'):
|
||||
make_shifted_key('SLSH', names=('QUESTION', 'QUES', '?'))
|
||||
|
||||
# International
|
||||
elif key in ('NONUS_HASH', 'NUHS'):
|
||||
make_key(code=50, names=('NONUS_HASH', 'NUHS'))
|
||||
elif key in ('NONUS_BSLASH', 'NUBS'):
|
||||
make_key(code=100, names=('NONUS_BSLASH', 'NUBS'))
|
||||
elif key in ('APP', 'APPLICATION', 'SEL', 'WINMENU'):
|
||||
make_key(code=101, names=('APP', 'APPLICATION', 'SEL', 'WINMENU'))
|
||||
|
||||
elif key in ('INT1', 'RO'):
|
||||
make_key(code=135, names=('INT1', 'RO'))
|
||||
elif key in ('INT2', 'KANA'):
|
||||
make_key(code=136, names=('INT2', 'KANA'))
|
||||
elif key in ('INT3', 'JYEN'):
|
||||
make_key(code=137, names=('INT3', 'JYEN'))
|
||||
elif key in ('INT4', 'HENK'):
|
||||
make_key(code=138, names=('INT4', 'HENK'))
|
||||
elif key in ('INT5', 'MHEN'):
|
||||
make_key(code=139, names=('INT5', 'MHEN'))
|
||||
elif key in ('INT6',):
|
||||
make_key(code=140, names=('INT6',))
|
||||
elif key in ('INT7',):
|
||||
make_key(code=141, names=('INT7',))
|
||||
elif key in ('INT8',):
|
||||
make_key(code=142, names=('INT8',))
|
||||
elif key in ('INT9',):
|
||||
make_key(code=143, names=('INT9',))
|
||||
elif key in ('LANG1', 'HAEN'):
|
||||
make_key(code=144, names=('LANG1', 'HAEN'))
|
||||
elif key in ('LANG2', 'HAEJ'):
|
||||
make_key(code=145, names=('LANG2', 'HAEJ'))
|
||||
elif key in ('LANG3',):
|
||||
make_key(code=146, names=('LANG3',))
|
||||
elif key in ('LANG4',):
|
||||
make_key(code=147, names=('LANG4',))
|
||||
elif key in ('LANG5',):
|
||||
make_key(code=148, names=('LANG5',))
|
||||
elif key in ('LANG6',):
|
||||
make_key(code=149, names=('LANG6',))
|
||||
elif key in ('LANG7',):
|
||||
make_key(code=150, names=('LANG7',))
|
||||
elif key in ('LANG8',):
|
||||
make_key(code=151, names=('LANG8',))
|
||||
elif key in ('LANG9',):
|
||||
make_key(code=152, names=('LANG9',))
|
||||
|
||||
# Consumer ("media") keys. Most known keys aren't supported here. A much
|
||||
# longer list used to exist in this file, but the codes were almost certainly
|
||||
# incorrect, conflicting with each other, or otherwise 'weird'. We'll add them
|
||||
# back in piecemeal as needed. PRs welcome.
|
||||
#
|
||||
# A super useful reference for these is http://www.freebsddiary.org/APC/usb_hid_usages.php
|
||||
# Note that currently we only have the PC codes. Recent MacOS versions seem to
|
||||
# support PC media keys, so I don't know how much value we would get out of
|
||||
# adding the old Apple-specific consumer codes, but again, PRs welcome if the
|
||||
# lack of them impacts you.
|
||||
elif key in ('AUDIO_MUTE', 'MUTE'):
|
||||
make_consumer_key(code=226, names=('AUDIO_MUTE', 'MUTE')) # 0xE2
|
||||
elif key in ('AUDIO_VOL_UP', 'VOLU'):
|
||||
make_consumer_key(code=233, names=('AUDIO_VOL_UP', 'VOLU')) # 0xE9
|
||||
elif key in ('AUDIO_VOL_DOWN', 'VOLD'):
|
||||
make_consumer_key(code=234, names=('AUDIO_VOL_DOWN', 'VOLD')) # 0xEA
|
||||
elif key in ('MEDIA_NEXT_TRACK', 'MNXT'):
|
||||
make_consumer_key(code=181, names=('MEDIA_NEXT_TRACK', 'MNXT')) # 0xB5
|
||||
elif key in ('MEDIA_PREV_TRACK', 'MPRV'):
|
||||
make_consumer_key(code=182, names=('MEDIA_PREV_TRACK', 'MPRV')) # 0xB6
|
||||
elif key in ('MEDIA_STOP', 'MSTP'):
|
||||
make_consumer_key(code=183, names=('MEDIA_STOP', 'MSTP')) # 0xB7
|
||||
elif key in ('MEDIA_PLAY_PAUSE', 'MPLY'):
|
||||
make_consumer_key(
|
||||
code=205, names=('MEDIA_PLAY_PAUSE', 'MPLY')
|
||||
) # 0xCD (this may not be right)
|
||||
elif key in ('MEDIA_EJECT', 'EJCT'):
|
||||
make_consumer_key(code=184, names=('MEDIA_EJECT', 'EJCT')) # 0xB8
|
||||
elif key in ('MEDIA_FAST_FORWARD', 'MFFD'):
|
||||
make_consumer_key(code=179, names=('MEDIA_FAST_FORWARD', 'MFFD')) # 0xB3
|
||||
elif key in ('MEDIA_REWIND', 'MRWD'):
|
||||
make_consumer_key(code=180, names=('MEDIA_REWIND', 'MRWD')) # 0xB4
|
||||
# Now try all the other weird special cases to get them out of our way:
|
||||
|
||||
# Internal, diagnostic, or auxiliary/enhanced keys
|
||||
|
||||
# NO and TRNS are functionally identical in how they (don't) mutate
|
||||
# the state, but are tracked semantically separately, so create
|
||||
# two keys with the exact same functionality
|
||||
elif key in ('NO',):
|
||||
elif key in ('NO', 'XXXXXXX'):
|
||||
make_key(
|
||||
names=('NO',),
|
||||
names=('NO', 'XXXXXXX'),
|
||||
on_press=handlers.passthrough,
|
||||
on_release=handlers.passthrough,
|
||||
)
|
||||
@@ -447,12 +118,6 @@ class KeyAttrDict(AttrDict):
|
||||
on_press=handlers.debug_pressed,
|
||||
on_release=handlers.passthrough,
|
||||
)
|
||||
elif key in ('GESC',):
|
||||
make_key(
|
||||
names=('GESC',),
|
||||
on_press=handlers.gesc_pressed,
|
||||
on_release=handlers.gesc_released,
|
||||
)
|
||||
elif key in ('BKDL',):
|
||||
make_key(
|
||||
names=('BKDL',),
|
||||
@@ -514,8 +179,204 @@ class KeyAttrDict(AttrDict):
|
||||
elif key in ('HID_SWITCH', 'HID'):
|
||||
make_key(names=('HID_SWITCH', 'HID'), on_press=handlers.hid_switch)
|
||||
else:
|
||||
raise ValueError('Invalid key')
|
||||
return self.__getattr__(key)
|
||||
maybe_key = first_truthy(
|
||||
key,
|
||||
# Modifiers
|
||||
lambda key: left_pipe_until_some(
|
||||
key,
|
||||
maybe_make_mod_key,
|
||||
(0x01, ('LEFT_CONTROL', 'LCTRL', 'LCTL')),
|
||||
(0x02, ('LEFT_SHIFT', 'LSHIFT', 'LSFT')),
|
||||
(0x04, ('LEFT_ALT', 'LALT')),
|
||||
(0x08, ('LEFT_SUPER', 'LGUI', 'LCMD', 'LWIN')),
|
||||
(0x10, ('RIGHT_CONTROL', 'RCTRL', 'RCTL')),
|
||||
(0x20, ('RIGHT_SHIFT', 'RSHIFT', 'RSFT')),
|
||||
(0x40, ('RIGHT_ALT', 'RALT')),
|
||||
(0x80, ('RIGHT_SUPER', 'RGUI', 'RCMD', 'RWIN')),
|
||||
# MEH = LCTL | LALT | LSFT# MEH = LCTL |
|
||||
(0x07, ('MEH',)),
|
||||
# HYPR = LCTL | LALT | LSFT | LGUI
|
||||
(0x0F, ('HYPER', 'HYPR')),
|
||||
),
|
||||
lambda key: left_pipe_until_some(
|
||||
key,
|
||||
maybe_make_key,
|
||||
# More ASCII standard keys
|
||||
(40, ('ENTER', 'ENT', '\n')),
|
||||
(41, ('ESCAPE', 'ESC')),
|
||||
(42, ('BACKSPACE', 'BSPC', 'BKSP')),
|
||||
(43, ('TAB', '\t')),
|
||||
(44, ('SPACE', 'SPC', ' ')),
|
||||
(45, ('MINUS', 'MINS', '-')),
|
||||
(46, ('EQUAL', 'EQL', '=')),
|
||||
(47, ('LBRACKET', 'LBRC', '[')),
|
||||
(48, ('RBRACKET', 'RBRC', ']')),
|
||||
(49, ('BACKSLASH', 'BSLASH', 'BSLS', '\\')),
|
||||
(51, ('SEMICOLON', 'SCOLON', 'SCLN', ';')),
|
||||
(52, ('QUOTE', 'QUOT', "'")),
|
||||
(53, ('GRAVE', 'GRV', 'ZKHK', '`')),
|
||||
(54, ('COMMA', 'COMM', ',')),
|
||||
(55, ('DOT', '.')),
|
||||
(56, ('SLASH', 'SLSH')),
|
||||
# Function Keys
|
||||
(58, ('F1',)),
|
||||
(59, ('F2',)),
|
||||
(60, ('F3',)),
|
||||
(61, ('F4',)),
|
||||
(62, ('F5',)),
|
||||
(63, ('F6',)),
|
||||
(64, ('F7',)),
|
||||
(65, ('F8',)),
|
||||
(66, ('F9',)),
|
||||
(67, ('F10',)),
|
||||
(68, ('F11',)),
|
||||
(69, ('F12',)),
|
||||
(104, ('F13',)),
|
||||
(105, ('F14',)),
|
||||
(106, ('F15',)),
|
||||
(107, ('F16',)),
|
||||
(108, ('F17',)),
|
||||
(109, ('F18',)),
|
||||
(110, ('F19',)),
|
||||
(111, ('F20',)),
|
||||
(112, ('F21',)),
|
||||
(113, ('F22',)),
|
||||
(114, ('F23',)),
|
||||
(115, ('F24',)),
|
||||
# Lock Keys, Navigation, etc.
|
||||
(57, ('CAPS_LOCK', 'CAPSLOCK', 'CLCK', 'CAPS')),
|
||||
# FIXME: Investigate whether this key actually works, and
|
||||
# uncomment when/if it does.
|
||||
# (130, ('LOCKING_CAPS', 'LCAP')),
|
||||
(70, ('PRINT_SCREEN', 'PSCREEN', 'PSCR')),
|
||||
(71, ('SCROLL_LOCK', 'SCROLLLOCK', 'SLCK')),
|
||||
# FIXME: Investigate whether this key actually works, and
|
||||
# uncomment when/if it does.
|
||||
# (132, ('LOCKING_SCROLL', 'LSCRL')),
|
||||
(72, ('PAUSE', 'PAUS', 'BRK')),
|
||||
(73, ('INSERT', 'INS')),
|
||||
(74, ('HOME',)),
|
||||
(75, ('PGUP',)),
|
||||
(76, ('DELETE', 'DEL')),
|
||||
(77, ('END',)),
|
||||
(78, ('PGDOWN', 'PGDN')),
|
||||
(79, ('RIGHT', 'RGHT')),
|
||||
(80, ('LEFT',)),
|
||||
(81, ('DOWN',)),
|
||||
(82, ('UP',)),
|
||||
# Numpad
|
||||
(83, ('NUM_LOCK', 'NUMLOCK', 'NLCK')),
|
||||
# FIXME: Investigate whether this key actually works, and
|
||||
# uncomment when/if it does.
|
||||
# (131, names=('LOCKING_NUM', 'LNUM')),
|
||||
(84, ('KP_SLASH', 'NUMPAD_SLASH', 'PSLS')),
|
||||
(85, ('KP_ASTERISK', 'NUMPAD_ASTERISK', 'PAST')),
|
||||
(86, ('KP_MINUS', 'NUMPAD_MINUS', 'PMNS')),
|
||||
(87, ('KP_PLUS', 'NUMPAD_PLUS', 'PPLS')),
|
||||
(88, ('KP_ENTER', 'NUMPAD_ENTER', 'PENT')),
|
||||
(89, ('KP_1', 'P1', 'NUMPAD_1')),
|
||||
(90, ('KP_2', 'P2', 'NUMPAD_2')),
|
||||
(91, ('KP_3', 'P3', 'NUMPAD_3')),
|
||||
(92, ('KP_4', 'P4', 'NUMPAD_4')),
|
||||
(93, ('KP_5', 'P5', 'NUMPAD_5')),
|
||||
(94, ('KP_6', 'P6', 'NUMPAD_6')),
|
||||
(95, ('KP_7', 'P7', 'NUMPAD_7')),
|
||||
(96, ('KP_8', 'P8', 'NUMPAD_8')),
|
||||
(97, ('KP_9', 'P9', 'NUMPAD_9')),
|
||||
(98, ('KP_0', 'P0', 'NUMPAD_0')),
|
||||
(99, ('KP_DOT', 'PDOT', 'NUMPAD_DOT')),
|
||||
(103, ('KP_EQUAL', 'PEQL', 'NUMPAD_EQUAL')),
|
||||
(133, ('KP_COMMA', 'PCMM', 'NUMPAD_COMMA')),
|
||||
(134, ('KP_EQUAL_AS400', 'NUMPAD_EQUAL_AS400')),
|
||||
),
|
||||
# Making life better for folks on tiny keyboards especially: exposes
|
||||
# the 'shifted' keys as raw keys. Under the hood we're still
|
||||
# sending Shift+(whatever key is normally pressed) to get these, so
|
||||
# for example `KC_AT` will hold shift and press 2.
|
||||
lambda key: left_pipe_until_some(
|
||||
key,
|
||||
maybe_make_shifted_key,
|
||||
('GRAVE', ('TILDE', 'TILD', '~')),
|
||||
('1', ('EXCLAIM', 'EXLM', '!')),
|
||||
('2', ('AT', '@')),
|
||||
('3', ('HASH', 'POUND', '#')),
|
||||
('4', ('DOLLAR', 'DLR', '$')),
|
||||
('5', ('PERCENT', 'PERC', '%')),
|
||||
('6', ('CIRCUMFLEX', 'CIRC', '^')),
|
||||
('7', ('AMPERSAND', 'AMPR', '&')),
|
||||
('8', ('ASTERISK', 'ASTR', '*')),
|
||||
('9', ('LEFT_PAREN', 'LPRN', '(')),
|
||||
('0', ('RIGHT_PAREN', 'RPRN', ')')),
|
||||
('MINUS', ('UNDERSCORE', 'UNDS', '_')),
|
||||
('EQUAL', ('PLUS', '+')),
|
||||
('LBRACKET', ('LEFT_CURLY_BRACE', 'LCBR', '{')),
|
||||
('RBRACKET', ('RIGHT_CURLY_BRACE', 'RCBR', '}')),
|
||||
('BACKSLASH', ('PIPE', '|')),
|
||||
('SEMICOLON', ('COLON', 'COLN', ':')),
|
||||
('QUOTE', ('DOUBLE_QUOTE', 'DQUO', 'DQT', '"')),
|
||||
('COMMA', ('LEFT_ANGLE_BRACKET', 'LABK', '<')),
|
||||
('DOT', ('RIGHT_ANGLE_BRACKET', 'RABK', '>')),
|
||||
('SLSH', ('QUESTION', 'QUES', '?')),
|
||||
),
|
||||
# International
|
||||
lambda key: left_pipe_until_some(
|
||||
key,
|
||||
maybe_make_key,
|
||||
(50, ('NONUS_HASH', 'NUHS')),
|
||||
(100, ('NONUS_BSLASH', 'NUBS')),
|
||||
(101, ('APP', 'APPLICATION', 'SEL', 'WINMENU')),
|
||||
(135, ('INT1', 'RO')),
|
||||
(136, ('INT2', 'KANA')),
|
||||
(137, ('INT3', 'JYEN')),
|
||||
(138, ('INT4', 'HENK')),
|
||||
(139, ('INT5', 'MHEN')),
|
||||
(140, ('INT6',)),
|
||||
(141, ('INT7',)),
|
||||
(142, ('INT8',)),
|
||||
(143, ('INT9',)),
|
||||
(144, ('LANG1', 'HAEN')),
|
||||
(145, ('LANG2', 'HAEJ')),
|
||||
(146, ('LANG3',)),
|
||||
(147, ('LANG4',)),
|
||||
(148, ('LANG5',)),
|
||||
(149, ('LANG6',)),
|
||||
(150, ('LANG7',)),
|
||||
(151, ('LANG8',)),
|
||||
(152, ('LANG9',)),
|
||||
),
|
||||
# Consumer ("media") keys. Most known keys aren't supported here. A much
|
||||
# longer list used to exist in this file, but the codes were almost certainly
|
||||
# incorrect, conflicting with each other, or otherwise 'weird'. We'll add them
|
||||
# back in piecemeal as needed. PRs welcome.
|
||||
#
|
||||
# A super useful reference for these is http://www.freebsddiary.org/APC/usb_hid_usages.php
|
||||
# Note that currently we only have the PC codes. Recent MacOS versions seem to
|
||||
# support PC media keys, so I don't know how much value we would get out of
|
||||
# adding the old Apple-specific consumer codes, but again, PRs welcome if the
|
||||
# lack of them impacts you.
|
||||
lambda key: left_pipe_until_some(
|
||||
key,
|
||||
maybe_make_consumer_key,
|
||||
(226, ('AUDIO_MUTE', 'MUTE')), # 0xE2
|
||||
(233, ('AUDIO_VOL_UP', 'VOLU')), # 0xE9
|
||||
(234, ('AUDIO_VOL_DOWN', 'VOLD')), # 0xEA
|
||||
(181, ('MEDIA_NEXT_TRACK', 'MNXT')), # 0xB5
|
||||
(182, ('MEDIA_PREV_TRACK', 'MPRV')), # 0xB6
|
||||
(183, ('MEDIA_STOP', 'MSTP')), # 0xB7
|
||||
(205, ('MEDIA_PLAY_PAUSE', 'MPLY')), # 0xCD (this may not be right)
|
||||
(184, ('MEDIA_EJECT', 'EJCT')), # 0xB8
|
||||
(179, ('MEDIA_FAST_FORWARD', 'MFFD')), # 0xB3
|
||||
(180, ('MEDIA_REWIND', 'MRWD')), # 0xB4
|
||||
),
|
||||
)
|
||||
|
||||
if DEBUG_OUTPUT:
|
||||
print(f'{key}: {maybe_key}')
|
||||
|
||||
if not maybe_key:
|
||||
raise ValueError('Invalid key')
|
||||
|
||||
return self.__getattr__(key, depth=depth + 1)
|
||||
|
||||
|
||||
# Global state, will be filled in througout this file, and
|
||||
@@ -810,12 +671,19 @@ def make_key(code=None, names=tuple(), type=KEY_SIMPLE, **kwargs): # NOQA
|
||||
return key
|
||||
|
||||
|
||||
def make_mod_key(*args, **kwargs):
|
||||
return make_key(*args, **kwargs, type=KEY_MODIFIER)
|
||||
def make_mod_key(code, names, *args, **kwargs):
|
||||
return make_key(code, names, *args, **kwargs, type=KEY_MODIFIER)
|
||||
|
||||
|
||||
def make_shifted_key(target_name, names=tuple()): # NOQA
|
||||
key = KC.LSFT(KC[target_name])
|
||||
# For... probably a few years, a bug existed here where keys were looked
|
||||
# up by `KC[...]`, but that's incorrect: an AttrDit exposes a dictionary
|
||||
# with attributes, but key-based dictionary access with brackets does
|
||||
# *not* implicitly call __getattr__. We got away with this when key defs
|
||||
# were not lazily created, but now that they are, shifted keys would
|
||||
# sometimes break, complaining that they couldn't find their underlying
|
||||
# key to shift. Fixed!
|
||||
key = KC.LSFT(getattr(KC, target_name))
|
||||
|
||||
register_key_names(key, names)
|
||||
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
import digitalio
|
||||
|
||||
from kmk.kmktime import ticks_ms
|
||||
from kmk.modules import Module
|
||||
|
||||
|
||||
class EncoderPadState:
|
||||
OFF = False
|
||||
ON = True
|
||||
|
||||
|
||||
class EndcoderDirection:
|
||||
Left = False
|
||||
Right = True
|
||||
|
||||
|
||||
class Encoder:
|
||||
def __init__(
|
||||
self,
|
||||
pad_a,
|
||||
pad_b,
|
||||
button_pin=None,
|
||||
):
|
||||
self.pad_a = self.PreparePin(pad_a) # board pin for enc pin a
|
||||
self.pad_a_state = False
|
||||
self.pad_b = self.PreparePin(pad_b) # board pin for enc pin b
|
||||
self.pad_b_state = False
|
||||
self.button_pin = self.PreparePin(button_pin) # board pin for enc btn
|
||||
self.button_state = None # state of pushbutton on encoder if enabled
|
||||
self.encoder_value = 0 # clarify what this value is
|
||||
self.encoder_state = (
|
||||
self.pad_a_state,
|
||||
self.pad_b_state,
|
||||
) # quaderature encoder state
|
||||
self.encoder_direction = None # arbitrary, tells direction of knob
|
||||
self.last_encoder_state = None # not used yet
|
||||
self.resolution = 2 # number of keys sent per position change
|
||||
self.revolution_count = 20 # position changes per revolution
|
||||
self.has_button = False # enable/disable button functionality
|
||||
self.encoder_data = None # 6tuple containing all encoder data
|
||||
self.position_change = None # revolution count, inc/dec as knob turns
|
||||
self.last_encoder_value = 0 # not used
|
||||
self.is_inverted = False # switch to invert knob direction
|
||||
self.vel_mode = False # enable the velocity output
|
||||
self.vel_ts = None # velocity timestamp
|
||||
self.last_vel_ts = 0 # last velocity timestamp
|
||||
self.encoder_speed = None # ms per position change(4 states)
|
||||
self.encoder_map = None
|
||||
self.eps = EncoderPadState()
|
||||
self.encoder_pad_lookup = {
|
||||
False: self.eps.OFF,
|
||||
True: self.eps.ON,
|
||||
}
|
||||
self.edr = EndcoderDirection() # lookup for current encoder direction
|
||||
self.encoder_dir_lookup = {
|
||||
False: self.edr.Left,
|
||||
True: self.edr.Right,
|
||||
}
|
||||
|
||||
def __repr__(self, idx):
|
||||
return 'ENCODER_{}({})'.format(idx, self._to_dict())
|
||||
|
||||
def _to_dict(self):
|
||||
return {
|
||||
'Encoder_State': self.encoder_state,
|
||||
'Direction': self.encoder_direction,
|
||||
'Value': self.encoder_value,
|
||||
'Position_Change': self.position_change,
|
||||
'Speed': self.encoder_speed,
|
||||
'Button_State': self.button_state,
|
||||
}
|
||||
|
||||
# adapted for CircuitPython from raspi
|
||||
def PreparePin(self, num):
|
||||
if num is not None:
|
||||
pad = digitalio.DigitalInOut(num)
|
||||
pad.direction = digitalio.Direction.INPUT
|
||||
pad.pull = digitalio.Pull.UP
|
||||
return pad
|
||||
else:
|
||||
return None
|
||||
|
||||
# checks encoder pins, reports encoder data
|
||||
def report(self):
|
||||
new_encoder_state = (
|
||||
self.encoder_pad_lookup[int(self.pad_a.value)],
|
||||
self.encoder_pad_lookup[int(self.pad_b.value)],
|
||||
)
|
||||
|
||||
if self.encoder_state == (self.eps.ON, self.eps.ON): # Resting position
|
||||
if new_encoder_state == (self.eps.ON, self.eps.OFF): # Turned right 1
|
||||
self.encoder_direction = self.edr.Right
|
||||
elif new_encoder_state == (self.eps.OFF, self.eps.ON): # Turned left 1
|
||||
self.encoder_direction = self.edr.Left
|
||||
elif self.encoder_state == (self.eps.ON, self.eps.OFF): # R1 or L3 position
|
||||
if new_encoder_state == (self.eps.OFF, self.eps.OFF): # Turned right 1
|
||||
self.encoder_direction = self.edr.Right
|
||||
elif new_encoder_state == (self.eps.ON, self.eps.ON): # Turned left 1
|
||||
if self.encoder_direction == self.edr.Left:
|
||||
self.encoder_value = self.encoder_value - 1
|
||||
elif self.encoder_state == (self.eps.OFF, self.eps.ON): # R3 or L1
|
||||
if new_encoder_state == (self.eps.OFF, self.eps.OFF): # Turned left 1
|
||||
self.encoder_direction = self.edr.Left
|
||||
elif new_encoder_state == (self.eps.ON, self.eps.ON): # Turned right 1
|
||||
if self.encoder_direction == self.edr.Right:
|
||||
self.encoder_value = self.encoder_value + 1
|
||||
else: # self.encoder_state == '11'
|
||||
if new_encoder_state == (self.eps.ON, self.eps.OFF): # Turned left 1
|
||||
self.encoder_direction = self.edr.Left
|
||||
elif new_encoder_state == (self.eps.OFF, self.eps.ON): # Turned right 1
|
||||
self.encoder_direction = self.edr.Right # 'R'
|
||||
elif new_encoder_state == (
|
||||
self.eps.ON,
|
||||
self.eps.ON,
|
||||
): # Skipped intermediate 01 or 10 state, however turn completed
|
||||
if self.encoder_direction == self.edr.Left:
|
||||
self.encoder_value = self.encoder_value - 1
|
||||
elif self.encoder_direction == self.edr.Right:
|
||||
self.encoder_value = self.encoder_value + 1
|
||||
|
||||
self.encoder_state = new_encoder_state
|
||||
|
||||
if self.vel_mode:
|
||||
self.vel_ts = ticks_ms()
|
||||
|
||||
if self.encoder_state != self.last_encoder_state:
|
||||
self.position_change = self.invert_rotation(
|
||||
self.encoder_value, self.last_encoder_value
|
||||
)
|
||||
|
||||
self.last_encoder_state = self.encoder_state
|
||||
self.last_encoder_value = self.encoder_value
|
||||
|
||||
if self.position_change > 0:
|
||||
self._to_dict()
|
||||
# return self.increment_key
|
||||
return 0
|
||||
elif self.position_change < 0:
|
||||
self._to_dict()
|
||||
# return self.decrement_key
|
||||
return 1
|
||||
else:
|
||||
return None
|
||||
|
||||
# invert knob direction if encoder pins are soldered backwards
|
||||
def invert_rotation(self, new, old):
|
||||
if self.is_inverted:
|
||||
return -(new - old)
|
||||
else:
|
||||
return new - old
|
||||
|
||||
# returns knob velocity as milliseconds between position changes(detents)
|
||||
def vel_report(self):
|
||||
self.encoder_speed = self.vel_ts - self.last_vel_ts
|
||||
self.last_vel_ts = self.vel_ts
|
||||
return self.encoder_speed
|
||||
|
||||
|
||||
class EncoderHandler(Module):
|
||||
|
||||
encoders = []
|
||||
debug_enabled = False # not working as inttended, do not use for now
|
||||
|
||||
def __init__(self, pad_a, pad_b, encoder_map):
|
||||
self.pad_a = pad_a
|
||||
self.pad_b = pad_b
|
||||
self.encoder_count = len(self.pad_a)
|
||||
self.encoder_map = encoder_map
|
||||
self.make_encoders()
|
||||
|
||||
def on_runtime_enable(self, keyboard):
|
||||
return
|
||||
|
||||
def on_runtime_disable(self, keyboard):
|
||||
return
|
||||
|
||||
def during_bootup(self, keyboard):
|
||||
return
|
||||
|
||||
def before_matrix_scan(self, keyboard):
|
||||
'''
|
||||
Return value will be injected as an extra matrix update
|
||||
'''
|
||||
return self.get_reports(keyboard)
|
||||
|
||||
def after_matrix_scan(self, keyboard):
|
||||
'''
|
||||
Return value will be replace matrix update if supplied
|
||||
'''
|
||||
return
|
||||
|
||||
def before_hid_send(self, keyboard):
|
||||
return
|
||||
|
||||
def after_hid_send(self, keyboard):
|
||||
return
|
||||
|
||||
def on_powersave_enable(self, keyboard):
|
||||
return
|
||||
|
||||
def on_powersave_disable(self, keyboard):
|
||||
return
|
||||
|
||||
def make_encoders(self):
|
||||
for i in range(self.encoder_count):
|
||||
self.encoders.append(
|
||||
Encoder(
|
||||
self.pad_a[i], # encoder pin a
|
||||
self.pad_b[i], # encoder pin b
|
||||
)
|
||||
)
|
||||
|
||||
def send_encoder_keys(self, keyboard, encoder_key, encoder_idx):
|
||||
# position in the encoder map tuple
|
||||
encoder_resolution = 2
|
||||
for _ in range(
|
||||
self.encoder_map[keyboard.active_layers[0]][encoder_idx][encoder_resolution]
|
||||
):
|
||||
keyboard.tap_key(
|
||||
self.encoder_map[keyboard.active_layers[0]][encoder_idx][encoder_key]
|
||||
)
|
||||
return keyboard
|
||||
|
||||
def get_reports(self, keyboard):
|
||||
for idx in range(self.encoder_count):
|
||||
if self.debug_enabled: # not working as inttended, do not use for now
|
||||
print(self.encoders[idx].__repr__(idx))
|
||||
encoder_key = self.encoders[idx].report()
|
||||
if encoder_key is not None:
|
||||
return self.send_encoder_keys(keyboard, encoder_key, idx)
|
||||
@@ -64,7 +64,7 @@ class Split(Module):
|
||||
self.UARTService = UARTService
|
||||
except ImportError:
|
||||
print('BLE Import error')
|
||||
pass # BLE isn't supported on this platform
|
||||
return # BLE isn't supported on this platform
|
||||
self._ble = BLERadio()
|
||||
self._ble_last_scan = ticks_ms() - 5000
|
||||
self._connection_count = 0
|
||||
|
||||
+45
-296
@@ -7,11 +7,9 @@ import board
|
||||
# from adafruit_display_text import label
|
||||
from kb import KMKKeyboard
|
||||
|
||||
from kmk.extensions.rgb import RGB
|
||||
from kmk.hid import HIDModes
|
||||
from kmk.keys import KC
|
||||
from kmk.modules.layers import Layers
|
||||
from kmk.modules.power import Power
|
||||
from kmk.modules.split import Split, SplitType
|
||||
|
||||
keyboard = KMKKeyboard()
|
||||
@@ -20,36 +18,10 @@ keyboard = KMKKeyboard()
|
||||
keyboard.tap_time = 320
|
||||
keyboard.debug_enabled = False
|
||||
|
||||
rgb_ext = RGB(
|
||||
pixel_pin=keyboard.rgb_pixel_pin,
|
||||
num_pixels=6,
|
||||
val_limit=100,
|
||||
hue_default=190,
|
||||
sat_default=100,
|
||||
val_default=5,
|
||||
)
|
||||
|
||||
split = Split(split_type=SplitType.BLE)
|
||||
power = Power(powersave_pin=keyboard.powersave_pin)
|
||||
split = Split(split_type=SplitType.UART)
|
||||
layers = Layers()
|
||||
|
||||
keyboard.modules = [split, power, layers]
|
||||
keyboard.extensions = [rgb_ext]
|
||||
|
||||
enable_oled = False
|
||||
|
||||
'''
|
||||
if enable_oled:
|
||||
displayio.release_displays()
|
||||
i2c = board.I2C()
|
||||
display_bus = displayio.I2CDisplay(i2c, device_address=0x3c)
|
||||
display = adafruit_displayio_ssd1306.SSD1306(display_bus, width=128, height=32)
|
||||
splash = displayio.Group(max_size=10)
|
||||
display.show(splash)
|
||||
else:
|
||||
displayio.release_displays()
|
||||
'''
|
||||
keyboard.i2c_deinit_count += 1
|
||||
keyboard.modules = [split, layers]
|
||||
|
||||
_______ = KC.TRNS
|
||||
XXXXXXX = KC.NO
|
||||
@@ -74,49 +46,12 @@ keyboard.keymap = [
|
||||
#
|
||||
[
|
||||
# DVORAK
|
||||
KC.GESC,
|
||||
KC.QUOT,
|
||||
KC.COMM,
|
||||
KC.DOT,
|
||||
KC.P,
|
||||
KC.Y,
|
||||
KC.F,
|
||||
KC.G,
|
||||
KC.C,
|
||||
KC.R,
|
||||
KC.L,
|
||||
KC.BSPC,
|
||||
TAB_SB,
|
||||
KC.A,
|
||||
KC.O,
|
||||
KC.E,
|
||||
KC.U,
|
||||
KC.I,
|
||||
KC.D,
|
||||
KC.H,
|
||||
KC.T,
|
||||
KC.N,
|
||||
KC.S,
|
||||
KC.ENT,
|
||||
KC.LSFT,
|
||||
KC.SCLN,
|
||||
KC.Q,
|
||||
KC.J,
|
||||
KC.K,
|
||||
KC.X,
|
||||
KC.B,
|
||||
KC.M,
|
||||
KC.W,
|
||||
KC.V,
|
||||
KC.Z,
|
||||
KC.SLSH,
|
||||
KC.LALT,
|
||||
SUPER_L,
|
||||
LT1_SP,
|
||||
LT2_SP,
|
||||
KC.LCTL,
|
||||
KC.N0,
|
||||
KC.GESC, KC.QUOT, KC.COMM, KC.DOT, KC.P, KC.Y, KC.F, KC.G, KC.C, KC.R, KC.L, KC.BSPC, \
|
||||
TAB_SB, KC.A, KC.O, KC.E, KC.U, KC.I, KC.D, KC.H, KC.T, KC.N, KC.S, KC.ENT, \
|
||||
KC.LSFT, KC.SCLN, KC.Q, KC.J, KC.K, KC.X, KC.B, KC.M, KC.W, KC.V, KC.Z, KC.SLSH, \
|
||||
KC.LALT, SUPER_L, LT1_SP, LT2_SP, KC.LCTL, KC.NO,
|
||||
],
|
||||
|
||||
# GAMING
|
||||
# ,-----------------------------------------. ,-----------------------------------------.
|
||||
# | Tab | ' | , | . | P | Y | | F | G | C | R | L | BKSP |
|
||||
@@ -131,48 +66,10 @@ keyboard.keymap = [
|
||||
#
|
||||
[
|
||||
# GAMING
|
||||
KC.ESC,
|
||||
KC.QUOT,
|
||||
KC.COMM,
|
||||
KC.DOT,
|
||||
KC.P,
|
||||
KC.Y,
|
||||
KC.F,
|
||||
KC.G,
|
||||
KC.C,
|
||||
KC.R,
|
||||
KC.L,
|
||||
KC.BSPC,
|
||||
KC.LCTL,
|
||||
KC.A,
|
||||
KC.O,
|
||||
KC.E,
|
||||
KC.U,
|
||||
KC.I,
|
||||
KC.D,
|
||||
KC.H,
|
||||
KC.T,
|
||||
KC.N,
|
||||
KC.S,
|
||||
KC.ENT,
|
||||
KC.LSFT,
|
||||
KC.SCLN,
|
||||
KC.Q,
|
||||
KC.J,
|
||||
KC.K,
|
||||
KC.X,
|
||||
KC.B,
|
||||
KC.M,
|
||||
KC.W,
|
||||
KC.V,
|
||||
KC.Z,
|
||||
KC.SLSH,
|
||||
KC.LALT,
|
||||
KC.SPC,
|
||||
KC.SPC,
|
||||
LT2_SP,
|
||||
KC.LCTL,
|
||||
KC.UP,
|
||||
KC.ESC, KC.QUOT, KC.COMM, KC.DOT, KC.P, KC.Y, KC.F, KC.G, KC.C, KC.R, KC.L, KC.BSPC, \
|
||||
KC.LCTL, KC.A, KC.O, KC.E, KC.U, KC.I, KC.D, KC.H, KC.T, KC.N, KC.S, KC.ENT, \
|
||||
KC.LSFT, KC.SCLN, KC.Q, KC.J, KC.K, KC.X, KC.B, KC.M, KC.W, KC.V, KC.Z, KC.SLSH, \
|
||||
KC.LALT, KC.SPC, KC.SPC, LT2_SP, KC.LCTL, KC.UP,
|
||||
],
|
||||
# RAISE1
|
||||
# ,-----------------------------------------. ,-----------------------------------------.
|
||||
@@ -188,48 +85,10 @@ keyboard.keymap = [
|
||||
#
|
||||
[
|
||||
# RAISE1
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
KC.PS_TOG,
|
||||
XXXXXXX,
|
||||
KC.N7,
|
||||
KC.N8,
|
||||
KC.N9,
|
||||
KC.DEL,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
XXXXXXX,
|
||||
XXXXXXX,
|
||||
KC.N4,
|
||||
KC.N5,
|
||||
KC.N6,
|
||||
KC.BSLS,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
XXXXXXX,
|
||||
XXXXXXX,
|
||||
KC.N1,
|
||||
KC.N2,
|
||||
KC.N3,
|
||||
KC.MINS,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
KC.EQL,
|
||||
KC.N0,
|
||||
_______, _______, _______, _______, _______, _______, XXXXXXX, XXXXXXX, KC.N7, KC.N8, KC.N9, KC.DEL, \
|
||||
_______, _______, _______, _______, _______, _______, XXXXXXX, XXXXXXX, KC.N4, KC.N5, KC.N6, KC.BSLS, \
|
||||
_______, _______, _______, _______, _______, _______, XXXXXXX, XXXXXXX, KC.N1, KC.N2, KC.N3, KC.MINS, \
|
||||
_______, _______, _______, _______, KC.EQL, KC.N0,
|
||||
],
|
||||
# RAISE2
|
||||
# ,-----------------------------------------. ,-----------------------------------------.
|
||||
@@ -243,50 +102,13 @@ keyboard.keymap = [
|
||||
# | | |/ / \ \ | | |
|
||||
# `---------------------' '------''-------------'
|
||||
#
|
||||
|
||||
[
|
||||
# RAISE2
|
||||
_______,
|
||||
KC.F9,
|
||||
KC.F10,
|
||||
KC.F11,
|
||||
KC.F12,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
KC.LBRC,
|
||||
KC.RBRC,
|
||||
KC.LSHIFT(KC.INS),
|
||||
_______,
|
||||
KC.F5,
|
||||
KC.F6,
|
||||
KC.F7,
|
||||
KC.F8,
|
||||
_______,
|
||||
KC.HOME,
|
||||
KC.LEFT,
|
||||
KC.DOWN,
|
||||
KC.UP,
|
||||
KC.RGHT,
|
||||
KC.END,
|
||||
_______,
|
||||
KC.F1,
|
||||
KC.F2,
|
||||
KC.F3,
|
||||
KC.F4,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
KC.BSLS,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
KC.DF(0),
|
||||
KC.DF(1),
|
||||
_______, KC.F9, KC.F10, KC.F11, KC.F12, _______, _______, _______, _______, KC.LBRC, KC.RBRC, KC.LSHIFT(KC.INS), \
|
||||
_______, KC.F5, KC.F6, KC.F7, KC.F8, _______, KC.HOME, KC.LEFT, KC.DOWN, KC.UP, KC.RGHT, KC.END, \
|
||||
_______, KC.F1, KC.F2, KC.F3, KC.F4, _______, _______, _______, _______, _______, _______, KC.BSLS, \
|
||||
_______, _______, _______, _______, KC.DF(0), KC.DF(1),
|
||||
],
|
||||
# GUI
|
||||
# ,-----------------------------------------. ,-----------------------------------------.
|
||||
@@ -299,109 +121,36 @@ keyboard.keymap = [
|
||||
# | LALT | LGUI | /LT1_SP / \LT2_SP\ | | |
|
||||
# | | |/ / \ \ | | |
|
||||
# `---------------------' '------''-------------'
|
||||
|
||||
[
|
||||
# GUI
|
||||
_______,
|
||||
KC.N1,
|
||||
KC.N2,
|
||||
KC.N3,
|
||||
KC.N4,
|
||||
KC.N5,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
KC.N6,
|
||||
KC.N7,
|
||||
KC.N8,
|
||||
KC.N9,
|
||||
KC.N0,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______, KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, _______, _______, _______, _______, _______, _______, \
|
||||
_______, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0, _______, _______, _______, _______, _______, _______, \
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
|
||||
|
||||
_______, _______, _______, _______, _______, _______ \
|
||||
],
|
||||
# SYMBOLS
|
||||
# ,-----------------------------------------. ,-----------------------------------------.
|
||||
# | | ! | @ | # | $ | % | | ^ | & | * | ( | ) | Del |
|
||||
# |------+------+------+------+------+------| |------+------+------+------+------+------|
|
||||
# | | | | | | | | | | | [ | ] | |
|
||||
# |------+------+------+------+------+------| |------+------+------+------+------+------|
|
||||
# | | | | | | |-------. ,-------| | | | | | |
|
||||
# `-----------------------------------------/ / \ \-----------------------------------------'
|
||||
# | LALT | LGUI | /LT1_SP / \LT2_SP\ | | |
|
||||
# | | |/ / \ \ | | |
|
||||
# `---------------------' '------''-------------'
|
||||
#
|
||||
# SYMBOLS
|
||||
# ,-----------------------------------------. ,-----------------------------------------.
|
||||
# | | ! | @ | # | $ | % | | ^ | & | * | ( | ) | Del |
|
||||
# |------+------+------+------+------+------| |------+------+------+------+------+------|
|
||||
# | | | | | | | | | | | [ | ] | |
|
||||
# |------+------+------+------+------+------| |------+------+------+------+------+------|
|
||||
# | | | | | | |-------. ,-------| | | | | | |
|
||||
# `-----------------------------------------/ / \ \-----------------------------------------'
|
||||
# | LALT | LGUI | /LT1_SP / \LT2_SP\ | | |
|
||||
# | | |/ / \ \ | | |
|
||||
# `---------------------' '------''-------------'
|
||||
#
|
||||
[
|
||||
# SYMBOLS
|
||||
_______,
|
||||
KC.EXLM,
|
||||
KC.AT,
|
||||
KC.HASH,
|
||||
KC.DLR,
|
||||
KC.PERC,
|
||||
KC.CIRC,
|
||||
KC.AMPR,
|
||||
KC.ASTR,
|
||||
KC.LPRN,
|
||||
KC.RPRN,
|
||||
KC.DEL,
|
||||
_______,
|
||||
KC.RGB_HUI,
|
||||
KC.RGB_HUD,
|
||||
KC.RGB_VAI,
|
||||
KC.RGB_VAD,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
KC.LBRC,
|
||||
KC.RBRC,
|
||||
_______,
|
||||
_______,
|
||||
KC.RGB_RST,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
KC.RGB_TOG,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
_______,
|
||||
],
|
||||
_______, KC.EXLM, KC.AT, KC.HASH, KC.DLR, KC.PERC, KC.CIRC, KC.AMPR, KC.ASTR, KC.LPRN, KC.RPRN, KC.DEL, \
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, KC.LBRC, KC.RBRC, _______, \
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
|
||||
_______, _______, _______, _______, _______, _______,
|
||||
]
|
||||
|
||||
]
|
||||
|
||||
if __name__ == '__main__':
|
||||
keyboard.go(hid_type=HIDModes.BLE)
|
||||
keyboard.go(hid_type=HIDModes.USB)
|
||||
Reference in new issue
Block a user