Compare commits
21 Commits
mpy_build
...
feature-bo
Author | SHA1 | Date | |
---|---|---|---|
|
20bcfcdbb9 | ||
|
2ccad46e26 | ||
|
94c042fec5 | ||
|
013046b44d | ||
|
18687e5278 | ||
|
20be6e9072 | ||
|
e40fd90d5c | ||
|
301ce3c025 | ||
|
6532497bb2 | ||
|
deb941b196 | ||
|
88c3616b6a | ||
|
6ab4154ad5 | ||
|
db2082f1c6 | ||
|
317f6407d6 | ||
|
08c255b6e4 | ||
|
61cf527370 | ||
|
38acda77b4 | ||
|
7ef2c2c2d3 | ||
|
1f751d8374 | ||
|
d4fe745e71 | ||
|
1674ff4ed7 |
23
.github/workflows/build.yml
vendored
23
.github/workflows/build.yml
vendored
@@ -1,23 +0,0 @@
|
||||
name: build_mpy
|
||||
on: [push]
|
||||
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
name: Build
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: run build script
|
||||
run: ./docker_mpy_build.sh
|
||||
|
||||
- name: look
|
||||
run: ls -la compiled/
|
||||
|
||||
- name: Archive
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: mpy
|
||||
path: compiled
|
37
Dockerfile
37
Dockerfile
@@ -1,20 +1,39 @@
|
||||
FROM python:3.9-slim-buster
|
||||
|
||||
ARG KMKPY_REF
|
||||
ARG KMKPY_URL
|
||||
|
||||
ENV KMKPY_REF ${KMKPY_REF}
|
||||
ENV KMKPY_URL ${KMKPY_URL}
|
||||
|
||||
RUN mkdir -p /app /dist
|
||||
WORKDIR /app
|
||||
|
||||
RUN apt-get update && apt-get install -y curl
|
||||
RUN apt-get update && apt-get install -y build-essential curl gettext git git-lfs rsync wget zip lbzip2
|
||||
RUN pip install pipenv
|
||||
|
||||
RUN curl https://adafruit-circuit-python.s3.amazonaws.com/bin/mpy-cross/linux-amd64/mpy-cross.static-amd64-linux-8.0.0 --output mpy-cross-8
|
||||
RUN curl https://adafruit-circuit-python.s3.amazonaws.com/bin/mpy-cross/linux-amd64/mpy-cross.static-amd64-linux-7.0.0 --output mpy-cross-7
|
||||
# Pull CircuitPython-designated ARM GCC to avoid mismatches/weird
|
||||
# inconsistencies with upstream
|
||||
RUN curl -L -o /tmp/gcc-arm.tar.bz2 https://adafruit-circuit-python.s3.amazonaws.com/gcc-arm-none-eabi-9-2019-q4-major-x86_64-linux.tar.bz2 && \
|
||||
tar -C /usr --strip-components=1 -xaf /tmp/gcc-arm.tar.bz2 && \
|
||||
rm -rf /tmp/gcc-arm.tar.bz2
|
||||
|
||||
# Get a local copy of KMKPython and its dependencies. We don't provide MPY
|
||||
# builds for kmkpython anymore, so we can get away with being opinionated
|
||||
# here.
|
||||
RUN git init /opt/kmkpython && \
|
||||
git -C /opt/kmkpython remote add origin ${KMKPY_URL} && \
|
||||
git -C /opt/kmkpython fetch --depth 1 origin ${KMKPY_REF} && \
|
||||
git -C /opt/kmkpython checkout FETCH_HEAD && \
|
||||
git -C /opt/kmkpython submodule update --init --recursive
|
||||
|
||||
RUN chmod +x mpy-cross-8
|
||||
# Build the MPY compiler
|
||||
RUN make -C /opt/kmkpython/mpy-cross
|
||||
|
||||
RUN chmod +x mpy-cross-7
|
||||
ENV PATH=/opt/kmkpython/mpy-cross:${PATH}
|
||||
|
||||
RUN mkdir -p /opt/kmkpython/frozen/kmk/kmk
|
||||
COPY ./build_kmkpython_release.sh /app/
|
||||
COPY ./kmk /opt/kmkpython/frozen/kmk/kmk
|
||||
|
||||
COPY ./docker_mpy_build.sh /app/build.sh
|
||||
# COPY ./kmk /app/kmk/
|
||||
|
||||
CMD ["bash", "build.sh"]
|
||||
CMD /app/build_kmkpython_release.sh
|
||||
|
103
Makefile
103
Makefile
@@ -30,19 +30,19 @@ TIMESTAMP := $(shell date +%s)
|
||||
|
||||
all: copy-kmk copy-bootpy copy-keymap copy-board
|
||||
|
||||
compile: $(MPY_TARGET_DIR)/.mpy.compiled
|
||||
|
||||
$(MPY_TARGET_DIR)/.mpy.compiled: $(PY_KMK_TREE)
|
||||
.PHONY: compile compile-check
|
||||
compile: compile-check
|
||||
ifeq ($(MPY_CROSS),)
|
||||
compile-check:
|
||||
@echo "===> Could not find mpy-cross in PATH, exiting"
|
||||
@false
|
||||
endif
|
||||
else
|
||||
compile-check: $(PY_KMK_TREE:%.py=$(MPY_TARGET_DIR)/%.mpy)
|
||||
@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
|
||||
$(MPY_TARGET_DIR)/%.mpy: %.py
|
||||
@mkdir -p $(dir $@)
|
||||
@$(MPY_CROSS) $(MPY_FLAGS) $? -o $@
|
||||
endif
|
||||
|
||||
.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
|
||||
@$(PIPENV) run python3 -m unittest $(TESTS)
|
||||
|
||||
reset-bootloader:
|
||||
@echo "===> Rebooting your board to bootloader (safe to ignore file not found errors)"
|
||||
@@ -102,55 +102,44 @@ 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
|
||||
$(MOUNTPOINT)/kmk/boot.py: boot.py
|
||||
@echo "===> Copying required boot.py"
|
||||
@rsync -rh boot.py $(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 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 -rh $(USER_KEYMAP) $@
|
||||
@sync
|
||||
endif # USER_KEYMAP
|
||||
|
||||
copy-keymap: $(MOUNTPOINT)/main.py
|
||||
else
|
||||
copy-keymap:
|
||||
echo "**** MOUNTPOINT must be defined (wherever your CIRCUITPY drive is mounted) ****" && exit 1
|
||||
|
||||
ifdef BOARD
|
||||
copy-board: $(MOUNTPOINT)/kb.py
|
||||
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
|
||||
|
||||
endif # MOUNTPOINT
|
||||
copy-bootpy:
|
||||
@echo "===> Copying required boot.py"
|
||||
@rsync -rhu boot.py $(MOUNTPOINT)/boot.py
|
||||
@sync
|
||||
|
||||
copy-compiled:
|
||||
@echo "===> Copying compiled KMK folder"
|
||||
@rsync -rhu $(MPY_TARGET_DIR)/* $(MOUNTPOINT)/
|
||||
@sync
|
||||
|
||||
ifdef USER_KEYMAP
|
||||
copy-keymap:
|
||||
@echo "===> Copying your keymap to main.py"
|
||||
@rsync -rhu $(USER_KEYMAP) $(MOUNTPOINT)/main.py
|
||||
@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
|
||||
|
||||
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
|
||||
|
@@ -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()
|
||||
modtap = ModTap()
|
||||
holdtap = HoldTap()
|
||||
layers_ext = Layers()
|
||||
keyboard.modules.append(layers_ext)
|
||||
keyboard.modules.append(modtap)
|
||||
keyboard.modules.append(holdtap)
|
||||
|
||||
oled_ext = Oled(
|
||||
OledData(
|
||||
|
@@ -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
|
||||
- [ModTap](/docs/en/modtap.md) Allows mod keys to act as different keys when tapped.
|
||||
- [HoldTap](/docs/en/holdtap.md) Allows mod keys to act as different keys when tapped.
|
||||
|
||||
Common Extensions
|
||||
- [Split](/docs/en/split_keyboards.md) Connects halves using a wire
|
||||
|
@@ -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())
|
||||
|
||||
modtap = ModTap()
|
||||
keyboard.modules.append(modtap)
|
||||
holdtap = HoldTap()
|
||||
keyboard.modules.append(holdtap)
|
||||
|
||||
|
||||
NONE = KC.NO
|
||||
@@ -25,9 +25,9 @@ CAD = KC.LCTL(KC.LALT(KC.DEL))
|
||||
|
||||
|
||||
|
||||
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)
|
||||
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)
|
||||
|
||||
# flake8: noqa: E261
|
||||
keyboard.keymap = [
|
||||
|
@@ -3,13 +3,12 @@
|
||||
|
||||
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 = [
|
||||
|
@@ -3,11 +3,12 @@
|
||||
# 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
|
||||
|
||||
@@ -27,7 +28,7 @@ split = Split(
|
||||
)
|
||||
|
||||
layers_ext = Layers()
|
||||
mod_tap = ModTap()
|
||||
holdtap = HoldTap()
|
||||
mouse_key = MouseKeys()
|
||||
|
||||
|
||||
@@ -39,12 +40,12 @@ XXXXXXX = KC.NO
|
||||
|
||||
|
||||
# Mod-taps
|
||||
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)
|
||||
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)
|
||||
CTL_ALT = KC.LCTRL(KC.LALT)
|
||||
|
||||
|
||||
|
@@ -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)
|
||||
|
||||
modtap = ModTap()
|
||||
holdtap = HoldTap()
|
||||
layers = Layers()
|
||||
media_keys = MediaKeys()
|
||||
|
||||
encoder_handler = EncoderHandler()
|
||||
|
||||
keyboard.modules = [layers, modtap] #, encoder_handler]
|
||||
keyboard.modules = [layers, holdtap] #, 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.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)
|
||||
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)
|
||||
|
||||
# OTHER SHORTCUTS
|
||||
BRWSR_LFT = KC.LCTRL(KC.LSFT(KC.TAB))
|
||||
|
@@ -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.
|
||||
- [ModTap](/docs/en/modtap.md) Allows mod keys to act as different keys when tapped.
|
||||
- [HoldTap](/docs/en/holdtap.md) Allows mod keys to act as different keys when tapped.
|
||||
- [LED](/docs/en/led.md) Light your keys up
|
||||
|
||||
Common Extensions
|
||||
|
@@ -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()
|
||||
|
||||
|
||||
modtap = ModTap()
|
||||
holdtap = HoldTap()
|
||||
layers_ext = Layers()
|
||||
led = LED()
|
||||
keyboard.extensions = [led]
|
||||
keyboard.modules = [layers_ext, modtap]
|
||||
keyboard.modules = [layers_ext, holdtap]
|
||||
|
||||
# Cleaner key names
|
||||
_______ = KC.TRNS
|
||||
|
@@ -2,6 +2,7 @@ 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],
|
||||
|
@@ -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.
|
||||
- [ModTap](/docs/en/modtap.md) Enable press/hold double binding of keys
|
||||
- [HoldTap](/docs/en/holdtap.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:
|
||||
|
@@ -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(ModTap())
|
||||
keyboard.modules.append(HoldTap())
|
||||
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.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)
|
||||
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)
|
||||
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,
|
||||
|
@@ -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()
|
||||
modtap_ext = ModTap()
|
||||
holdtap_ext = HoldTap()
|
||||
|
||||
# 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, modtap_ext, split]
|
||||
keyboard.modules = [layers_ext, holdtap_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.MT(KC.TAB, KC.LCTRL)
|
||||
CT_QUOT = KC.MT(KC.QUOT, KC.LCTRL)
|
||||
SF_MINS = KC.MT(KC.MINS, KC.LSHIFT)
|
||||
CT_TAB = KC.HT(KC.TAB, KC.LCTRL)
|
||||
CT_QUOT = KC.HT(KC.QUOT, KC.LCTRL)
|
||||
SF_MINS = KC.HT(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))
|
||||
|
@@ -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
|
||||
- [ModTap](/docs/en/modtap.md) Allows mod keys to act as different keys when tapped.
|
||||
- [HoldTap](/docs/en/holdtap.md) Allows mod keys to act as different keys when tapped.
|
||||
|
||||
Common Extensions
|
||||
- [Power](/docs/en/power.md) Powersaving features for battery life
|
||||
|
@@ -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)
|
||||
|
||||
modtap = ModTap()
|
||||
holdtap = HoldTap()
|
||||
layers_ext = Layers()
|
||||
|
||||
keyboard.modules = [layers_ext, modtap]
|
||||
keyboard.modules = [layers_ext, holdtap]
|
||||
keyboard.extensions = [rgb]
|
||||
|
||||
# Cleaner key names
|
||||
|
@@ -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
|
||||
- [ModTap](/docs/en/modtap.md) Allows mod keys to act as different keys when tapped.
|
||||
- [HoldTap](/docs/en/holdtap.md) Allows mod keys to act as different keys when tapped.
|
||||
|
||||
Common Extensions
|
||||
- [Power](/docs/en/power.md) Powersaving features for battery life
|
||||
|
@@ -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)
|
||||
|
||||
modtap = ModTap()
|
||||
holdtap = HoldTap()
|
||||
layers_ext = Layers()
|
||||
|
||||
keyboard.modules = [layers_ext, modtap]
|
||||
keyboard.modules = [layers_ext, holdtap]
|
||||
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.MT(KC.ENT, KC.RSFT)
|
||||
RSFT_SPC = KC.MT(KC.SPC, KC.RSFT)
|
||||
RSFT_ENT = KC.HT(KC.ENT, KC.RSFT)
|
||||
RSFT_SPC = KC.HT(KC.SPC, KC.RSFT)
|
||||
|
||||
RGB_TOG = KC.RGB_TOG
|
||||
RGB_HUI = KC.RGB_HUI
|
||||
|
@@ -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
|
||||
- [ModTap](/docs/en/modtap.md) Allows mod keys to act as different keys when tapped.
|
||||
- [HoldTap](/docs/en/holdtap.md) Allows mod keys to act as different keys when tapped.
|
||||
|
||||
Common Extensions
|
||||
- [Split](/docs/en/split_keyboards.md) Connects halves using a wire
|
||||
|
@@ -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()
|
||||
modtap = ModTap()
|
||||
holdtap = HoldTap()
|
||||
layers_ext = Layers()
|
||||
keyboard.modules.append(layers_ext)
|
||||
keyboard.modules.append(modtap)
|
||||
keyboard.modules.append(holdtap)
|
||||
|
||||
oled_ext = Oled(
|
||||
OledData(
|
||||
|
@@ -1,7 +0,0 @@
|
||||
version: '3.3'
|
||||
services:
|
||||
mpy_kmk:
|
||||
build: .
|
||||
volumes:
|
||||
- ./kmk:/app/kmk
|
||||
- ./.compiled:/app/compiled
|
@@ -1,14 +0,0 @@
|
||||
|
||||
#!/bin/sh
|
||||
echo "building mpy"
|
||||
echo $(ls compiled)
|
||||
|
||||
find kmk/ -name "*.py" -exec sh -c 'mkdir -p compiled/8/$(dirname {}) &&\
|
||||
./mpy-cross-8 -O2 {} -o compiled/8/$(dirname {})/$(basename -s .py {}).mpy' \;
|
||||
|
||||
find kmk/ -name "*.py" -exec sh -c 'mkdir -p compiled/7/$(dirname {}) &&\
|
||||
./mpy-cross-7 -O2 {} -o compiled/7/$(dirname {})/$(basename -s .py {}).mpy' \;
|
||||
|
||||
echo $(ls compiled)
|
||||
|
||||
echo "done building"
|
@@ -2,9 +2,8 @@
|
||||
> 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 [here](Officially_Supported_Microcontrollers.md)
|
||||
Known working and recommended devices can be found in the [list of officially supported microcontrollers](Officially_Supported_Microcontrollers.md)
|
||||
|
||||
<br>
|
||||
|
||||
## TL;DR Quick start guide
|
||||
> To infinity and beyond!
|
||||
@@ -13,7 +12,7 @@ Known working and recommended devices can be found [here](Officially_Supported_M
|
||||
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 ! <br>
|
||||
***IMPORTANT:*** adapt the GP0 / GP1 pins to your specific board !
|
||||
|
||||
```
|
||||
print("Starting")
|
||||
@@ -45,31 +44,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 [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).
|
||||
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.
|
||||
|
||||
### 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 [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
|
||||
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.
|
||||
- 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 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
|
||||
- [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
|
||||
|
||||
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.
|
||||
|
@@ -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
|
||||
- [ModTap](modtap.md): Adds support for augmented modifier keys to act as one key when tapped, and modifier when held.
|
||||
- [HoldTap](holdtap.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.
|
||||
|
@@ -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
|
||||
[here](https://github.com/adafruit/Adafruit_CircuitPython_BLE/tree/master/adafruit_ble).
|
||||
This can be downloaded from the
|
||||
[Adafruit CircuitPython BLE repository](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.
|
||||
|
||||
|
@@ -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 ModTap, Layers, etc.
|
||||
By default it will not deactivate CapsWord on numbers, alphabets, underscore, modifiers, minus, backspace and other keys like HoldTap, Layers, etc.
|
||||
Add it to your keyboard's modules list with:
|
||||
|
||||
```python
|
||||
|
@@ -27,7 +27,12 @@ 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 `python -m unittest`.
|
||||
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"
|
||||
```
|
||||
|
||||
## Contributing Documentation
|
||||
While KMK welcomes documentation from anyone with and understanding of the issues
|
||||
@@ -35,8 +40,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. 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).
|
||||
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.
|
||||
|
||||
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.
|
||||
|
@@ -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, modtap, encoder_handler]
|
||||
keyboard.modules = [layers, holdtap, 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`.
|
||||
|
@@ -24,9 +24,8 @@ 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
|
||||
[here](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](https://wiki.archlinux.org/index.php/File_systems#Mount_a_file_system).
|
||||
|
||||
For example,
|
||||
|
||||
|
@@ -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 the amazing guide for that [here](https://docs.qmk.fm/#/hand_wire). That
|
||||
follow this amazing [hand wiring guide](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)
|
||||
|
@@ -1,39 +1,39 @@
|
||||
# ModTap Keycodes
|
||||
Enabling ModTap will give you access to the following keycodes and can simply be
|
||||
# HoldTap Keycodes
|
||||
Enabling HoldTap will give you access to the following keycodes and can simply be
|
||||
added to the modules list.
|
||||
|
||||
```python
|
||||
from kmk.modules.modtap import ModTap
|
||||
modtap = ModTap()
|
||||
from kmk.modules.holdtap import HoldTap
|
||||
holdtap = HoldTap()
|
||||
# optional: set a custom tap timeout in ms
|
||||
# modtap.tap_time = 300
|
||||
keyboard.modules.append(modtap)
|
||||
# holdtap.tap_time = 300
|
||||
keyboard.modules.append(holdtap)
|
||||
```
|
||||
|
||||
## Keycodes
|
||||
|
||||
|New Keycode | Description |
|
||||
|---------------------------------------------------------|-----------------------------------------------------------------|
|
||||
|`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|
|
||||
|`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|
|
||||
|
||||
## Custom HoldTap Behavior
|
||||
The full ModTap signature is as follows:
|
||||
The full HoldTap signature is as follows:
|
||||
```python
|
||||
KC.MT(KC.TAP, KC.HOLD, prefer_hold=True, tap_interrupted=False, tap_time=None, repeat=HoldTapRepeat.NONE)
|
||||
KC.HT(KC.TAP, KC.HOLD, prefer_hold=True, tap_interrupted=False, tap_time=None, repeat=HoldTapRepeat.NONE)
|
||||
```
|
||||
* `prefer_hold`: decides which keycode the ModTap key resolves to when another
|
||||
* `prefer_hold`: decides which keycode the HoldTap 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.MT(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 ModTap key individually.
|
||||
Each of these parameters can be set for every HoldTap key individually.
|
@@ -15,7 +15,7 @@ the box.
|
||||
|
||||
### CircuitPython
|
||||
CircuitPython can be installed by following this guide using the guide
|
||||
[here](https://learn.adafruit.com/welcome-to-circuitpython/installing-circuitpython).
|
||||
for [installing circuit python](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
|
||||
|
@@ -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
|
||||
ModTap. Check out the [ModTap doc](modtap.md) to find out more.
|
||||
HoldTap. Check out the [HoldTap doc](holdtap.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
|
||||
|
@@ -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.
|
||||
- [ModTap](modtap.md): Adds support for augmented modifier keys to act as one key
|
||||
- [HoldTap](holdtap.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.
|
||||
|
@@ -15,6 +15,8 @@ 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 |
|
||||
|
@@ -35,12 +35,12 @@ KC.OS(
|
||||
)
|
||||
```
|
||||
|
||||
|
||||
## OneShot Modifier Combinations
|
||||
|
||||
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`.
|
||||
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`.
|
||||
|
||||
```python
|
||||
from kmk.modules.combos import Chord, Combos
|
||||
from kmk.modules.oneshot import OneShot
|
||||
|
||||
oneshot = OneShot()
|
||||
@@ -48,58 +48,8 @@ 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)
|
||||
|
||||
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]]
|
||||
keyboard.keymap = [[OS_LSFT, OS_LCTL, KC.TAB]]
|
||||
```
|
||||
|
||||
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>
|
||||
|
@@ -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 here](https://github.com/adafruit/Adafruit_CircuitPython_Bundle/releases/download/20220415/adafruit-circuitpython-bundle-7.x-mpy-20220415.zip)
|
||||
* [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)
|
||||
|
||||
|
||||
## kb.py
|
||||
|
@@ -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 here](https://github.com/adafruit/Adafruit_CircuitPython_Bundle/releases/download/20220415/adafruit-circuitpython-bundle-7.x-mpy-20220415.zip)
|
||||
* [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)
|
||||
|
||||
## Required Changes to main.py and kb.py
|
||||
|
||||
|
@@ -126,4 +126,4 @@ if __name__ == '__main__':
|
||||
```
|
||||
|
||||
## More information
|
||||
More information on keymaps can be found [here](config_and_keymap.md)
|
||||
More information on keymaps can be found in the [config and keymap](config_and_keymap.md) documentation.
|
||||
|
Before Width: | Height: | Size: 400 KiB After Width: | Height: | Size: 400 KiB |
@@ -15,7 +15,7 @@ microcontrollers with only a single line change and less mistakes.
|
||||
|
||||
## Pro micro footprint pinout
|
||||
|
||||

|
||||

|
||||
|
||||
## Example
|
||||
|
||||
|
@@ -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 ModTap module to the keyboard.modules.
|
||||
Notice that this Split module must be added after the HoldTap 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
|
||||
|
@@ -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.MT(KC.B, KC.LCTL, prefer_hold=False),
|
||||
KC.HT(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
|
||||
|
@@ -9,7 +9,6 @@ KMK は[CircuitPython](https://circuitpython.org/)の上に配置されるキー
|
||||
|
||||
CircuitPython の最適化バージョン(特定のボードの容量制限に対処した、プリインストールされた関連モジュールの選択が可能なバージョン)も提供しています。
|
||||
|
||||
<br>
|
||||
|
||||
## TL;DR クイックスタートガイド
|
||||
> To infinity and beyond!
|
||||
@@ -25,7 +24,7 @@ CircuitPython の最適化バージョン(特定のボードの容量制限に
|
||||
|
||||
4. 同じルートディレクトリー(boot.py と同レベル)に新規で*code.py* または *main.py*のファイルを作成する。中身は以下の例とする。
|
||||
|
||||
***重要:*** GP0 / GP1 ピンを使用ボードに合わせて下さい!<br>
|
||||
***重要:*** GP0 / GP1 ピンを使用ボードに合わせて下さい
|
||||
|
||||
|
||||
```
|
||||
@@ -56,8 +55,6 @@ 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.
|
||||
@@ -72,7 +69,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)があります。
|
||||
@@ -83,13 +80,12 @@ QMK チームが提供している手配線キーボード用の[ガイド](http
|
||||
- [シーケンス](sequences.md) 一つのアクションで複数のキーストロークを送信するために使用します。
|
||||
- [レイヤー](layers.md)でタッチ一つでキーボードの全体の動きを変えることができます。
|
||||
|
||||
- [モドタップ](modtap.md) でキーの押し/長押しの動作を設定し、何回押されたかによって[タップダンス](tapdance.md)を設定します。
|
||||
- [モドタップ](holdtap.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.
|
||||
|
@@ -13,7 +13,6 @@ 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!
|
||||
@@ -30,7 +29,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! <br>
|
||||
***IMPORTANTE:*** adapte os pinos GP0 / GP1 para a tua placa específica!
|
||||
|
||||
```
|
||||
print("Starting")
|
||||
@@ -61,7 +60,6 @@ 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...
|
||||
@@ -88,7 +86,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.
|
||||
|
||||
<br>Uma vez que você compreendeu a essência da coisa:
|
||||
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*)
|
||||
@@ -103,7 +101,7 @@ E para ir mais além:
|
||||
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 é
|
||||
- [HoldTap](holdtap.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.
|
||||
|
||||
@@ -115,7 +113,6 @@ 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.
|
||||
|
@@ -1,27 +1,27 @@
|
||||
# Keycodes ModTap
|
||||
# Keycodes HoldTap
|
||||
|
||||
Habilitar o ModTap (adicionando-o à lista de módulos) te dará acesso aos
|
||||
Habilitar o HoldTap (adicionando-o à lista de módulos) te dará acesso aos
|
||||
keycodes abaixo:
|
||||
|
||||
```python
|
||||
from kmk.modules.modtap import ModTap
|
||||
keyboard.modules.append(ModTap())
|
||||
from kmk.modules.holdtap import HoldTap
|
||||
keyboard.modules.append(HoldTap())
|
||||
```
|
||||
|
||||
## Keycodes
|
||||
|
||||
| Novo Keycode | Descrição |
|
||||
|--------------------------------------------------------|-----------------------------------------------------------------|
|
||||
| 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 |
|
||||
| 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 |
|
@@ -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.
|
||||
- [ModTap](modtap.md): Acrescenta suporte para teclas modificadoras que agem
|
||||
- [HoldTap](holdtap.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!
|
||||
|
60
kmk/bootcfg.py
Normal file
60
kmk/bootcfg.py
Normal file
@@ -0,0 +1,60 @@
|
||||
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
|
@@ -435,7 +435,7 @@ class KeyAttrDict:
|
||||
|
||||
def __iter__(self):
|
||||
for partition in self.__cache:
|
||||
for name in partition.__iter__():
|
||||
for name in partition:
|
||||
yield name
|
||||
|
||||
def __setitem__(self, name: str, key: Key):
|
||||
|
@@ -386,6 +386,10 @@ 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:
|
||||
@@ -498,8 +502,12 @@ 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)
|
||||
while True:
|
||||
self._main_loop()
|
||||
try:
|
||||
while True:
|
||||
self._main_loop()
|
||||
finally:
|
||||
debug('Unexpected error: cleaning up')
|
||||
self._deinit_hid()
|
||||
|
||||
def _init(
|
||||
self,
|
||||
|
@@ -2,6 +2,7 @@ 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__()
|
||||
|
@@ -1,26 +1,8 @@
|
||||
from kmk.hid import HID_REPORT_SIZES, HIDReportTypes
|
||||
from kmk.keys import AX, make_key, make_mouse_key
|
||||
from kmk.kmktime import PeriodicTimer
|
||||
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._nav_key_activated = 0
|
||||
@@ -46,6 +28,14 @@ class MouseKeys(Module):
|
||||
names=('MB_RMB',),
|
||||
code=2,
|
||||
)
|
||||
make_mouse_key(
|
||||
names=('MB_BTN4',),
|
||||
code=8,
|
||||
)
|
||||
make_mouse_key(
|
||||
names=('MB_BTN5',),
|
||||
code=16,
|
||||
)
|
||||
make_key(
|
||||
names=('MW_UP',),
|
||||
on_press=self._mw_up_press,
|
||||
|
@@ -1,9 +1,14 @@
|
||||
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__)
|
||||
|
||||
|
||||
def oneshot_validator(kc, tap_time=None):
|
||||
return HoldTapKeyMeta(tap=kc, hold=kc, prefer_hold=False, tap_time=tap_time)
|
||||
class OneShotKeyMeta(HoldTapKeyMeta):
|
||||
def __init__(self, kc, tap_time=None):
|
||||
super().__init__(tap=kc, hold=kc, prefer_hold=False, tap_time=tap_time)
|
||||
|
||||
|
||||
class OneShot(HoldTap):
|
||||
@@ -12,30 +17,49 @@ class OneShot(HoldTap):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
make_argumented_key(
|
||||
validator=oneshot_validator,
|
||||
validator=OneShotKeyMeta,
|
||||
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 keyup.'''
|
||||
'''Release os key after interrupting non-os keyup, or reset timeout and
|
||||
stack multiple os keys.'''
|
||||
send_buffer = False
|
||||
|
||||
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:
|
||||
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)
|
||||
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)
|
||||
|
||||
return current_key
|
||||
|
||||
@@ -51,8 +75,8 @@ class OneShot(HoldTap):
|
||||
try:
|
||||
state = self.key_states[key]
|
||||
except KeyError:
|
||||
if keyboard.debug_enabled:
|
||||
print(f'OneShot.osk_released: no such key {key}')
|
||||
if debug.enabled:
|
||||
debug(f'OneShot.osk_released: no such key {key}')
|
||||
return keyboard
|
||||
|
||||
if state.activated == ActivationType.PRESSED:
|
||||
|
@@ -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:
|
||||
elif check_deadline(ticks_ms(), self._powersave_start, 240000) is False:
|
||||
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)
|
||||
return bool(check_deadline(ticks_ms(), self._usb_last_scan, 5000) is False)
|
||||
|
||||
def usb_time_reset(self):
|
||||
self._usb_last_scan = ticks_ms()
|
||||
|
@@ -1,39 +0,0 @@
|
||||
FROM python:3.9-slim-buster
|
||||
|
||||
ARG KMKPY_REF
|
||||
ARG KMKPY_URL
|
||||
|
||||
ENV KMKPY_REF ${KMKPY_REF}
|
||||
ENV KMKPY_URL ${KMKPY_URL}
|
||||
|
||||
RUN mkdir -p /app /dist
|
||||
WORKDIR /app
|
||||
|
||||
RUN apt-get update && apt-get install -y build-essential curl gettext git git-lfs rsync wget zip lbzip2
|
||||
RUN pip install pipenv
|
||||
|
||||
# Pull CircuitPython-designated ARM GCC to avoid mismatches/weird
|
||||
# inconsistencies with upstream
|
||||
RUN curl -L -o /tmp/gcc-arm.tar.bz2 https://adafruit-circuit-python.s3.amazonaws.com/gcc-arm-none-eabi-9-2019-q4-major-x86_64-linux.tar.bz2 && \
|
||||
tar -C /usr --strip-components=1 -xaf /tmp/gcc-arm.tar.bz2 && \
|
||||
rm -rf /tmp/gcc-arm.tar.bz2
|
||||
|
||||
# Get a local copy of KMKPython and its dependencies. We don't provide MPY
|
||||
# builds for kmkpython anymore, so we can get away with being opinionated
|
||||
# here.
|
||||
RUN git init /opt/kmkpython && \
|
||||
git -C /opt/kmkpython remote add origin ${KMKPY_URL} && \
|
||||
git -C /opt/kmkpython fetch --depth 1 origin ${KMKPY_REF} && \
|
||||
git -C /opt/kmkpython checkout FETCH_HEAD && \
|
||||
git -C /opt/kmkpython submodule update --init --recursive
|
||||
|
||||
# Build the MPY compiler
|
||||
RUN make -C /opt/kmkpython/mpy-cross
|
||||
|
||||
ENV PATH=/opt/kmkpython/mpy-cross:${PATH}
|
||||
|
||||
RUN mkdir -p /opt/kmkpython/frozen/kmk/kmk
|
||||
COPY ./build_kmkpython_release.sh /app/
|
||||
COPY ./kmk /opt/kmkpython/frozen/kmk/kmk
|
||||
|
||||
CMD /app/build_kmkpython_release.sh
|
BIN
mpy-cross-7
BIN
mpy-cross-7
Binary file not shown.
BIN
mpy-cross-8
BIN
mpy-cross-8
Binary file not shown.
@@ -23,6 +23,7 @@ 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]
|
||||
|
@@ -74,7 +74,14 @@ class KeyboardTest:
|
||||
is_pressed = e[1]
|
||||
self.pins[key_pos].value = is_pressed
|
||||
self.do_main_loop()
|
||||
self.keyboard._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'
|
||||
|
||||
matching = True
|
||||
for i in range(max(len(hid_reports), len(assert_reports))):
|
||||
|
@@ -1,65 +1,66 @@
|
||||
import unittest
|
||||
|
||||
from kmk.keys import KC
|
||||
from kmk.modules.holdtap import HoldTapRepeat
|
||||
from kmk.modules.holdtap import HoldTap, 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(), ModTap(), OneShot()],
|
||||
[Layers(), HoldTap()],
|
||||
[
|
||||
[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],
|
||||
[KC.HT(KC.A, KC.LCTL), KC.LT(1, KC.B), KC.C, KC.D],
|
||||
[KC.N1, KC.N2, KC.N3, KC.N4],
|
||||
],
|
||||
debug_enabled=False,
|
||||
)
|
||||
|
||||
keyboard.test('MT tap behaviour', [(0, True), 100, (0, False)], [{KC.A}, {}])
|
||||
keyboard.test('HT tap behaviour', [(0, True), 100, (0, False)], [{KC.A}, {}])
|
||||
|
||||
keyboard.test(
|
||||
'MT hold behaviour', [(0, True), 350, (0, False)], [{KC.LCTL}, {}]
|
||||
'HT hold behaviour', [(0, True), 350, (0, False)], [{KC.LCTL}, {}]
|
||||
)
|
||||
|
||||
# TODO test multiple mods being held
|
||||
|
||||
# MT
|
||||
# HT
|
||||
keyboard.test(
|
||||
'MT within tap time sequential -> tap behavior',
|
||||
'HT within tap time sequential -> tap behavior',
|
||||
[(0, True), 100, (0, False), (3, True), (3, False)],
|
||||
[{KC.A}, {}, {KC.D}, {}],
|
||||
)
|
||||
|
||||
keyboard.test(
|
||||
'MT within tap time rolling -> hold behavior',
|
||||
'HT 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(
|
||||
'MT within tap time nested -> hold behavior',
|
||||
'HT 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(
|
||||
'MT after tap time sequential -> hold behavior',
|
||||
'HT after tap time sequential -> hold behavior',
|
||||
[(0, True), 350, (0, False), (3, True), (3, False)],
|
||||
[{KC.LCTL}, {}, {KC.D}, {}],
|
||||
)
|
||||
|
||||
keyboard.test(
|
||||
'MT after tap time rolling -> hold behavior',
|
||||
'HT 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(
|
||||
'MT after tap time nested -> hold behavior',
|
||||
'HT after tap time nested -> hold behavior',
|
||||
[(0, True), 350, (3, True), (3, False), (0, False)],
|
||||
[{KC.LCTL}, {KC.LCTL, KC.D}, {KC.LCTL}, {}],
|
||||
)
|
||||
@@ -118,13 +119,13 @@ class TestHoldTap(unittest.TestCase):
|
||||
|
||||
def test_holdtap_chain(self):
|
||||
keyboard = KeyboardTest(
|
||||
[ModTap()],
|
||||
[HoldTap()],
|
||||
[
|
||||
[
|
||||
KC.N0,
|
||||
KC.MT(KC.N1, KC.LCTL, tap_time=50),
|
||||
KC.MT(KC.N2, KC.LSFT, tap_interrupted=True, tap_time=50),
|
||||
KC.MT(
|
||||
KC.HT(KC.N1, KC.LCTL, tap_time=50),
|
||||
KC.HT(KC.N2, KC.LSFT, tap_interrupted=True, tap_time=50),
|
||||
KC.HT(
|
||||
KC.N3,
|
||||
KC.LALT,
|
||||
prefer_hold=False,
|
||||
@@ -275,12 +276,12 @@ class TestHoldTap(unittest.TestCase):
|
||||
|
||||
def test_holdtap_repeat(self):
|
||||
keyboard = KeyboardTest(
|
||||
[ModTap()],
|
||||
[HoldTap()],
|
||||
[
|
||||
[
|
||||
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),
|
||||
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),
|
||||
]
|
||||
],
|
||||
debug_enabled=False,
|
||||
@@ -349,76 +350,3 @@ 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()
|
||||
|
147
tests/test_oneshot.py
Normal file
147
tests/test_oneshot.py
Normal file
@@ -0,0 +1,147 @@
|
||||
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},
|
||||
{},
|
||||
],
|
||||
)
|
@@ -88,7 +88,7 @@ class TestTapDance(unittest.TestCase):
|
||||
[{KC.N1}, {KC.N1, KC.N4}, {KC.N4}, {}],
|
||||
)
|
||||
|
||||
def test_modtap(self):
|
||||
def test_holdtap(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_modtap_repeat(self):
|
||||
def test_holdtap_repeat(self):
|
||||
keyboard = self.keyboard
|
||||
t_after = self.t_after
|
||||
|
||||
keyboard.test(
|
||||
'ModTap repeat',
|
||||
'HoldTap repeat',
|
||||
[
|
||||
(2, True),
|
||||
(2, False),
|
||||
|
@@ -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()
|
||||
modtap = ModTap()
|
||||
holdtap = HoldTap()
|
||||
|
||||
keyboard.modules = [layers_ext, modtap]
|
||||
keyboard.modules = [layers_ext, holdtap]
|
||||
keyboard.extensions = [rgb_ext]
|
||||
|
||||
_______ = KC.TRNS
|
||||
XXXXXXX = KC.NO
|
||||
HOME = KC.MT(KC.HOME, KC.LSFT)
|
||||
END = KC.MT(KC.END, KC.RSFT)
|
||||
HOME = KC.HT(KC.HOME, KC.LSFT)
|
||||
END = KC.HT(KC.END, KC.RSFT)
|
||||
LEFT_LAY = KC.LT(FN1, KC.LEFT)
|
||||
SHFT_INS = KC.LSFT(KC.INS)
|
||||
SPC = KC.LT(FN1, KC.SPC)
|
||||
|
@@ -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()
|
||||
modtap = ModTap()
|
||||
holdtap = HoldTap()
|
||||
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 = [modtap, layers, split]
|
||||
keyboard.modules = [holdtap, layers, split]
|
||||
keyboard.extensions = [rgb_ext]
|
||||
|
||||
_______ = KC.TRNS
|
||||
|
@@ -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.MT(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.HT(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,
|
||||
],
|
||||
[
|
||||
|
Reference in New Issue
Block a user