1 Commits

Author SHA1 Message Date
xs5871
490e94e4e3 Add option to select specific unit test to Makefile 2023-02-15 09:13:09 +00:00
68 changed files with 615 additions and 687 deletions

View File

@@ -30,19 +30,19 @@ TIMESTAMP := $(shell date +%s)
all: copy-kmk copy-bootpy copy-keymap copy-board
.PHONY: compile compile-check
compile: compile-check
compile: $(MPY_TARGET_DIR)/.mpy.compiled
$(MPY_TARGET_DIR)/.mpy.compiled: $(PY_KMK_TREE)
ifeq ($(MPY_CROSS),)
compile-check:
@echo "===> Could not find mpy-cross in PATH, exiting"
@false
else
compile-check: $(PY_KMK_TREE:%.py=$(MPY_TARGET_DIR)/%.mpy)
@echo "===> Compiling all py files to mpy with flags $(MPY_FLAGS)"
$(MPY_TARGET_DIR)/%.mpy: %.py
@mkdir -p $(dir $@)
@$(MPY_CROSS) $(MPY_FLAGS) $? -o $@
endif
@echo "===> Compiling all py files to mpy with flags $(MPY_FLAGS)"
@mkdir -p $(MPY_TARGET_DIR)
@echo "KMK_RELEASE = '$(DIST_DESCRIBE)'" > $(MPY_SOURCES)/release_info.py
@find $(MPY_SOURCES) -name "*.py" -exec sh -c 'mkdir -p $(MPY_TARGET_DIR)/$$(dirname {}) && $(MPY_CROSS) $(MPY_FLAGS) {} -o $(MPY_TARGET_DIR)/$$(dirname {})/$$(basename -s .py {}).mpy' \;
@rm -rf $(MPY_SOURCES)/release_info.py
@touch $(MPY_TARGET_DIR)/.mpy.compiled
.devdeps: Pipfile.lock
@echo "===> Installing dependencies with pipenv"
@@ -92,7 +92,7 @@ test: lint unit-tests
.PHONY: unit-tests
unit-tests: devdeps
@$(PIPENV) run python3 -m unittest $(TESTS)
@$(PIPENV) run python3 -m unittest ${TESTS}
reset-bootloader:
@echo "===> Rebooting your board to bootloader (safe to ignore file not found errors)"
@@ -102,44 +102,55 @@ reset-board:
@echo "===> Rebooting your board (safe to ignore file not found errors)"
@-timeout -k 5s 10s $(PIPENV) run ampy -p /dev/ttyACM0 -d ${AMPY_DELAY} -b ${AMPY_BAUD} run util/reset.py
ifdef MOUNTPOINT
$(MOUNTPOINT)/kmk/.copied: $(shell find kmk/ -name "*.py" | xargs -0)
@echo "===> Copying KMK source folder"
@rsync -rh kmk $(MOUNTPOINT)/
@touch $(MOUNTPOINT)/kmk/.copied
@sync
copy-kmk: $(MOUNTPOINT)/kmk/.copied
else
copy-kmk:
echo "**** MOUNTPOINT must be defined (wherever your CIRCUITPY drive is mounted) ****" && exit 1
endif
copy-board: $(MOUNTPOINT)/kb.py
$(MOUNTPOINT)/kb.py: $(BOARD)
@echo "===> Copying your board to kb.py"
@rsync -rh $(BOARD) $@
@sync
ifdef MOUNTPOINT
ifdef BOARD
copy-board:
@echo "===> Copying your board from $(BOARD) to $(MOUNTPOINT)"
@rsync -rhu $(BOARD)/*.py $(MOUNTPOINT)/
@sync
else # BOARD
copy-board:
@echo "**** Missing BOARD argument ****" && exit 1
endif # BOARD
copy-bootpy:
$(MOUNTPOINT)/kmk/boot.py: boot.py
@echo "===> Copying required boot.py"
@rsync -rhu boot.py $(MOUNTPOINT)/boot.py
@rsync -rh boot.py $(MOUNTPOINT)/
@sync
copy-compiled:
@echo "===> Copying compiled KMK folder"
@rsync -rhu $(MPY_TARGET_DIR)/* $(MOUNTPOINT)/
@sync
copy-bootpy: $(MOUNTPOINT)/kmk/boot.py
else
copy-bootpy:
echo "**** MOUNTPOINT must be defined (wherever your CIRCUITPY drive is mounted) ****" && exit 1
endif
ifdef USER_KEYMAP
copy-keymap:
ifdef MOUNTPOINT
ifndef USER_KEYMAP
$(MOUNTPOINT)/main.py:
@echo "**** USER_KEYMAP must be defined (ex. USER_KEYMAP=user_keymaps/noop.py) ****" && exit 1
else
$(MOUNTPOINT)/main.py: $(USER_KEYMAP)
@echo "===> Copying your keymap to main.py"
@rsync -rhu $(USER_KEYMAP) $(MOUNTPOINT)/main.py
@rsync -rh $(USER_KEYMAP) $@
@sync
else # USER_KEYMAP
copy-keymap:
@echo "**** Missing USER_KEYMAP argument ****" && exit 1
endif # USER_KEYMAP
copy-kmk:
@echo "===> Copying KMK source folder"
@rsync -rhu kmk $(MOUNTPOINT)/
@sync
copy-keymap: $(MOUNTPOINT)/main.py
else
copy-keymap:
echo "**** MOUNTPOINT must be defined (wherever your CIRCUITPY drive is mounted) ****" && exit 1
else # MOUNTPOINT
copy-board copy-bootpy copy-compiled copy-keymap copy-kmk:
@echo "**** MOUNTPOINT must be defined (wherever your CIRCUITPY drive is mounted) ****" && exit 1
endif # ifndef MOUNTPOINT
ifdef BOARD
copy-board: $(MOUNTPOINT)/kb.py
endif # BOARD
endif # MOUNTPOINT

View File

@@ -15,7 +15,6 @@ knob.extensions.append(media_keys)
# Rotary encoder that also acts as a key
encoder_handler = EncoderHandler()
encoder_handler.divisor = 2
encoder_handler.pins = ((board.D1, board.D2, board.D0),)
encoder_handler.map = (((KC.VOLD, KC.VOLU, KC.MUTE),),)
knob.modules.append(encoder_handler)

View File

@@ -15,7 +15,6 @@ knob.extensions.append(media_keys)
# Rotary encoders that also acts as keys
encoder_handler = EncoderHandler()
encoder_handler.divisor = 2
encoder_handler.pins = (
(board.D1, board.D2, board.D0),
(board.D9, board.D10, board.D3),

View File

@@ -78,7 +78,6 @@ keyboard.keymap = [
# Rotary encoder that also acts as a key
encoder_handler = EncoderHandler()
encoder_handler.divisor = 2
encoder_handler.pins = ((board.D8, board.D7, board.D9),)
encoder_handler.map = (((KC.VOLD, KC.VOLU, KC.MUTE),),)
keyboard.modules.append(encoder_handler)

View File

@@ -12,15 +12,15 @@ from kmk.extensions.peg_rgb_matrix import Rgb_matrix
from kmk.handlers.sequences import send_string
from kmk.hid import HIDModes
from kmk.keys import KC
from kmk.modules.holdtap import HoldTap
from kmk.modules.layers import Layers
from kmk.modules.modtap import ModTap
from kmk.modules.split import Split, SplitSide, SplitType
keyboard = KMKKeyboard()
holdtap = HoldTap()
modtap = ModTap()
layers_ext = Layers()
keyboard.modules.append(layers_ext)
keyboard.modules.append(holdtap)
keyboard.modules.append(modtap)
oled_ext = Oled(
OledData(

View File

@@ -12,7 +12,7 @@ Retailers (USA)
Extensions enabled by default
- [Layers](/docs/en/layers.md) Need more keys than switches? Use layers.
- [BLE_Split](/docs/en/split_keyboards.md) Connects halves without wires
- [HoldTap](/docs/en/holdtap.md) Allows mod keys to act as different keys when tapped.
- [ModTap](/docs/en/modtap.md) Allows mod keys to act as different keys when tapped.
Common Extensions
- [Split](/docs/en/split_keyboards.md) Connects halves using a wire

View File

@@ -3,16 +3,16 @@ import board
from kb import KMKKeyboard
from kmk.keys import KC
from kmk.modules.holdtap import HoldTap
from kmk.modules.layers import Layers
from kmk.modules.modtap import ModTap
from kmk.scanners import DiodeOrientation
keyboard = KMKKeyboard()
keyboard.modules.append(Layers())
holdtap = HoldTap()
keyboard.modules.append(holdtap)
modtap = ModTap()
keyboard.modules.append(modtap)
NONE = KC.NO
@@ -25,9 +25,9 @@ CAD = KC.LCTL(KC.LALT(KC.DEL))
ZSFT = KC.HT(KC.Z, KC.LSFT, prefer_hold=True, tap_interrupted=False, tap_time=3000)
SLSHSFT = KC.HT(KC.SLSH, KC.LSFT, prefer_hold=True, tap_interrupted=False, tap_time=3000)
ALCTL = KC.HT(KC.A, KC.LCTRL, prefer_hold=False, tap_interrupted=False, tap_time=150)
ZSFT = KC.MT(KC.Z, KC.LSFT, prefer_hold=True, tap_interrupted=False, tap_time=3000)
SLSHSFT = KC.MT(KC.SLSH, KC.LSFT, prefer_hold=True, tap_interrupted=False, tap_time=3000)
ALCTL = KC.MT(KC.A, KC.LCTRL, prefer_hold=False, tap_interrupted=False, tap_time=150)
# flake8: noqa: E261
keyboard.keymap = [

View File

@@ -3,12 +3,13 @@
import board
from storage import getmount
from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard
from kmk.quickpin.pro_micro.kb2040 import pinout as pins
from kmk.scanners.keypad import KeysScanner
from storage import getmount
# GPIO to key mapping - each line is a new row.
# fmt: off
_KEY_CFG_LEFT = [

View File

@@ -3,12 +3,11 @@
# https://github.com/qmk/qmk_firmware/tree/master/keyboards/ferris/keymaps/default
import board
from kb import KMKKeyboard
from kmk.keys import KC
from kmk.modules.holdtap import HoldTap
from kmk.modules.layers import Layers
from kmk.modules.modtap import ModTap
from kmk.modules.mouse_keys import MouseKeys
from kmk.modules.split import Split, SplitSide
@@ -28,7 +27,7 @@ split = Split(
)
layers_ext = Layers()
holdtap = HoldTap()
mod_tap = ModTap()
mouse_key = MouseKeys()
@@ -40,12 +39,12 @@ XXXXXXX = KC.NO
# Mod-taps
A_SFT = KC.HT(KC.A, KC.LSFT)
SCLN_SFT = KC.HT(KC.SCLN, KC.LSFT)
X_CTL = KC.HT(KC.X, KC.LCTRL)
C_ALT = KC.HT(KC.C, KC.LALT)
COM_ALT = KC.HT(KC.COMM, KC.LALT)
DOT_CTL = KC.HT(KC.DOT, KC.LCTRL)
A_SFT = KC.MT(KC.A, KC.LSFT)
SCLN_SFT = KC.MT(KC.SCLN, KC.LSFT)
X_CTL = KC.MT(KC.X, KC.LCTRL)
C_ALT = KC.MT(KC.C, KC.LALT)
COM_ALT = KC.MT(KC.COMM, KC.LALT)
DOT_CTL = KC.MT(KC.DOT, KC.LCTRL)
CTL_ALT = KC.LCTRL(KC.LALT)

View File

@@ -6,8 +6,8 @@ from kmk.extensions.media_keys import MediaKeys
from kmk.extensions.rgb import RGB
from kmk.keys import KC
from kmk.modules.encoder import EncoderHandler
from kmk.modules.holdtap import HoldTap
from kmk.modules.layers import Layers
from kmk.modules.modtap import ModTap
from kmk.modules.mouse_keys import MouseKeys
keyboard = KMKKeyboard()
@@ -21,13 +21,13 @@ XXXXXXX = KC.NO
# Adding extensions
rgb = RGB(pixel_pin=keyboard.rgb_pixel_pin, num_pixels=keyboard.rgb_num_pixels, val_limit=50, hue_default=190, sat_default=100, val_default=5)
holdtap = HoldTap()
modtap = ModTap()
layers = Layers()
media_keys = MediaKeys()
encoder_handler = EncoderHandler()
keyboard.modules = [layers, holdtap] #, encoder_handler]
keyboard.modules = [layers, modtap] #, encoder_handler]
keyboard.modules.append(MouseKeys())
keyboard.extensions = [rgb, media_keys]
@@ -46,14 +46,14 @@ MEDIA_BSPC = KC.LT(LYR_MEDIA, KC.BSPC)
MOUSE_M = KC.LT(LYR_MOUSE, KC.M)
# HOMEROW MODS
LCTL_A = KC.HT(KC.A, KC.LCTRL)
LGUI_R = KC.HT(KC.R, KC.LGUI)
LALT_S = KC.HT(KC.S, KC.LALT)
LSFT_T = KC.HT(KC.T, KC.LSFT)
RSFT_N = KC.HT(KC.N, KC.RSFT)
RALT_E = KC.HT(KC.E, KC.RALT)
RGUI_I = KC.HT(KC.I, KC.RGUI)
RCTL_O = KC.HT(KC.O, KC.RCTRL)
LCTL_A = KC.MT(KC.A, KC.LCTRL)
LGUI_R = KC.MT(KC.R, KC.LGUI)
LALT_S = KC.MT(KC.S, KC.LALT)
LSFT_T = KC.MT(KC.T, KC.LSFT)
RSFT_N = KC.MT(KC.N, KC.RSFT)
RALT_E = KC.MT(KC.E, KC.RALT)
RGUI_I = KC.MT(KC.I, KC.RGUI)
RCTL_O = KC.MT(KC.O, KC.RCTRL)
# OTHER SHORTCUTS
BRWSR_LFT = KC.LCTRL(KC.LSFT(KC.TAB))

View File

@@ -8,7 +8,7 @@ Hardware Availability: [Gherkin project on 40% Keyboards](http://www.40percent.c
Extensions enabled by default
- [Layers](/docs/en/layers.md) Need more keys than switches? Use layers.
- [HoldTap](/docs/en/holdtap.md) Allows mod keys to act as different keys when tapped.
- [ModTap](/docs/en/modtap.md) Allows mod keys to act as different keys when tapped.
- [LED](/docs/en/led.md) Light your keys up
Common Extensions

View File

@@ -2,17 +2,17 @@ from kb import KMKKeyboard
from kmk.extensions.led import LED
from kmk.keys import KC
from kmk.modules.holdtap import HoldTap
from kmk.modules.layers import Layers
from kmk.modules.modtap import ModTap
keyboard = KMKKeyboard()
holdtap = HoldTap()
modtap = ModTap()
layers_ext = Layers()
led = LED()
keyboard.extensions = [led]
keyboard.modules = [layers_ext, holdtap]
keyboard.modules = [layers_ext, modtap]
# Cleaner key names
_______ = KC.TRNS

View File

@@ -2,7 +2,6 @@ from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard
from kmk.quickpin.pro_micro.sparkfun_promicro_rp2040 import pinout as pins
from kmk.scanners import DiodeOrientation
class KMKKeyboard(_KMKKeyboard):
col_pins = (
pins[19],

View File

@@ -31,7 +31,7 @@ It has the following modules/extensions enabled:
- [Split](/docs/en/split_keyboards.md) Connects halves using a wire
- [Layers](/docs/en/layers.md) Do you need more keys than switches? Use
layers.
- [HoldTap](/docs/en/holdtap.md) Enable press/hold double binding of keys
- [ModTap](/docs/en/modtap.md) Enable press/hold double binding of keys
- [MediaKeys](/docs/en/media_keys.md) Common media controls
Also uncomment right section to enable samples of following:

View File

@@ -4,15 +4,15 @@ from kmk.extensions.media_keys import MediaKeys
from kmk.extensions.rgb import RGB, AnimationModes
from kmk.keys import KC
from kmk.modules.encoder import EncoderHandler
from kmk.modules.holdtap import HoldTap
from kmk.modules.layers import Layers
from kmk.modules.modtap import ModTap
from kmk.modules.split import Split, SplitType
keyboard = KMKKeyboard()
keyboard.debug_enabled = True
keyboard.modules.append(Layers())
keyboard.modules.append(HoldTap())
keyboard.modules.append(ModTap())
keyboard.extensions.append(MediaKeys())
# Using drive names (KYRIAL, KYRIAR) to recognize sides; use split_side arg if you're not doing it
@@ -33,10 +33,10 @@ keyboard.extensions.append(rgb_ext)
# Edit your layout below
# Currently, that's a default QMK Kyria Layout - https://config.qmk.fm/#/splitkb/kyria/rev1/LAYOUT
ESC_LCTL = KC.HT(KC.ESC, KC.LCTL)
QUOTE_RCTL = KC.HT(KC.QUOTE, KC.RCTL)
ENT_LALT = KC.HT(KC.ENT, KC.LALT)
MINUS_RCTL = KC.HT(KC.MINUS, KC.RCTL)
ESC_LCTL = KC.MT(KC.ESC, KC.LCTL)
QUOTE_RCTL = KC.MT(KC.QUOTE, KC.RCTL)
ENT_LALT = KC.MT(KC.ENT, KC.LALT)
MINUS_RCTL = KC.MT(KC.MINUS, KC.RCTL)
keyboard.keymap = [
[
KC.TAB, KC.Q, KC.W, KC.E, KC.R, KC.T, KC.Y, KC.U, KC.I, KC.O, KC.P, KC.BSPC,

View File

@@ -8,8 +8,8 @@ from kb import KMKKeyboard
from kmk.extensions.media_keys import MediaKeys
from kmk.extensions.RGB import RGB, AnimationModes
from kmk.keys import KC
from kmk.modules.holdtap import HoldTap
from kmk.modules.layers import Layers
from kmk.modules.modtap import ModTap
from kmk.modules.split import Split, SplitSide, SplitType
led = digitalio.DigitalInOut(board.GP25)
@@ -20,7 +20,7 @@ keyboard = KMKKeyboard()
keyboard.tap_time = 100
layers_ext = Layers()
holdtap_ext = HoldTap()
modtap_ext = ModTap()
# TODO Comment one of these on each side
split_side = SplitSide.LEFT
@@ -43,7 +43,7 @@ rgb_ext = RGB(
animation_mode=AnimationModes.BREATHING_RAINBOW
)
keyboard.modules = [layers_ext, holdtap_ext, split]
keyboard.modules = [layers_ext, modtap_ext, split]
keyboard.extensions.append(MediaKeys())
keyboard.extensions.append(rgb_ext)
@@ -61,9 +61,9 @@ if split_side == SplitSide.LEFT:
LOWER = KC.MO(1)
RAISE = KC.MO(2)
ADJUST = KC.MO(3)
CT_TAB = KC.HT(KC.TAB, KC.LCTRL)
CT_QUOT = KC.HT(KC.QUOT, KC.LCTRL)
SF_MINS = KC.HT(KC.MINS, KC.LSHIFT)
CT_TAB = KC.MT(KC.TAB, KC.LCTRL)
CT_QUOT = KC.MT(KC.QUOT, KC.LCTRL)
SF_MINS = KC.MT(KC.MINS, KC.LSHIFT)
SG_PSCR = KC.LSFT(KC.LGUI(KC.PSCR))
SF_PSCR = KC.LSFT(KC.PSCR)
CG_RGHT = KC.LCTRL(KC.LGUI(KC.RGHT))

View File

@@ -17,7 +17,7 @@ Retailers (USA)
Extensions enabled by default
- [Layers](/docs/en/layers.md) Need more keys than switches? Use layers.
- [RGB](/docs/en/rgb.md) Light it up
- [HoldTap](/docs/en/holdtap.md) Allows mod keys to act as different keys when tapped.
- [ModTap](/docs/en/modtap.md) Allows mod keys to act as different keys when tapped.
Common Extensions
- [Power](/docs/en/power.md) Powersaving features for battery life

View File

@@ -2,18 +2,18 @@ from kb import KMKKeyboard
from kmk.extensions.rgb import RGB
from kmk.keys import KC
from kmk.modules.holdtap import HoldTap
from kmk.modules.layers import Layers
from kmk.modules.modtap import ModTap
keyboard = KMKKeyboard()
# Adding extensions
rgb = RGB(pixel_pin=keyboard.rgb_pixel_pin, num_pixels=keyboard.rgb_num_pixels, val_limit=100, hue_default=190, sat_default=100, val_default=5)
holdtap = HoldTap()
modtap = ModTap()
layers_ext = Layers()
keyboard.modules = [layers_ext, holdtap]
keyboard.modules = [layers_ext, modtap]
keyboard.extensions = [rgb]
# Cleaner key names

View File

@@ -18,7 +18,7 @@ Retailers (USA)
Extensions enabled by default
- [Layers](/docs/en/layers.md) Need more keys than switches? Use layers.
- [RGB](/docs/en/rgb.md) Light it up
- [HoldTap](/docs/en/holdtap.md) Allows mod keys to act as different keys when tapped.
- [ModTap](/docs/en/modtap.md) Allows mod keys to act as different keys when tapped.
Common Extensions
- [Power](/docs/en/power.md) Powersaving features for battery life

View File

@@ -2,18 +2,18 @@ from kb import KMKKeyboard
from kmk.extensions.rgb import RGB
from kmk.keys import KC
from kmk.modules.holdtap import HoldTap
from kmk.modules.layers import Layers
from kmk.modules.modtap import ModTap
keyboard = KMKKeyboard()
# Adding extensions
rgb = RGB(pixel_pin=keyboard.rgb_pixel_pin, num_pixels=keyboard.rgb_num_pixels, val_limit=100, hue_default=190, sat_default=100, val_default=5)
holdtap = HoldTap()
modtap = ModTap()
layers_ext = Layers()
keyboard.modules = [layers_ext, holdtap]
keyboard.modules = [layers_ext, modtap]
keyboard.extensions = [rgb]
# Cleaner key names
@@ -23,8 +23,8 @@ XXXXXXX = KC.NO
LOWER = KC.MO(1)
RAISE = KC.MO(2)
ADJUST = KC.LT(3, KC.SPC)
RSFT_ENT = KC.HT(KC.ENT, KC.RSFT)
RSFT_SPC = KC.HT(KC.SPC, KC.RSFT)
RSFT_ENT = KC.MT(KC.ENT, KC.RSFT)
RSFT_SPC = KC.MT(KC.SPC, KC.RSFT)
RGB_TOG = KC.RGB_TOG
RGB_HUI = KC.RGB_HUI

View File

@@ -14,7 +14,7 @@ Retailers (USA)
Extensions enabled by default
- [Layers](/docs/en/layers.md) Need more keys than switches? Use layers.
- [BLE_Split](/docs/en/split_keyboards.md) Connects halves without wires
- [HoldTap](/docs/en/holdtap.md) Allows mod keys to act as different keys when tapped.
- [ModTap](/docs/en/modtap.md) Allows mod keys to act as different keys when tapped.
Common Extensions
- [Split](/docs/en/split_keyboards.md) Connects halves using a wire

View File

@@ -12,15 +12,15 @@ from kmk.extensions.peg_rgb_matrix import Rgb_matrix
from kmk.handlers.sequences import send_string
from kmk.hid import HIDModes
from kmk.keys import KC
from kmk.modules.holdtap import HoldTap
from kmk.modules.layers import Layers
from kmk.modules.modtap import ModTap
from kmk.modules.split import Split, SplitSide, SplitType
keyboard = KMKKeyboard()
holdtap = HoldTap()
modtap = ModTap()
layers_ext = Layers()
keyboard.modules.append(layers_ext)
keyboard.modules.append(holdtap)
keyboard.modules.append(modtap)
oled_ext = Oled(
OledData(

View File

@@ -2,8 +2,9 @@
> Life was like a box of chocolates. You never know what you're gonna get.
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). KMK requires CircuitPython version 7.0 or above.
Known working and recommended devices can be found in the [list of officially supported microcontrollers](Officially_Supported_Microcontrollers.md)
Known working and recommended devices can be found [here](Officially_Supported_Microcontrollers.md)
<br>
## TL;DR Quick start guide
> To infinity and beyond!
@@ -12,7 +13,7 @@ Known working and recommended devices can be found in the [list of officially su
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:
***IMPORTANT:*** adapt the GP0 / GP1 pins to your specific board !
***IMPORTANT:*** adapt the GP0 / GP1 pins to your specific board ! <br>
```
print("Starting")
@@ -44,31 +45,31 @@ if __name__ == '__main__':
6. If it prints the letter "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 in the repositories [boards folder](https://github.com/KMKfw/kmk_firmware/tree/master/boards).
You will need the `kb.py` and `main.py`. If you need more detailed instructions on how to customize the configuration settings and key mappings, please refer to the [config and keymap](config_and_keymap.md) documentation.
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/kmk_firmware/tree/master/boards). You will need the `kb.py` and `main.py`. More advanced instructions can be found [here](config_and_keymap.md).
### You've got another, maybe DIY, board and want to customize KMK for it
First, be sure to understand how your device work, and particularly its specific matrix configuration. You can have a look at [how key matrices work](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
Once you've got the gist of it:
- To start customizing your `code.py`/`main.py` file, please refer to the [config and keymap](config_and_keymap.md) and [keys](keys.md) files respectively, which provide detailed instructions on how to modify the configuration settings and key mappings.
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
- [HoldTap](holdtap.md) allow you to customize the way a key behaves whether it is tapped or hold, and [TapDance](tapdance.md) depending on the number of times it is pressed
- [ModTap](modtap.md) allow you to customize the way a key behaves whether 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/kmk_firmware/tree/master/user_keymaps) that we provide and dig into our [documentation](README.md).
<br>
## Additional help and support
> Roads? Where we're going we don't need roads.

View File

@@ -25,7 +25,7 @@
- [Combos](combos.md): Adds chords and sequences
- [Layers](layers.md): Adds layer support (Fn key) to allow many more keys to be put on your keyboard
- [HoldTap](holdtap.md): Adds support for augmented modifier keys to act as one key when tapped, and modifier when held.
- [ModTap](modtap.md): Adds support for augmented modifier keys to act as one key when tapped, and modifier when held.
- [Mouse keys](mouse_keys.md): Adds mouse keycodes
- [OneShot](oneshot.md): Adds support for oneshot/sticky keys.
- [Power](power.md): Power saving features. This is mostly useful when on battery power.

View File

@@ -3,8 +3,8 @@ Bluetooth connections help clean up the wire mess!
## CircuitPython
If not running KMKPython, this does require the adafruit_ble library from Adafruit.
This can be downloaded from the
[Adafruit CircuitPython BLE repository](https://github.com/adafruit/Adafruit_CircuitPython_BLE/tree/master/adafruit_ble).
This can be downloaded
[here](https://github.com/adafruit/Adafruit_CircuitPython_BLE/tree/master/adafruit_ble).
It is part of the [Adafruit CircuitPython Bundle](https://github.com/adafruit/Adafruit_CircuitPython_Bundle).
Simply put this in the "root" of your CircuitPython device. If unsure, it's the folder with main.py in it, and should be the first folder you see when you open the device.

View File

@@ -1,6 +1,6 @@
# CapsWord
The CapsWord module functions similar to caps lock but will deactivate automatically when its encounters a key that breaks the word or after inactivity timeout.
By default it will not deactivate CapsWord on numbers, alphabets, underscore, modifiers, minus, backspace and other keys like HoldTap, Layers, etc.
By default it will not deactivate CapsWord on numbers, alphabets, underscore, modifiers, minus, backspace and other keys like ModTap, Layers, etc.
Add it to your keyboard's modules list with:
```python

View File

@@ -27,12 +27,9 @@ to Black formatting as documented in `pyproject.toml`)
Unit tests within the `tests` folder mock various CircuitPython modules to allow
them to be executed in a desktop development environment.
Execute tests using the command `make unit-tests`. The unit-tests target accepts
an optional environment variable for specifying a subset of tests with python
unittest syntax:
```sh
make unit-tests TESTS="tests.test_capsword tests.test_hold_tap"
```
Execute tests using the command `make unit-tests`. The `unit-tests` target
accepts an additional environment variable for selection of specific tests,
example `make unit-tests TESTS="tests.test_kmk_keys tests.test_layers"`.
## Contributing Documentation
While KMK welcomes documentation from anyone with and understanding of the issues
@@ -40,8 +37,8 @@ and a willingness to write them up, it's a good idea to familiarize yourself wit
the docs. Documentation should be informative but concise.
### Styling
Docs are written and rendered in GitHub Markdown.
Check out this comprehensive [guide to basic writing and formatting syntax](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax) from GitHub's documentation.
Docs are written and rendered in GitHub Markdown. A comprehensive guide to GitHub's
Markdown can be found [here](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax).
In particular, KMK's docs should include a title, demarcated with `#`, and subheadings
should be demarcated with `##`, `###`, and so on. Headings should be short and specific.

View File

@@ -23,7 +23,7 @@ Here is all you need to use this module in your `main.py` / `code.py` file.
```python
from kmk.modules.encoder import EncoderHandler
encoder_handler = EncoderHandler()
keyboard.modules = [layers, holdtap, encoder_handler]
keyboard.modules = [layers, modtap, encoder_handler]
```
2. Define the pins for each encoder: `pin_a`, `pin_b` for rotations, `pin_button` for the switch in the encoder. Set switch to `None` if the encoder's button is handled differently (as a part of matrix for example) or not at all. If you want to invert the direction of the encoder, set the 4th (optional) parameter `is_inverted` to `True`. 5th parameter is [encoder divisor](#encoder-resolution) (optional), it can be either `2` or `4`.

View File

@@ -24,8 +24,9 @@ make MOUNTPOINT=/media/CIRCUITPY USER_KEYMAP=user_keymaps/nameofyourkeymap.py BO
Check to see if your drive may have mounted elsewhere with a GUI tool or other
automounter. Most of these tools will mount your device under `/media`, probably
as `/media/CIRCUITPY`. If it's not mounted, you can read up on how to [mount a
drive manually](https://wiki.archlinux.org/index.php/File_systems#Mount_a_file_system).
as `/media/CIRCUITPY`. If it's not mounted, you can read up on how to mount a
drive manually
[here](https://wiki.archlinux.org/index.php/File_systems#Mount_a_file_system).
For example,

View File

@@ -1,6 +1,6 @@
# Handwire keyboards
This guide will not talk about the physical wiring. Check out our
[recommended microcontrollers](Officially_Supported_Microcontrollers.md) and
follow this amazing [hand wiring guide](https://docs.qmk.fm/#/hand_wire). That
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)

View File

@@ -15,7 +15,7 @@ the box.
### CircuitPython
CircuitPython can be installed by following this guide using the guide
for [installing circuit python](https://learn.adafruit.com/welcome-to-circuitpython/installing-circuitpython).
[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

View File

@@ -21,7 +21,7 @@ keyboard.modules.append(Layers())
## Custom HoldTap Behavior
`KC.TT` and `KC.LT` use the same heuristic to determine taps and holds as
HoldTap. Check out the [HoldTap doc](holdtap.md) to find out more.
ModTap. Check out the [ModTap doc](modtap.md) to find out more.
## Working with Layers
When starting out, care should be taken when working with layers, since it's possible to lock

View File

@@ -1,39 +1,39 @@
# HoldTap Keycodes
Enabling HoldTap will give you access to the following keycodes and can simply be
# ModTap Keycodes
Enabling ModTap will give you access to the following keycodes and can simply be
added to the modules list.
```python
from kmk.modules.holdtap import HoldTap
holdtap = HoldTap()
from kmk.modules.modtap import ModTap
modtap = ModTap()
# optional: set a custom tap timeout in ms
# holdtap.tap_time = 300
keyboard.modules.append(holdtap)
# modtap.tap_time = 300
keyboard.modules.append(modtap)
```
## Keycodes
|New Keycode | Description |
|---------------------------------------------------------|-----------------------------------------------------------------|
|`LCTL = KC.HT(KC.SOMETHING, KC.LCTRL)` |`LCTRL` if held `kc` if tapped |
|`LSFT = KC.HT(KC.SOMETHING, KC.LSFT)` |`LSHIFT` if held `kc` if tapped |
|`LALT = KC.HT(KC.SOMETHING, KC.LALT)` |`LALT` if held `kc` if tapped |
|`LGUI = KC.HT(KC.SOMETHING, KC.LGUI)` |`LGUI` if held `kc` if tapped |
|`RCTL = KC.HT(KC.SOMETHING, KC.RCTRL)` |`RCTRL` if held `kc` if tapped |
|`RSFT = KC.HT(KC.SOMETHING, KC.RSFT)` |`RSHIFT` if held `kc` if tapped |
|`RALT = KC.HT(KC.SOMETHING, KC.RALT)` |`RALT` if held `kc` if tapped |
|`RGUI = KC.HT(KC.SOMETHING, KC.RGUI)` |`RGUI` if held `kc` if tapped |
|`SGUI = KC.HT(KC.SOMETHING, KC.LSHFT(KC.LGUI))` |`LSHIFT` and `LGUI` if held `kc` if tapped |
|`LCA = KC.HT(KC.SOMETHING, KC.LCTRL(KC.LALT))` |`LCTRL` and `LALT` if held `kc` if tapped |
|`LCAG = KC.HT(KC.SOMETHING, KC.LCTRL(KC.LALT(KC.LGUI)))` |`LCTRL` and `LALT` and `LGUI` if held `kc` if tapped |
|`MEH = KC.HT(KC.SOMETHING, KC.LCTRL(KC.LSFT(KC.LALT)))` |`CTRL` and `LSHIFT` and `LALT` if held `kc` if tapped |
|`HYPR = KC.HT(KC.SOMETHING, KC.HYPR)` |`LCTRL` and `LSHIFT` and `LALT` and `LGUI` if held `kc` if tapped|
|`LCTL = KC.MT(KC.SOMETHING, KC.LCTRL)` |`LCTRL` if held `kc` if tapped |
|`LSFT = KC.MT(KC.SOMETHING, KC.LSFT)` |`LSHIFT` if held `kc` if tapped |
|`LALT = KC.MT(KC.SOMETHING, KC.LALT)` |`LALT` if held `kc` if tapped |
|`LGUI = KC.MT(KC.SOMETHING, KC.LGUI)` |`LGUI` if held `kc` if tapped |
|`RCTL = KC.MT(KC.SOMETHING, KC.RCTRL)` |`RCTRL` if held `kc` if tapped |
|`RSFT = KC.MT(KC.SOMETHING, KC.RSFT)` |`RSHIFT` if held `kc` if tapped |
|`RALT = KC.MT(KC.SOMETHING, KC.RALT)` |`RALT` if held `kc` if tapped |
|`RGUI = KC.MT(KC.SOMETHING, KC.RGUI)` |`RGUI` if held `kc` if tapped |
|`SGUI = KC.MT(KC.SOMETHING, KC.LSHFT(KC.LGUI))` |`LSHIFT` and `LGUI` if held `kc` if tapped |
|`LCA = KC.MT(KC.SOMETHING, KC.LCTRL(KC.LALT))` |`LCTRL` and `LALT` if held `kc` if tapped |
|`LCAG = KC.MT(KC.SOMETHING, KC.LCTRL(KC.LALT(KC.LGUI)))` |`LCTRL` and `LALT` and `LGUI` if held `kc` if tapped |
|`MEH = KC.MT(KC.SOMETHING, KC.LCTRL(KC.LSFT(KC.LALT)))` |`CTRL` and `LSHIFT` and `LALT` if held `kc` if tapped |
|`HYPR = KC.MT(KC.SOMETHING, KC.HYPR)` |`LCTRL` and `LSHIFT` and `LALT` and `LGUI` if held `kc` if tapped|
## Custom HoldTap Behavior
The full HoldTap signature is as follows:
The full ModTap signature is as follows:
```python
KC.HT(KC.TAP, KC.HOLD, prefer_hold=True, tap_interrupted=False, tap_time=None, repeat=HoldTapRepeat.NONE)
KC.MT(KC.TAP, KC.HOLD, prefer_hold=True, tap_interrupted=False, tap_time=None, repeat=HoldTapRepeat.NONE)
```
* `prefer_hold`: decides which keycode the HoldTap key resolves to when another
* `prefer_hold`: decides which keycode the ModTap key resolves to when another
key is pressed before the timeout finishes. When `True` the hold keycode is
chosen, the tap keycode when `False`.
* `tap_interrupted`: decides if the timeout will interrupt at the first other
@@ -48,4 +48,4 @@ KC.HT(KC.TAP, KC.HOLD, prefer_hold=True, tap_interrupted=False, tap_time=None, r
* `NONE`: no repeat action (default), everything works as expected.
The `HoldTapRepeat` enum must be imported from `kmk.modules.holdtap`.
Each of these parameters can be set for every HoldTap key individually.
Each of these parameters can be set for every ModTap key individually.

View File

@@ -10,7 +10,7 @@ modules are
- [Combos](combos.md): Adds chords and sequences
- [Layers](layers.md): Adds layer support (Fn key) to allow many more keys to be
put on your keyboard.
- [HoldTap](holdtap.md): Adds support for augmented modifier keys to act as one key
- [ModTap](modtap.md): Adds support for augmented modifier keys to act as one key
when tapped, and modifier when held.
- [Mouse keys](mouse_keys.md): Adds mouse keycodes.
- [OneShot](oneshot.md): Adds support for oneshot/sticky keys.

View File

@@ -15,8 +15,6 @@ keyboard.modules.append(MouseKeys())
| `KC.MB_LMB` | Left mouse button |
| `KC.MB_RMB` | Right mouse button |
| `KC.MB_MMB` | Middle mouse button |
| `KC.MB_BTN4` | mouse button 4 |
| `KC.MB_BTN5` | mouse button 5 |
| `KC.MW_UP` | Mouse wheel up |
| `KC.MW_DOWN`, `KC.MW_DN` | Mouse wheel down |
| `KC.MS_UP` | Move mouse cursor up |

View File

@@ -35,12 +35,12 @@ KC.OS(
)
```
## OneShot Modifier Combinations
The OneShot keys can be chained. In this example if you press `OS_LCTL` and then `OS_LSFT` followed by `KC.TAB`, the output will be `ctrl+shift+tab`.
The OneShot module by default cannot apply two OneShot modifiers to another key. To get around this you can use the [Combos](combos.md) module. Below is a minimal example that allows for multiple OneShot modifiers to apply to the next key pressed. In this example you can tap either of the OneShot keys then tap the other and finally tap `p` and that will send `ctrl+shift+p`.
```python
from kmk.modules.combos import Chord, Combos
from kmk.modules.oneshot import OneShot
oneshot = OneShot()
@@ -48,8 +48,58 @@ keyboard.modules.append(oneshot)
OS_LCTL = KC.OS(KC.LCTL, tap_time=None)
OS_LSFT = KC.OS(KC.LSFT, tap_time=None)
OS_LCTL_LSFT = KC.OS(KC.LCTL(OS_LSFT), tap_time=None)
keyboard.keymap = [[OS_LSFT, OS_LCTL, KC.TAB]]
combos = Combos()
keyboard.modules.append(combos)
combos.combos = [
Chord((OS_LCTL, OS_LSFT), OS_LCTL_LSFT, timeout=1000),
]
keyboard.keymap = [[OS_LSFT, OS_LCTL, KC.P]]
```
Below is the complete list of OneShot and Chords you need to allow any combination of modifiers (left modifiers only).
> <details>
> <summary>Long code chunk (click to load)</summary>
>
> ```python
> OS_LCTL = KC.OS(KC.LCTL, tap_time=None)
> OS_LSFT = KC.OS(KC.LSFT, tap_time=None)
> OS_LGUI = KC.OS(KC.LGUI, tap_time=None)
> OS_LALT = KC.OS(KC.LALT, tap_time=None)
>
> OS_LCTL_LSFT = KC.OS(KC.LCTL(OS_LSFT), tap_time=None)
> OS_LCTL_LALT = KC.OS(KC.LCTL(OS_LALT), tap_time=None)
> OS_LCTL_LGUI = KC.OS(KC.LCTL(OS_LGUI), tap_time=None)
> OS_LSFT_LALT = KC.OS(KC.LSFT(OS_LALT), tap_time=None)
> OS_LSFT_LGUI = KC.OS(KC.LSFT(OS_LGUI), tap_time=None)
> OS_LALT_LGUI = KC.OS(KC.LALT(OS_LGUI), tap_time=None)
>
> OS_LCTL_LSFT_LGUI = KC.OS(KC.LCTL(KC.LSFT(OS_LGUI)), tap_time=None)
> OS_LCTL_LSFT_LALT = KC.OS(KC.LCTL(KC.LSFT(OS_LALT)), tap_time=None)
> OS_LCTL_LALT_LGUI = KC.OS(KC.LCTL(KC.LALT(OS_LGUI)), tap_time=None)
> OS_LSFT_LALT_LGUI = KC.OS(KC.LSFT(KC.LALT(OS_LGUI)), tap_time=None)
>
> OS_LCTL_LSFT_LALT_LGUI = KC.OS(KC.LCTL(KC.LSFT(KC.LALT(OS_LGUI))), tap_time=None)
>
> combos.combos = [
> Chord((OS_LCTL, OS_LSFT), OS_LCTL_LSFT, timeout=1000),
> Chord((OS_LCTL, OS_LALT), OS_LCTL_LALT, timeout=1000),
> Chord((OS_LCTL, OS_LGUI), OS_LCTL_LGUI, timeout=1000),
> Chord((OS_LSFT, OS_LALT), OS_LSFT_LALT, timeout=1000),
> Chord((OS_LSFT, OS_LGUI), OS_LSFT_LGUI, timeout=1000),
> Chord((OS_LALT, OS_LGUI), OS_LALT_LGUI, timeout=1000),
>
> Chord((OS_LCTL, OS_LSFT, OS_LGUI), OS_LCTL_LSFT_LGUI, timeout=1000),
> Chord((OS_LCTL, OS_LSFT, OS_LALT), OS_LCTL_LSFT_LALT, timeout=1000),
> Chord((OS_LCTL, OS_LALT, OS_LGUI), OS_LCTL_LALT_LGUI, timeout=1000),
> Chord((OS_LSFT, OS_LALT, OS_LGUI), OS_LSFT_LALT_LGUI, timeout=1000),
>
> Chord((OS_LCTL, OS_LSFT, OS_LALT, OS_LGUI), OS_LCTL_LSFT_LALT_LGUI, timeout=1000),
> ]
> ```
>
> </details>

View File

@@ -17,7 +17,7 @@ To use this you need to make some changes to your kb.py as well as you main.py I
You need these frozen into your circuitpython or in a lib folder at the root of your drive.
* [Adafruit_CircuitPython_DisplayIO_SSD1306](https://github.com/adafruit/Adafruit_CircuitPython_DisplayIO_SSD1306)
* [Adafruit_CircuitPython_Display_Text](https://github.com/adafruit/Adafruit_CircuitPython_Display_Text)
* [Download .mpy versions from Adafruit_CircuitPython_Bundle](https://github.com/adafruit/Adafruit_CircuitPython_Bundle/releases/download/20220415/adafruit-circuitpython-bundle-7.x-mpy-20220415.zip)
* [Download .mpy versions from here](https://github.com/adafruit/Adafruit_CircuitPython_Bundle/releases/download/20220415/adafruit-circuitpython-bundle-7.x-mpy-20220415.zip)
## kb.py

View File

@@ -30,7 +30,7 @@ Currently this extension does not support changing LEDs at runtime, as a result
The following libraries must be frozen in your CircuitPython distribution or in a 'lib' folder at the root of your drive.
* [Adafruit_CircuitPython_NeoPixel](https://github.com/adafruit/Adafruit_CircuitPython_NeoPixel)
* [Download .mpy versions from Adafruit_CircuitPython_Bundle](https://github.com/adafruit/Adafruit_CircuitPython_Bundle/releases/download/20220415/adafruit-circuitpython-bundle-7.x-mpy-20220415.zip)
* [Download .mpy versions from here](https://github.com/adafruit/Adafruit_CircuitPython_Bundle/releases/download/20220415/adafruit-circuitpython-bundle-7.x-mpy-20220415.zip)
## Required Changes to main.py and kb.py

View File

@@ -126,4 +126,4 @@ if __name__ == '__main__':
```
## More information
More information on keymaps can be found in the [config and keymap](config_and_keymap.md) documentation.
More information on keymaps can be found [here](config_and_keymap.md)

View File

@@ -15,7 +15,7 @@ microcontrollers with only a single line change and less mistakes.
## Pro micro footprint pinout
![pro micro footprint pins](pro_micro_pinout.png)
![pro micro footprint pins](../img/pro_micro_pinout.png)
## Example

View File

@@ -2,7 +2,7 @@
Split keyboards are mostly the same as unsplit. Wired UART is fully supported,
and testing of Bluetooth splits, though we don't currently offer support for this.
Notice that this Split module must be added after the HoldTap module to the keyboard.modules.
Notice that this Split module must be added after the ModTap module to the keyboard.modules.
## Drive names
As you will have two circuitpython drives to update regularly, it is adviced to rename them to make

View File

@@ -46,7 +46,7 @@ EXAMPLE_TD = KC.TD(
# Tap once for "a"
KC.A,
# Tap twice for "b", or tap and hold for "left control"
KC.HT(KC.B, KC.LCTL, prefer_hold=False),
KC.MT(KC.B, KC.LCTL, prefer_hold=False),
# Tap three times to send a raw string via macro
send_string('macros in a tap dance? I think yes'),
# Tap four times to toggle layer index 1, tap 3 times and hold for 3s to

View File

Before

Width:  |  Height:  |  Size: 400 KiB

After

Width:  |  Height:  |  Size: 400 KiB

View File

@@ -9,6 +9,7 @@ KMK は[CircuitPython](https://circuitpython.org/)の上に配置されるキー
CircuitPython の最適化バージョン(特定のボードの容量制限に対処した、プリインストールされた関連モジュールの選択が可能なバージョン)も提供しています。
<br>
## TL;DR クイックスタートガイド
> To infinity and beyond!
@@ -24,7 +25,7 @@ CircuitPython の最適化バージョン(特定のボードの容量制限に
4. 同じルートディレクトリーboot.py と同レベル)に新規で*code.py* または *main.py*のファイルを作成する。中身は以下の例とする。
***重要:*** GP0 / GP1 ピンを使用ボードに合わせて下さい
***重要:*** GP0 / GP1 ピンを使用ボードに合わせて下さい<br>
```
@@ -55,6 +56,8 @@ if __name__ == '__main__':
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.
@@ -69,7 +72,7 @@ if __name__ == '__main__':
最初にデバイスの動作や具体的なマトリックス構成についてしっかり理解してください。
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)があります。
@@ -80,12 +83,13 @@ QMK チームが提供している手配線キーボード用の[ガイド](http
- [シーケンス](sequences.md) 一つのアクションで複数のキーストロークを送信するために使用します。
- [レイヤー](layers.md)でタッチ一つでキーボードの全体の動きを変えることができます。
- [モドタップ](holdtap.md) でキーの押し/長押しの動作を設定し、何回押されたかによって[タップダンス](tapdance.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.

View File

@@ -13,6 +13,7 @@ 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
<br>
## Guia Rápido
> Ao Infinito e Além!
@@ -29,7 +30,7 @@ módulos relevantes pré-instalados). Se você estiver se perguntando por que us
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!
***IMPORTANTE:*** adapte os pinos GP0 / GP1 para a tua placa específica! <br>
```
print("Starting")
@@ -60,6 +61,7 @@ if __name__ == '__main__':
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...
@@ -86,7 +88,7 @@ sua configuração matricial específica. Você pode observar
[guia](https://docs.qmk.fm/#/hand_wire) feito pelo time da QMK para teclados
artesanais.
Uma vez que você compreendeu a essência da coisa:
<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*)
@@ -101,7 +103,7 @@ E para ir mais além:
só.
- [Camadas](layers.md) podem transformar totalmente como seu teclado age com um
simples toque.
- [HoldTap](holdtap.md) te permite customizar a maneira que uma tecla age quando é
- [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.
@@ -113,6 +115,7 @@ 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
> Estradas? Para onde vamos, estradas são desnecessárias.

View File

@@ -1,27 +1,27 @@
# Keycodes HoldTap
# Keycodes ModTap
Habilitar o HoldTap (adicionando-o à lista de módulos) te dará acesso aos
Habilitar o ModTap (adicionando-o à lista de módulos) te dará acesso aos
keycodes abaixo:
```python
from kmk.modules.holdtap import HoldTap
keyboard.modules.append(HoldTap())
from kmk.modules.modtap import ModTap
keyboard.modules.append(ModTap())
```
## Keycodes
| Novo Keycode | Descrição |
|--------------------------------------------------------|-----------------------------------------------------------------|
| LCTL = KC.HT(KC.SOMETHING, KC.LCTRL) | `LCTRL` se segurado `kc` se tocado |
| LSFT = KC.HT(KC.SOMETHING, KC.LSFT) | `LSHIFT` se segurado `kc` se tocado |
| LALT = KC.HT(KC.SOMETHING, KC.LALT) | `LALT` se segurado `kc` se tocado |
| LGUI = KC.HT(KC.SOMETHING, KC.LGUI) | `LGUI` se segurado `kc` se tocado |
| RCTL = KC.HT(KC.SOMETHING, KC.RCTRL) | `RCTRL` se segurado `kc` se tocado |
| RSFT = KC.HT(KC.SOMETHING, KC.RSFT) | `RSHIFT` se segurado `kc` se tocado |
| RALT = KC.HT(KC.SOMETHING, KC.RALT) | `RALT` se segurado `kc` se tocado |
| RGUI = KC.HT(KC.SOMETHING, KC.RGUI) | `RGUI` se segurado `kc` se tocado |
| SGUI = KC.HT(KC.SOMETHING, KC.LSHFT(KC.LGUI)) | `LSHIFT` e `LGUI` se segurado `kc` se tocado |
| LCA = KC.HT(KC.SOMETHING, KC.LCTRL(KC.LALT)) | `LCTRL` e `LALT` se segurado `kc` se tocado |
| LCAG = KC.HT(KC.SOMETHING, KC.LCTRL(KC.LALT(KC.LGUI))) | `LCTRL` e `LALT` e `LGUI` se segurado `kc` se tocado |
| MEH = KC.HT(KC.SOMETHING, KC.LCTRL(KC.LSFT(KC.LALT))) | `CTRL` e `LSHIFT` e `LALT` se segurado `kc` se tocado |
| HYPR = KC.HT(KC.SOMETHING, KC.HYPR) | `LCTRL` e `LSHIFT` e `LALT` e `LGUI` se segurado `kc` if tapped |
| LCTL = KC.MT(KC.SOMETHING, KC.LCTRL) | `LCTRL` se segurado `kc` se tocado |
| LSFT = KC.MT(KC.SOMETHING, KC.LSFT) | `LSHIFT` se segurado `kc` se tocado |
| LALT = KC.MT(KC.SOMETHING, KC.LALT) | `LALT` se segurado `kc` se tocado |
| LGUI = KC.MT(KC.SOMETHING, KC.LGUI) | `LGUI` se segurado `kc` se tocado |
| RCTL = KC.MT(KC.SOMETHING, KC.RCTRL) | `RCTRL` se segurado `kc` se tocado |
| RSFT = KC.MT(KC.SOMETHING, KC.RSFT) | `RSHIFT` se segurado `kc` se tocado |
| RALT = KC.MT(KC.SOMETHING, KC.RALT) | `RALT` se segurado `kc` se tocado |
| RGUI = KC.MT(KC.SOMETHING, KC.RGUI) | `RGUI` se segurado `kc` se tocado |
| SGUI = KC.MT(KC.SOMETHING, KC.LSHFT(KC.LGUI)) | `LSHIFT` e `LGUI` se segurado `kc` se tocado |
| LCA = KC.MT(KC.SOMETHING, KC.LCTRL(KC.LALT)) | `LCTRL` e `LALT` se segurado `kc` se tocado |
| LCAG = KC.MT(KC.SOMETHING, KC.LCTRL(KC.LALT(KC.LGUI))) | `LCTRL` e `LALT` e `LGUI` se segurado `kc` se tocado |
| MEH = KC.MT(KC.SOMETHING, KC.LCTRL(KC.LSFT(KC.LALT))) | `CTRL` e `LSHIFT` e `LALT` se segurado `kc` se tocado |
| HYPR = KC.MT(KC.SOMETHING, KC.HYPR) | `LCTRL` e `LSHIFT` e `LALT` e `LGUI` se segurado `kc` if tapped |

View File

@@ -12,7 +12,7 @@ módulos oferecidos correntemente são;
- [Layers](layers.md): Acrescenta suporte a camadas (Tecla Fn) para permitir
colocar bem mais teclas no seu teclado.
- [HoldTap](holdtap.md): Acrescenta suporte para teclas modificadoras que agem
- [ModTap](modtap.md): Acrescenta suporte para teclas modificadoras que agem
como teclas comuns ao serem tocadas, mas como modificadores quando seguradas.
- [Power](power.md): Economia de energia. Este é mais útil quando usando baterias.
- [Split](split_keyboards.md): Teclados repartidos em dois. Tão ergonômicos!

View File

@@ -1,60 +0,0 @@
import digitalio
import microcontroller
def bootcfg(
sense,
source=None,
no_cdc=True,
no_hid=False,
no_midi=True,
no_storage=True,
usb_id=None,
):
if isinstance(sense, microcontroller.Pin):
sense = digitalio.DigitalInOut(sense)
sense.direction = digitalio.Direction.INPUT
sense.pull = digitalio.Pull.UP
if isinstance(source, microcontroller.Pin):
source = digitalio.DigitalInOut(source)
source.direction = digitalio.Direction.OUTPUT
source.value = False
else:
return False
# sense pulled low -> skip boot configuration
if not sense.value:
return False
if no_cdc:
import usb_cdc
usb_cdc.disable()
if no_hid:
import usb_hid
usb_hid.disable()
if no_midi:
import usb_midi
usb_midi.disable()
if isinstance(usb_id, tuple):
import supervisor
if hasattr(supervisor, 'set_usb_identification'):
supervisor.set_usb_identification(*usb_id)
# The no_storage entry is intentionally evaluated last to ensure the drive
# is mountable and rescueable, in case any of the previous code throws an
# exception.
if no_storage:
import storage
storage.disable_usb_drive()
return True

View File

@@ -127,13 +127,3 @@ def ble_refresh(key, keyboard, *args, **kwargs):
keyboard._hid_helper.stop_advertising()
keyboard._hid_helper.start_advertising()
return keyboard
def ble_disconnect(key, keyboard, *args, **kwargs):
from kmk.hid import HIDModes
if keyboard.hid_type != HIDModes.BLE:
return keyboard
keyboard._hid_helper.clear_bonds()
return keyboard

View File

@@ -4,8 +4,7 @@ from micropython import const
from storage import getmount
from kmk.keys import FIRST_KMK_INTERNAL_KEY, ConsumerKey, ModifierKey, MouseKey
from kmk.utils import clamp
from kmk.keys import FIRST_KMK_INTERNAL_KEY, ConsumerKey, ModifierKey
try:
from adafruit_ble import BLERadio
@@ -69,14 +68,6 @@ class AbstractHID:
self.report_mods = memoryview(self._evt)[1:2]
self.report_non_mods = memoryview(self._evt)[3:]
self._cc_report = bytearray(HID_REPORT_SIZES[HIDReportTypes.CONSUMER] + 1)
self._cc_report[0] = HIDReportTypes.CONSUMER
self._cc_pending = False
self._pd_report = bytearray(HID_REPORT_SIZES[HIDReportTypes.MOUSE] + 1)
self._pd_report[0] = HIDReportTypes.MOUSE
self._pd_pending = False
self.post_init()
def __repr__(self):
@@ -85,27 +76,47 @@ class AbstractHID:
def post_init(self):
pass
def create_report(self, keys_pressed, axes):
def create_report(self, keys_pressed):
self.clear_all()
consumer_key = None
for key in keys_pressed:
if key.code >= FIRST_KMK_INTERNAL_KEY:
continue
if isinstance(key, ConsumerKey):
consumer_key = key
break
if isinstance(key, ModifierKey):
self.add_modifier(key)
elif isinstance(key, ConsumerKey):
self.add_cc(key)
elif isinstance(key, MouseKey):
self.add_pd(key)
else:
self.add_key(key)
if key.has_modifiers:
for mod in key.has_modifiers:
self.add_modifier(mod)
reporting_device = self.report_device[0]
needed_reporting_device = HIDReportTypes.KEYBOARD
for axis in axes:
self.move_axis(axis)
if consumer_key:
needed_reporting_device = HIDReportTypes.CONSUMER
if reporting_device != needed_reporting_device:
# If we are about to change reporting devices, release
# all keys and close our proverbial tab on the existing
# device, or keys will get stuck (mostly when releasing
# media/consumer keys)
self.send()
self.report_device[0] = needed_reporting_device
if consumer_key:
self.add_key(consumer_key)
else:
for key in keys_pressed:
if key.code >= FIRST_KMK_INTERNAL_KEY:
continue
if isinstance(key, ModifierKey):
self.add_modifier(key)
else:
self.add_key(key)
if key.has_modifiers:
for mod in key.has_modifiers:
self.add_modifier(mod)
return self
def hid_send(self, evt):
# Don't raise a NotImplementedError so this can serve as our "dummy" HID
@@ -120,24 +131,12 @@ class AbstractHID:
self._prev_evt[:] = self._evt
self.hid_send(self._evt)
if self._cc_pending:
self.hid_send(self._cc_report)
self._cc_pending = False
if self._pd_pending:
self.hid_send(self._pd_report)
self._pd_pending = False
return self
def clear_all(self):
for idx, _ in enumerate(self.report_keys):
self.report_keys[idx] = 0x00
self.remove_cc()
self.remove_pd()
self.clear_axis()
return self
def clear_non_modifiers(self):
@@ -176,6 +175,9 @@ class AbstractHID:
where_to_place = self.report_non_mods
if self.report_device[0] == HIDReportTypes.CONSUMER:
where_to_place = self.report_keys
for idx, _ in enumerate(where_to_place):
if where_to_place[idx] == 0x00:
where_to_place[idx] = key.code
@@ -191,44 +193,15 @@ class AbstractHID:
def remove_key(self, key):
where_to_place = self.report_non_mods
if self.report_device[0] == HIDReportTypes.CONSUMER:
where_to_place = self.report_keys
for idx, _ in enumerate(where_to_place):
if where_to_place[idx] == key.code:
where_to_place[idx] = 0x00
return self
def add_cc(self, cc):
# Add (or write over) consumer control report. There can only be one CC
# active at any time.
memoryview(self._cc_report)[1:3] = cc.code.to_bytes(2, 'little')
self._cc_pending = True
def remove_cc(self):
# Remove consumer control report.
report = memoryview(self._cc_report)[1:3]
if report != b'\x00\x00':
report[:] = b'\x00\x00'
self._cc_pending = True
def add_pd(self, key):
self._pd_report[1] |= key.code
self._pd_pending = True
def remove_pd(self):
if self._pd_report[1]:
self._pd_pending = True
self._pd_report[1] = 0x00
def move_axis(self, axis):
delta = clamp(axis.delta, -127, 127)
axis.delta -= delta
self._pd_report[axis.code + 2] = 0xFF & delta
self._pd_pending = True
def clear_axis(self):
for idx in range(2, len(self._pd_report)):
self._pd_report[idx] = 0x00
class USBHID(AbstractHID):
REPORT_BYTES = 9

View File

@@ -20,7 +20,6 @@ class KeyType:
SIMPLE = const(0)
MODIFIER = const(1)
CONSUMER = const(2)
MOUSE = const(3)
FIRST_KMK_INTERNAL_KEY = const(1000)
@@ -34,29 +33,6 @@ ALL_NUMBER_ALIASES = tuple(f'N{x}' for x in ALL_NUMBERS)
debug = Debug(__name__)
class Axis:
def __init__(self, code: int) -> None:
self.code = code
self.delta = 0
def __repr__(self) -> str:
return f'Axis(code={self.code}, delta={self.delta})'
def move(self, keyboard: Keyboard, delta: int):
self.delta += delta
if self.delta:
keyboard.axes.add(self)
keyboard.hid_pending = True
else:
keyboard.axes.discard(self)
class AX:
W = Axis(2)
X = Axis(0)
Y = Axis(1)
def maybe_make_key(
code: Optional[int],
names: Tuple[str, ...],
@@ -364,7 +340,6 @@ def maybe_make_unicode_key(candidate: str) -> Optional[Key]:
def maybe_make_firmware_key(candidate: str) -> Optional[Key]:
keys = (
((('BLE_REFRESH',), handlers.ble_refresh)),
((('BLE_DISCONNECT',), handlers.ble_disconnect)),
((('BOOTLOADER',), handlers.bootloader)),
((('DEBUG', 'DBG'), handlers.debug_pressed)),
((('HID_SWITCH', 'HID'), handlers.hid_switch)),
@@ -435,7 +410,7 @@ class KeyAttrDict:
def __iter__(self):
for partition in self.__cache:
for name in partition:
for name in partition.__iter__():
yield name
def __setitem__(self, name: str, key: Key):
@@ -713,10 +688,6 @@ class ConsumerKey(Key):
pass
class MouseKey(Key):
pass
def make_key(
code: Optional[int] = None,
names: Tuple[str, ...] = tuple(), # NOQA
@@ -747,8 +718,6 @@ def make_key(
constructor = ModifierKey
elif type == KeyType.CONSUMER:
constructor = ConsumerKey
elif type == KeyType.MOUSE:
constructor = MouseKey
else:
raise ValueError('Unrecognized key type')
@@ -781,10 +750,6 @@ def make_consumer_key(*args, **kwargs) -> Key:
return make_key(*args, **kwargs, type=KeyType.CONSUMER)
def make_mouse_key(*args, **kwargs) -> Key:
return make_key(*args, **kwargs, type=KeyType.MOUSE)
# Argumented keys are implicitly internal, so auto-gen of code
# is almost certainly the best plan here
def make_argumented_key(

View File

@@ -49,7 +49,6 @@ class KMKKeyboard:
#####
# Internal State
keys_pressed = set()
axes = set()
_coordkeys_pressed = {}
hid_type = HIDModes.USB
secondary_hid_type = None
@@ -89,7 +88,6 @@ class KMKKeyboard:
f' unicode_mode={self.unicode_mode}, ',
f'_hid_helper={self._hid_helper},\n',
f' keys_pressed={self.keys_pressed},\n',
f' axes={self.axes},\n',
f' _coordkeys_pressed={self._coordkeys_pressed},\n',
f' hid_pending={self.hid_pending}, ',
f'active_layers={self.active_layers}, ',
@@ -104,24 +102,15 @@ class KMKKeyboard:
debug(f'keys_pressed={self.keys_pressed}')
def _send_hid(self) -> None:
if not self._hid_send_enabled:
return
if self.axes and debug.enabled:
debug(f'axes={self.axes}')
self._hid_helper.create_report(self.keys_pressed, self.axes)
try:
self._hid_helper.send()
except KeyError as e:
if debug.enabled:
debug(f'HidNotFound(HIDReportType={e})')
if self._hid_send_enabled:
hid_report = self._hid_helper.create_report(self.keys_pressed)
try:
hid_report.send()
except KeyError as e:
if debug.enabled:
debug(f'HidNotFound(HIDReportType={e})')
self.hid_pending = False
for axis in self.axes:
axis.move(self, 0)
def _handle_matrix_report(self, kevent: KeyEvent) -> None:
if kevent is not None:
self._on_matrix_changed(kevent)
@@ -386,10 +375,6 @@ class KMKKeyboard:
self._hid_helper = self._hid_helper(**self._go_args)
self._hid_send_enabled = True
def _deinit_hid(self) -> None:
self._hid_helper.clear_all()
self._hid_helper.send()
def _init_matrix(self) -> None:
if self.matrix is None:
if debug.enabled:
@@ -502,12 +487,8 @@ class KMKKeyboard:
def go(self, hid_type=HIDModes.USB, secondary_hid_type=None, **kwargs) -> None:
self._init(hid_type=hid_type, secondary_hid_type=secondary_hid_type, **kwargs)
try:
while True:
self._main_loop()
finally:
debug('Unexpected error: cleaning up')
self._deinit_hid()
while True:
self._main_loop()
def _init(
self,

View File

@@ -4,9 +4,9 @@ import microcontroller
import time
from kmk.keys import AX
from kmk.modules import Module
from kmk.modules.adns9800_firmware import firmware
from kmk.modules.mouse_keys import PointingDevice
class REG:
@@ -70,6 +70,7 @@ class ADNS9800(Module):
DIR_READ = 0x7F
def __init__(self, cs, sclk, miso, mosi, invert_x=False, invert_y=False):
self.pointing_device = PointingDevice()
self.cs = digitalio.DigitalInOut(cs)
self.cs.direction = digitalio.Direction.OUTPUT
self.spi = busio.SPI(clock=sclk, MOSI=mosi, MISO=miso)
@@ -202,14 +203,27 @@ class ADNS9800(Module):
if self.invert_y:
delta_y *= -1
if delta_x:
AX.X.move(delta_x)
if delta_x < 0:
self.pointing_device.report_x[0] = (delta_x & 0xFF) | 0x80
else:
self.pointing_device.report_x[0] = delta_x & 0xFF
if delta_y:
AX.Y.move(delta_y)
if delta_y < 0:
self.pointing_device.report_y[0] = (delta_y & 0xFF) | 0x80
else:
self.pointing_device.report_y[0] = delta_y & 0xFF
if keyboard.debug_enabled:
print('Delta: ', delta_x, ' ', delta_y)
self.pointing_device.hid_pending = True
if self.pointing_device.hid_pending:
keyboard._hid_helper.hid_send(self.pointing_device._evt)
self.pointing_device.hid_pending = False
self.pointing_device.report_x[0] = 0
self.pointing_device.report_y[0] = 0
return
def after_matrix_scan(self, keyboard):
return

View File

@@ -4,8 +4,8 @@ Extension handles usage of AS5013 by AMS
from supervisor import ticks_ms
from kmk.keys import AX
from kmk.modules import Module
from kmk.modules.mouse_keys import PointingDevice
I2C_ADDRESS = 0x40
I2X_ALT_ADDRESS = 0x41
@@ -44,6 +44,7 @@ class Easypoint(Module):
self._i2c_bus = i2c
# HID parameters
self.pointing_device = PointingDevice()
self.polling_interval = 20
self.last_tick = ticks_ms()
@@ -81,8 +82,12 @@ class Easypoint(Module):
return
else:
# Set the X/Y from easypoint
AX.X.move(keyboard, x)
AX.Y.move(keyboard, y)
self.pointing_device.report_x[0] = x
self.pointing_device.report_y[0] = y
self.pointing_device.hid_pending = x != 0 or y != 0
return
def after_matrix_scan(self, keyboard):
return
@@ -91,6 +96,9 @@ class Easypoint(Module):
return
def after_hid_send(self, keyboard):
if self.pointing_device.hid_pending:
keyboard._hid_helper.hid_send(self.pointing_device._evt)
self._clear_pending_hid()
return
def on_powersave_enable(self, keyboard):
@@ -99,6 +107,13 @@ class Easypoint(Module):
def on_powersave_disable(self, keyboard):
return
def _clear_pending_hid(self):
self.pointing_device.hid_pending = False
self.pointing_device.report_x[0] = 0
self.pointing_device.report_y[0] = 0
self.pointing_device.report_w[0] = 0
self.pointing_device.button_status[0] = 0
def _read_raw_state(self):
'''Read data from AS5013'''
x, y = self._i2c_rdwr([X], length=2)

View File

@@ -114,15 +114,17 @@ class Layers(HoldTap):
'''
As MO(layer) but with mod active
'''
keyboard.hid_pending = True
# Sets the timer start and acts like MO otherwise
keyboard.add_key(key.meta.kc)
keyboard.keys_pressed.add(key.meta.kc)
self._mo_pressed(key, keyboard, *args, **kwargs)
def _lm_released(self, key, keyboard, *args, **kwargs):
'''
As MO(layer) but with mod active
'''
keyboard.remove_key(key.meta.kc)
keyboard.hid_pending = True
keyboard.keys_pressed.discard(key.meta.kc)
self._mo_released(key, keyboard, *args, **kwargs)
def _tg_pressed(self, key, keyboard, *args, **kwargs):

View File

@@ -2,7 +2,6 @@ from kmk.keys import make_argumented_key
from kmk.modules.holdtap import HoldTap, HoldTapKeyMeta
# Deprecation Notice: The `ModTap` class serves as an alias for `HoldTap` and will be removed in a future update. Please use `HoldTap` instead.
class ModTap(HoldTap):
def __init__(self):
super().__init__()

View File

@@ -1,40 +1,54 @@
from kmk.keys import AX, make_key, make_mouse_key
from kmk.kmktime import PeriodicTimer
from supervisor import ticks_ms
from kmk.hid import HID_REPORT_SIZES, HIDReportTypes
from kmk.keys import make_key
from kmk.modules import Module
class PointingDevice:
MB_LMB = 1
MB_RMB = 2
MB_MMB = 4
_evt = bytearray(HID_REPORT_SIZES[HIDReportTypes.MOUSE] + 1)
def __init__(self):
self.key_states = {}
self.hid_pending = False
self.report_device = memoryview(self._evt)[0:1]
self.report_device[0] = HIDReportTypes.MOUSE
self.button_status = memoryview(self._evt)[1:2]
self.report_x = memoryview(self._evt)[2:3]
self.report_y = memoryview(self._evt)[3:4]
self.report_w = memoryview(self._evt)[4:]
class MouseKeys(Module):
def __init__(self):
self.pointing_device = PointingDevice()
self._nav_key_activated = 0
self._up_activated = False
self._down_activated = False
self._left_activated = False
self._right_activated = False
self._mw_up_activated = False
self._mw_down_activated = False
self.max_speed = 10
self.acc_interval = 10 # Delta ms to apply acceleration
self.ac_interval = 100 # Delta ms to apply acceleration
self._next_interval = 0 # Time for next tick interval
self.move_step = 1
make_mouse_key(
make_key(
names=('MB_LMB',),
code=1,
on_press=self._mb_lmb_press,
on_release=self._mb_lmb_release,
)
make_mouse_key(
make_key(
names=('MB_MMB',),
code=4,
on_press=self._mb_mmb_press,
on_release=self._mb_mmb_release,
)
make_mouse_key(
make_key(
names=('MB_RMB',),
code=2,
)
make_mouse_key(
names=('MB_BTN4',),
code=8,
)
make_mouse_key(
names=('MB_BTN5',),
code=16,
on_press=self._mb_rmb_press,
on_release=self._mb_rmb_release,
)
make_key(
names=('MW_UP',),
@@ -80,33 +94,38 @@ class MouseKeys(Module):
)
def during_bootup(self, keyboard):
self._timer = PeriodicTimer(self.acc_interval)
return
def matrix_detected_press(self, keyboard):
return keyboard.matrix_update is None
def before_matrix_scan(self, keyboard):
return
def after_matrix_scan(self, keyboard):
if not self._timer.tick():
return
if self._nav_key_activated:
if self.move_step < self.max_speed:
self.move_step = self.move_step + 1
if self._next_interval <= ticks_ms():
# print("hello: ")
# print(ticks_ms())
self._next_interval = ticks_ms() + self.ac_interval
# print(self._next_interval)
if self.move_step < self.max_speed:
self.move_step = self.move_step + 1
if self._right_activated:
AX.X.move(keyboard, self.move_step)
self.pointing_device.report_x[0] = self.move_step
if self._left_activated:
AX.X.move(keyboard, -self.move_step)
self.pointing_device.report_x[0] = 0xFF & (0 - self.move_step)
if self._up_activated:
AX.Y.move(keyboard, -self.move_step)
self.pointing_device.report_y[0] = 0xFF & (0 - self.move_step)
if self._down_activated:
AX.Y.move(keyboard, self.move_step)
if self._mw_up_activated:
AX.W.move(keyboard, 1)
if self._mw_down_activated:
AX.W.move(keyboard, -1)
self.pointing_device.report_y[0] = self.move_step
self.pointing_device.hid_pending = True
return
def before_hid_send(self, keyboard):
if self.pointing_device.hid_pending and keyboard._hid_send_enabled:
keyboard._hid_helper.hid_send(self.pointing_device._evt)
self.pointing_device.hid_pending = False
return
def after_hid_send(self, keyboard):
@@ -118,21 +137,50 @@ class MouseKeys(Module):
def on_powersave_disable(self, keyboard):
return
def _mb_lmb_press(self, key, keyboard, *args, **kwargs):
self.pointing_device.button_status[0] |= self.pointing_device.MB_LMB
self.pointing_device.hid_pending = True
def _mb_lmb_release(self, key, keyboard, *args, **kwargs):
self.pointing_device.button_status[0] &= ~self.pointing_device.MB_LMB
self.pointing_device.hid_pending = True
def _mb_mmb_press(self, key, keyboard, *args, **kwargs):
self.pointing_device.button_status[0] |= self.pointing_device.MB_MMB
self.pointing_device.hid_pending = True
def _mb_mmb_release(self, key, keyboard, *args, **kwargs):
self.pointing_device.button_status[0] &= ~self.pointing_device.MB_MMB
self.pointing_device.hid_pending = True
def _mb_rmb_press(self, key, keyboard, *args, **kwargs):
self.pointing_device.button_status[0] |= self.pointing_device.MB_RMB
self.pointing_device.hid_pending = True
def _mb_rmb_release(self, key, keyboard, *args, **kwargs):
self.pointing_device.button_status[0] &= ~self.pointing_device.MB_RMB
self.pointing_device.hid_pending = True
def _mw_up_press(self, key, keyboard, *args, **kwargs):
self._mw_up_activated = True
self.pointing_device.report_w[0] = self.move_step
self.pointing_device.hid_pending = True
def _mw_up_release(self, key, keyboard, *args, **kwargs):
self._mw_up_activated = False
self.pointing_device.report_w[0] = 0
self.pointing_device.hid_pending = True
def _mw_down_press(self, key, keyboard, *args, **kwargs):
self._mw_down_activated = True
self.pointing_device.report_w[0] = 0xFF
self.pointing_device.hid_pending = True
def _mw_down_release(self, key, keyboard, *args, **kwargs):
self._mw_down_activated = False
self.pointing_device.report_w[0] = 0
self.pointing_device.hid_pending = True
# Mouse movement
def _reset_next_interval(self):
if self._nav_key_activated == 1:
self._next_interval = ticks_ms() + self.ac_interval
self.move_step = 1
def _check_last(self):
@@ -143,38 +191,56 @@ class MouseKeys(Module):
self._nav_key_activated += 1
self._reset_next_interval()
self._up_activated = True
self.pointing_device.report_y[0] = 0xFF & (0 - self.move_step)
self.pointing_device.hid_pending = True
def _ms_up_release(self, key, keyboard, *args, **kwargs):
self._up_activated = False
self._nav_key_activated -= 1
self._check_last()
self.pointing_device.report_y[0] = 0
self.pointing_device.hid_pending = False
def _ms_down_press(self, key, keyboard, *args, **kwargs):
self._nav_key_activated += 1
self._reset_next_interval()
self._down_activated = True
# if not self.x_activated and not self.y_activated:
# self.next_interval = ticks_ms() + self.ac_intervalle
self.pointing_device.report_y[0] = self.move_step
self.pointing_device.hid_pending = True
def _ms_down_release(self, key, keyboard, *args, **kwargs):
self._down_activated = False
self._nav_key_activated -= 1
self._check_last()
self.pointing_device.report_y[0] = 0
self.pointing_device.hid_pending = False
def _ms_left_press(self, key, keyboard, *args, **kwargs):
self._nav_key_activated += 1
self._reset_next_interval()
self._left_activated = True
self.pointing_device.report_x[0] = 0xFF & (0 - self.move_step)
self.pointing_device.hid_pending = True
def _ms_left_release(self, key, keyboard, *args, **kwargs):
self._nav_key_activated -= 1
self._left_activated = False
self._check_last()
self.pointing_device.report_x[0] = 0
self.pointing_device.hid_pending = False
def _ms_right_press(self, key, keyboard, *args, **kwargs):
self._nav_key_activated += 1
self._reset_next_interval()
self._right_activated = True
self.pointing_device.report_x[0] = self.move_step
self.pointing_device.hid_pending = True
def _ms_right_release(self, key, keyboard, *args, **kwargs):
self._nav_key_activated -= 1
self._right_activated = False
self._check_last()
self.pointing_device.report_x[0] = 0
self.pointing_device.hid_pending = False

View File

@@ -1,14 +1,9 @@
from kmk.keys import make_argumented_key
from kmk.modules.holdtap import ActivationType, HoldTap, HoldTapKeyMeta
from kmk.modules.layers import LayerKeyMeta
from kmk.utils import Debug
debug = Debug(__name__)
class OneShotKeyMeta(HoldTapKeyMeta):
def __init__(self, kc, tap_time=None):
super().__init__(tap=kc, hold=kc, prefer_hold=False, tap_time=tap_time)
def oneshot_validator(kc, tap_time=None):
return HoldTapKeyMeta(tap=kc, hold=kc, prefer_hold=False, tap_time=tap_time)
class OneShot(HoldTap):
@@ -17,49 +12,30 @@ class OneShot(HoldTap):
def __init__(self):
super().__init__()
make_argumented_key(
validator=OneShotKeyMeta,
validator=oneshot_validator,
names=('OS', 'ONESHOT'),
on_press=self.osk_pressed,
on_release=self.osk_released,
)
def process_key(self, keyboard, current_key, is_pressed, int_coord):
'''Release os key after interrupting non-os keyup, or reset timeout and
stack multiple os keys.'''
send_buffer = False
'''Release os key after interrupting keyup.'''
for key, state in self.key_states.items():
if key == current_key:
continue
if (isinstance(current_key.meta, OneShotKeyMeta)) or (
isinstance(current_key.meta, LayerKeyMeta)
):
keyboard.cancel_timeout(state.timeout_key)
if key.meta.tap_time is None:
tap_time = self.tap_time
else:
tap_time = key.meta.tap_time
state.timeout_key = keyboard.set_timeout(
tap_time,
lambda k=key: self.on_tap_time_expired(k, keyboard),
)
continue
if state.activated == ActivationType.PRESSED and is_pressed:
state.activated = ActivationType.HOLD_TIMEOUT
elif state.activated == ActivationType.RELEASED and is_pressed:
state.activated = ActivationType.INTERRUPTED
elif state.activated == ActivationType.INTERRUPTED:
if is_pressed:
send_buffer = True
self.key_buffer.insert(0, (0, key, False))
if send_buffer:
self.key_buffer.append((int_coord, current_key, is_pressed))
current_key = None
self.send_key_buffer(keyboard)
keyboard.remove_key(key.meta.tap)
self.key_buffer.append((int_coord, current_key, is_pressed))
keyboard.set_timeout(False, lambda: self.send_key_buffer(keyboard))
current_key = None
else:
self.ht_released(key, keyboard)
return current_key
@@ -75,8 +51,8 @@ class OneShot(HoldTap):
try:
state = self.key_states[key]
except KeyError:
if debug.enabled:
debug(f'OneShot.osk_released: no such key {key}')
if keyboard.debug_enabled:
print(f'OneShot.osk_released: no such key {key}')
return keyboard
if state.activated == ActivationType.PRESSED:

View File

@@ -7,9 +7,10 @@ from micropython import const
import math
import struct
from kmk.keys import AX, KC, make_argumented_key, make_key
from kmk.keys import make_argumented_key, make_key
from kmk.kmktime import PeriodicTimer
from kmk.modules import Module
from kmk.modules.mouse_keys import PointingDevice
I2C_ADDRESS = 0x0A
I2C_ADDRESS_ALTERNATIVE = 0x0B
@@ -77,16 +78,29 @@ class TrackballHandler:
class PointingHandler(TrackballHandler):
def handle(self, keyboard, trackball, x, y, switch, state):
if x:
AX.X.move(keyboard, x)
if y:
AX.Y.move(keyboard, y)
if x > 0:
trackball.pointing_device.report_x[0] = x
elif x < 0:
trackball.pointing_device.report_x[0] = 0xFF & x
if y > 0:
trackball.pointing_device.report_y[0] = y
elif y < 0:
trackball.pointing_device.report_y[0] = 0xFF & y
if x != 0 or y != 0:
trackball.pointing_device.hid_pending = True
if switch == 1: # Button pressed
keyboard.pre_process_key(KC.MB_LMB, is_pressed=True)
trackball.pointing_device.button_status[
0
] |= trackball.pointing_device.MB_LMB
trackball.pointing_device.hid_pending = True
if not state and trackball.previous_state is True: # Button released
keyboard.pre_process_key(KC.MB_LMB, is_pressed=False)
trackball.pointing_device.button_status[
0
] &= ~trackball.pointing_device.MB_LMB
trackball.pointing_device.hid_pending = True
trackball.previous_state = state
@@ -100,13 +114,17 @@ class ScrollHandler(TrackballHandler):
y = -y
if y != 0:
AX.W.move(keyboard, y)
pointing_device = trackball.pointing_device
pointing_device.report_w[0] = 0xFF & y
pointing_device.hid_pending = True
if switch == 1: # Button pressed
keyboard.pre_process_key(KC.MB_LMB, is_pressed=True)
pointing_device.button_status[0] |= pointing_device.MB_LMB
pointing_device.hid_pending = True
if not state and trackball.previous_state is True: # Button released
keyboard.pre_process_key(KC.MB_LMB, is_pressed=False)
pointing_device.button_status[0] &= ~pointing_device.MB_LMB
pointing_device.hid_pending = True
trackball.previous_state = state
@@ -167,6 +185,7 @@ class Trackball(Module):
self._i2c_address = address
self._i2c_bus = i2c
self.pointing_device = PointingDevice()
self.mode = mode
self.previous_state = False # click state
self.handlers = handlers
@@ -215,6 +234,9 @@ class Trackball(Module):
return
def after_hid_send(self, keyboard):
if self.pointing_device.hid_pending:
keyboard._hid_helper.hid_send(self.pointing_device._evt)
self._clear_pending_hid()
return
def on_powersave_enable(self, keyboard):
@@ -258,6 +280,13 @@ class Trackball(Module):
next_index = 0
self.activate_handler(next_index)
def _clear_pending_hid(self):
self.pointing_device.hid_pending = False
self.pointing_device.report_x[0] = 0
self.pointing_device.report_y[0] = 0
self.pointing_device.report_w[0] = 0
self.pointing_device.button_status[0] = 0
def _read_raw_state(self):
'''Read up, down, left, right and switch data from trackball.'''
left, right, up, down, switch = self._i2c_rdwr([REG_LEFT], 5)

View File

@@ -103,9 +103,9 @@ class Power(Module):
'''
Sleeps longer and longer to save power the more time in between updates.
'''
if check_deadline(ticks_ms(), self._powersave_start, 60000):
if check_deadline(ticks_ms(), self._powersave_start) <= 60000:
sleep(8 / 1000)
elif check_deadline(ticks_ms(), self._powersave_start, 240000) is False:
elif check_deadline(ticks_ms(), self._powersave_start) >= 240000:
sleep(180 / 1000)
return
@@ -123,7 +123,7 @@ class Power(Module):
return
def usb_rescan_timer(self):
return bool(check_deadline(ticks_ms(), self._usb_last_scan, 5000) is False)
return bool(check_deadline(ticks_ms(), self._usb_last_scan) > 5000)
def usb_time_reset(self):
self._usb_last_scan = ticks_ms()

View File

@@ -23,7 +23,6 @@ per-file-ignores =
# your imports in whatever order you want
user_keymaps/**/*.py: E131,F401,E501,E241,E131,BLK100,I003
boards/**/main.py: E131,F401,E501,E241,E131,BLK100,I003
boards/**/kb.py: E131,F401,E501,E241,E131,BLK100,I003
tests/test_data/keymaps/**/*.py: F401,E501
[isort]

View File

@@ -74,14 +74,7 @@ class KeyboardTest:
is_pressed = e[1]
self.pins[key_pos].value = is_pressed
self.do_main_loop()
# wait up to 10s for delayed actions to resolve, if there are any
timeout = time.time_ns() + 10 * 1_000_000_000
while timeout > time.time_ns():
self.do_main_loop()
if not self.keyboard._timeouts and not self.keyboard._resume_buffer:
break
assert timeout > time.time_ns(), 'infinite loop detected'
self.keyboard._main_loop()
matching = True
for i in range(max(len(hid_reports), len(assert_reports))):

View File

@@ -1,66 +1,65 @@
import unittest
from kmk.keys import KC
from kmk.modules.holdtap import HoldTap, HoldTapRepeat
from kmk.modules.holdtap import HoldTapRepeat
from kmk.modules.layers import Layers
from kmk.modules.modtap import ModTap
from kmk.modules.oneshot import OneShot
from tests.keyboard_test import KeyboardTest
class TestHoldTap(unittest.TestCase):
def setUp(self):
KC.clear()
def test_holdtap(self):
keyboard = KeyboardTest(
[Layers(), HoldTap()],
[Layers(), ModTap(), OneShot()],
[
[KC.HT(KC.A, KC.LCTL), KC.LT(1, KC.B), KC.C, KC.D],
[KC.N1, KC.N2, KC.N3, KC.N4],
[KC.MT(KC.A, KC.LCTL), KC.LT(1, KC.B), KC.C, KC.D, KC.OS(KC.E)],
[KC.N1, KC.N2, KC.N3, KC.N4, KC.N5],
],
debug_enabled=False,
)
keyboard.test('HT tap behaviour', [(0, True), 100, (0, False)], [{KC.A}, {}])
keyboard.test('MT tap behaviour', [(0, True), 100, (0, False)], [{KC.A}, {}])
keyboard.test(
'HT hold behaviour', [(0, True), 350, (0, False)], [{KC.LCTL}, {}]
'MT hold behaviour', [(0, True), 350, (0, False)], [{KC.LCTL}, {}]
)
# TODO test multiple mods being held
# HT
# MT
keyboard.test(
'HT within tap time sequential -> tap behavior',
'MT within tap time sequential -> tap behavior',
[(0, True), 100, (0, False), (3, True), (3, False)],
[{KC.A}, {}, {KC.D}, {}],
)
keyboard.test(
'HT within tap time rolling -> hold behavior',
'MT within tap time rolling -> hold behavior',
[(0, True), 100, (3, True), 250, (0, False), (3, False)],
[{KC.LCTL}, {KC.LCTL, KC.D}, {KC.D}, {}],
)
keyboard.test(
'HT within tap time nested -> hold behavior',
'MT within tap time nested -> hold behavior',
[(0, True), 100, (3, True), (3, False), 250, (0, False)],
[{KC.LCTL}, {KC.LCTL, KC.D}, {KC.LCTL}, {}],
)
keyboard.test(
'HT after tap time sequential -> hold behavior',
'MT after tap time sequential -> hold behavior',
[(0, True), 350, (0, False), (3, True), (3, False)],
[{KC.LCTL}, {}, {KC.D}, {}],
)
keyboard.test(
'HT after tap time rolling -> hold behavior',
'MT after tap time rolling -> hold behavior',
[(0, True), 350, (3, True), (0, False), (3, False)],
[{KC.LCTL}, {KC.LCTL, KC.D}, {KC.D}, {}],
)
keyboard.test(
'HT after tap time nested -> hold behavior',
'MT after tap time nested -> hold behavior',
[(0, True), 350, (3, True), (3, False), (0, False)],
[{KC.LCTL}, {KC.LCTL, KC.D}, {KC.LCTL}, {}],
)
@@ -119,13 +118,13 @@ class TestHoldTap(unittest.TestCase):
def test_holdtap_chain(self):
keyboard = KeyboardTest(
[HoldTap()],
[ModTap()],
[
[
KC.N0,
KC.HT(KC.N1, KC.LCTL, tap_time=50),
KC.HT(KC.N2, KC.LSFT, tap_interrupted=True, tap_time=50),
KC.HT(
KC.MT(KC.N1, KC.LCTL, tap_time=50),
KC.MT(KC.N2, KC.LSFT, tap_interrupted=True, tap_time=50),
KC.MT(
KC.N3,
KC.LALT,
prefer_hold=False,
@@ -276,12 +275,12 @@ class TestHoldTap(unittest.TestCase):
def test_holdtap_repeat(self):
keyboard = KeyboardTest(
[HoldTap()],
[ModTap()],
[
[
KC.HT(KC.A, KC.B, repeat=HoldTapRepeat.ALL, tap_time=50),
KC.HT(KC.A, KC.B, repeat=HoldTapRepeat.TAP, tap_time=50),
KC.HT(KC.A, KC.B, repeat=HoldTapRepeat.HOLD, tap_time=50),
KC.MT(KC.A, KC.B, repeat=HoldTapRepeat.ALL, tap_time=50),
KC.MT(KC.A, KC.B, repeat=HoldTapRepeat.TAP, tap_time=50),
KC.MT(KC.A, KC.B, repeat=HoldTapRepeat.HOLD, tap_time=50),
]
],
debug_enabled=False,
@@ -350,3 +349,76 @@ class TestHoldTap(unittest.TestCase):
[(2, True), (2, False), (2, True), t_after, (2, False)],
[{KC.A}, {}, {KC.B}, {}],
)
def test_oneshot(self):
keyboard = KeyboardTest(
[Layers(), ModTap(), OneShot()],
[
[
KC.MT(KC.A, KC.LCTL),
KC.LT(1, KC.B),
KC.C,
KC.D,
KC.OS(KC.E, tap_time=50),
],
[KC.N1, KC.N2, KC.N3, KC.N4, KC.N5],
],
debug_enabled=False,
)
t_within = 40
t_after = 60
# OS
keyboard.test(
'OS timed out',
[(4, True), (4, False), t_after],
[{KC.E}, {}],
)
keyboard.test(
'OS interrupt within tap time',
[(4, True), (4, False), t_within, (3, True), (3, False)],
[{KC.E}, {KC.D, KC.E}, {KC.E}, {}],
)
keyboard.test(
'OS interrupt, multiple within tap time',
[(4, True), (4, False), (3, True), (3, False), (2, True), (2, False)],
[{KC.E}, {KC.D, KC.E}, {KC.E}, {}, {KC.C}, {}],
)
keyboard.test(
'OS interrupt, multiple interleaved',
[(4, True), (4, False), (3, True), (2, True), (2, False), (3, False)],
[{KC.E}, {KC.D, KC.E}, {KC.D}, {KC.C, KC.D}, {KC.D}, {}],
)
keyboard.test(
'OS interrupt, multiple interleaved',
[(4, True), (4, False), (3, True), (2, True), (3, False), (2, False)],
[{KC.E}, {KC.D, KC.E}, {KC.D}, {KC.C, KC.D}, {KC.C}, {}],
)
keyboard.test(
'OS interrupt within tap time, hold',
[(4, True), (3, True), (4, False), t_after, (3, False)],
[{KC.E}, {KC.D, KC.E}, {KC.D}, {}],
)
keyboard.test(
'OS hold with multiple interrupt keys',
[
(4, True),
t_within,
(3, True),
(3, False),
(2, True),
(2, False),
(4, False),
],
[{KC.E}, {KC.D, KC.E}, {KC.E}, {KC.C, KC.E}, {KC.E}, {}],
)
if __name__ == '__main__':
unittest.main()

View File

@@ -1,147 +0,0 @@
import unittest
from kmk.keys import KC
from kmk.modules.layers import Layers
from kmk.modules.oneshot import OneShot
from tests.keyboard_test import KeyboardTest
class TestHoldTap(unittest.TestCase):
def test_oneshot(self):
keyboard = KeyboardTest(
[Layers(), OneShot()],
[
[
KC.OS(KC.MO(1), tap_time=50),
KC.MO(1),
KC.C,
KC.D,
KC.OS(KC.E, tap_time=50),
KC.OS(KC.F, tap_time=50),
],
[KC.N0, KC.N1, KC.N2, KC.N3, KC.OS(KC.LSFT, tap_time=50), KC.TRNS],
],
debug_enabled=False,
)
t_within = 40
t_after = 60
keyboard.test(
'OS timed out',
[(4, True), (4, False), t_after],
[{KC.E}, {}],
)
keyboard.test(
'OS interrupt within tap time',
[(4, True), (4, False), t_within, (3, True), (3, False)],
[{KC.E}, {KC.D, KC.E}, {KC.E}, {}],
)
keyboard.test(
'OS interrupt, multiple within tap time',
[(4, True), (4, False), (3, True), (3, False), (2, True), (2, False)],
[{KC.E}, {KC.D, KC.E}, {KC.E}, {}, {KC.C}, {}],
)
keyboard.test(
'OS interrupt, multiple interleaved',
[(4, True), (4, False), (3, True), (2, True), (2, False), (3, False)],
[{KC.E}, {KC.D, KC.E}, {KC.D}, {KC.C, KC.D}, {KC.D}, {}],
)
keyboard.test(
'OS interrupt, multiple interleaved',
[(4, True), (4, False), (3, True), (2, True), (3, False), (2, False)],
[{KC.E}, {KC.D, KC.E}, {KC.D}, {KC.C, KC.D}, {KC.C}, {}],
)
keyboard.test(
'OS interrupt within tap time, hold',
[(4, True), (3, True), (4, False), t_after, (3, False)],
[{KC.E}, {KC.D, KC.E}, {KC.D}, {}],
)
keyboard.test(
'OS interrupt within tap time, hold',
[(4, True), (4, False), (3, True), t_after, (3, False)],
[{KC.E}, {KC.D, KC.E}, {KC.E}, {}],
)
keyboard.test(
'OS hold with multiple interrupt keys',
[
(4, True),
t_within,
(3, True),
(3, False),
(2, True),
(2, False),
(4, False),
],
[{KC.E}, {KC.D, KC.E}, {KC.E}, {KC.C, KC.E}, {KC.E}, {}],
)
keyboard.test(
'OS stacking within timeout reset',
[
(4, True),
(4, False),
t_within,
(5, True),
(5, False),
t_within,
(3, True),
(3, False),
],
[{KC.E}, {KC.E, KC.F}, {KC.E, KC.F, KC.D}, {KC.E, KC.F}, {KC.E}, {}],
)
keyboard.test(
'OS stacking timed out',
[
(4, True),
(4, False),
(5, True),
(5, False),
t_after,
(3, True),
(3, False),
],
[{KC.E}, {KC.E, KC.F}, {KC.E}, {}, {KC.D}, {}],
)
keyboard.test(
'OS stacking with OS-layer',
[
(0, True),
(0, False),
(4, True),
(4, False),
(1, True),
(1, False),
],
[{KC.LSFT}, {KC.LSFT, KC.N1}, {KC.LSFT}, {}],
)
keyboard.test(
'OS stacking with layer change',
[
(1, True),
(4, True),
(4, False),
(1, False),
(4, True),
(4, False),
(2, True),
(2, False),
],
[
{KC.LSFT},
{KC.LSFT, KC.E},
{KC.LSFT, KC.E, KC.C},
{KC.LSFT, KC.E},
{KC.LSFT},
{},
],
)

View File

@@ -88,7 +88,7 @@ class TestTapDance(unittest.TestCase):
[{KC.N1}, {KC.N1, KC.N4}, {KC.N4}, {}],
)
def test_holdtap(self):
def test_modtap(self):
keyboard = self.keyboard
t_within = self.t_within
t_after = self.t_after
@@ -199,12 +199,12 @@ class TestTapDance(unittest.TestCase):
[{KC.A}, {}, {KC.N5}, {}],
)
def test_holdtap_repeat(self):
def test_modtap_repeat(self):
keyboard = self.keyboard
t_after = self.t_after
keyboard.test(
'HoldTap repeat',
'ModTap repeat',
[
(2, True),
(2, False),

View File

@@ -2,8 +2,8 @@ from kb import KMKKeyboard
from kmk.extensions.rgb import RGB
from kmk.keys import KC
from kmk.modules.holdtap import HoldTap
from kmk.modules.layers import Layers
from kmk.modules.modtap import ModTap
keyboard = KMKKeyboard()
@@ -22,15 +22,15 @@ FN1 = 2
rgb_ext = RGB(pixel_pin=keyboard.rgb_pixel_pin, num_pixels=16)
layers_ext = Layers()
holdtap = HoldTap()
modtap = ModTap()
keyboard.modules = [layers_ext, holdtap]
keyboard.modules = [layers_ext, modtap]
keyboard.extensions = [rgb_ext]
_______ = KC.TRNS
XXXXXXX = KC.NO
HOME = KC.HT(KC.HOME, KC.LSFT)
END = KC.HT(KC.END, KC.RSFT)
HOME = KC.MT(KC.HOME, KC.LSFT)
END = KC.MT(KC.END, KC.RSFT)
LEFT_LAY = KC.LT(FN1, KC.LEFT)
SHFT_INS = KC.LSFT(KC.INS)
SPC = KC.LT(FN1, KC.SPC)

View File

@@ -5,8 +5,8 @@ from kb import KMKKeyboard
from kmk.extensions.rgb import RGB
from kmk.handlers.sequences import send_string, simple_key_sequence
from kmk.keys import KC
from kmk.modules.holdtap import HoldTap
from kmk.modules.layers import Layers
from kmk.modules.modtap import ModTap
from kmk.modules.split import Split
keyboard = KMKKeyboard()
@@ -15,11 +15,11 @@ keyboard = KMKKeyboard()
keyboard.tap_time = 150
layers = Layers()
holdtap = HoldTap()
modtap = ModTap()
rgb_ext = RGB(pixel_pin=keyboard.rgb_pixel_pin, num_pixels=27, val_limit=100, hue_default=190, sat_default=100, val_default=5)
split = Split()
keyboard.modules = [holdtap, layers, split]
keyboard.modules = [modtap, layers, split]
keyboard.extensions = [rgb_ext]
_______ = KC.TRNS

View File

@@ -35,7 +35,7 @@ keyboard.keymap = [
# Default
KC.GESC, KC.Q, KC.W, KC.E, KC.R, KC.T, KC.Y, KC.U, KC.I, KC.O, KC.P, KC.BSPC,
KC.TAB, KC.A, KC.S, KC.D, KC.F, KC.G, KC.H, KC.J, KC.K, KC.L, KC.SCLN, KC.QUOT,
KC.LSFT, KC.Z, KC.X, KC.C, KC.V, KC.B, KC.N, KC.M, KC.COMM, KC.DOT, KC.SLSH, KC.HT(KC.BSLS, KC.LSFT),
KC.LSFT, KC.Z, KC.X, KC.C, KC.V, KC.B, KC.N, KC.M, KC.COMM, KC.DOT, KC.SLSH, KC.MT(KC.BSLS, KC.LSFT),
KC.LCTRL, KC.LGUI, KC.LALT, LOWER, KC.ENT, KC.SPC, KC.SPC, UP_HYP, KC.LEFT, KC.DOWN, KC.UP, KC.RGHT,
],
[